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:
+5
-2
@@ -1223,12 +1223,15 @@
|
|||||||
// the buyer's credits are read by the member id of their LINKED wallet.
|
// 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
|
// 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.
|
// 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) {
|
if (!meNow.address) {
|
||||||
IAP.status('Link your wallet first — one quick signature…');
|
IAP.status('Link your wallet first — one quick signature…');
|
||||||
await IAPWallet.signIn();
|
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…');
|
IAP.status('Confirm the purchase in your wallet…');
|
||||||
const r = await IAPWallet.buy(Number(b.dataset.id), spNow.sponsorId || 0, b.dataset.cost);
|
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.');
|
if (r.status !== '0x1' && r.receipt && r.receipt.status !== '0x1') throw new Error('Transaction reverted.');
|
||||||
|
|||||||
@@ -109,9 +109,11 @@ window.IAPWallet = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function waitTx(hash) {
|
async function waitTx(hash) {
|
||||||
for (let i = 0; i < 60; i++) {
|
for (let i = 0; i < 90; i++) {
|
||||||
const r = await (await fetch('/api/tx/' + hash)).json();
|
try {
|
||||||
if (r.found) return { status: r.status, blockNumber: r.blockNumber };
|
const r = await (await fetch('/api/tx/' + hash)).json();
|
||||||
|
if (r.found) return { status: r.status, blockNumber: r.blockNumber };
|
||||||
|
} catch (e) { /* transient fetch failure (e.g. mobile app-switch) — keep polling */ }
|
||||||
await new Promise(res => setTimeout(res, 2500));
|
await new Promise(res => setTimeout(res, 2500));
|
||||||
}
|
}
|
||||||
throw new Error('Timed out waiting for the transaction. Check the explorer.');
|
throw new Error('Timed out waiting for the transaction. Check the explorer.');
|
||||||
|
|||||||
+1
-1
@@ -439,7 +439,7 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<script src="/assets/common.js?v=20260908c"></script>
|
<script src="/assets/common.js?v=20260908c"></script>
|
||||||
<script src="/assets/wallet.js?v=20260908k"></script>
|
<script src="/assets/wallet.js?v=20260908l"></script>
|
||||||
<script src="/assets/home.js?v=20260906m"></script>
|
<script src="/assets/home.js?v=20260906m"></script>
|
||||||
<script src="/assets/chat.js?v=20260906m"></script>
|
<script src="/assets/chat.js?v=20260906m"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
+2
-2
@@ -696,8 +696,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/assets/common.js?v=20260908c"></script>
|
<script src="/assets/common.js?v=20260908c"></script>
|
||||||
<script src="/assets/wallet.js?v=20260908k"></script>
|
<script src="/assets/wallet.js?v=20260908l"></script>
|
||||||
<script src="/assets/my.js?v=20260908k"></script>
|
<script src="/assets/my.js?v=20260908l"></script>
|
||||||
<script src="/assets/chat.js?v=20260907l"></script>
|
<script src="/assets/chat.js?v=20260907l"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user