Buy flow: survive mobile app-switch fetch drops

Mobile drops in-flight fetches when the page returns from the wallet app, which
aborted the purchase before the tx ("Failed to fetch"). Retry /api/me and
/api/sponsor, and make waitTx keep polling through transient fetch failures.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-08 10:08:34 -05:00
parent 8eedfbe6e6
commit 7d6818a8d4
4 changed files with 13 additions and 8 deletions
+5 -2
View File
@@ -1223,12 +1223,15 @@
// the buyer's credits are read by the member id of their LINKED wallet.
// If they only connected a wallet (e.g. for the faucet) but never linked
// it, link it first (one signature) so the purchase's credits show up.
const meNow = await (await fetch('/api/me')).json();
// retry these through transient failures — mobile drops in-flight
// fetches when the page returns from the wallet app-switch
const jretry = async url => { let err; for (let i = 0; i < 4; i++) { try { return await (await fetch(url)).json(); } catch (e) { err = e; await new Promise(s => setTimeout(s, 500 * (i + 1))); } } throw err; };
const meNow = await jretry('/api/me');
if (!meNow.address) {
IAP.status('Link your wallet first — one quick signature…');
await IAPWallet.signIn();
}
const spNow = await (await fetch('/api/sponsor')).json();
const spNow = await jretry('/api/sponsor');
IAP.status('Confirm the purchase in your wallet…');
const r = await IAPWallet.buy(Number(b.dataset.id), spNow.sponsorId || 0, b.dataset.cost);
if (r.status !== '0x1' && r.receipt && r.receipt.status !== '0x1') throw new Error('Transaction reverted.');