No-payout positions (siteConfig.noPayoutIds, default 25): linkage only. Buy-from picker disables them, purchases from them refused, joins routed away from them and their upline chain
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -411,6 +411,7 @@ function siteConfig() {
|
||||
launchAt: '', // public launch moment, ISO 8601 with offset (e.g. 2026-09-18T19:00:00-05:00): countdown on /launch + dashboard mark
|
||||
aiCreditsPerGen: 10, aiFreeSurge: 20, aiFreeCircuit: 60, aiFreeNexus: 150, // AI Copy Engine: free generations per month by badge, then credits per generation
|
||||
memberWeeklyEmail: '0', // 1 = the weekly 'Your week on InstantAdPay' email goes to every active member, not only sponsors with a line
|
||||
noPayoutIds: '25', // positions kept for linkage only (compromised wallets): no buys signed from them, no new joins routed under them or their upline chain (Marty, 2026-09-14)
|
||||
leaderboardWeeklyPrize: '', leaderboardMonthlyPrize: '', leaderboardWeeklyCredits: '1000,500,250', leaderboardMonthlyCredits: '5000,2500,1000', leaderboardAnnounceGeneral: '1', // referral contest prizes (text shown on /leaderboard; credits granted to the winner automatically at rollover)
|
||||
legacyCreditsAdvertiser: 500, legacyCreditsEarner: 150, // welcome-back credits for listed Faucet Wave / Tier One Ads emails arriving via /from/<brand>
|
||||
geoTier1: '', // comma-separated ISO country codes; empty = built-in default (US, CA, GB, AU, NZ, IE, DE, FR, NL, SE, NO, DK, FI, CH, AT, BE)
|
||||
@@ -494,6 +495,17 @@ async function attachNames(evts) {
|
||||
// A sponsor token is a numeric chain id or a site share code. Codes resolve
|
||||
// to the referrer's CURRENT chain id, so activation any time before the
|
||||
// referral's first purchase still locks the line to them.
|
||||
// No-payout positions (siteConfig.noPayoutIds): a member id whose on-chain wallet must never be paid again.
|
||||
// A purchase pays the buyer's three uplines, so a buy from `id` is blocked when id itself or any of its three
|
||||
// uplines is listed; a join under `id` is blocked when id or its two uplines is listed (the new member's buys
|
||||
// would reach the listed wallet at tier 2 or 3). Returns the listed id that would be hit, else 0.
|
||||
function noPayoutSet() { return new Set(String(siteConfig().noPayoutIds || '').split(/[,\s]+/).map(Number).filter(n => n > 0)); }
|
||||
async function payoutChainBlocked(id, hops) {
|
||||
const bad = noPayoutSet(); if (!bad.size || !id) return 0;
|
||||
let cur = Number(id);
|
||||
for (let i = 0; i <= hops && cur; i++) { if (bad.has(cur)) return cur; let m = null; try { m = await chain.member(cur); } catch (e) { break; } cur = m ? Number(m.sponsorId) || 0 : 0; }
|
||||
return 0;
|
||||
}
|
||||
async function resolveSponsorToken(tok) {
|
||||
const t = String(tok || '').trim().toLowerCase();
|
||||
if (!t) return 0;
|
||||
@@ -828,6 +840,7 @@ const server = http.createServer(async (req, res) => {
|
||||
const acct = s && s.email ? await accounts.byEmail(s.email) : null;
|
||||
const tok = (acct && acct.sponsorRef) || parseCookies(req)['iap.sponsor'] || '';
|
||||
let sponsorId = await resolveSponsorToken(tok);
|
||||
if (sponsorId && await payoutChainBlocked(sponsorId, 2)) { console.log('sponsor routed away from no-payout chain', sponsorId); sponsorId = 0; }
|
||||
// orphan fallback: an unresolvable/absent sponsor (dead link, no link) lands
|
||||
// the new member under the configured catch position (#1) instead of root
|
||||
if (!sponsorId && (!acct || acct.memberId !== (Number(siteConfig().defaultSponsorId) || 1))) sponsorId = Number(siteConfig().defaultSponsorId) || 1;
|
||||
@@ -1012,6 +1025,7 @@ const server = http.createServer(async (req, res) => {
|
||||
const memberId = await auth.refreshMemberId(s);
|
||||
const acct = (s.email && await accounts.byEmail(s.email)) || (s.address && await accounts.byAddress(s.address)) || null;
|
||||
let sponsorId = await resolveSponsorToken((acct && acct.sponsorRef) || parseCookies(req)['iap.sponsor']);
|
||||
if (sponsorId && await payoutChainBlocked(sponsorId, 2)) sponsorId = 0;
|
||||
const _defSpon = Number(siteConfig().defaultSponsorId) || 1;
|
||||
if (!sponsorId && memberId !== _defSpon) sponsorId = _defSpon; // orphan fallback → #1 (never self-sponsor)
|
||||
if (memberId && acct && acct.memberId !== memberId) accounts.setMemberId(acct.email, memberId).catch(() => {});
|
||||
@@ -1142,6 +1156,7 @@ const server = http.createServer(async (req, res) => {
|
||||
if (id) {
|
||||
try { const mm = await chain.member(id); row.buyerCount = mm.buyerCount; row.counted = mm.countedAsBuyer; row.sponsorId = mm.sponsorId; } catch (e) {}
|
||||
row.credits = balPer[id] != null ? balPer[id] : 0;
|
||||
row.noPayout = await payoutChainBlocked(id, 3); // linkage only: a buy from here would pay a listed wallet
|
||||
}
|
||||
out.push(row);
|
||||
}
|
||||
@@ -1149,6 +1164,7 @@ const server = http.createServer(async (req, res) => {
|
||||
if (mainId) {
|
||||
main.credits = balPer[mainId] != null ? balPer[mainId] : 0;
|
||||
try { main.buyerCount = (await chain.member(mainId)).buyerCount; } catch (e) {}
|
||||
main.noPayout = await payoutChainBlocked(mainId, 3);
|
||||
}
|
||||
// live POL balances (the link signature proved the wallet is theirs) + a POL/USD rate from the catalog
|
||||
const bal = async a => { try { return BigInt(await chain.rpc('eth_getBalance', [a, 'latest'])).toString(); } catch (e) { return null; } };
|
||||
|
||||
Reference in New Issue
Block a user