Skip to content

Commit b2958c6

Browse files
ralyodioclaude
andcommitted
Return the sale promise, so the write lands before the receipt
The gateway awaits onSale before sending the buyer's receipt (its JSDoc said otherwise; profullstack/x402-gateway#5 fixes the comment and tests the behaviour). Dropping the promise made the write fire and forget, which is fine while a long-lived server keeps running and silently loses the sale anywhere the runtime can stop once the response is sent. Returning it makes the sale land first. A rejection is still swallowed by the gateway, so a database failure never costs a buyer the pass it paid for. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0144uEVbZK3jdaQkwcLYTXPE
1 parent d6076bf commit b2958c6

1 file changed

Lines changed: 19 additions & 14 deletions

File tree

‎apps/web/src/app.js‎

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -215,21 +215,26 @@ const crawlGateway = createGateway({
215215
/*
216216
* Write the sale down. Until now a pass existed only for as long as the
217217
* response took to send, so neither "what did this earn" nor "who is the
218-
* customer" could be answered afterwards. Never awaited into the answer: a
219-
* bookkeeping failure must not fail a payment the buyer already made.
218+
* customer" could be answered afterwards.
219+
*
220+
* The promise is returned rather than dropped: the gateway awaits this hook
221+
* before the receipt goes out, so returning it is what makes the sale land
222+
* before the buyer is told it succeeded. The gateway swallows a rejection,
223+
* so a database failure still sells the pass it was paid for.
220224
*/
221-
onSale: (sale) => {
222-
q.recordCrawlSale({
223-
payer: sale.payer,
224-
ref: sale.ref,
225-
days: sale.days,
226-
priceCents: sale.priceCents,
227-
totalCents: sale.totalCents,
228-
currency: sale.currency,
229-
userAgent: sale.userAgent,
230-
expiresAt: sale.expiresAt,
231-
}).catch((err) => console.error('[x402] could not record the sale', err));
232-
},
225+
onSale: (sale) =>
226+
q
227+
.recordCrawlSale({
228+
payer: sale.payer,
229+
ref: sale.ref,
230+
days: sale.days,
231+
priceCents: sale.priceCents,
232+
totalCents: sale.totalCents,
233+
currency: sale.currency,
234+
userAgent: sale.userAgent,
235+
expiresAt: sale.expiresAt,
236+
})
237+
.catch((err) => console.error('[x402] could not record the sale', err)),
233238
});
234239
/*
235240
* Count what the wall turns away, before it answers.

0 commit comments

Comments
 (0)