feat(x402): production-grade HTTP payment rails - #468
Conversation
- Persistent receipt store: file-backed JSON in .data/x402-receipts.json - Persistent subscription store: .data/x402-subscriptions.json (survives restarts) - Webhook callbacks: register/list/delete endpoints + HMAC SHA-256 signed dispatch - dispatchX402Webhooks fires on every settlement via settleX402() - Developer SDK: @open-stellar/x402 with withX402() 5-line route middleware - lib/sdk/x402.ts: receipt + subscription header verification gate - Multi-chain: Stellar, BNB, Base shown in marketplace service cards - Service catalog API: /api/protocol/x402/services with pricing + subscription tiers - Marketplace UI: chain tags, subscription badge, live Test x402 Gate modal - Payment Explorer: added Base chain filter option - Tests: 577/577 passing, 0 TypeScript errors, 0 lint errors
cb3afa8 to
39c4f60
Compare
39c4f60 to
365f55c
Compare
|
This PR is blocked by one check, and nobody told youHeads up: the only thing standing between this PR and a merge is the SonarCloud Code Analysis quality gate, which is red. Everything else passes. That failure has been sitting here without anyone explaining it, which is on us, not on you. What to do: open the SonarCloud link in the failed check (or the
Push a fix to the same branch and the gate re-runs on its own. Comment here when it is green and it gets merged. If you think the gate is wrong about something, say so in a comment rather than working around it — sometimes it is, and we would rather discuss it than have you contort the code. |




EPIC: x402 Payment Rails — Implementation Summary
1. Persistent Receipt Store
Problem:
RECEIPT_REGISTRYwas an in-memoryMap— all receipts lost on restart.Solution:
lib/protocols/x402-receipt-store.ts— file-backed JSON at.data/x402-receipts.jsonensureDb()— auto-creates.data/dir and empty JSON on first runsaveX402Receipt()— appends and persistslistX402Receipts(filters?)— filter byagentId,serviceId, orchaingetX402Receipt(id)— single lookup2. Persistent Subscription Store
Problem: No recurring billing — every payment was one-off.
Solution:
lib/protocols/x402-subscription-store.ts—.data/x402-subscriptions.jsonmonthlyCap,usedThisPeriod,periodStart,tiersettleX402()now checks active subscriptions, enforces the monthly cap, and auto-renews periods older than 30 daysrenewSubscriptionPeriod()resetsusedThisPeriodto0and advancesperiodStart3. Webhook Callbacks
Problem: No external notification when a payment settled.
Solution:
lib/protocols/x402-webhook-store.ts+app/api/protocol/x402/webhooks/route.tsserviceIdviaPOST /api/protocol/x402/webhooksdispatchX402Webhooks(serviceId, receipt)fires after every settlement — POSTs to all registered endpoints with:x-x402-signature: sha256=<HMAC-SHA256>x-x402-event: settlementx-x402-timestampPromise.allSettled) — a failing webhook never breaks payment flowPOST/GET/DELETEon/api/protocol/x402/webhooks4. Multi-Chain Settlement
Problem: Only Stellar was supported.
Solution: Settlement now supports Stellar, BNB Chain, and Base (Coinbase L2)
SettlementChainunion type:"stellar" | "bnb" | "base"settleX402()routes to chain-specific logic based onchainfieldchainandchainId(56 for BNB, 8453 for Base)5. Developer SDK:
@open-stellar/x402Problem: Integrating x402 required understanding the full quote/settle protocol.
Solution:
lib/sdk/x402.ts+packages/x402-sdk/withX402middleware flow:x-x402-receipt-idheader — looks up receipt, verifies it belongs to this service, checks not expired/replayedx-x402-subscription-token— decodesagentId:serviceId:tier, verifies active subscription with remaining cap402 Payment Requiredwith live quote headersThe package is npm-publishable with CJS + ESM + TypeScript declaration outputs.
6. Service Marketplace UI
Problem: No visual browse experience for API services and prices.
Changes to
components/marketplace/service-card.tsx:New
app/api/protocol/x402/services/route.ts:GET /api/protocol/x402/services— full catalog with per-chain pricing + subscription tiersGET /api/protocol/x402/services?id=<id>— single service7. Payment Explorer Enhancement
components/explorer/receipt-table.tsx— added Base to the chain filter dropdown.8. New API Endpoints
GET/POST/DELETE/api/protocol/x402/webhooksGET/api/protocol/x402/servicesGET/api/protocol/x402/receiptsGET/api/protocol/x402/receipts/[id]POST/GET/api/protocol/x402/subscriptionsGET/api/protocol/x402/subscriptions/[agentId]/[serviceId]9. Tests Added
__tests__/api/protocol/x402-receipts.test.ts__tests__/api/protocol/x402-webhooks.test.ts__tests__/api/protocol/x402-subscriptions.test.ts__tests__/api/protocol/x402-sdk.test.tse2e/x402-payment-rails.spec.tsFinal results: 577/577 passing, 0 TypeScript errors, 0 lint errors, production build clean.
10. Bug Fixed: Windows
renameSyncEPERMThe atomic
tmp → renameSyncwrite pattern fails on Windows in two ways:unlinkSyncmarks the file for deletion;existsSyncstill returnstruebutreadFileSyncthrowsFix: All three stores now use a plain
writeFileSync(DB_PATH, data)overwrite — cross-platform, no locking issues.Data Files Created at Runtime
All auto-created on first write, gitignored, and human-readable JSON.
Closes #18