@render-foundation/utils 0.0.243 → 0.0.244
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 +48 -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 +41 -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,30 @@ 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 balance (pre-cutoff OTOY grants): still a granted source, folded in here so the
|
|
285
|
+
// consumer no longer seeds it separately.
|
|
286
|
+
const legacy = yield db
|
|
287
|
+
.selectFrom(exports.CURRENT_USER_GRANT_SPEND_TABLE)
|
|
288
|
+
.select(['user_id', 'render_spent'])
|
|
289
|
+
.where('user_id', 'in', p.userIds)
|
|
290
|
+
.execute();
|
|
277
291
|
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
|
|
292
|
+
const jobBy = new Map(jobspend.map((r) => { var _a; return [r.user_id, BigInt((_a = r.amt) !== null && _a !== void 0 ? _a : 0)]; }));
|
|
293
|
+
const legBy = new Map(legacy.map((r) => {
|
|
294
|
+
const v = BigInt(r.render_spent);
|
|
295
|
+
return [r.user_id, v > BigInt(0) ? v : BigInt(0)];
|
|
296
|
+
}));
|
|
279
297
|
for (const g of grants) {
|
|
280
298
|
const u = g.user_id;
|
|
281
299
|
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 +306,25 @@ const pgClient = (config) => {
|
|
|
288
306
|
createdAt: g.otoy_created_at ? new Date(g.otoy_created_at) : null,
|
|
289
307
|
});
|
|
290
308
|
}
|
|
309
|
+
// legacy-only users (no mirrored grant) still get an entry — their CSV balance is a granted source
|
|
310
|
+
for (const [u, v] of legBy) {
|
|
311
|
+
if (v > BigInt(0) && !out[u])
|
|
312
|
+
out[u] = { userId: u, granted: BigInt(0), consumed: BigInt(0), avail: BigInt(0), grants: [] };
|
|
313
|
+
}
|
|
291
314
|
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
|
-
|
|
315
|
+
const attributed = (_c = spentBy.get(u)) !== null && _c !== void 0 ? _c : BigInt(0); // ledger-counted (burns + pool-tied credits)
|
|
316
|
+
const spend = (_d = jobBy.get(u)) !== null && _d !== void 0 ? _d : BigInt(0); // ALL in-window job spend
|
|
317
|
+
const leg = (_e = legBy.get(u)) !== null && _e !== void 0 ? _e : BigInt(0);
|
|
318
|
+
// consumed = the larger of the two accountings — the ledger can exceed job spend (pool-tied
|
|
319
|
+
// credits retiring capacity), job spend can exceed the ledger (pre-go-live buy-and-burn jobs).
|
|
320
|
+
const consumed = attributed > spend ? attributed : spend;
|
|
321
|
+
const f = (0, exports.foldGrantAllotment)(out[u].grants, consumed, BigInt(0));
|
|
322
|
+
out[u].granted = f.granted + leg;
|
|
323
|
+
out[u].consumed = consumed;
|
|
324
|
+
out[u].avail =
|
|
325
|
+
f.granted + leg > consumed ? f.granted + leg - consumed : BigInt(0);
|
|
326
|
+
if (spend > attributed) {
|
|
327
|
+
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
328
|
}
|
|
301
329
|
}
|
|
302
330
|
return out;
|
|
@@ -1573,21 +1601,11 @@ const pgClient = (config) => {
|
|
|
1573
1601
|
var _a;
|
|
1574
1602
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1575
1603
|
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
1604
|
let q = db.trx
|
|
1586
1605
|
.selectFrom('burn')
|
|
1587
1606
|
.selectAll('burn')
|
|
1588
1607
|
.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'));
|
|
1608
|
+
.select(['sol_tx.executed_at', 'sol_tx.sig']);
|
|
1591
1609
|
if (!f.inclManual) {
|
|
1592
1610
|
q = q.where('burn.usdc_spent', '>', String(0));
|
|
1593
1611
|
}
|
|
@@ -1618,19 +1636,16 @@ const pgClient = (config) => {
|
|
|
1618
1636
|
const comp = q.compile();
|
|
1619
1637
|
const { rows } = yield (0, base_1.timedQuery)(pgPool, comp.sql, comp.parameters, 'fetchBurnsPage', log);
|
|
1620
1638
|
const burns = rows.map((r) => {
|
|
1621
|
-
var _a, _b
|
|
1639
|
+
var _a, _b;
|
|
1622
1640
|
return ({
|
|
1623
1641
|
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
1642
|
id: Number(r.id),
|
|
1628
1643
|
renderToUsdc: r.render_to_usdc,
|
|
1629
1644
|
solTx: r.sig,
|
|
1630
1645
|
executedAt: r.executed_at,
|
|
1631
1646
|
pricedAt: r.priced_at,
|
|
1632
|
-
usdcSpent: BigInt((
|
|
1633
|
-
quoteAmt: BigInt((
|
|
1647
|
+
usdcSpent: BigInt((_a = r.usdc_spent) !== null && _a !== void 0 ? _a : 0),
|
|
1648
|
+
quoteAmt: BigInt((_b = r.quote_amt) !== null && _b !== void 0 ? _b : 0),
|
|
1634
1649
|
burned: BigInt(r.burned),
|
|
1635
1650
|
eurToUsdc: r.eur_to_usdc,
|
|
1636
1651
|
markedBurnedAt: r.marked_burned_at,
|
|
@@ -1671,16 +1686,12 @@ const pgClient = (config) => {
|
|
|
1671
1686
|
// Truncating the naive column is pure arithmetic and identical under every session timezone, and
|
|
1672
1687
|
// to_char hands back a plain 'YYYY-MM-DD' so node-postgres has no Date to decode in local time.
|
|
1673
1688
|
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
1689
|
let q = db.trx
|
|
1678
1690
|
.selectFrom('burn')
|
|
1679
1691
|
.innerJoin('sol_tx', 'sol_tx.id', 'burn.sol_tx_id')
|
|
1680
1692
|
.select(({ fn }) => [
|
|
1681
1693
|
dayExpr.as('day'),
|
|
1682
1694
|
fn.sum('burn.burned').as('render_burned'),
|
|
1683
|
-
grantBurnedDay.as('grant_burned'),
|
|
1684
1695
|
fn.sum('burn.usdc_spent').as('usdc_spent'),
|
|
1685
1696
|
fn.count('burn.id').as('burn_count'),
|
|
1686
1697
|
])
|
|
@@ -1699,13 +1710,12 @@ const pgClient = (config) => {
|
|
|
1699
1710
|
const { rows } = yield (0, base_1.timedQuery)(pgPool, comp.sql, comp.parameters, 'fetchDailyBurnStats', log);
|
|
1700
1711
|
log.info(`fetchDailyBurnStats len ${rows.length}`);
|
|
1701
1712
|
return rows.map((r) => {
|
|
1702
|
-
var _a, _b, _c
|
|
1713
|
+
var _a, _b, _c;
|
|
1703
1714
|
return ({
|
|
1704
1715
|
day: r.day,
|
|
1705
1716
|
renderBurned: BigInt((_a = r.render_burned) !== null && _a !== void 0 ? _a : 0),
|
|
1706
1717
|
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),
|
|
1718
|
+
burnCount: Number((_c = r.burn_count) !== null && _c !== void 0 ? _c : 0),
|
|
1709
1719
|
});
|
|
1710
1720
|
});
|
|
1711
1721
|
});
|