Skip to Content
Networkx402 earn rail

x402 earn rail

Claros does not only publish data, it sells it. The x402 earn rail is the paid surface where the oracle’s own attested readings are sold per call over HTTP 402 , settled in WCSPR on Casper, with the proceeds landing in the autonomous agent’s account. This page is the architecture and economics of that earn side: the three services that compose the rail, who touches the chain, who custodies funds, and how each paid read feeds the agent’s on-chain reinvestment loop.

This is the seller’s view. For the buyer’s view (the 402 handshake step by step, the payment parameters, and copy-pasteable client code), see pay-per-call (x402). The free read paths (REST, the SDK, cross-contract) return the same data without payment; the rail exists to monetize that data and fund the agent.

The rail at a glance

Three small services make up the paid path. Each is a standalone process with one job, and they communicate over plain HTTP. Run all three locally for the demo, or host the oracle server and facilitator for real agent-to-agent traffic.

ComponentSourceDefault portRole
Oracle serverservices/oracle-server4021The resource. Gates GET /oracle/feed behind x402, advertises the price, asset, and payTo, builds the reading with on-chain provenance, and delegates settlement to the facilitator.
Facilitatorservices/facilitator4022Verify and settle on Casper. Holds a Casper signing key, verifies the signed authorization, and submits the WCSPR transfer on testnet. The only component that touches the chain.
Consumerservices/consumern/aThe payer. Signs a WCSPR transfer_with_authorization off-chain and retries with X-PAYMENT. Any client can fill this role.

The resource server never talks to Casper directly. It holds a facilitator client (HTTPFacilitatorClient) pointed at FACILITATOR_URL and asks the facilitator to verify and settle. That separation is the whole architecture: the resource server stays stateless and chain-free, while a single facilitator (the only process with a funded key, a node connection, and a gas budget) can settle for many resource servers.

consumer (payer) oracle server :4021 facilitator :4022 Casper testnet services/consumer services/oracle-server services/facilitator | | | | | 1. GET /oracle/feed | | | |------------------------->| | | | 2. 402 Payment Required | | | | exact, WCSPR, amount, | | | | payTo=agent, network | | | |<-------------------------| | | | 3. sign WCSPR transfer_with_authorization | | | retry with X-PAYMENT | | | |------------------------->| 4. verify + settle | | | |------------------------>| 5. submit transfer | | | |--------------------->| | | | WCSPR: payer to agent | | settle result |<---------------------| | |<------------------------| | | 6. 200 OK: reading + provenance (PAYMENT-RESPONSE) | | |<-------------------------| | |

The handshake is automatic on the client: steps 1 through 6 happen inside one fetchWithPayment(...) call. The full client walkthrough lives on the pay-per-call page; here we focus on what each server does and where the money goes.

Trust and custody boundaries

The three roles are deliberately unequal in what they can touch. Understanding the boundaries is the key to the rail’s economics.

ConcernConsumer (payer)Oracle server (resource)Facilitator
Touches CasperNo (signs off-chain)No (delegates over HTTP)Yes (submits settle)
Needs a node + gasNoNoYes
Custodies the WCSPRSpends its ownNeverNever
Holds a keyIts own payer keyNone for paymentIts own facilitator key
Trusts whomNo one (verifies via source_hash)The facilitator’s verify/settle resultThe signed authorization

Two facts fall out of this table and matter for the economics below:

  • The facilitator pays gas but never custodies the payment. A WCSPR transfer_with_authorization moves funds straight from the consumer (the authorizer) to payTo (the agent). The facilitator only relays and submits that authorization, so the WCSPR is never in its hands. It bears the settlement gas, nothing more.
  • The consumer trusts no one. The reading comes back with the same source_hash the agent attested on-chain, so the buyer reconciles the purchased value against the registry rather than trusting the server. See provenance and source hash.

The resource: oracle server

The oracle server (services/oracle-server, port 4021) is the paid product. It wraps one route, GET /oracle/feed?asset_id=OP-1, in x402 payment middleware. The product it sells is the latest attested reading plus a provenance block that points back to the AttestationRegistry, so the buyer can verify the value independently.

It advertises the payment in accepts and pins the exact settled amount with a money parser. The $0.001 price is a display label; the parser resolves it to FEED_PRICE_MOTES of WCSPR.

// services/oracle-server/index.ts (trimmed) const facilitatorClient = new HTTPFacilitatorClient({ url: cfg.facilitatorURL }); // The exact amount the buyer pays, independent of the "$0.001" label. const assetAmount: AssetAmount = { asset: cfg.assetPackage, // WCSPR package hash amount: cfg.priceMotes, // FEED_PRICE_MOTES, default 1_000_000_000 = 1 WCSPR extra: { name: cfg.assetName, symbol: 'WCSPR', version: '1', decimals: '9' }, }; const casperScheme = new ExactCasperScheme() .registerAsset(chainID, cfg.assetPackage, 9) // WCSPR, 9 decimals .registerMoneyParser(() => Promise.resolve(assetAmount)); app.use( paymentMiddleware( { 'GET /oracle/feed': { accepts: [{ scheme: 'exact', price: '$0.001', network: chainID, payTo: cfg.payeeAddress }], description: 'Claros: latest attested parking-revenue reading for an asset', mimeType: 'application/json', }, }, new x402ResourceServer(facilitatorClient).register(chainID, casperScheme), ), );

payTo is PAYEE_ADDRESS, the agent’s account (account-hash-43d7dd06d5538e504e54a3f235f1596f7d2e803e9065bf3c0d040f5cd31a21d4), the same identity that attests the reading on-chain. Selling the data therefore pays the oracle that produced it. That is the link the whole rail exists to create.

Configuration

Every payment parameter the resource advertises comes from its environment.

VariableDefaultMeaning
PORT4021Listen port.
PAYEE_ADDRESSrequiredThe payTo account. WCSPR lands here (the agent).
FACILITATOR_URLrequiredWhere to reach the facilitator’s verify and settle.
FACILITATOR_API_KEY""Optional bearer sent on the facilitator calls.
CAIP2_CHAIN_IDrequiredThe CAIP-2 network id, casper:casper-test.
ASSET_PACKAGErequiredWCSPR package hash (3d80df21ba4ee4d66a2a1f60c32570dd5685e4b279f6538162a5fd1314847c1e).
ASSET_NAMErequiredThe asset’s display name, Wrapped CSPR.
FEED_PRICE_MOTES1000000000The settled price in motes (1 WCSPR, 9 decimals).
ATTESTATION_REGISTRY_PACKAGErequiredRegistry hash stamped into the provenance block.
SAN_DIEGO_YEAR2026Which civic CSV year the OP-1 reading is built from.

The facilitator: verify and settle on Casper

The facilitator (services/facilitator, port 4022) is the rail’s gateway to Casper. It exposes a tiny, stateless API and holds the only key in the rail that signs a settlement transaction. The resource server calls it; it never calls the resource server.

EndpointMethodPurposeOn-chain
/verifyPOSTCheck a signed payload satisfies the payment requirements. Returns VerifyResponse.No
/settlePOSTSubmit the WCSPR transfer_with_authorization on Casper, moving funds payer to agent. Returns SettleResponse.Yes
/supportedGETThe schemes and networks this facilitator can settle (facilitator.getSupported()).No
/healthGETLiveness.No

It builds one signer per configured network from a PEM key and an RPC URL, then registers the Casper exact scheme. The limitedPaymentMotes option is the gas budget it will spend per settlement.

// services/facilitator/index.ts (trimmed) const facilitator = new x402Facilitator() .onBeforeSettle(async () => console.log('settling payment...')) .onAfterSettle(async ctx => console.log('settled', ctx)) .onSettleFailure(async ctx => console.log('settle failure', ctx)); for (const network of cfg.networks) { const key = cfg.keys[network]; // PEM + algorithm + rpcUrl, per network const signer = await buildSigner(key); // toFacilitatorCasperSigner(privateKey, rpcUrl) facilitator.register( network, new ExactCasperScheme(signer, { limitedPaymentMotes: cfg.transactionPaymentMotes }), ); } // verify(payload, requirements) -> VerifyResponse (read-only) // settle(payload, requirements) -> SettleResponse (submits the transfer on Casper)

A failed settlement is reported, not thrown past the API: when the scheme aborts, /settle returns { success: false, errorReason, network } so the resource server can answer the buyer cleanly instead of paying for an undelivered reading.

Configuration

The facilitator is keyed per network. The env-var suffix for each network is its CAIP-2 id, uppercased with : and - rewritten to _, so casper:casper-test becomes CASPER_CASPER_TEST.

VariableDefaultMeaning
PORT4022Listen port.
CASPER_NETWORKScasper:casper-testComma-separated CAIP-2 networks to settle on.
SECRET_KEY_PATH_<NET>requiredPEM key path for that network (or SECRET_KEY_PEM_<NET> inline).
SECRET_KEY_ALGO_<NET>ed25519ed25519 or secp256k1.
RPCURL_<NET>requiredCasper JSON-RPC endpoint for that network.
TRANSACTION_PAYMENT_MOTES7000000000Gas budget per settlement (7 CSPR).
LOG_LEVELinfoLog verbosity.

TRANSACTION_PAYMENT_MOTES is a gas limit, and Casper testnet bills the limit you set, not the gas actually consumed, with no refund. So each settled call costs the facilitator operator up to 7 CSPR regardless of the WCSPR price. See network and contracts for the gas model.

The consumer: the payer

The consumer is any client that holds a funded WCSPR key. It signs a transfer_with_authorization (an EIP-3009-style off-chain authorization) for the exact amount, payable to the agent, and retries the request with the signature in the X-PAYMENT header. It never submits a transaction itself, so it needs no node and no gas budget, only WCSPR.

The reference client is services/consumer, which wraps fetch with wrapFetchWithPayment from @x402/fetch and an ExactCasperScheme from @make-software/casper-x402, turning the entire 402 handshake into one call.

The full payer how-to (client code, wrapping CSPR into WCSPR, reading the settlement receipt from the PAYMENT-RESPONSE header) is the pay-per-call (x402) page. This page does not repeat it; the consumer is shown here only to complete the architecture.

Economics: how read fees fund the agent

Every settled call moves a fixed amount of WCSPR from the payer to the agent. The three roles map to three distinct Casper identities, and the money flow per call is:

IdentityAccountRoleSpends per callReceives per call
Agent (payee + attester)43d7dd06...The payTo; the oracle that attested the datanothing on the rail+ FEED_PRICE_MOTES WCSPR
Facilitator signerecf70a7f...Signs and submits the settlementup to TRANSACTION_PAYMENT_MOTES CSPR (gas)nothing (no custody)
Consumer (payer)any funded WCSPR keySigns the authorizationFEED_PRICE_MOTES WCSPRthe reading + provenance

The full account hashes for each identity are on the network page.

The price knob and the gas budget are separate

The amount the buyer pays is FEED_PRICE_MOTES (default 1000000000 motes, or 1 WCSPR at 9 decimals), set on the resource server. The amount the facilitator can spend to settle it is TRANSACTION_PAYMENT_MOTES (default 7 CSPR), set on the facilitator. They are independent dials:

  • FEED_PRICE_MOTES is the revenue knob. Raise it to charge more per reading.
  • TRANSACTION_PAYMENT_MOTES is the cost ceiling per settlement (billed as a limit on testnet, not as consumption).

At the demo price the per-call WCSPR revenue is intentionally nominal ($0.001, about 1 WCSPR), below the testnet gas ceiling, because it exists to demonstrate the rail end to end. For a production deployment, FEED_PRICE_MOTES is the single value to set so that read revenue clears settlement cost.

The funding loop

The earn rail closes a loop with the autonomous agent. The same feed the agent attests on-chain is what the oracle server sells, so the agent is paid in WCSPR for its own data. During each cycle the agent’s read_x402_earnings tool reads that WCSPR balance and counts it as treasury available to reinvest. The agent then decides whether to stake the idle balance into WiseLending (CSPR to sCSPR), delegate it natively, or hold, and writes the decision to the TreasuryVault.

upstream data -> agent attests on-chain -> oracle server sells the reading over x402 ^ | | v more attestations <- agent reinvests (sCSPR yield) <- consumer pays WCSPR to the agent

The result is a self-funding oracle: selling verifiable data pays for producing it. The attestation gas, the treasury, and the yield operations are all fed by the WCSPR the rail collects. See the autonomous agent for the reinvestment cycle in detail.

Why x402 for the earn side

x402 fits the earn rail for reasons specific to an autonomous, on-chain oracle:

  • Agent-to-agent commerce. The payer is often another autonomous agent. There is no account, no API key, and no invoice: a GET either returns the data or returns a 402 that says exactly what to pay, and the client pays in one step.
  • Settlement is on-chain and final. Payment is a real WCSPR transfer on Casper, settled by the facilitator, not a promise or an off-chain credit.
  • The asset is already on Casper. WCSPR is a CEP-18 token that supports transfer_with_authorization, so the payer can authorize a transfer off-chain and let the facilitator submit it. The payer never needs gas.
  • The data is verifiable, so trust is not required. Because the sold reading carries the same source_hash the agent attested, the buyer reconciles it against the chain. The rail monetizes data whose correctness the buyer can check independently. See provenance and source hash.
Last updated on