Referrals pay only for people PolHunter actually sent
The floor already blocked anyone who existed in InstantAdPay before the mission. It did NOT ask who brought them. A member who joined off an email, a banner or another site and only later wandered over to PolHunter still earned their sponsor a bounty, which is the case Marty called out: "not just members that come on board IAP and work their way over to POL Hunter." The proof is InstantAdPay's own first-touch source, handed across signed in the sign-in payload. A PolHunter share link stamps it polhunter.com from the URL itself, so a stripped referrer (in-app browser, a link pasted into chat) does not lose a genuine referral. Fails closed, and only an explicit '0' can disable it: no origin on file pays nobody, and a typo in the setting leaves the gate standing. The board says the same thing the payout code does. Somebody who joined another way now reads "joined InstantAdPay some other way, not through your link" instead of sitting there looking like a bounty that never arrives. Of the one hunter currently past the floor, linkmohd arrived direct, so under the live rules they would have paid opgnetwerk a bounty PolHunter never earned. That stops now. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+23
-3
@@ -29,6 +29,8 @@ const DEFAULTS = {
|
|||||||
// existed before. That's why we're doing it."). Anyone whose account predates this moment was
|
// existed before. That's why we're doing it."). Anyone whose account predates this moment was
|
||||||
// already a member, by definition, and can never earn their sponsor a bounty or a match.
|
// already a member, by definition, and can never earn their sponsor a bounty or a match.
|
||||||
refNewAfter: '2026-09-23T10:00:00Z',
|
refNewAfter: '2026-09-23T10:00:00Z',
|
||||||
|
refRequireOrigin: 1, // only pay for members PolHunter actually sent (joinedRef)
|
||||||
|
|
||||||
refNewDays: 30, // secondary: a newcomer only earns their sponsor a bounty in their first
|
refNewDays: 30, // secondary: a newcomer only earns their sponsor a bounty in their first
|
||||||
// month, so a dormant signup cannot trigger one a year later
|
// month, so a dormant signup cannot trigger one a year later
|
||||||
refCapPol: 20, // referral pool per Central day, separate from the find pool
|
refCapPol: 20, // referral pool per Central day, separate from the find pool
|
||||||
@@ -54,6 +56,7 @@ function seen(claims) {
|
|||||||
if (claims.wallet) cur.wallet = norm(claims.wallet);
|
if (claims.wallet) cur.wallet = norm(claims.wallet);
|
||||||
if (claims.sponsorRef) cur.sponsorRef = norm(claims.sponsorRef);
|
if (claims.sponsorRef) cur.sponsorRef = norm(claims.sponsorRef);
|
||||||
if (claims.joinedAt) cur.joinedAt = Number(claims.joinedAt);
|
if (claims.joinedAt) cur.joinedAt = Number(claims.joinedAt);
|
||||||
|
if (claims.joinedRef) cur.joinedRef = String(claims.joinedRef).toLowerCase();
|
||||||
cur.lastSeen = Date.now();
|
cur.lastSeen = Date.now();
|
||||||
h[id] = cur;
|
h[id] = cur;
|
||||||
return h;
|
return h;
|
||||||
@@ -130,6 +133,16 @@ function onFind(member, find) {
|
|||||||
const floor = Date.parse(String(c.refNewAfter || ''));
|
const floor = Date.parse(String(c.refNewAfter || ''));
|
||||||
if (!Number.isFinite(floor) || floor <= 0) return [];
|
if (!Number.isFinite(floor) || floor <= 0) return [];
|
||||||
if (!me.joinedAt || Number(me.joinedAt) < floor) return [];
|
if (!me.joinedAt || Number(me.joinedAt) < floor) return [];
|
||||||
|
// AND PolHunter has to have actually sent them. The account being new is not enough: somebody who
|
||||||
|
// joined InstantAdPay off an email, a banner or another site and only later wandered over here was
|
||||||
|
// never a PolHunter acquisition, and paying a bounty for them defeats the point (Marty,
|
||||||
|
// 2026-09-24). The proof is InstantAdPay's first-touch source, handed over signed in the sign-in
|
||||||
|
// payload; a share link stamps it polhunter.com from the URL itself, so a stripped referrer does
|
||||||
|
// not lose a genuine referral. Fails closed: no origin on file pays nobody.
|
||||||
|
// only an explicit '0' turns this off: a typo or a stray value must leave the gate standing,
|
||||||
|
// the same way the floor does
|
||||||
|
if (String(c.refRequireOrigin) !== '0'
|
||||||
|
&& !/polhunter/i.test(String(me.joinedRef || ''))) return [];
|
||||||
const who = { forMemberId: id, forName: me.username || ('#' + id) };
|
const who = { forMemberId: id, forName: me.username || ('#' + id) };
|
||||||
|
|
||||||
// the bounty, once, on their first find, and only while they are genuinely a new member
|
// the bounty, once, on their first find, and only while they are genuinely a new member
|
||||||
@@ -165,10 +178,13 @@ function state(member) {
|
|||||||
// the same floor onFind pays by, so the card can never promise an earning it will not make
|
// the same floor onFind pays by, so the card can never promise an earning it will not make
|
||||||
const floor = Date.parse(String(c.refNewAfter || ''));
|
const floor = Date.parse(String(c.refNewAfter || ''));
|
||||||
const gateOk = Number.isFinite(floor) && floor > 0;
|
const gateOk = Number.isFinite(floor) && floor > 0;
|
||||||
|
const needOrigin = String(c.refRequireOrigin) !== '0';
|
||||||
const mine = broughtBy(id).map(x => {
|
const mine = broughtBy(id).map(x => {
|
||||||
const theirFinds = store.read('payouts', []).filter(p => Number(p.memberId) === Number(x.memberId) && !p.ref && !p.prize && p.status !== 'failed');
|
const theirFinds = store.read('payouts', []).filter(p => Number(p.memberId) === Number(x.memberId) && !p.ref && !p.prize && p.status !== 'failed');
|
||||||
const paid = bountyPaidFor(x.memberId);
|
const paid = bountyPaidFor(x.memberId);
|
||||||
const isNew = !!(gateOk && x.joinedAt && Number(x.joinedAt) >= floor);
|
const viaHunt = /polhunter/i.test(String(x.joinedRef || ''));
|
||||||
|
// qualifying means BOTH: new to InstantAdPay, and sent here by PolHunter
|
||||||
|
const isNew = !!(gateOk && x.joinedAt && Number(x.joinedAt) >= floor && (!needOrigin || viaHunt));
|
||||||
return {
|
return {
|
||||||
name: x.username || ('#' + x.memberId),
|
name: x.username || ('#' + x.memberId),
|
||||||
// when they actually joined InstantAdPay, not when this directory first noticed them:
|
// when they actually joined InstantAdPay, not when this directory first noticed them:
|
||||||
@@ -177,8 +193,12 @@ function state(member) {
|
|||||||
finds: theirFinds.length,
|
finds: theirFinds.length,
|
||||||
// an account that predates the mission was already a member: say so plainly rather than
|
// an account that predates the mission was already a member: say so plainly rather than
|
||||||
// show them as 'hunting' next to a bounty that will never arrive
|
// show them as 'hunting' next to a bounty that will never arrive
|
||||||
isNew,
|
isNew, viaHunt,
|
||||||
state: !isNew ? 'already a member before the mission, earns nothing'
|
// say exactly which condition they miss, so nobody waits on a bounty that will not come
|
||||||
|
state: !isNew
|
||||||
|
? (gateOk && x.joinedAt && Number(x.joinedAt) < floor
|
||||||
|
? 'already a member before the mission, earns nothing'
|
||||||
|
: 'joined InstantAdPay some other way, not through your link')
|
||||||
: paid ? 'earning' : theirFinds.length ? 'hunting' : 'signed up, no find yet',
|
: paid ? 'earning' : theirFinds.length ? 'hunting' : 'signed up, no find yet',
|
||||||
stillNew: isNew && (Date.now() - Number(x.joinedAt)) / 86400000 <= Number(c.refMatchDays),
|
stillNew: isNew && (Date.now() - Number(x.joinedAt)) / 86400000 <= Number(c.refMatchDays),
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user