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
+15
View File
@@ -385,6 +385,21 @@ async function handleApi(req,res,pathname){
}
}
}
// Next-step plan + funded badge. Wallet balance is checked server-side and
// ONLY the boolean (covers next upgrade?) is exposed — never the raw amount.
if(r.registered){
const lvl=r.level||1, tier=r.tier===2?2:1, qualified=(r.directCount||0)>=2;
if(!qualified){
r.nextStep={kind:'qualify',need:2-(r.directCount||0)};
}else if(lvl<8){
const cost=(r.upgradeCosts&&r.upgradeCosts[tier]&&r.upgradeCosts[tier][lvl-1])||0;
let funded=null;
try{ if(r.account&&cost){ const bal=await chain.balanceOf(r.account); if(bal!=null) funded=bal>=cost; } }catch(e){}
r.nextStep={kind:'upgrade',nextLevel:lvl+1,cost,funded};
}else{
r.nextStep={kind:'max'};
}
}
memberCache.set(id,{data:r,ts:Date.now()});
if(memberCache.size>500)memberCache.delete(memberCache.keys().next().value);
return json(res,200,r,{'Cache-Control':'public, max-age=60'});