Overview
The Cloudflare Agents x402 demo showcases wallet-to-wallet autonomous payments between two agents running on Cloudflare Workers. This example demonstrates how agents can independently manage payments without requiring private keys from users.
Key Features:
- Two-agent system: Server Agent (receives payments) and Client Agent (makes payments)
- Crossmint smart wallets managed via API (no private keys needed)
- x402 protocol for HTTP-native payments
- Fully autonomous payment flow
What This Demo Does
User β PayAgent (Wallet A) β Protected API (Wallet B)
β (402 Payment Required)
β Agent pays $0.10 automatically
β Content returned β
- Server Agent - Has a Crossmint wallet that receives $0.10 payments
- Client Agent - Has a Crossmint wallet that automatically pays for protected content
No private keys needed - both wallets are Crossmint smart wallets managed via API.
Prerequisites
Crossmint API Key
Get a server API key from Crossmint Console:
- Create a new Smart Wallet project
- Navigate to API Keys section
- Create an API key with scopes:
wallets.create, wallets.read, wallets:messages.sign
- Copy the key (starts with
sk_)
Test Tokens (Optional)
Get test USDC on Base Sepolia from Circle Faucet
Setup Instructions
Step 1: Install Dependencies
cd cloudflare-agents
npm install
Create .dev.vars with your Crossmint API key:
CROSSMINT_API_KEY=sk_your_api_key_here
Step 3: Run Locally
You should see:
πΌ Server wallet created: 0xABC...
π° Will receive payments at Crossmint smart wallet
β Ready on http://localhost:8787
Testing the Payment Flow
1. Check Wallets Are Created
curl http://localhost:8787/
Response shows both wallet addresses and their roles.
2. Try Accessing Protected Route Directly (Will Fail)
curl http://localhost:8787/protected-route
Returns 402 Payment Required with payment instructions.
3. Trigger the Agent to Pay and Access
curl http://localhost:8787/agent
The PayAgent will:
- Create its own Crossmint wallet (on first request)
- Attempt to fetch
/protected-route
- Receive
402 Payment Required
- Automatically pay $0.10 to the server wallet
- Receive the protected content
Response:
{
"message": "π This content is behind a paywall. Thanks for paying!",
"data": {
"premium": true,
"timestamp": "2025-10-02T...",
"service": "Crossmint Premium API"
}
}
4. Check Wallet Balances
curl http://localhost:8787/wallets/status
Response:
{
"server": {
"address": "0xABC...",
"balance": { "usdc": "0.10", "eth": "0" }
},
"agent": {
"address": "0xDEF...",
"balance": { "usdc": "0", "eth": "0" }
}
}
How It Works
Server Wallet (Receives Payments)
// Create Crossmint wallet for server
const crossmint = createCrossmint({ apiKey });
const crossmintWallets = CrossmintWallets.from(crossmint);
const serverWallet = await crossmintWallets.createWallet({
chain: "base-sepolia",
signer: { type: "api-key" }
});
// Protect routes with payment middleware
paymentMiddleware(serverWallet.address, {
"/protected-route": { price: "$0.10", network: "base-sepolia" }
});
Client Agent (Makes Payments)
export class PayAgent extends Agent {
async onStart() {
// Create agent's Crossmint wallet
this.wallet = await crossmintWallets.createWallet({
chain: "base-sepolia",
signer: { type: "api-key" }
});
// Create x402-compatible signer
const x402Signer = createX402Signer(this.wallet);
this.fetchWithPay = wrapFetchWithPayment(fetch, x402Signer);
}
async onRequest(req: Request) {
// Automatically pays when encountering 402 status
return this.fetchWithPay(protectedUrl, {});
}
}
Use Cases
This pattern enables:
- π Pay-per-use APIs: Agents pay per call instead of subscriptions
- π Data marketplaces: Buy/sell data between agents
- π€ Agent-to-agent commerce: Autonomous service transactions
- β‘ Micropayments: Pay fractions of a cent per API call
- π Cross-platform payments: No platform lock-in
Architecture
βββββββββββββββ
β Client β
β (Agent) β
β + Wallet β
ββββββββ¬βββββββ
β
β GET /protected-route
βΌ
βββββββββββββββββββββββ
β Payment Middleware β
β (x402-hono) β
ββββββββ¬βββββββββββββββ
β
β 402 Payment Required
β + payment instructions
βΌ
βββββββββββββββ ββββββββββββββββββββ
β Client ββββββββββΆβ Facilitator β
β Pays β β (x402.org) β
βββββββββββββββ ββββββββββ¬ββββββββββ
β β
β β Verify
β GET + payment proof β
βΌ βΌ
βββββββββββββββββββββββ
β Protected Content β
βββββββββββββββββββββββ
βββββββββββββββ
β Client β
β (Agent) β
β + Wallet β
ββββββββ¬βββββββ
β
β GET /protected-route
βΌ
βββββββββββββββββββββββ
β Payment Middleware β
β (x402-hono) β
ββββββββ¬βββββββββββββββ
β
β 402 Payment Required
β + payment instructions
βΌ
βββββββββββββββ ββββββββββββββββββββ
β Client ββββββββββΆβ Facilitator β
β Pays β β (x402.org) β
βββββββββββββββ ββββββββββ¬ββββββββββ
β β
β β Verify
β GET + payment proof β
βΌ βΌ
βββββββββββββββββββββββ
β Protected Content β
β Returned β
βββββββββββββββββββββββ
## Payment Flow Sequence
```mermaid
sequenceDiagram
participant Client as PayAgent
participant Server as Protected API
participant Facilitator as x402 Facilitator
participant Chain as Base Sepolia
Client->>Server: GET /protected-route
Server-->>Client: 402 Payment Required<br/>{amount, to, network}
Client->>Client: Sign payment (EIP-712)
Client->>Facilitator: Submit payment signature
Facilitator->>Chain: Verify & settle USDC
Chain-->>Facilitator: TX confirmation
Client->>Server: GET /protected-route + proof
Server->>Facilitator: Verify payment
Facilitator-->>Server: Payment verified
Server-->>Client: Protected content
```text
## Deploying to Production
### Step 1: Set Production Secret
```bash
npx wrangler secret put CROSSMINT_API_KEY
# Paste your API key when prompted
```text
### Step 2: Update to Mainnet
Edit `src/index.ts` to use Base mainnet:
```typescript
// Change from:
chain: "base-sepolia",
network: "base-sepolia",
// To:
chain: "base",
network: "base",
```text
### Step 3: Deploy
```bash
npm run deploy
```text
### Step 4: Test Live
```bash
curl https://crossmint-x402.your-subdomain.workers.dev/agent
```text
## Troubleshooting
### "Wallets need test tokens"
- Both wallets start with zero balance
- Get test USDC from [Circle Faucet](https://faucet.circle.com/)
- Fund the agent wallet address shown in logs
### "Cannot find module '@crossmint/wallets-sdk'"
- Run `npm install` to install dependencies
- Make sure package.json has the correct version
### "Payment verification failed"
- Check agent wallet has sufficient USDC balance
- Verify network is "base-sepolia" consistently
- Ensure facilitator URL is accessible
## Key Technical Details
### Smart Contract Wallets
Crossmint wallets are ERC-4337 smart contract accounts:
- Work before on-chain deployment (ERC-6492 signatures)
- Auto-deploy on first transaction
- Gas-sponsored transactions available
- No private key management required
### x402 Protocol
HTTP-native payment protocol:
- Uses `402 Payment Required` status code
- Payment details in response headers
- Signature-based payment proof
- Async settlement via facilitator
### x402 Adapter
The `x402Adapter.ts` file bridges Crossmint wallets to x402:
- Converts Crossmint wallet API to viem-compatible Account
- Handles EIP-712 typed data signing
- Supports both ERC-6492 and EIP-1271 signatures
```typescript
export function createX402Signer(wallet: CrossmintWallet): Account {
return {
address: wallet.address as `0x${string}`,
type: "local",
signTypedData: async (typedData) => {
return wallet.signTypedData(typedData);
}
};
}
```text
## Learn More
- π **Crossmint Wallets**: https://docs.crossmint.com/wallets
- π **x402 Protocol**: https://developers.cloudflare.com/agents/x402/
- ποΈ **Cloudflare Agents**: https://developers.cloudflare.com/agents/
- π° **Base Network**: https://base.org/
## Key Features Summary
β
**No private key management** - Crossmint handles wallet security
β
**Smart contract wallets** - Account abstraction, gas sponsorship
β
**Agent-to-agent payments** - Autonomous commerce between services
β
**HTTP-native payments** - x402 protocol for seamless integration
---
Built with Cloudflare Agents + Crossmint Wallets + x402 Protocol