From a87a63d75d44a1ca6241b9f5bac623a15a79304c Mon Sep 17 00:00:00 2001 From: martbost Date: Fri, 4 Sep 2026 12:51:16 -0500 Subject: [PATCH] Branded Voice copy pass, members activity panels, menu update Site copy regenerated through the bv-tester1 engine; em dashes scrubbed from all user-visible strings. /api/my/activity serves per-member earnings, referrals, and purchases from the chain index. Co-Authored-By: Claude Fable 5 --- public/assets/common.js | 5 +-- public/assets/home.js | 6 ++-- public/assets/ledger.js | 2 +- public/assets/my.js | 27 +++++++++++++--- public/assets/site.css | 2 +- public/assets/wallet.js | 2 +- public/index.html | 68 ++++++++++++++++++++--------------------- public/ledger.html | 9 +++--- public/my.html | 36 ++++++++++++++++------ server.js | 16 +++++++++- 10 files changed, 111 insertions(+), 62 deletions(-) diff --git a/public/assets/common.js b/public/assets/common.js index c88424c..8697dbd 100644 --- a/public/assets/common.js +++ b/public/assets/common.js @@ -30,14 +30,15 @@ window.IAP = (function () { + '' + '' + 'How it works' + + 'Ad packages' + 'Live ledger' - + 'My account' + + 'Members' + '…'; document.body.prepend(nav); if (c.rehearsal) { const b = document.createElement('div'); b.className = 'rehearsal'; - b.innerHTML = 'Testnet rehearsal — running on ' + c.chainName + '. Purchases use valueless test POL while we prove every payout in public.'; + b.innerHTML = 'Testnet rehearsal: running on ' + c.chainName + '. Purchases use valueless test POL while we prove every payout in public.'; document.body.prepend(b); } const a = nav.querySelector('[data-p="' + active + '"]'); diff --git a/public/assets/home.js b/public/assets/home.js index 59570b2..3da5d3e 100644 --- a/public/assets/home.js +++ b/public/assets/home.js @@ -8,7 +8,7 @@ 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.'; + 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() { @@ -33,8 +33,8 @@ 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'); + if (r.receipt.status !== '0x1') throw new Error('Transaction reverted. Check 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'); diff --git a/public/assets/ledger.js b/public/assets/ledger.js index db27772..d187171 100644 --- a/public/assets/ledger.js +++ b/public/assets/ledger.js @@ -7,7 +7,7 @@ const { events } = await (await fetch('/api/feed?n=150')).json(); feed.innerHTML = ''; - if (!events.length) feed.innerHTML = '
No activity yet — the first purchase will appear here the moment it lands.
'; + if (!events.length) feed.innerHTML = '
No activity yet. The first purchase will appear here the moment it lands.
'; for (const ev of events) feed.appendChild(IAP.feedRow(ev, c)); try { diff --git a/public/assets/my.js b/public/assets/my.js index 3233828..3a59618 100644 --- a/public/assets/my.js +++ b/public/assets/my.js @@ -16,15 +16,16 @@ $('creditLine').textContent = (me.credits || 0).toLocaleString(); const bc = me.buyerCount || 0; $('qualLine').innerHTML = '' + bc + ' qualifying buyer(s) referred
' - + (bc >= 5 ? 'Level 3 unlocked — full three-level earnings' + + (bc >= 5 ? 'Level 3 unlocked: full three-level earnings' : bc >= 2 ? 'Level 2 unlocked · ' + (5 - bc) + ' more for level 3' : (2 - bc) + ' more ≥$20 buyer(s) unlock level 2'); $('activateCard').hidden = true; $('inviteLine').textContent = location.origin + '/join/' + me.memberId; $('copyInvite').hidden = false; + loadActivity(); } else { $('posLine').innerHTML = 'Signed in as ' + me.address.slice(0, 8) + '…' + me.address.slice(-6) - + '
free member — not on-chain yet' + + '
free member, not on-chain yet' + (me.sponsorId ? '
invited by member #' + me.sponsorId : ''); $('creditLine').textContent = '0'; $('qualLine').textContent = 'Activate your payout wallet (or buy any package) to start; referrals who buy ≥$20 packages qualify you.'; @@ -34,6 +35,22 @@ } } + async function loadActivity() { + try { + const c = await IAP.getConfig(); + const a = await (await fetch('/api/my/activity')).json(); + const fill = (id, evs, empty) => { + const el = $(id); + el.innerHTML = ''; + if (!evs.length) { el.innerHTML = '
' + empty + '
'; return; } + for (const ev of evs) el.appendChild(IAP.feedRow(ev, c)); + }; + fill('earnFeed', a.earnings, 'No payouts yet. They appear here the moment one lands.'); + fill('refFeed', a.referrals, 'No referral activity yet. Share your invite link.'); + fill('buyFeed', a.purchases, 'No purchases from this wallet yet.'); + } catch (e) {} + } + $('signinBtn').addEventListener('click', async () => { try { $('signinBtn').disabled = true; @@ -51,8 +68,8 @@ const me = await (await fetch('/api/me')).json(); 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 — see the explorer.'); - IAP.status('Payout wallet activated — your invite link is live.', 'ok'); + if (r.receipt.status !== '0x1') throw new Error('Transaction reverted. Check the explorer.'); + IAP.status('Payout wallet activated. Your invite link is live.', 'ok'); await render(); } catch (e) { IAP.status('Activation failed: ' + ((e && e.message) || e), 'bad'); } finally { $('activateBtn').disabled = false; } @@ -60,7 +77,7 @@ $('copyInvite').addEventListener('click', async () => { try { await navigator.clipboard.writeText($('inviteLine').textContent); IAP.status('Link copied.', 'ok'); } - catch (e) { IAP.status('Copy failed — select and copy the link text.', 'bad'); } + catch (e) { IAP.status('Copy failed. Select and copy the link text.', 'bad'); } }); render(); diff --git a/public/assets/site.css b/public/assets/site.css index 07cf4d9..53ee7e8 100644 --- a/public/assets/site.css +++ b/public/assets/site.css @@ -13,7 +13,7 @@ a:hover{text-decoration:underline} .wrap{max-width:1020px;margin:0 auto;padding:0 18px} /* nav */ nav{border-bottom:1px solid var(--line);background:rgba(13,20,32,.92);position:sticky;top:0;z-index:10} -nav .wrap{display:flex;align-items:center;gap:22px;height:58px} +nav .wrap{display:flex;align-items:center;gap:22px;min-height:58px;flex-wrap:wrap;padding-top:6px;padding-bottom:6px} .logo{font-weight:800;font-size:19px;color:var(--ink)} .logo b{color:var(--amber)} nav .links{display:flex;gap:18px;font-size:14.5px;flex:1} diff --git a/public/assets/wallet.js b/public/assets/wallet.js index 8fddf45..fc5b88a 100644 --- a/public/assets/wallet.js +++ b/public/assets/wallet.js @@ -56,7 +56,7 @@ window.IAPWallet = (function () { if (r.result) return r.result; 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.'); } // buy: quote is read live server-side; pad 2% for oracle drift, contract // refunds every wei of excess in the same transaction. diff --git a/public/index.html b/public/index.html index b5ba621..e001655 100644 --- a/public/index.html +++ b/public/index.html @@ -2,17 +2,17 @@ -InstantAdPay — advertising that pays instantly, on-chain - +InstantAdPay: advertise and earn, locked in code +
-

Advertising that pays the people who build it — instantly, on-chain.

-

Free to join. Real ad inventory. And when anyone buys an ad package, - the payment splits to their sponsors in the same blockchain transaction — - no balances, no withdrawal requests, no company holding your money. Ever.

+

Advertise and earn. Locked in code, not promises.

+

Buy real ad packages from 5 to 250 dollars. Every purchase settles through + a smart contract you can read yourself, and your earnings land in + your own wallet before the page even refreshes.

Join free Watch payments land live @@ -20,7 +20,7 @@

-

Where every dollar goes — enforced by code, not promises

+

Where every dollar goes

50%
direct sponsor
@@ -28,25 +28,25 @@
10%
level 3
20%
platform
-

These percentages are constants in an immutable smart contract — there is no - function to change them, pause payouts, or hold funds. The contract's balance is zero after every - sale because everything is delivered the moment it arrives. Don't take our word for it: - every payment is public on the live ledger with a verify link to the blockchain.

+

Most referral programs run on a database someone can change after you promote. + This one runs on Polygon. The percentages are written into a contract nobody can touch, not even us. + Payouts split 50-20-10 across three levels plus a 20 percent platform fee, every single time, on a + public ledger where every payment has a verify link you can click.

-

🆓 Join free, earn from day one

-

Membership costs nothing. Share your link and you earn 50% of every ad package - your referrals ever buy — not once, every time. Payment arrives in your own wallet within seconds - of their purchase.

-

📣 Real advertising, on real audiences

-

Packages buy ad credits delivered across our owned network — banner, text, and - login placements seen by active members. Credits are recorded on-chain and only ever spent by - your own campaigns.

-

🔎 Qualification by performance

-

Deeper earning levels unlock by referring real buyers — 2 buyers unlock level 2, - 5 unlock level 3. No buying your way in, no timers, no demotions. When someone in your line isn't - qualified, their share passes up to the next person who is.

+

🆓 Join free. Earn from every package your referrals ever buy.

+

Sign up costs nothing. Zero. Every ad package your direct referrals buy for life + pays you 50 percent straight to your wallet. Level 2 pays 20 percent. Level 3 pays 10 percent. + No balances held, no withdrawal button, no company touching the money.

+

📣 Real ads. Real audience. Credits on-chain.

+

Your ad credits are minted on-chain when you buy. One credit equals one cent of + ad delivery across our network of sites. Banner, text, and login ads that only your campaigns + can spend.

+

🔎 Qualify by performance. Pass-ups fill the gaps.

+

Level 2 unlocks when you bring 2 buyers who have purchased 20 dollars or more. + Level 3 unlocks at 5 qualified buyers. If someone in your line is not qualified, their share passes + up to the next qualified person automatically. The contract handles it.

The ad packages

@@ -64,21 +64,21 @@

Why this is different

-

No trust required

-

Most affiliate platforms ask you to trust their dashboard number and their - payout schedule. Here there is no dashboard number to trust — your earnings arrive as blockchain - transactions to your own wallet, and the contract that sends them cannot be modified by anyone, - including us.

-

Honest about what it is

-

This is advertising with a referral program, not an investment. Nobody earns - without real ad purchases happening, and no income is guaranteed. What we guarantee is the part - code can guarantee: if a purchase happens in your line, your share reaches your wallet — instantly, - or it visibly passes to someone qualified.

+

No trust required. Your earnings are a transaction to your wallet.

+

Every other platform asks you to trust their ledger. Believe their numbers. + Wait for their withdrawal window. InstantAdPay does none of that. The smart contract pays each level + at the moment of purchase. Your earnings are a blockchain transaction landing in your own wallet. + You can verify every single one on the live ledger with your own eyes.

+

It is an ad service. That is the only thing it is.

+

This is an advertising platform with a referral program. Plain and simple. + You buy ad credits. You get ads delivered. You refer other advertisers and earn from what they spend. + There is no investment pool, no ROI claim, no income promise. What the code guarantees is what the + code does: split the money and pay it out. That is it.

InstantAdPay · every payment verifiable on-chain · live ledger · view the contract ↗
-
Advertising services with a performance referral program. Not an investment product; no income guarantees. Crypto transactions are irreversible — never spend what you cannot afford.
+
Advertising services with a performance referral program. Not an investment product; no income guarantees. Crypto transactions are irreversible. Never spend what you cannot afford.
diff --git a/public/ledger.html b/public/ledger.html index 3ee74a2..da5beca 100644 --- a/public/ledger.html +++ b/public/ledger.html @@ -2,17 +2,16 @@ -Live ledger — InstantAdPay +Live ledger | InstantAdPay
-

The live ledger

-

This feed is not our database — it is the blockchain itself, decoded. - Every line has a verify link that opens the raw transaction. If it's not here, it didn't happen; - if it is here, nobody can undo it.

+

The ledger does not lie.

+

This page streams every payment the contract has ever made. If it is not here, + it did not happen. Every line carries a verify link straight to the block explorer. Go click one.

connecting…

diff --git a/public/my.html b/public/my.html index 80f52b1..078c86f 100644 --- a/public/my.html +++ b/public/my.html @@ -2,21 +2,21 @@ -My account — InstantAdPay +My account | InstantAdPay

My account

-

One free wallet signature signs you in — it cannot move funds or approve anything. - No email, no password.

+

Sign in with one free wallet signature. No email. No password. + No account to create. The signature is free and cannot move funds.

Sign in with your wallet

New here? The same button creates your free membership. Your earnings always go - straight to this wallet — we never hold them.

+ straight to this wallet. We never hold them.

@@ -32,7 +32,7 @@
diff --git a/server.js b/server.js index 9123cb5..ef831b2 100644 --- a/server.js +++ b/server.js @@ -30,7 +30,7 @@ function siteConfig() { try { saved = JSON.parse(fs.readFileSync(SITE_FILE, 'utf8')); } catch (e) {} return Object.assign({ siteName: 'InstantAdPay', - tagline: 'Advertising that pays the people who build it — instantly, on-chain.', + tagline: 'Advertise and earn. Locked in code, not promises.', rehearsal: true // shows the testnet banner; flipped off at mainnet launch }, saved); } @@ -172,6 +172,20 @@ const server = http.createServer(async (req, res) => { return json(res, 200, out); } + if (p === '/api/my/activity' && req.method === 'GET') { + const s = auth.fromRequest(req); + if (!s) return json(res, 401, { error: 'Sign in first.' }); + const id = s.memberId || await auth.refreshMemberId(s); + if (!id) return json(res, 200, { memberId: 0, earnings: [], purchases: [], referrals: [] }); + const evs = chain.recentEvents(600); + return json(res, 200, { + memberId: id, + earnings: evs.filter(e => (e.type === 'TierPaid' && e.recipientId === id) || (e.type === 'AwardPaid' && e.toId === id)), + purchases: evs.filter(e => e.type === 'Purchase' && e.buyerId === id), + referrals: evs.filter(e => (e.type === 'MemberActivated' && e.sponsorId === id) || (e.type === 'BuyerCounted' && e.sponsorId === id)) + }); + } + // -- admin (Bearer ADMIN_PASSWORD) if (p === '/api/admin/site' && req.method === 'PATCH') { if (!isAdmin(req)) return json(res, 401, { error: 'auth' });