diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index bb2a0522..8b2ddaee 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -36,6 +36,7 @@ jobs: run: pnpm run build env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NODE_OPTIONS: --max-old-space-size=4096 e2e: name: E2E Tests (${{ matrix.shard }}/${{ strategy.job-total }}) diff --git a/README.md b/README.md index 1111acb2..e3a1c82f 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@
diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 00000000..254e8360 --- /dev/null +++ b/SKILL.md @@ -0,0 +1,49 @@ +--- +name: tempo-docs +description: Answer Tempo blockchain questions using official documentation. Use when asked about Tempo protocol, TIP-20 tokens, fees, transactions, stablecoin DEX, or any Tempo-related questions. +--- + +# Tempo Docs + +Skill for navigating Tempo documentation and source code. + +## Quick Context + +Before using MCP tools, try fetching context directly: + +- **llms.txt** – Concise index of all pages: `https://docs.tempo.xyz/llms.txt` +- **Markdown pages** – Append `.md` to any page URL (e.g. `https://docs.tempo.xyz/quickstart/integrate-tempo.md`) + +Use `read_web_page` to fetch these when you need broad context or a quick answer. + +## MCP Tools + +Use these tools for structured exploration: + +| Tool | Description | +| --- | --- | +| `mcp__tempo_mcp__list_pages` | List all documentation pages | +| `mcp__tempo_mcp__read_page` | Read a specific documentation page | +| `mcp__tempo_mcp__search_docs` | Search documentation | +| `mcp__tempo_mcp__list_sources` | List available source repositories | +| `mcp__tempo_mcp__list_source_files` | List files in a directory | +| `mcp__tempo_mcp__read_source_file` | Read a source code file | +| `mcp__tempo_mcp__get_file_tree` | Get recursive file tree | +| `mcp__tempo_mcp__search_source` | Search source code | + +## Available Sources + +- `tempoxyz/tempo` – Tempo node (Rust) +- `tempoxyz/tempo-ts` – TypeScript SDK +- `paradigmxyz/reth` – Reth Ethereum client +- `foundry-rs/foundry` – Foundry toolkit +- `wevm/viem` – TypeScript Ethereum interface +- `wevm/wagmi` – React hooks for Ethereum + +## Workflow + +1. **Quick lookup**: Use `read_web_page` on `https://docs.tempo.xyz/llms.txt` for an overview, or fetch a specific page as Markdown +2. **Search docs**: Use `mcp__tempo_mcp__search_docs` to find relevant pages +3. **Read pages**: Use `mcp__tempo_mcp__read_page` with the page path +4. **Explore source**: Use `mcp__tempo_mcp__search_source` or `mcp__tempo_mcp__get_file_tree` to find implementations +5. **Read code**: Use `mcp__tempo_mcp__read_source_file` to examine specific files \ No newline at end of file diff --git a/package.json b/package.json index 24470774..938d28cc 100644 --- a/package.json +++ b/package.json @@ -37,9 +37,9 @@ "unplugin-auto-import": "^21.0.0", "unplugin-icons": "^23.0.1", "viem": "^2.44.4", - "vocs": "https://pkg.pr.new/wevm/vocs@e5ad67e", + "vocs": "https://pkg.pr.new/vocs@8b55a2c", "wagmi": "3.4.1", - "waku": "1.0.0-alpha.2", + "waku": "1.0.0-alpha.4", "zod": "^4.3.5" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 47067146..abccd96d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -89,14 +89,14 @@ importers: specifier: ^2.44.4 version: 2.44.4(typescript@5.9.3)(zod@4.3.5) vocs: - specifier: https://pkg.pr.new/wevm/vocs@e5ad67e - version: https://pkg.pr.new/wevm/vocs@e5ad67e(@types/react@19.2.9)(mermaid@11.12.2)(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(rollup@4.56.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(waku@1.0.0-alpha.2(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + specifier: https://pkg.pr.new/vocs@8b55a2c + version: https://pkg.pr.new/vocs@8b55a2c(@types/react@19.2.9)(mermaid@11.12.2)(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(rollup@4.56.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(waku@1.0.0-alpha.4(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) wagmi: specifier: 3.4.1 version: 3.4.1(@tanstack/query-core@5.90.19)(@tanstack/react-query@5.90.19(react@19.2.3))(@types/react@19.2.9)(ox@0.11.3(typescript@5.9.3)(zod@4.3.5))(react@19.2.3)(typescript@5.9.3)(viem@2.44.4(typescript@5.9.3)(zod@4.3.5)) waku: - specifier: 1.0.0-alpha.2 - version: 1.0.0-alpha.2(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) + specifier: 1.0.0-alpha.4 + version: 1.0.0-alpha.4(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) zod: specifier: ^4.3.5 version: 4.3.5 @@ -803,6 +803,9 @@ packages: '@rolldown/pluginutils@1.0.0-beta.53': resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==} + '@rolldown/pluginutils@1.0.0-rc.5': + resolution: {integrity: sha512-RxlLX/DPoarZ9PtxVrQgZhPoor987YtKQqCo5zkjX+0S0yLJ7Vv515Wk6+xtTL67VONKJKxETWZwuZjss2idYw==} + '@rollup/pluginutils@5.3.0': resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} engines: {node: '>=14.0.0'} @@ -1478,8 +1481,8 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - '@vitejs/plugin-rsc@0.5.16': - resolution: {integrity: sha512-BopxxopgDQjKIikc6VW1BeC1uRJgY0HOi2uJnF3L+J44oQVjmHIunHEaO85InW6FnFtaMpBeLQ/OJ/sbnwhiEA==} + '@vitejs/plugin-rsc@0.5.21': + resolution: {integrity: sha512-uNayLT8IKvWoznvQyfwKuGiEFV28o7lxUDnw/Av36VCuGpDFZnMmvVCwR37gTvnSmnpul9V0tdJqY3tBKEaDqw==} peerDependencies: react: '*' react-dom: '*' @@ -2052,8 +2055,8 @@ packages: resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} engines: {node: '>=12'} - dotenv@17.2.3: - resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} + dotenv@17.3.1: + resolution: {integrity: sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA==} engines: {node: '>=12'} dunder-proto@1.0.1: @@ -3441,8 +3444,8 @@ packages: resolution: {integrity: sha512-o2yiy7fYXK1HvzA8P6wwj8QSuwG3e/XcpWht/jIxkQX99c0SVPw0OXdLSV9fHASPiYB09HLA0uq8hokGydi/QA==} hasBin: true - srvx@0.10.1: - resolution: {integrity: sha512-A//xtfak4eESMWWydSRFUVvCTQbSwivnGCEf8YGPe2eHU0+Z6znfUTCPF0a7oV3sObSOcrXHlL6Bs9vVctfXdg==} + srvx@0.11.12: + resolution: {integrity: sha512-AQfrGqntqVPXgP03pvBDN1KyevHC+KmYVqb8vVf4N+aomQqdhaZxjvoVp+AOm4u6x+GgNQY3MVzAUIn+TqwkOA==} engines: {node: '>=20.16.0'} hasBin: true @@ -3810,8 +3813,8 @@ packages: vite: optional: true - vocs@https://pkg.pr.new/wevm/vocs@e5ad67e: - resolution: {integrity: sha512-CIZ4KPSeTK3f4V2Ti25OG6VPfMpd/2/j5vzbTlapoqd+cbYIbdbB5oOvlnhtInqvfXFLACVU/bNf8fx/HORVHw==, tarball: https://pkg.pr.new/wevm/vocs@e5ad67e} + vocs@https://pkg.pr.new/vocs@8b55a2c: + resolution: {tarball: https://pkg.pr.new/vocs@8b55a2c} version: 0.0.0 hasBin: true peerDependencies: @@ -3865,14 +3868,14 @@ packages: typescript: optional: true - waku@1.0.0-alpha.2: - resolution: {integrity: sha512-AqS1+jEH+gBeqbxt+Tg8cbDp9Kxqgilr/awifeaWyZsKfsMDfzi0thw/OZlW9KT2W8xJNV1lG4OwSNxgvigJpA==} + waku@1.0.0-alpha.4: + resolution: {integrity: sha512-gZFEaaAL0YWEE55Z5GAggaDkwgpEmkL/ok9uUzq8exykNbXEDAuVd+H/ctXfQqW6VZGZb1aEyEMvjIamDv9igQ==} engines: {node: ^24.0.0 || ^22.12.0 || ^20.19.0} hasBin: true peerDependencies: - react: ~19.2.3 - react-dom: ~19.2.3 - react-server-dom-webpack: ~19.2.3 + react: ~19.2.4 + react-dom: ~19.2.4 + react-server-dom-webpack: ~19.2.4 watchpack@2.5.1: resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==} @@ -4685,6 +4688,8 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.53': {} + '@rolldown/pluginutils@1.0.0-rc.5': {} + '@rollup/pluginutils@5.3.0(rollup@4.56.0)': dependencies: '@types/estree': 1.0.8 @@ -5288,15 +5293,16 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitejs/plugin-rsc@0.5.16(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))': + '@vitejs/plugin-rsc@0.5.21(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))': dependencies: + '@rolldown/pluginutils': 1.0.0-rc.5 es-module-lexer: 2.0.0 estree-walker: 3.0.3 magic-string: 0.30.21 periscopic: 4.0.2 react: 19.2.3 react-dom: 19.2.3(react@19.2.3) - srvx: 0.10.1 + srvx: 0.11.12 strip-literal: 3.1.0 turbo-stream: 3.1.0 vite: 7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) @@ -5848,7 +5854,7 @@ snapshots: dotenv@16.6.1: {} - dotenv@17.2.3: {} + dotenv@17.3.1: {} dunder-proto@1.0.1: dependencies: @@ -7623,7 +7629,7 @@ snapshots: argparse: 2.0.1 nearley: 2.20.1 - srvx@0.10.1: {} + srvx@0.11.12: {} state-local@1.0.7: {} @@ -7974,7 +7980,7 @@ snapshots: optionalDependencies: vite: 7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) - vocs@https://pkg.pr.new/wevm/vocs@e5ad67e(@types/react@19.2.9)(mermaid@11.12.2)(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(rollup@4.56.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(waku@1.0.0-alpha.2(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)): + vocs@https://pkg.pr.new/vocs@8b55a2c(@types/react@19.2.9)(mermaid@11.12.2)(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(rollup@4.56.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))(waku@1.0.0-alpha.4(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)): dependencies: '@base-ui/react': 1.1.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@codesandbox/sandpack-react': 2.20.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -7998,7 +8004,7 @@ snapshots: '@takumi-rs/image-response': 0.62.8 '@takumi-rs/wasm': 0.62.8 '@vitejs/plugin-react': 5.1.2(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) - '@vitejs/plugin-rsc': 0.5.16(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + '@vitejs/plugin-rsc': 0.5.21(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) cac: 6.7.14 cva: class-variance-authority@0.7.1 debug: 4.4.3 @@ -8050,7 +8056,7 @@ snapshots: optionalDependencies: mermaid: 11.12.2 vite: 7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) - waku: 1.0.0-alpha.2(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) + waku: 1.0.0-alpha.4(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - '@cfworker/json-schema' - '@remix-run/react' @@ -8112,12 +8118,12 @@ snapshots: - ox - porto - waku@1.0.0-alpha.2(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2): + waku@1.0.0-alpha.4(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2): dependencies: '@hono/node-server': 1.19.9(hono@4.11.5) '@vitejs/plugin-react': 5.1.2(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) - '@vitejs/plugin-rsc': 0.5.16(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) - dotenv: 17.2.3 + '@vitejs/plugin-rsc': 0.5.21(react-dom@19.2.3(react@19.2.3))(react-server-dom-webpack@19.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(webpack@5.104.1))(react@19.2.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + dotenv: 17.3.1 hono: 4.11.5 magic-string: 0.30.21 picocolors: 1.1.1 diff --git a/public/learn/wallet-add-funds.png b/public/learn/wallet-add-funds.png new file mode 100644 index 00000000..2e82115f Binary files /dev/null and b/public/learn/wallet-add-funds.png differ diff --git a/src/components/IndexSupplyQuery.tsx b/src/components/IndexSupplyQuery.tsx index ceac85cb..6df8045c 100644 --- a/src/components/IndexSupplyQuery.tsx +++ b/src/components/IndexSupplyQuery.tsx @@ -1,7 +1,7 @@ 'use client' import * as React from 'react' import { isAddress, isHash } from 'viem' -import { tempoModerato } from 'viem/chains' +import { tempo } from 'viem/chains' import type * as z from 'zod/mini' import LucideExternalLink from '~icons/lucide/external-link' import { Container } from './Container' @@ -68,7 +68,7 @@ function getExplorerHost() { if (VITE_TEMPO_ENV !== 'testnet' && VITE_EXPLORER_OVERRIDE !== undefined) { return VITE_EXPLORER_OVERRIDE } - return tempoModerato.blockExplorers.default.url + return tempo.blockExplorers.default.url } function classifyHash(value: string | number | boolean | null): { diff --git a/src/components/MermaidDiagram.tsx b/src/components/MermaidDiagram.tsx new file mode 100644 index 00000000..8b06449f --- /dev/null +++ b/src/components/MermaidDiagram.tsx @@ -0,0 +1,1077 @@ +'use client' + +import { useCallback, useEffect, useRef, useState } from 'react' + +// --------------------------------------------------------------------------- +// Layout constants +// --------------------------------------------------------------------------- + +export const LAYOUT = { + padding: 20, + actorGap: 260, + actorGap2: 360, + actorBoxH: 36, + actorPadX: 24, + headerGap: 72, + + rowHeight: 72, + blockPadX: 12, + blockPadTop: 28, + blockPadBottom: 10, + labelLineGap: 22, + arrowSize: 8, + badgeR: 10, + noteBoxPadX: 16, + noteBoxPadY: 8, + noteExtraMargin: 28, + fontFamily: + '"Geist Pixel Square", "Geist Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace', + actorFontSize: 14, + actorFontWeight: 600, + labelFontSize: 14, + labelFontWeight: 400, + noteFontSize: 13, + noteFontWeight: 500, + badgeFontSize: 10, + blockLabelFontSize: 11, + blockLabelFontWeight: 600, + messageStroke: 1.2, + lifelineStroke: 0.75, +} + +export interface ThemeColors { + text: string + textMuted: string + line: string + lifeline: string + arrow: string + successArrow: string + errorCode: string + actorFill: string + actorStroke: string + blockStroke: string + blockHeaderBg: string + badgeBg: string + badgeText: string +} + +export const THEMES: Record<'light' | 'dark', ThemeColors> = { + light: { + text: '#27272a', + textMuted: '#3f3f46', + line: '#a1a1aa', + lifeline: '#d4d4d8', + arrow: '#0166ff', + successArrow: '#16a34a', + errorCode: '#dc2626', + actorFill: '#ffffff', + actorStroke: '#e4e4e7', + blockStroke: '#e4e4e7', + blockHeaderBg: '#f4f4f5', + badgeBg: '#e4e4e7', + badgeText: '#52525b', + }, + dark: { + text: '#e4e4e7', + textMuted: '#e4e4e7', + line: '#71717a', + lifeline: '#3f3f46', + arrow: '#60a5fa', + successArrow: '#4ade80', + errorCode: '#f87171', + actorFill: '#27272a', + actorStroke: '#3f3f46', + blockStroke: '#3f3f46', + blockHeaderBg: '#27272a', + badgeBg: '#3f3f46', + badgeText: '#a1a1aa', + }, +} + +// --------------------------------------------------------------------------- +// Parser +// --------------------------------------------------------------------------- + +export interface Participant { + id: string + label: string +} + +export type Step = + | { + type: 'message' + from: string + to: string + label: string + num: string | null + dashed: boolean + } + | { type: 'note'; over: string; text: string; num: string | null } + | { type: 'loop-start'; label: string } + | { type: 'loop-end' } + +export interface ParsedDiagram { + participants: Participant[] + steps: Step[] +} + +export function extractNum(text: string): { num: string | null; rest: string } { + const m = text.match(/^\((\d+)\)\s*(.+)$/) + return m ? { num: m[1], rest: m[2] } : { num: null, rest: text } +} + +export function parse(source: string): ParsedDiagram { + const lines = source + .split('\n') + .map((l) => l.trim()) + .filter((l) => l && !l.startsWith('%%')) + const participants: Participant[] = [] + const steps: Step[] = [] + const seen = new Set
+
+
+
+
+
Press Enter or click to start
+
+
+### With the CLI
+
+Fund your wallet from the terminal using the [Tempo CLI](/cli):
+
+```bash
+tempo wallet fund
+```
+
+### With an agent
+
+Paste this into your agent to set up Tempo Wallet and add funds:
+
+```
+Read https://wallet.tempo.xyz/SKILL.md and fund my Tempo Wallet
+```
+
+## Testnet Funds
+
+For development and testing, use the [Tempo Faucet](/quickstart/faucet).
+
+The faucet provides `pathUSD`, `alphaUSD`, `betaUSD`, and `thetaUSD` test stablecoins.
diff --git a/src/pages/guide/issuance/create-a-stablecoin.mdx b/src/pages/guide/issuance/create-a-stablecoin.mdx
index 4599ca55..cfe25a5c 100644
--- a/src/pages/guide/issuance/create-a-stablecoin.mdx
+++ b/src/pages/guide/issuance/create-a-stablecoin.mdx
@@ -68,11 +68,11 @@ export function AddFunds() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
@@ -129,11 +129,11 @@ export function CreateStablecoin() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
@@ -197,11 +197,11 @@ export function CreateStablecoin() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
@@ -265,11 +265,11 @@ export function CreateStablecoin() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
diff --git a/src/pages/guide/issuance/distribute-rewards.mdx b/src/pages/guide/issuance/distribute-rewards.mdx
index 0e5bab24..dd9c43af 100644
--- a/src/pages/guide/issuance/distribute-rewards.mdx
+++ b/src/pages/guide/issuance/distribute-rewards.mdx
@@ -76,11 +76,11 @@ export function OptInToRewards() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
@@ -136,11 +136,11 @@ export function StartReward() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
@@ -189,11 +189,11 @@ export function ClaimReward() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
diff --git a/src/pages/guide/issuance/manage-stablecoin.mdx b/src/pages/guide/issuance/manage-stablecoin.mdx
index fdb4560b..4cd91cb0 100644
--- a/src/pages/guide/issuance/manage-stablecoin.mdx
+++ b/src/pages/guide/issuance/manage-stablecoin.mdx
@@ -73,11 +73,11 @@ export function GrantRoles() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
@@ -152,11 +152,11 @@ export function GrantRoles() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
@@ -265,11 +265,11 @@ export function RevokeRoles() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
@@ -336,11 +336,11 @@ export function SetSupplyCap() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
@@ -445,11 +445,11 @@ export function LinkTokenPolicy() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
@@ -525,11 +525,11 @@ export function PauseUnpauseTransfers() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
@@ -599,11 +599,11 @@ export function BurnBlocked() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
diff --git a/src/pages/guide/issuance/mint-stablecoins.mdx b/src/pages/guide/issuance/mint-stablecoins.mdx
index 70621a4b..b4b8caca 100644
--- a/src/pages/guide/issuance/mint-stablecoins.mdx
+++ b/src/pages/guide/issuance/mint-stablecoins.mdx
@@ -76,11 +76,11 @@ export function GrantIssuerRole() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
@@ -179,11 +179,11 @@ export function MintToken() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
@@ -338,11 +338,11 @@ export function BurnToken() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
diff --git a/src/pages/guide/issuance/use-for-fees.mdx b/src/pages/guide/issuance/use-for-fees.mdx
index 0c5cdc36..4ad675c4 100644
--- a/src/pages/guide/issuance/use-for-fees.mdx
+++ b/src/pages/guide/issuance/use-for-fees.mdx
@@ -200,11 +200,11 @@ export function PayWithIssuedToken() {
```tsx twoslash [config.ts] filename="config.ts"
// @noErrors
import { createConfig, http } from 'wagmi'
-import { tempoModerato } from 'viem/chains'
+import { tempo } from 'viem/chains'
import { KeyManager, webAuthn } from 'wagmi/tempo'
export const config = createConfig({
- chains: [tempoModerato],
+ chains: [tempo],
connectors: [webAuthn({
keyManager: KeyManager.localStorage(),
})],
diff --git a/src/pages/guide/machine-payments/client.mdx b/src/pages/guide/machine-payments/client.mdx
new file mode 100644
index 00000000..4ae816d8
--- /dev/null
+++ b/src/pages/guide/machine-payments/client.mdx
@@ -0,0 +1,202 @@
+---
+title: Client Quickstart
+description: Set up an MPP client on Tempo. Polyfill fetch to automatically pay for 402 responses with TIP-20 stablecoins.
+---
+
+import { Card, Cards } from 'vocs'
+
+# Client quickstart
+
+Polyfill `fetch` to handle `402` responses. Your existing code works unchanged — payments happen in the background.
+
+::::steps
+
+### Install dependencies
+
+:::code-group
+```bash [npm]
+npm install mppx viem
+```
+```bash [pnpm]
+pnpm add mppx viem
+```
+```bash [bun]
+bun add mppx viem
+```
+:::
+
+### Define an account
+
+```ts
+import { privateKeyToAccount } from 'viem/accounts'
+
+const account = privateKeyToAccount('0xabc…123')
+```
+
+:::tip
+With Tempo, you can also use [Passkey or WebCrypto accounts](https://viem.sh/tempo/accounts).
+:::
+
+### Create payment handler
+
+Call `Mppx.create` at startup. This polyfills `fetch` to automatically handle `402` payment challenges.
+
+```ts
+import { privateKeyToAccount } from 'viem/accounts'
+import { Mppx, tempo } from 'mppx/client'
+
+const account = privateKeyToAccount('0xabc…123')
+
+Mppx.create({
+ methods: [tempo({ account })],
+})
+```
+
+:::tip
+If you want to avoid polyfilling, use the bound `fetch` instead.
+
+```ts
+const mppx = Mppx.create({
+ polyfill: false,
+ methods: [tempo({ account })]
+})
+
+const response = await mppx.fetch('https://api.example.com/resource')
+```
+:::
+
+### Request protected resources
+
+Use `fetch`. Payment happens when a server returns `402`.
+
+```ts
+const response = await fetch('https://api.example.com/resource')
+```
+
+::::
+
+## Learn more
+
+### Wagmi
+
+You can inject a [Wagmi](https://wagmi.sh) connector into Mppx by passing the `getConnectorClient` function.
+
+:::code-group
+
+```ts [example.ts]
+import { Mppx, tempo } from 'mppx/client'
+import { getConnectorClient } from 'wagmi/actions'
+import { config } from './config'
+
+Mppx.create({
+ methods: [tempo({
+ getClient: (parameters) => getConnectorClient(config, parameters),
+ })],
+})
+```
+
+```ts [config.ts]
+import { createConfig, http } from 'wagmi'
+import { webAuthn } from 'wagmi/tempo'
+import { tempoModerato } from 'viem/chains'
+
+export const config = createConfig({
+ connectors: [webAuthn()],
+ chains: [tempoModerato],
+ transports: {
+ [tempoModerato.id]: http(),
+ },
+})
+```
+
+:::
+
+### Per-request accounts
+
+Pass accounts on individual requests instead of at setup:
+
+```ts
+import { privateKeyToAccount } from 'viem/accounts'
+import { Mppx, tempo } from 'mppx/client'
+
+const mppx = Mppx.create({
+ polyfill: false,
+ methods: [tempo()]
+})
+
+const response = await mppx.fetch('https://api.example.com/resource', {
+ context: {
+ account: privateKeyToAccount('0xabc…123'),
+ }
+})
+```
+
+### Manual payment handling
+
+Use `Mppx.create` for full control over the payment flow:
+
+- Present payment UI before paying
+- Implement custom retry logic
+- Handle credentials manually
+
+```ts
+import { Mppx, tempo } from 'mppx/client'
+import { privateKeyToAccount } from 'viem/accounts'
+
+const mppx = Mppx.create({
+ polyfill: false,
+ methods: [tempo()],
+})
+
+const response = await fetch('https://api.example.com/resource')
+
+if (response.status === 402) {
+ const credential = await mppx.createCredential(response, {
+ account: privateKeyToAccount('0x...'),
+ })
+
+ const paidResponse = await fetch('https://api.example.com/resource', {
+ headers: { Authorization: credential },
+ })
+}
+```
+
+### Payment receipts
+
+On success, the server returns a `Payment-Receipt` header:
+
+```ts
+import { Receipt } from 'mppx'
+
+const response = await fetch('https://api.example.com/resource')
+
+const receipt = Receipt.fromResponse(response)
+
+console.log(receipt.status)
+// success
+console.log(receipt.reference)
+// 0xtx789abc...
+```
+
+## Next steps
+
+