A sleek browser client that demonstrates the full x402 payment flow:
Call → 402 Payment Required → Wallet pays → Retry → Success
- Connect wallet (Base Sepolia) via RainbowKit + Wagmi
- Pay directly from the connected wallet using x402-fetch
- Automatic 402 → pay → retry → success handling
- Clean Tailwind UI
- Interaction Log: Calling API → Got 402 → Retrying with payment → Success (200) → Payment receipt received
- Server Response + decoded X-PAYMENT-RESPONSE
Next.js 14 · wagmi v2 · RainbowKit · viem · Tailwind CSS v3 · x402-fetch
cd examples/typescript/servers/express
cp .env.example .envSet at least:
RECEIVING_WALLET_ADDRESS=0xYourReceivingAddress
PORT=4021Start & verify:
pnpm dev
curl -i http://localhost:4021/weather # expect: HTTP/1.1 402 Payment Requiredcd ../../clients/x402-ui
pnpm installAdd a rewrite to avoid CORS (proxy browser calls → Express):
// next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
async rewrites() {
return [{ source: '/x402/:path*', destination: 'http://localhost:4021/:path*' }]
},
}
export default nextConfigStart:
pnpm devOpen → http://localhost:3000
- Connect wallet (Base Sepolia + test USDC)
- Click Fetch paid /weather
- Watch the log:
Calling API Got 402 (Payment Required) Retrying with payment Success (200) Payment receipt received - View decoded payment and response on the right.
const fetchWithPayment = wrapFetchWithPayment(fetch, walletClient)
const res = await fetchWithPayment('/x402/weather', { method: 'GET' })x402-fetch wraps fetch to:
- Detect a 402 challenge
- Sign
X-PAYMENTusing the connected wallet - Retry the request
- Return the unlocked response
src/
app/
layout.tsx → includes Providers (Wagmi + RainbowKit)
providers.tsx → provider setup
page.tsx → main UI and log
wagmi.ts → network + WalletConnect config
next.config.mjs → rewrite proxy to Express (/x402/*)
| Issue | Fix |
|---|---|
| CORS error | Ensure the rewrite in next.config.mjs is present and you call /x402/... from the client. |
| WagmiProviderNotFoundError | Make sure Providers wraps the app in layout.tsx. |
| Invalid EVM wallet client | Pass the full walletClient, not just the account. |
| Missing fetch request configuration | Call with { method: 'GET' }. |
| Still 402 after retry | Switch to Base Sepolia and ensure the wallet has test USDC. |
pnpm dev # run Next.js dev server
pnpm build # production build
pnpm start # serve production buildMIT — same as the root x402 repository.