From a3cd5bbe237d62fd6c62ac980d16c6de36900112 Mon Sep 17 00:00:00 2001 From: holistis Date: Sun, 18 Oct 2026 11:35:47 +0200 Subject: [PATCH] Mainnet goes first, because the client picks accepts[0] Measured, not preferred. The official client takes the first entry it can satisfy, so the ORDER decides where an ordinary buyer pays. Our first real mainnet attempt settled on TESTNET with mainnet sitting in second place: no money moved, and the route was not proven either. Whoever switches real money on wants a buyer to pay real money; a tester picks the other line explicitly. With the flag off there is still exactly one entry and nothing changes here. Tests: 144 pass, with the order asserted rather than assumed. --- .../src/x402-keuring-18-okt.test.ts | 4 +++- packages/self-check-server/src/x402-seller.ts | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/self-check-server/src/x402-keuring-18-okt.test.ts b/packages/self-check-server/src/x402-keuring-18-okt.test.ts index 47ff126..9cfccb1 100644 --- a/packages/self-check-server/src/x402-keuring-18-okt.test.ts +++ b/packages/self-check-server/src/x402-keuring-18-okt.test.ts @@ -567,7 +567,9 @@ describe("de mainnet-route, standaard uit", () => { const routes = buildPaidRoutes(config) as any; const accepts = routes["POST /api/paid/verify-ownership"].accepts; expect(accepts).toHaveLength(2); - expect(accepts.map((a: { network: string }) => a.network)).toEqual([SELLER_NETWORK, MAINNET_NETWORK]); + // MAINNET VOOROP, want de officiele client kiest accepts[0]. Gemeten: onze eerste + // mainnet-poging betaalde op testnet omdat die regel vooraan stond. + expect(accepts.map((a: { network: string }) => a.network)).toEqual([MAINNET_NETWORK, SELLER_NETWORK]); // Dezelfde prijs en hetzelfde ontvangstadres op beide, anders adverteren we twee // verschillende aanbiedingen zonder dat iemand dat besloot. expect(new Set(accepts.map((a: { price: string }) => a.price)).size).toBe(1); diff --git a/packages/self-check-server/src/x402-seller.ts b/packages/self-check-server/src/x402-seller.ts index 1ce8c52..0181a3c 100644 --- a/packages/self-check-server/src/x402-seller.ts +++ b/packages/self-check-server/src/x402-seller.ts @@ -553,12 +553,13 @@ export function buildPaidRoutes(config: SellerConfig): Record { // buildOfferReceiptExtension leest context.requirements.network, dus die volgt // automatisch de regel die de koper koos. accepts: [ - { - scheme: "exact", - price: config.price, - network: SELLER_NETWORK, - payTo: config.payTo, - }, + // MAINNET VOOROP ZODRA HIJ AAN STAAT, en dat is gemeten en geen voorkeur. De + // officiele client kiest accepts[0] (zie @x402/core, getDisplayAmount en de + // selectie eromheen), dus de ORDE bepaalt waar een gewone koper betaalt. Onze + // eerste mainnet-poging ging daardoor over testnet, met mainnet op plek twee. + // Wie echt geld aanzet, wil dat een koper echt geld betaalt; een tester kiest + // de andere regel expliciet. Staat mainnet uit, dan is er maar een regel en + // verandert hier niets. ...(config.mainnet ? [ { @@ -569,6 +570,12 @@ export function buildPaidRoutes(config: SellerConfig): Record { }, ] : []), + { + scheme: "exact", + price: config.price, + network: SELLER_NETWORK, + payTo: config.payTo, + }, ], description: "Ownership verification with a signed receipt. The receipt is the product: the same answer is available for free at /api/verify-ownership.",