Go x402 payment protocol playground — TUI for learning, exploring & practicing EIP-3009/Permit2 flows
x402-playground is an early-stage Go project in the AI payments / x402 ecosystem. It currently has 0 GitHub stars and 0 forks.
HTTP-native micropayments for any EVM blockchain.
A production-grade Go implementation of the x402 payment protocol — four components including an interactive TUI explorer that demonstrate the full payment lifecycle with real on-chain USDC transfers.
Most x402 examples are minimal snippets. This project is a complete, working reference implementation with real money tested on Base Sepolia:
$EDITOR integration and auto-grading via go test / forge testClient CLI ──HTTP──> Resource Server ──HTTP──> Facilitator Server ──RPC──> EVM Chain
cmd/client cmd/resource cmd/facilitator
Explorer TUI (cmd/explorer) — Interactive learning & live execution tool
├── Learn — 17 coding quizzes (Go + Solidity), editor integration, auto-grading
├── Explore — Data structure inspector (headers, EIP-712, on-chain state)
├── Practice — Live 10-step payment flow with real HTTP/SDK calls
└── Dashboard — Wallet balances with animated loading (live from chain)
| Step | What happens |
|---|---|
| 1 | Client sends a normal HTTP request to a protected endpoint |
| 2 | Resource Server responds with HTTP 402 + PAYMENT-REQUIRED header |
| 3 | Client creates an EIP-712 signature (EIP-3009 or Permit2) and retries with PAYMENT-SIGNATURE |
| 4-5 | Resource Server delegates to Facilitator via /verify and /settle |
| 6 | Facilitator submits the tx on-chain, pays gas, returns tx hash |
| 7 | Client receives API response + PAYMENT-RESPONSE with settlement hash |
x402 Payment Flow
─────────────────
┌────────────┐ ┌──────────────────┐ ┌────────────────────┐
│ Client CLI │ 1. GET /api │ Resource Server │ │ Facilitator Server │
│ │ ──────────────>│ │ │ │
│ │ │ "No payment │ │ │
│ │ 2. HTTP 402 │ header found" │ │ │
│ │ <──────────────│ │ │ │
│ │ + PAYMENT- │ │ │ │
│ │ REQUIRED │ │ │ │
│ │ │ │ │ │
│ Signs │ │ │ │ │
│ EIP-3009 │ 3. GET /api │ │ 4. POST │ │
│ or │ ──────────────>│ Parses header, │ ──/verify────> │ Recovers signer, │
│ Permit2 │ + PAYMENT- │ forwards to │ │ checks balance, │
│ payload │ SIGNATURE │ facilitator │ 5. POST │ simulates call │ ┌───────────┐
│ │ │ │ ──/settle────> │ │ │ EVM Chain │
│ │ │ │ │ Builds EIP-1559 │ │ │
│ │ │ │ │ tx, settles via │──│ USDC │
│ │ │ │ 6. tx hash │ EIP-3009 or │ │ transfer │
│ │ 7. HTTP 200 │ Returns API data │ <─────────────│ Permit2 Proxy │ │ │
│ │ <──────────────│ + PAYMENT- │ │ │ │ │
│ │ + response │ RESPONSE │ │ │ └───────────┘
└────────────┘ └──────────────────┘ └────────────────────┘
Three wallets, three roles. PAY_TO_ADDRESS does not need a private key:
Client Wallet PAY_TO Address
(signs payment) (receives USDC)
│ ▲
│ 0.1 USDC │
│ (EIP-3009: transferWithAuth) │
│ (Permit2: via x402Permit2Proxy) │
└──────────────────────────────────────┘
│
Facilitator Wallet
(pays gas only, never touches USDC)
| Wallet | Private Key? | Role |
|---|---|---|
| Facilitator | Yes | Pays gas, submits payment tx on-chain |
| Client | Yes | Holds USDC, signs payment authorizations |
| PAY_TO | No | Receives USDC — any EVM address works |
git clone https://github.com/GrapeInTheTree/x402-playground.git
cd x402-playground
make build
cp .env.example .env
Edit .env with your values:
FACILITATOR_PRIVATE_KEY=0x... # Pays gas for on-chain settlement
CLIENT_PRIVATE_KEY=0x... # Holds USDC, signs authorizations
PAY_TO_ADDRESS=0x... # Receives USDC (no private key needed)
ASSET_TRANSFER_METHOD=eip3009 # or permit2
make run-explorer # Home menu — choose a mode
make run-learn # Learn mode — coding quiz (Go + Solidity)
make run-dashboard # Dashboard — live wallet balances
Learn mode opens your $EDITOR (nvim/vim/nano) with code templates. Write the solution, save, and the TUI auto-grades it via go test or forge test.
Press ? at any time for keyboard shortcuts.
Prerequisites for Solidity quizzes: Foundry (forge) must be installed.
# Terminal 1 — Facilitator (port 4022)
make run-facilitator
# Terminal 2 — Resource Server (port 4021)
make run-resource
# Terminal 3 — Practice flow (press n to execute each step)
make run-demo # EIP-3009 live flow
make run-demo-permit2 # Permit2 live flow
Practice mode executes real HTTP calls and x402 SDK operations — press n to run each step, watch the 3-panel view update with live results from the facilitator and resource servers.
make run-client
→ GET http://localhost:4021/weather
← 200 OK
💰 Payment Settlement:
Success: true
Transaction: 0x99e49093...faedc24
Network: eip155:84532
Response:
{
"city": "New York",
"temperature": 25,
"condition": "Windy"
}
Two methods, switchable via ASSET_TRANSFER_METHOD:
| EIP-3009 (default) | Permit2 | |
|---|---|---|
| On-chain call | USDC.transferWithAuthorization(...) |
x402Permit2Proxy.settle(...) |
| Token requirement | Must implement EIP-3009 | Any ERC-20 |
| Setup | None | Client must approve(Permit2) once |
| Gas cost | Lower (direct call) | Slightly higher (proxy hop) |
| EIP-712 domain | Token contract | Permit2 contract |
Permit2 contracts use CREATE2 — same address on all EVM chains:
| Contract | Address |
|---|---|
| Permit2 (Uniswap) | 0x000000000022D473030F116dDEE9F6B43aC78BA3 |
| x402Permit2Proxy (Coinbase) | 0x402085c248EeA27D92E8b30b2C58ed07f9E20001 |
| Chain | EIP-3009 | Permit2 | Status |
|---|---|---|---|
| Base Sepolia | Yes | Yes | Verified working |
| Base Mainnet | Yes | Yes | SDK built-in |
| Polygon | Yes | Yes | SDK built-in |
| Arbitrum | Yes | Yes | SDK built-in |
| Chiliz Mainnet | No | Unverified | Bridged USDC, no EIP-3009 |
| Chiliz Spicy | No | No | No USDC deployed |
To switch chains, change three env vars:
NETWORK=eip155:8453
RPC_URL=https://mainnet.base.org
USDC_ADDRESS=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
| Endpoint | Price | Description |
|---|---|---|
GET /weather |
$0.10 | Random city weather data |
GET /joke |
$0.10 | Programming jokes |
GET /premium-data |
$0.10 | Mock analytics report |
GET /health |
Free | Server health check |
make build # Compile all binaries (facilitator, resource, client, explorer)
make test # Run all 45 unit tests
make lint # Run golangci-lint
make clean # Remove compiled binaries
| Package | Tests | What's tested |
|---|---|---|
internal/config |
13 | Env loading, defaults, validation, Permit2 config, ExplorerConfig |
internal/demo |
11 | Header decoding, JSON formatting, accept item parsing, flow state |
internal/facilserver |
9 | Verify/settle/supported handlers with mock |
internal/server |
6 | API handlers, health, route structure |
internal/signer |
5 | Key parsing, address derivation, Close() zeroing |
| Total | 45 |
docker compose up --build # Facilitator + Resource
RESOURCE_URL=http://localhost:4021 make run-client # Client against Docker
docker compose down
POST /verifyValidates a payment payload off-chain. Checks signature, balance, timestamps, nonce.
// Request
{ "x402Version": 2, "paymentPayload": { ... }, "paymentRequirements": { ... } }
// Response
{ "isValid": true, "payer": "0x47322Ca2..." }
POST /settleExecutes payment on-chain. Auto-detects EIP-3009 vs Permit2 payload type.
{ "success": true, "transaction": "0x99e49093...", "network": "eip155:84532", "payer": "0x47322Ca2..." }
GET /supported{ "kinds": [{ "x402Version": 2, "scheme": "exact", "network": "eip155:84532" }], "signers": { "eip155:*": ["0x23fbdE5A..."] } }
GET /health{ "status": "ok", "service": "facilitator", "network": "eip155:84532", "address": "0x23fbdE5A..." }
| Header | Direction | Purpose |
|---|---|---|
PAYMENT-REQUIRED |
Server → Client | Base64-encoded payment requirements (in 402 response) |
PAYMENT-SIGNATURE |
Client → Server | Base64-encoded signed payment payload |
PAYMENT-RESPONSE |
Server → Client | Base64-encoded settlement result |
transferWithAuthorization(from, to, value, validAfter, validBefore, nonce, v, r, s)PermitWitnessTransferFrom (domain = Permit2 contract)x402Permit2Proxy.settle() → Permit2.permitWitnessTransferFrom()approve(Permit2, amount) from Client wallet| Variable | Used by | Default | Description |
|---|---|---|---|
FACILITATOR_PRIVATE_KEY |
facilitator | required | Wallet that pays gas for settlement |
CLIENT_PRIVATE_KEY |
client | required | Wallet that holds USDC and signs authorizations |
RPC_URL |
facilitator, client | https://sepolia.base.org |
JSON-RPC endpoint |
NETWORK |
all | eip155:84532 |
CAIP-2 network identifier |
USDC_ADDRESS |
resource, client | 0x036CbD53... |
Token contract address |
FACILITATOR_URL |
resource | required | Facilitator base URL |
PAY_TO_ADDRESS |
resource | required | Payment recipient (no private key needed) |
FACILITATOR_PORT |
facilitator | 4022 |
HTTP listen port |
RESOURCE_PORT |
resource | 4021 |
HTTP listen port |
RESOURCE_URL |
client | required | Resource Server base URL |
ENDPOINT_PATH |
client | /weather |
Default API endpoint |
ASSET_TRANSFER_METHOD |
all | eip3009 |
eip3009 or permit2 |
LOG_LEVEL |
all | info |
debug, info, warn, error |
x402-playground/
├── cmd/
│ ├── facilitator/main.go Facilitator HTTP server
│ ├── resource/main.go Resource HTTP server
│ ├── client/main.go Client CLI
│ ├── explorer/main.go Bubbletea TUI explorer (--mode, --flow flags)
│ └── balance/main.go Wallet balance checker
├── internal/
│ ├── config/ Environment variable loading + validation
│ ├── demo/ Protocol logic + LiveExecutor for real payment execution
│ ├── quiz/ Quiz engine: questions (Go + Solidity), runner (go test + forge test)
│ ├── facilserver/ Facilitator HTTP handlers (/verify, /settle, /supported)
│ ├── server/ Resource Server routes + API handlers
│ ├── signer/ FacilitatorEvmSigner (EIP-1559, EIP-712)
│ └── tui/ TUI framework
│ ├── app.go Root model + page routing + help overlay + min size check
│ ├── components/ Reusable UI (menu, panel, jsonview, fieldexplorer, progress...)
│ ├── home/ Main menu (4 modes)
│ ├── learn/ Interactive coding quiz with editor integration
│ ├── explore/ Data structure inspector (headers, EIP-712, on-chain)
│ ├── practice/ Live payment flow execution (EIP-3009, Permit2, side-by-side)
│ └── dashboard/ Live wallet balances
├── pkg/health/ Shared health check type
├── .github/workflows/ci.yml GitHub Actions CI (build + test + vet)
├── .env.example Environment variable template
├── Dockerfile Multi-stage build
├── docker-compose.yml Facilitator + Resource orchestration
├── CONTRIBUTING.md Contributor guidelines
├── LICENSE MIT License
└── Makefile Build, test, run targets
| Component | Technology |
|---|---|
| Language | Go 1.24+ |
| x402 SDK | coinbase/x402/go v2.6.0 |
| EVM Client | go-ethereum v1.17 |
| HTTP Framework | Gin v1.12 |
| TUI Framework | bubbletea + lipgloss (OpenCode-style layout) |
| Quiz Runner | go test (Go) + forge test (Foundry) (Solidity) |
| Editor Integration | tea.ExecProcess → $EDITOR (nvim/vim/nano) |
| Payment Scheme | EIP-3009 / Permit2 (exact scheme) |
| Signatures | EIP-712 Typed Structured Data |
| Transactions | EIP-1559 (dynamic fee) |
| Tx Hash | From | To | Amount |
|---|---|---|---|
0x99e4...dc24 |
0x4732...037b |
0x23fb...b37A |
0.1 USDC |
0x6d3a...2445 |
0x4732...037b |
0xDBCb...07F5 |
0.1 USDC |
Your AI trading terminal assistant for US stocks, commodities, forex, and crypto.
Golang SDK for A2A Protocol
Publishes localhost services to the agentic web through self-hostable, trustless relays with x402 payments.
Building blocks for Agentic payments (x402, MPP, AP2) for TypeScript, Rust, Go, Python, Ruby, PHP, Lua, Kotlin and Swift.
Building blocks for Agentic payments (x402, MPP, AP2) for TypeScript, Rust, Go, Python, Ruby, PHP, Lua, Kotlin and Swift.
Go implementation of the x402 payment protocol