How Snakey uses x402 for USDC game entry fees ($0.25 USDC; set via GAME_ENTRY_FEE, same on testnet and mainnet).
x402 revives the HTTP 402 "Payment Required" status code for blockchain micropayments. Developed by Coinbase and Cloudflare, launched May 2025.
Key idea: Client requests resource → Server returns 402 → Client signs payment → Client retries → Server verifies and delivers.
Agent Snakey Server Facilitator Blockchain
│ │ │ │
│─── POST /join ────────────▶│ │ │
│ │ │ │
│◀── 402 + payment details ──│ │ │
│ (price, network, payTo) │ │ │
│ │ │ │
│ (Agent signs EIP-712 msg) │ │ │
│ │ │ │
│─── POST /join + signature ▶│ │ │
│ │─── POST /verify ────────▶│ │
│ │ │── USDC transfer ───▶│
│ │◀── settlement OK ────────│ │
│◀── 200 OK (joined queue) ──│ │ │
Environment Variables:
X402_WALLET_ADDRESS=0x... # Your wallet receiving payments
X402_NETWORK=eip155:84532 # Network (see below)Networks:
| Network | X402_NETWORK | Facilitator | USDC |
|---|---|---|---|
| Testnet | eip155:84532 |
x402.org/facilitator | Free (faucet) |
| Mainnet | eip155:8453 |
api.cdp.coinbase.com/platform/v2/x402 | Real |
Facilitator URL auto-detected based on network.
| Package | Purpose | We Use |
|---|---|---|
@x402/core |
Types, client, facilitator | ✅ |
@x402/express |
Server middleware | ✅ |
@x402/evm |
EVM blockchain support | ✅ |
@x402/fetch |
Client auto-payment | For SDK |
Server (src/server.js):
import { paymentMiddleware, x402ResourceServer } from '@x402/express';
import { ExactEvmScheme } from '@x402/evm/exact/server';
import { HTTPFacilitatorClient } from '@x402/core/server';
const x402Server = new x402ResourceServer(
new HTTPFacilitatorClient({ url: FACILITATOR_URL })
)
.register('eip155:84532', new ExactEvmScheme()) // Testnet
.register('eip155:8453', new ExactEvmScheme()); // Mainnet
app.use(paymentMiddleware({
'POST /join': {
accepts: {
scheme: 'exact',
price: '$0.25',
network: X402_NETWORK,
payTo: X402_WALLET_ADDRESS
}
}
}, x402Server));Settlement observer (not middleware hooks):
@x402/express v2.2.0 does not expose afterSettlement / onVerificationFailure hooks — the 3rd positional arg is paywallConfig. Snakey uses an explicit res.on('finish') observer (attachSettlementObserver in src/server.js) to:
- Record settled payments to the
paymentstable on HTTP 200 (decodingX-Payment-Response) - Roll back queue + jackpot contribution on HTTP 402 (settlement failure)
- Track payer wallet for verification
402 Response (Server → Client):
HTTP/1.1 402 Payment Required
X-Payment-Required: [{"scheme":"exact","price":"$0.25","network":"eip155:84532","payTo":"0x..."}]
Retry Request (Client → Server):
POST /join
X-Payment: <base64-encoded-signed-payment>
Use @x402/fetch to auto-handle payments:
import { wrapFetchWithPayment } from '@x402/fetch';
import { x402Client } from '@x402/core/client';
import { registerExactEvmScheme } from '@x402/evm/exact/client';
const client = new x402Client();
registerExactEvmScheme(client, { signer: yourWallet });
const fetch402 = wrapFetchWithPayment(fetch, client);
// Automatically handles 402 → sign → retry
const response = await fetch402('https://api.snakey.ai/join', {
method: 'POST',
body: JSON.stringify({ playerId, displayName, walletAddress })
});Get free testnet tokens:
- ETH (gas): coinbase.com/faucets/base-ethereum-sepolia-faucet
- USDC: faucet.circle.com (select Base Sepolia)
| Problem | Fix |
|---|---|
| 402 in development | Set NODE_ENV=development to bypass |
| Network mismatch | Check X402_NETWORK matches facilitator |
| Payment not recognized | Verify wallet has USDC on correct network |
| "Payment required" loop | Check signature, may need fresh wallet nonce |
- Payments verified by facilitator before settlement
- On-chain USDC transfer (irreversible)
- Wallet ownership verified via EIP-712 signature
- Rate limited: 3 joins per wallet per hour
- x402.org - Protocol docs
- Coinbase x402 Docs - Integration guide
- GitHub - Source code