Credits: reserve live campaign budgets so purchased credits can't be over-committed; burner dry-runs and skips reverting burns; coaching flags directs not bound to you on-chain

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-10 07:50:59 -05:00
parent 9ebb9a86b2
commit 7374dc8f1b
5 changed files with 15 additions and 6 deletions
+6 -1
View File
@@ -61,16 +61,21 @@ async function describe(acct, now = Date.now()) {
const stalled = rung < 6 && quietDays >= STALL_DAYS;
const R = RUNGS[rung];
return { rung, label: R.label, next: R.next, say: R.say, quietDays, stalled, buyerCount: mm ? mm.buyerCount : 0,
counted: !!(mm && mm.countedAsBuyer), joined: acct.created, lastSeen: acct.lastSeen || 0 };
counted: !!(mm && mm.countedAsBuyer), joined: acct.created, lastSeen: acct.lastSeen || 0, onchainSponsorId: mm ? mm.sponsorId : null };
}
// coaching view for a sponsor: every direct, ladder rung, stalled flag, what to say
async function coachView(email) {
const levels = await accounts.downline(email, 1);
const directs = levels.length ? levels[0].members : [];
const me = await accounts.byEmail(email);
const myId = me ? (me.memberId || 0) : 0;
const now = Date.now();
const out = [];
for (const d of directs) {
const c = await describe(d, now);
// bound: the contract pays whoever the member registered under. A direct who activated with
// no sponsor (or a different one) is in this line on the site but pays this member nothing.
c.bound = c.onchainSponsorId == null ? null : (myId > 0 && c.onchainSponsorId === myId);
out.push(Object.assign({ email: d.email, name: d.username ? '@' + d.username : (d.memberId ? 'member #' + d.memberId : d.email.replace(/^(.).*(@.*)$/, '$1***$2')), memberId: d.memberId || 0 }, c));
}
// most actionable first: stalled lowest rung, then quiet days