0d2621defd
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
54 lines
3.1 KiB
JavaScript
54 lines
3.1 KiB
JavaScript
// The missed-payout notice, whole chain in one message (Marty, 2026-09-19).
|
|
//
|
|
// A purchase pays three tiers up the sponsor line. When a tier's rightful recipient is not
|
|
// qualified, the contract passes that share up until it finds someone who is, or hands it to
|
|
// the company. Every hop is an on-chain event: PassedUp (who was skipped, and why) and TierPaid
|
|
// (who finally got it, and how many hops up). Until now the Telegram notice reported one tier
|
|
// per message; this composes ONE message per purchase that shows every tier's walk, every
|
|
// person passed, and what it added up to. The point is that the people passed over see, in
|
|
// numbers, exactly what qualifying would have paid them.
|
|
//
|
|
// Pure: takes the events of one transaction plus a name resolver; returns the text or null.
|
|
'use strict';
|
|
|
|
const SHARE = { 1: 0.5, 2: 0.2, 3: 0.1 }; // tier shares of the purchase, for a tier nobody caught
|
|
const NEED = { 2: 2, 3: 5 }; // qualifying buyers a tier requires
|
|
|
|
function fmtPol(wei) {
|
|
try { return (Number(BigInt(String(wei)) / 10n ** 14n) / 1e4).toFixed(4); } catch (e) { return '0'; }
|
|
}
|
|
|
|
// txEvents: every indexed event sharing the tx. who(id) -> '#id @name'. had(id, tier) -> qualifying
|
|
// buyers that member had at the time (a number) or null when unknown.
|
|
function composeMissed(txEvents, who, had, site) {
|
|
const buy = txEvents.find(e => e.type === 'Purchase');
|
|
const skips = txEvents.filter(e => e.type === 'PassedUp');
|
|
if (!buy || !skips.length) return null;
|
|
const price = '$' + Math.round((buy.priceCents || 0) / 100);
|
|
const lines = ['\u{1F62C} <b>Missed payouts</b> on ' + who(buy.buyerId) + "'s " + price + ' purchase:'];
|
|
const passed = new Set(); let walked = 0;
|
|
for (const tier of [2, 3]) {
|
|
const sk = skips.filter(s => Number(s.tier) === tier).sort((x, y) => Number(x.li || 0) - Number(y.li || 0)); // walk order: nearest first
|
|
if (!sk.length) continue;
|
|
const paid = txEvents.find(e => e.type === 'TierPaid' && Number(e.tier) === tier);
|
|
const pol = paid ? Number(fmtPol(paid.amountWei)) : Number(fmtPol(BigInt(String(buy.paidWei || 0)) * BigInt(Math.round(SHARE[tier] * 100)) / 100n));
|
|
walked += pol;
|
|
const hops = sk.map(s => {
|
|
passed.add(s.skippedId);
|
|
let why;
|
|
if (s.reason === 'unqualified') { const n = had(s.skippedId, tier); why = (n == null ? 'not qualified' : n + ' of ' + NEED[tier] + ' qualifying buyers'); }
|
|
else if (s.reason === 'send-failed') why = 'wallet refused the payment';
|
|
else why = String(s.reason || 'passed');
|
|
return who(s.skippedId) + ' (' + why + ')';
|
|
});
|
|
const end = paid ? 'paid to ' + who(paid.recipientId) : 'nobody above was qualified, so the company kept it';
|
|
lines.push('Level ' + tier + ' · <b>' + pol.toFixed(4) + ' POL</b>: ' + hops.join(' → ') + ' → ' + end);
|
|
}
|
|
const n = passed.size;
|
|
lines.push('<b>' + walked.toFixed(4) + ' POL walked past ' + n + ' ' + (n === 1 ? 'person' : 'people') + ' on one ' + price + ' sale.</b>');
|
|
lines.push('Qualify before the next one: <a href="' + site + '">' + site.replace(/^https:\/\//, '') + '</a>');
|
|
return lines.join('\n');
|
|
}
|
|
|
|
module.exports = { composeMissed, fmtPol };
|