Dashboard 'My Next Step' panel + funded badge

Adds a synthesized next-step panel to /my: the level ladder (you-are-here →
upgrade-next), the single clearest action (qualify vs upgrade), and a funded
badge that checks the member's wallet against their next upgrade cost.

Privacy: the wallet balance is checked server-side (chain.balanceOf via
eth_getBalance) and ONLY a funded true/false is returned — the raw balance is
never exposed on the ID-addressable dashboard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-08-17 06:33:59 -05:00
parent f4481a390b
commit a3e9d05f5d
5 changed files with 71 additions and 1 deletions
+9 -1
View File
@@ -101,6 +101,14 @@ const pol = wei => Number(wei / 1000000000000n) / 1e6; // 6-decimal POL
const encU = v => BigInt(v).toString(16).padStart(64, '0');
async function ethCall(data) { return await rpc('eth_call', [{ to: CONTRACT, data }, 'latest']); }
// Native POL balance of a wallet (public on-chain data). Used ONLY to derive a
// funded / not-funded flag for a member's next upgrade — the API never returns
// the raw balance, only the boolean, to keep members' holdings private.
async function balanceOf(address) {
if (!/^0x[0-9a-fA-F]{40}$/.test(address || '')) return null;
try { const hex = await rpc('eth_getBalance', [address, 'latest'], 6000); return Number(BigInt(hex)) / 1e18; }
catch (e) { return null; }
}
function decodeMemberStruct(r) {
// members(uint48): account, joinedAt, referrerId, uplineId, tier, level, directCount,
@@ -617,4 +625,4 @@ async function getIncome(id) {
};
}
module.exports = { startIndexer, getPayoutsPublic, verifyMember, memberLookup, memberPublic, getIncome, getOwnerUpgradeNeeds, getOrgRouting, getOrgShare, getMatrixTree, isInTeam, CONTRACT };
module.exports = { startIndexer, getPayoutsPublic, verifyMember, memberLookup, memberPublic, getIncome, getOwnerUpgradeNeeds, getOrgRouting, getOrgShare, getMatrixTree, isInTeam, balanceOf, CONTRACT };