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>'
|
||||
+ 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>')
|
||||
+ '<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>'
|
||||
+ (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('')
|
||||
|
||||
@@ -406,7 +406,7 @@ textarea{resize:vertical;font:inherit}
|
||||
.lin-lvl{margin:10px 0}
|
||||
.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}
|
||||
.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)}
|
||||
.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}
|
||||
@@ -606,3 +606,6 @@ img{max-width:100%}
|
||||
.obj .lab-say{color:var(--amber)}
|
||||
.obj-truth p{margin:0;font-size:14.5px;color:var(--ink)}
|
||||
.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,
|
||||
metadata: { name: c.siteName || 'InstantAdPay', description: c.tagline || 'Advertise and earn, paid on-chain.',
|
||||
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;
|
||||
})();
|
||||
|
||||
+1
-1
@@ -439,7 +439,7 @@
|
||||
</section>
|
||||
|
||||
<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/chat.js?v=20260906m"></script>
|
||||
</body>
|
||||
|
||||
+4
-4
@@ -5,7 +5,7 @@
|
||||
<title>Member area | InstantAdPay</title>
|
||||
<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="stylesheet" href="/assets/site.css?v=20260909a">
|
||||
<link rel="stylesheet" href="/assets/site.css?v=20260909b">
|
||||
</head>
|
||||
<body class="bo-body">
|
||||
|
||||
@@ -283,7 +283,7 @@
|
||||
|
||||
<div class="card">
|
||||
<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>
|
||||
<div id="lineageWrap"><p class="muted small">Loading…</p></div>
|
||||
</div>
|
||||
@@ -737,9 +737,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<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/my.js?v=20260909f"></script>
|
||||
<script src="/assets/my.js?v=20260909g"></script>
|
||||
<script src="/assets/chat.js?v=20260907l"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -872,11 +872,22 @@ const server = http.createServer(async (req, res) => {
|
||||
const s = await auth.fromRequest(req);
|
||||
if (!s || !s.email) return json(res, 401, { error: 'Sign in first.' });
|
||||
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 => ({
|
||||
memberId: m.memberId || 0,
|
||||
name: m.username ? '@' + m.username : m.memberId ? 'member #' + m.memberId : 'member',
|
||||
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) });
|
||||
}
|
||||
// -- broadcast a message to your downline (1/day), on-site inbox + email
|
||||
|
||||
Reference in New Issue
Block a user