diff --git a/snapshot.js b/snapshot.js
index 25234e0..0c95317 100644
--- a/snapshot.js
+++ b/snapshot.js
@@ -19,7 +19,8 @@ async function gather(now = Date.now()) {
const since = now - DAY, prior = now - 2 * DAY;
const s = { signups: 0, signupsPrior: 0, members: 0, wallets: 0, payoutsOn: 0, seen24h: 0,
campaigns: 0, advertisers: 0, active: 0, activeAdvertisers: 0, imps: 0, viewers: 0, views: 0,
- buys: 0, buysPrior: 0, usd: 0, activations: 0, paidWei: 0n, lifeBuys: 0, lifePaidWei: 0n, lifePayouts: 0 };
+ buys: 0, buysPrior: 0, usd: 0, activations: 0, paidWei: 0n, lifeBuys: 0, lifePaidWei: 0n, lifePayouts: 0,
+ creditsHandedOut: 0, creditsEarned: 0, creditsSpent: 0 };
if (X.db && X.db.enabled()) {
const q = (a, b) => X.db.q(a, b || []);
const a = (await q('SELECT COUNT(*) total, SUM(created>=?) s24, SUM(created>=? AND created) sPrior, SUM(address IS NOT NULL) wallet, SUM(member_id>0) payouts, SUM(last_seen>=?) seen FROM accounts', [since, prior, since, since]))[0] || {};
@@ -34,6 +35,10 @@ async function gather(now = Date.now()) {
s.imps = Number(im.imps || 0);
const v = (await q('SELECT COUNT(*) viewers, SUM(views) views FROM daily_views WHERE day=? AND views>0', [d1]))[0] || {};
s.viewers = Number(v.viewers || 0); s.views = Number(v.views || 0);
+ // where the credits came from (Marty, 2026-09-19): handed out = grants, partner codes and
+ // bonuses; earned = viewing; spent = everything that left a balance for ad delivery or a buy
+ const cl = (await q("SELECT SUM(CASE WHEN delta>0 AND kind IN ('grant','promo','bonus') THEN delta ELSE 0 END) handed, SUM(CASE WHEN delta>0 AND kind='earn' THEN delta ELSE 0 END) earned, SUM(CASE WHEN delta<0 THEN -delta ELSE 0 END) spent FROM credit_log WHERE ts>=?", [since]))[0] || {};
+ s.creditsHandedOut = Number(cl.handed || 0); s.creditsEarned = Number(cl.earned || 0); s.creditsSpent = Number(cl.spent || 0);
}
try {
for (const ev of X.chain.recentEvents(1e9)) {
@@ -56,6 +61,7 @@ function compose(s, cta) {
L.push('\u{1F9FE} Purchases: ' + n(s.buys) + ' for $' + n(Math.round(s.usd)) + trend(s.buys, s.buysPrior, 'the day before') + ' · ' + pol(s.paidWei) + ' POL paid to members in the same transactions');
L.push('\u{1F4E3} Campaigns: ' + n(s.campaigns) + ' posted by ' + n(s.advertisers) + ' advertiser' + (s.advertisers === 1 ? '' : 's') + ' · ' + n(s.active) + ' running now · ' + n(s.imps) + ' ad impressions served');
L.push('\u{1F440} Earning: ' + n(s.viewers) + ' members viewed ads today · ' + n(s.seen24h) + ' signed in');
+ L.push('\u{1F4B3} Credits: ' + n(s.creditsHandedOut) + ' handed out · ' + n(s.creditsEarned) + ' earned by viewing · ' + n(s.creditsSpent) + ' spent on ads');
L.push('\u{1F3C1} So far: ' + n(s.members) + ' members · ' + n(s.wallets) + ' wallets linked · ' + n(s.payoutsOn) + ' with payouts on · ' + n(s.lifeBuys) + ' purchases · ' + pol(s.lifePaidWei) + ' POL paid out in ' + n(s.lifePayouts) + ' payouts, every one on the public ledger');
L.push('Live ledger' + (cta ? ' · Join free' : ''));
return L.join('\n');