@agentbadge/circle-payments
Circle Gateway nanopayments + x402 payment rails for AgentBadge — trusted
agent payments on Base Sepolia and Arc.
This package is the single boundary for everything payment-related in the
AgentBadge server: x402 scheme registration, payment routing, Hono
middleware, identity extensions, failure ledger, pricing, payment status /
history, and the ERC-8183 agentic-commerce escrow stack on Arc.
Boundary rule
All Circle SDK (@circle-fin/x402-batching) and x402 (@x402/core,
@x402/evm) usage stays inside this package. Server code imports only
from @agentbadge/circle-payments — never from the underlying SDKs directly.
Features
- Three payment rails behind one router:
- Gateway batch — gasless sub-cent USDC via Circle Gateway
(
BatchFacilitatorClient + GatewayEvmScheme)
- Exact — standard x402 EIP-3009
exact scheme via a facilitator
(Base Sepolia)
eip3009-client-broadcast — Arc self-settle: the buyer broadcasts
transferWithAuthorization themselves (gas paid in USDC, Arc's native
token — zero ETH, no facilitator), the server verifies the on-chain
receipt
requirePayment Hono middleware — 402 challenge → verify → settle →
receipt headers, with identity extension injection
- Identity extension — embeds the seller's AgentBadge passport
(
passportTokenId, readinessScore, verifyUrl) into 402 responses
- ERC-8183 escrow — full job lifecycle on Arc (
createJob → setBudget → fund → submit → evaluate → complete), evaluator with verdict store, and
commission split to treasury
- ERC-8004 mirror — passport registration in the ERC-8004
IdentityRegistry on Arc
- Memo audit — attach order/job metadata to settlement transactions via
the Arc Memo contract
- Ops surface — pricing table, payment status lookup, payment history,
failure ledger, wallet balance helpers
Architecture
Mermaid source
flowchart LR
subgraph Server["Hono server"]
MW["requirePayment()<br/>middleware"]
RT["createPaymentRouter()<br/>router.ts"]
PR["PRICE_TABLE<br/>pricing.ts"]
ID["identityExtension()<br/>identity.ts"]
LG["FailureStore<br/>ledger.ts"]
end
subgraph Schemes["Scheme handles (schemes/)"]
GW["Gateway batch<br/>gateway.ts"]
EX["Exact EIP-3009<br/>exact.ts"]
AS["Arc self-settle<br/>arc-self-settle.ts"]
end
subgraph Escrow["Agentic commerce (escrow/)"]
E8["createErc8183()<br/>erc8183.ts"]
EV["createEvaluator()<br/>evaluator.ts"]
CM["createCommissionSplitter()<br/>commission.ts"]
end
subgraph Ext["External"]
FAC["x402.org facilitator"]
CGW["Circle Gateway"]
ARC["Arc testnet<br/>USDC 0x3600…0000"]
E8183["ERC-8183 AgenticCommerce<br/>0x0747…4583"]
end
MW --> RT
MW --> ID
MW --> LG
RT --> GW & EX & AS
GW --> CGW
EX --> FAC
AS --> ARC
E8 --> E8183
EV --> E8
CM --> E8183
Payment flow (x402)
Mermaid source
sequenceDiagram
participant A as Buyer agent
participant S as Server (requirePayment)
participant R as PaymentRouter
participant F as Facilitator / Arc RPC
A->>S: GET /resource (no payment)
S->>R: buildAccepts(price, payTo)
R-->>S: accepts[] (gateway, exact, arc-broadcast)
S-->>A: 402 + PAYMENT-REQUIRED (+ agentbadge ext)
A->>A: pick rail, sign EIP-3009
alt Arc self-settle
A->>F: broadcast transferWithAuthorization (gas in USDC)
F-->>A: txHash
end
A->>S: GET /resource + payment-signature
S->>R: verify(payload, requirements)
alt exact / gateway
R->>F: facilitator verify+settle
else arc self-settle
R->>F: getTransactionReceipt(txHash)<br/>check Transfer log + replay
end
F-->>R: settled
R-->>S: SettleResult
S-->>A: 200 + PAYMENT-RESPONSE + body
ERC-8183 escrow lifecycle (Arc)
Mermaid source
stateDiagram-v2
[*] --> Open: client createJob(provider,<br/>evaluator, expiredAt, description)
Open --> Funded: provider setBudget +<br/>client approve USDC + fund
Funded --> Submitted: provider submit(deliverable)
Funded --> Expired: claimRefund (past expiredAt)
Submitted --> Completed: evaluator complete<br/>(escrow → provider, fee → treasury)
Submitted --> Rejected: evaluator reject<br/>(escrow → client)
Submitted --> Expired: claimRefund (past expiredAt)
Completed --> [*]
Rejected --> [*]
Expired --> [*]
Install
npm install @agentbadge/circle-payments
Usage
Server: gate a route with a price
import { createPaymentRouter, requirePayment } from "@agentbadge/circle-payments";
const router = createPaymentRouter({
gateway: true,
exact: true,
arcSelfSettle: true,
facilitatorUrl: "https://x402.org/facilitator",
payTo: "0x…",
identityLookup,
});
app.get("/api/paid", requirePayment(router, { price: "$0.001" }), (c) =>
c.json({ data: "premium" }),
);
Escrow (ERC-8183 on Arc)
import { createErc8183, createEvaluator, splitPayout } from "@agentbadge/circle-payments";
const escrow = createErc8183({ read: publicClient });
const { jobId } = await escrow.createJob(clientWallet, {
provider, evaluator, expiredAt, description,
});
const evaluator = createEvaluator({ escrow, wallet: evaluatorWallet, verify });
const verdict = await evaluator.evaluate(jobId);
API surface
createPaymentRouter, buildAccepts | Rail registry + 402 accepts generation |
requirePayment | Hono middleware: 402 → verify → settle → receipt |
registerGatewayScheme, registerExactScheme, registerArcSelfSettleScheme | Scheme registration on x402ResourceServer |
BASE_SEPOLIA, ARC_TESTNET, ARC_CONTRACTS, getChain | Chain configs (CAIP-2, USDC, RPC) |
identityExtension | AgentBadge passport extension for 402 responses |
PRICE_TABLE, getPrice, validatePriceTable | Route pricing config |
createPaymentStatusLookup | Payment status by tx hash / gateway transfer |
createMemoryFailureStore | Failure ledger (alerts on repeated failures) |
createErc8183, createJobRegistry, jobDescription | ERC-8183 job lifecycle + registry |
createEvaluator, createEvaluationStore | Evaluator verdicts + on-chain settle |
splitPayout, createCommissionSplitter | Fee split to treasury (BPS) |
createErc8004Mirror | Passport registration in ERC-8004 registry |
verifyPassport | Buyer-side helper: 402 response → trust score |
createMemoClient | Arc Memo contract metadata on settlement txs |
Verified on-chain facts (Arc testnet)
- CAIP-2:
eip155:5042002 · USDC: 0x3600000000000000000000000000000000000000
- EIP-712 domain:
{name:"USDC", version:"2", chainId:5042002, verifyingContract: USDC}
- Gas floor:
maxFeePerGas ≥ 20 Gwei, maxPriorityFeePerGas 0–1 Gwei,
~65k gas per transferWithAuthorization — paid in USDC (6 dec)
- ERC-8183 AgenticCommerce:
0x0747EEf0706327138c69792bF28Cd525089e4583
- Memo contract:
0x5294E9927c3306DcBaDb03fe70b92e01cCede505
License
MIT
Part of AgentBadge — support@agentbadge.xyz