Request → 402 → pay → 200
The whole protocol in one round trip. The server never asks for a card, an API key, or an account — it prices the resource and the client pays for it in-band.
Quickstart
Node ≥ 20. viem is a peer dependency.
import express from 'express'
import { paywall } from 'hood402/server'
const app = express()
app.get('/premium', paywall({
price: '0.01', // USDG
payTo: '0xYourReceivingAddress',
network: 'robinhood', // or 'robinhood-testnet'
facilitator: 'https://your-facilitator.example.com',
}), (req, res) => {
res.json({ data: 'unlocked after a settled USDG payment' })
})
No facilitator? Pass wallet (a viem WalletClient
with a gas key), account, and reader (a viem
PublicClient) instead — the server settles locally.
import { Hood402Client, fromAccount } from 'hood402/client'
import { privateKeyToAccount } from 'viem/accounts'
const account = privateKeyToAccount(process.env.ROBINHOOD_CHAIN_PRIVATE_KEY)
const client = new Hood402Client({
signer: fromAccount(account),
maxSpendPerOrigin: '1.00', // hard cap, USDG
})
const res = await client.fetch('https://api.example.com/premium')
console.log(await res.json()) // the 402 was paid automatically
git clone https://github.com/nirholas/robinhood-chain-x402.git && cd robinhood-chain-x402
npm install && npm run build
cd facilitator && npm install && npm run build
FACILITATOR_PRIVATE_KEY=0x... \
FACILITATOR_NETWORKS=robinhood,robinhood-testnet \
npm start
# -> GET /healthz /supported /metrics
# -> POST /verify /settle
Or build the Docker image — see the facilitator README.
Spec conformance
hood402 implements x402 v1's exact scheme for EVM verbatim — the
X-PAYMENT/X-PAYMENT-RESPONSE header pair, the
PaymentRequirements shape, and the facilitator /verify,
/settle, /supported endpoints — so it interoperates with the
wider x402 client ecosystem out of the box, not just its own client.
Settlement mechanism
USDG is a facet/diamond stablecoin. Its base implementation doesn't expose
EIP-3009, but getFacet(bytes4) proves transferWithAuthorization,
receiveWithAuthorization, and authorizationState are all
registered — verified live on both networks. hood402 settles with the standard
gasless EIP-3009 path; the facilitator pays gas, the payer signs and needs no ETH.
Domain separator
Reconstructed to match the on-chain DOMAIN_SEPARATOR() exactly:
name="Global Dollar", version="1", the chain's own
chainId, and the USDG proxy as verifyingContract.
Replay protection
Every authorization carries a random 32-byte nonce. The facilitator checks
authorizationState(payer, nonce) before broadcasting and claims an
idempotency slot in its ledger first — a retried /settle for the same
signed payment returns the original transaction instead of double-spending gas.
Networks
Mainnet robinhood (chain 4663) and testnet robinhood-testnet
(chain 46630) — both with live, verified USDG deployments.
hood402 vs. r0x
r0x is a hosted facilitator plus an agent-OS SDK and MCP plugin — you call r0x's service and its skill catalog. hood402 is the other end of that spectrum: protocol primitives you self-host, with no dependency on any one operator.
| hood402 | r0x | |
|---|---|---|
| What it is | Middleware + client + facilitator you run yourself | Hosted facilitator + agent SDK + MCP plugin |
| x402 wire format | v1 — X-PAYMENT / X-PAYMENT-RESPONSE, matches the deployed client ecosystem (x402-fetch, x402-axios, etc.) | v2-style CAIP-2 network naming (eip155:4663) and a PAYMENT-RESPONSE header |
| Settlement | EIP-3009 transferWithAuthorization | EIP-3009 TransferWithAuthorization |
| Run your own facilitator | Yes — Dockerfile + Cloud Run docs included | No — r0x operates the facilitator |
| Skill catalog / agent OS | Out of scope — protocol only | 18 MCP tools (trade, bridge, liquidity, …) |
| License | Apache-2.0 | MIT |
They're complementary, not competing: an r0x agent can pay a hood402-protected endpoint,
and a hood402 client can pay an r0x-facilitated one — both speak exact/EIP-3009
USDG under the hood.