GraphPayAsk before you pay
MapRace modeHow it works

How it works

Agents that can pay, can be trusted and can be stopped. Each one is identified by ENS, remembered on Arkiv and paid on Whitechain: decentralized, secure and verifiable, on testnets only.

Identify

ENS on Ethereum Sepolia

Every person, agent and shop has a name under graphpay.eth, for example payer.vitalik.graphpay.eth. The owner can pause an agent with one text record or unregister it, and every payment checks the name first. A shop’s address record says where its money goes.

Pay

x402 on Whitechain Sepolia

The shop asks for payment with HTTP 402. The payer agent signs the order’s terms and pays no gas; our own facilitator checks the signature and the ENS name, and its relayer settles in test USDT and pays the gas. An on-chain policy caps what each agent can spend in a day.

USDT token 0xcedf…55a7(opens the explorer in a new tab)

Remember

Graph Arkiv on Arkiv Rabdi

Every payment, refund and delivery becomes a line between two ENS names, with running tallies per name. The receipts cannot be edited. Any agent can ask the graph in one GraphQL query and see every Arkiv read behind the answer before it pays.

No database of our own

State lives on the Whitechain contract and on Arkiv; the website only runs code. No personal data is collected and nothing identifies a visitor. The city of shops around the demo is synthetic and labelled as such.

The website’s routes

Every route that makes anyone sign runs on the server behind the demo passcode, sent in a header and never in a URL.

RouteGateWhat it doesWho signs
POST /api/agents/runpasscodestart one errand (one at a time) and stream its events (SSE)the payer agent, then the relayer
GET /api/agents/run/:id/eventsopenreplay a run held by this server (best effort; the POST streams it live)nobody
GET /api/state/customeropenthe payer agent's status, cap, spend, last order, subscriptionnobody
POST /api/customer/reorderpasscodere-order from the same shopthe payer agent, then the relayer
POST /api/customer/refund-requestpasscoderecord a refund request on Arkivthe recorder (W_SYNC)
POST /api/customer/subscribepasscodesubscribe to the weekly box (or the demo period)the payer agent, then the relayer
POST /api/customer/unsubscribepasscodecancel the subscriptionthe payer agent, then the relayer
POST /api/customer/pausepasscodeset the payer agent's ENS status to pausedthe owner (Sepolia)
POST /api/customer/resumepasscodeset the payer agent's ENS status back to activethe owner (Sepolia)
POST /api/customer/kill-disposablepasscodeprovision, pay with and unregister a disposable agentthe owner, the disposable agent, the relayer
GET /api/merchant/eventsopenstream the shop's new edges (SSE, polled from GraphQL)nobody
POST /api/merchant/dispatchpasscodemark the order deliveredthe merchant
POST /api/merchant/openpasscodelist the shop as open on Arkiv (renewed every 5 min while on) or take it offW_DIRECTORY (Arkiv)
POST /api/merchant/refundpasscodepartial or full refundthe merchant
GET /api/merchant/export.csvopenthe accountant's CSV from GraphQLnobody
GET /api/racerate limitone side of the race, live and uncached (SSE)nobody
GET /api/mapopenthe shop directory, open shops and agents at work, from the graphnobody
GET /api/statusopenblock heads, mirror lag, relayer balance, token modenobody
POST /api/passcodepasscodecheck the passcode (signs nothing)nobody

For other shops

A short drop-in checkout lets any shop take these payments; the demo store adds it in about 20 lines. It is shown here when it ships.

Source code on GitHub

Enter the demo passcode

Buttons that move money, pause an agent or refund an order run on the server behind this passcode. It stays in this browser tab only.