pages / example / reseller_sale
canister coord://offchain/genie/program/reseller_sale@v1/9f78557cf1a2b9d3 · v1 · artifact root 0x9f78557cf1a2b9d34f3b327ba39d042c608f33d99dacb2987b4bab99927b3f16 · previous none (first version) · superroot at publish not sealed yet
sealed cases that reached it: 0 — sealed cases that reached this word (the store counts, never reads)
reseller sale (a .genie program) in the studio: 9 symptoms, 9 fixes
// _GENIE_RESELLER_E2E_v1_ — one sale of a reseller's builder, end to end: a child key the reseller minted buys one call through a named // exchange edge, and the layer's own answers say what happened: the agreement the call was made under, the delivery, the meter line the // call wrote, and the edge's state after it. On a Base edge the call is paid from the reseller's USDC balance under the child key's cap // (the meter line says `paid.by == "balance"`); a key payment never makes an edge live, so the edge must stay where it was. On a devnet // edge (chain 36927) the call is metered in test units and nothing is paid. // `node lang/genie/cli.mjs e2e` runs it whole: mint the child key, run `keyed_sale` under it, read the reseller's view, revoke the key. // Run the agent alone: COORD_API_KEY=<a key> node lang/genie/cli.mjs run lang/genie/examples/reseller_sale.genie \ // --input edge_id=edge_<16 hex> --input task="…" [--send] genie reseller_sale v1 about "A reseller's builder buys one call through an exchange edge under a capped child key, and the layer's answers prove the sale: agreement, delivery, meter line, edge state" agent keyed_sale is "one call through a named edge under the caller's key, read back from the edge's meter" states picked agreed called delivered fetched collected metered no_edge not_checked not_live unpaid refused not_delivered not_collected not_metered recorded_test kept_quoted promoted_by_key start picked final no_edge not_checked not_live unpaid refused not_delivered not_collected not_metered recorded_test kept_quoted promoted_by_key failed no_edge not_checked not_live unpaid refused not_delivered not_collected not_metered promoted_by_key read GET /v1/exchanges as edge pick rows where row.edge_id == input.edge_id move picked -> no_edge when not edge move picked -> not_checked when not edge.check.passed move picked -> agreed op GET /v1/exchanges/:edge_id/agreement with edge_id from edge.edge_id into agreement move agreed -> called op POST /v1/exchanges/:edge_id/call with edge_id from edge.edge_id with class from edge.class with task from input.task with tool from input.tool with args from input.args into sale effect record move called -> unpaid when sale.code == "payment_required" move called -> not_live when sale.code == "edge_not_live" move called -> not_delivered when sale.code == "not_delivered" move called -> not_delivered when sale.ok == true and not sale.delivery.status == "ready" move called -> delivered when sale.ok == true and sale.meter_line.id move called -> refused move delivered -> collected when sale.delivery.answer.text move delivered -> fetched op GET /v1/handshake/:id with id from sale.delivery.handshake_id with full from "1" into reply when sale.delivery.handshake_id move delivered -> not_collected move fetched -> collected when reply.delivery.reply_full move fetched -> not_collected move collected -> metered op GET /v1/exchanges/:edge_id/meter with edge_id from edge.edge_id with limit from "1" into lines move metered -> not_metered when not lines.lines.0.id == sale.meter_line.id move metered -> promoted_by_key when sale.sale.by == "balance" and sale.edge.promoted == true move metered -> kept_quoted when sale.sale.by == "balance" and sale.meter_line.paid.by == "balance" and sale.edge.promoted == false move metered -> recorded_test when edge.chain_id == 36927 and sale.meter_line.edge_id == edge.edge_id move metered -> not_metered say no_edge "GET /v1/exchanges lists no edge by that id" say not_checked "The edge has not passed its check: no call is sold through it" say not_live "The edge takes no calls in its state" say unpaid "The edge answered 402: the key's balance did not pay (a child key past its cap, a balance that is not USDC-funded, or no balance)" say refused "The edge refused the call before any payment: read sale.code (the agreement, the house bound, the policy)" say not_delivered "The seller's reply carried no content, or an MCP seller with several tools was called with none named (sale.delivery.tools): nothing was charged" say not_collected "The call was charged as delivered and the buyer cannot read the work: no answer in the call and no reply on its handshake" say not_metered "The call answered and its meter line cannot be read back from the edge's meter" say recorded_test "The devnet seller answered through the edge and the layer wrote one meter line in test units: nothing was paid" say kept_quoted "The call was paid from the reseller's USDC balance under the child key, delivered, metered, and the edge stayed where it was: a key payment is not an outside payer" say promoted_by_key "A key payment moved the edge: only an outside x402 payer may make an edge live" next picked agreed "Name an edge GET /v1/exchanges lists (edge_id) and the task to send" next agreed called "The call is made under the edge's agreement; a Base edge takes the key's USDC balance" next delivered collected "The buyer holds the work: a house edge answers it in the call (delivery.answer); a seller's edge holds it on the handshake, read with GET /v1/handshake/:id?full=1 under the same key" next collected metered "The meter line the call wrote is read back from GET /v1/exchanges/:edge_id/meter" knowledge symptom "the run ends at unpaid" caused_by "the child key's cap is spent, the reseller's balance is empty, or its credit is not USDC-funded" fixed_by "GET /v1/access/reseller/children shows the key's spent and left; the reseller tops up with POST /v1/access/topup" symptom "the run ends at not_collected" caused_by "the seller's reply was not held, or the key that reads it did not open the handshake" fixed_by "read GET /v1/handshake/:id?full=1 with the key that made the call; only the opener reads the reply" symptom "the run ends at not_delivered with sale.delivery.status tool_required" caused_by "the seller speaks MCP and offers several tools; a call that names none gets the tool list, which is no delivery" fixed_by "send the same task with tool and args, one of sale.delivery.tools (genie e2e --tool <name> --args <json>)" symptom "the run ends at not_metered" caused_by "another call wrote a newer meter line, or the store answered late" fixed_by "read GET /v1/exchanges/:edge_id/meter?limit=50 and find sale.meter_line.id" symptom "the run ends at promoted_by_key" caused_by "the edge was moved by a key payment" fixed_by "a defect of the layer: paid-in.cue says only an outside x402 payer makes an edge live; report it" rule "the program never holds a key: the host's call does; the e2e driver mints, uses and revokes the child key" rule "every value a step sends comes from the run's input or an answer bound before it"