Fix credits showing 0 + purchase confirmation email

- chain.rpc(): retry the RPC pool 3 rounds with backoff. Public Amoy nodes
  routinely return transient "Temporary internal error. Please retry" on
  eth_call; a single miss was silently surfacing as 0 credits / chainReadError
  on the dashboard even when the buy succeeded on-chain.
- emailOnEvent: send a purchase confirmation on the Purchase event — credits
  added, new ad-credit balance, POL paid, and a link to view the tx on the
  explorer. Fires server-side for every wallet and the Mini App.
- Added a third Amoy RPC (tenderly) to the volume config for read redundancy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-08 10:26:53 -05:00
parent 09804cda22
commit 8958a9d145
2 changed files with 24 additions and 5 deletions
+13 -1
View File
@@ -277,7 +277,19 @@ async function emailOnEvent(ev) {
const a = await accounts.byMemberId(memberId);
if (a && a.email) mailer.send(a.email, subject, body + '\n\nSee it on the live ledger: https://instantadpay.com/ledger\n\nInstantAdPay').catch(() => {});
};
if (ev.type === 'TierPaid') await notify(ev.recipientId, 'You just got paid on InstantAdPay', 'A level-' + ev.tier + ' payout of ' + weiToPol(ev.amountWei) + ' POL just landed in your wallet.');
if (ev.type === 'Purchase') {
const cc = chain.getConfig();
const txUrl = (cc.explorer ? cc.explorer.replace(/\/+$/, '') : 'https://amoy.polygonscan.com') + '/tx/' + ev.tx;
let bal = ev.creditAmount;
try { bal = await chain.creditBalance(ev.buyerId, ev.creditType); } catch (e) {}
await notify(ev.buyerId, 'Your InstantAdPay purchase is confirmed',
'Your purchase is complete and settled on-chain.\n\n' +
'Ad credits added: ' + ev.creditAmount + '\n' +
'Your ad-credit balance is now: ' + bal + '\n' +
'Amount paid: ' + weiToPol(ev.paidWei) + ' POL\n\n' +
'View your transaction on the blockchain:\n' + txUrl);
}
else if (ev.type === 'TierPaid') await notify(ev.recipientId, 'You just got paid on InstantAdPay', 'A level-' + ev.tier + ' payout of ' + weiToPol(ev.amountWei) + ' POL just landed in your wallet.');
else if (ev.type === 'AwardPaid') await notify(ev.toId, 'You just got paid on InstantAdPay', weiToPol(ev.amountWei) + ' POL just landed in your wallet.');
else if (ev.type === 'PassedUp') await notify(ev.skippedId, 'A payout passed you by on InstantAdPay', 'A level-' + ev.tier + ' payout passed you by because you were not qualified yet. Get qualified so you catch the next one.');
}