@render-foundation/utils 0.0.192 → 0.0.193

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.
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.compareBurnAmounts = exports.analyzeBurnJobs = void 0;
13
+ const burnCalculations_1 = require("./burnCalculations");
14
+ const logger_1 = require("../logger");
15
+ /**
16
+ * Analyzes a set of jobs and calculates what should have been burned
17
+ * This function can be used for both live processing and backfill analysis
18
+ */
19
+ const analyzeBurnJobs = (ctx, input, opts = {
20
+ perpetual: true,
21
+ }, log = logger_1.consoleLogger) => __awaiter(void 0, void 0, void 0, function* () {
22
+ const { jobs, params, decimals, pricedAt } = input;
23
+ // Get user grant spends
24
+ const userIds = jobs.reduce((acc, job) => {
25
+ if (job.userId) {
26
+ acc.add(job.userId);
27
+ }
28
+ return acc;
29
+ }, new Set());
30
+ // For analysis, we use the underlying db object directly
31
+ const userGrantSpends = (yield Promise.all(Array.from(userIds).map((userId) => __awaiter(void 0, void 0, void 0, function* () {
32
+ // Note: For backfill, we might need historical grant spend data
33
+ // This is a limitation we'll need to address
34
+ const currSpend = yield ctx.pgV2.getCurrentUserGrantSpend(ctx.pgV2.db, // Use the underlying db object
35
+ { userId }, log);
36
+ return { userId, currSpend };
37
+ })))).reduce((acc, us) => {
38
+ if (us.currSpend) {
39
+ acc[us.userId] = {
40
+ userGrantSpend: us.currSpend,
41
+ currAllot: us.currSpend.renderSpent,
42
+ };
43
+ }
44
+ return acc;
45
+ }, {});
46
+ // Get burn adjustments (for backfill, we might need historical data)
47
+ const burnAdjustments = yield ctx.pgV2.getBurnAdjustments(ctx.pgV2.db, // Use the underlying db object
48
+ { toFill: true }, log);
49
+ // Determine pricing date
50
+ const effectivePricedAt = pricedAt ||
51
+ (0, burnCalculations_1.calculateBurnAmounts)({
52
+ jobs,
53
+ userGrantSpends,
54
+ burnAdjustments,
55
+ params,
56
+ decimals,
57
+ priceAtDate: 1,
58
+ eurToUSDC: 1, // Dummy value for date calculation
59
+ }, opts, log).pricedAt;
60
+ // Get historical prices
61
+ const price = yield ctx.priceClient.getRenderPriceAtDate({
62
+ ts: effectivePricedAt,
63
+ });
64
+ const eurToUSDC = yield ctx.priceClient.eurToUSDC(effectivePricedAt);
65
+ // Calculate burn amounts
66
+ const result = (0, burnCalculations_1.calculateBurnAmounts)({
67
+ jobs,
68
+ userGrantSpends,
69
+ burnAdjustments,
70
+ params,
71
+ decimals,
72
+ priceAtDate: price,
73
+ eurToUSDC,
74
+ }, opts, log);
75
+ return Object.assign(Object.assign({}, result), { price,
76
+ eurToUSDC });
77
+ });
78
+ exports.analyzeBurnJobs = analyzeBurnJobs;
79
+ const compareBurnAmounts = (expected, actual) => {
80
+ const discrepancyTotalToBurn = actual.totalToBurn - expected.totalToBurn;
81
+ // Only return discrepancy if absolute total discrepancy is significant (> 10^8)
82
+ if (Math.abs(discrepancyTotalToBurn) <= Math.pow(10, 8)) {
83
+ return null;
84
+ }
85
+ return {
86
+ expectedRenderToBuyAndBurn: expected.renderToBuyAndBurn,
87
+ actualRenderToBuyAndBurn: actual.renderToBuyAndBurn,
88
+ expectedRenderToBurnFromEmissions: expected.renderToBurnFromEmissions,
89
+ actualRenderToBurnFromEmissions: actual.renderToBurnFromEmissions,
90
+ expectedTotalToBurn: expected.totalToBurn,
91
+ actualTotalToBurn: actual.totalToBurn,
92
+ discrepancyRenderToBuyAndBurn: actual.renderToBuyAndBurn - expected.renderToBuyAndBurn,
93
+ discrepancyRenderToBurnFromEmissions: actual.renderToBurnFromEmissions - expected.renderToBurnFromEmissions,
94
+ discrepancyTotalToBurn,
95
+ jobs: actual.jobs,
96
+ burnDate: actual.burnDate,
97
+ txSig: actual.txSig,
98
+ };
99
+ };
100
+ exports.compareBurnAmounts = compareBurnAmounts;
101
+ //# sourceMappingURL=burnAnalysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"burnAnalysis.js","sourceRoot":"","sources":["../../../src/burn/burnAnalysis.ts"],"names":[],"mappings":"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"}
@@ -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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"}
@@ -1031,16 +1031,18 @@ const pgClient = (config) => {
1031
1031
  .executeTakeFirstOrThrow();
1032
1032
  grantBurnId = Number(id);
1033
1033
  }
1034
+ const burnId = buyBurnId !== null && buyBurnId !== void 0 ? buyBurnId : grantBurnId;
1035
+ const grantId = grantBurnId !== null && grantBurnId !== void 0 ? grantBurnId : buyBurnId;
1034
1036
  for (const job of p.jobs) {
1035
1037
  const res = yield trx.trx
1036
1038
  .updateTable(exports.JOB_TABLE)
1037
1039
  .where('id', '=', String(job.id))
1038
- .set('burn_id', job.buyRenderAmt != undefined ? buyBurnId : null)
1039
- .set('grant_burn_id', job.grantRenderAmt != undefined ? grantBurnId : null)
1040
+ .set('burn_id', burnId)
1041
+ .set('grant_burn_id', grantId)
1040
1042
  .set('buy_render_amt', (_a = job.buyRenderAmt) !== null && _a !== void 0 ? _a : 0)
1041
1043
  .set('grant_render_amt', (_b = job.grantRenderAmt) !== null && _b !== void 0 ? _b : 0)
1042
1044
  .executeTakeFirstOrThrow();
1043
- log.debug(`set grant_burn_id ${grantBurnId} burn_id ${buyBurnId} buy_render_amt ${job.buyRenderAmt} grant_render_amt ${job.grantRenderAmt} on ${res.numUpdatedRows} jobs id ${job.id}`);
1045
+ log.debug(`set burn_id ${burnId} grant_burn_id ${grantId} buy_render_amt ${job.buyRenderAmt} grant_render_amt ${job.grantRenderAmt} on ${res.numUpdatedRows} jobs id ${job.id}`);
1044
1046
  }
1045
1047
  return { grantBurnId, buyBurnId };
1046
1048
  });
@@ -1186,6 +1188,7 @@ const pgClient = (config) => {
1186
1188
  .select('inserted_at')
1187
1189
  .orderBy('completed_at asc')
1188
1190
  .where('burn_id', 'is', null)
1191
+ .where('grant_burn_id', 'is', null)
1189
1192
  .execute();
1190
1193
  if (res.length == 0) {
1191
1194
  return { outstandingJobs: 0 };
@@ -1267,6 +1270,146 @@ const pgClient = (config) => {
1267
1270
  return burns;
1268
1271
  });
1269
1272
  },
1273
+ fetchBurnsAndGrants(db, f, log = logger_1.consoleLogger) {
1274
+ var _a, _b;
1275
+ return __awaiter(this, void 0, void 0, function* () {
1276
+ // Build a unified query to get all transactions with both buy burns and grant burns
1277
+ let baseQuery = db.trx
1278
+ .selectFrom('sol_tx')
1279
+ .select(['sol_tx.sig', 'sol_tx.executed_at'])
1280
+ .leftJoin('burn', 'burn.sol_tx_id', 'sol_tx.id')
1281
+ .leftJoin('grant_burn', 'grant_burn.sol_tx_id', 'sol_tx.id')
1282
+ .select([
1283
+ 'burn.id as buy_burn_id',
1284
+ 'burn.burned as buy_burned',
1285
+ 'burn.priced_at',
1286
+ 'burn.render_to_usdc',
1287
+ 'burn.usdc_spent',
1288
+ 'burn.quote_amt',
1289
+ 'burn.eur_to_usdc',
1290
+ 'burn.marked_burned_at as buy_marked_burned_at',
1291
+ 'burn.tags as buy_tags',
1292
+ 'grant_burn.id as grant_burn_id',
1293
+ 'grant_burn.burned as grant_burned',
1294
+ 'grant_burn.marked_burned_at as grant_marked_burned_at',
1295
+ 'grant_burn.tags as grant_tags',
1296
+ ])
1297
+ .where((eb) => eb.or([
1298
+ eb('burn.id', 'is not', null),
1299
+ eb('grant_burn.id', 'is not', null),
1300
+ ]));
1301
+ // Apply date filters
1302
+ if (f.executedAfter) {
1303
+ baseQuery = baseQuery.where('sol_tx.executed_at', '>=', f.executedAfter);
1304
+ }
1305
+ if (f.executedBefore) {
1306
+ baseQuery = baseQuery.where('sol_tx.executed_at', '<=', f.executedBefore);
1307
+ }
1308
+ if (f.pricedAtBefore) {
1309
+ baseQuery = baseQuery.where('burn.priced_at', '<=', f.pricedAtBefore);
1310
+ }
1311
+ if (f.pricedAtAfter) {
1312
+ baseQuery = baseQuery.where('burn.priced_at', '>=', f.pricedAtAfter);
1313
+ }
1314
+ // Apply ordering
1315
+ if (f.orderBy == 'pricedAt') {
1316
+ baseQuery = baseQuery.orderBy(['burn.priced_at']);
1317
+ }
1318
+ else if (f.orderBy == 'executedAt') {
1319
+ baseQuery = baseQuery.orderBy(['sol_tx.executed_at']);
1320
+ }
1321
+ log.info(`fetchBurnsAndGrants query ${baseQuery.compile().sql}`);
1322
+ const comp = baseQuery.compile();
1323
+ const { rows } = yield (0, base_1.timedQuery)(pgPool, comp.sql, comp.parameters, 'fetchBurnsAndGrants', log);
1324
+ log.info(`fetchBurnsAndGrants found ${rows.length} burn transactions`);
1325
+ // Group by transaction signature
1326
+ const groupedBurns = {};
1327
+ for (const r of rows) {
1328
+ const txSig = r.sig;
1329
+ if (!groupedBurns[txSig]) {
1330
+ groupedBurns[txSig] = {
1331
+ solTx: txSig,
1332
+ executedAt: r.executed_at,
1333
+ allJobs: [],
1334
+ };
1335
+ }
1336
+ // Add buy burn if exists
1337
+ if (r.buy_burn_id) {
1338
+ groupedBurns[txSig].buyBurn = {
1339
+ jobs: [],
1340
+ id: Number(r.buy_burn_id),
1341
+ renderToUsdc: r.render_to_usdc,
1342
+ solTx: txSig,
1343
+ executedAt: r.executed_at,
1344
+ pricedAt: r.priced_at,
1345
+ usdcSpent: BigInt((_a = r.usdc_spent) !== null && _a !== void 0 ? _a : 0),
1346
+ quoteAmt: BigInt((_b = r.quote_amt) !== null && _b !== void 0 ? _b : 0),
1347
+ burned: BigInt(r.buy_burned),
1348
+ eurToUsdc: r.eur_to_usdc,
1349
+ markedBurnedAt: r.buy_marked_burned_at,
1350
+ tags: r.buy_tags ? r.buy_tags.split(',') : [],
1351
+ };
1352
+ }
1353
+ // Add grant burn if exists
1354
+ if (r.grant_burn_id) {
1355
+ groupedBurns[txSig].grantBurn = {
1356
+ id: Number(r.grant_burn_id),
1357
+ burned: BigInt(r.grant_burned),
1358
+ markedBurnedAt: r.grant_marked_burned_at,
1359
+ tags: r.grant_tags ? r.grant_tags.split(',') : [],
1360
+ };
1361
+ }
1362
+ }
1363
+ // Fetch jobs if requested
1364
+ if (f.inclJobs) {
1365
+ const allTxSigs = Object.keys(groupedBurns);
1366
+ if (allTxSigs.length > 0) {
1367
+ // Get all jobs for these transactions
1368
+ const q = db.trx
1369
+ .selectFrom('job')
1370
+ .selectAll('job')
1371
+ .leftJoin('burn', 'burn.id', 'job.burn_id')
1372
+ .leftJoin('sol_tx as buy_tx', 'buy_tx.id', 'burn.sol_tx_id')
1373
+ .select(['buy_tx.sig as buy_tx_sig'])
1374
+ .leftJoin('grant_burn', 'grant_burn.id', 'job.grant_burn_id')
1375
+ .leftJoin('sol_tx as grant_tx', 'grant_tx.id', 'grant_burn.sol_tx_id')
1376
+ .select(['grant_tx.sig as grant_tx_sig'])
1377
+ .where((eb) => eb.or([
1378
+ eb('buy_tx.sig', 'in', allTxSigs),
1379
+ eb('grant_tx.sig', 'in', allTxSigs),
1380
+ ]));
1381
+ log.info(`fetchJobs q ${q.compile().sql}`);
1382
+ const jobRows = yield q.execute();
1383
+ log.info(`fetchJobs found ${jobRows.length} jobs`);
1384
+ // Add jobs to the appropriate transactions
1385
+ for (const r of jobRows) {
1386
+ const txSig = r.buy_tx_sig || r.grant_tx_sig;
1387
+ if (txSig && groupedBurns[txSig]) {
1388
+ const job = {
1389
+ id: Number(r.id),
1390
+ completedAt: r.completed_at,
1391
+ rndrUsed: BigInt(r.render_amt),
1392
+ obhUsed: r.obh_used ? Number(r.obh_used) : undefined,
1393
+ userId: r.user_id,
1394
+ buyRenderAmt: r.buy_render_amt
1395
+ ? Number(r.buy_render_amt)
1396
+ : undefined,
1397
+ grantRenderAmt: r.grant_render_amt
1398
+ ? Number(r.grant_render_amt)
1399
+ : undefined,
1400
+ };
1401
+ groupedBurns[txSig].allJobs.push(job);
1402
+ // Also add to specific burn type
1403
+ if (r.buy_tx_sig && groupedBurns[txSig].buyBurn) {
1404
+ groupedBurns[txSig].buyBurn.jobs.push(job);
1405
+ }
1406
+ }
1407
+ }
1408
+ }
1409
+ }
1410
+ return groupedBurns;
1411
+ });
1412
+ },
1270
1413
  createBridgeTransfers(db, bts, log = logger_1.consoleLogger) {
1271
1414
  return __awaiter(this, void 0, void 0, function* () {
1272
1415
  return createBridgeTransfers(db.trx, bts, log);