My line: POL earned from each person; wallet picker features non-Trust wallets first
- /api/my/line sums TierPaid events per buyer for the signed-in member; the downline rows show "+X POL" (what that person has paid you so far). - AppKit featuredWalletIds: MetaMask, Phantom, SafePal, Coinbase first; Trust Wallet stays available under All wallets. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -949,6 +949,8 @@
|
|||||||
'<div class="lin-lvl"><div class="cap">Level ' + L.level + ' · ' + L.members.length + (L.level === 1 ? ' direct' : '') + '</div>'
|
'<div class="lin-lvl"><div class="cap">Level ' + L.level + ' · ' + L.members.length + (L.level === 1 ? ' direct' : '') + '</div>'
|
||||||
+ L.members.map(m => '<div class="lin-row"><span class="nm">' + esc(m.name) + '</span>'
|
+ L.members.map(m => '<div class="lin-row"><span class="nm">' + esc(m.name) + '</span>'
|
||||||
+ (m.email ? '<span class="em">' + esc(m.email) + '</span>' : '<span class="id">#' + m.memberId + '</span>')
|
+ (m.email ? '<span class="em">' + esc(m.email) + '</span>' : '<span class="id">#' + m.memberId + '</span>')
|
||||||
|
+ '<span class="earn' + (m.earnedWei && m.earnedWei !== '0' ? ' on' : '') + '" title="POL this person has paid you so far">'
|
||||||
|
+ (m.earnedWei && m.earnedWei !== '0' ? '+' + IAP.fmtPol(m.earnedWei) + ' POL' : '0.00 POL') + '</span>'
|
||||||
+ '<span class="dt">' + new Date(m.joined).toLocaleDateString() + '</span>'
|
+ '<span class="dt">' + new Date(m.joined).toLocaleDateString() + '</span>'
|
||||||
+ (m.email ? '<button class="btn sec small chat-msg-btn" type="button" data-cemail="' + esc(m.email) + '" data-cname="' + esc(m.name) + '">Message</button>' : '')
|
+ (m.email ? '<button class="btn sec small chat-msg-btn" type="button" data-cemail="' + esc(m.email) + '" data-cname="' + esc(m.name) + '">Message</button>' : '')
|
||||||
+ '</div>').join('')
|
+ '</div>').join('')
|
||||||
|
|||||||
@@ -406,7 +406,7 @@ textarea{resize:vertical;font:inherit}
|
|||||||
.lin-lvl{margin:10px 0}
|
.lin-lvl{margin:10px 0}
|
||||||
.lin-lvl>.cap{display:inline-block;font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;
|
.lin-lvl>.cap{display:inline-block;font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;
|
||||||
color:var(--mint);background:var(--mint-soft);border:1px solid var(--line-strong);border-radius:8px;padding:4px 10px;margin-bottom:10px}
|
color:var(--mint);background:var(--mint-soft);border:1px solid var(--line-strong);border-radius:8px;padding:4px 10px;margin-bottom:10px}
|
||||||
.lin-row{display:grid;grid-template-columns:minmax(110px,1.2fr) minmax(0,2fr) auto auto;gap:6px 14px;
|
.lin-row{display:grid;grid-template-columns:minmax(110px,1.2fr) minmax(0,2fr) auto auto auto;gap:6px 14px;
|
||||||
align-items:center;padding:9px 0;border-bottom:1px solid var(--line)}
|
align-items:center;padding:9px 0;border-bottom:1px solid var(--line)}
|
||||||
.lin-row .nm{font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
.lin-row .nm{font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||||
.lin-row .em{font-size:12px;color:var(--mint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
.lin-row .em{font-size:12px;color:var(--mint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
||||||
@@ -606,3 +606,6 @@ img{max-width:100%}
|
|||||||
.obj .lab-say{color:var(--amber)}
|
.obj .lab-say{color:var(--amber)}
|
||||||
.obj-truth p{margin:0;font-size:14.5px;color:var(--ink)}
|
.obj-truth p{margin:0;font-size:14.5px;color:var(--ink)}
|
||||||
.obj-say{margin:0}
|
.obj-say{margin:0}
|
||||||
|
|
||||||
|
.lin-row .earn{font-family:var(--mono);font-size:12px;color:var(--muted);white-space:nowrap;font-variant-numeric:tabular-nums}
|
||||||
|
.lin-row .earn.on{color:var(--mint);font-weight:700}
|
||||||
|
|||||||
+10
-1
@@ -49,7 +49,16 @@ window.IAPWallet = (function () {
|
|||||||
adapters: [wagmiAdapter], networks: allNets, projectId, defaultNetwork: net,
|
adapters: [wagmiAdapter], networks: allNets, projectId, defaultNetwork: net,
|
||||||
metadata: { name: c.siteName || 'InstantAdPay', description: c.tagline || 'Advertise and earn, paid on-chain.',
|
metadata: { name: c.siteName || 'InstantAdPay', description: c.tagline || 'Advertise and earn, paid on-chain.',
|
||||||
url: location.origin, icons: [location.origin + '/logo-icon.png'] },
|
url: location.origin, icons: [location.origin + '/logo-icon.png'] },
|
||||||
features: { analytics: false, email: false, socials: [] }
|
features: { analytics: false, email: false, socials: [] },
|
||||||
|
// Picker order: wallets without Trust's balance-proportion block go first.
|
||||||
|
// Trust Wallet is NOT excluded; it just drops out of the featured row into
|
||||||
|
// "All wallets" (Marty, 2026-09-09: move Trust to the bottom, not off).
|
||||||
|
featuredWalletIds: [
|
||||||
|
'c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96', // MetaMask
|
||||||
|
'a797aa35c0fadbfc1a53e7f675162ed5226968b44a19ee3d24385c64d1d3c393', // Phantom
|
||||||
|
'0b415a746fb9ee99cce155c2ceca0c6f6061b1dbca2d722b3ba16381d0562150', // SafePal
|
||||||
|
'fd20dc426fb37566d803205b19bbc1d4096b248ac04548e3cfb6b3a38bd033aa' // Coinbase Wallet
|
||||||
|
]
|
||||||
});
|
});
|
||||||
return modal;
|
return modal;
|
||||||
})();
|
})();
|
||||||
|
|||||||
+1
-1
@@ -439,7 +439,7 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<script src="/assets/common.js?v=20260909a"></script>
|
<script src="/assets/common.js?v=20260909a"></script>
|
||||||
<script src="/assets/wallet.js?v=20260909b"></script>
|
<script src="/assets/wallet.js?v=20260909c"></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>
|
||||||
|
|||||||
+4
-4
@@ -5,7 +5,7 @@
|
|||||||
<title>Member area | InstantAdPay</title>
|
<title>Member area | InstantAdPay</title>
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
|
||||||
<link rel="icon" type="image/png" href="/logo-icon.png">
|
<link rel="icon" type="image/png" href="/logo-icon.png">
|
||||||
<link rel="stylesheet" href="/assets/site.css?v=20260909a">
|
<link rel="stylesheet" href="/assets/site.css?v=20260909b">
|
||||||
</head>
|
</head>
|
||||||
<body class="bo-body">
|
<body class="bo-body">
|
||||||
|
|
||||||
@@ -283,7 +283,7 @@
|
|||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h3>Your downline, three levels deep</h3>
|
<h3>Your downline, three levels deep</h3>
|
||||||
<p class="muted small">Everyone below you across levels 1–3. You see email addresses for your
|
<p class="muted small">Everyone below you across levels 1–3. The POL figure is what each person has paid you so far, straight from the ledger. You see email addresses for your
|
||||||
direct referrals only; deeper levels show username and ID. Message your direct referrals right here.</p>
|
direct referrals only; deeper levels show username and ID. Message your direct referrals right here.</p>
|
||||||
<div id="lineageWrap"><p class="muted small">Loading…</p></div>
|
<div id="lineageWrap"><p class="muted small">Loading…</p></div>
|
||||||
</div>
|
</div>
|
||||||
@@ -737,9 +737,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="/assets/common.js?v=20260909a"></script>
|
<script src="/assets/common.js?v=20260909a"></script>
|
||||||
<script src="/assets/wallet.js?v=20260909b"></script>
|
<script src="/assets/wallet.js?v=20260909c"></script>
|
||||||
<script src="/assets/promo.js?v=20260909b"></script>
|
<script src="/assets/promo.js?v=20260909b"></script>
|
||||||
<script src="/assets/my.js?v=20260909f"></script>
|
<script src="/assets/my.js?v=20260909g"></script>
|
||||||
<script src="/assets/chat.js?v=20260907l"></script>
|
<script src="/assets/chat.js?v=20260907l"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -872,11 +872,22 @@ const server = http.createServer(async (req, res) => {
|
|||||||
const s = await auth.fromRequest(req);
|
const s = await auth.fromRequest(req);
|
||||||
if (!s || !s.email) return json(res, 401, { error: 'Sign in first.' });
|
if (!s || !s.email) return json(res, 401, { error: 'Sign in first.' });
|
||||||
const levels = await accounts.downline(s.email, 3);
|
const levels = await accounts.downline(s.email, 3);
|
||||||
|
// what each person has paid THIS member so far: sum of TierPaid events where
|
||||||
|
// this member is the recipient and that person is the buyer (all indexed events)
|
||||||
|
const myId = await auth.refreshMemberId(s);
|
||||||
|
const earnedBy = {};
|
||||||
|
if (myId) {
|
||||||
|
for (const ev of chain.recentEvents(1e9)) {
|
||||||
|
if (ev.type === 'TierPaid' && ev.recipientId === myId && ev.buyerId)
|
||||||
|
earnedBy[ev.buyerId] = (BigInt(earnedBy[ev.buyerId] || '0') + BigInt(ev.amountWei)).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
const out = levels.map(L => ({ level: L.level, members: L.members.map(m => ({
|
const out = levels.map(L => ({ level: L.level, members: L.members.map(m => ({
|
||||||
memberId: m.memberId || 0,
|
memberId: m.memberId || 0,
|
||||||
name: m.username ? '@' + m.username : m.memberId ? 'member #' + m.memberId : 'member',
|
name: m.username ? '@' + m.username : m.memberId ? 'member #' + m.memberId : 'member',
|
||||||
email: L.level === 1 ? m.email : null, // directs only
|
email: L.level === 1 ? m.email : null, // directs only
|
||||||
joined: m.created })) }));
|
joined: m.created,
|
||||||
|
earnedWei: (m.memberId && earnedBy[m.memberId]) || '0' })) }));
|
||||||
return json(res, 200, { levels: out, counts: out.map(L => L.members.length) });
|
return json(res, 200, { levels: out, counts: out.map(L => L.members.length) });
|
||||||
}
|
}
|
||||||
// -- broadcast a message to your downline (1/day), on-site inbox + email
|
// -- broadcast a message to your downline (1/day), on-site inbox + email
|
||||||
|
|||||||
Reference in New Issue
Block a user