Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions blogs/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Writing blog posts

Posts in this folder are rendered at `/blog` (index with category filters) and `/blog/<filename>` (post page). Drop a `.md` file here and it ships — no registration step.

Name post files in kebab-case (`my-post-title.md`). ALL-CAPS `.md` files in this folder (like this one and `DIAGRAMS.md`) are documentation and are excluded from the site.

To keep a post as a draft (written but not published), move it into the `drafts/` subfolder. Only `.md` files directly in `blogs/` are published; anything in a subfolder is ignored. Move it back up to ship it.

## Frontmatter (required)

```yaml
---
title: "Tuning Reth for payments: how we hit 21,200 TPS"
excerpt: "One or two sentences shown on the index and as the post's lede."
date: 2026-06-02
category: technical # network-upgrades | events | technical | case-studies
featured: true # optional — pins the post to the hero card on /blog
---
```

`category` must be one of the four slugs above (the build fails loudly otherwise). At most one post should be `featured`; if none is, the newest post takes the hero card.

## Body

Standard markdown + GFM (tables, strikethrough). Code blocks are syntax-highlighted at build time by Shiki — always tag the language:

````markdown
```rust
fn main() {}
```
````

## Images

- Assets live in `public/blog/`, referenced root-relative: `![Alt text](/blog/my-asset.svg)`
- Alt text is required. An italic-only paragraph directly after an image renders as a caption:

```markdown
![Sustained TPS by release](/blog/reth-tps-benchmark.svg)

*Benchmarked on a live network under continuous load.*
```

- Prefer SVG for charts and diagrams, photos as compressed JPEG/PNG.

## Diagrams

Charts and diagrams must follow the house diagram style — dark monochrome,
mono type, single accent. Before drawing one, read
[`DIAGRAMS.md`](./DIAGRAMS.md) in this folder; it has the full palette,
typography rules, layout system, and copy-paste templates.
159 changes: 159 additions & 0 deletions blogs/DIAGRAMS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# Blog diagram style guide

The house style for every chart and diagram embedded in a blog post. Diagrams
are hand-written static SVGs — no charting library, no runtime component. The
constraint is the point: everything is flat, monochrome, monospaced, and
square, with a single accent color carrying the one idea the diagram exists to
show.

Reference implementations: `public/blog/reth-tps-benchmark.svg` (chart),
`public/blog/parallel-execution-lanes.svg` (box/lane diagram).

There is a live playground at [`/diagrams`](/diagrams) (run the dev server and
open it in a browser): edit the style tokens and chart data, preview both
templates, and copy or download ready-to-ship SVG. The values below are the
house defaults; if the playground tokens and this document ever disagree, this
document wins.

## Rules in one paragraph

Dark `#0e0e0e` canvas, 840px wide. All text is monospace, labels are
UPPERCASE. Boxes are sharp-cornered rectangles with 1px strokes. Everything is
greyscale except **one** accent color, used only on the element the diagram is
about. No gradients, no shadows, no rounded corners, no icons, no second
accent.

## Canvas

| Property | Value |
| --- | --- |
| Width | `840` (fixed — matches the post column) |
| Height | whatever the content needs, typically 360–420 |
| Background | full-bleed `<rect>` of `#0e0e0e` |
| Margins | 40px on all sides; content starts at `x=40` |
| Root attrs | `fill="none" xmlns="http://www.w3.org/2000/svg" font-family="ui-monospace, 'JetBrains Mono', monospace"` |

The site wraps embedded images in a 1px border, so don't draw your own outer
frame.

## Palette

Hardcode these hex values — an SVG loaded via `<img>` can't read the site's
CSS variables. They mirror tokens in `app/globals.css`:

| Role | Value | Mirrors token |
| --- | --- | --- |
| Canvas background | `#0e0e0e` | `--surface-block` |
| Neutral box fill | `#1c1c1c` | — |
| Neutral box stroke | `#2e2e2e` | `--line-strong` |
| Gridlines, dividers | `#181818` | `--line` |
| Dashed annotation stroke | `#2e2e2e`, `stroke-dasharray="4 4"` | — |
| Accent stroke/text | `#65ff54` | `--indicator-green` |
| Accent fill | `#143810` | — |
| Alt accent (rare) | `#5d88ff` stroke, `#10204d` fill | `--accent-blue` |

Use green by default. Reach for blue only when a single diagram genuinely
needs two accents (almost never).

## Typography

All monospace (inherited from the root `font-family`), all caps for labels:

| Role | Size | Fill |
| --- | --- | --- |
| Title | `13`, `letter-spacing="0.04em"` | `rgba(255,255,255,0.85)` |
| Subtitle | `11` | `rgba(255,255,255,0.4)` |
| Box/data labels | `11` | `rgba(255,255,255,0.6)` neutral, `#65ff54` accent |
| Axis ticks, lane names | `10`–`11` | `rgba(255,255,255,0.3)`–`0.35` |
| Emphasized value or axis label | `11` | `rgba(255,255,255,0.7)` |

Every diagram opens with a title block at the top left:

```xml
<text x="40" y="44" font-size="13" letter-spacing="0.04em" fill="rgba(255,255,255,0.85)">TITLE OF THE DIAGRAM</text>
<text x="40" y="64" font-size="11" fill="rgba(255,255,255,0.4)">ONE-LINE QUALIFIER OR DATA SOURCE</text>
```

## Layout

- Center text in boxes with `text-anchor="middle"`; vertically, place text
baseline ~5px below box center (e.g. 32px-tall box at `y=256` → text
`y=277`).
- Separate stacked sections with a full-width `#181818` divider line.
- Charts: gridlines `#181818` with tick labels on the left, a `#2e2e2e`
baseline, values labeled above each mark.
- Annotate empty/conceptual regions with a dashed `#2e2e2e` rect and a muted
centered label (see "RECLAIMED BLOCKSPACE" in the lanes diagram).

## Templates

### Bar chart

```xml
<svg width="840" height="420" viewBox="0 0 840 420" fill="none" xmlns="http://www.w3.org/2000/svg" font-family="ui-monospace, 'JetBrains Mono', monospace">
<rect width="840" height="420" fill="#0e0e0e"/>
<text x="40" y="44" font-size="13" letter-spacing="0.04em" fill="rgba(255,255,255,0.85)">TITLE</text>
<text x="40" y="64" font-size="11" fill="rgba(255,255,255,0.4)">QUALIFIER</text>

<g stroke="#181818">
<line x1="40" y1="120" x2="800" y2="120"/>
<line x1="40" y1="240" x2="800" y2="240"/>
</g>
<line x1="40" y1="360" x2="800" y2="360" stroke="#2e2e2e"/>

<!-- neutral bar -->
<rect x="120" y="250" width="96" height="110" fill="#1c1c1c" stroke="#2e2e2e"/>
<text x="168" y="238" font-size="11" fill="rgba(255,255,255,0.45)" text-anchor="middle">VALUE</text>
<text x="168" y="382" font-size="11" fill="rgba(255,255,255,0.4)" text-anchor="middle">LABEL</text>

<!-- accent bar: the data point the diagram is about -->
<rect x="612" y="106" width="96" height="254" fill="#143810" stroke="#65ff54"/>
<text x="660" y="94" font-size="11" fill="#65ff54" text-anchor="middle">VALUE</text>
<text x="660" y="382" font-size="11" fill="rgba(255,255,255,0.7)" text-anchor="middle">LABEL</text>
</svg>
```

### Box / lane diagram

```xml
<svg width="840" height="220" viewBox="0 0 840 220" fill="none" xmlns="http://www.w3.org/2000/svg" font-family="ui-monospace, 'JetBrains Mono', monospace">
<rect width="840" height="220" fill="#0e0e0e"/>
<text x="40" y="44" font-size="13" letter-spacing="0.04em" fill="rgba(255,255,255,0.85)">TITLE</text>
<text x="40" y="64" font-size="11" fill="rgba(255,255,255,0.4)">QUALIFIER</text>

<text x="40" y="120" font-size="11" fill="rgba(255,255,255,0.35)">LANE</text>

<!-- neutral box -->
<rect x="120" y="96" width="110" height="36" fill="#1c1c1c" stroke="#2e2e2e"/>
<text x="175" y="119" font-size="11" fill="rgba(255,255,255,0.6)" text-anchor="middle">item</text>

<!-- accent box -->
<rect x="246" y="96" width="110" height="36" fill="#143810" stroke="#65ff54"/>
<text x="301" y="119" font-size="11" fill="#65ff54" text-anchor="middle">item</text>

<!-- conceptual region -->
<rect x="372" y="96" width="200" height="36" fill="none" stroke="#2e2e2e" stroke-dasharray="4 4"/>
<text x="472" y="119" font-size="11" fill="rgba(255,255,255,0.35)" text-anchor="middle">ANNOTATION</text>
</svg>
```

## Shipping checklist

1. Save to `public/blog/<kebab-name>.svg`.
2. **Validate the XML** — SVGs loaded via `<img>` are strict XML. One bad
byte (smart quote, em dash corrupted to a control char, unescaped `&`)
silently breaks the whole image in the browser:

```bash
xmllint --noout public/blog/<name>.svg
```

Escape `&` as `&amp;` and `<` as `&lt;` in labels. Em dashes are fine as
UTF-8 `—`, but verify with xmllint after writing.
3. Embed with required alt text and an optional italic caption:

```markdown
![One sentence describing what the diagram shows](/blog/<name>.svg)

*Optional caption.*
```
82 changes: 82 additions & 0 deletions blogs/t6.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
---
title: "T6 network upgrade: Receive policies, admin access keys, and more"
excerpt: "The T6 network upgrade adds two new account-level controls to Tempo: receive policies, which let an account decide which tokens and senders it accepts, and admin access keys, which let an account delegate key management without using the root key."
date: 2026-06-23
category: network-upgrades
---

**The T6 network upgrade adds two new account-level controls to Tempo: receive policies, which let an account decide which tokens and senders it accepts, and admin access keys, which let an account delegate key management without using the root key.** [Read the T6 docs to start integrating →](/docs/protocol/upgrades/t6)

## Account-level receive policies

Receive policies let an account specify which TIP-20 tokens it will accept and which addresses can send to it. This is useful for exchanges, custodians, on and off ramps, payment processors, and treasury systems that need to keep unsupported or unwanted assets out of balances, or limit who can send to an account.

An account opting in configures three things:

- **Tokens:** an allowlist or blocklist of TIP-20 tokens it will accept.
- **Senders:** an allowlist or blocklist of addresses that can send to it.
- **Recovery authority:** who can move the funds if a send is held.

Policies are opt-in. An account with no policy works exactly as it does today, and a sender starts a normal transfer or mint without needing to know a policy exists. Policies are set and enforced on the TIP-403 precompile, and any policy a token already enforces still runs first.

When a transfer is accepted, the funds are credited normally. When it is not, the transfer still succeeds, but delivery is redirected to the `ReceivePolicyGuard` precompile and a receipt records enough context for recovery. The held funds stay attributable and recoverable by the authority the account chose in advance.

For integrators, this adds a third delivery state to model:

- **Failed:** token checks revert and the transfer does not go through, as today.
- **Credited:** the receiver accepts the transfer and the funds arrive.
- **Held:** the transfer succeeds, but the policy routes the funds to the guard for recovery.

![A receive policy adds a third delivery state, held, alongside failed and credited.](/blog/receive-policy-delivery-states.svg)

*An unaccepted transfer still succeeds; the funds are held by the guard and stay recoverable.*

Wallets, explorers, and indexers should treat held sends as their own state and listen for the `TransferBlocked` event, since blocked receipts are not enumerable onchain. For deposit flows that use TIP-1022 virtual addresses, the policy is resolved against the master account before the check runs, and receipts preserve the original recipient for attribution.

In practice, this makes several common payment operations easier to run:

### Supported-asset controls

A platform can configure deposit addresses to accept only the stablecoins it supports. If a user sends an unsupported token, the funds are held and recoverable rather than becoming an operational problem.

### Counterparty controls

A regulated business can define which addresses are allowed to send to an account. This gives compliance and operations teams a protocol-native control for inbound payments, rather than relying only on monitoring after funds have already arrived.

Read the [specification](https://tips.sh/1028), [learn more in the docs](/docs/learn/tempo/receive-policies#account-level-receive-policies), and [try the demo](https://tempo.xyz/receive-policies).

## Admin access keys

[Access keys](/docs/protocol/transactions#access-keys) on Tempo let users and applications authorize limited actions. They are useful for subscriptions, delegated payments, automated operations, and other flows where a narrowly scoped key is safer than using the root key directly.

Until now, key management itself still depended on the root key. Admin access keys change that: an account can designate certain access keys as administrative, and those keys can authorize and revoke other keys on the account's behalf. This separates account ownership from day-to-day key administration:

- An admin key can manage operational keys for services, devices, and automated systems while the root key stays protected.
- An operational key can be rotated or revoked without root-key access.
- Admin keys are for key management only. They cannot carry spending limits, call scopes, or expiry.

![Admin keys can authorize and revoke other keys while the root key stays protected.](/blog/account-key-roles.svg)

*Admin keys manage operational keys without using the root key.*

T6 also gives contracts a canonical way to verify key status. `verifyKeychain` confirms a signature came from an active key on an account, and `verifyKeychainAdmin` confirms it came from the root key or an admin key. Builders get a safe primitive for account-gated workflows instead of rebuilding key-status logic in every contract. Note that `verifyKeychainAdmin` does not bind the account into the signed digest, so callers should include a replay domain such as chain ID, contract address, and account address in whatever they ask a key to sign.

Read the [specification](https://tips.sh/1049) and [learn more in the docs](/docs/protocol/transactions#access-keys).

## What integrators should know

Node operators should run the `v1.9.0` release to stay in sync with mainnet. The full set of changes and compatible package versions are in the release notes.

See the [v1.9.0 release](https://github.com/tempoxyz/tempo/releases/tag/v1.9.0) and the [T6 upgrade notes](/docs/protocol/upgrades/t6).

## Resources

- [T6 upgrade docs](/docs/protocol/upgrades/t6)
- [Receive policies overview](/docs/learn/tempo/receive-policies#account-level-receive-policies)
- [Access keys](/docs/protocol/transactions#access-keys)
- [TIP-1028: receive policies specification](https://tips.sh/1028)
- [TIP-1049: admin access keys specification](https://tips.sh/1049)
- [Receive policies demo](https://tempo.xyz/receive-policies)
- [v1.9.0 release](https://github.com/tempoxyz/tempo/releases/tag/v1.9.0)
- [Tempo on GitHub](https://github.com/tempoxyz)
- [All TIPs](/docs/protocol/tips)
7 changes: 7 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@iconify-json/lucide": "^1.2.102",
"@iconify-json/simple-icons": "^1.2.77",
"@monaco-editor/react": "^4.7.0",
"@shikijs/rehype": "^3.23.0",
"@takumi-rs/image-response": "0.62.8",
"@takumi-rs/wasm": "0.62.8",
"@tanstack/react-query": "^5.99.0",
Expand All @@ -42,10 +43,16 @@
"react": "^19.2.6",
"react-dom": "^19.2.6",
"react-server-dom-webpack": "~19.2.6",
"rehype-stringify": "^10.0.1",
"remark-gfm": "^4.0.1",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.2",
"shiki": "^3.23.0",
"sonner": "^2.0.7",
"sql-formatter": "^15.7.3",
"tailwind-merge": "^3.5.0",
"tailwindcss": "^4.2.2",
"unified": "^11.0.5",
"unplugin-auto-import": "^21.0.0",
"unplugin-icons": "^23.0.1",
"viem": "^2.52.2",
Expand Down
21 changes: 21 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions public/blog/account-key-roles.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading