Agent-to-Provider
A self-contained demo that runs both an Express provider and an agent in a single script. This is the easiest way to see the full x402 payment flow end-to-end.
What it does
- Starts an Express server on port 3001 with a paywalled
/searchendpoint ($0.001 per call) - After 500ms, launches an agent that connects to the provider
- The agent checks its balance, makes a paid request, and prints the results
- The provider logs the received payment
- The script exits after the payment completes
Source
import express from 'express'
import { Crumb } from 'crumb-alpha-sdk'
import { createGatewayMiddleware } from '@circle-fin/x402-batching/server'
const AGENT_PRIVATE_KEY = process.env.TEST_PRIVATE_KEY!
const PROVIDER_ADDRESS = process.env.CRUMB_WALLET_ADDRESS!
const PORT = 3001
// ── Provider ──────────────────────────────────────────────
const app = express()
app.use(express.json())
const gateway = createGatewayMiddleware({
sellerAddress: PROVIDER_ADDRESS,
description: 'Demo search endpoint',
})
app.post('/search', gateway.require('$0.001'), (req: any, res) => {
if (req.payment) {
console.log(`[Provider] Received ${req.payment.amount} USDC`)
}
res.json({
results: [
{ title: 'Demo result 1', relevance: 0.95 },
{ title: 'Demo result 2', relevance: 0.87 },
],
})
})
// ── Agent ─────────────────────────────────────────────────
async function runAgent() {
const crumb = new Crumb({
privateKey: AGENT_PRIVATE_KEY,
chain: 'arcTestnet',
onLowBalance: (bal) => console.log(`[Agent] Low balance: ${bal} USDC`),
})
console.log(`[Agent] Address: ${crumb.address}`)
console.log(`[Agent] Balance: ${await crumb.balance()} USDC`)
const result = await crumb.fetch(`http://localhost:${PORT}/search`, {
method: 'POST',
body: { query: 'test query' },
maxPayment: 0.01,
})
console.log('[Agent] Response:', JSON.stringify(result.data, null, 2))
console.log(`[Agent] Paid: ${result.formattedAmount} USDC`)
console.log(`[Agent] Tx: ${result.txHash}`)
process.exit(0)
}
// ── Start ─────────────────────────────────────────────────
app.listen(PORT, () => {
console.log(`[Provider] Running on http://localhost:${PORT}`)
setTimeout(() => runAgent().catch(console.error), 500)
})
Running
npx tsx --env-file=.env examples/agent-to-provider/index.ts
Expected output
[Provider] Running on http://localhost:3001
[Provider] Price: $0.001 per call
[Agent] Address: 0x22b2...
[Agent] Balance: 10.0 USDC
[Provider] Received 0.001 USDC
[Agent] Response: {
"results": [
{ "title": "Demo result 1", "relevance": 0.95 },
{ "title": "Demo result 2", "relevance": 0.87 }
]
}
[Agent] Paid: 0.001 USDC
[Agent] Tx: 0xabc...
Demo complete.