diff --git a/docs/ai-agents/guides/batch-calls.mdx b/docs/ai-agents/guides/batch-calls.mdx new file mode 100644 index 000000000..389545c48 --- /dev/null +++ b/docs/ai-agents/guides/batch-calls.mdx @@ -0,0 +1,66 @@ +--- +title: "Execute Contract Calls" +description: "Batch multiple contract interactions into a single user approval using send_calls and Base MCP" +keywords: ["send_calls MCP", "batch contract calls AI", "EIP-5792 AI", "DeFi AI agent", "Morpho AI Base", "batch transaction AI"] +--- + +import { AcceptingPaymentsDemo } from "/snippets/AcceptingPaymentsDemo.jsx" + + + +## What it does + +`send_calls` submits a batch of EIP-5792 contract calls to your Base Account in a single approval. Use it for DeFi interactions, multi-step operations, and NFT mints that go beyond simple send or swap. + +The most common use case: protocol plugins like [Morpho](/ai-agents/plugins/morpho) prepare a `calls` array (including token approvals and deposits), and you pass it directly to `send_calls` — everything executes atomically in one approval. + +## What you can ask + +With the [Morpho plugin](/ai-agents/plugins/morpho) installed: + +```text +Find the best USDC vault on Base and deposit 100 USDC +``` + +```text +Supply 1 ETH as collateral on Morpho and borrow 2000 USDC +``` + +```text +Repay all my Morpho debt +``` + +## How it works + + + + Protocol plugins like Morpho return a `calls` array and `chainId` from their `prepare_*` tools. The calls include any required token approvals and the protocol interaction itself. + + + Passes the `calls` array and hex `chainId` to Base MCP. + + + Open the `keys.coinbase.com` link to review all calls in the batch before signing. + + + All calls in the batch execute atomically — if one fails, none go through. + + + +## Parameters + +| Parameter | Required | What it does | +|-----------|----------|-------------| +| `chainId` | Yes | Hex chain ID: `0x2105` for Base mainnet, `0x14a34` for Base Sepolia | +| `calls` | Yes | Array of `{ to, value?, data? }` objects | + +## Related guides + + + + Full Morpho orchestration pattern — query, prepare, execute. + + + Sign individual messages and typed data. + + diff --git a/docs/ai-agents/guides/check-balance.mdx b/docs/ai-agents/guides/check-balance.mdx new file mode 100644 index 000000000..8cc99b4ce --- /dev/null +++ b/docs/ai-agents/guides/check-balance.mdx @@ -0,0 +1,53 @@ +--- +title: "Check Balance & Portfolio" +description: "View your token balances, portfolio value, and wallet details using Base MCP" +keywords: ["check balance AI", "get_portfolio MCP", "get_wallets MCP", "Base wallet balance AI assistant"] +--- + +import { DataFetchingDemo } from "/snippets/DataFetchingDemo.jsx" + + + +## What you can ask + +```text +Show me my wallets +``` + +```text +What's my USDC balance on Base? +``` + +```text +Show my full portfolio +``` + +```text +What's the balance of 0x1234...abcd? +``` + +## How it works + +**`get_wallets`** — lists all wallets in your wallet group (your Base Account plus any agent wallets). Shows which wallets are active in the current session (`inSession: true`). + +**`get_portfolio`** — returns portfolio value and per-asset breakdown. Works for any public address — not just your own. + +| Parameter | What it does | +|-----------|-------------| +| `address` | Address to query — defaults to your Base Account | +| `chain` | Filter by chain: `base` or `ethereum` | +| `query` | Filter by token name or symbol (e.g. "USDC") | +| `includePnl` | Include unrealized/realized P&L per asset | + +**`search_tokens`** — resolve a token symbol or name to its contract address and decimals. Useful before sending less common tokens. + +## Related guides + + + + Send ETH or any ERC-20 from your Base Account. + + + See past sends, swaps, and receives. + + diff --git a/docs/ai-agents/guides/index.mdx b/docs/ai-agents/guides/index.mdx new file mode 100644 index 000000000..bf938918b --- /dev/null +++ b/docs/ai-agents/guides/index.mdx @@ -0,0 +1,29 @@ +--- +title: "Guides" +description: "Step-by-step guides for common things to do with Base MCP" +keywords: ["Base MCP guides", "send tokens AI", "swap tokens AI", "check balance AI", "x402 payments AI"] +--- + + + + View your token balances, portfolio value, and wallet details. + + + Send ETH or any ERC-20 to an address, ENS name, or basename. + + + Swap between any two tokens via the Coinbase swap service. + + + Pay for API access per-request in USDC — no subscriptions, no API keys. + + + Browse past transactions and filter by asset or date range. + + + Sign EIP-712 typed data and plain messages for authentication. + + + Batch multiple contract interactions into a single user approval. + + diff --git a/docs/ai-agents/guides/pay-for-services.mdx b/docs/ai-agents/guides/pay-for-services.mdx new file mode 100644 index 000000000..b7902b551 --- /dev/null +++ b/docs/ai-agents/guides/pay-for-services.mdx @@ -0,0 +1,90 @@ +--- +title: "Pay for Services (x402)" +description: "Pay for API access per-request in USDC using the x402 protocol — no subscriptions, no API keys required" +keywords: ["x402 payments AI", "pay for API AI", "pay-for-service skill", "x402 protocol Base", "USDC API payments AI agent"] +--- + +import { PaymentsQuickstartDemo } from "/snippets/PaymentsQuickstartDemo.jsx" + + + +## What is x402? + +x402 is a payment protocol built on HTTP status `402 Payment Required`. When your agent calls an x402-enabled API without paying, the server responds with `402` and payment terms (amount, token, network). Your agent pays in USDC and retries — the entire flow is automatic. + +No subscriptions. No API keys. No pre-existing relationship with the provider. + +## What you can ask + +```text +Find a weather API and get the forecast for New York +``` + +```text +Get the current ETH price from a paid data source +``` + +```text +Find APIs for sentiment analysis +``` + +```text +Set up a paid endpoint for my market data at $0.01 per request +``` + +## x402 with CDP Agentic Wallet + +x402 payments currently require the **CDP Agentic Wallet** skill. Install it once and your agent handles discovery, payment, and retries automatically. + +```bash Terminal +npx skills add coinbase/agentic-wallet-skills +``` + +Then authenticate: + +```text +Sign in to my wallet with your@email.com +``` + +The `pay-for-service` skill handles the full flow: discovers the API, pays in USDC, retries with the payment signature, and returns the data. + + +x402 support for Base MCP is coming soon. Once available, no separate wallet skill will be needed — your Base Account will pay directly. + + +## How the x402 flow works + + + + A standard HTTP request to any x402-enabled endpoint. + + + The response includes payment terms: how much, which token, which network. + + + The CDP Agentic Wallet constructs and signs a payment in USDC on Base. + + + The original request is retried with the `X-Payment-Signature` header. The server verifies and returns the data. + + + +## Discover x402 services + +Browse the x402 Bazaar to find APIs that accept per-request USDC payments: + +```bash Terminal +npx awal@latest x402 bazaar search "price feed" +npx awal@latest x402 bazaar list --network base +``` + +## Reference + + + + Install the wallet skill needed for x402 payments today. + + + search-for-service, pay-for-service, and monetize-service skills. + + diff --git a/docs/ai-agents/guides/send-tokens.mdx b/docs/ai-agents/guides/send-tokens.mdx new file mode 100644 index 000000000..cc7e971aa --- /dev/null +++ b/docs/ai-agents/guides/send-tokens.mdx @@ -0,0 +1,73 @@ +--- +title: "Send Tokens" +description: "Send ETH or any ERC-20 token to an address, ENS name, basename, or cb.id using Base MCP" +keywords: ["send tokens AI", "send USDC AI assistant", "send ETH AI", "Base MCP send", "ENS basename send AI"] +--- + +import { TradeExecutionDemo } from "/snippets/TradeExecutionDemo.jsx" + + + +## What you can ask + +```text +Send 10 USDC to alice.base.eth +``` + +```text +Transfer 0.01 ETH to 0x1234...abcd +``` + +```text +Pay bob.eth 5 USDC +``` + +```text +Send 50 DEGEN to vitalik.eth +``` + +## How it works + +The `send` tool constructs a transaction from your Base Account and requires your approval at `keys.coinbase.com`. Nothing is sent until you confirm. + +| Parameter | Required | What it does | +|-----------|----------|-------------| +| `recipient` | Yes | Address, ENS name, basename (e.g. `alice.base.eth`), cb.id name, or username | +| `amount` | Yes | Human-readable decimal (e.g. `"10.5"`) | +| `asset` | Yes | Token symbol (`ETH`, `USDC`) or ERC-20 contract address | +| `chain` | Yes | `base` or `base-sepolia` | +| `decimals` | When using contract address | Required when `asset` is a contract address | + + +For common tokens like ETH and USDC, just use the symbol — no contract address needed. For less common tokens, your assistant will call `search_tokens` first to resolve the address and decimals automatically. + + +## Approval flow + +Every send requires a manual approval: + + + + The transaction is constructed but not yet broadcast. + + + Open the `keys.coinbase.com` link to review the recipient, amount, and fee. + + + Confirm the transaction in the approval UI. Nothing is sent without your explicit confirmation. + + + Your assistant polls `get_request_status` and reports success once the transaction is confirmed onchain. + + + +## Related guides + + + + Exchange one token for another. + + + Verify your balance before sending. + + diff --git a/docs/ai-agents/guides/sign-messages.mdx b/docs/ai-agents/guides/sign-messages.mdx new file mode 100644 index 000000000..4b3636c8a --- /dev/null +++ b/docs/ai-agents/guides/sign-messages.mdx @@ -0,0 +1,60 @@ +--- +title: "Sign Messages" +description: "Sign EIP-712 typed data and plain messages with your Base Account using Base MCP" +keywords: ["sign message AI", "EIP-712 sign AI", "personal_sign AI", "Base MCP sign", "sign typed data AI assistant"] +--- + +import { X402PayDemo } from "/snippets/x402PayDemo.jsx" + + + +## What it does + +The `sign` tool requests a cryptographic signature from your Base Account. Like all write tools, it requires your approval at `keys.coinbase.com`. + +Two signature types are supported: + +| Type | Standard | Use case | +|------|----------|---------| +| `0x45` | personal_sign (EIP-191) | Simple text messages, SIWE auth challenges | +| `0x01` | EIP-712 typed data | Structured data, permit signatures, protocol auth | + +## What you can ask + +```text +Sign this message: "I agree to the terms of service" +``` + +```text +Sign in to this app using my Base Account +``` + +Signing is usually invoked by protocols or integrations, not directly prompted by users. Your assistant will handle the signing flow when a service requests it. + +## How it works + + + + Passes the message type and payload to Base MCP. + + + Open `keys.coinbase.com` to review what you're signing — the message content is shown in full. + + + Confirm the signature in the approval UI. + + + Your assistant polls `get_request_status` to retrieve the completed signature, then passes it to the requesting service. + + + +## Related guides + + + + Batch multiple contract interactions into one approval. + + + Example of signing-in-the-flow with a DeFi protocol. + + diff --git a/docs/ai-agents/guides/swap-tokens.mdx b/docs/ai-agents/guides/swap-tokens.mdx new file mode 100644 index 000000000..cb186ef02 --- /dev/null +++ b/docs/ai-agents/guides/swap-tokens.mdx @@ -0,0 +1,57 @@ +--- +title: "Swap Tokens" +description: "Swap between any two tokens on Base via the Coinbase swap service using Base MCP" +keywords: ["swap tokens AI", "token swap AI assistant", "USDC ETH swap AI", "Base MCP swap", "DeFi swap AI"] +--- + +import { TradingQuickstartDemo } from "/snippets/TradingQuickstartDemo.jsx" + + + +## What you can ask + +```text +Swap 100 USDC for ETH on Base +``` + +```text +Buy $50 of ETH with USDC +``` + +```text +Trade 0.01 ETH for USDC +``` + +```text +Convert all my USDC to ETH +``` + +## How it works + +The `swap` tool routes through the Coinbase swap service and requires your approval at `keys.coinbase.com`. Swaps are only supported on mainnet — not on testnets. + +| Parameter | Required | What it does | +|-----------|----------|-------------| +| `fromAsset` | Yes | Token to swap from — symbol (`USDC`) or contract address | +| `toAsset` | Yes | Token to swap to — symbol (`ETH`) or contract address | +| `amount` | Yes | Amount of `fromAsset` to swap (human-readable decimal) | +| `chain` | Yes | `base` — testnets are not supported | + + +Testnet swaps are not supported. If you need to test, use `send` on `base-sepolia` instead. + + +## Approval flow + +Same as sending — every swap requires approval at `keys.coinbase.com`. Your assistant will give you a link to review the swap details (input amount, expected output, price impact) before anything is signed. + +## Related guides + + + + Send tokens directly to another address. + + + Verify balances before swapping. + + diff --git a/docs/ai-agents/guides/view-history.mdx b/docs/ai-agents/guides/view-history.mdx new file mode 100644 index 000000000..b5b3bd8fe --- /dev/null +++ b/docs/ai-agents/guides/view-history.mdx @@ -0,0 +1,64 @@ +--- +title: "View Transaction History" +description: "Browse past transactions, filter by asset, and paginate through your onchain history using Base MCP" +keywords: ["transaction history AI", "get_transaction_history MCP", "Base wallet history AI", "onchain history AI assistant"] +--- + +import { AgentRegistrationDemo } from "/snippets/AgentRegistrationDemo.jsx" + + + +## What you can ask + +```text +Show my recent transactions on Base +``` + +```text +Show my last 10 USDC transactions +``` + +```text +What did I send last week? +``` + +```text +Check the transaction history for 0x1234...abcd +``` + +## How it works + +`get_transaction_history` returns transactions in reverse chronological order (newest first) for any public wallet address. + +| Parameter | What it does | +|-----------|-------------| +| `address` | Address to query — defaults to your Base Account | +| `chain` | `base` or `ethereum` — defaults to `base` | +| `asset` | Filter to a specific token (e.g. `USDC`, `ETH`) | +| `limit` | Number of transactions per page (1–200, default 50) | +| `cursor` | Pagination cursor from the previous response's `nextCursor` | + + +Date range filtering is not supported — paginate through results to find transactions from a specific period. + + +## Pagination + +When `hasMore` is `true` in the response, more transactions exist. Ask your assistant to load more: + +```text +Show me the next page of transactions +``` + +Your assistant will use the `nextCursor` value from the previous response automatically. + +## Related guides + + + + View current balances alongside history. + + + Send tokens from your Base Account. + + diff --git a/docs/ai-agents/index.mdx b/docs/ai-agents/index.mdx index 9e9d47dfa..866e39c8f 100644 --- a/docs/ai-agents/index.mdx +++ b/docs/ai-agents/index.mdx @@ -1,65 +1,69 @@ --- -title: "AI Agents on Base" -description: "Build AI agents that trade, earn, and transact autonomously on Base" -keywords: ["AI agents Base", "x402 protocol", "onchain agents", "Base L2", "Build with AI", "OpenClaw", "trading agent", "payment agent"] +title: "Base MCP" +description: "Give your AI assistant a wallet. Base MCP connects any AI to your Base Account — check balances, send funds, swap tokens, and sign messages." +keywords: ["Base MCP", "AI agent wallet", "mcp.base.org", "AI assistant wallet", "onchain AI"] --- -import { AgentPaymentDemo } from "/snippets/AgentPaymentDemo.jsx" +import { WalletSetupDemo } from "/snippets/WalletSetupDemo.jsx" -Base gives your AI agent the tools to operate as an independent economic actor: a wallet to hold and spend funds, identity standards so other agents and services can trust it, and payment protocols for services and commerce. +Base MCP gives your AI assistant direct access to your [Base Account](https://base.org/account) — a smart wallet on Base. Connect once and your assistant can check balances, send funds, swap tokens, and sign messages. Every transaction requires your approval. +## Demo -## Mock Demo + - - -### High-level flow - -Here's how the agent you can build from these guides operates end-to-end — from wallet setup and identity registration to making authenticated, paid API requests using the [x402 protocol](https://www.x402.org). +## How it works ```mermaid sequenceDiagram - participant Agent - participant Wallet as Agent Wallet - participant Registry as Identity Registry - participant API as Paid API - participant Facilitator as x402 Facilitator - - Agent->>Wallet: Set up wallet (Bankr / CDP / Sponge) - Wallet-->>Agent: Address + signing capability - - Agent->>Registry: Register identity (ERC-8004 + Basename) - Registry-->>Agent: Agent ID published onchain - - Agent->>API: HTTP request - API-->>Agent: 402 Payment Required - Note over API,Agent: PAYMENT-REQUIRED header includes amount, token, and network - Agent->>Wallet: Sign payment payload - Wallet-->>Agent: Signed payment - Agent->>API: Retry with PAYMENT-SIGNATURE header - API->>Facilitator: Verify and settle payment - Facilitator-->>API: Payment confirmed - API-->>Agent: Response data + participant User + participant AI as AI Assistant + participant MCP as Base MCP + participant BA as Base Account + participant Approve as keys.coinbase.com + + User->>AI: "Send 10 USDC to alice.base.eth" + AI->>MCP: send(recipient, amount, asset, chain) + MCP->>BA: Construct transaction + BA-->>MCP: approvalUrl + requestId + MCP-->>AI: { approvalUrl, requestId } + AI-->>User: "Please approve: [link]" + User->>Approve: Opens link, approves + AI->>MCP: get_request_status(requestId) + MCP-->>AI: confirmed + AI-->>User: "Done — 10 USDC sent" ``` -## How this section is organized - -The AI agents section covers the full stack for building an autonomous onchain agent: +## What you can do -- **[Quickstarts](/ai-agents/quickstart/payments)** — End-to-end walkthroughs to get a working agent running in minutes. Start here if you're new. -- **[Setup](/ai-agents/setup/wallet-setup)** — Give your agent a wallet and a registered onchain identity. Wallets let it hold funds and authorize transactions; registration lets other agents and services verify who they're dealing with. -- **[Payments](/ai-agents/payments/pay-for-services-with-x402)** — Use x402 to pay for API access per-request in stablecoins, with no subscriptions or API keys required. Or gate your own endpoints to charge other agents. -- **[Trading](/ai-agents/trading/data-fetching)** — Fetch live market data and execute token swaps on Base. -- **[Skills](/ai-agents/skills)** — Installable knowledge packs that give your AI coding assistant deep context on Base APIs, tooling, and migration paths. + + + View your portfolio, token balances, and transaction history across any address on Base. + + + Send ETH or any ERC-20 token to addresses, ENS names, basenames, and cb.id names. + + + Swap between any tokens via the Coinbase swap service directly from your assistant. + + + Sign EIP-712 typed data and personal messages for authentication and protocol interactions. + + -## Choose your path +## Get started - - Build an agent that pays for API access with stablecoins and charges other agents for your services. Get running in under 10 minutes. + + Connect mcp.base.org to your AI assistant in under 2 minutes. - - - Build an agent that fetches live market data and executes token swaps automatically on Base. + + Step-by-step guides for sending, swapping, checking balance, and more. + + + Extend with protocol plugins like Morpho for lending and vaults. + + + Install the base-mcp skill to give your coding assistant deep context on MCP tools. - \ No newline at end of file + diff --git a/docs/ai-agents/payments.mdx b/docs/ai-agents/payments.mdx new file mode 100644 index 000000000..193031dbc --- /dev/null +++ b/docs/ai-agents/payments.mdx @@ -0,0 +1,35 @@ +--- +title: "Payments (x402)" +description: "x402 payment protocol support for AI agents on Base" +keywords: ["x402 agent payments", "Base MCP x402", "CDP agentic wallet x402", "agent payments Base"] +--- + +import { PaymentsQuickstartDemo } from "/snippets/PaymentsQuickstartDemo.jsx" + + + +## x402 and Base MCP + +Base MCP supports sending and swapping tokens directly. **x402 payment protocol** — which lets agents pay for API access per-request in stablecoins — is not yet supported through Base MCP. + + +x402 support for Base MCP is coming soon. + + +## For x402 payments today: CDP Agentic Wallet + +If you need your agent to make or accept x402 payments right now, use the [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/welcome): + +```bash Terminal +npx skills add coinbase/agentic-wallet-skills +``` + +The CDP Agentic Wallet skill bundle includes `pay-for-service`, `search-for-service`, and `monetize-service` — the full x402 client and server stack. + + + Set up x402 payments with the CDP Agentic Wallet. + + +See also: +- [CDP Agentic Wallet skill →](/ai-agents/skills/wallets/cdp-agentic-wallet) +- [CDP payment skills →](/ai-agents/skills/payments/cdp-payment-skills) diff --git a/docs/ai-agents/payments/accepting-payments.mdx b/docs/ai-agents/payments/accepting-payments.mdx deleted file mode 100644 index 8dcea8224..000000000 --- a/docs/ai-agents/payments/accepting-payments.mdx +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: "Accepting Payments (x402)" -description: "Gate your agent's endpoints with x402 to charge other agents per request" -keywords: ["x402 server", "accept agent payments", "monetize API agent", "x402-express", "monetize-service skill", "OpenClaw x402 server"] ---- - -import { AcceptingPaymentsDemo } from "/snippets/AcceptingPaymentsDemo.jsx" - -You can build agent services that charge other agents for access using x402. When a client calls your endpoint without paying, you return `402` with payment requirements. Once the client pays, the facilitator verifies the payment and your server delivers the response. - -## Mock Demo - - - -## Option 1 — OpenClaw monetize-service skill (simplest) - -With the CDP Agentic Wallet skills installed, expose a paid endpoint with a single prompt: - -```bash Terminal -npx skills add coinbase/agentic-wallet-skills -``` - -Then ask your agent: - -```text -Set up a paid endpoint for my market data at $0.01 per request -``` - -The `monetize-service` skill configures the x402 gating and deploys the endpoint. No server code required. - -[CDP Agentic Wallet skills →](https://docs.cdp.coinbase.com/agentic-wallet/skills) - -## Option 2 — Sponge Wallet payment links - -Create a reusable x402 payment link that other agents pay before accessing your service: - -```bash Terminal -curl -X POST "https://api.wallet.paysponge.com/api/payment-links" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" \ - -H "Content-Type: application/json" \ - -d '{ - "amount": "0.01", - "description": "Access to my market data API" - }' -``` - -Share the returned payment link URL with clients. Check payment status: - -```bash Terminal -curl "https://api.wallet.paysponge.com/api/payment-links/{paymentLinkId}" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" -``` - -[Sponge Wallet docs →](https://wallet.paysponge.com/skill.md) - -## Option 3 — Custom server with x402-express - -Use the `x402-express` package to add payment gating to any Express endpoint: - -```bash Terminal -npm install x402-express express -``` - -```typescript TypeScript -import express from "express"; -import { paymentMiddleware } from "x402-express"; - -const app = express(); - -app.use( - paymentMiddleware( - "0xYourAgentWalletAddress", - { - "/api/data": { - price: "$0.01", - network: "base-sepolia", - }, - } - ) -); - -app.get("/api/data", (req, res) => { - res.json({ data: "premium content" }); -}); - -app.listen(3000); -``` - -The middleware returns `402` to unpaid callers. The CDP facilitator handles verification and onchain settlement. - -[x402 seller quickstart →](https://docs.cdp.coinbase.com/x402/docs/client-server-model) - -## Configuring facilitators - -A facilitator is the off-chain service that verifies payment payloads and settles payments onchain. Two options: - -| Facilitator | When to use | -|-------------|-------------| -| **CDP facilitator** (default) | Production — requires CDP API key, supports Base and Solana | -| **Public testnet facilitator** | Development — no API key, Base Sepolia only | - -The public testnet facilitator endpoint is `https://www.x402.org/facilitator`. Switch to the CDP facilitator for mainnet. See the [x402 client-server model](https://docs.cdp.coinbase.com/x402/docs/client-server-model) for full endpoint details. - -## Pricing and payment terms - -- Set prices in USD (e.g., `"$0.01"`) — the middleware converts to the appropriate token amount -- Payments settle in USDC on Base by default -- There is no minimum payment — even fractions of a cent are supported -- Your wallet receives payment directly — no platform fee from the protocol - -## Make your endpoint discoverable - -Host a `SKILL.md` file at `/.well-known/SKILL.md` describing your endpoint's inputs, outputs, pricing, and authentication requirements. Agents discover your service by checking this path. - -```markdown SKILL.md template -# Your Agent Service - -## Description -What your service does, in plain language. - -## Endpoints - -### GET /api/data -- **Description:** Returns premium market data -- **Payment:** $0.01 per request via x402 (Base, USDC) -- **Output:** JSON with current prices and volume - -## Authentication -x402 payment required. No API key needed. -``` - -Register your service in the ERC-8004 registry so agents can discover it by category — see [agent registration](/ai-agents/setup/agent-registration). - -## Related - - - - How x402 works from the client side. - - - - Facilitator endpoints and protocol addresses. - - diff --git a/docs/ai-agents/payments/pay-for-services-with-x402.mdx b/docs/ai-agents/payments/pay-for-services-with-x402.mdx deleted file mode 100644 index 6153baaab..000000000 --- a/docs/ai-agents/payments/pay-for-services-with-x402.mdx +++ /dev/null @@ -1,157 +0,0 @@ ---- -title: "Pay for APIs & Services (x402)" -description: "How x402 works, how your agent makes payments, and which networks and tokens are supported" -keywords: ["x402 protocol", "autonomous agent payments", "machine payments protocol", "programmatic payments", "AI agent payments", "agentic payments", "HTTP 402 payment required", "x402 Base"] ---- - -import { X402PayDemo } from "/snippets/x402PayDemo.jsx" - -x402 is a payment protocol built on HTTP status code `402 Payment Required` — a code in the HTTP spec since the 1990s, finally put to use. It lets agents pay for API access with stablecoins per-request, with no subscriptions or API keys required. - -## Mock Demo - - - -## Payment flow - - - - Your agent sends a standard HTTP request to an API endpoint, just like any other API call. - - - - Instead of returning data, the server responds with a `402` status code and includes payment requirements in the `PAYMENT-REQUIRED` header: how much it costs, which token, and on which network. - - - - Your agent's wallet constructs a signed payment payload and resubmits the request with a `PAYMENT-SIGNATURE` header. No human approval needed. - - - - The server verifies the payment via a facilitator, settles onchain, and returns the requested data. The entire flow takes seconds. - - - -Any agent with a funded wallet can pay for any x402-enabled API — no pre-existing relationship or account required. - -[Learn more about x402 →](https://docs.cdp.coinbase.com/x402/docs/client-server-model) - -## Making x402 requests - -### CDP Agentic Wallet - -With the [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/) skills installed, your agent handles x402 payments automatically: - -```bash Terminal -npx skills add coinbase/agentic-wallet-skills -``` - -**Discover available services** using the [`search-for-service`](https://docs.cdp.coinbase.com/agentic-wallet/skills/search-for-service) skill: - -```bash Terminal -npx awal@latest x402 bazaar search "weather forecast" -``` - -**Call a paid service** using the [`pay-for-service`](https://docs.cdp.coinbase.com/agentic-wallet/skills/pay-for-service) skill: - -```bash Terminal -npx awal@latest x402 pay https://example.com/api/weather \ - -X POST \ - -d '{"query": "New York"}' -``` - -Or prompt your agent directly: - -```text -Find APIs for sentiment analysis -Call that weather API and get the forecast for New York -``` - -The [`search-for-service`](https://docs.cdp.coinbase.com/agentic-wallet/skills/search-for-service) and [`pay-for-service`](https://docs.cdp.coinbase.com/agentic-wallet/skills/pay-for-service) skills handle discovery, payment, and retries. - -[CDP Agentic Wallet skills →](https://docs.cdp.coinbase.com/agentic-wallet/skills) - -### Sponge Wallet - -[Sponge Wallet](https://www.paysponge.com) has a built-in x402 proxy that discovers services and handles payment automatically: - -**Step 1 — Discover a service:** - -```bash Terminal -curl "https://api.wallet.paysponge.com/api/discover?query=weather+forecast" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" -``` - -**Step 2 — Get service details** (required — do not skip): - -```bash Terminal -curl "https://api.wallet.paysponge.com/api/discover/{serviceId}" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" -``` - -This returns the `baseUrl`, endpoint paths, parameters, and pricing. - -**Step 3 — Call the service** (payment is automatic): - -```bash Terminal -curl -X POST "https://api.wallet.paysponge.com/api/x402/fetch" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" \ - -H "Content-Type: application/json" \ - -d '{ - "url": "https://{baseUrl}/{endpointPath}", - "method": "POST", - "body": { "query": "New York" }, - "preferred_chain": "base" - }' -``` - -[Sponge Wallet](https://www.paysponge.com) detects the `402`, pays in USDC from your wallet, and returns the API response. - -[Sponge Wallet docs →](https://wallet.paysponge.com/skill.md) - -## Error handling and retries - -| Status | Meaning | What to do | -|--------|---------|------------| -| `402` | Payment required | Parse `PAYMENT-REQUIRED` header and pay | -| `402` with `X-Payment-Error` | Payment rejected | Check wallet balance and token approval | -| `408` | Payment timeout | Retry with same or higher payment | -| `429` | Rate limit | Back off and retry after the indicated delay | - -The [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/) [`pay-for-service`](https://docs.cdp.coinbase.com/agentic-wallet/skills/pay-for-service) skill and [Sponge Wallet's](https://www.paysponge.com) x402 proxy handle retries automatically. If you're building a custom client, parse the `PAYMENT-REQUIRED` header, construct the signed payload, and retry with the `PAYMENT-SIGNATURE` header. - - - If you're using [Bankr](https://bankr.bot), no setup is required. Just prompt it directly: - - ```text - Get the current ETH price from a paid data source - Find a weather API and get the forecast for New York - Get the token balances for 0xYourAddress on Base - ``` - - Bankr handles service discovery, payment, and data extraction automatically. - - -## Video Tutorial - - -## Related - - - - Gate your own endpoints and charge other agents per request. - - - - Facilitator endpoints and protocol addresses. - - diff --git a/docs/ai-agents/plugins/morpho.mdx b/docs/ai-agents/plugins/morpho.mdx new file mode 100644 index 000000000..1aa961351 --- /dev/null +++ b/docs/ai-agents/plugins/morpho.mdx @@ -0,0 +1,184 @@ +--- +title: "Morpho Plugin" +description: "Add Morpho lending and vault operations to your AI assistant via the Morpho MCP, executed through your Base Account" +keywords: ["Morpho MCP", "Base lending AI", "Morpho vault agent", "mcp.morpho.org", "AI lending agent Base"] +--- + +import { AcceptingPaymentsDemo } from "/snippets/AcceptingPaymentsDemo.jsx" + +[Morpho](https://morpho.org) is a lending protocol on Base. The Morpho MCP server gives your assistant tools to query vaults, check markets, and prepare lending operations — which are then signed and sent through Base MCP. + +## Demo + + + +## How it works + +Morpho handles the protocol layer. Your Base Account handles signing. + +```mermaid +sequenceDiagram + participant User + participant AI as AI Assistant + participant Morpho as Morpho MCP + participant BA as Base MCP + + User->>AI: "Deposit 100 USDC into the best vault" + AI->>Morpho: morpho_query_vaults(asset=USDC, sortBy=APY) + Morpho-->>AI: vault list with APYs + AI->>Morpho: morpho_prepare_deposit(vaultAddress, 100 USDC) + Morpho-->>AI: { calls, chainId } (simulated, unsigned) + AI->>BA: send_calls(chainId, calls) + BA-->>AI: { approvalUrl, requestId } + AI-->>User: "Please approve: [link]" + User-->>AI: approved + AI->>BA: get_request_status(requestId) + BA-->>AI: confirmed + AI-->>User: "100 USDC deposited" +``` + + +Morpho's `prepare_*` tools simulate the transaction before returning. Review the simulation output before approving — it shows expected state changes, health factors, and any warnings. + + +## Install + +Add both MCPs to your assistant: + + + + ```json claude_desktop_config.json + { + "mcpServers": { + "base-account": { + "url": "https://mcp.base.org" + }, + "morpho": { + "url": "https://mcp.morpho.org/" + } + } + } + ``` + + + ```bash Terminal + claude mcp add --transport http base-account https://mcp.base.org + claude mcp add morpho --transport http https://mcp.morpho.org/ + ``` + + + ```toml codex.toml + [mcp_servers.base-account] + url = "https://mcp.base.org/" + + [mcp_servers.morpho] + url = "https://mcp.morpho.org/" + ``` + + + Add a second entry alongside `base-account` in your MCP config: + + ```json + { + "mcpServers": { + "base-account": { "url": "https://mcp.base.org" }, + "morpho": { "url": "https://mcp.morpho.org/" } + } + } + ``` + + + +## Morpho tools + +17 tools across read, write (prepare), and simulate. + +### Read + +| Tool | What it does | +|------|-------------| +| `morpho_health_check` | Check server connectivity | +| `morpho_get_supported_chains` | List supported chains | +| `morpho_query_vaults` | List vaults with filtering and sorting | +| `morpho_get_vault` | Details for a specific vault | +| `morpho_query_markets` | List markets with filtering | +| `morpho_get_market` | Details for a specific market | +| `morpho_get_positions` | All positions for an address (vaults + markets) | +| `morpho_get_token_balance` | Token balance and approval state | + +### Prepare (write via `send_calls`) + +These tools return unsigned call data. Pass the result to Base MCP's `send_calls` to execute. + +| Tool | What it does | +|------|-------------| +| `morpho_prepare_deposit` | Prepare vault deposit with token approvals | +| `morpho_prepare_withdraw` | Prepare vault withdrawal (supports max) | +| `morpho_prepare_supply` | Prepare market supply with approvals | +| `morpho_prepare_borrow` | Prepare market borrow with health check | +| `morpho_prepare_repay` | Prepare market repay (supports max) | +| `morpho_prepare_supply_collateral` | Supply collateral to a market | +| `morpho_prepare_withdraw_collateral` | Withdraw collateral with health check | + +### Simulate + +| Tool | What it does | +|------|-------------| +| `morpho_simulate_transactions` | Simulate transactions with post-state analysis | + +## Example prompts + +**Deposit into a vault:** +```text +Find the best USDC vault on Base by APY and deposit 100 USDC +``` + +**Check positions:** +```text +Show all my Morpho positions on Base +``` + +**Borrow against collateral:** +```text +Supply 1 ETH as collateral on Morpho and borrow 2000 USDC +``` + +**Check health:** +```text +What's my Morpho borrow health factor? +``` + +**Withdraw:** +```text +Withdraw all my USDC from Morpho vaults +``` + +## Orchestration pattern + +Every Morpho write operation follows the same pattern: + + + + Use a read tool to find the right vault or market: `morpho_query_vaults`, `morpho_get_market`, etc. + + + Call a `prepare_*` tool. Morpho simulates the operation and returns `{ calls, chainId }`. + + + Pass `calls` and `chainId` to Base MCP's `send_calls`. You'll get an `approvalUrl`. + + + Open the `approvalUrl`, approve the transaction, then your assistant polls `get_request_status`. + + + +## Related + + + + Full guide to `send_calls` and batching protocol interactions. + + + Full Morpho MCP documentation and prompt library. + + diff --git a/docs/ai-agents/quickstart.mdx b/docs/ai-agents/quickstart.mdx new file mode 100644 index 000000000..de1f79ac9 --- /dev/null +++ b/docs/ai-agents/quickstart.mdx @@ -0,0 +1,250 @@ +--- +title: "Quickstart" +description: "Connect Base MCP to your AI assistant in under 2 minutes" +keywords: ["Base MCP quickstart", "mcp.base.org setup", "Claude Desktop MCP", "ChatGPT MCP", "Claude Code MCP wallet", "Cursor MCP", "VS Code MCP", "Windsurf MCP"] +--- + +import { WalletSetupDemo } from "/snippets/WalletSetupDemo.jsx" + +Connect `mcp.base.org` to your AI assistant, then send your first prompt. + +## Demo + + + +## Step 1 — Connect + + + + + Add to Claude + + + Paste `https://mcp.base.org` as the server URL and save. Works in Claude.ai (web, iOS, Android) and Claude Desktop. + + + Remote MCP integrations require a Claude Pro, Max, Team, or Enterprise plan. + + + **Claude Desktop config file** — if you prefer to configure manually, open **Settings → Developer → Edit Config** and add: + + | Platform | Config path | + |----------|-------------| + | macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` | + | Windows | `%APPDATA%\Claude\claude_desktop_config.json` | + | Linux | `~/.config/Claude/claude_desktop_config.json` | + + ```json claude_desktop_config.json + { + "mcpServers": { + "base-account": { + "url": "https://mcp.base.org" + } + } + } + ``` + + Save and restart Claude Desktop. A wallet icon will appear in the toolbar when connected. + + + + Add to ChatGPT + + + Then: + + 1. Enable **Developer Mode** if prompted (under Advanced) + 2. Click **Add custom connector** + 3. Enter the server URL: + + ```text + https://mcp.base.org + ``` + + 4. Save. ChatGPT will prompt you to authorize when you first use a wallet tool. + + + MCP connectors require a ChatGPT Plus or Pro plan. + + + + Run this in your terminal to add the server to the current project: + + ```bash Terminal + claude mcp add --transport http base-account https://mcp.base.org + ``` + + To install globally (available across all your projects): + + ```bash Terminal + claude mcp add --transport http --scope user base-account https://mcp.base.org + ``` + + Verify it connected: + + ```bash Terminal + claude mcp list + ``` + + The `base-account` server will show with a tool count once active. You can also run `/mcp` inside a Claude Code session to see server status. + + + ```bash Terminal + codex mcp add base-account --url https://mcp.base.org/ + ``` + + Or add to your `codex.toml`: + + ```toml codex.toml + [mcp_servers.base-account] + url = "https://mcp.base.org/" + ``` + + + + Add to Cursor + + + Or add manually to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project): + + ```json mcp.json + { + "mcpServers": { + "base-account": { + "url": "https://mcp.base.org" + } + } + } + ``` + + Restart Cursor, then open **Settings → MCP** to confirm `base-account` shows as active. + + + + Add to VS Code + + + Or add manually to `.vscode/mcp.json` (workspace) or your user MCP settings: + + ```json .vscode/mcp.json + { + "servers": { + "base-account": { + "type": "http", + "url": "https://mcp.base.org" + } + } + } + ``` + + Open **Copilot Chat** in agent mode and confirm the wallet tools appear in the tool picker. + + + Add to `~/.codeium/windsurf/mcp_config.json`: + + ```json mcp_config.json + { + "mcpServers": { + "base-account": { + "url": "https://mcp.base.org" + } + } + } + ``` + + Restart Windsurf. Open **Cascade** — the MCP tools will be available once connected. + + + You can also add MCP servers from the UI: open **Cascade** → click the **hammer icon** → **Add MCP Server**. + + + + + + **Other clients** — Any MCP client that supports remote HTTP (Streamable HTTP) servers works with `https://mcp.base.org`. See the [setup guide](/ai-agents/setup) for Zed, JetBrains, Le Chat (Mistral), Warp, and others. On mobile, the Claude connector above works in the iOS and Android apps. + + +## Step 2 — Authorize + +The first time you use a wallet tool, your assistant will redirect you to `keys.coinbase.com` to connect your Base Account. You'll need a Coinbase account. Once authorized, all transactions still require individual approval at that same URL. + +## Step 3 — Try it + +Ask your assistant: + +```text +Show me my wallets +``` + +```text +What's my USDC balance on Base? +``` + +```text +Send 1 USDC to vitalik.base.eth +``` + +Every send, swap, or sign operation will give you an approval link. Open it, review the transaction, and confirm. + +--- + +## Add a plugin — Morpho lending + +Morpho lets your assistant query vaults, check APYs, and execute lending operations on Base — then sign them through your Base Account. + +Add both MCPs to your config: + + + + ```json claude_desktop_config.json + { + "mcpServers": { + "base-account": { + "url": "https://mcp.base.org" + }, + "morpho": { + "url": "https://mcp.morpho.org/" + } + } + } + ``` + + + ```bash Terminal + claude mcp add --transport http base-account https://mcp.base.org + claude mcp add morpho --transport http https://mcp.morpho.org/ + ``` + + + Add a second entry alongside `base-account`: + + ```json + "morpho": { "url": "https://mcp.morpho.org/" } + ``` + + + +Then try: + +```text +Find the best USDC vault on Base by APY and deposit 100 USDC +``` + +Morpho prepares the transaction; your Base Account signs it. See [Morpho plugin →](/ai-agents/plugins/morpho) + +## Next steps + + + + Step-by-step guides for sending, swapping, checking balance, and more. + + + Query vaults, check APYs, and execute lending operations on Base. + + + Detailed platform setup, auth flow, and approval mode explained. + + + Install the base-mcp skill for your coding assistant. + + diff --git a/docs/ai-agents/quickstart/payments.mdx b/docs/ai-agents/quickstart/payments.mdx deleted file mode 100644 index 79dd9f679..000000000 --- a/docs/ai-agents/quickstart/payments.mdx +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: "Get Started with Payments" -description: "Build an agent that makes and accepts x402 payments on Base in under 10 minutes" -keywords: ["x402 quickstart", "agent payments", "OpenClaw payments", "AI agent pay for API", "accept payments agent"] ---- - -import { PaymentsQuickstartDemo } from "/snippets/PaymentsQuickstartDemo.jsx" - -This guide gets you from zero to a working agent that makes a paid x402 API request and exposes its own paid endpoint — all in under 10 minutes. - -## Mock Demo - - - - -## Install OpenClaw - - - - **macOS / Linux:** - - ```bash Terminal - curl -fsSL https://openclaw.ai/install.sh | bash - ``` - - **Windows (PowerShell):** - - ```powershell Terminal - iwr -useb https://openclaw.ai/install.ps1 | iex - ``` - - Verify the installation: - - ```bash Terminal - openclaw --version - ``` - - - - ```bash Terminal - openclaw onboard --install-daemon - ``` - - Follow the prompts to connect your LLM provider and set up your wallet plugin. - - - - ```bash Terminal - openclaw gateway --port 18789 - ``` - - Open `http://127.0.0.1:18789/` to verify the gateway is live. - - - - -**Claude Code, Codex, and OpenCode users** — the wallet skills and x402 payment tools below are compatible with any skills-enabled AI coding tool. Run the same `npx skills add` commands and the capabilities work identically. - - -## Configure a wallet - -Install the CDP Agentic Wallet skills: - -```bash Terminal -npx skills add coinbase/agentic-wallet-skills -``` - -Then authenticate: - -```text -Sign in to my wallet with your@email.com -``` - -Or use a [Sponge Wallet](https://www.paysponge.com) with native x402 support — see [wallet setup](/ai-agents/setup/wallet-setup) for all options. - -## Make your first x402 payment - -Ask your agent to discover and call a paid API: - -```text -Find a weather API and get the forecast for New York -``` - -The `search-for-service` and `pay-for-service` skills handle discovery, payment, and retries automatically. Your agent pays in USDC, gets the data, and returns the result — no API keys, no subscriptions. - -To make a direct x402 request with Sponge Wallet: - -```bash Terminal -curl -X POST "https://api.wallet.paysponge.com/api/x402/fetch" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" \ - -H "Content-Type: application/json" \ - -d '{ - "url": "https://api.example.com/paid-endpoint", - "method": "GET", - "preferred_chain": "base" - }' -``` - -## Gate your own endpoint with x402 - -Ask your agent to expose a paid API: - -```text -Set up a paid endpoint for my market data at $0.01 per request -``` - -The `monetize-service` skill (`npx skills add coinbase/agentic-wallet-skills`) configures the x402 gating and deploys the endpoint. Other agents can now discover and pay for your service automatically. - -Or use `x402-express` for a custom server — see [Accepting payments](/ai-agents/payments/accepting-payments). - -## Next steps - - - - Deep dive into how x402 works, supported networks, and error handling. - - - - Set up server-side x402 gating with OpenClaw skills or custom middleware. - - - - Configure Bankr, CDP, or Sponge for your agent. - - - - Register your agent for discoverability and identity verification. - - diff --git a/docs/ai-agents/quickstart/trading.mdx b/docs/ai-agents/quickstart/trading.mdx deleted file mode 100644 index 23219ecb1..000000000 --- a/docs/ai-agents/quickstart/trading.mdx +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: "Get Started with Trading" -description: "Build an agent that fetches live market data and executes token swaps on Base" -keywords: ["trading agent quickstart", "OpenClaw trading", "Base trading agent", "token swap agent", "x402 market data"] ---- - -import { TradingQuickstartDemo } from "/snippets/TradingQuickstartDemo.jsx" - -This guide gets you from zero to a working agent that fetches live price data via x402 and executes a token swap on Base. - -## Mock Demo - - - - -## Install OpenClaw - - - - **macOS / Linux:** - - ```bash Terminal - curl -fsSL https://openclaw.ai/install.sh | bash - ``` - - **Windows (PowerShell):** - - ```powershell Terminal - iwr -useb https://openclaw.ai/install.ps1 | iex - ``` - - Verify: - - ```bash Terminal - openclaw --version - ``` - - - - ```bash Terminal - openclaw onboard --install-daemon - ``` - - - - ```bash Terminal - openclaw gateway --port 18789 - ``` - - - - -**Claude Code, Codex, and OpenCode users** — the wallet and trading skills below are compatible with any skills-enabled AI coding tool. Run the same `npx skills add` commands from within your tool. - - -## Configure a trading wallet - -Bankr provides cross-chain wallet access with gas sponsorship and built-in swap support — ideal for trading agents: - -```text -install the bankr skill from https://github.com/BankrBot/skills -``` - -Create a dedicated account at [bankr.bot](https://bankr.bot) and generate an API key at [bankr.bot/api](https://bankr.bot/api). - -For [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/) or [Sponge Wallet](https://www.paysponge.com), see [wallet setup](/ai-agents/setup/wallet-setup). - -## Execute a swap - -Ask your agent to execute a trade using wallet-native tools: - -```text -Buy $50 of ETH on Base -``` - -With Bankr or CDP Agentic Wallet, built-in swap tools handle the trade — no external DEX integration needed. The wallet constructs, signs, and broadcasts the transaction. - -For best execution on Base, use the preconf endpoint to simulate before signing: - -```text -Simulate buying $50 of ETH then execute if the price impact is below 1% -``` - -## Next steps - - - - Full catalog of x402 data sources for trading agents. - - - - Flashblocks timing, fee calibration, and failure modes on Base. - - - - Configure Bankr, CDP, or Sponge for your agent. - - - - How x402 works for data fetching and payments. - - diff --git a/docs/ai-agents/setup/agent-registration.mdx b/docs/ai-agents/setup/agent-registration.mdx deleted file mode 100644 index ac68e1217..000000000 --- a/docs/ai-agents/setup/agent-registration.mdx +++ /dev/null @@ -1,188 +0,0 @@ ---- -title: "Agent Registration & Identity" -description: "Register your agent's identity onchain, get a Basename, and authenticate with services using Sign In With Agent (SIWA)" -keywords: ["ERC-8004", "agent registration", "Basename agent", "agent identity", "SIWA", "Sign In With Agent", "ERC-8128", "onchain identity Base"] ---- - -import { AgentRegistrationDemo } from "/snippets/AgentRegistrationDemo.jsx" - -When your agent calls a service, how does that service know it's really your agent? When your agent receives a response, how does it know the response is legitimate? Registration and identity verification solve both problems. - -## Mock Demo - - - -## Why register? - -- **Discoverability** — other agents and services can find your agent by querying the public registry -- **SIWA authentication** — services use your registration to verify that requests genuinely come from your agent -- **Reputation** — the reputation registry accumulates trust signals that other agents can query before interacting with yours - -## Get a Basename for your agent - -A Basename gives your agent a human-readable identity (e.g., `myagent.base.eth`) that resolves to its wallet address. Register at [base.org/names](https://www.base.org/names). - -## Register in the ERC-8004 registry - -The [ERC-8004](https://www.8004.org/) standard is an onchain NFT registry where agents publish their identity: name, description, endpoints, and public key. - - - - Use 8004scan.io to register and explore registered agents through a web interface — no code required. - - - Use the Agent0 SDK to register your agent programmatically and manage its onchain profile. - - - -A registry entry includes your agent's name and description, the endpoints where it can be reached, and a key pair that ties the agent's identity to its cryptographic credentials. - -The canonical registry addresses are at [8004scan.io](https://www.8004scan.io). - -[Learn more about ERC-8004 →](https://www.8004.org/) - -## Verify identity at runtime (ERC-8128) - -Registration tells the world your agent exists. The **ERC-8128** standard lets your agent prove it's really yours with every request: - - - - Your agent registers its identity and public key in the ERC-8004 registry. This is a one-time setup step. - - - - When your agent calls a service, it signs the request using its private key. This creates a cryptographic signature unique to that specific request. - - - - The service looks up your agent's public key from the registry, then checks the signature. If it matches, the service knows the request came from your registered agent. - - - -This works in both directions — your agent can verify a service's responses are authentic by checking the service's signature against the registry. - -[ERC-8128 specification →](https://erc8128.slice.so/concepts/overview) - -## Sign In With Agent (SIWA) - -[SIWA](https://siwa.id) bundles ERC-8004 registration and ERC-8128 signing into a single SDK — similar to how "Sign in with Google" bundles OAuth into one integration. - - -**Start with SIWA** for the simplest integration path. Use ERC-8004 and ERC-8128 directly only if you need fine-grained control over registration and verification. - - -### Agent-side integration - -Install the SIWA SDK: - -```bash Terminal -npm install @buildersgarden/siwa -``` - -Choose a signer based on your wallet provider. SIWA supports private keys, Bankr, Circle, Openfort, Privy, and smart contract accounts: - -```typescript TypeScript -import { createLocalAccountSigner } from "@buildersgarden/siwa/signer"; -import { privateKeyToAccount } from "viem/accounts"; - -const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`); -const signer = createLocalAccountSigner(account); -``` - -Request a nonce from the service, then sign and submit a SIWA message: - -```typescript TypeScript -import { signSIWAMessage } from "@buildersgarden/siwa"; - -// Step 1: Request a nonce from the service -const nonceResponse = await fetch("https://api.example.com/siwa/nonce", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ address: await signer.getAddress() }), -}); -const { nonce, issuedAt } = await nonceResponse.json(); - -// Step 2: Sign the SIWA message -const { message, signature } = await signSIWAMessage( - { - domain: "api.example.com", - uri: "https://api.example.com/siwa", - agentId: 42, // your ERC-8004 token ID - agentRegistry: "eip155:8453:0x8004A169FB4a3325136EB29fA0ceB6D2e539a432", - chainId: 8453, - nonce, - issuedAt, - }, - signer -); - -// Step 3: Submit for verification and receive a receipt -const verifyResponse = await fetch("https://api.example.com/siwa/verify", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ message, signature }), -}); -const { receipt } = await verifyResponse.json(); -``` - -Use the receipt to sign subsequent requests with ERC-8128: - -```typescript TypeScript -import { signAuthenticatedRequest } from "@buildersgarden/siwa/erc8128"; - -const request = new Request("https://api.example.com/action", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ action: "transfer" }), -}); - -const signedRequest = await signAuthenticatedRequest(request, receipt, signer, 8453); -const response = await fetch(signedRequest); -``` - -### Server-side verification - -Services that accept SIWA-authenticated agents implement two endpoints: one to issue nonces and one to verify signatures. - -```typescript TypeScript -import { verifySIWA, createSIWANonce } from "@buildersgarden/siwa"; -import { createReceipt } from "@buildersgarden/siwa/receipt"; -import { createPublicClient, http } from "viem"; -import { base } from "viem/chains"; - -const client = createPublicClient({ chain: base, transport: http() }); - -// POST /siwa/nonce -const { nonce, issuedAt } = await createSIWANonce({ address, agentId, agentRegistry }, client); - -// POST /siwa/verify -const result = await verifySIWA(message, signature, "api.example.com", nonceValid, client); -if (result.success) { - const { receipt } = createReceipt({ address: result.address, agentId: result.agentId }); - return { receipt }; -} -``` - -SIWA ships drop-in middleware for Express, Next.js, Hono, and Fastify. See the [SIWA documentation](https://siwa.id/docs) for framework-specific examples, replay protection, and x402 payment integration. - -## Video Tutorial - - - -## Related - - - - Browse and verify registered agents and registry addresses on Base. - - - - Pay for API access with stablecoins using the x402 protocol. - - diff --git a/docs/ai-agents/setup/index.mdx b/docs/ai-agents/setup/index.mdx new file mode 100644 index 000000000..8369e4961 --- /dev/null +++ b/docs/ai-agents/setup/index.mdx @@ -0,0 +1,250 @@ +--- +title: "Setup" +description: "Connect Base MCP to Claude Desktop, Claude.ai, ChatGPT, Claude Code, Cursor, VS Code, Windsurf, Zed, JetBrains, Le Chat, Warp, and more" +keywords: ["mcp.base.org setup", "Base MCP install", "Claude Desktop MCP config", "ChatGPT MCP connector", "Claude Code MCP", "Cursor MCP", "VS Code MCP", "Windsurf MCP", "Zed MCP", "JetBrains MCP"] +--- + +import { X402PayDemo } from "/snippets/x402PayDemo.jsx" + +Base MCP lives at `https://mcp.base.org`. Add it to your AI assistant once and your wallet tools are available in every conversation. + +## Authentication + +Connecting `mcp.base.org` requires a **Coinbase account** with a Base Account (smart wallet). When you first use a transactional tool (send, swap, sign), your assistant will return an `approvalUrl` — open it at `keys.coinbase.com` to authorize your Base Account and approve the transaction. + + +Every individual transaction requires approval at `keys.coinbase.com`. Your assistant never has unilateral access to your funds. + + +## Platform setup + +### Claude Desktop + + + Add to Claude + + +Click the button above to open the connector settings directly, paste `https://mcp.base.org`, and save. + +**Or edit the config file manually:** + +| Platform | Config path | +|----------|-------------| +| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` | +| Windows | `%APPDATA%\Claude\claude_desktop_config.json` | +| Linux | `~/.config/Claude/claude_desktop_config.json` | + +```json claude_desktop_config.json +{ + "mcpServers": { + "base-account": { + "url": "https://mcp.base.org" + } + } +} +``` + +Restart Claude Desktop. The wallet MCP will show as connected in the toolbar. + +--- + +### ChatGPT + + + Add to ChatGPT + + +1. Enable **Developer Mode** if prompted (under Advanced) +2. Click **Add custom connector** +3. Enter `https://mcp.base.org` as the server URL +4. Save + +On first use, ChatGPT will prompt you to authorize your Coinbase account. + +--- + +### Claude Code + +```bash Terminal +claude mcp add --transport http base-account https://mcp.base.org +``` + +This writes to your project's `.claude/settings.json`. To add globally (all projects): + +```bash Terminal +claude mcp add --transport http --scope user base-account https://mcp.base.org +``` + +Verify the connection: + +```bash Terminal +claude mcp list +``` + +--- + +### Codex + +```bash Terminal +codex mcp add base-account --url https://mcp.base.org/ +``` + +Or add to `codex.toml`: + +```toml codex.toml +[mcp_servers.base-account] +url = "https://mcp.base.org/" +``` + +--- + +### Cursor + + + Add to Cursor + + +Or add manually to `~/.cursor/mcp.json`: + +```json ~/.cursor/mcp.json +{ + "mcpServers": { + "base-account": { + "url": "https://mcp.base.org" + } + } +} +``` + +--- + +### VS Code + + + Add to VS Code + + +Or add to your VS Code MCP settings: + +```json settings.json +{ + "servers": { + "base-account": { + "type": "http", + "url": "https://mcp.base.org" + } + } +} +``` + +--- + +### Windsurf + +Add to `~/.codeium/windsurf/mcp_config.json`: + +```json mcp_config.json +{ + "mcpServers": { + "base-account": { + "url": "https://mcp.base.org" + } + } +} +``` + +You can also add servers from the UI: open **Cascade** → click the **hammer icon** → **Add MCP Server**. + +--- + +### Zed + +Add to your Zed `settings.json` (`~/.config/zed/settings.json` on macOS/Linux, `%APPDATA%\Zed\settings.json` on Windows): + +```json settings.json +{ + "context_servers": { + "base-account": { + "source": "custom", + "command": { + "path": "npx", + "args": ["-y", "mcp-remote", "https://mcp.base.org"] + } + } + } +} +``` + + + Zed does not yet support native remote HTTP MCP servers. The snippet above uses [`mcp-remote`](https://github.com/geelen/mcp-remote) as a local proxy bridge — no pre-install needed. See [Zed MCP docs](https://zed.dev/docs/ai/mcp) for the latest config format. + + +--- + +### JetBrains AI Assistant + +1. Open your JetBrains IDE (IntelliJ, WebStorm, PyCharm, etc.) +2. Go to **Settings** → **AI Assistant** → **Model Context Protocol (MCP)** +3. Click **Add** and select **HTTP** as the transport +4. Enter `https://mcp.base.org` as the server URL +5. Apply and restart the IDE + +See [JetBrains AI Assistant MCP docs](https://www.jetbrains.com/help/ai-assistant/mcp.html) for full configuration options. + +--- + +### Le Chat (Mistral) + +1. Open [mistral.ai](https://mistral.ai) and sign in +2. Go to **Settings** → **Connectors** +3. Click **Add custom connector** +4. Enter `https://mcp.base.org` as the server URL +5. Save and return to a chat + +See [Le Chat MCP connector docs](https://help.mistral.ai/en/articles/393572-configuring-a-custom-connector) for full details. + +--- + +### Warp + +1. Open [Warp](https://www.warp.dev/) terminal +2. Go to **Settings** → **AI** → **MCP Servers** +3. Click **Add server** +4. Select **SSE** as the transport and enter `https://mcp.base.org` as the URL +5. Save — the server starts automatically with Warp + +See [Warp MCP docs](https://docs.warp.dev/knowledge-and-collaboration/mcp) for CLI-based setup. + +--- + +## Approval mode + + + +All write operations (send, swap, sign, send_calls) work in **approval mode**: + + + + You ask your assistant to send funds, swap tokens, or sign a message. + + + Your assistant returns an `approvalUrl` (at `keys.coinbase.com`) and a `requestId`. + + + Open the link, review the transaction details, and confirm. Nothing is signed until you do. + + + Your assistant polls `get_request_status` with the `requestId` and confirms completion once you've approved. + + + +## Next steps + + + + Step-by-step guides for sending, swapping, checking balance, and more. + + + Add Morpho for lending and vault operations on Base. + + diff --git a/docs/ai-agents/setup/wallet-setup.mdx b/docs/ai-agents/setup/wallet-setup.mdx deleted file mode 100644 index 2c48d5a80..000000000 --- a/docs/ai-agents/setup/wallet-setup.mdx +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: "Wallet Setup for Agents" -description: "Give your AI agent a dedicated wallet on Base to hold funds, send payments, sign messages, and interact with onchain protocols securely." -keywords: ["AI agent wallet", "Bankr wallet", "CDP agentic wallet", "Sponge wallet", "onchain AI agent", "agent wallet setup"] ---- - -import { WalletSetupDemo } from "/snippets/WalletSetupDemo.jsx" - -An onchain wallet gives your agent the ability to hold funds, authorize transactions, and sign messages. Without one, your agent can read data but can't pay for services, receive payments, or prove its identity. - -## Mock Demo - - - -## Why your agent needs a dedicated wallet - -An AI agent *could* generate its own wallet by creating a random private key through prompting, but this is unsafe: - -- The private key appears in the agent's conversation context, where it can be logged, cached, or leaked through middleware -- Any system with access to the agent's prompt history could extract the key -- If the key is compromised, all funds in the wallet are permanently lost - -Dedicated wallet services solve this by managing keys in secure infrastructure separated from your agent's runtime. Your agent requests transactions without ever seeing the private key. - -## Choose a wallet - - - - Every Bankr agent gets a cross-chain wallet on Base, Ethereum, Solana, Polygon, and Unichain. Gas is sponsored on supported chains. Built-in swap tools make Bankr ideal for trading agents. - - Install the Bankr skill from your agent chat: - - ```text - install the bankr skill from https://github.com/BankrBot/skills - ``` - - Create a dedicated account at [bankr.bot](https://bankr.bot) and generate an API key at [bankr.bot/api](https://bankr.bot/api). Don't use your personal Bankr account — keep your agent's wallet separate. - - [Bankr docs →](https://docs.bankr.bot) - - - - Coinbase's standalone wallet for AI agents. Authentication is via email OTP — no API keys required in your agent. Private keys stay in Coinbase's secure infrastructure. Native x402 payment support is built in. - - Install the pre-built wallet skills: - - ```bash Terminal - npx skills add coinbase/agentic-wallet-skills - ``` - - Then ask your agent to authenticate: - - ```text - Sign in to my wallet with your@email.com - ``` - - Skills include: `authenticate-wallet`, `fund`, `send-usdc`, `trade`, `pay-for-service`, `monetize-service`, and more. Operates on Base. - - [CDP Agentic Wallet docs →](https://docs.cdp.coinbase.com/agentic-wallet/welcome) - - - - A multi-chain agent wallet with native x402 payment handling, built-in token swaps, and cross-chain bridges across Base, Ethereum, and Solana. Sponge's x402 proxy handles discovery, payment, and retries automatically. - - Register your agent to get a wallet immediately: - - ```bash Terminal - curl -X POST https://api.wallet.paysponge.com/api/agents/register \ - -H "Sponge-Version: 0.2.1" \ - -H "Content-Type: application/json" \ - -d '{"name": "my-agent", "agentFirst": true}' - ``` - - Store the returned `apiKey`: - - ```bash Terminal - export SPONGE_API_KEY=sponge_live_... - ``` - - [Sponge Wallet docs →](https://wallet.paysponge.com/skill.md) - - - - -**Claude Code, Codex, and OpenCode users** — the wallet skills above work with any skills-enabled AI coding tool. Run the same `npx skills add` command from within your coding tool to get the same onchain capabilities. - - -## What your agent can do with a wallet - -Once your agent has a wallet, it can: - -- **Hold stablecoins**: receive and store USDC or other tokens -- **Send and receive payments**: transfer funds to other wallets, pay for API access, or receive payments for services -- **Sign messages**: cryptographically prove that a message or request came from your agent (used for identity verification) -- **Interact with protocols**: call smart contracts to swap tokens, provide liquidity, or use other onchain services - - - -## Next step - - - Register your agent for discoverability and identity verification. - diff --git a/docs/ai-agents/skills/index.mdx b/docs/ai-agents/skills/index.mdx index 6ffde202c..7c6d67f02 100644 --- a/docs/ai-agents/skills/index.mdx +++ b/docs/ai-agents/skills/index.mdx @@ -1,41 +1,42 @@ --- -title: "Overview" -description: "Installable agent capabilities for wallets, payments, and trading on Base" -keywords: ["agent skills", "Bankr", "CDP agentic wallet", "Sponge wallet", "x402 skills", "trading agent", "Base agent"] +title: "Skills" +description: "Install skills to give your AI coding assistant deep context on Base MCP tools and CDP Agentic Wallet capabilities" +keywords: ["base-mcp skill", "CDP agentic wallet skill", "Base skills", "agent skills", "npx skills add base"] --- -Skills are installable knowledge packs that give your AI agent specific onchain capabilities — a wallet, payment handling, market data access, or trade execution. Install a skill and your agent knows what to do without any custom integration code. +Skills are installable knowledge packs that give your AI coding assistant deep context on specific APIs and tools — so it knows what to do without custom integration code. - - - Cross-chain wallet with built-in swaps, gas sponsorship, and token launching. - +## base-mcp skill - - Email-authenticated wallet on Base with x402 payment skills bundled in. - +The `base-mcp` skill gives your coding assistant full context on Base MCP: all 9 tools, when to use them, approval mode patterns, and how to orchestrate with protocol plugins like Morpho. - - Multi-chain wallet with native x402 proxy, swaps, bridges, and banking. - +```bash Terminal +npx skills add base/base-skills --skill base-mcp +``` - - Discover, pay for, and monetize x402 API services via CDP Agentic Wallet. - +The skill uses progressive context sharing — it loads detailed reference docs only for the task at hand, keeping context tight. - - Sponge's built-in x402 proxy — discover and pay for services automatically. - +[base/base-skills on GitHub →](https://github.com/base/base-skills) - - Price feeds, market cap, and OHLCV data via x402 — no API key required. - +## CDP Agentic Wallet skills - - Token balances, NFT metadata, portfolio data, and prices via x402 SIWE auth. - +For x402 payments (paying for API access per-request in stablecoins), use the CDP Agentic Wallet skill bundle: + +```bash Terminal +npx skills add coinbase/agentic-wallet-skills +``` - - Execute token swaps using wallet-native skills across Bankr, CDP, and Sponge. +Includes `pay-for-service`, `search-for-service`, `monetize-service`, `send-usdc`, `trade`, and more. + + + + Email-authenticated wallet with x402 payment skills bundled in. + + + Discover, pay for, and monetize x402 API services. + + +x402 support for Base MCP is coming soon. See [Payments](/ai-agents/payments) for details. + diff --git a/docs/ai-agents/skills/payments/cdp-payment-skills.mdx b/docs/ai-agents/skills/payments/cdp-payment-skills.mdx index e49427ac7..22de94614 100644 --- a/docs/ai-agents/skills/payments/cdp-payment-skills.mdx +++ b/docs/ai-agents/skills/payments/cdp-payment-skills.mdx @@ -1,10 +1,14 @@ --- title: "CDP Payment Skills" -description: "Skills for discovering, paying for, and monetizing x402 API services via the CDP Agentic Wallet" -keywords: ["CDP payment skills", "search-for-service skill", "pay-for-service skill", "monetize-service skill", "x402 bazaar skill"] +description: "x402 payment skills for discovering, paying for, and monetizing API services — part of the CDP Agentic Wallet skill bundle" +keywords: ["CDP payment skills", "x402 skills", "pay-for-service skill", "search-for-service skill", "monetize-service skill"] --- -Three skills from the CDP Agentic Wallet bundle cover the full x402 commerce loop: finding paid APIs, calling them with automatic payment, and gating your own endpoints to charge other agents. +The CDP payment skills — included in the CDP Agentic Wallet bundle — give your agent the ability to discover x402-compatible APIs, pay for them per-request, and expose its own paid endpoints. + + +x402 support for Base MCP is coming soon. Until then, these skills require the CDP Agentic Wallet. See [Payments](/ai-agents/payments) for context. + ## Install @@ -12,9 +16,7 @@ Three skills from the CDP Agentic Wallet bundle cover the full x402 commerce loo npx skills add coinbase/agentic-wallet-skills ``` -Included in the same package as the [CDP Agentic Wallet](/ai-agents/skills/wallets/cdp-agentic-wallet). No separate install needed. - -## What the skill covers +## Payment skills | Skill | What it does | |-------|-------------| diff --git a/docs/ai-agents/skills/payments/sponge-x402.mdx b/docs/ai-agents/skills/payments/sponge-x402.mdx deleted file mode 100644 index 0708d7116..000000000 --- a/docs/ai-agents/skills/payments/sponge-x402.mdx +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: "Sponge x402" -description: "Skill for discovering and paying for x402 services automatically using Sponge Wallet's built-in proxy" -keywords: ["Sponge x402 skill", "x402 proxy skill", "automatic x402 payment skill", "discover x402 service skill", "paysponge x402 skill"] ---- - -Sponge's built-in x402 proxy handles service discovery, payment signing, and retries automatically. The skill lets your agent find and pay for any x402-gated API in a single step — no manual 402 handling, no retry logic. - -## Install - -Included with [Sponge Wallet](/ai-agents/skills/wallets/sponge-wallet). No separate install needed. - -## What the skill covers - -| Capability | Description | -|------------|-------------| -| **Service discovery** | Search the x402 catalog by keyword | -| **Automatic payment** | Detect a 402, pay in USDC, and retry transparently | -| **Payment links** | Create reusable payment links to gate your own services | - -## Example prompts - -```text -Find a weather API and pay for it using Sponge -``` - -```text -Search for sentiment analysis APIs in the x402 catalog -``` - -```text -Create a payment link for my market data service at $0.01 per request -``` - -## Reference - -- [Sponge Wallet skill doc →](https://wallet.paysponge.com/skill.md) diff --git a/docs/ai-agents/skills/trading/alchemy-agentic-gateway.mdx b/docs/ai-agents/skills/trading/alchemy-agentic-gateway.mdx deleted file mode 100644 index 5825974c3..000000000 --- a/docs/ai-agents/skills/trading/alchemy-agentic-gateway.mdx +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: "Alchemy Agentic Gateway" -description: "Skill for accessing Alchemy's blockchain APIs — token balances, NFTs, portfolio data, and prices — via x402 SIWE auth" -keywords: ["Alchemy agentic gateway skill", "Alchemy x402 skill", "onchain data agent skill", "SIWE x402 skill", "alchemy skill agent"] ---- - -The Alchemy Agentic Gateway skill gives your agent access to Alchemy's enhanced blockchain APIs at `https://x402.alchemy.com` — token balances, NFT metadata, portfolio data, token prices, and decoded transaction history — authenticated via Sign-In With Ethereum (SIWE) and paid per call via x402. - -## Install - -```bash Terminal -npx @alchemy/x402 wallet generate -``` - -Then follow the skill setup to sign a SIWE auth token. The full setup guide is in the skill reference below. - -## What the skill covers - -| Data | Description | -|------|-------------| -| **Token balances** | ERC-20 balances for any address on Base | -| **NFT metadata** | Token attributes, images, and ownership | -| **Portfolio data** | Multi-chain token holdings with metadata | -| **Token prices** | Current prices by symbol | -| **Transaction history** | Decoded asset transfers | - -## Example prompts - -```text -Check the token balances at 0xYourAddress on Base -``` - -```text -Get the portfolio for 0xYourAddress across all chains -``` - -```text -What's the current price of ETH and USDC? -``` - -```text -Show me the NFTs owned by 0xYourAddress -``` - -## Reference - -- [Alchemy Agentic Gateway skill →](https://github.com/alchemyplatform/skills/tree/main/skills/agentic-gateway) diff --git a/docs/ai-agents/skills/trading/coingecko.mdx b/docs/ai-agents/skills/trading/coingecko.mdx deleted file mode 100644 index bdbf7bd4f..000000000 --- a/docs/ai-agents/skills/trading/coingecko.mdx +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: "CoinGecko" -description: "Skill for fetching live crypto price feeds, market cap, and OHLCV data via x402 — no API key required" -keywords: ["CoinGecko skill", "price feed skill", "crypto market data x402 skill", "agent data source skill", "CoinGecko x402 agent"] ---- - -CoinGecko provides cryptocurrency price feeds, market cap data, and historical OHLCV via x402-enabled endpoints. Your agent pays per call in USDC — no API key, no subscription, no rate-limit tier. - -## Install - -Access CoinGecko data through your existing wallet skill: - -- **CDP Agentic Wallet** — use the `pay-for-service` skill (`npx skills add coinbase/agentic-wallet-skills`) -- **Sponge Wallet** — use the built-in x402 proxy (no extra install) -- **Bankr** — prompt directly, Bankr handles discovery and payment - -## What the skill covers - -| Data | Description | -|------|-------------| -| **Price feeds** | Current price for any asset in USD or other currencies | -| **Market data** | Market cap, volume, and circulating supply | -| **Historical OHLCV** | Open/high/low/close/volume over any time range | - -## Example prompts - -```text -Get the current ETH price from CoinGecko -``` - -```text -Get current prices for ETH, BTC, and SOL -``` - -```text -Fetch the 7-day OHLCV for Bitcoin from CoinGecko -``` - -```text -What's the market cap of Ethereum? -``` - -## Reference - -- [pay-for-service skill →](https://docs.cdp.coinbase.com/agentic-wallet/skills/pay-for-service) -- [CoinGecko API docs →](https://docs.coingecko.com) diff --git a/docs/ai-agents/skills/trading/swap-execution.mdx b/docs/ai-agents/skills/trading/swap-execution.mdx deleted file mode 100644 index 8a6d005ea..000000000 --- a/docs/ai-agents/skills/trading/swap-execution.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Swap Execution" -description: "Skills for executing token swaps on Base using wallet-native tools across Bankr, CDP Agentic Wallet, and Sponge" -keywords: ["swap execution skill", "token swap agent skill", "Bankr swap skill", "CDP trade skill", "Sponge swap skill"] ---- - -Bankr, CDP Agentic Wallet, and Sponge Wallet all include built-in swap skills — no external DEX integration required. Install any of the three wallet skills and your agent can trade tokens on Base with a simple prompt. - -## Install - -Choose the wallet skill that fits your agent: - -| Wallet | Install | -|--------|---------| -| **Bankr** | `install the bankr skill from https://github.com/BankrBot/skills` | -| **CDP Agentic Wallet** | `npx skills add coinbase/agentic-wallet-skills` | -| **Sponge Wallet** | Register via `https://api.wallet.paysponge.com/api/agents/register` | - -## What the skill covers - -| Capability | Bankr | CDP | Sponge | -|------------|-------|-----|--------| -| Token swaps on Base | ✓ | ✓ | ✓ | -| Cross-chain swaps | ✓ | — | ✓ (via deBridge) | -| Gas sponsorship | ✓ | ✓ | — | -| Preconf simulation | ✓ | ✓ | ✓ | - -## Example prompts - -```text -Buy $50 of ETH on Base -``` - -```text -Swap 100 USDC for ETH at market price -``` - -```text -Simulate buying $50 of ETH then execute if the price impact is below 1% -``` - -```text -Trade 0.01 ETH for USDC -``` - -## Reference - -- [Bankr docs →](https://docs.bankr.bot) -- [CDP trade skill →](https://docs.cdp.coinbase.com/agentic-wallet/skills) -- [Sponge skill doc →](https://wallet.paysponge.com/skill.md) diff --git a/docs/ai-agents/skills/wallets/bankr.mdx b/docs/ai-agents/skills/wallets/bankr.mdx deleted file mode 100644 index 051841362..000000000 --- a/docs/ai-agents/skills/wallets/bankr.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Bankr" -description: "Skill that gives your AI agent a cross-chain wallet with built-in swaps, gas sponsorship, and token launching" -keywords: ["Bankr skill", "agent wallet skill", "cross-chain wallet agent", "Bankr AI agent", "bankr.bot skill"] ---- - -The Bankr skill gives your AI agent a self-custodied wallet across Base, Ethereum, Solana, Polygon, and Unichain. Gas is sponsored on supported chains, swap tools handle trades natively, and agents can launch tokens and earn trading fees to fund their own compute. - -## Install - -From your agent chat: - -```text -install the bankr skill from https://github.com/BankrBot/skills -``` - -Then create a dedicated account at [bankr.bot](https://bankr.bot) and generate an API key at [bankr.bot/api](https://bankr.bot/api). - -## What the skill covers - -| Capability | Description | -|------------|-------------| -| **Cross-chain wallet** | Hold and transfer funds on Base, ETH, Solana, Polygon, and Unichain | -| **Gas sponsorship** | Transactions on supported chains don't require ETH for gas | -| **Token swaps** | Buy and sell tokens with wallet-native tools — no DEX integration needed | -| **Token launching** | Deploy tokens on Base and redirect trading fees to the agent | -| **Trading signals** | Base network signals via the `bankr-signals` skill | - -## Example prompts - -```text -Buy $50 of ETH on Base -``` - -```text -Swap 100 USDC for ETH at market price -``` - -```text -Check my wallet balance across all chains -``` - -```text -Send 10 USDC to 0xRecipientAddress -``` - -## Reference - -- [Bankr docs →](https://docs.bankr.bot) -- [Bankr skills on GitHub →](https://github.com/BankrBot/skills) diff --git a/docs/ai-agents/skills/wallets/cdp-agentic-wallet.mdx b/docs/ai-agents/skills/wallets/cdp-agentic-wallet.mdx index 27f44d1a9..a3cde1bec 100644 --- a/docs/ai-agents/skills/wallets/cdp-agentic-wallet.mdx +++ b/docs/ai-agents/skills/wallets/cdp-agentic-wallet.mdx @@ -1,10 +1,14 @@ --- title: "CDP Agentic Wallet" -description: "Skill that gives your AI agent an email-authenticated wallet on Base with x402 payments built in" -keywords: ["CDP agentic wallet skill", "coinbase agent wallet skill", "awal skill", "x402 agent skill", "npx skills add coinbase"] +description: "Email-authenticated wallet on Base with x402 payment skills — use this for agents that need to pay for or accept API payments" +keywords: ["CDP agentic wallet skill", "x402 agent wallet", "coinbase agentic wallet skill", "awal skill", "npx skills add coinbase"] --- -The CDP Agentic Wallet skill gives your AI agent a managed wallet on Base authenticated via email OTP — no private keys in the agent's context. The skill bundle includes seven capabilities covering authentication, funding, sending, trading, and x402 payments. +The CDP Agentic Wallet is the recommended path for agents that need **x402 payment capabilities** — paying for API access per-request in stablecoins, or charging other agents for your services. + + +For wallet operations (sending, swapping, checking balances), use [Base MCP](/ai-agents/quickstart) instead. CDP Agentic Wallet is specifically the right choice when you need x402 protocol support. + ## Install @@ -30,14 +34,6 @@ npx skills add coinbase/agentic-wallet-skills Sign in to my wallet with your@email.com ``` -```text -Send 10 USDC to 0xRecipientAddress -``` - -```text -Trade 0.01 ETH for USDC -``` - ```text Find a weather API and get the forecast for New York ``` diff --git a/docs/ai-agents/skills/wallets/sponge-wallet.mdx b/docs/ai-agents/skills/wallets/sponge-wallet.mdx deleted file mode 100644 index f90cc9b79..000000000 --- a/docs/ai-agents/skills/wallets/sponge-wallet.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "Sponge Wallet" -description: "Skill that gives your AI agent a multi-chain wallet with native x402 payments, swaps, bridges, and banking" -keywords: ["Sponge wallet skill", "paysponge skill", "x402 proxy skill", "multi-chain agent wallet skill", "sponge skill.md"] ---- - -The Sponge Wallet skill gives your AI agent a multi-chain wallet covering Base, Ethereum, and Solana. It includes a native x402 payment proxy, token swaps, cross-chain bridges, prediction market trading, and banking integrations. - -## Install - -Register your agent to receive a wallet and API key: - -```text -Register my agent with Sponge Wallet using the API at https://api.wallet.paysponge.com/api/agents/register -``` - -Or read the full skill reference your agent can follow: - -```text -Read the Sponge skill doc at https://wallet.paysponge.com/skill.md -``` - -## What the skill covers - -| Capability | Description | -|------------|-------------| -| **Multi-chain wallet** | Hold and transfer funds on Base, Ethereum, and Solana | -| **Native x402 proxy** | Discover services, pay, and get responses in one step | -| **Token swaps** | Swap tokens on Base and Solana DEXs | -| **Cross-chain bridges** | Bridge assets across chains via deBridge | -| **Prediction markets** | Trade on Polymarket and Hyperliquid | -| **Banking** | Virtual bank accounts and ACH payouts via Bridge.xyz | - -## Example prompts - -```text -Check my Sponge wallet balance -``` - -```text -Swap 100 USDC for ETH on Base using Sponge -``` - -```text -Find a weather API and pay for it using my Sponge wallet -``` - -```text -Bridge 50 USDC from Base to Solana -``` - -## Reference - -- [Sponge Wallet skill doc →](https://wallet.paysponge.com/skill.md) diff --git a/docs/ai-agents/trading/data-fetching.mdx b/docs/ai-agents/trading/data-fetching.mdx deleted file mode 100644 index 317e5da3e..000000000 --- a/docs/ai-agents/trading/data-fetching.mdx +++ /dev/null @@ -1,190 +0,0 @@ ---- -title: "Fetching Market Data" -description: "Use x402 to access live market data from CoinGecko, Alchemy, and other sources — no API key management required" -keywords: ["x402 market data", "trading agent data", "CoinGecko x402", "Alchemy x402", "pay per call data", "agent data fetching"] ---- - -import { DataFetchingDemo } from "/snippets/DataFetchingDemo.jsx" - -x402 is well-suited for trading data: your agent pays per call in USDC, with no API key registration, subscription management, or rate-limit tiers to negotiate. The agent gets the data, the provider gets paid — that's the entire relationship. - -## Mock Demo - - - -## Why x402 for market data - -- **No API key management** — your agent pays on demand; no credentials to rotate or store securely -- **Pay only for what you use** — no monthly subscription for data you might not always need -- **Works across any wallet** — [Sponge Wallet's](https://www.paysponge.com) x402 proxy, [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/) skills, and `x402-axios` all handle payment automatically -- **Composable** — your agent can call multiple data providers in the same session, paying each separately - -## Discovering x402-compatible endpoints - -x402-compatible services publish a discovery document at `/.well-known/x402.json`. You can also browse the Bazaar catalog for a curated list of x402 data providers. - - - - Use the [`search-for-service`](https://docs.cdp.coinbase.com/agentic-wallet/skills/search-for-service) skill to search the x402 Bazaar: - - ```bash Terminal - npx awal@latest x402 bazaar search "price feed" - ``` - - To browse all available resources: - - ```bash Terminal - npx awal@latest x402 bazaar list --network base - ``` - - - ```bash Terminal - curl "https://api.wallet.paysponge.com/api/discover?query=price+feed" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" - ``` - - - -## Example x402 data sources - -### CoinGecko — price feeds - -CoinGecko provides cryptocurrency price feeds, market cap data, and historical OHLCV via x402-enabled endpoints. - -Fetch the current ETH price: - - - - Use the [`pay-for-service`](https://docs.cdp.coinbase.com/agentic-wallet/skills/pay-for-service) skill: - - ```bash Terminal - npx awal@latest x402 pay "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd" - ``` - - - ```bash Terminal - curl -X POST "https://api.wallet.paysponge.com/api/x402/fetch" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" \ - -H "Content-Type: application/json" \ - -d '{ - "url": "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd", - "method": "GET", - "preferred_chain": "base" - }' - ``` - - - -### Alchemy — onchain data - -Alchemy exposes enhanced APIs for onchain data — token balances, NFT metadata, mempool visibility, and decoded transaction history — via their [Agentic Gateway](https://github.com/alchemyplatform/skills/tree/main/skills/agentic-gateway) at `https://x402.alchemy.com`. - - - Alchemy's x402 gateway uses SIWE wallet authentication via their own [`@alchemy/x402`](https://github.com/alchemyplatform/skills/tree/main/skills/agentic-gateway) CLI — not a generic x402 bazaar endpoint. Follow the setup steps below before making requests. - - -**Step 1 — Install and set up a wallet:** - -```bash Terminal -npx @alchemy/x402 wallet generate -``` - -**Step 2 — Generate a SIWE auth token:** - -```bash Terminal -npx @alchemy/x402 sign --private-key ./wallet-key.txt > siwe-token.txt -``` - -**Step 3 — Fetch token balances on Base:** - - - - ```bash Terminal - TOKEN=$(cat siwe-token.txt) - - curl -s -X POST "https://x402.alchemy.com/base-mainnet/v2" \ - -H "Content-Type: application/json" \ - -H "Authorization: SIWE $TOKEN" \ - -d '{ - "jsonrpc": "2.0", - "id": 1, - "method": "alchemy_getTokenBalances", - "params": ["0xYourAddress"] - }' - ``` - - - ```bash Terminal - TOKEN=$(cat siwe-token.txt) - - curl -s -X POST "https://x402.alchemy.com/data/v1/assets/tokens/by-address" \ - -H "Content-Type: application/json" \ - -H "Authorization: SIWE $TOKEN" \ - -d '{"addresses": ["0xYourAddress"], "withMetadata": true}' - ``` - - - ```bash Terminal - TOKEN=$(cat siwe-token.txt) - - curl -s -G "https://x402.alchemy.com/prices/v1/tokens/by-symbol" \ - --data-urlencode "symbols=ETH" \ - --data-urlencode "symbols=USDC" \ - -H "Authorization: SIWE $TOKEN" - ``` - - - -If the gateway returns `402`, handle payment with the CLI and retry: - -```bash Terminal -PAYMENT_SIG=$(npx @alchemy/x402 pay --private-key ./wallet-key.txt --payment-required "$PAYMENT_REQUIRED") -``` - -See the full [Alchemy Agentic Gateway skill](https://github.com/alchemyplatform/skills/tree/main/skills/agentic-gateway) for wallet bootstrap, payment handling, and SDK integration. - -## Making data calls inside an OpenClaw agent - -Install the [Sponge Wallet](https://www.paysponge.com) skill or [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/) skills, then prompt your agent directly: - -```text -Get the current prices of ETH, BTC, and SOL from a paid data source -``` - -```text -Check the token balances at 0xYourWatchAddress on Base -``` - -The agent handles service discovery, payment, and data extraction. For a custom implementation using `x402-axios`: - -```bash Terminal -npm install x402-axios axios -``` - -```typescript TypeScript -import { withPaymentInterceptor } from "x402-axios"; -import axios from "axios"; - -// walletClient must be a viem-compatible WalletClient -const client = withPaymentInterceptor(axios.create(), walletClient); - -// If the endpoint returns 402, the interceptor pays automatically and retries -const response = await client.get("https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd"); -console.log(response.data); -``` - -The interceptor handles the full 402 → pay → retry flow. For wiring a viem `WalletClient` to your setup, see the [x402 client docs](https://docs.cdp.coinbase.com/x402/docs/client-server-model). - -## Related - - - - Execute swaps using Flashblocks timing and Base fee calibration. - - - - Full x402 flow, supported networks, and error handling. - - diff --git a/docs/ai-agents/trading/trade-execution.mdx b/docs/ai-agents/trading/trade-execution.mdx deleted file mode 100644 index 6d5675bea..000000000 --- a/docs/ai-agents/trading/trade-execution.mdx +++ /dev/null @@ -1,115 +0,0 @@ ---- -title: "Trade Execution on Base" -description: "Base-specific patterns, fee calibration, and onchain signals for trading agents" -keywords: ["Flashblocks trading", "trading agent Base", "base_transactionStatus", "onchain trading agent EVM", "L1 L2 fee optimization Base", "token swap agent"] ---- - -import { TradeExecutionDemo } from "/snippets/TradeExecutionDemo.jsx" - -Base offers two structural advantages for trading agents: **Flashblocks** (200ms preconfirmed block state, 10× faster than the 2-second block) and an exposed L1/L2 fee structure that enables explicit cost-vs-speed tradeoffs. This page covers only what is unique to Base — general EVM execution patterns are in the [Ethereum documentation](https://ethereum.org/developers/docs), and Base's RPC methods are in the [API Reference](/base-chain/api-reference/rpc-overview). - -## Mock Demo - - - -## Executing swaps with wallet-native tools - -[Bankr](https://bankr.bot), [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/), and [Sponge Wallet](https://www.paysponge.com) all include built-in swap capabilities — no external DEX integration needed. - -With [Bankr](https://bankr.bot): - -```text -Buy $50 of ETH on Base -Swap 100 USDC for ETH at market price -``` - -With [CDP Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/) skills: - -```text -Buy $50 of ETH -Trade 0.01 ETH for USDC -``` - -With [Sponge Wallet](https://www.paysponge.com): - -```bash Terminal -curl -X POST "https://api.wallet.paysponge.com/api/swap" \ - -H "Authorization: Bearer $SPONGE_API_KEY" \ - -H "Sponge-Version: 0.2.1" \ - -H "Content-Type: application/json" \ - -d '{ - "fromToken": "USDC", - "toToken": "ETH", - "amount": "100", - "chain": "base" - }' -``` - -## Execution patterns - -### Use the preconf endpoint for all reads and submissions - -Always connect to `mainnet-preconf.base.org` (or `sepolia-preconf.base.org` for testnet) rather than the standard endpoint. This is the only way to access Flashblocks `pending` state, preconfirmed transaction streams, and `base_transactionStatus`. See [Flashblocks endpoints](/base-chain/flashblocks/app-integration#rpc-endpoints) for the full list. - -### Simulate against preconfirmed state before signing - -Call [`eth_simulateV1`](/base-chain/api-reference/flashblocks-api/eth_simulateV1) against the preconf endpoint with `"blockStateCalls"` targeting the `pending` block before signing any transaction. This catches reverts against current Flashblocks state rather than the last sealed block — which may be up to 2 seconds stale by the time your transaction lands. - -### Poll `base_transactionStatus` instead of blocking on a receipt - -After submission, [`base_transactionStatus`](/base-chain/api-reference/flashblocks-api/base_transactionStatus) returns preconfirmed inclusion status within a single Flashblock interval (~200ms). Blocking on `eth_getTransactionReceipt` waits for a full sealed block (up to 2 seconds). For latency-sensitive strategies, poll `base_transactionStatus` first and only fall back to the receipt for finality confirmation. - -## Fee calibration - -### L2 priority fee heuristics - -Use [`eth_feeHistory`](/base-chain/api-reference/rpc-overview#eth_feehistory) over the last 5–10 blocks with reward percentiles `[50, 90]`: - -- **50th percentile reward** — standard inclusion within 1–3 Flashblocks -- **90th percentile reward** — fast inclusion within the next Flashblock -- **`maxFeePerGas`** — set to `nextBaseFee * 2 + maxPriorityFeePerGas` to survive base fee increases across multiple blocks without overpaying - -### L1 fee decision rule - -Before signing, estimate the L1 cost via the [GasPriceOracle](/base-chain/network-information/network-fees#querying-the-l1-fee). If the ratio below exceeds `0.8` and trade size is small, the L1 fee dominates total cost — consider deferring until Ethereum congestion subsides: - -``` -l1FeeUpperBound / (gasLimit × maxFeePerGas + l1FeeUpperBound) > 0.8 -``` - -## Base-specific failure modes - -Most transaction errors are standard EVM. These are the Base-specific cases that require different handling: - -| Failure | What it means | What to do | -| ------- | ------------- | ---------- | -| `replacement transaction underpriced` | Replacing a pending tx requires ≥10% higher `maxFeePerGas` **and** `maxPriorityFeePerGas` | Increase both by ≥10%, resubmit with same nonce | -| DA throttling (no error code returned) | Sequencer is rate-limiting L2 throughput to manage L1 data availability costs | Fee-bumping does not resolve this — wait for the throttle to lift | - -For the full error taxonomy, see [Troubleshooting Transactions](/base-chain/network-information/troubleshooting-transactions). - -**Nonce for concurrent submissions:** Always fetch with `eth_getTransactionCount(address, "pending")`. For parallel submissions, fetch once and increment locally — fetching fresh per call returns the same value for all concurrent requests. - -## Strategy signals - -Base exposes data that most chains don't provide at this resolution: - -| Signal | How to access | Opportunity category | -| ------ | ------------- | -------------------- | -| Preconfirmed pending block state (200ms early) | `eth_getBlockByNumber("pending")` on preconf endpoint | Detect price impact before block seals | -| Preconfirmed transaction stream | `eth_subscribe("newFlashblockTransactions")` | First-mover on large trades entering the block | -| Preconfirmed logs | `eth_subscribe("pendingLogs", { address, topics })` | Detect liquidation thresholds, oracle updates before finality | -| Fee spike detection | `eth_feeHistory` trend over last 5 blocks | Identify congestion onset; adjust routing or pause | -| L1 base fee trend | `GasPriceOracle.l1BaseFee()` polled over time | Time submissions to minimize L1 data cost | -| Block gas utilization | `gasUsedRatio` from `eth_feeHistory` | Predict upcoming base fee increases | - -**The Flashblocks advantage:** Most chains expose a pool of pending transactions with uncertain ordering. On Base, the Flashblocks endpoint gives agents a deterministic, ordered view of the next 200ms of chain state before it finalizes. This is an information edge that does not exist on chains with mempool-only visibility. - -## Related - -- [Flashblocks API Reference](/base-chain/api-reference/rpc-overview#flashblocks-api) — `eth_simulateV1`, `base_transactionStatus`, subscription types -- [Flashblocks Integration Guide](/base-chain/flashblocks/app-integration) — endpoints, library setup (Wagmi, Viem, Ethers) -- [Block Building](/base-chain/network-information/block-building) — Flashblocks timing, per-transaction gas maximum -- [Network Fees](/base-chain/network-information/network-fees) — EIP-1559 parameters, GasPriceOracle methods -- [JSON-RPC API Reference](/base-chain/api-reference/rpc-overview) — complete RPC method reference -- [Troubleshooting Transactions](/base-chain/network-information/troubleshooting-transactions) — full error taxonomy and retry policies diff --git a/docs/docs.json b/docs/docs.json index 241800d27..389349666 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -680,61 +680,23 @@ }, { "group": "Quickstart", - "pages": [ - "ai-agents/quickstart/payments", - "ai-agents/quickstart/trading" - ] - }, - { - "group": "Setup", - "pages": [ - "ai-agents/setup/wallet-setup", - "ai-agents/setup/agent-builder-codes", - "ai-agents/setup/agent-registration" - ] + "pages": ["ai-agents/quickstart"] }, { - "group": "Payments", - "pages": [ - "ai-agents/payments/pay-for-services-with-x402", - "ai-agents/payments/accepting-payments" - ] - }, - { - "group": "Trading", + "group": "Guides", "pages": [ - "ai-agents/trading/data-fetching", - "ai-agents/trading/trade-execution" + "ai-agents/guides/check-balance", + "ai-agents/guides/send-tokens", + "ai-agents/guides/swap-tokens", + "ai-agents/guides/pay-for-services", + "ai-agents/guides/view-history", + "ai-agents/guides/sign-messages", + "ai-agents/guides/batch-calls" ] }, { - "group": "Skills", - "pages": [ - "ai-agents/skills/index", - { - "group": "Wallets", - "pages": [ - "ai-agents/skills/wallets/bankr", - "ai-agents/skills/wallets/cdp-agentic-wallet", - "ai-agents/skills/wallets/sponge-wallet" - ] - }, - { - "group": "Payments", - "pages": [ - "ai-agents/skills/payments/cdp-payment-skills", - "ai-agents/skills/payments/sponge-x402" - ] - }, - { - "group": "Trading", - "pages": [ - "ai-agents/skills/trading/coingecko", - "ai-agents/skills/trading/alchemy-agentic-gateway", - "ai-agents/skills/trading/swap-execution" - ] - } - ] + "group": "Plugins", + "pages": ["ai-agents/plugins/morpho"] } ] } @@ -799,7 +761,70 @@ ] }, "redirects": [ - + { + "source": "/ai-agents/quickstart/payments", + "destination": "/ai-agents/quickstart" + }, + { + "source": "/ai-agents/quickstart/trading", + "destination": "/ai-agents/quickstart" + }, + { + "source": "/ai-agents/setup/wallet-setup", + "destination": "/ai-agents/setup" + }, + { + "source": "/ai-agents/setup/agent-registration", + "destination": "/ai-agents/index" + }, + { + "source": "/ai-agents/payments/pay-for-services-with-x402", + "destination": "/ai-agents/payments" + }, + { + "source": "/ai-agents/payments/accepting-payments", + "destination": "/ai-agents/payments" + }, + { + "source": "/ai-agents/tools", + "destination": "/ai-agents/guides" + }, + { + "source": "/ai-agents/tools/index", + "destination": "/ai-agents/guides" + }, + { + "source": "/ai-agents/trading/data-fetching", + "destination": "/ai-agents/guides" + }, + { + "source": "/ai-agents/trading/trade-execution", + "destination": "/ai-agents/guides" + }, + { + "source": "/ai-agents/skills/wallets/bankr", + "destination": "/ai-agents/tools" + }, + { + "source": "/ai-agents/skills/wallets/sponge-wallet", + "destination": "/ai-agents/tools" + }, + { + "source": "/ai-agents/skills/payments/sponge-x402", + "destination": "/ai-agents/payments" + }, + { + "source": "/ai-agents/skills/trading/coingecko", + "destination": "/ai-agents/tools" + }, + { + "source": "/ai-agents/skills/trading/alchemy-agentic-gateway", + "destination": "/ai-agents/tools" + }, + { + "source": "/ai-agents/skills/trading/swap-execution", + "destination": "/ai-agents/tools" + }, { "source": "/base-chain/reference/json-rpc-api", "destination": "/base-chain/api-reference/rpc-overview" diff --git a/docs/snippets/AcceptingPaymentsDemo.jsx b/docs/snippets/AcceptingPaymentsDemo.jsx index 99ca4b529..416ec8129 100644 --- a/docs/snippets/AcceptingPaymentsDemo.jsx +++ b/docs/snippets/AcceptingPaymentsDemo.jsx @@ -1,5 +1,6 @@ import { useState, useEffect, useRef } from "react"; +// Morpho plugin orchestration demo — used in plugins/morpho.mdx export const AcceptingPaymentsDemo = () => { const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; const col = { @@ -8,41 +9,50 @@ export const AcceptingPaymentsDemo = () => { active: "#60a5fa", success: "#34d399", code: "#d4d4d8", + warn: "#fb923c", }; const steps = [ - { delay: 350, left: [{ t: "> npm install x402-express express", c: "active" }], right: [ - { t: "── Middleware Config ───────────────────", c: "dim" }, - { t: "{", c: "code" }, + { delay: 400, left: [{ t: "> Find the best USDC vault on Base and deposit 100 USDC", c: "active" }], right: [ + { t: "── morpho_query_vaults ──────────────────", c: "dim" }, + { t: " asset: USDC", c: "muted" }, + { t: " sortBy: APY", c: "muted" }, + ]}, + { delay: 700, left: [{ t: " ← top vault: Morpho Flagship USDC", c: "muted" }], right: [ + { t: "", c: "dim" }, + { t: " Morpho Flagship USDC", c: "success" }, + { t: " APY: 8.42% TVL: $42.1M", c: "success" }, + { t: " address: 0x8eB6...4Fa1", c: "code" }, ]}, - { delay: 650, left: [{ t: " ✓ x402-express installed", c: "success" }], right: [ - { t: ' "path": "/api/data",', c: "code" }, - { t: ' "price": "$0.01",', c: "code" }, - { t: ' "network": "base",', c: "code" }, - { t: ' "payTo": "0x742d...c4f2"', c: "code" }, + { delay: 500, left: [{ t: "> prepare_deposit(vault, 100 USDC)", c: "active" }], right: [ + { t: "", c: "dim" }, + { t: "── morpho_prepare_deposit ───────────────", c: "dim" }, + { t: " Simulating deposit...", c: "muted" }, + ]}, + { delay: 700, left: [{ t: " ← simulation ok · calls ready", c: "muted" }], right: [ + { t: "", c: "dim" }, + { t: "{", c: "code" }, + { t: ' "chainId": "0x2105",', c: "code" }, + { t: ' "calls": [approve, deposit]', c: "code" }, { t: "}", c: "code" }, ]}, - { delay: 500, left: [{ t: "> configure x402 middleware...", c: "active" }], right: [] }, - { delay: 600, left: [{ t: " ✓ paymentMiddleware applied", c: "success" }], right: [] }, - { delay: 400, left: [{ t: " ✓ endpoint live: /api/data · $0.01/req", c: "success" }], right: [ + { delay: 500, left: [{ t: "> send_calls(chainId, calls)", c: "active" }], right: [ { t: "", c: "dim" }, - { t: "── Live endpoint ───────────────────────", c: "dim" }, - { t: " GET /api/data → 402 (unpaid)", c: "muted" }, - { t: " GET /api/data + sig → 200 (paid)", c: "success" }, + { t: "── send_calls ──────────────────────────", c: "dim" }, + { t: " Submitting to Base Account MCP...", c: "muted" }, ]}, - { delay: 900, left: [{ t: " waiting for requests...", c: "muted" }], right: [ + { delay: 600, left: [{ t: " ← approval required", c: "warn" }], right: [ { t: "", c: "dim" }, - { t: "── Incoming request ────────────────────", c: "dim" }, - { t: "GET /api/data", c: "code" }, - { t: "X-Payment-Sig: 0xc3d1...f891", c: "success" }, + { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, + { t: ' requestId: "req_xyz789"', c: "muted" }, ]}, - { delay: 700, left: [{ t: " ← payment verified · 0.01 USDC", c: "muted" }], right: [ + { delay: 500, left: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }], right: [] }, + { delay: 1000, left: [{ t: " ← user approved ✓", c: "success" }], right: [ { t: "", c: "dim" }, - { t: "── Payment verified ────────────────────", c: "dim" }, - { t: " amount: 0.01 USDC ✓", c: "success" }, - { t: " sig valid: true ✓", c: "success" }, + { t: "── get_request_status ──────────────────", c: "dim" }, + { t: ' status: "confirmed"', c: "success" }, ]}, - { delay: 400, left: [{ t: " ✓ serving data · balance +0.01 USDC", c: "success", bold: true }], right: [] }, + { delay: 400, left: [{ t: " ✓ 100 USDC deposited · earning 8.42% APY", c: "success" }], right: [] }, ]; const [leftLines, setLeftLines] = useState([]); @@ -53,39 +63,31 @@ export const AcceptingPaymentsDemo = () => { const leftRef = useRef(null); const rightRef = useRef(null); - useEffect(() => { - const t = setInterval(() => setBlink(b => !b), 530); - return () => clearInterval(t); - }, []); - + useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); + useEffect(() => { if (rightRef.current) rightRef.current.scrollTop = rightRef.current.scrollHeight; }, [rightLines]); + + const reset = () => { setLeftLines([]); setRightLines([]); setRunning(false); setDone(false); }; - const play = () => { - setLeftLines([]); - setRightLines([]); + const run = () => { + if (running || done) return; setRunning(true); - setDone(false); let i = 0; const next = () => { if (i >= steps.length) { setRunning(false); setDone(true); return; } const s = steps[i]; setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); + if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; - next(); + i++; next(); }, s.delay); }; next(); }; - useEffect(() => { setTimeout(play, 350); }, []); // eslint-disable-line react-hooks/exhaustive-deps - const renderLine = (item, i) => { if (!item.t) return
; - return ( -
{item.t}
- ); + return
{item.t}
; }; return ( @@ -94,33 +96,41 @@ export const AcceptingPaymentsDemo = () => {
{">"}_
- Accepting Payments + Morpho + Base Account MCP
- + onMouseLeave={e => { e.currentTarget.style.color = "#3f3f46"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "transparent"; }}>{"↺"}
- -
-
- Agent +
+
+
+ Agent +
+
+ {leftLines.map(renderLine)} + {running &&
{"▋"}
} +
-
- {leftLines.map(renderLine)} - {running &&
{"▋"}
} +
+
+ MCP Response +
+
+ {rightLines.map(renderLine)} +
-
+ {!running && !done && leftLines.length === 0 && ( + + )} {done && ( - + onMouseLeave={e => { e.currentTarget.style.color = "#52525b"; e.currentTarget.style.background = "none"; }}>{"↺"} Play again )}
diff --git a/docs/snippets/AgentPaymentDemo.jsx b/docs/snippets/AgentPaymentDemo.jsx index 5224d02e1..a21b0772b 100644 --- a/docs/snippets/AgentPaymentDemo.jsx +++ b/docs/snippets/AgentPaymentDemo.jsx @@ -8,199 +8,158 @@ export const AgentPaymentDemo = () => { active: "#60a5fa", success: "#34d399", code: "#d4d4d8", + warn: "#fb923c", }; const flows = { - wallet_cdp: [ - { delay: 350, left: [{ t: "> npx skills add coinbase/agentic-wallet-skills", c: "active" }], right: [ - { t: "── wallet.config.json ──────────────────", c: "dim" }, + // Tab 0 — Connect: platform choice + connect_claude: [ + { delay: 400, left: [{ t: "> claude mcp add --transport http base-account https://mcp.base.org", c: "active" }], right: [ + { t: "── .claude/settings.json ───────────────", c: "dim" }, { t: "{", c: "code" }, ]}, - { delay: 550, left: [{ t: " ✓ skill installed", c: "success" }], right: [ - { t: ' "provider": "coinbase",', c: "code" }, - { t: ' "network": "base",', c: "code" }, - { t: ' "skills": ["agentic-wallet"]', c: "code" }, + { delay: 650, left: [{ t: " ✓ MCP server added: base-account", c: "success" }], right: [ + { t: ' "mcpServers": {', c: "code" }, + { t: ' "base-account": {', c: "code" }, + { t: ' "url": "https://mcp.base.org"', c: "code" }, + { t: " }", c: "code" }, + { t: " }", c: "code" }, { t: "}", c: "code" }, ]}, - { delay: 500, left: [{ t: "> Sign in with your@email.com", c: "active" }], right: [] }, - { delay: 650, left: [{ t: " ← OTP sent · checking...", c: "muted" }], right: [] }, - { delay: 600, left: [{ t: " ✓ CDP wallet connected 0x4a3f...b7c1", c: "success" }], right: [ + { delay: 600, left: [{ t: "> Show me my wallets", c: "active" }], right: [] }, + { delay: 500, left: [{ t: " ← Authorizing via keys.coinbase.com...", c: "warn" }], right: [ { t: "", c: "dim" }, - { t: " address: 0x4a3f...b7c1", c: "success" }, - { t: " network: base-mainnet", c: "success" }, + { t: "── OAuth ───────────────────────────────", c: "dim" }, + { t: " → keys.coinbase.com/authorize", c: "warn" }, ]}, - ], - wallet_sponge: [ - { delay: 350, left: [{ t: "> curl -X POST https://api.wallet.paysponge.com/...", c: "active" }], right: [ - { t: "── POST /api/agents/register ───────────", c: "dim" }, - { t: "Host: api.wallet.paysponge.com", c: "muted" }, - { t: "Content-Type: application/json", c: "muted" }, - ]}, - { delay: 750, left: [{ t: ' ← {"apiKey": "sponge_live_..."}', c: "muted" }], right: [ + { delay: 800, left: [{ t: " ✓ Base Account connected 0x4a3f...b7c1", c: "success" }], right: [ { t: "", c: "dim" }, - { t: "── 200 OK ──────────────────────────────", c: "dim" }, - { t: "{", c: "code" }, - { t: ' "apiKey": "sponge_live_abc...xyz",', c: "code" }, - { t: ' "walletId": "wlt_a1b2c3d4"', c: "code" }, - { t: "}", c: "code" }, + { t: ' address: "0x4a3f...b7c1"', c: "success" }, + { t: ' network: "base-mainnet"', c: "success" }, + { t: ' status: "ready"', c: "success" }, ]}, - { delay: 450, left: [{ t: "> export SPONGE_API_KEY=sponge_live_...", c: "active" }], right: [] }, - { delay: 450, left: [{ t: " ✓ Sponge wallet ready", c: "success" }], right: [] }, ], - wallet_bankr: [ - { delay: 350, left: [{ t: "> install bankr skill from github.com/BankrBot/skills", c: "active" }], right: [ - { t: "── github.com/BankrBot/skills ──────────", c: "dim" }, - { t: "GET /releases/latest", c: "muted" }, + connect_desktop: [ + { delay: 400, left: [{ t: "> Edit claude_desktop_config.json", c: "active" }], right: [ + { t: "── claude_desktop_config.json ──────────", c: "dim" }, + { t: "{", c: "code" }, ]}, - { delay: 700, left: [{ t: " ✓ Bankr skill installed", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: " tag: bankr-wallet-v2.1.0", c: "success" }, - { t: " size: 142 KB", c: "muted" }, + { delay: 600, left: [{ t: " Adding base-account entry...", c: "muted" }], right: [ + { t: ' "mcpServers": {', c: "code" }, + { t: ' "base-account": {', c: "code" }, + { t: ' "url": "https://mcp.base.org"', c: "code" }, + { t: " }", c: "code" }, + { t: " }", c: "code" }, + { t: "}", c: "code" }, ]}, - { delay: 500, left: [{ t: " ✓ Bankr wallet connected", c: "success" }], right: [ - { t: " ready: true", c: "success" }, + { delay: 550, left: [{ t: " Restart Claude Desktop →", c: "muted" }], right: [] }, + { delay: 700, left: [{ t: " ✓ base-account MCP connected", c: "success" }], right: [ + { t: "", c: "dim" }, + { t: "── toolbar ─────────────────────────────", c: "dim" }, + { t: " [🔵 base-account] connected", c: "success" }, ]}, ], - pay: [ - { delay: 350, left: [{ t: "> Find and fetch ETH price from a paid source", c: "active" }], right: [ - { t: "── Request ─────────────────────────────", c: "dim" }, - { t: "GET /api/v3/simple/price?ids=ethereum", c: "code" }, - { t: "Host: api.coingecko.com", c: "muted" }, + connect_chatgpt: [ + { delay: 400, left: [{ t: "> Settings → Connectors → Add MCP", c: "active" }], right: [ + { t: "── ChatGPT Connectors ───────────────────", c: "dim" }, + { t: " Add custom connector", c: "muted" }, ]}, - { delay: 600, left: [{ t: " → GET api.coingecko.com/simple/price", c: "muted" }], right: [] }, - { delay: 650, left: [{ t: " ← 402 Payment Required · 0.001 USDC", c: "muted" }], right: [ + { delay: 550, left: [{ t: " Enter: https://mcp.base.org", c: "muted" }], right: [ { t: "", c: "dim" }, - { t: "── Response 1 ──────────────────────────", c: "dim" }, - { t: "HTTP/1.1 402 Payment Required", c: "muted" }, - { t: 'X-Payment-Required: {', c: "muted" }, - { t: ' "amount": "0.001", "asset": "USDC"', c: "code" }, - { t: '}', c: "muted" }, + { t: " Server URL:", c: "muted" }, + { t: " https://mcp.base.org [Save]", c: "active" }, ]}, - { delay: 650, left: [{ t: " paying via wallet...", c: "muted" }], right: [] }, - { delay: 600, left: [{ t: " ✓ tx confirmed", c: "success" }], right: [] }, - { delay: 500, left: [{ t: " → retrying with payment signature", c: "muted" }], right: [ + { delay: 700, left: [{ t: " ✓ Base Account MCP saved", c: "success" }], right: [ { t: "", c: "dim" }, - { t: "── Request 2 ───────────────────────────", c: "dim" }, - { t: "GET /api/v3/simple/price?ids=ethereum", c: "code" }, - { t: "X-Payment-Sig: 0x1a9f...c4e2", c: "success" }, + { t: "── Connectors ──────────────────────────", c: "dim" }, + { t: " ✓ base-account mcp.base.org", c: "success" }, ]}, - { delay: 600, left: [{ t: " ← 200 OK", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── Response 2 ──────────────────────────", c: "dim" }, - { t: "HTTP/1.1 200 OK", c: "success" }, - { t: '{"ethereum":{"usd":2847.32}}', c: "code" }, - ]}, - { delay: 300, left: [{ t: " ETH $2,847.32 ↑ 2.3%", c: "code", bold: true }], right: [] }, ], - getpaid: [ - { delay: 350, left: [{ t: "> Set up a paid endpoint at $0.01 per request", c: "active" }], right: [ - { t: "── x402 middleware config ──────────────", c: "dim" }, - { t: "{", c: "code" }, - { t: ' "path": "/market-data",', c: "code" }, - { t: ' "price": "0.01",', c: "code" }, - { t: ' "asset": "USDC"', c: "code" }, - { t: "}", c: "code" }, - ]}, - { delay: 600, left: [{ t: " creating x402 middleware...", c: "muted" }], right: [] }, - { delay: 500, left: [{ t: " ✓ endpoint live: api.myagent.com/market-data", c: "success" }], right: [] }, - { delay: 400, left: [{ t: " ✓ payTo: 0x742d...c4f2", c: "success" }], right: [] }, - { delay: 800, left: [{ t: " waiting for requests...", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: "── Incoming request ────────────────────", c: "dim" }, - { t: "GET /market-data", c: "code" }, - { t: "X-Payment-Sig: 0xc3d1...f891", c: "success" }, + + // Tab 1 — Wallets & Balances: linear + balances: [ + { delay: 400, left: [{ t: "> Show me my wallets", c: "active" }], right: [ + { t: "── get_wallets ─────────────────────────", c: "dim" }, + { t: "tool: get_wallets()", c: "muted" }, ]}, - { delay: 700, left: [{ t: " ← incoming payment · 0.01 USDC", c: "muted" }], right: [ + { delay: 650, left: [{ t: " ← 2 wallets", c: "muted" }], right: [ { t: "", c: "dim" }, - { t: "── Payment verified ────────────────────", c: "dim" }, - { t: " amount: 0.01 USDC ✓", c: "success" }, - { t: " sig valid: true ✓", c: "success" }, + { t: ' { type: "base-account",', c: "code" }, + { t: ' address: "0x4a3f...b7c1",', c: "code" }, + { t: ' inSession: true }', c: "code" }, ]}, - { delay: 450, left: [{ t: " ✓ payment verified · serving data", c: "success" }], right: [] }, - ], - swap_cdp: [ - { delay: 350, left: [{ t: " ✓ using CDP wallet 0x4a3f...b7c1", c: "success" }], right: [ - { t: "── Swap quote ───────────────────────────", c: "dim" }, - { t: "POST /v1/swap/quote", c: "code" }, - { t: "Host: api.developer.coinbase.com", c: "muted" }, - ]}, - { delay: 500, left: [{ t: "> Buy $50 of ETH on Base", c: "active" }], right: [] }, - { delay: 600, left: [{ t: " fetching quote...", c: "muted" }], right: [ + { delay: 400, left: [{ t: " Base Account: 0x4a3f...b7c1", c: "success" }], right: [ { t: "", c: "dim" }, - { t: "── Quote response ───────────────────────", c: "dim" }, - { t: '{"fromAmount":"50.00 USDC",', c: "code" }, - { t: ' "toAmount":"0.01756 ETH",', c: "code" }, - { t: ' "priceImpact":"0.12%"}', c: "code" }, + { t: ' { type: "agent-wallet",', c: "code" }, + { t: ' address: "0x9c2d...e4f8",', c: "code" }, + { t: ' inSession: false }', c: "code" }, ]}, - { delay: 500, left: [{ t: " ← 0.01756 ETH · price impact 0.12%", c: "muted" }], right: [] }, - { delay: 550, left: [{ t: " impact below 1% — executing...", c: "muted" }], right: [] }, - { delay: 700, left: [{ t: " ✓ tx 0xb4f2...91ca confirmed", c: "success" }], right: [ + { delay: 600, left: [{ t: "> What's my balance on Base?", c: "active" }], right: [] }, + { delay: 500, left: [{ t: " ← get_portfolio(chain=base)", c: "muted" }], right: [ { t: "", c: "dim" }, - { t: "── Transaction ──────────────────────────", c: "dim" }, - { t: " hash: 0xb4f2...91ca", c: "success" }, - { t: " status: confirmed", c: "success" }, - { t: " block: 28,419,042", c: "muted" }, + { t: "── get_portfolio ────────────────────────", c: "dim" }, + { t: " USDC 245.80 $245.80", c: "success" }, + { t: " ETH 0.0412 $148.33", c: "success" }, + { t: " WETH 0.0100 $36.02 ", c: "success" }, ]}, - { delay: 400, left: [{ t: " ✓ received 0.01756 ETH", c: "success" }], right: [] }, + { delay: 400, left: [{ t: " Total: $430.15 on Base", c: "success" }], right: [] }, ], - swap_sponge: [ - { delay: 350, left: [{ t: " ✓ using Sponge wallet", c: "success" }], right: [ - { t: "── Swap quote ───────────────────────────", c: "dim" }, - { t: "POST /swap/quote", c: "code" }, - { t: "Host: api.wallet.paysponge.com", c: "muted" }, + + // Tab 2 — Send & Swap: choice + send: [ + { delay: 400, left: [{ t: "> Send 10 USDC to alice.base.eth", c: "active" }], right: [ + { t: "── send() ──────────────────────────────", c: "dim" }, + { t: " recipient: alice.base.eth", c: "muted" }, + { t: " amount: 10", c: "muted" }, + { t: " asset: USDC", c: "muted" }, + { t: " chain: base", c: "muted" }, ]}, - { delay: 500, left: [{ t: "> Buy $50 of ETH on Base", c: "active" }], right: [] }, - { delay: 600, left: [{ t: " fetching quote...", c: "muted" }], right: [ + { delay: 650, left: [{ t: " ← approval required", c: "warn" }], right: [ { t: "", c: "dim" }, - { t: "── Quote response ───────────────────────", c: "dim" }, - { t: '{"fromAmount":"50.00 USDC",', c: "code" }, - { t: ' "toAmount":"0.01756 ETH",', c: "code" }, - { t: ' "priceImpact":"0.12%"}', c: "code" }, + { t: "── approval mode ────────────────────────", c: "warn" }, + { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, + { t: ' requestId: "req_abc123"', c: "muted" }, ]}, - { delay: 500, left: [{ t: " ← 0.01756 ETH · price impact 0.12%", c: "muted" }], right: [] }, - { delay: 550, left: [{ t: " impact below 1% — executing...", c: "muted" }], right: [] }, - { delay: 700, left: [{ t: " ✓ tx 0xb4f2...91ca confirmed", c: "success" }], right: [ + { delay: 500, left: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }], right: [] }, + { delay: 900, left: [{ t: " ← user approved ✓", c: "success" }], right: [ { t: "", c: "dim" }, - { t: "── Transaction ──────────────────────────", c: "dim" }, - { t: " hash: 0xb4f2...91ca", c: "success" }, - { t: " status: confirmed", c: "success" }, - { t: " block: 28,419,042", c: "muted" }, + { t: "── get_request_status ──────────────────", c: "dim" }, + { t: ' status: "confirmed"', c: "success" }, + { t: ' txHash: "0xf7e3...9a12"', c: "success" }, ]}, - { delay: 400, left: [{ t: " ✓ received 0.01756 ETH", c: "success" }], right: [] }, + { delay: 400, left: [{ t: " ✓ 10 USDC sent to alice.base.eth", c: "success" }], right: [] }, ], - swap_bankr: [ - { delay: 350, left: [{ t: " ✓ using Bankr wallet", c: "success" }], right: [ - { t: "── Swap quote ───────────────────────────", c: "dim" }, - { t: "POST /swap/quote", c: "code" }, - { t: "Host: api.bankr.bot", c: "muted" }, + swap: [ + { delay: 400, left: [{ t: "> Swap 100 USDC for ETH on Base", c: "active" }], right: [ + { t: "── swap() ──────────────────────────────", c: "dim" }, + { t: " fromAsset: USDC", c: "muted" }, + { t: " toAsset: ETH", c: "muted" }, + { t: " amount: 100", c: "muted" }, + { t: " chain: base", c: "muted" }, ]}, - { delay: 500, left: [{ t: "> Buy $50 of ETH on Base", c: "active" }], right: [] }, - { delay: 600, left: [{ t: " fetching quote...", c: "muted" }], right: [ + { delay: 650, left: [{ t: " ← approval required", c: "warn" }], right: [ { t: "", c: "dim" }, - { t: "── Quote response ───────────────────────", c: "dim" }, - { t: '{"fromAmount":"50.00 USDC",', c: "code" }, - { t: ' "toAmount":"0.01756 ETH",', c: "code" }, - { t: ' "priceImpact":"0.12%"}', c: "code" }, + { t: "── approval mode ────────────────────────", c: "warn" }, + { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, + { t: ' requestId: "req_def456"', c: "muted" }, ]}, - { delay: 500, left: [{ t: " ← 0.01756 ETH · price impact 0.12%", c: "muted" }], right: [] }, - { delay: 550, left: [{ t: " impact below 1% — executing...", c: "muted" }], right: [] }, - { delay: 700, left: [{ t: " ✓ tx 0xb4f2...91ca confirmed", c: "success" }], right: [ + { delay: 500, left: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }], right: [] }, + { delay: 900, left: [{ t: " ← user approved ✓", c: "success" }], right: [ { t: "", c: "dim" }, - { t: "── Transaction ──────────────────────────", c: "dim" }, - { t: " hash: 0xb4f2...91ca", c: "success" }, - { t: " status: confirmed", c: "success" }, - { t: " block: 28,419,042", c: "muted" }, + { t: "── get_request_status ──────────────────", c: "dim" }, + { t: ' status: "confirmed"', c: "success" }, + { t: ' received: "0.03512 ETH"', c: "success" }, ]}, - { delay: 400, left: [{ t: " ✓ received 0.01756 ETH", c: "success" }], right: [] }, + { delay: 400, left: [{ t: " ✓ received 0.03512 ETH", c: "success" }], right: [] }, ], }; - const tabs = ["Setup Wallet", "Pay & Get Paid", "Swap"]; - const rightLabels = ["Wallet Config", "HTTP Trace", "Quote Details"]; + const tabs = ["Connect", "Wallets & Balances", "Send & Swap"]; + const rightLabels = ["Config", "MCP Response", "Approval Flow"]; const intros = [ - "> Setting up your agent wallet...", - "> Choose a flow:", - "> Which wallet should execute the swap?", + "> Choose your platform:", + "> Checking your Base Account...", + "> Choose an action:", ]; const [activeTab, setActiveTab] = useState(0); @@ -240,7 +199,13 @@ export const AgentPaymentDemo = () => { setChoice2(null); setRunning(false); setDone(false); - const t = setTimeout(() => setLeftLines([{ t: intros[activeTab], c: "muted" }]), 350); + const t = setTimeout(() => { + setLeftLines([{ t: intros[activeTab], c: "muted" }]); + // Tab 1 is linear — auto-start + if (activeTab === 1) { + setTimeout(() => animateFlow("balances"), 300); + } + }, 350); return () => clearTimeout(t); // eslint-disable-next-line react-hooks/exhaustive-deps }, [activeTab]); @@ -264,35 +229,27 @@ export const AgentPaymentDemo = () => { next(); }; - const pickWallet = (w) => { + const pickConnect = (p) => { if (choice1) return; - setChoice1(w); - setLeftLines(prev => [...prev, { t: " [" + w.toUpperCase() + "]", c: "active" }]); - setTimeout(() => animateFlow("wallet_" + w), 150); + setChoice1(p); + const labels = { claude: "Claude Code", desktop: "Claude Desktop", chatgpt: "ChatGPT" }; + setLeftLines(prev => [...prev, { t: " [" + labels[p] + "]", c: "active" }]); + setTimeout(() => animateFlow("connect_" + p), 150); }; - const pickPay = (p) => { + const pickAction = (a) => { if (choice2) return; - setChoice2(p); - const label = p === "pay" ? "Pay for a service" : "Get paid"; - setLeftLines(prev => [...prev, { t: " [" + label + "]", c: "active" }]); - setTimeout(() => animateFlow(p), 150); - }; - - const pickSwap = (w) => { - if (choice1) return; - setChoice1(w); - setLeftLines(prev => [...prev, { t: " [" + w.toUpperCase() + "]", c: "active" }]); - setTimeout(() => animateFlow("swap_" + w), 150); + setChoice2(a); + const labels = { send: "Send", swap: "Swap" }; + setLeftLines(prev => [...prev, { t: " [" + labels[a] + "]", c: "active" }]); + setTimeout(() => animateFlow(a), 150); }; const renderLine = (item, i) => { if (!item.t) return
; return (
{ cursor: "pointer", padding: "1px 8px", marginRight: 6, lineHeight: "20px", }; - const onBtnEnter = (e) => { - e.currentTarget.style.color = "#e4e4e7"; - e.currentTarget.style.background = "#1c1c1e"; - e.currentTarget.style.borderColor = "#3f3f46"; - }; - const onBtnLeave = (e) => { - e.currentTarget.style.color = "#60a5fa"; - e.currentTarget.style.background = "transparent"; - e.currentTarget.style.borderColor = "#27272a"; - }; + const onBtnEnter = (e) => { e.currentTarget.style.color = "#e4e4e7"; e.currentTarget.style.background = "#1c1c1e"; e.currentTarget.style.borderColor = "#3f3f46"; }; + const onBtnLeave = (e) => { e.currentTarget.style.color = "#60a5fa"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "#27272a"; }; - const showWalletBtns = activeTab === 0 && !choice1 && leftLines.length > 0; - const showPayBtns = activeTab === 1 && !choice2 && leftLines.length > 0; - const showSwapBtns = activeTab === 2 && !choice1 && leftLines.length > 0; - const isLastTab = activeTab === 2; - const footerLabel = isLastTab ? "\u21ba Play again" : "Next: " + tabs[activeTab + 1] + " \u2192"; + const showConnectBtns = activeTab === 0 && !choice1 && leftLines.length > 0; + const showActionBtns = activeTab === 2 && !choice2 && leftLines.length > 0; + const isLastTab = activeTab === 2; + const footerLabel = isLastTab ? "↺ Play again" : "Next: " + tabs[activeTab + 1] + " →"; return (
{/* Tab bar */}
- -
+
{">"}_
- {tabs.map((tab, i) => { const active = i === activeTab; return ( - ); })} -
- -
- {/* Terminal pane */} -
-
- Agent + {/* Split pane */} +
+ {/* Left — Agent */} +
+
+ Agent +
+
+ {leftLines.map(renderLine)} + {showConnectBtns && ( +
+ pick: + + + +
+ )} + {showActionBtns && ( +
+ pick: + + +
+ )} + {running &&
{"▋"}
} +
-
- {leftLines.map(renderLine)} - - {showWalletBtns && ( -
- pick: - - - -
- )} - {showPayBtns && ( -
- pick: - - -
- )} - {showSwapBtns && ( -
- pick: - - - -
- )} - - {running && ( -
{"▋"}
- )} + {/* Right — Config/Response */} +
+
+ {rightLabels[activeTab]} +
+
+ {rightLines.map(renderLine)} +
{/* Footer */}
{done && ( - )}
-
); }; diff --git a/docs/snippets/AgentRegistrationDemo.jsx b/docs/snippets/AgentRegistrationDemo.jsx index 9b83e2053..d62899ee4 100644 --- a/docs/snippets/AgentRegistrationDemo.jsx +++ b/docs/snippets/AgentRegistrationDemo.jsx @@ -2,85 +2,57 @@ import { useState, useEffect, useRef } from "react"; export const AgentRegistrationDemo = () => { const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { - dim: "#3f3f46", - muted: "#52525b", - active: "#60a5fa", - success: "#34d399", - code: "#d4d4d8", - }; + const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8" }; const steps = [ - { delay: 400, left: [{ t: "> npm install @buildersgarden/siwa", c: "active" }], right: [ - { t: "── ERC-8004 Registry ───────────────────", c: "dim" }, - { t: "0x8004A169FB4...9f432", c: "muted" }, + { delay: 400, lines: [{ t: "> Show my last 5 transactions on Base", c: "active" }] }, + { delay: 500, lines: [ + { t: " ── get_transaction_history ────────────────", c: "dim" }, + { t: " chain: base limit: 5", c: "muted" }, ]}, - { delay: 700, left: [{ t: " ✓ @buildersgarden/siwa installed", c: "success" }], right: [] }, - { delay: 500, left: [{ t: "> Register agent identity onchain...", c: "active" }], right: [] }, - { delay: 800, left: [{ t: " signing registration tx...", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: "── Registering ─────────────────────────", c: "dim" }, - { t: " name: my-trading-agent", c: "code" }, - { t: " endpoint: https://agent.example.com", c: "code" }, - { t: " pubKey: 0x04c2...f9a1", c: "code" }, + { delay: 700, lines: [ + { t: " send -10.00 USDC alice.base.eth 2min ago", c: "code" }, + { t: " swap -100.00 USDC +0.0351 ETH 1hr ago ", c: "code" }, + { t: " recv +50.00 USDC coinbase.com 3hr ago ", c: "success" }, + { t: " send -5.00 USDC bob.eth 1d ago ", c: "code" }, + { t: " recv +100.00 USDC 0x9f3a...2e01 2d ago ", c: "success" }, ]}, - { delay: 900, left: [{ t: " ✓ tx confirmed · token ID: 4219", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── Registry entry ──────────────────────", c: "dim" }, - { t: " tokenId: 4219", c: "success" }, - { t: " owner: 0x4a3f...b7c1", c: "success" }, - { t: " block: 28,419,042", c: "muted" }, + { delay: 500, lines: [{ t: "", c: "dim" }, { t: "> What's my current balance?", c: "active" }] }, + { delay: 500, lines: [ + { t: " ── get_portfolio ──────────────────────────", c: "dim" }, ]}, - { delay: 600, left: [{ t: "> Claim Basename: myagent.base.eth", c: "active" }], right: [] }, - { delay: 700, left: [{ t: " ✓ myagent.base.eth registered", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── Basename ────────────────────────────", c: "dim" }, - { t: " name: myagent.base.eth", c: "success" }, - { t: " address: 0x4a3f...b7c1", c: "success" }, + { delay: 650, lines: [ + { t: " USDC 280.80 $280.80", c: "success" }, + { t: " ETH 0.0763 $274.33", c: "success" }, + { t: " DEGEN 4820.00 $182.33", c: "success" }, + { t: " Total: $737.46 on Base", c: "success" }, ]}, ]; - const [leftLines, setLeftLines] = useState([]); - const [rightLines, setRightLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const leftRef = useRef(null); - const rightRef = useRef(null); - - useEffect(() => { - const t = setInterval(() => setBlink(b => !b), 530); - return () => clearInterval(t); - }, []); + const [lines, setLines] = useState([]); + const [running, setRunning] = useState(false); + const [done, setDone] = useState(false); + const [blink, setBlink] = useState(true); + const ref = useRef(null); - useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); + useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); + useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [lines]); - const play = () => { - setLeftLines([]); - setRightLines([]); + const reset = () => { setLines([]); setRunning(false); setDone(false); }; + const run = () => { + if (running || done) return; setRunning(true); - setDone(false); let i = 0; const next = () => { if (i >= steps.length) { setRunning(false); setDone(true); return; } - const s = steps[i]; - setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); - if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; - next(); - }, s.delay); + setTimeout(() => { setLines(p => [...p, ...steps[i].lines]); i++; next(); }, steps[i].delay); }; next(); }; - useEffect(() => { setTimeout(play, 350); }, []); // eslint-disable-line react-hooks/exhaustive-deps - const renderLine = (item, i) => { - if (!item.t) return
; - return ( -
{item.t}
- ); + if (!item.t) return
; + return
{item.t}
; }; return ( @@ -89,34 +61,22 @@ export const AgentRegistrationDemo = () => {
{">"}_
- Agent Registration + Transaction History
- + onMouseLeave={e => { e.currentTarget.style.color = "#3f3f46"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "transparent"; }}>{"↺"}
- -
-
- Agent -
-
- {leftLines.map(renderLine)} +
+
Terminal
+
+ {lines.map(renderLine)} {running &&
{"▋"}
}
-
- {done && ( - - )} + {!running && !done && } + {done && }
); diff --git a/docs/snippets/DataFetchingDemo.jsx b/docs/snippets/DataFetchingDemo.jsx index 36355f730..3853403fd 100644 --- a/docs/snippets/DataFetchingDemo.jsx +++ b/docs/snippets/DataFetchingDemo.jsx @@ -2,92 +2,86 @@ import { useState, useEffect, useRef } from "react"; export const DataFetchingDemo = () => { const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { - dim: "#3f3f46", - muted: "#52525b", - active: "#60a5fa", - success: "#34d399", - code: "#d4d4d8", - }; + const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8" }; - const steps = [ - { delay: 350, left: [{ t: "> Discover price feed service...", c: "active" }], right: [ - { t: "── Service Discovery ───────────────────", c: "dim" }, - { t: "GET /api/discover?query=price+feed", c: "code" }, - { t: "Host: api.wallet.paysponge.com", c: "muted" }, - ]}, - { delay: 700, left: [{ t: " ← found: api.coingecko.com · 0.001 USDC", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: '{"id":"coingecko-price",', c: "code" }, - { t: ' "baseUrl":"api.coingecko.com",', c: "code" }, - { t: ' "price":"0.001 USDC/req"}', c: "code" }, - ]}, - { delay: 500, left: [{ t: "> Fetch ETH price...", c: "active" }], right: [ - { t: "", c: "dim" }, - { t: "── API Request ─────────────────────────", c: "dim" }, - { t: "GET /api/v3/simple/price?ids=ethereum", c: "code" }, - ]}, - { delay: 600, left: [{ t: " ← 402 · paying 0.001 USDC...", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: "HTTP/1.1 402 Payment Required", c: "muted" }, - { t: "X-Payment-Sig: pending...", c: "muted" }, - ]}, - { delay: 700, left: [{ t: " ✓ payment sent · retrying...", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── API Response ────────────────────────", c: "dim" }, - { t: "HTTP/1.1 200 OK", c: "success" }, - ]}, - { delay: 500, left: [{ t: " ← 200 OK · data returned", c: "success" }], right: [ - { t: '{"ethereum":{', c: "code" }, - { t: ' "usd": 2847.32,', c: "code" }, - { t: ' "usd_24h_change": 2.31', c: "code" }, - { t: "} }", c: "code" }, - ]}, - { delay: 350, left: [{ t: " ETH $2,847.32 ↑ 2.3%", c: "code", bold: true }], right: [] }, - ]; + const flows = { + wallets: [ + { delay: 450, + left: [{ t: "> Show me my wallets", c: "active" }, { t: " ← get_wallets()", c: "muted" }], + right: [{ t: "── get_wallets ─────────────────────", c: "dim" }, { t: " (no params required)", c: "muted" }] }, + { delay: 700, + left: [{ t: " Base Account: 0x4a3f...b7c1 ✓", c: "success" }, { t: " Agent Wallet: 0x9c2d...e4f8 (not in session)", c: "muted" }], + right: [{ t: "", c: "dim" }, { t: ' { type: "base-account",', c: "code" }, { t: ' address: "0x4a3f...b7c1",', c: "code" }, { t: ' inSession: true }', c: "code" }] }, + { delay: 500, + left: [{ t: "", c: "dim" }, { t: " 2 wallets found", c: "success" }], + right: [{ t: "", c: "dim" }, { t: ' { type: "agent-wallet",', c: "code" }, { t: ' address: "0x9c2d...e4f8",', c: "code" }, { t: ' inSession: false }', c: "code" }] }, + ], + portfolio: [ + { delay: 450, + left: [{ t: "> What's my balance on Base?", c: "active" }, { t: " ← get_portfolio(chain=base)", c: "muted" }], + right: [{ t: "── get_portfolio ────────────────────", c: "dim" }, { t: " chain: base", c: "muted" }] }, + { delay: 700, + left: [{ t: " USDC 245.80 $245.80", c: "success" }, { t: " ETH 0.0412 $148.33", c: "success" }], + right: [{ t: "", c: "dim" }, { t: " totalValue: $430.15", c: "success" }, { t: " assetCount: 3", c: "code" }] }, + { delay: 500, + left: [{ t: " WETH 0.0100 $36.02", c: "success" }, { t: " Total: $430.15 on Base ✓", c: "success" }], + right: [{ t: "", c: "dim" }, { t: ' { symbol: "WETH",', c: "code" }, { t: ' balance: "0.0100",', c: "code" }, { t: ' usdValue: "$36.02" }', c: "code" }] }, + ], + history: [ + { delay: 450, + left: [{ t: "> Show my recent USDC sends", c: "active" }, { t: " ← get_transaction_history(asset=USDC, limit=4)", c: "muted" }], + right: [{ t: "── get_transaction_history ─────────", c: "dim" }, { t: " asset: USDC limit: 4", c: "muted" }] }, + { delay: 700, + left: [{ t: " send -10.00 USDC alice.base.eth", c: "code" }, { t: " recv +50.00 USDC coinbase.com ", c: "success" }], + right: [{ t: "", c: "dim" }, { t: " hasMore: true", c: "muted" }, { t: ' nextCursor: "cur_abc..."', c: "muted" }] }, + { delay: 500, + left: [{ t: " send -5.00 USDC bob.eth ", c: "code" }, { t: " recv +100.00 USDC 0x9f3a...2e01 ", c: "success" }], + right: [{ t: "", c: "dim" }, { t: " 4 USDC transactions returned", c: "success" }, { t: " More pages available", c: "muted" }] }, + ], + }; - const [leftLines, setLeftLines] = useState([]); - const [rightLines, setRightLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); + const [choice, setChoice] = useState(null); + const [leftLines, setLeft] = useState([{ t: "> Try a read tool:", c: "muted" }]); + const [rightLines, setRight]= useState([]); + const [running, setRunning] = useState(false); + const [done, setDone] = useState(false); + const [blink, setBlink] = useState(true); const leftRef = useRef(null); const rightRef = useRef(null); - useEffect(() => { - const t = setInterval(() => setBlink(b => !b), 530); - return () => clearInterval(t); - }, []); - + useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); + useEffect(() => { if (rightRef.current) rightRef.current.scrollTop = rightRef.current.scrollHeight; }, [rightLines]); + + const reset = () => { setChoice(null); setLeft([{ t: "> Try a read tool:", c: "muted" }]); setRight([]); setRunning(false); setDone(false); }; - const play = () => { - setLeftLines([]); - setRightLines([]); + const pick = (key) => { + if (choice) return; + const labels = { wallets: "get_wallets", portfolio: "get_portfolio", history: "get_transaction_history" }; + setChoice(key); + setLeft(p => [...p, { t: " [" + labels[key] + "]", c: "active" }]); + const steps = flows[key]; setRunning(true); - setDone(false); let i = 0; const next = () => { if (i >= steps.length) { setRunning(false); setDone(true); return; } const s = steps[i]; setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); - if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; - next(); + if (s.left) setLeft(p => [...p, ...s.left]); + if (s.right) setRight(p => [...p, ...s.right]); + i++; next(); }, s.delay); }; - next(); + setTimeout(next, 200); }; - useEffect(() => { setTimeout(play, 350); }, []); // eslint-disable-line react-hooks/exhaustive-deps - const renderLine = (item, i) => { - if (!item.t) return
; - return ( -
{item.t}
- ); + if (!item.t) return
; + return
{item.t}
; }; + const btnBase = { fontFamily: mono, fontSize: 12, color: "#60a5fa", background: "transparent", border: "1px solid #27272a", borderRadius: 4, cursor: "pointer", padding: "2px 8px", marginRight: 6, lineHeight: "20px" }; + const onEnter = (e) => { e.currentTarget.style.color = "#e4e4e7"; e.currentTarget.style.background = "#1c1c1e"; e.currentTarget.style.borderColor = "#3f3f46"; }; + const onLeave = (e) => { e.currentTarget.style.color = "#60a5fa"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "#27272a"; }; return (
@@ -95,34 +89,34 @@ export const DataFetchingDemo = () => {
{">"}_
- Data Fetching + Read Tools
- + onMouseLeave={e => { e.currentTarget.style.color = "#3f3f46"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "transparent"; }}>{"↺"}
- -
-
- Agent +
+
+
Agent
+
+ {leftLines.map(renderLine)} + {!choice && ( +
+ + + +
+ )} + {running &&
{"▋"}
} +
-
- {leftLines.map(renderLine)} - {running &&
{"▋"}
} +
+
MCP Response
+
{rightLines.map(renderLine)}
-
- {done && ( - - )} + {done && }
); diff --git a/docs/snippets/PaymentsQuickstartDemo.jsx b/docs/snippets/PaymentsQuickstartDemo.jsx index 0b9050d56..05a33e902 100644 --- a/docs/snippets/PaymentsQuickstartDemo.jsx +++ b/docs/snippets/PaymentsQuickstartDemo.jsx @@ -1,5 +1,6 @@ import { useState, useEffect, useRef } from "react"; +// CDP x402 payments demo — used in payments.mdx export const PaymentsQuickstartDemo = () => { const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; const col = { @@ -12,44 +13,40 @@ export const PaymentsQuickstartDemo = () => { const steps = [ { delay: 350, left: [{ t: "> npx skills add coinbase/agentic-wallet-skills", c: "active" }], right: [ - { t: "── Installing skills ───────────────────", c: "dim" }, + { t: "── Installing CDP skills ───────────────", c: "dim" }, { t: "authenticate-wallet", c: "muted" }, { t: "pay-for-service", c: "muted" }, - { t: "monetize-service", c: "muted" }, - ]}, - { delay: 700, left: [{ t: " ✓ skills installed", c: "success" }], right: [ { t: "search-for-service", c: "muted" }, - { t: "send-usdc trade", c: "muted" }, + { t: "monetize-service", c: "muted" }, ]}, + { delay: 700, left: [{ t: " ✓ CDP Agentic Wallet skills installed", c: "success" }], right: [] }, { delay: 500, left: [{ t: "> Sign in with you@email.com", c: "active" }], right: [] }, - { delay: 650, left: [{ t: " ✓ wallet authenticated 0x4a3f...b7c1", c: "success" }], right: [ + { delay: 650, left: [{ t: " ✓ CDP wallet authenticated 0x4a3f...b7c1", c: "success" }], right: [ { t: "", c: "dim" }, - { t: "── Wallet ready ────────────────────────", c: "dim" }, + { t: "── wallet ready ────────────────────────", c: "dim" }, { t: " address: 0x4a3f...b7c1", c: "success" }, { t: " balance: 10.00 USDC", c: "success" }, ]}, - { delay: 500, left: [{ t: "> Find and fetch ETH price from a paid source", c: "active" }], right: [ + { delay: 500, left: [{ t: "> Find a weather API and get the NYC forecast", c: "active" }], right: [ { t: "", c: "dim" }, - { t: "── HTTP Trace ──────────────────────────", c: "dim" }, - { t: "GET /api/v3/simple/price?ids=ethereum", c: "code" }, - { t: "Host: api.coingecko.com", c: "muted" }, + { t: "── search-for-service ──────────────────", c: "dim" }, + { t: 'query: "weather forecast"', c: "code" }, ]}, - { delay: 700, left: [{ t: " ← 402 Payment Required · 0.001 USDC", c: "muted" }], right: [ + { delay: 700, left: [{ t: " ← found: weather.x402.io · 0.001 USDC/req", c: "muted" }], right: [ { t: "", c: "dim" }, - { t: "HTTP/1.1 402 Payment Required", c: "muted" }, - { t: 'X-Payment-Required: {"amount":"0.001"}', c: "code" }, + { t: "── pay-for-service ─────────────────────", c: "dim" }, + { t: "GET /v1/forecast?city=NYC", c: "code" }, + { t: "← HTTP 402 Payment Required", c: "muted" }, ]}, - { delay: 550, left: [{ t: " paying 0.001 USDC via wallet...", c: "muted" }], right: [] }, - { delay: 600, left: [{ t: " ✓ tx confirmed", c: "success" }], right: [ + { delay: 550, left: [{ t: " paying 0.001 USDC...", c: "muted" }], right: [ { t: "", c: "dim" }, - { t: "── Retry with payment ──────────────────", c: "dim" }, - { t: "GET /api/v3/simple/price?ids=ethereum", c: "code" }, - { t: "X-Payment-Sig: 0x1a9f...c4e2", c: "success" }, + { t: " Paying 0.001 USDC · signing...", c: "muted" }, + { t: " Retrying with X-Payment-Sig", c: "muted" }, ]}, - { delay: 600, left: [{ t: " ← 200 OK · ETH $2,847.32 ↑ 2.3%", c: "success", bold: true }], right: [ + { delay: 600, left: [{ t: " ← 200 OK · forecast received", c: "success", bold: true }], right: [ { t: "", c: "dim" }, { t: "HTTP/1.1 200 OK", c: "success" }, - { t: '{"ethereum":{"usd":2847.32}}', c: "code" }, + { t: '{"city":"NYC","temp":"68°F",...}', c: "code" }, ]}, ]; @@ -67,6 +64,7 @@ export const PaymentsQuickstartDemo = () => { }, []); useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); + useEffect(() => { if (rightRef.current) rightRef.current.scrollTop = rightRef.current.scrollHeight; }, [rightLines]); const play = () => { setLeftLines([]); @@ -102,22 +100,32 @@ export const PaymentsQuickstartDemo = () => {
{">"}_
- Payments Quickstart + x402 via CDP Agentic Wallet
-
-
- Agent +
+
+
+ Agent +
+
+ {leftLines.map(renderLine)} + {running &&
{"▋"}
} +
-
- {leftLines.map(renderLine)} - {running &&
{"▋"}
} +
+
+ HTTP Trace +
+
+ {rightLines.map(renderLine)} +
@@ -127,7 +135,7 @@ export const PaymentsQuickstartDemo = () => { style={{ fontFamily: mono, fontSize: 11, color: "#52525b", background: "none", border: "none", cursor: "pointer", padding: "4px 10px", borderRadius: 4 }} onMouseEnter={e => { e.currentTarget.style.color = "#a1a1aa"; e.currentTarget.style.background = "#18181b"; }} onMouseLeave={e => { e.currentTarget.style.color = "#52525b"; e.currentTarget.style.background = "none"; }}> - {"\u21ba"} Play again + {"↺"} Play again )}
diff --git a/docs/snippets/TradeExecutionDemo.jsx b/docs/snippets/TradeExecutionDemo.jsx index 959b3898e..6fbc00fe8 100644 --- a/docs/snippets/TradeExecutionDemo.jsx +++ b/docs/snippets/TradeExecutionDemo.jsx @@ -2,97 +2,54 @@ import { useState, useEffect, useRef } from "react"; export const TradeExecutionDemo = () => { const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { - dim: "#3f3f46", - muted: "#52525b", - active: "#60a5fa", - success: "#34d399", - code: "#d4d4d8", - }; + const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8", warn: "#fb923c" }; const steps = [ - { delay: 350, left: [{ t: "> Connect to mainnet-preconf.base.org...", c: "active" }], right: [ - { t: "── Flashblocks State ───────────────────", c: "dim" }, - { t: "eth_getBlockByNumber(\"pending\")", c: "code" }, - { t: "Host: mainnet-preconf.base.org", c: "muted" }, - ]}, - { delay: 650, left: [{ t: " ✓ preconf endpoint connected (200ms)", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: '{"pending": {', c: "code" }, - { t: ' "number": "0x1B2A4F2",', c: "code" }, - { t: ' "baseFeePerGas": "0x2386F26FC10"', c: "code" }, - { t: "} }", c: "code" }, + { delay: 400, lines: [{ t: "> Send 50 DEGEN to alice.base.eth", c: "active" }] }, + { delay: 500, lines: [ + { t: " ── search_tokens ──────────────────────────", c: "dim" }, + { t: ' query: "DEGEN" chain: base', c: "muted" }, ]}, - { delay: 500, left: [{ t: "> Simulate buying $50 ETH (preconf state)...", c: "active" }], right: [ - { t: "", c: "dim" }, - { t: "── eth_simulateV1 ──────────────────────", c: "dim" }, - { t: "blockStateCalls: [pending]", c: "muted" }, + { delay: 650, lines: [ + { t: ' ← name: "Degen" symbol: "DEGEN"', c: "code" }, + { t: ' address: "0x4ed4...9fa2" decimals: 18', c: "code" }, ]}, - { delay: 700, left: [{ t: " ✓ simulation passed · no revert", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: '{"results":[{"status":"0x1",', c: "code" }, - { t: ' "gasUsed":"0x14c08"}]}', c: "code" }, + { delay: 500, lines: [{ t: "", c: "dim" }, { t: "> send(alice.base.eth, 50 DEGEN, 0x4ed4..., 18)", c: "active" }] }, + { delay: 500, lines: [ + { t: " ── approval required ──────────────────────", c: "warn" }, + { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, ]}, - { delay: 450, left: [{ t: "> Get swap quote · price impact check...", c: "active" }], right: [ - { t: "", c: "dim" }, - { t: "── Quote Details ───────────────────────", c: "dim" }, - { t: '{"fromAmount":"50.00 USDC",', c: "code" }, - { t: ' "toAmount":"0.01756 ETH",', c: "code" }, - { t: ' "priceImpact":"0.12%"}', c: "code" }, + { delay: 500, lines: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }] }, + { delay: 1000, lines: [ + { t: ' ← status: "confirmed"', c: "success" }, + { t: " ✓ 50 DEGEN sent to alice.base.eth", c: "success" }, ]}, - { delay: 500, left: [{ t: " impact 0.12% < 1% — executing...", c: "muted" }], right: [] }, - { delay: 750, left: [{ t: " ✓ tx 0xb4f2...91ca confirmed (1 Flashblock)", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── base_transactionStatus ──────────────", c: "dim" }, - { t: " status: preconfirmed", c: "success" }, - { t: " hash: 0xb4f2...91ca", c: "success" }, - { t: " block: 28,419,042", c: "muted" }, - { t: " latency: ~200ms", c: "muted" }, - ]}, - { delay: 350, left: [{ t: " ✓ received 0.01756 ETH", c: "success", bold: true }], right: [] }, ]; - const [leftLines, setLeftLines] = useState([]); - const [rightLines, setRightLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const leftRef = useRef(null); - const rightRef = useRef(null); - - useEffect(() => { - const t = setInterval(() => setBlink(b => !b), 530); - return () => clearInterval(t); - }, []); + const [lines, setLines] = useState([]); + const [running, setRunning] = useState(false); + const [done, setDone] = useState(false); + const [blink, setBlink] = useState(true); + const ref = useRef(null); - useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); + useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); + useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [lines]); - const play = () => { - setLeftLines([]); - setRightLines([]); + const reset = () => { setLines([]); setRunning(false); setDone(false); }; + const run = () => { + if (running || done) return; setRunning(true); - setDone(false); let i = 0; const next = () => { if (i >= steps.length) { setRunning(false); setDone(true); return; } - const s = steps[i]; - setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); - if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; - next(); - }, s.delay); + setTimeout(() => { setLines(p => [...p, ...steps[i].lines]); i++; next(); }, steps[i].delay); }; next(); }; - useEffect(() => { setTimeout(play, 350); }, []); // eslint-disable-line react-hooks/exhaustive-deps - const renderLine = (item, i) => { - if (!item.t) return
; - return ( -
{item.t}
- ); + if (!item.t) return
; + return
{item.t}
; }; return ( @@ -101,34 +58,22 @@ export const TradeExecutionDemo = () => {
{">"}_
- Trade Execution + Token Search + Send
- + onMouseLeave={e => { e.currentTarget.style.color = "#3f3f46"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "transparent"; }}>{"↺"}
- -
-
- Agent -
-
- {leftLines.map(renderLine)} +
+
Terminal
+
+ {lines.map(renderLine)} {running &&
{"▋"}
}
-
- {done && ( - - )} + {!running && !done && } + {done && }
); diff --git a/docs/snippets/TradingQuickstartDemo.jsx b/docs/snippets/TradingQuickstartDemo.jsx index 2fe9f3744..3e8cd48e1 100644 --- a/docs/snippets/TradingQuickstartDemo.jsx +++ b/docs/snippets/TradingQuickstartDemo.jsx @@ -2,90 +2,57 @@ import { useState, useEffect, useRef } from "react"; export const TradingQuickstartDemo = () => { const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { - dim: "#3f3f46", - muted: "#52525b", - active: "#60a5fa", - success: "#34d399", - code: "#d4d4d8", - }; + const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8", warn: "#fb923c" }; const steps = [ - { delay: 350, left: [{ t: "> install bankr skill from github.com/BankrBot/skills", c: "active" }], right: [ - { t: "── Bankr Wallet ────────────────────────", c: "dim" }, - { t: "GET /releases/latest", c: "muted" }, - ]}, - { delay: 700, left: [{ t: " ✓ Bankr skill installed", c: "success" }], right: [ - { t: " tag: bankr-wallet-v2.1.0", c: "success" }, - { t: " chains: base, eth, solana", c: "muted" }, - { t: " gas: sponsored", c: "muted" }, + { delay: 400, lines: [{ t: "> Swap 100 USDC for ETH on Base", c: "active" }] }, + { delay: 500, lines: [ + { t: " ── swap() ─────────────────────────────", c: "dim" }, + { t: " fromAsset: USDC toAsset: ETH amount: 100", c: "muted" }, ]}, - { delay: 500, left: [{ t: " ✓ Bankr wallet connected wlt_bankr_...", c: "success" }], right: [] }, - { delay: 500, left: [{ t: "> Buy $50 of ETH on Base", c: "active" }], right: [ - { t: "", c: "dim" }, - { t: "── Swap Quote ──────────────────────────", c: "dim" }, - { t: "POST /v1/swap/quote", c: "code" }, - { t: "Host: api.bankr.bot", c: "muted" }, + { delay: 700, lines: [ + { t: " ← quote ready", c: "muted" }, + { t: " 0.03512 ETH · price impact 0.09%", c: "code" }, ]}, - { delay: 700, left: [{ t: " fetching quote...", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: '{"fromAmount":"50.00 USDC",', c: "code" }, - { t: ' "toAmount":"0.01756 ETH",', c: "code" }, - { t: ' "priceImpact":"0.12%"}', c: "code" }, + { delay: 500, lines: [{ t: "", c: "dim" }, { t: " ── approval required ──────────────────────", c: "warn" }] }, + { delay: 400, lines: [ + { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, + { t: ' requestId: "req_swap01"', c: "muted" }, ]}, - { delay: 500, left: [{ t: " ← 0.01756 ETH · price impact 0.12%", c: "muted" }], right: [] }, - { delay: 500, left: [{ t: " impact below 1% — executing...", c: "muted" }], right: [] }, - { delay: 750, left: [{ t: " ✓ tx 0xb4f2...91ca confirmed", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── Transaction ─────────────────────────", c: "dim" }, - { t: " hash: 0xb4f2...91ca", c: "success" }, - { t: " status: confirmed", c: "success" }, - { t: " block: 28,419,042", c: "muted" }, + { delay: 500, lines: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }] }, + { delay: 1000, lines: [{ t: " ← user approved ✓", c: "success" }] }, + { delay: 500, lines: [ + { t: " ── get_request_status ─────────────────────", c: "dim" }, + { t: ' status: "confirmed" received: "0.03512 ETH"', c: "success" }, ]}, - { delay: 400, left: [{ t: " ✓ received 0.01756 ETH", c: "success", bold: true }], right: [] }, + { delay: 400, lines: [{ t: "", c: "dim" }, { t: " ✓ 0.03512 ETH received", c: "success" }] }, ]; - const [leftLines, setLeftLines] = useState([]); - const [rightLines, setRightLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const leftRef = useRef(null); - const rightRef = useRef(null); - - useEffect(() => { - const t = setInterval(() => setBlink(b => !b), 530); - return () => clearInterval(t); - }, []); + const [lines, setLines] = useState([]); + const [running, setRunning] = useState(false); + const [done, setDone] = useState(false); + const [blink, setBlink] = useState(true); + const ref = useRef(null); - useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); + useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); + useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [lines]); - const play = () => { - setLeftLines([]); - setRightLines([]); + const reset = () => { setLines([]); setRunning(false); setDone(false); }; + const run = () => { + if (running || done) return; setRunning(true); - setDone(false); let i = 0; const next = () => { if (i >= steps.length) { setRunning(false); setDone(true); return; } const s = steps[i]; - setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); - if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; - next(); - }, s.delay); + setTimeout(() => { setLines(p => [...p, ...s.lines]); i++; next(); }, s.delay); }; next(); }; - useEffect(() => { setTimeout(play, 350); }, []); // eslint-disable-line react-hooks/exhaustive-deps - const renderLine = (item, i) => { - if (!item.t) return
; - return ( -
{item.t}
- ); + if (!item.t) return
; + return
{item.t}
; }; return ( @@ -94,34 +61,26 @@ export const TradingQuickstartDemo = () => {
{">"}_
- Trading Quickstart + Swap Tokens
- + onMouseLeave={e => { e.currentTarget.style.color = "#3f3f46"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "transparent"; }}>{"↺"}
- -
+
- Agent + Terminal
-
- {leftLines.map(renderLine)} +
+ {lines.map(renderLine)} {running &&
{"▋"}
}
-
- {done && ( - - )} + {!running && !done && } + {done && }
); diff --git a/docs/snippets/WalletSetupDemo.jsx b/docs/snippets/WalletSetupDemo.jsx index 752e5098b..946101314 100644 --- a/docs/snippets/WalletSetupDemo.jsx +++ b/docs/snippets/WalletSetupDemo.jsx @@ -1,196 +1,399 @@ import { useState, useEffect, useRef } from "react"; export const WalletSetupDemo = () => { - const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { - dim: "#3f3f46", - muted: "#52525b", - active: "#60a5fa", - success: "#34d399", - code: "#d4d4d8", - }; + const sans = "ui-sans-serif,system-ui,-apple-system,'Segoe UI',Roboto,sans-serif"; + const serif = "'Tiempos Headline','Iowan Old Style','Source Serif Pro',ui-serif,Georgia,serif"; + const mono = "ui-monospace,'SF Mono','Cascadia Code',Menlo,Monaco,Consolas,monospace"; - const flows = { - cdp: [ - { delay: 400, left: [{ t: "> npx skills add coinbase/agentic-wallet-skills", c: "active" }], right: [ - { t: "── wallet.config.json ──────────────────", c: "dim" }, - { t: "{", c: "code" }, - ]}, - { delay: 600, left: [{ t: " ✓ skill installed", c: "success" }], right: [ - { t: ' "provider": "coinbase",', c: "code" }, - { t: ' "network": "base",', c: "code" }, - { t: ' "skills": ["agentic-wallet"]', c: "code" }, - { t: "}", c: "code" }, - ]}, - { delay: 500, left: [{ t: "> Sign in to my wallet with you@email.com", c: "active" }], right: [] }, - { delay: 700, left: [{ t: " ← OTP sent · checking...", c: "muted" }], right: [] }, - { delay: 650, left: [{ t: " ✓ CDP wallet connected 0x4a3f...b7c1", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: " address: 0x4a3f...b7c1", c: "success" }, - { t: " network: base-mainnet", c: "success" }, - { t: " status: ready", c: "success" }, - ]}, - ], - sponge: [ - { delay: 400, left: [{ t: "> curl -X POST https://api.wallet.paysponge.com/...", c: "active" }], right: [ - { t: "── POST /api/agents/register ───────────", c: "dim" }, - { t: "Host: api.wallet.paysponge.com", c: "muted" }, - { t: "Content-Type: application/json", c: "muted" }, - ]}, - { delay: 750, left: [{ t: ' ← {"apiKey": "sponge_live_..."}', c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: "── 200 OK ──────────────────────────────", c: "dim" }, - { t: "{", c: "code" }, - { t: ' "apiKey": "sponge_live_abc...xyz",', c: "code" }, - { t: ' "walletId": "wlt_a1b2c3d4"', c: "code" }, - { t: "}", c: "code" }, - ]}, - { delay: 450, left: [{ t: "> export SPONGE_API_KEY=sponge_live_...", c: "active" }], right: [] }, - { delay: 400, left: [{ t: " ✓ Sponge wallet ready", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: " chains: base, ethereum, solana", c: "success" }, - { t: " x402: enabled", c: "success" }, - ]}, - ], - bankr: [ - { delay: 400, left: [{ t: "> install bankr skill from github.com/BankrBot/skills", c: "active" }], right: [ - { t: "── github.com/BankrBot/skills ──────────", c: "dim" }, - { t: "GET /releases/latest", c: "muted" }, - ]}, - { delay: 700, left: [{ t: " ✓ Bankr skill installed", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: " tag: bankr-wallet-v2.1.0", c: "success" }, - { t: " size: 142 KB", c: "muted" }, - ]}, - { delay: 500, left: [{ t: " ✓ Bankr wallet connected wlt_bankr_...", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: " chains: base, eth, solana, polygon", c: "success" }, - { t: " gas: sponsored", c: "success" }, - { t: " swaps: built-in", c: "success" }, - ]}, - ], + const c = { + bg: "#1f1e1d", + header: "#262624", + border: "#34322f", + inputBg: "#2a2926", + text: "#f5f4ed", + body: "#e8e4dc", + muted: "#a8a39d", + dim: "#6b6663", + accent: "#D97757", + bubble: "#2c2b28", + bubbleText: "#f5f4ed", + code: "#e89972", + codeBg: "rgba(217,119,87,0.12)", + toolBg: "#272622", + toolBorder: "#3a3835", + success: "#a3c585", }; - const [choice, setChoice] = useState(null); - const [leftLines, setLeftLines] = useState([]); - const [rightLines, setRightLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const leftRef = useRef(null); - const rightRef = useRef(null); - - useEffect(() => { - const t = setInterval(() => setBlink(b => !b), 530); - return () => clearInterval(t); - }, []); - - useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); - - const reset = () => { - setChoice(null); - setLeftLines([{ t: "> Choose a wallet provider:", c: "muted" }]); - setRightLines([]); - setRunning(false); - setDone(false); - }; + // Each example is a sequence of events. Each event reveals one block. + // Block types: thinking, tool, text, rows, approval, confirm + // (thinking auto-hides once the next event renders) + const examples = [ + { + prompt: "Send 5 USDC to vitalik.base.eth", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "base-account", action: "send", args: { to: "vitalik.base.eth", asset: "USDC", amount: "5" } } }, + { delay: 550, type: "text", text: "Resolved vitalik.base.eth → 0xd8dA…6045. Approve to send:" }, + { delay: 250, type: "approval", url: "keys.coinbase.com/approve/req_a4f7c2" }, + { delay: 1100, type: "confirm", text: "Sent 5 USDC to vitalik.base.eth" }, + ], + }, + { + prompt: "Swap 0.05 ETH to USDC on Base — best rate", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "aerodrome", action: "get_quote", args: { from: "0.05 ETH", to: "USDC" } } }, + { delay: 700, type: "tool", tool: { server: "uniswap-v3", action: "get_quote", args: { from: "0.05 ETH", to: "USDC" } } }, + { delay: 600, type: "text", text: "Routed across two Base DEXes — Uniswap v3 has the better fill:" }, + { delay: 250, type: "rows", rows: [ + { token: "Aerodrome", amount: "178.92 USDC", value: "0.30% fee · slippage 0.18%" }, + { token: "Uniswap v3 (best)", amount: "179.41 USDC", value: "0.05% fee · slippage 0.12%" }, + ]}, + { delay: 700, type: "tool", tool: { server: "uniswap-v3", action: "prepare_swap", args: { route: "ETH→USDC", min_out: "179.20 USDC" } } }, + { delay: 450, type: "approval", url: "keys.coinbase.com/approve/req_8c2e4d" }, + { delay: 1100, type: "confirm", text: "Swapped 0.05 ETH → 179.41 USDC on Uniswap v3" }, + ], + }, + { + prompt: "Find the best USDC yield on Base and deposit 100", + events: [ + { delay: 380, type: "thinking" }, + { delay: 600, type: "tool", tool: { server: "morpho", action: "list_vaults", args: { asset: "USDC", chain: "base" } } }, + { delay: 700, type: "tool", tool: { server: "moonwell", action: "list_markets", args: { asset: "USDC", chain: "base" } } }, + { delay: 600, type: "text", text: "Compared Morpho vaults and Moonwell markets — top USDC yields on Base:" }, + { delay: 250, type: "rows", rows: [ + { token: "Morpho · Steakhouse USDC", amount: "8.42% APY", value: "$24.1M TVL · winner" }, + { token: "Morpho · Re7 USDC", amount: "7.91% APY", value: "$18.7M TVL" }, + { token: "Moonwell · USDC market", amount: "5.13% APY", value: "$41.2M supplied" }, + ]}, + { delay: 700, type: "tool", tool: { server: "morpho", action: "prepare_deposit", args: { vault: "Steakhouse USDC", amount: "100 USDC" } } }, + { delay: 450, type: "approval", url: "keys.coinbase.com/approve/req_b9f2a1" }, + { delay: 1100, type: "confirm", text: "Deposited 100 USDC into Steakhouse USDC · earning 8.42% APY" }, + ], + }, + ]; - useEffect(() => { reset(); }, []); // eslint-disable-line react-hooks/exhaustive-deps - - const animateFlow = (key) => { - const steps = flows[key]; - if (!steps) return; - setRunning(true); - setDone(false); - let i = 0; - const next = () => { - if (i >= steps.length) { setRunning(false); setDone(true); return; } - const s = steps[i]; - setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); - if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; - next(); - }, s.delay); - }; - next(); - }; + const [activeIdx, setActiveIdx] = useState(null); + const [eventIdx, setEventIdx] = useState(0); + const scrollRef = useRef(null); + const timersRef = useRef([]); + + const clearTimers = () => { timersRef.current.forEach(clearTimeout); timersRef.current = []; }; - const pick = (w) => { - if (choice) return; - setChoice(w); - const label = w === "cdp" ? "CDP" : w === "sponge" ? "Sponge" : "Bankr"; - setLeftLines(prev => [...prev, { t: " [" + label + "]", c: "active" }]); - setTimeout(() => animateFlow(w), 150); + useEffect(() => { if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight; }, [eventIdx, activeIdx]); + useEffect(() => () => clearTimers(), []); + + const pick = (idx) => { + if (activeIdx !== null) return; + setActiveIdx(idx); + setEventIdx(0); + clearTimers(); + let cumulative = 0; + examples[idx].events.forEach((e, i) => { + cumulative += e.delay; + timersRef.current.push(setTimeout(() => setEventIdx(i + 1), cumulative)); + }); }; - const renderLine = (item, i) => { - if (!item.t) return
; + const reset = () => { clearTimers(); setActiveIdx(null); setEventIdx(0); }; + + const ex = activeIdx !== null ? examples[activeIdx] : null; + + // ----- UI bits ----- + + const TrafficLights = () => ( +
+ + + +
+ ); + + const UserBubble = ({ children }) => ( +
+
{children}
+
+ ); + + const ToolCall = ({ tool, completed }) => ( +
+
+ + {completed ? ( + + ) : ( + + + + + )} + + + {tool.server} + · + {tool.action} + ( + {Object.entries(tool.args).map(([k, v], i, arr) => ( + + {k}: + "{v}" + {i < arr.length - 1 && , } + + ))} + ) + +
+
+ ); + + const Thinking = () => ( +
+ + {[0, 1, 2].map(i => ( + + ))} + + Thinking +
+ ); + + const ResponseText = ({ children, top }) => ( +
{children}
+ ); + + const ResponseRows = ({ rows }) => ( +
+ {rows.map((r, i) => ( +
+ + {r.token} + {r.amount} + {r.value} +
+ ))} +
+ ); + + const ApprovalLink = ({ url }) => ( +
+ + + + + + {url} + +
+ ); + + const Confirm = ({ text }) => ( +
+ + + + {text} +
+ ); + + const ChipBtn = ({ onClick, children }) => { + const [hover, setHover] = useState(false); return ( -
{item.t}
+ ); }; - const btnBase = { - fontFamily: mono, fontSize: 12, - color: "#60a5fa", background: "transparent", - border: "1px solid #27272a", borderRadius: 4, - cursor: "pointer", padding: "1px 8px", - marginRight: 6, lineHeight: "20px", + // Render the events shown so far for the active example + const renderEvents = () => { + if (!ex) return null; + const shown = ex.events.slice(0, eventIdx); + return shown.map((event, i) => { + // Hide thinking once any later event has appeared + if (event.type === "thinking") { + if (i < shown.length - 1) return null; + return ; + } + if (event.type === "tool") { + // Mark as completed once any later non-thinking event has appeared + const hasLater = shown.slice(i + 1).some(e => e.type !== "thinking"); + return ; + } + if (event.type === "text") return {event.text}; + if (event.type === "rows") return ; + if (event.type === "approval") return ; + if (event.type === "confirm") return ; + return null; + }); }; - const onEnter = (e) => { e.currentTarget.style.color = "#e4e4e7"; e.currentTarget.style.background = "#1c1c1e"; e.currentTarget.style.borderColor = "#3f3f46"; }; - const onLeave = (e) => { e.currentTarget.style.color = "#60a5fa"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "#27272a"; }; return ( -
- {/* Chrome bar */} -
-
- {">"}_ -
- Wallet Setup +
+ {/* keyframes + responsive */} + + + {/* Header */} +
+ + + Base wallet + +
- + {activeIdx !== null && ( + + )}
- {/* Terminal pane */} -
-
- Agent -
-
- {leftLines.map(renderLine)} - {!choice && leftLines.length > 0 && ( -
- pick: - - - + {/* Chat area */} +
+ {!ex && ( +
+
+ Try asking your assistant once mcp.base.org is connected:
- )} - {running &&
{"▋"}
} -
+
+ {examples.map((e, i) => ( + pick(i)}>{e.prompt} + ))} +
+
+ )} + + {ex && ( + <> + {ex.prompt} + {renderEvents()} + + )}
- {/* Footer */} -
- {done && ( - - )} + + Write a message... + + + Sonnet 4.6 + + + + + + +
+
+ Demo · Your assistant approves every transaction at keys.coinbase.com +
); diff --git a/docs/snippets/x402PayDemo.jsx b/docs/snippets/x402PayDemo.jsx index 7e5da9440..b7f7384e4 100644 --- a/docs/snippets/x402PayDemo.jsx +++ b/docs/snippets/x402PayDemo.jsx @@ -2,88 +2,56 @@ import { useState, useEffect, useRef } from "react"; export const X402PayDemo = () => { const mono = "ui-monospace,'Cascadia Code','Source Code Pro',Menlo,Monaco,Consolas,monospace"; - const col = { - dim: "#3f3f46", - muted: "#52525b", - active: "#60a5fa", - success: "#34d399", - code: "#d4d4d8", - }; + const col = { dim: "#3f3f46", muted: "#52525b", active: "#60a5fa", success: "#34d399", code: "#d4d4d8", warn: "#fb923c" }; const steps = [ - { delay: 350, left: [{ t: "> GET api.coingecko.com/api/v3/simple/price", c: "active" }], right: [ - { t: "── Request 1 ───────────────────────────", c: "dim" }, - { t: "GET /api/v3/simple/price?ids=ethereum", c: "code" }, - { t: "Host: api.coingecko.com", c: "muted" }, + { delay: 400, lines: [{ t: "> Send 5 USDC to bob.base.eth", c: "active" }] }, + { delay: 500, lines: [ + { t: " ── send() ─────────────────────────────────", c: "dim" }, + { t: " recipient: bob.base.eth amount: 5 asset: USDC", c: "muted" }, ]}, - { delay: 650, left: [{ t: " ← 402 Payment Required", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: "── Response 1 ──────────────────────────", c: "dim" }, - { t: "HTTP/1.1 402 Payment Required", c: "muted" }, - { t: "X-Payment-Required: {", c: "muted" }, - { t: ' "amount": "0.001",', c: "code" }, - { t: ' "asset": "USDC",', c: "code" }, - { t: ' "network": "base"', c: "code" }, - { t: "}", c: "muted" }, + { delay: 650, lines: [ + { t: " ── approval required ──────────────────────", c: "warn" }, + { t: ' approvalUrl: "keys.coinbase.com/..."', c: "warn" }, + { t: ' requestId: "req_abc123"', c: "muted" }, ]}, - { delay: 500, left: [{ t: " paying 0.001 USDC via wallet...", c: "muted" }], right: [] }, - { delay: 700, left: [{ t: " ✓ tx confirmed 0x1a9f...c4e2", c: "success" }], right: [] }, - { delay: 450, left: [{ t: " → retrying with payment signature", c: "muted" }], right: [ - { t: "", c: "dim" }, - { t: "── Request 2 ───────────────────────────", c: "dim" }, - { t: "GET /api/v3/simple/price?ids=ethereum", c: "code" }, - { t: "X-Payment-Sig: 0x1a9f...c4e2", c: "success" }, + { delay: 500, lines: [{ t: " Please approve: keys.coinbase.com/…", c: "warn" }] }, + { delay: 1100, lines: [{ t: " ← user opened and approved ✓", c: "success" }] }, + { delay: 500, lines: [ + { t: " ── get_request_status ─────────────────────", c: "dim" }, + { t: ' requestId: "req_abc123"', c: "muted" }, ]}, - { delay: 600, left: [{ t: " ← 200 OK", c: "success" }], right: [ - { t: "", c: "dim" }, - { t: "── Response 2 ──────────────────────────", c: "dim" }, - { t: "HTTP/1.1 200 OK", c: "success" }, - { t: '{"ethereum":{"usd":2847.32}}', c: "code" }, + { delay: 500, lines: [ + { t: ' status: "confirmed"', c: "success" }, + { t: ' txHash: "0xf7e3...9a12"', c: "success" }, ]}, - { delay: 300, left: [{ t: " ETH $2,847.32 ↑ 2.3%", c: "code", bold: true }], right: [] }, + { delay: 300, lines: [{ t: "", c: "dim" }, { t: " ✓ 5 USDC sent to bob.base.eth", c: "success" }] }, ]; - const [leftLines, setLeftLines] = useState([]); - const [rightLines, setRightLines] = useState([]); - const [running, setRunning] = useState(false); - const [done, setDone] = useState(false); - const [blink, setBlink] = useState(true); - const leftRef = useRef(null); - const rightRef = useRef(null); - - useEffect(() => { - const t = setInterval(() => setBlink(b => !b), 530); - return () => clearInterval(t); - }, []); + const [lines, setLines] = useState([]); + const [running, setRunning] = useState(false); + const [done, setDone] = useState(false); + const [blink, setBlink] = useState(true); + const ref = useRef(null); - useEffect(() => { if (leftRef.current) leftRef.current.scrollTop = leftRef.current.scrollHeight; }, [leftLines]); + useEffect(() => { const t = setInterval(() => setBlink(b => !b), 530); return () => clearInterval(t); }, []); + useEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [lines]); - const play = () => { - setLeftLines([]); - setRightLines([]); + const reset = () => { setLines([]); setRunning(false); setDone(false); }; + const run = () => { + if (running || done) return; setRunning(true); - setDone(false); let i = 0; const next = () => { if (i >= steps.length) { setRunning(false); setDone(true); return; } - const s = steps[i]; - setTimeout(() => { - if (s.left && s.left.length) setLeftLines(prev => [...prev, ...s.left]); - if (s.right && s.right.length) setRightLines(prev => [...prev, ...s.right]); - i++; - next(); - }, s.delay); + setTimeout(() => { setLines(p => [...p, ...steps[i].lines]); i++; next(); }, steps[i].delay); }; next(); }; - useEffect(() => { setTimeout(play, 350); }, []); // eslint-disable-line react-hooks/exhaustive-deps - const renderLine = (item, i) => { - if (!item.t) return
; - return ( -
{item.t}
- ); + if (!item.t) return
; + return
{item.t}
; }; return ( @@ -92,34 +60,22 @@ export const X402PayDemo = () => {
{">"}_
- x402 Pay Flow + Approval Mode
- + onMouseLeave={e => { e.currentTarget.style.color = "#3f3f46"; e.currentTarget.style.background = "transparent"; e.currentTarget.style.borderColor = "transparent"; }}>{"↺"}
- -
-
- Agent -
-
- {leftLines.map(renderLine)} +
+
Terminal
+
+ {lines.map(renderLine)} {running &&
{"▋"}
}
-
- {done && ( - - )} + {!running && !done && } + {done && }
);