@render-foundation/utils 0.0.180 → 0.0.182

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.
Files changed (110) hide show
  1. package/lib/cjs/backfiller.js +895 -0
  2. package/lib/cjs/backfiller.js.map +1 -0
  3. package/lib/cjs/client/onchain.js +132 -0
  4. package/lib/cjs/client/onchain.js.map +1 -0
  5. package/lib/cjs/client/pg/base.js +198 -0
  6. package/lib/cjs/client/pg/base.js.map +1 -0
  7. package/lib/cjs/client/pg/v1.js +623 -0
  8. package/lib/cjs/client/pg/v1.js.map +1 -0
  9. package/lib/cjs/client/pg/v2Client.js +1584 -0
  10. package/lib/cjs/client/pg/v2Client.js.map +1 -0
  11. package/lib/cjs/client/pg/viewClient.js +107 -0
  12. package/lib/cjs/client/pg/viewClient.js.map +1 -0
  13. package/lib/cjs/client/price.js +63 -0
  14. package/lib/cjs/client/price.js.map +1 -0
  15. package/lib/cjs/client/render.js +173 -0
  16. package/lib/cjs/client/render.js.map +1 -0
  17. package/lib/cjs/client/squads.js +204 -0
  18. package/lib/cjs/client/squads.js.map +1 -0
  19. package/lib/cjs/client/trade.js +235 -0
  20. package/lib/cjs/client/trade.js.map +1 -0
  21. package/lib/cjs/client/wormhole.js +69 -0
  22. package/lib/cjs/client/wormhole.js.map +1 -0
  23. package/lib/cjs/constants.js +46 -0
  24. package/lib/cjs/constants.js.map +1 -0
  25. package/lib/cjs/dbTypes.js +3 -0
  26. package/lib/cjs/dbTypes.js.map +1 -0
  27. package/lib/cjs/dbTypesV2.js +3 -0
  28. package/lib/cjs/dbTypesV2.js.map +1 -0
  29. package/lib/cjs/dbViewTypes.js +3 -0
  30. package/lib/cjs/dbViewTypes.js.map +1 -0
  31. package/lib/cjs/errorReporter.js +126 -0
  32. package/lib/cjs/errorReporter.js.map +1 -0
  33. package/lib/cjs/index.js +44 -0
  34. package/lib/cjs/index.js.map +1 -0
  35. package/lib/cjs/logger.js +21 -0
  36. package/lib/cjs/logger.js.map +1 -0
  37. package/lib/esm/src/backfiller.js +850 -0
  38. package/lib/esm/src/backfiller.js.map +1 -0
  39. package/lib/esm/src/client/onchain.js +122 -0
  40. package/lib/esm/src/client/onchain.js.map +1 -0
  41. package/lib/esm/src/client/pg/base.js +162 -0
  42. package/lib/esm/src/client/pg/base.js.map +1 -0
  43. package/lib/esm/src/client/pg/v1.js +559 -0
  44. package/lib/esm/src/client/pg/v1.js.map +1 -0
  45. package/lib/esm/src/client/pg/v2Client.js +1465 -0
  46. package/lib/esm/src/client/pg/v2Client.js.map +1 -0
  47. package/lib/esm/src/client/pg/viewClient.js +91 -0
  48. package/lib/esm/src/client/pg/viewClient.js.map +1 -0
  49. package/lib/esm/src/client/price.js +41 -0
  50. package/lib/esm/src/client/price.js.map +1 -0
  51. package/lib/esm/src/client/render.js +147 -0
  52. package/lib/esm/src/client/render.js.map +1 -0
  53. package/lib/esm/src/client/squads.js +163 -0
  54. package/lib/esm/src/client/squads.js.map +1 -0
  55. package/lib/esm/src/client/trade.js +219 -0
  56. package/lib/esm/src/client/trade.js.map +1 -0
  57. package/lib/esm/src/client/wormhole.js +33 -0
  58. package/lib/esm/src/client/wormhole.js.map +1 -0
  59. package/lib/esm/src/constants.js +43 -0
  60. package/lib/esm/src/constants.js.map +1 -0
  61. package/lib/esm/src/dbTypes.js +2 -0
  62. package/lib/esm/src/dbTypes.js.map +1 -0
  63. package/lib/esm/src/dbTypesV2.js +2 -0
  64. package/lib/esm/src/dbTypesV2.js.map +1 -0
  65. package/lib/esm/src/dbViewTypes.js +2 -0
  66. package/lib/esm/src/dbViewTypes.js.map +1 -0
  67. package/lib/esm/src/errorReporter.js +117 -0
  68. package/lib/esm/src/errorReporter.js.map +1 -0
  69. package/lib/esm/src/index.js +15 -0
  70. package/lib/esm/src/index.js.map +1 -0
  71. package/lib/esm/src/logger.js +18 -0
  72. package/lib/esm/src/logger.js.map +1 -0
  73. package/lib/esm/tsconfig.esm.tsbuildinfo +1 -1
  74. package/lib/types/src/backfiller.d.ts +62 -0
  75. package/lib/types/src/backfiller.d.ts.map +1 -0
  76. package/lib/types/src/client/onchain.d.ts +24 -0
  77. package/lib/types/src/client/onchain.d.ts.map +1 -0
  78. package/lib/types/src/client/pg/base.d.ts +82 -0
  79. package/lib/types/src/client/pg/base.d.ts.map +1 -0
  80. package/lib/types/src/client/pg/v1.d.ts +137 -0
  81. package/lib/types/src/client/pg/v1.d.ts.map +1 -0
  82. package/lib/types/src/client/pg/v2Client.d.ts +309 -0
  83. package/lib/types/src/client/pg/v2Client.d.ts.map +1 -0
  84. package/lib/types/src/client/pg/viewClient.d.ts +55 -0
  85. package/lib/types/src/client/pg/viewClient.d.ts.map +1 -0
  86. package/lib/types/src/client/price.d.ts +12 -0
  87. package/lib/types/src/client/price.d.ts.map +1 -0
  88. package/lib/types/src/client/render.d.ts +24 -0
  89. package/lib/types/src/client/render.d.ts.map +1 -0
  90. package/lib/types/src/client/squads.d.ts +17 -0
  91. package/lib/types/src/client/squads.d.ts.map +1 -0
  92. package/lib/types/src/client/trade.d.ts +24 -0
  93. package/lib/types/src/client/trade.d.ts.map +1 -0
  94. package/lib/types/src/client/wormhole.d.ts +9 -0
  95. package/lib/types/src/client/wormhole.d.ts.map +1 -0
  96. package/lib/types/src/constants.d.ts +41 -0
  97. package/lib/types/src/constants.d.ts.map +1 -0
  98. package/lib/types/src/dbTypes.d.ts +123 -0
  99. package/lib/types/src/dbTypes.d.ts.map +1 -0
  100. package/lib/types/src/dbTypesV2.d.ts +193 -0
  101. package/lib/types/src/dbTypesV2.d.ts.map +1 -0
  102. package/lib/types/src/dbViewTypes.d.ts +35 -0
  103. package/lib/types/src/dbViewTypes.d.ts.map +1 -0
  104. package/lib/types/src/errorReporter.d.ts +13 -0
  105. package/lib/types/src/errorReporter.d.ts.map +1 -0
  106. package/lib/types/src/index.d.ts +15 -0
  107. package/lib/types/src/index.d.ts.map +1 -0
  108. package/lib/types/src/logger.d.ts +16 -0
  109. package/lib/types/src/logger.d.ts.map +1 -0
  110. package/package.json +1 -1
@@ -0,0 +1,1584 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __importDefault = (this && this.__importDefault) || function (mod) {
35
+ return (mod && mod.__esModule) ? mod : { "default": mod };
36
+ };
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.pgClient = exports.batchFinishedAtMedian = exports.GRANT_BURN_TABLE = exports.GRANT_BURN_ID_TABLE = exports.USER_GRANT_SPEND_TABLE = exports.CURRENT_USER_GRANT_SPEND_TABLE = exports.POLYGON_UPGRADE_TABLE = exports.ENTITY_EPOCH_INFO_TABLE = exports.BURN_ADJUSTMENT_TABLE = exports.NETWORK_REVENUE_TABLE = exports.BRIDGE_TRANSFER_TABLE = exports.BURN_TABLE = exports.JOB_TABLE = exports.JOB_ID_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
+ const kysely_1 = require("kysely");
40
+ const logger_1 = require("../../logger");
41
+ const pg_1 = require("pg");
42
+ const pg = __importStar(require("pg"));
43
+ const base_1 = require("./base");
44
+ exports.SOL_TX_TABLE = 'sol_tx';
45
+ exports.EPOCH_TABLE = 'epoch';
46
+ exports.MANUAL_BURN_TABLE = 'manual_burn';
47
+ exports.ENTITY_TABLE = 'entity';
48
+ exports.SOL_TRANSFER_TABLE = 'sol_transfer1';
49
+ exports.LIABILITY_TABLE = 'liability';
50
+ exports.JOB_ID_TABLE = 'job_id';
51
+ exports.JOB_TABLE = 'job';
52
+ exports.BURN_TABLE = 'burn';
53
+ exports.BRIDGE_TRANSFER_TABLE = 'bridge_transfer';
54
+ exports.NETWORK_REVENUE_TABLE = 'network_revenue';
55
+ exports.BURN_ADJUSTMENT_TABLE = 'burn_adjustment';
56
+ exports.ENTITY_EPOCH_INFO_TABLE = 'entity_epoch_info';
57
+ exports.POLYGON_UPGRADE_TABLE = 'polygon_upgrade';
58
+ exports.CURRENT_USER_GRANT_SPEND_TABLE = 'current_user_grant_spend';
59
+ exports.USER_GRANT_SPEND_TABLE = 'user_grant_spend';
60
+ exports.GRANT_BURN_ID_TABLE = 'grant_burn_id';
61
+ exports.GRANT_BURN_TABLE = 'grant_burn';
62
+ BigInt.prototype.toJSON = function () {
63
+ return this.toString();
64
+ };
65
+ const base_2 = require("./base");
66
+ const moment_1 = __importDefault(require("moment"));
67
+ pg.types.setTypeParser(1114, (str) => moment_1.default.utc(str).toDate());
68
+ pg.defaults.parseInputDatesAsUTC = true;
69
+ /* ;(Date.prototype as any).toPostgres = function (prepareValue: (v: any) => any) {
70
+ return this.toISOString()
71
+ }
72
+ */
73
+ const batchFinishedAtMedian = (jobs) => {
74
+ const pricedAt = jobs.length % 2 == 0
75
+ ? new Date(Math.trunc((Date.parse(jobs[jobs.length / 2].finishedAt) +
76
+ Date.parse(jobs[jobs.length / 2 - 1].finishedAt)) /
77
+ 2))
78
+ : new Date(Date.parse(jobs[Math.floor(jobs.length / 2)].finishedAt));
79
+ return pricedAt;
80
+ };
81
+ exports.batchFinishedAtMedian = batchFinishedAtMedian;
82
+ const pgClient = (config) => {
83
+ // Single pg pool that we can also use for ad-hoc performance tests outside Kysely
84
+ const pgPool = new pg_1.Pool(config);
85
+ pgPool.on('connect', (c) => console.log('new pg socket created'));
86
+ pgPool.on('error', (err) => console.log('idle pg client died and was replaced:', err));
87
+ const dialect = new kysely_1.PostgresDialect({ pool: pgPool });
88
+ // Database interface is passed to Kysely's constructor, and from now on, Kysely
89
+ // knows your database structure.
90
+ // Dialect is passed to Kysely's constructor, and from now on, Kysely knows how
91
+ // to communicate with your database.
92
+ const db = new kysely_1.Kysely({
93
+ dialect,
94
+ });
95
+ const getOrInsertEntity = (db, p, log = logger_1.consoleLogger) => __awaiter(void 0, void 0, void 0, function* () {
96
+ const res = (yield db
97
+ .selectFrom(exports.ENTITY_TABLE)
98
+ .select('id')
99
+ .where('sol_key', '=', p.solKey)
100
+ .executeTakeFirst());
101
+ if (res) {
102
+ log.debug(`already found entity ${res.id}`);
103
+ return res.id;
104
+ }
105
+ const { id } = (yield db
106
+ .insertInto(exports.ENTITY_TABLE)
107
+ .values({
108
+ sol_key: p.solKey,
109
+ })
110
+ .onConflict((oc) => oc.column('sol_key').doNothing())
111
+ .returning((eb) => ['id as id'])
112
+ .executeTakeFirst());
113
+ log.debug(`inserted entity ${id}`);
114
+ return id;
115
+ });
116
+ const getOrInsertTx = (db, p, log = logger_1.consoleLogger) => __awaiter(void 0, void 0, void 0, function* () {
117
+ const res = yield db
118
+ .selectFrom(exports.SOL_TX_TABLE)
119
+ .select('id')
120
+ .where('sig', '=', p.sig)
121
+ .executeTakeFirst();
122
+ if (res) {
123
+ log.debug(`already found tx ${res.id}`);
124
+ return res.id;
125
+ }
126
+ const { id } = (yield db
127
+ .insertInto(exports.SOL_TX_TABLE)
128
+ .values({
129
+ sig: p.sig,
130
+ executed_at: p.executedAt,
131
+ })
132
+ .onConflict((oc) => oc.column('sig').doNothing())
133
+ .returning((eb) => ['id as id'])
134
+ .executeTakeFirst());
135
+ log.debug(`inserted tx ${id}`);
136
+ return id;
137
+ });
138
+ const getOrInsertEpoch = (db, p, log = logger_1.consoleLogger) => __awaiter(void 0, void 0, void 0, function* () {
139
+ const res = yield db
140
+ .selectFrom(exports.EPOCH_TABLE)
141
+ .select('id')
142
+ .where('ui', '=', String(p.uiEpochId))
143
+ .where('channel', '=', p.channel)
144
+ .executeTakeFirst();
145
+ if (res) {
146
+ log.debug(`already found epoch ${res.id}`);
147
+ return res.id;
148
+ }
149
+ const { id } = (yield db
150
+ .insertInto(exports.EPOCH_TABLE)
151
+ .values({
152
+ ui: p.uiEpochId,
153
+ channel: p.channel,
154
+ start_time: p.startTime,
155
+ end_time: p.endTime,
156
+ saved_at: p.channel == 'node_operator' || p.channel == 'availability'
157
+ ? new Date()
158
+ : undefined,
159
+ })
160
+ .onConflict((oc) => oc.columns(['ui', 'channel']).doNothing())
161
+ .returning((eb) => ['id as id'])
162
+ .executeTakeFirst());
163
+ log.debug(`inserted epoch ${id}`);
164
+ return id;
165
+ });
166
+ const getCurrentUserGrantSpend = (db, p, log = logger_1.consoleLogger) => __awaiter(void 0, void 0, void 0, function* () {
167
+ var _a;
168
+ const res = yield db
169
+ .selectFrom(exports.CURRENT_USER_GRANT_SPEND_TABLE)
170
+ .selectAll()
171
+ .where('user_id', '=', p.userId)
172
+ .forUpdate()
173
+ .executeTakeFirst();
174
+ return res
175
+ ? {
176
+ id: BigInt(res.id),
177
+ user: res.user_id,
178
+ renderSpent: BigInt(res.render_spent),
179
+ perpetual: (_a = res.perpetual) !== null && _a !== void 0 ? _a : false,
180
+ description: res.description,
181
+ }
182
+ : undefined;
183
+ });
184
+ const updateTotalRndr = (db, p, totalRndr, savedAt, log) => __awaiter(void 0, void 0, void 0, function* () {
185
+ const res = (yield db
186
+ .updateTable(exports.EPOCH_TABLE)
187
+ .set({
188
+ total_rndr: totalRndr,
189
+ saved_at: savedAt,
190
+ })
191
+ .where('channel', '=', p.channel)
192
+ .where('ui', '=', String(p.uiEpochId))
193
+ .executeTakeFirst());
194
+ log.info(`set ${res.numUpdatedRows} rows. channel: ${p.channel}, ui: ${p.uiEpochId} -> totalRndr ${totalRndr} `);
195
+ });
196
+ const fetchJobs1 = (db, f, log = logger_1.consoleLogger) => __awaiter(void 0, void 0, void 0, function* () {
197
+ let q = db.selectFrom('job').selectAll();
198
+ //.where('job.burn_id', 'is not', null)
199
+ if (f.completedAtAfter) {
200
+ q = q.where('completed_at', '>=', f.completedAtAfter);
201
+ }
202
+ if (f.completedAtBefore) {
203
+ q = q.where('completed_at', '<=', f.completedAtBefore);
204
+ }
205
+ if (f.ids) {
206
+ q = q.where('id', 'in', f.ids);
207
+ }
208
+ else {
209
+ if (f.burned == false) {
210
+ q = q.where('burn_id', 'is', null);
211
+ }
212
+ else if (f.burned == true) {
213
+ q = q.where('burn_id', 'is not', null);
214
+ }
215
+ }
216
+ q = q.orderBy('completed_at asc');
217
+ log.info(`fetchJobs q ${q.compile().sql} ${JSON.stringify(f)}`);
218
+ const rows = yield q.execute();
219
+ return rows.map((r) => ({
220
+ id: Number(r.id),
221
+ completedAt: r.completed_at,
222
+ rndrUsed: BigInt(r.render_amt),
223
+ insertedAt: r.inserted_at,
224
+ }));
225
+ });
226
+ const createBridgeTransfers = (db, bts, log = logger_1.consoleLogger) => __awaiter(void 0, void 0, void 0, function* () {
227
+ const sequenceNumbers = [];
228
+ const dbEpochIds = [];
229
+ for (const bt of bts) {
230
+ let { solKey: toSolKey, seq, createdAt, amount, upgradeBracket, priorSupply, points, epochId, } = bt;
231
+ let entityId;
232
+ if (toSolKey && toSolKey != '') {
233
+ entityId = yield getOrInsertEntity(db, { solKey: toSolKey });
234
+ }
235
+ const dbEpochId = yield getOrInsertEpoch(db, {
236
+ channel: 'upgrade',
237
+ uiEpochId: epochId,
238
+ }, log);
239
+ dbEpochIds.push(BigInt(dbEpochId));
240
+ const q = db
241
+ .insertInto(exports.BRIDGE_TRANSFER_TABLE)
242
+ .values({
243
+ entity_id: entityId,
244
+ sequence: seq,
245
+ created_at: createdAt,
246
+ amount: amount,
247
+ upgrade_bracket: upgradeBracket,
248
+ prior_supply: priorSupply,
249
+ points: points,
250
+ epoch_id: dbEpochId,
251
+ })
252
+ .onConflict((oc) => oc.column('sequence').doUpdateSet({
253
+ created_at: createdAt,
254
+ amount: amount,
255
+ upgrade_bracket: upgradeBracket,
256
+ prior_supply: priorSupply,
257
+ points: points,
258
+ epoch_id: dbEpochId,
259
+ entity_id: entityId,
260
+ }))
261
+ .returning('sequence');
262
+ const c = q.compile();
263
+ log.debug(`inserting bridge transfer ${JSON.stringify(bt)} -> ${c.sql} ps ${c.parameters}`);
264
+ const { sequence: seqNum } = yield q.executeTakeFirst();
265
+ log.debug(`inserted bridge transfer sequence ${seq}`);
266
+ sequenceNumbers.push(BigInt(seqNum));
267
+ }
268
+ return { sequenceNumbers: sequenceNumbers };
269
+ });
270
+ const createPayments = (db, ps, log = logger_1.consoleLogger) => __awaiter(void 0, void 0, void 0, function* () {
271
+ const ids = [];
272
+ const epochDbIds = [];
273
+ for (const p of ps) {
274
+ let liabilityId;
275
+ let transferId;
276
+ if (p.liability) {
277
+ let { id: dbId, solKey, channel, epochId, createdAt, amountDue, deviceId, points, obhUsed, } = p.liability;
278
+ try {
279
+ let entityId;
280
+ if (solKey && solKey != '') {
281
+ entityId = yield getOrInsertEntity(db, { solKey });
282
+ }
283
+ const dbEpochId = yield getOrInsertEpoch(db, {
284
+ channel,
285
+ uiEpochId: epochId,
286
+ }, log);
287
+ epochDbIds.push(BigInt(dbEpochId));
288
+ log.debug(`inserting liability ${JSON.stringify(p.liability)}`);
289
+ const { id } = yield db
290
+ .insertInto(exports.LIABILITY_TABLE)
291
+ .values({
292
+ id: dbId,
293
+ entity_id: entityId,
294
+ epoch_id: dbEpochId,
295
+ channel,
296
+ created_at: createdAt !== null && createdAt !== void 0 ? createdAt : new Date(),
297
+ amount_due: amountDue,
298
+ device_id: deviceId,
299
+ points,
300
+ obh_used: obhUsed,
301
+ })
302
+ .returning((eb) => ['id as id'])
303
+ .executeTakeFirstOrThrow();
304
+ log.debug(`inserted liability ${id}`);
305
+ liabilityId = BigInt(id);
306
+ }
307
+ catch (e) {
308
+ throw new Error(`failed inserting solKey ${solKey} epochId ${epochId} ${JSON.stringify(p.liability)}: ${e}`);
309
+ }
310
+ }
311
+ if (p.transfer) {
312
+ let { executedAt, symbol, amountPayed, solTx, channel, fromSolKey, toSolKey, id: dbId, } = p.transfer;
313
+ if (!fromSolKey || !toSolKey || !solTx) {
314
+ log.debug(`skipping transfer. one of undefined: fromKey ${fromSolKey} toKey ${toSolKey} tx ${solTx}`);
315
+ continue;
316
+ }
317
+ log.debug(`inserting transfer ${JSON.stringify(p.transfer)}`);
318
+ const fromEntityId = yield getOrInsertEntity(db, { solKey: fromSolKey });
319
+ const toEntityId = yield getOrInsertEntity(db, { solKey: toSolKey });
320
+ const solTxId = yield getOrInsertTx(db, {
321
+ sig: solTx,
322
+ executedAt,
323
+ }, log);
324
+ const { id } = yield db
325
+ .insertInto(exports.SOL_TRANSFER_TABLE)
326
+ .values({
327
+ id: dbId,
328
+ sol_tx_id: solTxId,
329
+ from_entity_id: fromEntityId,
330
+ to_entity_id: toEntityId,
331
+ channel,
332
+ symbol,
333
+ amount_payed: amountPayed,
334
+ })
335
+ .returning((eb) => ['id as id'])
336
+ .executeTakeFirstOrThrow();
337
+ transferId = BigInt(id);
338
+ }
339
+ ids.push({ transferId, liabilityId });
340
+ }
341
+ return { epochDbIds, inserted: ids };
342
+ });
343
+ return {
344
+ db: {
345
+ commit: () => { },
346
+ rollback: () => { },
347
+ trx: db,
348
+ },
349
+ startTransaction(log = logger_1.consoleLogger) {
350
+ return __awaiter(this, void 0, void 0, function* () {
351
+ return (0, base_2.begin)(db, log);
352
+ });
353
+ },
354
+ createPayments(db, ps, log = logger_1.consoleLogger) {
355
+ return __awaiter(this, void 0, void 0, function* () {
356
+ return createPayments(db.trx, ps, log);
357
+ });
358
+ },
359
+ fetchTransfers(db, f, log = logger_1.consoleLogger) {
360
+ return __awaiter(this, void 0, void 0, function* () {
361
+ let lastId = undefined;
362
+ if (f.cursor) {
363
+ lastId = atob(f.cursor);
364
+ }
365
+ let q = db.trx
366
+ .selectFrom(exports.SOL_TRANSFER_TABLE)
367
+ .select([
368
+ 'sol_transfer1.id',
369
+ 'sol_transfer1.channel',
370
+ 'sol_transfer1.symbol',
371
+ 'sol_transfer1.amount_payed',
372
+ ])
373
+ .innerJoin('sol_tx', 'sol_tx.id', 'sol_transfer1.sol_tx_id')
374
+ .select(['sol_tx.sig', 'sol_tx.executed_at'])
375
+ .innerJoin('entity as f', 'f.id', 'sol_transfer1.from_entity_id')
376
+ .select(['f.sol_key as from_sol_key'])
377
+ .innerJoin('entity as t', 't.id', 'sol_transfer1.to_entity_id')
378
+ .select(['t.sol_key as to_sol_key']);
379
+ if (f.executedAfter) {
380
+ q = q.where('sol_tx.executed_at', '>=', f.executedAfter);
381
+ }
382
+ if (f.executedBefore) {
383
+ q = q.where('sol_tx.executed_at', '<=', f.executedBefore);
384
+ }
385
+ if (f.channels) {
386
+ q = q.where('sol_transfer1.channel', 'in', f.channels);
387
+ }
388
+ if (lastId) {
389
+ q = q.where('sol_transfer1.id', '>', lastId);
390
+ }
391
+ let limit = 10000;
392
+ if (f.limit) {
393
+ limit = f.limit;
394
+ }
395
+ q = q.limit(limit).orderBy(`${exports.SOL_TRANSFER_TABLE}.id`);
396
+ const comp = q.compile();
397
+ const { rows } = yield (0, base_1.timedQuery)(pgPool, comp.sql, comp.parameters, 'fetchTransfers', log);
398
+ const trs = rows.map((r) => ({
399
+ id: BigInt(r.id),
400
+ channel: r.channel,
401
+ symbol: r.symbol,
402
+ amountPayed: BigInt(r.amount_payed),
403
+ solTx: r.sig,
404
+ executedAt: r.executed_at,
405
+ fromSolKey: r.from_sol_key,
406
+ toSolKey: r.to_sol_key,
407
+ }));
408
+ return {
409
+ transfers: trs,
410
+ cursor: trs.length === limit
411
+ ? btoa(trs[trs.length - 1].id.toString())
412
+ : undefined,
413
+ };
414
+ });
415
+ },
416
+ fetchEpochs(db, f, log = logger_1.consoleLogger) {
417
+ return __awaiter(this, void 0, void 0, function* () {
418
+ let q = db.trx.selectFrom(exports.EPOCH_TABLE).selectAll();
419
+ if (f.channels) {
420
+ q = q.where('channel', 'in', f.channels);
421
+ }
422
+ if (f.startTimeAfter) {
423
+ q = q.where('epoch.start_time', '>', f.startTimeAfter);
424
+ }
425
+ if (f.endTimeBefore) {
426
+ q = q.where('epoch.end_time', '<', f.endTimeBefore);
427
+ }
428
+ q = q.orderBy('epoch.start_time');
429
+ const comp = q.compile();
430
+ const { rows } = yield (0, base_1.timedQuery)(pgPool, comp.sql, comp.parameters, 'fetchEpochs', log);
431
+ return rows.map((e) => ({
432
+ channel: e.channel,
433
+ startTime: e.start_time,
434
+ endTime: e.end_time,
435
+ ui: Number(e.ui),
436
+ totalRndr: Number(e.total_rndr),
437
+ }));
438
+ });
439
+ },
440
+ fetchLiabilities(db, f, log = logger_1.consoleLogger) {
441
+ var _a;
442
+ return __awaiter(this, void 0, void 0, function* () {
443
+ let offset = 0;
444
+ let orderBy = (_a = f.orderBy) !== null && _a !== void 0 ? _a : 'epoch.ui,liability.id';
445
+ if (f.cursor) {
446
+ const c = JSON.parse(atob(f.cursor));
447
+ if (c.offset) {
448
+ offset = c.offset;
449
+ }
450
+ if (c.orderBy) {
451
+ orderBy = c.orderBy;
452
+ }
453
+ }
454
+ let q = db.trx
455
+ .selectFrom(exports.LIABILITY_TABLE)
456
+ .selectAll()
457
+ .innerJoin(exports.ENTITY_TABLE, `${exports.LIABILITY_TABLE}.entity_id`, 'entity.id')
458
+ .select(['entity.sol_key'])
459
+ .innerJoin(exports.EPOCH_TABLE, `${exports.EPOCH_TABLE}.id`, 'liability.epoch_id')
460
+ .select(['epoch.ui', 'epoch.start_time', 'epoch.end_time']);
461
+ if (f.epochEndedAtAfter) {
462
+ q = q.where('epoch.end_time', '>=', f.epochEndedAtAfter);
463
+ }
464
+ if (f.epochEndedAtBefore) {
465
+ q = q.where('epoch.end_time', '<=', f.epochEndedAtBefore);
466
+ }
467
+ if (f.epochId) {
468
+ q = q.where('epoch.ui', '=', f.epochId.toString());
469
+ }
470
+ if (f.channels) {
471
+ q = q.where('liability.channel', 'in', f.channels);
472
+ }
473
+ let limit = 10000;
474
+ if (f.limit) {
475
+ limit = f.limit;
476
+ }
477
+ // @ts-ignore
478
+ q = q.limit(limit).orderBy(orderBy.split(','));
479
+ if (offset) {
480
+ q = q.offset(offset);
481
+ }
482
+ const comp = q.compile();
483
+ const { rows } = yield (0, base_1.timedQuery)(pgPool, comp.sql, comp.parameters, 'fetchLiabilities', log);
484
+ const ls = [];
485
+ for (const l of rows) {
486
+ ls.push({
487
+ id: BigInt(l.id),
488
+ solKey: l.sol_key,
489
+ epochId: Number(l.ui),
490
+ channel: l.channel,
491
+ createdAt: l.created_at,
492
+ amountDue: BigInt(l.amount_due),
493
+ deviceId: l.device_id,
494
+ obhUsed: l.obh_used,
495
+ points: l.points ? BigInt(l.points) : undefined,
496
+ startTime: l.start_time,
497
+ endTime: l.end_time,
498
+ ui: Number(l.ui),
499
+ });
500
+ }
501
+ return {
502
+ liabilities: ls,
503
+ cursor: ls.length == limit
504
+ ? btoa(JSON.stringify({ offset: ls.length + offset, orderBy }))
505
+ : undefined,
506
+ };
507
+ });
508
+ },
509
+ getLiabilitiesAndTransfers(f, log = logger_1.consoleLogger) {
510
+ return __awaiter(this, void 0, void 0, function* () {
511
+ let lq = db
512
+ .selectFrom(exports.LIABILITY_TABLE)
513
+ .selectAll()
514
+ .innerJoin(exports.ENTITY_TABLE, `${exports.LIABILITY_TABLE}.entity_id`, 'entity.id')
515
+ .select(['entity.sol_key'])
516
+ .innerJoin(exports.EPOCH_TABLE, `${exports.EPOCH_TABLE}.id`, 'liability.epoch_id')
517
+ .select(['epoch.ui', 'epoch.start_time', 'epoch.end_time'])
518
+ .where('entity.sol_key', '=', f.user);
519
+ let tq = db
520
+ .selectFrom(exports.SOL_TRANSFER_TABLE)
521
+ .selectAll()
522
+ .innerJoin(exports.SOL_TX_TABLE, 'sol_tx.id', 'sol_transfer1.sol_tx_id')
523
+ .select(['sol_tx.sig', 'sol_tx.executed_at'])
524
+ .innerJoin(`${exports.ENTITY_TABLE} as t`, `${exports.SOL_TRANSFER_TABLE}.to_entity_id`, 't.id')
525
+ .select(['t.sol_key as to_sol_key'])
526
+ .innerJoin(`${exports.ENTITY_TABLE} as f`, `${exports.SOL_TRANSFER_TABLE}.from_entity_id`, 'f.id')
527
+ .select(['f.sol_key as from_sol_key'])
528
+ .where('t.sol_key', '=', f.user);
529
+ log.info(`fetch liabilities ${lq.compile().sql} ps ${JSON.stringify(f)}`);
530
+ log.info(`fetch transfers ${tq.compile().sql} ps ${JSON.stringify(f)}`);
531
+ const lc = lq.compile();
532
+ const tc = tq.compile();
533
+ const [liabRes, transRes] = yield Promise.all([
534
+ (0, base_1.timedQuery)(pgPool, lc.sql, lc.parameters, 'getLiabilitiesAndTransfers->liabilities', log),
535
+ (0, base_1.timedQuery)(pgPool, tc.sql, tc.parameters, 'getLiabilitiesAndTransfers->transfers', log),
536
+ ]);
537
+ const rows = [liabRes.rows, transRes.rows];
538
+ const epochs = {};
539
+ const liabilities = [];
540
+ for (const l of rows[0]) {
541
+ epochs[`${l.ui}-${l.channel}`] = {
542
+ startTime: l.start_time,
543
+ endTime: l.end_time,
544
+ channel: l.channel,
545
+ ui: Number(l.ui),
546
+ };
547
+ liabilities.push({
548
+ id: BigInt(l.id),
549
+ solKey: l.sol_key,
550
+ epochId: Number(l.ui),
551
+ channel: l.channel,
552
+ createdAt: l.created_at,
553
+ amountDue: BigInt(l.amount_due),
554
+ deviceId: l.device_id,
555
+ points: l.points ? BigInt(l.points) : undefined,
556
+ });
557
+ }
558
+ const transfers = rows[1].map((r) => ({
559
+ id: BigInt(r.id),
560
+ fromSolKey: r.from_sol_key,
561
+ toSolKey: r.to_sol_key,
562
+ symbol: r.symbol,
563
+ channel: r.channel,
564
+ solTx: r.sig,
565
+ executedAt: r.executed_at,
566
+ amountPayed: BigInt(r.amount_payed),
567
+ }));
568
+ return { transfers, liabilities, epochs: Object.values(epochs) };
569
+ });
570
+ },
571
+ getOutstanding(f, log = logger_1.consoleLogger) {
572
+ var _a, _b;
573
+ return __awaiter(this, void 0, void 0, function* () {
574
+ let epochUi;
575
+ let epochEndTime;
576
+ if (f.startEpochId.id) {
577
+ if (((_a = f.channels) === null || _a === void 0 ? void 0 : _a.includes('node_operator')) ||
578
+ ((_b = f.channels) === null || _b === void 0 ? void 0 : _b.includes('availability'))) {
579
+ let qb = db
580
+ .selectFrom(exports.EPOCH_TABLE)
581
+ .selectAll(exports.EPOCH_TABLE)
582
+ .where('ui', '>', f.startEpochId.id.toString())
583
+ .where('channel', 'in', f.channels);
584
+ if (f.startEpochId.savedAtNotNull) {
585
+ qb = qb.where('saved_at', 'is not', null);
586
+ }
587
+ const e = yield qb
588
+ .orderBy('ui', 'desc')
589
+ .limit(1)
590
+ .executeTakeFirstOrThrow();
591
+ epochEndTime = e.end_time;
592
+ epochUi = e.ui;
593
+ }
594
+ else {
595
+ epochUi = f.startEpochId.id.toString();
596
+ }
597
+ }
598
+ let q = db
599
+ .selectFrom((eb) => eb
600
+ .selectFrom((eb) => {
601
+ let b = eb
602
+ .selectFrom(exports.SOL_TRANSFER_TABLE)
603
+ .select(({ fn }) => fn.sum(`amount_payed`).as('payed'))
604
+ .innerJoin(exports.ENTITY_TABLE, `${exports.SOL_TRANSFER_TABLE}.to_entity_id`, 'entity.id')
605
+ .select(['entity.sol_key'])
606
+ .groupBy('entity.sol_key');
607
+ if (f.banned) {
608
+ b = b.where('entity.banned', '=', true);
609
+ }
610
+ else {
611
+ b = b.where('entity.banned', '=', false);
612
+ }
613
+ if (epochEndTime) {
614
+ b = b
615
+ .innerJoin(exports.SOL_TX_TABLE, `${exports.SOL_TX_TABLE}.id`, `${exports.SOL_TRANSFER_TABLE}.sol_tx_id`)
616
+ .where(`${exports.SOL_TX_TABLE}.executed_at`, '>', epochEndTime);
617
+ }
618
+ if (f.channels && f.channels.length > 0) {
619
+ b = b.where((eb) => eb.or(f.channels.map((c) => eb('sol_transfer1.channel', '=', c))));
620
+ }
621
+ else {
622
+ b = b.where((eb) => eb.or([
623
+ eb('sol_transfer1.channel', '=', 'node_operator'),
624
+ eb('sol_transfer1.channel', '=', 'availability'),
625
+ ]));
626
+ }
627
+ return b.as('y');
628
+ })
629
+ .fullJoin((eb) => {
630
+ let b = eb
631
+ .selectFrom(exports.LIABILITY_TABLE)
632
+ .select(({ fn }) => fn.sum(`amount_due`).as('due'))
633
+ .innerJoin(exports.ENTITY_TABLE, `${exports.LIABILITY_TABLE}.entity_id`, 'entity.id')
634
+ .select(['entity.sol_key'])
635
+ .groupBy('entity.sol_key');
636
+ if (f.banned) {
637
+ b = b.where('entity.banned', '=', true);
638
+ }
639
+ else {
640
+ b = b.where('entity.banned', '=', false);
641
+ }
642
+ if (epochUi) {
643
+ b = b
644
+ .innerJoin(exports.EPOCH_TABLE, `${exports.LIABILITY_TABLE}.epoch_id`, `${exports.EPOCH_TABLE}.id`)
645
+ .where(`${exports.EPOCH_TABLE}.ui`, '>=', epochUi);
646
+ }
647
+ if (f.channels && f.channels.length > 0) {
648
+ b = b.where((eb) => eb.or(f.channels.map((c) => eb('liability.channel', '=', c))));
649
+ }
650
+ else {
651
+ b = b.where((eb) => eb.or([
652
+ eb('liability.channel', '=', 'node_operator'),
653
+ eb('liability.channel', '=', 'availability'),
654
+ ]));
655
+ }
656
+ return b.as('x');
657
+ }, (join) => join.onRef('y.sol_key', '=', 'x.sol_key'))
658
+ .select(({ fn }) => [
659
+ fn.coalesce('y.sol_key', 'x.sol_key').as('sol_key'),
660
+ (0, kysely_1.sql) `${fn.coalesce(`x.due`, (0, kysely_1.sql) `0`)} -
661
+ ${fn.coalesce(`y.payed`, (0, kysely_1.sql) `0`)}`.as('out'),
662
+ ])
663
+ .as('z'))
664
+ .selectAll();
665
+ if (f.due == 'overpayed') {
666
+ q = q.where('out', '<', '0');
667
+ }
668
+ else if (f.due == 'underpayed') {
669
+ q = q.where('out', '>', '0');
670
+ }
671
+ log.info(`${q.compile().sql} ps ${JSON.stringify(Object.assign(Object.assign({}, f), { epochEndTime,
672
+ epochUi }))}`);
673
+ const res = yield q.execute();
674
+ const out = {};
675
+ for (const r of res) {
676
+ out[r.sol_key] = BigInt(r.out);
677
+ }
678
+ return out;
679
+ });
680
+ },
681
+ fetchNodeOperatorEpoch(epochId, log = logger_1.consoleLogger) {
682
+ var _a;
683
+ return __awaiter(this, void 0, void 0, function* () {
684
+ const q = db
685
+ .selectFrom(exports.JOB_ID_TABLE)
686
+ .innerJoin(exports.EPOCH_TABLE, 'epoch.id', 'job_id.epoch_id')
687
+ .leftJoin(exports.MANUAL_BURN_TABLE, 'manual_burn.epoch_id', 'epoch.id')
688
+ .where('epoch.ui', '=', epochId.toString())
689
+ .where('epoch.channel', '=', 'node_operator')
690
+ .select([
691
+ 'job_id.id',
692
+ 'epoch.total_rndr',
693
+ 'epoch.start_time',
694
+ 'epoch.end_time',
695
+ 'manual_burn.burned',
696
+ 'manual_burn.tx_sig',
697
+ ])
698
+ .orderBy('job_id.id asc');
699
+ log.debug(`fetch epoch info q ${q.compile().sql} epochId ${epochId}`);
700
+ const res = yield q.execute();
701
+ if (res.length == 0) {
702
+ throw new Error(`epoch ${epochId} not found`);
703
+ }
704
+ log.debug(`fetchNodeOperatorEpoch -> fetching liablities`);
705
+ const ks = yield db
706
+ .selectFrom(exports.LIABILITY_TABLE)
707
+ .innerJoin(exports.ENTITY_TABLE, 'liability.entity_id', 'entity.id')
708
+ .select(({ fn }) => [
709
+ (0, kysely_1.sql) `distinct
710
+ (entity.sol_key)`.as('sol_key'),
711
+ ])
712
+ .innerJoin(exports.EPOCH_TABLE, 'liability.epoch_id', 'epoch.id')
713
+ .where('epoch.ui', '=', epochId.toString())
714
+ .where('epoch.channel', '=', 'node_operator')
715
+ .where('liability.channel', '=', 'node_operator')
716
+ .execute();
717
+ log.debug(`fetchNodeOperatorEpoch -> fetched liablities`);
718
+ const solKeys = ks.reduce((r, k) => {
719
+ r[k.sol_key] = {};
720
+ return r;
721
+ }, {});
722
+ return {
723
+ jobIds: res.map((r) => Number(r.id)),
724
+ totalRndr: BigInt(res[0].total_rndr),
725
+ startTime: res[0].start_time,
726
+ endTime: res[0].end_time,
727
+ burned: BigInt((_a = res[0].burned) !== null && _a !== void 0 ? _a : 0),
728
+ burnTx: res[0].tx_sig,
729
+ solKeys,
730
+ };
731
+ });
732
+ },
733
+ insertEpoch(db, epoch, log = logger_1.consoleLogger) {
734
+ return __awaiter(this, void 0, void 0, function* () {
735
+ yield getOrInsertEpoch(db.trx, Object.assign(Object.assign({}, epoch), { uiEpochId: epoch.ui }), log);
736
+ });
737
+ },
738
+ getEpoch(f, log = logger_1.consoleLogger) {
739
+ var _a;
740
+ return __awaiter(this, void 0, void 0, function* () {
741
+ const now = new Date(Date.now());
742
+ try {
743
+ let q = db
744
+ .selectFrom(exports.EPOCH_TABLE)
745
+ .selectAll()
746
+ .where('channel', '=', f.channel);
747
+ if (f.epochId) {
748
+ q = q.where('ui', '=', f.epochId.toString());
749
+ }
750
+ else {
751
+ q = q.where('end_time', '<=', now);
752
+ if (!f.savedAtNotNull) {
753
+ q = q.where('saved_at', 'is', null);
754
+ }
755
+ else {
756
+ q = q.where('saved_at', 'is not', null);
757
+ }
758
+ }
759
+ q = q.orderBy('end_time desc').limit(1);
760
+ const res = yield q.executeTakeFirstOrThrow();
761
+ return {
762
+ ui: Number(res.ui),
763
+ channel: f.channel,
764
+ startTime: res.start_time,
765
+ endTime: res.end_time,
766
+ savedAt: (_a = res.saved_at) !== null && _a !== void 0 ? _a : undefined,
767
+ };
768
+ }
769
+ catch (e) {
770
+ if (e instanceof kysely_1.NoResultError) {
771
+ log.info(`no node operator epoch found`);
772
+ return undefined;
773
+ }
774
+ throw e;
775
+ }
776
+ });
777
+ },
778
+ getLatestNodeOperatorEpoch(f, log = logger_1.consoleLogger) {
779
+ var _a;
780
+ return __awaiter(this, void 0, void 0, function* () {
781
+ const now = new Date(Date.now());
782
+ try {
783
+ let q = db
784
+ .selectFrom(exports.EPOCH_TABLE)
785
+ .selectAll()
786
+ .where('channel', '=', 'node_operator')
787
+ .where('end_time', '<=', now);
788
+ if (!f.latestDistributed) {
789
+ q = q.where('saved_at', 'is', null).orderBy('end_time asc');
790
+ }
791
+ else {
792
+ q = q.orderBy('end_time desc');
793
+ }
794
+ q = q.limit(1);
795
+ const res = yield q.executeTakeFirstOrThrow();
796
+ return {
797
+ epochId: BigInt(res.ui),
798
+ startedAt: res.start_time,
799
+ endedAt: res.end_time,
800
+ savedAt: (_a = res.saved_at) !== null && _a !== void 0 ? _a : undefined,
801
+ };
802
+ }
803
+ catch (e) {
804
+ if (e instanceof kysely_1.NoResultError) {
805
+ log.info(`no node operator epoch found`);
806
+ return undefined;
807
+ }
808
+ throw e;
809
+ }
810
+ });
811
+ },
812
+ insertEpochEntityInfo(db, eeis, log) {
813
+ return __awaiter(this, void 0, void 0, function* () {
814
+ for (const eei of eeis) {
815
+ yield db.trx.insertInto(exports.ENTITY_EPOCH_INFO_TABLE).values(eei).execute();
816
+ log.debug(`inserted eei ${JSON.stringify(eei)}`);
817
+ }
818
+ });
819
+ },
820
+ saveNodeOperatorEpoch(epochId, liabilities, jobIds, totalRndr, log = logger_1.consoleLogger) {
821
+ return __awaiter(this, void 0, void 0, function* () {
822
+ yield db
823
+ .transaction()
824
+ .setIsolationLevel('repeatable read')
825
+ .execute((trx) => __awaiter(this, void 0, void 0, function* () {
826
+ const { epochDbIds } = yield createPayments(trx, liabilities.map((l) => ({
827
+ liability: l,
828
+ })), log);
829
+ log.info(`inserted liabilities`);
830
+ for (const id of jobIds) {
831
+ yield trx
832
+ .insertInto(exports.JOB_ID_TABLE)
833
+ .values({
834
+ id: BigInt(id),
835
+ epoch_id: epochDbIds[0],
836
+ })
837
+ .executeTakeFirstOrThrow();
838
+ }
839
+ const now = new Date();
840
+ yield updateTotalRndr(db, { uiEpochId: epochId, channel: 'node_operator' }, totalRndr, now, log);
841
+ log.debug(`saved epoch`);
842
+ /*const now = new Date(Date.now())
843
+ const res = await trx
844
+ .updateTable(EPOCH_TABLE)
845
+ .set({
846
+ saved_at: now,
847
+ total_rndr: totalRndr,
848
+ })
849
+ .where('channel')
850
+ .where('ui', '=', epochId.toString())
851
+ .where('', '=')
852
+ .executeTakeFirstOrThrow()*/
853
+ }));
854
+ return;
855
+ });
856
+ },
857
+ produceBurnedJobs(jobs, log = logger_1.consoleLogger) {
858
+ return __awaiter(this, void 0, void 0, function* () {
859
+ yield db.transaction().execute((trx) => __awaiter(this, void 0, void 0, function* () {
860
+ var _a;
861
+ let num = BigInt(0);
862
+ for (const { amount, obhUsed, completedAt, jobId, userId } of jobs) {
863
+ const res = yield trx
864
+ .insertInto(exports.JOB_TABLE)
865
+ .values({
866
+ id: jobId,
867
+ render_amt: amount,
868
+ completed_at: completedAt,
869
+ inserted_at: new Date(Date.now()),
870
+ obh_used: obhUsed,
871
+ user_id: userId,
872
+ })
873
+ .onConflict((oc) => oc.column('id').doNothing())
874
+ .executeTakeFirstOrThrow();
875
+ num += (_a = res.numInsertedOrUpdatedRows) !== null && _a !== void 0 ? _a : BigInt(0);
876
+ }
877
+ log.debug(`inserted ${num} of ${jobs.length} burn jobs`);
878
+ }));
879
+ });
880
+ },
881
+ markJobsBurntWithGrant(db, p, log = logger_1.consoleLogger) {
882
+ var _a;
883
+ return __awaiter(this, void 0, void 0, function* () {
884
+ const solTxId = yield getOrInsertTx(db.trx, { sig: p.tx.sig, executedAt: p.tx.executedAt }, log);
885
+ const { id } = yield db.trx
886
+ .insertInto(exports.GRANT_BURN_TABLE)
887
+ .values({
888
+ sol_tx_id: solTxId,
889
+ burned: p.burned,
890
+ tags: (_a = p.tags) === null || _a === void 0 ? void 0 : _a.join(','),
891
+ })
892
+ .returning((eb) => ['id as id'])
893
+ .executeTakeFirstOrThrow();
894
+ const jobIdsStr = p.jobsIds.map(String);
895
+ const res = yield db.trx
896
+ .updateTable(exports.JOB_TABLE)
897
+ .where('id', 'in', jobIdsStr)
898
+ .set('grant_burn_id', id)
899
+ .executeTakeFirstOrThrow();
900
+ log.debug(`set grant_burn_id on ${res.numUpdatedRows} jobs`);
901
+ for (const [userId, grantSpendDelta] of Object.entries(p.userIdToGrantSpendDelta)) {
902
+ yield db.trx
903
+ .insertInto(exports.USER_GRANT_SPEND_TABLE)
904
+ .values({
905
+ user_id: userId,
906
+ grant_burn_id: id,
907
+ render_spent_delta: -grantSpendDelta,
908
+ })
909
+ .executeTakeFirstOrThrow();
910
+ }
911
+ return;
912
+ });
913
+ },
914
+ insertGrantSpend(db, p, log = logger_1.consoleLogger) {
915
+ var _a, _b, _c;
916
+ return __awaiter(this, void 0, void 0, function* () {
917
+ const existing = yield getCurrentUserGrantSpend(db.trx, { userId: p.userId }, log);
918
+ const diff = {
919
+ render_spent: ((_a = existing === null || existing === void 0 ? void 0 : existing.renderSpent) !== null && _a !== void 0 ? _a : BigInt(0)) + p.renderSpentDelta,
920
+ description: p.description ? p.description : existing === null || existing === void 0 ? void 0 : existing.description,
921
+ perpetual: p.perpetual ? p.perpetual : (_b = existing === null || existing === void 0 ? void 0 : existing.perpetual) !== null && _b !== void 0 ? _b : false,
922
+ updated_at: new Date(),
923
+ };
924
+ log.debug(`insertGrantSpend currUserGrantSpend: ${JSON.stringify(existing)} delta: ${JSON.stringify(p)}`);
925
+ const res = yield db.trx
926
+ .insertInto(exports.CURRENT_USER_GRANT_SPEND_TABLE)
927
+ .values({
928
+ user_id: p.userId,
929
+ render_spent: p.renderSpentDelta,
930
+ description: p.description,
931
+ perpetual: (_c = p.perpetual) !== null && _c !== void 0 ? _c : false,
932
+ })
933
+ .onConflict((oc) => oc.column('user_id').doUpdateSet(diff))
934
+ .returning((eb) => [
935
+ 'user_id as user_id',
936
+ 'render_spent as render_spent',
937
+ 'description as description',
938
+ 'perpetual as perpetual',
939
+ 'updated_at as updated_at',
940
+ ])
941
+ .executeTakeFirstOrThrow();
942
+ if (res) {
943
+ log.debug(`inserted current_user_grant_spend row ${JSON.stringify(res)}`);
944
+ }
945
+ if (p.renderSpentDelta > BigInt(0)) {
946
+ const v = {
947
+ user_id: p.userId,
948
+ render_spent_delta: p.renderSpentDelta,
949
+ grant_burn_id: p.grantBurnId,
950
+ };
951
+ const res = yield db.trx
952
+ .insertInto(exports.USER_GRANT_SPEND_TABLE)
953
+ .values(v)
954
+ .executeTakeFirstOrThrow();
955
+ log.debug(`inserted ${res.numInsertedOrUpdatedRows} user_grant_spend rows ${JSON.stringify(v)}`);
956
+ }
957
+ });
958
+ },
959
+ markJobsBurnt(trx, p, log = logger_1.consoleLogger) {
960
+ var _a, _b;
961
+ return __awaiter(this, void 0, void 0, function* () {
962
+ if (!p.buyBurn && !p.grantBurn) {
963
+ throw new Error('no buyBurn or grantBurn');
964
+ }
965
+ const solTxId = yield getOrInsertTx(trx, { sig: p.solTx.sig, executedAt: p.solTx.executedAt }, log);
966
+ let buyBurnId;
967
+ let grantBurnId;
968
+ if (p.buyBurn) {
969
+ const { burned, usdcSpent, eurToUsdc, renderToUsdc, quoteAmt, tags, burnAdjustmentId, toBurn, } = p.buyBurn;
970
+ let pricedAt = p.buyBurn.pricedAt;
971
+ if (!pricedAt) {
972
+ const jobs = yield fetchJobs1(trx, { ids: p.jobs.map((j) => String(j.id)) }, log);
973
+ pricedAt = (0, exports.batchFinishedAtMedian)(jobs.map((j) => ({
974
+ finishedAt: j.completedAt.toISOString(),
975
+ jobId: j.id,
976
+ rndrUsed: Number(j.rndrUsed.toString()),
977
+ })));
978
+ }
979
+ const { id } = yield trx
980
+ .insertInto(exports.BURN_TABLE)
981
+ .values({
982
+ sol_tx_id: solTxId,
983
+ priced_at: pricedAt,
984
+ eur_to_usdc: eurToUsdc,
985
+ render_to_usdc: renderToUsdc,
986
+ usdc_spent: usdcSpent,
987
+ quote_amt: quoteAmt,
988
+ burned: burned,
989
+ tags: tags.join(','),
990
+ burn_adjustment_id: burnAdjustmentId,
991
+ to_burn: toBurn,
992
+ })
993
+ //.onConflict((oc) => oc.column('sol_tx').doNothing())
994
+ .returning((eb) => ['id as id'])
995
+ .executeTakeFirstOrThrow();
996
+ buyBurnId = Number(id);
997
+ }
998
+ if (p.grantBurn) {
999
+ const { burned, tags } = p.grantBurn;
1000
+ const { id } = yield trx
1001
+ .insertInto(exports.GRANT_BURN_TABLE)
1002
+ .values({
1003
+ sol_tx_id: solTxId,
1004
+ burned: burned,
1005
+ tags: tags === null || tags === void 0 ? void 0 : tags.join(','),
1006
+ })
1007
+ .returning((eb) => ['id as id'])
1008
+ .executeTakeFirstOrThrow();
1009
+ grantBurnId = Number(id);
1010
+ }
1011
+ for (const job of p.jobs) {
1012
+ const res = yield trx
1013
+ .updateTable(exports.JOB_TABLE)
1014
+ .where('id', '=', String(job.id))
1015
+ .set('burn_id', job.buyRenderAmt != undefined ? buyBurnId : null)
1016
+ .set('grant_burn_id', job.grantRenderAmt != undefined ? grantBurnId : null)
1017
+ .set('buy_render_amt', (_a = job.buyRenderAmt) !== null && _a !== void 0 ? _a : 0)
1018
+ .set('grant_render_amt', (_b = job.grantRenderAmt) !== null && _b !== void 0 ? _b : 0)
1019
+ .executeTakeFirstOrThrow();
1020
+ 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}`);
1021
+ }
1022
+ return { grantBurnId, buyBurnId };
1023
+ });
1024
+ },
1025
+ markJobsBurned(trx, p, log = logger_1.consoleLogger) {
1026
+ return __awaiter(this, void 0, void 0, function* () {
1027
+ let { markedAt, solTx } = p;
1028
+ let res = yield trx.trx
1029
+ .updateTable(exports.BURN_TABLE)
1030
+ .set({ marked_burned_at: markedAt })
1031
+ .from(exports.SOL_TX_TABLE)
1032
+ .whereRef('burn.sol_tx_id', '=', 'sol_tx.id')
1033
+ .where('sol_tx.sig', '=', solTx)
1034
+ .executeTakeFirst();
1035
+ if (res) {
1036
+ log.debug(`buy burn set ${res.numUpdatedRows} ${solTx} -> marked_burned_at ${markedAt.toISOString()}`);
1037
+ }
1038
+ let res1 = yield trx.trx
1039
+ .updateTable(exports.GRANT_BURN_TABLE)
1040
+ .set({ marked_burned_at: markedAt })
1041
+ .from(exports.SOL_TX_TABLE)
1042
+ .whereRef('grant_burn.sol_tx_id', '=', 'sol_tx.id')
1043
+ .where('sol_tx.sig', '=', solTx)
1044
+ .executeTakeFirst();
1045
+ if (res1) {
1046
+ log.debug(`grant burn set ${res1.numUpdatedRows} ${solTx} -> marked_burned_at ${markedAt.toISOString()}`);
1047
+ }
1048
+ });
1049
+ },
1050
+ consumeAndLockBurnJobs(limit, lowerRndrThreshold, upperRndrThreshold, log = logger_1.consoleLogger) {
1051
+ return __awaiter(this, void 0, void 0, function* () {
1052
+ const trx = yield (0, base_2.begin)(db, log);
1053
+ const q = trx.trx
1054
+ .selectFrom(trx.trx
1055
+ .selectFrom(exports.JOB_TABLE)
1056
+ .select(({ fn, val, ref }) => [
1057
+ 'id',
1058
+ fn
1059
+ .sum('render_amt')
1060
+ .over((ob) => ob.orderBy(`completed_at`, `asc`))
1061
+ .as('total'),
1062
+ ])
1063
+ .where('burn_id', 'is', null)
1064
+ .where('grant_burn_id', 'is', null)
1065
+ .as('t'))
1066
+ .select('id')
1067
+ .where('total', '>=', lowerRndrThreshold)
1068
+ .where('total', '<=', upperRndrThreshold);
1069
+ log.debug(`outstanding jobs q: ${q.compile().sql} ${JSON.stringify({
1070
+ limit,
1071
+ lowerRndrThreshold,
1072
+ upperRndrThreshold,
1073
+ })}`);
1074
+ const idRs = yield q.execute();
1075
+ const ids = idRs.map((x) => x.id);
1076
+ log.debug(`${ids.length} candidate jobs for burn. locking up to ${limit} jobs`);
1077
+ if (ids.length == 0) {
1078
+ return { trx, jobs: [] };
1079
+ }
1080
+ const rows = yield trx.trx
1081
+ .selectFrom(exports.JOB_TABLE)
1082
+ .selectAll()
1083
+ .where('id', 'in', ids)
1084
+ .limit(limit)
1085
+ .forUpdate()
1086
+ .skipLocked()
1087
+ .execute();
1088
+ log.debug(`locked ${rows.length} jobs`);
1089
+ const jobs = [];
1090
+ for (const r of rows) {
1091
+ jobs.push({
1092
+ id: Number(r.id),
1093
+ completedAt: r.completed_at,
1094
+ userId: r.user_id,
1095
+ rndrUsed: BigInt(r.render_amt),
1096
+ });
1097
+ }
1098
+ return { trx, jobs };
1099
+ });
1100
+ },
1101
+ paymentMetrics(log) {
1102
+ return __awaiter(this, void 0, void 0, function* () {
1103
+ // Get the latest epochs for each channel
1104
+ const latestEpochs = yield db
1105
+ .selectFrom(exports.EPOCH_TABLE)
1106
+ .select(['id', 'ui', 'channel', 'start_time', 'end_time'])
1107
+ .where('channel', 'in', [
1108
+ 'availability',
1109
+ 'node_operator',
1110
+ 'render_compute_network',
1111
+ ])
1112
+ .distinctOn('channel')
1113
+ .where('saved_at', 'is not', null)
1114
+ .orderBy('channel')
1115
+ .orderBy('ui', 'desc')
1116
+ .execute();
1117
+ // Calculate distributed rewards for each channel
1118
+ let availabilityRewards = 0;
1119
+ let nodeOperatorRewards = 0;
1120
+ let renderComputeNetworkRewards = 0;
1121
+ let latestEpochId = 0;
1122
+ for (const epoch of latestEpochs) {
1123
+ if (!epoch.end_time) {
1124
+ log === null || log === void 0 ? void 0 : log.info(`Skipping epoch ${epoch.ui} for channel ${epoch.channel} - no end_time`);
1125
+ continue;
1126
+ }
1127
+ // Get total distributed rewards for this channel after epoch ended
1128
+ const transfersResult = yield db
1129
+ .selectFrom(exports.SOL_TRANSFER_TABLE)
1130
+ .innerJoin('sol_tx', 'sol_tx.id', `${exports.SOL_TRANSFER_TABLE}.sol_tx_id`)
1131
+ .select([(eb) => eb.fn.sum('amount_payed').as('total_distributed')])
1132
+ .where(`${exports.SOL_TRANSFER_TABLE}.channel`, '=', epoch.channel)
1133
+ .where('sol_tx.executed_at', '>', epoch.end_time)
1134
+ .executeTakeFirst();
1135
+ const totalDistributed = Number((transfersResult === null || transfersResult === void 0 ? void 0 : transfersResult.total_distributed) || 0);
1136
+ switch (epoch.channel) {
1137
+ case 'availability':
1138
+ availabilityRewards = totalDistributed;
1139
+ break;
1140
+ case 'node_operator':
1141
+ nodeOperatorRewards = totalDistributed;
1142
+ latestEpochId = Number(epoch.ui);
1143
+ break;
1144
+ case 'render_compute_network':
1145
+ renderComputeNetworkRewards = totalDistributed;
1146
+ break;
1147
+ }
1148
+ log === null || log === void 0 ? void 0 : log.info(`Channel ${epoch.channel}: ${totalDistributed} distributed after epoch ${epoch.ui}`);
1149
+ }
1150
+ return {
1151
+ latestEpochId,
1152
+ availabilityRewards,
1153
+ nodeOperatorRewards,
1154
+ renderComputeNetworkRewards,
1155
+ };
1156
+ });
1157
+ },
1158
+ incrBuyBurnMetrics(log = logger_1.consoleLogger) {
1159
+ var _a;
1160
+ return __awaiter(this, void 0, void 0, function* () {
1161
+ const res = yield db
1162
+ .selectFrom(exports.JOB_TABLE)
1163
+ .select('inserted_at')
1164
+ .orderBy('completed_at asc')
1165
+ .where('burn_id', 'is', null)
1166
+ .execute();
1167
+ if (res.length == 0) {
1168
+ return { outstandingJobs: 0 };
1169
+ }
1170
+ return {
1171
+ outstandingJobs: res.length,
1172
+ oldestJobInsertedAt: (_a = res[0].inserted_at) !== null && _a !== void 0 ? _a : undefined,
1173
+ };
1174
+ });
1175
+ },
1176
+ fetchBurns(db, f, log = logger_1.consoleLogger) {
1177
+ var _a, _b;
1178
+ return __awaiter(this, void 0, void 0, function* () {
1179
+ let q = db.trx
1180
+ .selectFrom('burn')
1181
+ .selectAll('burn')
1182
+ .innerJoin('sol_tx', 'sol_tx.id', 'burn.sol_tx_id')
1183
+ .select(['sol_tx.executed_at', 'sol_tx.sig']);
1184
+ if (!f.inclManual) {
1185
+ q = q.where('burn.usdc_spent', '>', String(0));
1186
+ }
1187
+ if (f.executedAfter) {
1188
+ q = q.where('sol_tx.executed_at', '>=', f.executedAfter);
1189
+ }
1190
+ if (f.executedBefore) {
1191
+ q = q.where('sol_tx.executed_at', '<=', f.executedBefore);
1192
+ }
1193
+ if (f.pricedAtBefore) {
1194
+ q = q.where('burn.priced_at', '<=', f.pricedAtBefore);
1195
+ }
1196
+ if (f.pricedAtAfter) {
1197
+ q = q.where('burn.priced_at', '>=', f.pricedAtAfter);
1198
+ }
1199
+ if (f.orderBy == 'pricedAt') {
1200
+ q = q.orderBy(['burn.priced_at']);
1201
+ }
1202
+ else if (f.orderBy == 'executedAt') {
1203
+ q = q.orderBy(['sol_tx.executed_at']);
1204
+ }
1205
+ log.info(`fetchBurns q ${q.compile().sql} ${JSON.stringify(f)}`);
1206
+ const burns = [];
1207
+ const burnIdToIdx = {};
1208
+ const comp = q.compile();
1209
+ const { rows } = yield (0, base_1.timedQuery)(pgPool, comp.sql, comp.parameters, 'fetchBurns', log);
1210
+ log.info(`fetchBurns len ${rows.length}`);
1211
+ for (const r of rows) {
1212
+ burns.push({
1213
+ jobs: [],
1214
+ id: Number(r.id),
1215
+ renderToUsdc: r.render_to_usdc,
1216
+ solTx: r.sig,
1217
+ executedAt: r.executed_at,
1218
+ pricedAt: r.priced_at,
1219
+ usdcSpent: BigInt((_a = r.usdc_spent) !== null && _a !== void 0 ? _a : 0),
1220
+ quoteAmt: BigInt((_b = r.quote_amt) !== null && _b !== void 0 ? _b : 0),
1221
+ burned: BigInt(r.burned),
1222
+ eurToUsdc: r.eur_to_usdc,
1223
+ markedBurnedAt: r.marked_burned_at,
1224
+ tags: r.tags ? r.tags.split(',') : [],
1225
+ });
1226
+ burnIdToIdx[r.id] = burns.length - 1;
1227
+ }
1228
+ if (f.inclJobs) {
1229
+ const jobRows = yield db.trx
1230
+ .selectFrom('job')
1231
+ .selectAll('job')
1232
+ .where('burn_id', 'in', rows.map((r) => r.id))
1233
+ .execute();
1234
+ log.info(`fetchBurns jobRows len ${jobRows.length}`);
1235
+ for (const r of jobRows) {
1236
+ burns[burnIdToIdx[r.burn_id]].jobs.push({
1237
+ id: Number(r.id),
1238
+ completedAt: r.completed_at,
1239
+ rndrUsed: BigInt(r.render_amt),
1240
+ obhUsed: r.obh_used ? Number(r.obh_used) : undefined,
1241
+ });
1242
+ }
1243
+ }
1244
+ return burns;
1245
+ });
1246
+ },
1247
+ createBridgeTransfers(db, bts, log = logger_1.consoleLogger) {
1248
+ return __awaiter(this, void 0, void 0, function* () {
1249
+ return createBridgeTransfers(db.trx, bts, log);
1250
+ });
1251
+ },
1252
+ getBridgeTransfers({ solKey, page, }, log = logger_1.consoleLogger) {
1253
+ return __awaiter(this, void 0, void 0, function* () {
1254
+ let q = db
1255
+ .selectFrom(exports.BRIDGE_TRANSFER_TABLE)
1256
+ .innerJoin(exports.EPOCH_TABLE, 'epoch.id', 'bridge_transfer.epoch_id')
1257
+ .innerJoin(exports.ENTITY_TABLE, 'entity.id', 'bridge_transfer.entity_id')
1258
+ .select([
1259
+ 'entity.sol_key',
1260
+ 'bridge_transfer.sequence',
1261
+ 'bridge_transfer.created_at',
1262
+ 'bridge_transfer.amount',
1263
+ 'bridge_transfer.upgrade_bracket',
1264
+ 'bridge_transfer.prior_supply',
1265
+ 'bridge_transfer.points',
1266
+ 'epoch.ui',
1267
+ ]);
1268
+ let limit = 10000;
1269
+ if (page && page.limit) {
1270
+ limit = page.limit;
1271
+ }
1272
+ q = q.limit(page.limit).orderBy(`${exports.BRIDGE_TRANSFER_TABLE}.id`);
1273
+ let offset = 0;
1274
+ if (page && page.cursor) {
1275
+ offset = Number(atob(page.cursor));
1276
+ q = q.offset(offset);
1277
+ }
1278
+ if (solKey) {
1279
+ q = q.where('entity.sol_key', '=', solKey);
1280
+ }
1281
+ const c = q.compile();
1282
+ log.debug(`fetch bridge transfers ${c.sql} params ${c.parameters}`);
1283
+ const res = yield q.execute();
1284
+ log.info(`bridge transfers ${res.length}`);
1285
+ return {
1286
+ bts: res.map((row) => {
1287
+ return {
1288
+ solKey: row.sol_key,
1289
+ seq: BigInt(row.sequence),
1290
+ createdAt: row.created_at,
1291
+ amount: BigInt(row.amount),
1292
+ upgradeBracket: row.upgrade_bracket
1293
+ ? Number(row.upgrade_bracket)
1294
+ : undefined,
1295
+ priorSupply: BigInt(row.prior_supply),
1296
+ points: row.points ? BigInt(row.points) : undefined,
1297
+ epochId: Number(row.ui),
1298
+ };
1299
+ }),
1300
+ cursor: res.length == limit ? btoa(`${res.length + offset}`) : undefined,
1301
+ };
1302
+ });
1303
+ },
1304
+ getLiabilitySolKeys(f) {
1305
+ return __awaiter(this, void 0, void 0, function* () {
1306
+ let q = db
1307
+ .selectFrom(exports.LIABILITY_TABLE)
1308
+ .innerJoin(exports.ENTITY_TABLE, `${exports.LIABILITY_TABLE}.entity_id`, 'entity.id')
1309
+ .select(({ fn }) => [
1310
+ (0, kysely_1.sql) `distinct
1311
+ (entity.sol_key)`.as('sol_key'),
1312
+ ])
1313
+ .where(`${exports.LIABILITY_TABLE}.channel`, '=', f.channel);
1314
+ if (f.epoch) {
1315
+ q = q.where('liability.epoch_id', '=', db
1316
+ .selectFrom('epoch')
1317
+ .select('id')
1318
+ .where('channel', '=', f.channel)
1319
+ .where('ui', '=', String(f.epoch)));
1320
+ }
1321
+ const ks = yield q.execute();
1322
+ const solKeys = {};
1323
+ for (const k of ks) {
1324
+ solKeys[k.sol_key] = {};
1325
+ }
1326
+ return solKeys;
1327
+ });
1328
+ },
1329
+ getTotalBurned(db) {
1330
+ var _a, _b;
1331
+ return __awaiter(this, void 0, void 0, function* () {
1332
+ const total = yield db.trx
1333
+ .selectFrom('burn')
1334
+ .select(({ fn }) => fn.sum('burned').as('total_burned'))
1335
+ .execute();
1336
+ return BigInt((_b = (_a = total[0]) === null || _a === void 0 ? void 0 : _a.total_burned) !== null && _b !== void 0 ? _b : 0);
1337
+ });
1338
+ },
1339
+ insertBurn(p, log = logger_1.consoleLogger) {
1340
+ return __awaiter(this, void 0, void 0, function* () {
1341
+ yield db.transaction().execute((trx) => __awaiter(this, void 0, void 0, function* () {
1342
+ var _a;
1343
+ const solTxId = yield getOrInsertTx(trx, { sig: p.solTx, executedAt: p.executedAt }, log);
1344
+ const { id } = yield trx
1345
+ .insertInto(exports.BURN_TABLE)
1346
+ .values({
1347
+ sol_tx_id: solTxId,
1348
+ priced_at: p.pricedAt,
1349
+ usdc_spent: p.usdcSpent,
1350
+ quote_amt: p.quoteAmt,
1351
+ burned: p.burned,
1352
+ marked_burned_at: p.markedBurnedAt,
1353
+ })
1354
+ //.onConflict((oc) => oc.column('sol_tx').doNothing())
1355
+ .returning((eb) => ['id as id'])
1356
+ .executeTakeFirstOrThrow();
1357
+ let num = BigInt(0);
1358
+ for (const { rndrUsed, completedAt, id: jobId, insertedAt, userId, } of p.jobs) {
1359
+ const res = yield trx
1360
+ .insertInto(exports.JOB_TABLE)
1361
+ .values({
1362
+ id: jobId,
1363
+ render_amt: rndrUsed,
1364
+ burn_id: id,
1365
+ completed_at: completedAt,
1366
+ inserted_at: insertedAt !== null && insertedAt !== void 0 ? insertedAt : new Date(),
1367
+ user_id: userId,
1368
+ })
1369
+ .onConflict((oc) => oc.column('id').doNothing())
1370
+ .executeTakeFirstOrThrow();
1371
+ num += (_a = res.numInsertedOrUpdatedRows) !== null && _a !== void 0 ? _a : BigInt(0);
1372
+ }
1373
+ log.debug(`burn id ${id} inserted ${num} of ${p.jobs.length} burn jobs`);
1374
+ }));
1375
+ });
1376
+ },
1377
+ fetchJobs(db, f, log = logger_1.consoleLogger) {
1378
+ return __awaiter(this, void 0, void 0, function* () {
1379
+ return yield fetchJobs1(db.trx, f, log);
1380
+ });
1381
+ },
1382
+ fetchLiabilityEpochs(db, log = logger_1.consoleLogger) {
1383
+ return __awaiter(this, void 0, void 0, function* () {
1384
+ const q = db.trx
1385
+ .selectFrom(exports.LIABILITY_TABLE)
1386
+ .select(({ fn }) => [
1387
+ `${exports.LIABILITY_TABLE}.channel`,
1388
+ fn.sum(`${exports.LIABILITY_TABLE}.amount_due`).as('amount_due'),
1389
+ ])
1390
+ .innerJoin(exports.EPOCH_TABLE, `${exports.EPOCH_TABLE}.id`, `${exports.LIABILITY_TABLE}.epoch_id`)
1391
+ .select(['ui', 'start_time', 'end_time'])
1392
+ .groupBy([
1393
+ 'liability.channel',
1394
+ 'epoch.ui',
1395
+ 'epoch.start_time',
1396
+ 'epoch.end_time',
1397
+ ])
1398
+ .orderBy(['epoch.start_time desc']);
1399
+ // Fetch node_operator SOL key metadata separately
1400
+ const nodeOpMetadataQuery = db.trx
1401
+ .selectFrom(exports.LIABILITY_TABLE)
1402
+ .select([`${exports.LIABILITY_TABLE}.obh_used`])
1403
+ .innerJoin(exports.EPOCH_TABLE, `${exports.EPOCH_TABLE}.id`, `${exports.LIABILITY_TABLE}.epoch_id`)
1404
+ .select([`${exports.EPOCH_TABLE}.ui as epoch_ui`])
1405
+ .innerJoin('entity', 'entity.id', `${exports.LIABILITY_TABLE}.entity_id`)
1406
+ .select(['entity.sol_key'])
1407
+ .where(`${exports.LIABILITY_TABLE}.channel`, '=', 'node_operator')
1408
+ .where('entity.sol_key', 'is not', null)
1409
+ .where(`${exports.LIABILITY_TABLE}.obh_used`, 'is not', null);
1410
+ log.debug(`fetchLiabilityEpochs ${q.compile().sql}`);
1411
+ log.debug(`nodeOpMetadata ${nodeOpMetadataQuery.compile().sql}`);
1412
+ const [rs, nodeOpMetadata] = yield Promise.all([
1413
+ q.execute(),
1414
+ nodeOpMetadataQuery.execute(),
1415
+ ]);
1416
+ // Group node operator metadata by epoch
1417
+ const metadataByEpoch = {};
1418
+ nodeOpMetadata.forEach((row) => {
1419
+ const epochId = Number(row.epoch_ui);
1420
+ if (!metadataByEpoch[epochId]) {
1421
+ metadataByEpoch[epochId] = {};
1422
+ }
1423
+ if (row.sol_key && row.obh_used !== null) {
1424
+ metadataByEpoch[epochId][row.sol_key] = {
1425
+ obhUsed: Number(row.obh_used),
1426
+ };
1427
+ }
1428
+ });
1429
+ return rs.map((r) => ({
1430
+ epochId: Number(r.ui),
1431
+ channel: r.channel,
1432
+ start: r.start_time,
1433
+ end: r.end_time,
1434
+ amountDue: Number(r.amount_due),
1435
+ metadataBySolKey: r.channel === 'node_operator'
1436
+ ? metadataByEpoch[Number(r.ui)] || {}
1437
+ : {},
1438
+ }));
1439
+ });
1440
+ },
1441
+ getBurnAdjustments(trx, ps, log = logger_1.consoleLogger) {
1442
+ return __awaiter(this, void 0, void 0, function* () {
1443
+ if (ps.toFill) {
1444
+ const q = trx
1445
+ .selectFrom(exports.BURN_ADJUSTMENT_TABLE)
1446
+ .selectAll(exports.BURN_ADJUSTMENT_TABLE)
1447
+ .innerJoin(exports.JOB_TABLE, `${exports.JOB_TABLE}.id`, `${exports.BURN_ADJUSTMENT_TABLE}.job_id`)
1448
+ .select([`${exports.JOB_TABLE}.completed_at`, `${exports.JOB_TABLE}.render_amt`])
1449
+ .leftJoin(exports.BURN_TABLE, `${exports.BURN_TABLE}.burn_adjustment_id`, `${exports.BURN_ADJUSTMENT_TABLE}.id`)
1450
+ .select(({ fn, lit }) => [
1451
+ fn
1452
+ .sum(fn.coalesce(`${exports.BURN_TABLE}.to_burn`, lit(0)))
1453
+ .as('tot_to_burn'),
1454
+ fn
1455
+ .sum(fn.coalesce(`${exports.BURN_TABLE}.burned`, lit(0)))
1456
+ .as('tot_burned'),
1457
+ ])
1458
+ .groupBy([
1459
+ `${exports.BURN_ADJUSTMENT_TABLE}.id`,
1460
+ `${exports.JOB_TABLE}.completed_at`,
1461
+ `${exports.JOB_TABLE}.render_amt`,
1462
+ ])
1463
+ .havingRef((0, kysely_1.sql) `SUM(COALESCE("burn"."to_burn", 0)) - SUM(COALESCE("burn"."burned", 0))`, '<', `${exports.BURN_ADJUSTMENT_TABLE}.down_adj_to_burn`);
1464
+ log.info(`getBurnAdjustments ${q.compile().sql}`);
1465
+ const res = yield q.execute();
1466
+ return res.map((r) => ({
1467
+ id: Number(r.id),
1468
+ createdAt: r.created_at,
1469
+ jobId: Number(r.job_id),
1470
+ downAdjRndrUsed: Number(r.down_adj_rndr_used),
1471
+ downAdjToBurn: Number(r.down_adj_to_burn),
1472
+ adjusted: Number(r.tot_to_burn) - Number(r.tot_burned),
1473
+ job: {
1474
+ id: Number(r.job_id),
1475
+ completedAt: r.completed_at,
1476
+ rndrUsed: BigInt(r.render_amt),
1477
+ },
1478
+ }));
1479
+ }
1480
+ return [];
1481
+ });
1482
+ },
1483
+ insertPolygonUpgrade(db, p, log = logger_1.consoleLogger) {
1484
+ return __awaiter(this, void 0, void 0, function* () {
1485
+ const solTxId = yield getOrInsertTx(db.trx, {
1486
+ sig: p.solTx.sig,
1487
+ executedAt: p.solTx.executedAt,
1488
+ });
1489
+ yield db.trx
1490
+ .insertInto(exports.POLYGON_UPGRADE_TABLE)
1491
+ .values({
1492
+ eth_addr: p.ethAddr,
1493
+ sol_addr: p.solAddr,
1494
+ amount: p.amount,
1495
+ sol_tx_id: solTxId,
1496
+ })
1497
+ .execute();
1498
+ log.info(`insertPolygonUpgrade ${JSON.stringify(p)}`);
1499
+ return;
1500
+ });
1501
+ },
1502
+ fetchPolygonUpgrades(db, f, log = logger_1.consoleLogger) {
1503
+ return __awaiter(this, void 0, void 0, function* () {
1504
+ let query = db.trx
1505
+ .selectFrom('polygon_upgrade')
1506
+ .selectAll('polygon_upgrade')
1507
+ .innerJoin('sol_tx', 'sol_tx.id', 'polygon_upgrade.sol_tx_id')
1508
+ .select(['sol_tx.sig', 'sol_tx.executed_at'])
1509
+ .orderBy('sol_tx.executed_at', 'desc');
1510
+ if (f.executedAfter) {
1511
+ query = query.where('sol_tx.executed_at', '>=', f.executedAfter);
1512
+ }
1513
+ if (f.executedBefore) {
1514
+ query = query.where('sol_tx.executed_at', '<=', f.executedBefore);
1515
+ }
1516
+ const results = yield query.execute();
1517
+ log.info(`fetchPolygonUpgrades returned ${results.length} records`);
1518
+ return results.map((row) => ({
1519
+ ethAddr: row.eth_addr,
1520
+ solAddr: row.sol_addr,
1521
+ amount: BigInt(row.amount.toString()),
1522
+ solTx: {
1523
+ sig: row.sig,
1524
+ executedAt: row.executed_at,
1525
+ },
1526
+ }));
1527
+ });
1528
+ },
1529
+ getCurrentUserGrantSpend(db, f, log = logger_1.consoleLogger) {
1530
+ return __awaiter(this, void 0, void 0, function* () {
1531
+ return yield getCurrentUserGrantSpend(db.trx, f, log);
1532
+ });
1533
+ },
1534
+ deleteAll(log = logger_1.consoleLogger) {
1535
+ return __awaiter(this, void 0, void 0, function* () {
1536
+ if (config.database.includes('render')) {
1537
+ throw new Error('cannot nuke from deployed database. call from tests only');
1538
+ }
1539
+ const tx = yield (0, base_2.begin)(db, log);
1540
+ try {
1541
+ const res = yield Promise.all([
1542
+ tx.trx
1543
+ .deleteFrom(exports.SOL_TX_TABLE)
1544
+ .where('id', 'is not', null)
1545
+ .executeTakeFirst(),
1546
+ tx.trx.deleteFrom(exports.LIABILITY_TABLE).executeTakeFirstOrThrow(),
1547
+ tx.trx.deleteFrom(exports.SOL_TRANSFER_TABLE).executeTakeFirstOrThrow(),
1548
+ tx.trx
1549
+ .deleteFrom(exports.EPOCH_TABLE)
1550
+ .where('id', 'is not', null)
1551
+ .executeTakeFirst(),
1552
+ tx.trx
1553
+ .deleteFrom(exports.ENTITY_TABLE)
1554
+ .where('id', 'is not', null)
1555
+ .executeTakeFirst(),
1556
+ tx.trx
1557
+ .deleteFrom(exports.MANUAL_BURN_TABLE)
1558
+ .where('epoch_id', 'is not', null)
1559
+ .executeTakeFirst(),
1560
+ tx.trx
1561
+ .deleteFrom(exports.JOB_ID_TABLE)
1562
+ .where('id', 'is not', null)
1563
+ .executeTakeFirst(),
1564
+ tx.trx
1565
+ .deleteFrom(exports.JOB_TABLE)
1566
+ .where('id', 'is not', null)
1567
+ .executeTakeFirst(),
1568
+ tx.trx
1569
+ .deleteFrom(exports.BURN_TABLE)
1570
+ .where('id', 'is not', null)
1571
+ .executeTakeFirst(),
1572
+ ]);
1573
+ tx.commit();
1574
+ }
1575
+ catch (e) {
1576
+ log.error(`caught ${e}`);
1577
+ tx.rollback();
1578
+ }
1579
+ });
1580
+ },
1581
+ };
1582
+ };
1583
+ exports.pgClient = pgClient;
1584
+ //# sourceMappingURL=v2Client.js.map