Proof feed: one message per purchase, and it says InstantAdPay
Marty, reading the feed on 25 September: "I see the level 1 payout, I see a level 2 payout, but I don't see who purchased something and what they bought." And in the main Crypto Team Build group the same lines carried no product name at all, so nobody knew what they were from. feedgroup.js composes one message from every event of a purchase transaction: the buyer and the package on top, the level payouts under it with their dollar equivalents, then who was passed over and why. It is triggered on AdminPaid, the last event the contract emits for a purchase, which is how the missed-payout notice already knows the whole transaction is indexed. Tier payouts and purchases are no longer posted one line at a time. In payouts mode a purchase that paid no member (root or unsponsored buyer) stays silent, as before. Every post now opens with the InstantAdPay header in the main group as well as the payments topic. Composed against three real transactions from the live index before shipping: three tiers, a double pass-up, and a root purchase. QA member walk: 0 bugs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -37,7 +37,8 @@ const releases = require('./releases');
|
||||
const ledger = require('./ledger');
|
||||
const videosweep = require('./videosweep');
|
||||
const sbcheck = require('./sbcheck');
|
||||
const marks = require('./marks'); // one-time claims shared across running instances (deploy overlap) // Google Safe Browsing screen on advertiser destinations
|
||||
const marks = require('./marks');
|
||||
const feedgroup = require('./feedgroup'); // one proof-feed message per purchase: buyer, package, then the tier payouts // one-time claims shared across running instances (deploy overlap) // Google Safe Browsing screen on advertiser destinations
|
||||
const updates = require('./updates');
|
||||
const audit = require('./audit'); // counter audit: views vs delivery logs, charges vs shows (Marty, 2026-09-15) // member update emails from Admin > Releases (Marty, 2026-09-14)
|
||||
const leaderboard = require('./leaderboard');
|
||||
@@ -1072,11 +1073,19 @@ async function telegramOnEvent(ev) {
|
||||
const who = id => '#' + id + (names[id] ? ' @' + names[id] : '');
|
||||
const cc = chain.getConfig();
|
||||
const tx = (cc.explorer ? cc.explorer.replace(/\/+$/, '') : 'https://polygonscan.com') + '/tx/' + ev.tx;
|
||||
const build = (mode) => {
|
||||
const build = async (mode) => {
|
||||
let line = null;
|
||||
if (ev.type === 'TierPaid') line = '\u{1F4B8} Level ' + ev.tier + ' payout: <b>' + weiToPol(ev.amountWei) + ' POL</b> \u2192 ' + who(ev.recipientId);
|
||||
// Tier payouts and the purchase itself are no longer posted one by one: they are composed
|
||||
// into ONE message on AdminPaid, the last event of every purchase tx, so the feed reads
|
||||
// "who bought what, then who was paid" (Marty, 2026-09-25). In payouts mode a purchase that
|
||||
// paid no member (root or unsponsored buyer) stays silent, as before.
|
||||
if (ev.type === 'AdminPaid') {
|
||||
const txEvents = chain.recentEvents(1e9).filter(x => x.tx === ev.tx);
|
||||
const ids = new Set(); txEvents.forEach(x => { for (const k of ['buyerId', 'recipientId', 'skippedId']) if (x[k]) ids.add(x[k]); });
|
||||
const nm = await accounts.namesForMembers([...ids]).catch(() => ({}));
|
||||
line = feedgroup.compose(txEvents, id => '#' + id + (nm[id] ? ' @' + nm[id] : ''), weiToPol, { requirePayout: mode === 'payouts' });
|
||||
}
|
||||
else if (ev.type === 'BuyerCounted' && mode !== 'payouts') line = '\u2B50 ' + who(ev.sponsorId) + ' now has <b>' + ev.newCount + '</b> qualifying buyer' + (ev.newCount === 1 ? '' : 's') + (ev.newCount === 2 ? ' \u00b7 level 2 open' : ev.newCount === 5 ? ' \u00b7 level 3 open' : '');
|
||||
else if (ev.type === 'Purchase' && mode !== 'payouts') line = '\u{1F9FE} ' + who(ev.buyerId) + ' bought a $' + Math.round(ev.priceCents / 100) + ' package';
|
||||
else if (ev.type === 'AwardPaid') line = '\u{1F4B8} Award payout: <b>' + weiToPol(ev.amountWei) + ' POL</b> \u2192 ' + who(ev.toId);
|
||||
else if (ev.type === 'MemberActivated' && mode === 'all') line = '\u{1F91D} ' + who(ev.id) + ' switched on payouts';
|
||||
if (!line) return null;
|
||||
@@ -1112,8 +1121,10 @@ async function telegramOnEvent(ev) {
|
||||
}
|
||||
}
|
||||
} catch (e) { console.error('missed-payout post', e.message); }
|
||||
if (sc.telegramChatId) { const t = build(String(sc.telegramEvents || 'payouts')); if (t) await telegramSend(sc.telegramChatId, t, sc.telegramTopicId); if (missed && String(sc.telegramEvents || 'payouts') !== 'none') await telegramSend(sc.telegramChatId, missed, sc.telegramTopicId).catch(() => {}); }
|
||||
if (sc.telegramEchoChatId) { const t = build(String(sc.telegramEchoEvents || 'payouts')); if (t) await telegramSend(sc.telegramEchoChatId, '\u{1F7E0} <b>InstantAdPay</b> \u00b7 ' + t, sc.telegramEchoTopicId); }
|
||||
// the main group used to get bare payout lines with no product name: nobody knew what they were from
|
||||
const brand = t => '\u{1F7E0} <b>InstantAdPay</b>\n' + t;
|
||||
if (sc.telegramChatId) { const t = await build(String(sc.telegramEvents || 'payouts')); if (t) await telegramSend(sc.telegramChatId, brand(t), sc.telegramTopicId); if (missed && String(sc.telegramEvents || 'payouts') !== 'none') await telegramSend(sc.telegramChatId, missed, sc.telegramTopicId).catch(() => {}); }
|
||||
if (sc.telegramEchoChatId) { const t = await build(String(sc.telegramEchoEvents || 'payouts')); if (t) await telegramSend(sc.telegramEchoChatId, brand(t), sc.telegramEchoTopicId); }
|
||||
if (missed && sc.telegramEchoChatId && String(sc.telegramEchoEvents || 'payouts') !== 'none') await telegramSend(sc.telegramEchoChatId, '\u{1F7E0} <b>InstantAdPay</b> \u00b7 ' + missed, sc.telegramEchoTopicId).catch(() => {});
|
||||
}
|
||||
// holding-tank arrivals -> one digest line in the shared payments topic (Marty, 2026-09-12): who is
|
||||
|
||||
Reference in New Issue
Block a user