@render-foundation/utils 0.0.243 → 0.0.245
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/burn/burnCalculations.js +140 -0
- package/lib/cjs/burn/burnCalculations.js.map +1 -0
- package/lib/cjs/client/pg/v2Client.js +50 -38
- package/lib/cjs/client/pg/v2Client.js.map +1 -1
- package/lib/esm/src/burn/burnCalculations.js +124 -0
- package/lib/esm/src/burn/burnCalculations.js.map +1 -0
- package/lib/esm/src/client/pg/v2Client.js +43 -31
- package/lib/esm/src/client/pg/v2Client.js.map +1 -1
- package/lib/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/lib/types/src/burn/burnCalculations.d.ts +52 -0
- package/lib/types/src/burn/burnCalculations.d.ts.map +1 -0
- package/lib/types/src/client/pg/v2Client.d.ts +2 -4
- package/lib/types/src/client/pg/v2Client.d.ts.map +1 -1
- package/package.json +1 -1
- package/lib/cjs/tsconfig.cjs.tsbuildinfo +0 -1
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.calculateBurnAmounts = exports.batchFinishedAtMedian = void 0;
|
|
15
|
+
const spl_utils_1 = require("@render-foundation/spl-utils");
|
|
16
|
+
const logger_1 = require("../logger");
|
|
17
|
+
// Utility function copied from cron-server
|
|
18
|
+
const batchFinishedAtMedian = (jobs) => {
|
|
19
|
+
const pricedAt = jobs.length % 2 == 0
|
|
20
|
+
? new Date(Math.trunc((Date.parse(jobs[jobs.length / 2].finishedAt) +
|
|
21
|
+
Date.parse(jobs[jobs.length / 2 - 1].finishedAt)) /
|
|
22
|
+
2))
|
|
23
|
+
: new Date(Date.parse(jobs[Math.floor(jobs.length / 2)].finishedAt));
|
|
24
|
+
return pricedAt;
|
|
25
|
+
};
|
|
26
|
+
exports.batchFinishedAtMedian = batchFinishedAtMedian;
|
|
27
|
+
/**
|
|
28
|
+
* Pure function that calculates burn amounts without side effects
|
|
29
|
+
* This is the core logic extracted from consumeIncrBuyAndBurnRenderPG
|
|
30
|
+
*/
|
|
31
|
+
const calculateBurnAmounts = (input, opts = {
|
|
32
|
+
perpetual: true,
|
|
33
|
+
}, log = logger_1.consoleLogger) => {
|
|
34
|
+
const { jobs, userGrantSpends, burnAdjustments, params, decimals, priceAtDate, eurToUSDC, } = input;
|
|
35
|
+
// Apply grant/buy split logic to jobs
|
|
36
|
+
const processedJobs = jobs.map((j) => {
|
|
37
|
+
const { buyRenderAmt, grantRenderAmt } = j, rest = __rest(j, ["buyRenderAmt", "grantRenderAmt"]);
|
|
38
|
+
return rest;
|
|
39
|
+
}); // Deep copy to avoid mutations
|
|
40
|
+
for (const j of processedJobs) {
|
|
41
|
+
const userGrantSpend = userGrantSpends[j.userId];
|
|
42
|
+
if (userGrantSpend) {
|
|
43
|
+
if (opts.perpetual ||
|
|
44
|
+
userGrantSpend.userGrantSpend.perpetual ||
|
|
45
|
+
j.rndrUsed <= userGrantSpend.currAllot) {
|
|
46
|
+
j.grantRenderAmt = Number(j.rndrUsed);
|
|
47
|
+
log.debug(`job ${j.id} grant split: ${j.rndrUsed}`);
|
|
48
|
+
userGrantSpend.currAllot -= BigInt(j.rndrUsed);
|
|
49
|
+
}
|
|
50
|
+
else if (userGrantSpend.currAllot <= BigInt(0)) {
|
|
51
|
+
log.debug(`job ${j.id} buy split: ${j.rndrUsed}`);
|
|
52
|
+
j.buyRenderAmt = Number(j.rndrUsed);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
log.debug(`job ${j.id} buy + grant split: ${j.rndrUsed} grant: ${Number(userGrantSpend.currAllot)} buy: ${Number(j.rndrUsed) - Number(userGrantSpend.currAllot)}`);
|
|
56
|
+
j.grantRenderAmt = Number(userGrantSpend.currAllot);
|
|
57
|
+
j.buyRenderAmt = Number(j.rndrUsed) - Number(userGrantSpend.currAllot);
|
|
58
|
+
userGrantSpend.currAllot = BigInt(0);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
log.debug(`job ${j.id} no grant split: ${j.rndrUsed}`);
|
|
63
|
+
j.buyRenderAmt = Number(j.rndrUsed);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const totalRenderUsed = processedJobs.reduce((tot, job) => tot + Number(job.rndrUsed.toString()), 0);
|
|
67
|
+
log.debug(`jobs buy + grant split: ${JSON.stringify(processedJobs)}`);
|
|
68
|
+
// Check minimum threshold
|
|
69
|
+
if (totalRenderUsed < (0, spl_utils_1.toBN)(params.minTotalRndrThreshold, decimals).toNumber()) {
|
|
70
|
+
throw new Error(`totalRenderUsed ${totalRenderUsed / Math.pow(10, decimals)} < total threshold ${params.minTotalRndrThreshold}`);
|
|
71
|
+
}
|
|
72
|
+
const totalRenderBuyAndBurn = processedJobs.reduce((tot, job) => { var _a; return tot + Number((_a = job.buyRenderAmt) !== null && _a !== void 0 ? _a : 0); }, 0);
|
|
73
|
+
const totalRender = processedJobs.reduce((tot, job) => tot + Number(job.rndrUsed.toString()), 0);
|
|
74
|
+
log.debug(`Burn calculation inputs:`);
|
|
75
|
+
log.debug(` totalRenderUsed: ${totalRenderUsed}`);
|
|
76
|
+
log.debug(` totalRenderBuyAndBurn: ${totalRenderBuyAndBurn}`);
|
|
77
|
+
log.debug(` totalRender: ${totalRender}`);
|
|
78
|
+
log.debug(` priceAtDate: ${priceAtDate}`);
|
|
79
|
+
log.debug(` eurToUSDC: ${eurToUSDC}`);
|
|
80
|
+
const pricedAt = (0, exports.batchFinishedAtMedian)(processedJobs.map((job) => ({
|
|
81
|
+
finishedAt: job.completedAt.toISOString(),
|
|
82
|
+
jobId: job.id,
|
|
83
|
+
rndrUsed: Number(job.rndrUsed.toString()),
|
|
84
|
+
})));
|
|
85
|
+
// Core burn calculation logic
|
|
86
|
+
const toBurn = Math.trunc((totalRender / priceAtDate / 4) * 0.95 * eurToUSDC);
|
|
87
|
+
let renderToBuyAndBurn = Math.trunc((totalRenderBuyAndBurn / totalRender) * toBurn);
|
|
88
|
+
const origRenderToBuyAndBurn = renderToBuyAndBurn;
|
|
89
|
+
log.debug(`Core burn calculation:`);
|
|
90
|
+
log.debug(` toBurn: ${toBurn}`);
|
|
91
|
+
log.debug(` renderToBuyAndBurn: ${renderToBuyAndBurn}`);
|
|
92
|
+
log.debug(` origRenderToBuyAndBurn: ${origRenderToBuyAndBurn}`);
|
|
93
|
+
let burnAdjustmentId = undefined;
|
|
94
|
+
// Apply burn adjustments
|
|
95
|
+
if (burnAdjustments.length > 0) {
|
|
96
|
+
const adjustment = burnAdjustments[0];
|
|
97
|
+
burnAdjustmentId = adjustment.id;
|
|
98
|
+
const adjLeft = adjustment.downAdjToBurn - adjustment.adjusted;
|
|
99
|
+
const minBurnRndrThreshold = (0, spl_utils_1.toBN)(params.minBurnRndrThreshold, decimals).toNumber();
|
|
100
|
+
const available = renderToBuyAndBurn - minBurnRndrThreshold;
|
|
101
|
+
if (adjLeft > available) {
|
|
102
|
+
renderToBuyAndBurn = minBurnRndrThreshold;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
renderToBuyAndBurn -= adjLeft;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Validate burn thresholds
|
|
109
|
+
const toBuyAndBurnUI = renderToBuyAndBurn / Math.pow(10, decimals);
|
|
110
|
+
if (renderToBuyAndBurn != 0) {
|
|
111
|
+
if (toBuyAndBurnUI > params.maxBurnRndrThreshold) {
|
|
112
|
+
throw new Error(`buy and burn RENDER ${toBuyAndBurnUI} too high`);
|
|
113
|
+
}
|
|
114
|
+
if (toBuyAndBurnUI < params.minBurnRndrThreshold) {
|
|
115
|
+
throw new Error(`buy and burn RENDER ${toBuyAndBurnUI} too low < ${params.minBurnRndrThreshold}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
const renderToBurnFromEmissions = toBurn - origRenderToBuyAndBurn;
|
|
119
|
+
const totalToBurn = renderToBuyAndBurn + renderToBurnFromEmissions;
|
|
120
|
+
log.debug(`Final burn calculation results:`);
|
|
121
|
+
log.debug(` renderToBuyAndBurn: ${renderToBuyAndBurn}`);
|
|
122
|
+
log.debug(` renderToBurnFromEmissions: ${renderToBurnFromEmissions}`);
|
|
123
|
+
log.debug(` totalToBurn: ${totalToBurn}`);
|
|
124
|
+
log.debug(` toBurn: ${toBurn}`);
|
|
125
|
+
return {
|
|
126
|
+
totalRenderUsed,
|
|
127
|
+
totalRenderBuyAndBurn,
|
|
128
|
+
totalRender,
|
|
129
|
+
renderToBuyAndBurn,
|
|
130
|
+
renderToBurnFromEmissions,
|
|
131
|
+
totalToBurn,
|
|
132
|
+
toBurn,
|
|
133
|
+
origRenderToBuyAndBurn,
|
|
134
|
+
burnAdjustmentId,
|
|
135
|
+
pricedAt,
|
|
136
|
+
processedJobs,
|
|
137
|
+
};
|
|
138
|
+
};
|
|
139
|
+
exports.calculateBurnAmounts = calculateBurnAmounts;
|
|
140
|
+
//# sourceMappingURL=burnCalculations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"burnCalculations.js","sourceRoot":"","sources":["../../../src/burn/burnCalculations.ts"],"names":[],"mappings":"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"}
|
|
@@ -35,7 +35,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
35
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
36
|
};
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
-
exports.pgClient = exports.batchFinishedAtMedian = exports.foldGrantAllotment = exports.CREDIT_DECIMALS = exports.EUR_TO_CREDITS = exports.DISPERSED_BURN_CORRECTION_TABLE = exports.DISPERSED_SETTLEMENT_TABLE = exports.GRANT_BURN_TABLE = exports.GRANT_BURN_ID_TABLE = exports.OTOY_GRANT_TABLE = exports.USER_GRANT_SPEND_TABLE = exports.CURRENT_USER_GRANT_SPEND_TABLE = exports.POLYGON_UPGRADE_TABLE = exports.ENTITY_EPOCH_INFO_TABLE = exports.BURN_CORRECTION_TABLE = exports.NETWORK_REVENUE_TABLE = exports.BRIDGE_TRANSFER_TABLE = exports.BURN_TABLE = exports.JOB_TABLE = exports.JOB_ID_TABLE = exports.LIABILITY_ADJUSTMENT_BATCH_TABLE = exports.LIABILITY_ADJUSTMENT_TABLE = exports.LIABILITY_TABLE = exports.SOL_TRANSFER_TABLE = exports.ENTITY_TABLE = exports.MANUAL_BURN_TABLE = exports.EPOCH_TABLE = exports.SOL_TX_TABLE = void 0;
|
|
38
|
+
exports.pgClient = exports.batchFinishedAtMedian = exports.foldGrantAllotment = exports.CREDIT_DECIMALS = exports.GRANT_WINDOW_START = exports.EUR_TO_CREDITS = exports.DISPERSED_BURN_CORRECTION_TABLE = exports.DISPERSED_SETTLEMENT_TABLE = exports.GRANT_BURN_TABLE = exports.GRANT_BURN_ID_TABLE = exports.OTOY_GRANT_TABLE = exports.USER_GRANT_SPEND_TABLE = exports.CURRENT_USER_GRANT_SPEND_TABLE = exports.POLYGON_UPGRADE_TABLE = exports.ENTITY_EPOCH_INFO_TABLE = exports.BURN_CORRECTION_TABLE = exports.NETWORK_REVENUE_TABLE = exports.BRIDGE_TRANSFER_TABLE = exports.BURN_TABLE = exports.JOB_TABLE = exports.JOB_ID_TABLE = exports.LIABILITY_ADJUSTMENT_BATCH_TABLE = exports.LIABILITY_ADJUSTMENT_TABLE = exports.LIABILITY_TABLE = exports.SOL_TRANSFER_TABLE = exports.ENTITY_TABLE = exports.MANUAL_BURN_TABLE = exports.EPOCH_TABLE = exports.SOL_TX_TABLE = void 0;
|
|
39
39
|
const kysely_1 = require("kysely");
|
|
40
40
|
const logger_1 = require("../../logger");
|
|
41
41
|
const pg_1 = require("pg");
|
|
@@ -71,6 +71,10 @@ BigInt.prototype.toJSON = function () {
|
|
|
71
71
|
// confirmed_amount = EUR, despite the column name); 1 render credit = EUR 0.25, so credits = EUR x 4.
|
|
72
72
|
// job.render_amt / user_grant_spend.render_spent_delta are credits x 1e8.
|
|
73
73
|
exports.EUR_TO_CREDITS = BigInt(4);
|
|
74
|
+
// Grant accounting window: otoy_grant mirrors OTOY RFG issuances from this date. Consumption against the
|
|
75
|
+
// window counts EVERY job the user ran in it — buy-and-burn jobs consumed OTOY credits exactly like
|
|
76
|
+
// emissions-funded ones (counting only emissions-attributed spend over-issued ~2.58M credits, 2026-08-04).
|
|
77
|
+
exports.GRANT_WINDOW_START = '2025-05-01';
|
|
74
78
|
exports.CREDIT_DECIMALS = BigInt(100000000); // 1e8
|
|
75
79
|
/**
|
|
76
80
|
* Pure core of the grant allotment: fold a user's OTOY grants against what's already been spent.
|
|
@@ -228,7 +232,7 @@ const pgClient = (config) => {
|
|
|
228
232
|
// Spendable grant per user, straight off otoy_grant (FIFO), net of what's already been spent or
|
|
229
233
|
// already settled by a burn correction. See GrantAllotment for the units + the double-spend guard.
|
|
230
234
|
const getGrantAllotments = (db, p, log = logger_1.consoleLogger) => __awaiter(void 0, void 0, void 0, function* () {
|
|
231
|
-
var _b, _c, _d;
|
|
235
|
+
var _b, _c, _d, _e;
|
|
232
236
|
const out = {};
|
|
233
237
|
if (!p.userIds.length)
|
|
234
238
|
return out;
|
|
@@ -266,16 +270,32 @@ const pgClient = (config) => {
|
|
|
266
270
|
.where('user_id', 'in', p.userIds)
|
|
267
271
|
.groupBy('user_id')
|
|
268
272
|
.execute();
|
|
269
|
-
//
|
|
270
|
-
|
|
273
|
+
// ALL in-window job spend — the true deduction ledger. Every render job flows through us, and every
|
|
274
|
+
// job consumed the user's OTOY credits regardless of HOW we funded the burn (emissions or USDC
|
|
275
|
+
// buy-and-burn). This supersedes the old correction-settled term (those jobs are in-window) and
|
|
276
|
+
// closes the pre-go-live gap where buy-and-burn jobs didn't decrement grants.
|
|
277
|
+
const jobspend = yield db
|
|
271
278
|
.selectFrom(`${exports.JOB_TABLE} as j`)
|
|
272
|
-
.innerJoin(`${exports.BURN_CORRECTION_TABLE} as bc`, 'bc.job_id', 'j.id')
|
|
273
279
|
.select((eb) => ['j.user_id as user_id', eb.fn.sum('j.render_amt').as('amt')])
|
|
274
280
|
.where('j.user_id', 'in', p.userIds)
|
|
281
|
+
.where('j.completed_at', '>=', new Date(exports.GRANT_WINDOW_START))
|
|
275
282
|
.groupBy('j.user_id')
|
|
276
283
|
.execute();
|
|
284
|
+
// legacy CSV CREDITED (pre-cutoff OTOY grants redeemed against in-window jobs): the FULL credited
|
|
285
|
+
// amount offsets job spend — those jobs were paid by pre-cutoff grants per OTOY's own redemption
|
|
286
|
+
// report. Using the floored remaining BALANCE here under-grants users whose emissions burns exceeded
|
|
287
|
+
// their credited amount (f5adcc66: balance 0 but credited 50,213 -> avail 6,390 vs correct 56,603).
|
|
288
|
+
const legacy = yield db
|
|
289
|
+
.selectFrom(exports.USER_GRANT_SPEND_TABLE)
|
|
290
|
+
.select((eb) => ['user_id', eb.fn.sum('render_spent_delta').as('v')])
|
|
291
|
+
.where('user_id', 'in', p.userIds)
|
|
292
|
+
.where('render_spent_delta', '>', '0')
|
|
293
|
+
.where('otoy_grant_id', 'is', null)
|
|
294
|
+
.groupBy('user_id')
|
|
295
|
+
.execute();
|
|
277
296
|
const spentBy = new Map(spent.map((r) => { var _a; return [r.user_id, BigInt((_a = r.net) !== null && _a !== void 0 ? _a : 0)]; }));
|
|
278
|
-
const
|
|
297
|
+
const jobBy = new Map(jobspend.map((r) => { var _a; return [r.user_id, BigInt((_a = r.amt) !== null && _a !== void 0 ? _a : 0)]; }));
|
|
298
|
+
const legBy = new Map(legacy.map((r) => { var _a; return [r.user_id, BigInt((_a = r.v) !== null && _a !== void 0 ? _a : 0)]; }));
|
|
279
299
|
for (const g of grants) {
|
|
280
300
|
const u = g.user_id;
|
|
281
301
|
const cur = (_b = out[u]) !== null && _b !== void 0 ? _b : (out[u] = { userId: u, granted: BigInt(0), consumed: BigInt(0), avail: BigInt(0), grants: [] });
|
|
@@ -288,15 +308,25 @@ const pgClient = (config) => {
|
|
|
288
308
|
createdAt: g.otoy_created_at ? new Date(g.otoy_created_at) : null,
|
|
289
309
|
});
|
|
290
310
|
}
|
|
311
|
+
// legacy-only users (no mirrored grant) still get an entry — their CSV balance is a granted source
|
|
312
|
+
for (const [u, v] of legBy) {
|
|
313
|
+
if (v > BigInt(0) && !out[u])
|
|
314
|
+
out[u] = { userId: u, granted: BigInt(0), consumed: BigInt(0), avail: BigInt(0), grants: [] };
|
|
315
|
+
}
|
|
291
316
|
for (const u of Object.keys(out)) {
|
|
292
|
-
const attributed = (_c = spentBy.get(u)) !== null && _c !== void 0 ? _c : BigInt(0); //
|
|
293
|
-
const
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
317
|
+
const attributed = (_c = spentBy.get(u)) !== null && _c !== void 0 ? _c : BigInt(0); // ledger-counted (burns + pool-tied credits)
|
|
318
|
+
const spend = (_d = jobBy.get(u)) !== null && _d !== void 0 ? _d : BigInt(0); // ALL in-window job spend
|
|
319
|
+
const leg = (_e = legBy.get(u)) !== null && _e !== void 0 ? _e : BigInt(0);
|
|
320
|
+
// consumed = the larger of the two accountings — the ledger can exceed job spend (pool-tied
|
|
321
|
+
// credits retiring capacity), job spend can exceed the ledger (pre-go-live buy-and-burn jobs).
|
|
322
|
+
const consumed = attributed > spend ? attributed : spend;
|
|
323
|
+
const f = (0, exports.foldGrantAllotment)(out[u].grants, consumed, BigInt(0));
|
|
324
|
+
out[u].granted = f.granted + leg;
|
|
325
|
+
out[u].consumed = consumed;
|
|
326
|
+
out[u].avail =
|
|
327
|
+
f.granted + leg > consumed ? f.granted + leg - consumed : BigInt(0);
|
|
328
|
+
if (spend > attributed) {
|
|
329
|
+
log.info(`grant allotment ${u}: in-window job spend ${spend} > ledger-counted ${attributed} — strict consumption applied (granted ${f.granted} + legacy ${leg} => avail ${out[u].avail})`);
|
|
300
330
|
}
|
|
301
331
|
}
|
|
302
332
|
return out;
|
|
@@ -1573,21 +1603,11 @@ const pgClient = (config) => {
|
|
|
1573
1603
|
var _a;
|
|
1574
1604
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1575
1605
|
const lastId = f.cursor ? atob(f.cursor) : undefined;
|
|
1576
|
-
// grant_burn holds the portion of the SAME transaction burned from emissions rather than bought with
|
|
1577
|
-
// USDC: markJobsBurnt writes buyBurn -> burn and grantBurn -> grant_burn, keyed on the same sol_tx_id.
|
|
1578
|
-
// So burn.burned alone UNDERSTATES what the tx actually burned. Measured on prod: 2,053 grant_burn rows
|
|
1579
|
-
// back to 2025-09, up to 23.9% of a month's total (Oct 2025) and ~1% recently.
|
|
1580
|
-
//
|
|
1581
|
-
// A correlated subquery, not a LEFT JOIN. Today there is at most one grant_burn per sol_tx (verified:
|
|
1582
|
-
// max 1, zero sol_tx with more), but nothing enforces that, and a join that started multiplying rows
|
|
1583
|
-
// would silently corrupt the limit and the cursor — the same failure the jobId filter avoids.
|
|
1584
|
-
const grantBurned = (0, kysely_1.sql) `coalesce((select sum(gb.burned) from grant_burn gb where gb.sol_tx_id = burn.sol_tx_id), 0)`;
|
|
1585
1606
|
let q = db.trx
|
|
1586
1607
|
.selectFrom('burn')
|
|
1587
1608
|
.selectAll('burn')
|
|
1588
1609
|
.innerJoin('sol_tx', 'sol_tx.id', 'burn.sol_tx_id')
|
|
1589
|
-
.select(['sol_tx.executed_at', 'sol_tx.sig'])
|
|
1590
|
-
.select(grantBurned.as('grant_burned'));
|
|
1610
|
+
.select(['sol_tx.executed_at', 'sol_tx.sig']);
|
|
1591
1611
|
if (!f.inclManual) {
|
|
1592
1612
|
q = q.where('burn.usdc_spent', '>', String(0));
|
|
1593
1613
|
}
|
|
@@ -1618,19 +1638,16 @@ const pgClient = (config) => {
|
|
|
1618
1638
|
const comp = q.compile();
|
|
1619
1639
|
const { rows } = yield (0, base_1.timedQuery)(pgPool, comp.sql, comp.parameters, 'fetchBurnsPage', log);
|
|
1620
1640
|
const burns = rows.map((r) => {
|
|
1621
|
-
var _a, _b
|
|
1641
|
+
var _a, _b;
|
|
1622
1642
|
return ({
|
|
1623
1643
|
jobs: [],
|
|
1624
|
-
// The emissions-burned portion of the same tx. Callers wanting "RENDER burned by this transaction"
|
|
1625
|
-
// must add this to `burned`.
|
|
1626
|
-
grantBurned: BigInt((_a = r.grant_burned) !== null && _a !== void 0 ? _a : 0),
|
|
1627
1644
|
id: Number(r.id),
|
|
1628
1645
|
renderToUsdc: r.render_to_usdc,
|
|
1629
1646
|
solTx: r.sig,
|
|
1630
1647
|
executedAt: r.executed_at,
|
|
1631
1648
|
pricedAt: r.priced_at,
|
|
1632
|
-
usdcSpent: BigInt((
|
|
1633
|
-
quoteAmt: BigInt((
|
|
1649
|
+
usdcSpent: BigInt((_a = r.usdc_spent) !== null && _a !== void 0 ? _a : 0),
|
|
1650
|
+
quoteAmt: BigInt((_b = r.quote_amt) !== null && _b !== void 0 ? _b : 0),
|
|
1634
1651
|
burned: BigInt(r.burned),
|
|
1635
1652
|
eurToUsdc: r.eur_to_usdc,
|
|
1636
1653
|
markedBurnedAt: r.marked_burned_at,
|
|
@@ -1671,16 +1688,12 @@ const pgClient = (config) => {
|
|
|
1671
1688
|
// Truncating the naive column is pure arithmetic and identical under every session timezone, and
|
|
1672
1689
|
// to_char hands back a plain 'YYYY-MM-DD' so node-postgres has no Date to decode in local time.
|
|
1673
1690
|
const dayExpr = (0, kysely_1.sql) `to_char(date_trunc('day', sol_tx.executed_at), 'YYYY-MM-DD')`;
|
|
1674
|
-
// Same emissions gap as fetchBurnsPage: summing burn.burned alone understates the daily total, so the
|
|
1675
|
-
// charts drawn from this were short by the emissions portion too.
|
|
1676
|
-
const grantBurnedDay = (0, kysely_1.sql) `coalesce(sum((select sum(gb.burned) from grant_burn gb where gb.sol_tx_id = burn.sol_tx_id)), 0)`;
|
|
1677
1691
|
let q = db.trx
|
|
1678
1692
|
.selectFrom('burn')
|
|
1679
1693
|
.innerJoin('sol_tx', 'sol_tx.id', 'burn.sol_tx_id')
|
|
1680
1694
|
.select(({ fn }) => [
|
|
1681
1695
|
dayExpr.as('day'),
|
|
1682
1696
|
fn.sum('burn.burned').as('render_burned'),
|
|
1683
|
-
grantBurnedDay.as('grant_burned'),
|
|
1684
1697
|
fn.sum('burn.usdc_spent').as('usdc_spent'),
|
|
1685
1698
|
fn.count('burn.id').as('burn_count'),
|
|
1686
1699
|
])
|
|
@@ -1699,13 +1712,12 @@ const pgClient = (config) => {
|
|
|
1699
1712
|
const { rows } = yield (0, base_1.timedQuery)(pgPool, comp.sql, comp.parameters, 'fetchDailyBurnStats', log);
|
|
1700
1713
|
log.info(`fetchDailyBurnStats len ${rows.length}`);
|
|
1701
1714
|
return rows.map((r) => {
|
|
1702
|
-
var _a, _b, _c
|
|
1715
|
+
var _a, _b, _c;
|
|
1703
1716
|
return ({
|
|
1704
1717
|
day: r.day,
|
|
1705
1718
|
renderBurned: BigInt((_a = r.render_burned) !== null && _a !== void 0 ? _a : 0),
|
|
1706
1719
|
usdcSpent: BigInt((_b = r.usdc_spent) !== null && _b !== void 0 ? _b : 0),
|
|
1707
|
-
|
|
1708
|
-
burnCount: Number((_d = r.burn_count) !== null && _d !== void 0 ? _d : 0),
|
|
1720
|
+
burnCount: Number((_c = r.burn_count) !== null && _c !== void 0 ? _c : 0),
|
|
1709
1721
|
});
|
|
1710
1722
|
});
|
|
1711
1723
|
});
|