
Public
Likex402-playground
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
Viewing readonly version of main branch: v78View latest version
A demo app showing both sides of the x402 protocol (HTTP 402 payments) — a buyer that pays for APIs with USDC, and a seller that charges for an API endpoint. All powered by automatic micropayments on Base.
This project contains two HTTP endpoints that share the same wallet (X402_PRIVATE_KEY):
| App | File | Role | Description |
|---|---|---|---|
| Buyer | buyer.tsx | Pays for APIs | Web UI that calls paid x402 endpoints using @x402/fetch |
| Seller | seller.tsx | Charges for an API | Hono app with @x402/hono middleware protecting GET /api/random |
Since both use the same wallet, calling the seller from the buyer sends $0.001 USDC from yourself to yourself — a perfect zero-cost demo loop. Gas is sponsored by the xpay facilitator (Base L2 gas costs fractions of a penny, so facilitators subsidize it to drive adoption of x402).
Rendering mermaid diagram...
Rendering mermaid diagram...
buyer.tsx → HTTP entry point for buyer app (Hono router)
seller.tsx → HTTP entry point for seller app (Hono + x402 middleware)
routes/
home.tsx → Buyer landing page with screenshot & random number forms
screenshot.tsx → Screenshot form + POST handler (pays Browserbase)
random.tsx → Random number handler (pays our own seller.tsx)
transactions.tsx → Transaction history table
lib/
x402.ts → x402 client setup (wallet signer + wrapFetchWithPayment)
browserbase.ts → Browserbase session creation via x402
screenshot.ts → Playwright CDP screenshot capture
db.ts → SQLite schema & queries for transaction log
layout.tsx → Shared HTML layout with Twind CSS
| Key | Description |
|---|---|
X402_PRIVATE_KEY | Private key for a Base wallet holding USDC (used by both buyer and seller) |
| Route | Description |
|---|---|
/ | Home — screenshot form, random number button, wallet info |
/screenshot | Capture a website screenshot ($0.01 USDC via Browserbase) |
/random | Get a random number ($0.001 USDC via our seller) |
/transactions | Table of past payments with totals and tx hashes |
| Route | Description |
|---|---|
/ | Homepage explaining the API and pricing |
/api/random | Paid endpoint — returns { random: Math.random() } for $0.001 USDC |
- Network: Base mainnet (
eip155:8453) - Currency: USDC
- Facilitator: xpay.sh (zero fees, gas sponsored)
- Seller price: $0.001 per random number
- Screenshot price: $0.01 per session (paid to Browserbase)
To run this yourself, you need a Base wallet with USDC and its private key. Here's how to set one up:
- Install the Coinbase Wallet Chrome extension (the iOS/Android app works too, but exporting the private key is easier from the extension)
- Create a new wallet
- Click Buy → Add with Coinbase Onramp
- Important: If you have a personal Coinbase account, fully log out of it first — otherwise the onramp may try to use your existing account and get confused
- Buy USDC on Base with a debit card (Apple Pay also works)
- Export the private key: Settings → Developer Settings → Show private key
- Add it as
X402_PRIVATE_KEYin your val's environment variables - Note: You may need to prefix the key with
0x— the key exported from Coinbase Wallet doesn't include it, but viem expects it