InstantAdPay site skeleton: SIWE auth, live chain ledger, join links, buy flow
Zero-dependency Node server on the RM Circle pattern. Chain config lives in the volume so the same code runs the Amoy dress rehearsal and mainnet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
// Landing page: live ladder, buy buttons, sponsor attribution line.
|
||||
(async function () {
|
||||
await IAP.renderNav('home');
|
||||
const c = await IAP.getConfig();
|
||||
IAP.$('contractLink').href = c.explorer + '/address/' + c.contract;
|
||||
|
||||
const sp = await (await fetch('/api/sponsor')).json();
|
||||
if (sp.sponsorId) {
|
||||
const el = IAP.$('sponsorLine');
|
||||
el.hidden = false;
|
||||
el.textContent = 'You were invited by member #' + sp.sponsorId + ' — your purchases pay their team, and your own link will do the same for you.';
|
||||
}
|
||||
|
||||
async function loadLadder() {
|
||||
const { products } = await (await fetch('/api/catalog')).json();
|
||||
const tb = document.querySelector('#ladder tbody');
|
||||
tb.innerHTML = '';
|
||||
const NAMES = { 1: 'Micro', 2: 'Activation', 3: 'Builder', 4: 'Growth', 5: 'Leader' };
|
||||
for (const p of products) {
|
||||
const tr = document.createElement('tr');
|
||||
tr.innerHTML = '<td><b>' + (NAMES[p.id] || 'Package ' + p.id) + '</b></td>'
|
||||
+ '<td class="num">' + IAP.fmtUsd(p.priceCents) + '</td>'
|
||||
+ '<td class="num">' + p.creditAmount.toLocaleString() + '</td>'
|
||||
+ '<td class="num mono">' + (p.costWei ? IAP.fmtPol(p.costWei) + ' POL' : 'paused') + '</td>'
|
||||
+ '<td><button class="btn small" data-id="' + p.id + '" data-cost="' + (p.costWei || '') + '"'
|
||||
+ (p.costWei ? '' : ' disabled') + '>Buy</button></td>';
|
||||
tb.appendChild(tr);
|
||||
}
|
||||
tb.querySelectorAll('button[data-id]').forEach(b => b.addEventListener('click', () => buyPack(b)));
|
||||
}
|
||||
async function buyPack(btn) {
|
||||
try {
|
||||
btn.disabled = true;
|
||||
IAP.status('Confirm the purchase in your wallet…');
|
||||
const r = await IAPWallet.buy(Number(btn.dataset.id), sp.sponsorId || 0, btn.dataset.cost);
|
||||
if (r.receipt.status !== '0x1') throw new Error('Transaction reverted — see the explorer.');
|
||||
IAP.status('Purchase settled on-chain — credits are yours, payouts delivered. Watch it on the ledger.', 'ok');
|
||||
IAP.refreshNavWallet();
|
||||
} catch (e) {
|
||||
IAP.status('Purchase failed: ' + (e.message || e), 'bad');
|
||||
} finally { btn.disabled = false; }
|
||||
}
|
||||
loadLadder();
|
||||
})();
|
||||
Reference in New Issue
Block a user