Sponsor hold: a named sponsor that cannot be paid (payouts off, chain lookup failed, unknown) blocks the first purchase and activation with a message and alerts the admin, instead of silently crediting the company

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-14 21:00:27 -05:00
parent 1533d377cc
commit f155a8cc24
4 changed files with 37 additions and 10 deletions
+9
View File
@@ -1933,6 +1933,7 @@
if (cur !== wantAddr) throw new Error('Your wallet connected as ' + cur.slice(0, 6) + '…' + cur.slice(-4) + ' but you chose ' + wantAddr.slice(0, 6) + '…' + wantAddr.slice(-4) + '. Switch accounts in your wallet app and try again.');
}
const spNow = fromPos ? { sponsorId: meNow.memberId } : await jretry('/api/sponsor');
if (!fromPos && !meNow.memberId && spNow.sponsorBlocked) { IAP.status(sponsorHoldText(spNow), 'bad'); return; } // first activation must not hand a sponsored member to the company
// pre-flight: stop early if the POL is not there. Trust Wallet also hard-blocks any
// transaction that spends most of the balance ("drain your wallet"), so Trust users
// get a heads-up first; other wallets go straight to the confirmation.
@@ -2169,8 +2170,16 @@
IAP.status('Disconnecting — reloading…', 'ok');
setTimeout(() => location.reload(), 900);
}));
// a named sponsor that cannot be paid right now: hold the transaction and say why (never credit the company by default)
function sponsorHoldText(sp) {
const who = sp.sponsorName || 'your sponsor';
if (sp.sponsorBlocked === 'notActivated') return who + ' has not switched on payouts yet, so this purchase would credit the company instead of them. Ask them to switch on payouts (Wallet tab, one free transaction), then try again.';
if (sp.sponsorBlocked === 'rpc') return 'Could not confirm your sponsor on the chain just now. Try again in a minute; nothing was charged.';
return 'Your sponsor link could not be matched to a member. Message support before buying so ' + who + ' gets credit.';
}
$('activateBtn').addEventListener('click', busy($('activateBtn'), async () => {
const me = await (await fetch('/api/me')).json();
if (me.sponsorBlocked) { IAP.status(sponsorHoldText(me), 'bad'); return; }
IAP.status('Confirm the free activation in your wallet…');
const r = await IAPWallet.activate(me.sponsorId || 0);
if (r.receipt.status !== '0x1') throw new Error('Transaction reverted. Check the explorer.');
+1 -1
View File
@@ -984,7 +984,7 @@
<script src="/assets/common.js?v=20260914a"></script>
<script src="/assets/wallet.js?v=20260911a"></script>
<script src="/assets/promo.js?v=20260911a"></script>
<script src="/assets/my.js?v=20260914l"></script>
<script src="/assets/my.js?v=20260914m"></script>
<script src="/assets/chat.js?v=20260907l"></script>
</body>
</html>