@render-foundation/utils 0.0.188 → 0.0.190

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 +932 -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 +1607 -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 +48 -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 +886 -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 +1488 -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 +45 -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 -0
  74. package/lib/types/src/backfiller.d.ts +64 -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 +308 -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 +43 -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 +194 -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 +2 -1
@@ -0,0 +1,1607 @@
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, _c, _d, _e;
573
+ return __awaiter(this, void 0, void 0, function* () {
574
+ log.info(`getting outstanding balances for ${(_a = f.channels) !== null && _a !== void 0 ? _a : '(no channels specified)'} epoch: ${(_b = f.startEpochId.id) !== null && _b !== void 0 ? _b : '(no epoch specified)'}`);
575
+ let epochUi;
576
+ let epochEndTime;
577
+ if (f.startEpochId.id) {
578
+ if (((_c = f.channels) === null || _c === void 0 ? void 0 : _c.includes('node_operator')) ||
579
+ ((_d = f.channels) === null || _d === void 0 ? void 0 : _d.includes('availability')) ||
580
+ ((_e = f.channels) === null || _e === void 0 ? void 0 : _e.includes('render_compute_network'))) {
581
+ let qb = db
582
+ .selectFrom(exports.EPOCH_TABLE)
583
+ .selectAll(exports.EPOCH_TABLE)
584
+ .where('ui', '=', f.startEpochId.id.toString())
585
+ .where('channel', 'in', f.channels);
586
+ if (f.startEpochId.savedAtNotNull) {
587
+ qb = qb.where('saved_at', 'is not', null);
588
+ }
589
+ const q = qb.orderBy('ui', 'desc').limit(1);
590
+ log.info(`getOutstanding->epoch ${qb.compile().sql} ps ${JSON.stringify(f)}`);
591
+ const e = yield q.executeTakeFirstOrThrow();
592
+ epochEndTime = e.end_time;
593
+ epochUi = e.ui;
594
+ }
595
+ else {
596
+ epochUi = f.startEpochId.id.toString();
597
+ }
598
+ }
599
+ let q = db
600
+ .selectFrom((eb) => eb
601
+ .selectFrom((eb) => {
602
+ let b = eb
603
+ .selectFrom(exports.SOL_TRANSFER_TABLE)
604
+ .select(({ fn }) => fn.sum(`amount_payed`).as('payed'))
605
+ .innerJoin(exports.ENTITY_TABLE, `${exports.SOL_TRANSFER_TABLE}.to_entity_id`, 'entity.id')
606
+ .select(['entity.sol_key'])
607
+ .groupBy('entity.sol_key');
608
+ if (f.banned) {
609
+ b = b.where('entity.banned', '=', true);
610
+ }
611
+ else {
612
+ b = b.where('entity.banned', '=', false);
613
+ }
614
+ if (epochEndTime) {
615
+ b = b
616
+ .innerJoin(exports.SOL_TX_TABLE, `${exports.SOL_TX_TABLE}.id`, `${exports.SOL_TRANSFER_TABLE}.sol_tx_id`)
617
+ .where(`${exports.SOL_TX_TABLE}.executed_at`, '>', epochEndTime);
618
+ }
619
+ if (f.channels && f.channels.length > 0) {
620
+ b = b.where((eb) => eb.or(f.channels.map((c) => eb('sol_transfer1.channel', '=', c))));
621
+ }
622
+ else {
623
+ b = b.where((eb) => eb.or([
624
+ eb('sol_transfer1.channel', '=', 'node_operator'),
625
+ eb('sol_transfer1.channel', '=', 'availability'),
626
+ ]));
627
+ }
628
+ return b.as('y');
629
+ })
630
+ .fullJoin((eb) => {
631
+ let b = eb
632
+ .selectFrom(exports.LIABILITY_TABLE)
633
+ .select(({ fn }) => fn.sum(`amount_due`).as('due'))
634
+ .innerJoin(exports.ENTITY_TABLE, `${exports.LIABILITY_TABLE}.entity_id`, 'entity.id')
635
+ .select(['entity.sol_key'])
636
+ .groupBy('entity.sol_key');
637
+ if (f.banned) {
638
+ b = b.where('entity.banned', '=', true);
639
+ }
640
+ else {
641
+ b = b.where('entity.banned', '=', false);
642
+ }
643
+ if (epochUi) {
644
+ b = b
645
+ .innerJoin(exports.EPOCH_TABLE, `${exports.LIABILITY_TABLE}.epoch_id`, `${exports.EPOCH_TABLE}.id`)
646
+ .where(`${exports.EPOCH_TABLE}.ui`, '>=', epochUi);
647
+ }
648
+ if (f.channels && f.channels.length > 0) {
649
+ b = b.where((eb) => eb.or(f.channels.map((c) => eb('liability.channel', '=', c))));
650
+ }
651
+ else {
652
+ b = b.where((eb) => eb.or([
653
+ eb('liability.channel', '=', 'node_operator'),
654
+ eb('liability.channel', '=', 'availability'),
655
+ ]));
656
+ }
657
+ return b.as('x');
658
+ }, (join) => join.onRef('y.sol_key', '=', 'x.sol_key'))
659
+ .select(({ fn }) => [
660
+ fn.coalesce('y.sol_key', 'x.sol_key').as('sol_key'),
661
+ (0, kysely_1.sql) `${fn.coalesce(`x.due`, (0, kysely_1.sql) `0`)} -
662
+ ${fn.coalesce(`y.payed`, (0, kysely_1.sql) `0`)}`.as('out'),
663
+ ])
664
+ .as('z'))
665
+ .selectAll();
666
+ if (f.due == 'overpayed') {
667
+ q = q.where('out', '<', '0');
668
+ }
669
+ else if (f.due == 'underpayed') {
670
+ q = q.where('out', '>', '0');
671
+ }
672
+ log.info(`${q.compile().sql} ps ${JSON.stringify(Object.assign(Object.assign({}, f), { epochEndTime,
673
+ epochUi }))}`);
674
+ const res = yield q.execute();
675
+ const out = {};
676
+ for (const r of res) {
677
+ out[r.sol_key] = BigInt(r.out);
678
+ }
679
+ return out;
680
+ });
681
+ },
682
+ fetchNodeOperatorEpoch(epochId, log = logger_1.consoleLogger) {
683
+ var _a;
684
+ return __awaiter(this, void 0, void 0, function* () {
685
+ const q = db
686
+ .selectFrom(exports.JOB_ID_TABLE)
687
+ .innerJoin(exports.EPOCH_TABLE, 'epoch.id', 'job_id.epoch_id')
688
+ .leftJoin(exports.MANUAL_BURN_TABLE, 'manual_burn.epoch_id', 'epoch.id')
689
+ .where('epoch.ui', '=', epochId.toString())
690
+ .where('epoch.channel', '=', 'node_operator')
691
+ .select([
692
+ 'job_id.id',
693
+ 'epoch.total_rndr',
694
+ 'epoch.start_time',
695
+ 'epoch.end_time',
696
+ 'manual_burn.burned',
697
+ 'manual_burn.tx_sig',
698
+ ])
699
+ .orderBy('job_id.id asc');
700
+ log.debug(`fetch epoch info q ${q.compile().sql} epochId ${epochId}`);
701
+ const res = yield q.execute();
702
+ if (res.length == 0) {
703
+ throw new Error(`epoch ${epochId} not found`);
704
+ }
705
+ log.debug(`fetchNodeOperatorEpoch -> fetching liablities`);
706
+ const ks = yield db
707
+ .selectFrom(exports.LIABILITY_TABLE)
708
+ .innerJoin(exports.ENTITY_TABLE, 'liability.entity_id', 'entity.id')
709
+ .select(({ fn }) => [
710
+ (0, kysely_1.sql) `distinct
711
+ (entity.sol_key)`.as('sol_key'),
712
+ ])
713
+ .innerJoin(exports.EPOCH_TABLE, 'liability.epoch_id', 'epoch.id')
714
+ .where('epoch.ui', '=', epochId.toString())
715
+ .where('epoch.channel', '=', 'node_operator')
716
+ .where('liability.channel', '=', 'node_operator')
717
+ .execute();
718
+ log.debug(`fetchNodeOperatorEpoch -> fetched liablities`);
719
+ const solKeys = ks.reduce((r, k) => {
720
+ r[k.sol_key] = {};
721
+ return r;
722
+ }, {});
723
+ return {
724
+ jobIds: res.map((r) => Number(r.id)),
725
+ totalRndr: BigInt(res[0].total_rndr),
726
+ startTime: res[0].start_time,
727
+ endTime: res[0].end_time,
728
+ burned: BigInt((_a = res[0].burned) !== null && _a !== void 0 ? _a : 0),
729
+ burnTx: res[0].tx_sig,
730
+ solKeys,
731
+ };
732
+ });
733
+ },
734
+ insertEpoch(db, epoch, log = logger_1.consoleLogger) {
735
+ return __awaiter(this, void 0, void 0, function* () {
736
+ yield getOrInsertEpoch(db.trx, Object.assign(Object.assign({}, epoch), { uiEpochId: epoch.ui }), log);
737
+ });
738
+ },
739
+ getEpoch(f, log = logger_1.consoleLogger) {
740
+ var _a;
741
+ return __awaiter(this, void 0, void 0, function* () {
742
+ const now = new Date(Date.now());
743
+ try {
744
+ let q = db
745
+ .selectFrom(exports.EPOCH_TABLE)
746
+ .selectAll()
747
+ .where('channel', '=', f.channel);
748
+ if (f.epochId) {
749
+ q = q.where('ui', '=', f.epochId.toString());
750
+ }
751
+ else {
752
+ q = q.where('end_time', '<=', now);
753
+ if (!f.savedAtNotNull) {
754
+ q = q.where('saved_at', 'is', null);
755
+ }
756
+ else {
757
+ q = q.where('saved_at', 'is not', null);
758
+ }
759
+ }
760
+ q = q.orderBy('end_time desc').limit(1);
761
+ const res = yield q.executeTakeFirstOrThrow();
762
+ return {
763
+ ui: Number(res.ui),
764
+ channel: f.channel,
765
+ startTime: res.start_time,
766
+ endTime: res.end_time,
767
+ savedAt: (_a = res.saved_at) !== null && _a !== void 0 ? _a : undefined,
768
+ };
769
+ }
770
+ catch (e) {
771
+ if (e instanceof kysely_1.NoResultError) {
772
+ log.info(`no node operator epoch found`);
773
+ return undefined;
774
+ }
775
+ throw e;
776
+ }
777
+ });
778
+ },
779
+ getLatestNodeOperatorEpoch(f, log = logger_1.consoleLogger) {
780
+ var _a;
781
+ return __awaiter(this, void 0, void 0, function* () {
782
+ const now = new Date(Date.now());
783
+ try {
784
+ let q = db
785
+ .selectFrom(exports.EPOCH_TABLE)
786
+ .selectAll()
787
+ .where('channel', '=', 'node_operator')
788
+ .where('end_time', '<=', now);
789
+ if (!f.latestDistributed) {
790
+ q = q.where('saved_at', 'is', null).orderBy('end_time asc');
791
+ }
792
+ else {
793
+ q = q.orderBy('end_time desc');
794
+ }
795
+ q = q.limit(1);
796
+ const res = yield q.executeTakeFirstOrThrow();
797
+ return {
798
+ epochId: BigInt(res.ui),
799
+ startedAt: res.start_time,
800
+ endedAt: res.end_time,
801
+ savedAt: (_a = res.saved_at) !== null && _a !== void 0 ? _a : undefined,
802
+ };
803
+ }
804
+ catch (e) {
805
+ if (e instanceof kysely_1.NoResultError) {
806
+ log.info(`no node operator epoch found`);
807
+ return undefined;
808
+ }
809
+ throw e;
810
+ }
811
+ });
812
+ },
813
+ insertEpochEntityInfo(db, eeis, log) {
814
+ return __awaiter(this, void 0, void 0, function* () {
815
+ for (const eei of eeis) {
816
+ yield db.trx.insertInto(exports.ENTITY_EPOCH_INFO_TABLE).values(eei).execute();
817
+ log.debug(`inserted eei ${JSON.stringify(eei)}`);
818
+ }
819
+ });
820
+ },
821
+ saveNodeOperatorEpoch(epochId, liabilities, jobIds, totalRndr, log = logger_1.consoleLogger) {
822
+ return __awaiter(this, void 0, void 0, function* () {
823
+ yield db
824
+ .transaction()
825
+ .setIsolationLevel('repeatable read')
826
+ .execute((trx) => __awaiter(this, void 0, void 0, function* () {
827
+ const { epochDbIds } = yield createPayments(trx, liabilities.map((l) => ({
828
+ liability: l,
829
+ })), log);
830
+ log.info(`inserted liabilities`);
831
+ for (const id of jobIds) {
832
+ yield trx
833
+ .insertInto(exports.JOB_ID_TABLE)
834
+ .values({
835
+ id: BigInt(id),
836
+ epoch_id: epochDbIds[0],
837
+ })
838
+ .executeTakeFirstOrThrow();
839
+ }
840
+ const now = new Date();
841
+ yield updateTotalRndr(db, { uiEpochId: epochId, channel: 'node_operator' }, totalRndr, now, log);
842
+ log.debug(`saved epoch`);
843
+ /*const now = new Date(Date.now())
844
+ const res = await trx
845
+ .updateTable(EPOCH_TABLE)
846
+ .set({
847
+ saved_at: now,
848
+ total_rndr: totalRndr,
849
+ })
850
+ .where('channel')
851
+ .where('ui', '=', epochId.toString())
852
+ .where('', '=')
853
+ .executeTakeFirstOrThrow()*/
854
+ }));
855
+ return;
856
+ });
857
+ },
858
+ produceBurnedJobs(jobs, log = logger_1.consoleLogger) {
859
+ return __awaiter(this, void 0, void 0, function* () {
860
+ yield db.transaction().execute((trx) => __awaiter(this, void 0, void 0, function* () {
861
+ var _a;
862
+ let num = BigInt(0);
863
+ for (const { amount, obhUsed, completedAt, jobId, userId } of jobs) {
864
+ const res = yield trx
865
+ .insertInto(exports.JOB_TABLE)
866
+ .values({
867
+ id: jobId,
868
+ render_amt: amount,
869
+ completed_at: completedAt,
870
+ inserted_at: new Date(Date.now()),
871
+ obh_used: obhUsed,
872
+ user_id: userId,
873
+ })
874
+ .onConflict((oc) => oc.column('id').doNothing())
875
+ .executeTakeFirstOrThrow();
876
+ num += (_a = res.numInsertedOrUpdatedRows) !== null && _a !== void 0 ? _a : BigInt(0);
877
+ }
878
+ log.debug(`inserted ${num} of ${jobs.length} burn jobs`);
879
+ }));
880
+ });
881
+ },
882
+ markJobsBurntWithGrant(db, p, log = logger_1.consoleLogger) {
883
+ var _a;
884
+ return __awaiter(this, void 0, void 0, function* () {
885
+ const solTxId = yield getOrInsertTx(db.trx, { sig: p.tx.sig, executedAt: p.tx.executedAt }, log);
886
+ const { id } = yield db.trx
887
+ .insertInto(exports.GRANT_BURN_TABLE)
888
+ .values({
889
+ sol_tx_id: solTxId,
890
+ burned: p.burned,
891
+ tags: (_a = p.tags) === null || _a === void 0 ? void 0 : _a.join(','),
892
+ })
893
+ .returning((eb) => ['id as id'])
894
+ .executeTakeFirstOrThrow();
895
+ const jobIdsStr = p.jobsIds.map(String);
896
+ const res = yield db.trx
897
+ .updateTable(exports.JOB_TABLE)
898
+ .where('id', 'in', jobIdsStr)
899
+ .set('grant_burn_id', id)
900
+ .executeTakeFirstOrThrow();
901
+ log.debug(`set grant_burn_id on ${res.numUpdatedRows} jobs`);
902
+ for (const [userId, grantSpendDelta] of Object.entries(p.userIdToGrantSpendDelta)) {
903
+ yield db.trx
904
+ .insertInto(exports.USER_GRANT_SPEND_TABLE)
905
+ .values({
906
+ user_id: userId,
907
+ grant_burn_id: id,
908
+ render_spent_delta: -grantSpendDelta,
909
+ })
910
+ .executeTakeFirstOrThrow();
911
+ }
912
+ return;
913
+ });
914
+ },
915
+ insertGrantSpend(db, p, log = logger_1.consoleLogger) {
916
+ var _a, _b, _c;
917
+ return __awaiter(this, void 0, void 0, function* () {
918
+ const existing = yield getCurrentUserGrantSpend(db.trx, { userId: p.userId }, log);
919
+ const diff = {
920
+ render_spent: ((_a = existing === null || existing === void 0 ? void 0 : existing.renderSpent) !== null && _a !== void 0 ? _a : BigInt(0)) + p.renderSpentDelta,
921
+ description: p.description ? p.description : existing === null || existing === void 0 ? void 0 : existing.description,
922
+ perpetual: p.perpetual ? p.perpetual : (_b = existing === null || existing === void 0 ? void 0 : existing.perpetual) !== null && _b !== void 0 ? _b : false,
923
+ updated_at: new Date(),
924
+ };
925
+ log.debug(`insertGrantSpend currUserGrantSpend: ${JSON.stringify(existing)} delta: ${JSON.stringify(p)}`);
926
+ let inserted = false;
927
+ if (p.renderSpentDelta != BigInt(0)) {
928
+ // Check if entry with same job_id and sign already exists
929
+ if (p.jobId) {
930
+ const existingEntry = yield db.trx
931
+ .selectFrom(exports.USER_GRANT_SPEND_TABLE)
932
+ .select(['id'])
933
+ .where('job_id', '=', String(p.jobId))
934
+ .where(p.renderSpentDelta > 0
935
+ ? 'render_spent_delta'
936
+ : 'render_spent_delta', p.renderSpentDelta > 0 ? '>' : '<', String(0))
937
+ .executeTakeFirst();
938
+ if (existingEntry) {
939
+ log.warn(`user_grant_spend job_id ${p.jobId} with same sign already exists. skipping`);
940
+ return;
941
+ }
942
+ }
943
+ const v = {
944
+ user_id: p.userId,
945
+ render_spent_delta: p.renderSpentDelta,
946
+ grant_burn_id: p.grantBurnId,
947
+ job_id: p.jobId,
948
+ };
949
+ const res = yield db.trx
950
+ .insertInto(exports.USER_GRANT_SPEND_TABLE)
951
+ .values(v)
952
+ .executeTakeFirstOrThrow();
953
+ log.debug(`inserted ${res.numInsertedOrUpdatedRows} user_grant_spend rows ${JSON.stringify(v)}`);
954
+ inserted = res.numInsertedOrUpdatedRows > 0;
955
+ }
956
+ if (!inserted) {
957
+ log.warn(`user_grant_spend job_id ${p.jobId} with same sign already exists. skipping`);
958
+ return;
959
+ }
960
+ const res = yield db.trx
961
+ .insertInto(exports.CURRENT_USER_GRANT_SPEND_TABLE)
962
+ .values({
963
+ user_id: p.userId,
964
+ render_spent: p.renderSpentDelta,
965
+ description: p.description,
966
+ perpetual: (_c = p.perpetual) !== null && _c !== void 0 ? _c : false,
967
+ })
968
+ .onConflict((oc) => oc.column('user_id').doUpdateSet(diff))
969
+ .returning((eb) => [
970
+ 'user_id as user_id',
971
+ 'render_spent as render_spent',
972
+ 'description as description',
973
+ 'perpetual as perpetual',
974
+ 'updated_at as updated_at',
975
+ ])
976
+ .executeTakeFirstOrThrow();
977
+ if (res) {
978
+ log.debug(`inserted current_user_grant_spend row ${JSON.stringify(res)}`);
979
+ }
980
+ });
981
+ },
982
+ markJobsBurnt(trx, p, log = logger_1.consoleLogger) {
983
+ var _a, _b;
984
+ return __awaiter(this, void 0, void 0, function* () {
985
+ if (!p.buyBurn && !p.grantBurn) {
986
+ throw new Error('no buyBurn or grantBurn');
987
+ }
988
+ const solTxId = yield getOrInsertTx(trx.trx, { sig: p.solTx.sig, executedAt: p.solTx.executedAt }, log);
989
+ let buyBurnId;
990
+ let grantBurnId;
991
+ if (p.buyBurn) {
992
+ const { burned, usdcSpent, eurToUsdc, renderToUsdc, quoteAmt, tags, burnAdjustmentId, toBurn, } = p.buyBurn;
993
+ let pricedAt = p.buyBurn.pricedAt;
994
+ if (!pricedAt) {
995
+ const jobs = yield fetchJobs1(trx.trx, { ids: p.jobs.map((j) => String(j.id)) }, log);
996
+ pricedAt = (0, exports.batchFinishedAtMedian)(jobs.map((j) => ({
997
+ finishedAt: j.completedAt.toISOString(),
998
+ jobId: j.id,
999
+ rndrUsed: Number(j.rndrUsed.toString()),
1000
+ })));
1001
+ }
1002
+ const { id } = yield trx.trx
1003
+ .insertInto(exports.BURN_TABLE)
1004
+ .values({
1005
+ sol_tx_id: solTxId,
1006
+ priced_at: pricedAt,
1007
+ eur_to_usdc: eurToUsdc,
1008
+ render_to_usdc: renderToUsdc,
1009
+ usdc_spent: usdcSpent,
1010
+ quote_amt: quoteAmt,
1011
+ burned: burned,
1012
+ tags: tags.join(','),
1013
+ burn_adjustment_id: burnAdjustmentId,
1014
+ to_burn: toBurn,
1015
+ })
1016
+ //.onConflict((oc) => oc.column('sol_tx').doNothing())
1017
+ .returning((eb) => ['id as id'])
1018
+ .executeTakeFirstOrThrow();
1019
+ buyBurnId = Number(id);
1020
+ }
1021
+ if (p.grantBurn) {
1022
+ const { burned, tags } = p.grantBurn;
1023
+ const { id } = yield trx.trx
1024
+ .insertInto(exports.GRANT_BURN_TABLE)
1025
+ .values({
1026
+ sol_tx_id: solTxId,
1027
+ burned: burned,
1028
+ tags: tags === null || tags === void 0 ? void 0 : tags.join(','),
1029
+ })
1030
+ .returning((eb) => ['id as id'])
1031
+ .executeTakeFirstOrThrow();
1032
+ grantBurnId = Number(id);
1033
+ }
1034
+ for (const job of p.jobs) {
1035
+ const res = yield trx.trx
1036
+ .updateTable(exports.JOB_TABLE)
1037
+ .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('buy_render_amt', (_a = job.buyRenderAmt) !== null && _a !== void 0 ? _a : 0)
1041
+ .set('grant_render_amt', (_b = job.grantRenderAmt) !== null && _b !== void 0 ? _b : 0)
1042
+ .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}`);
1044
+ }
1045
+ return { grantBurnId, buyBurnId };
1046
+ });
1047
+ },
1048
+ markJobsBurned(trx, p, log = logger_1.consoleLogger) {
1049
+ return __awaiter(this, void 0, void 0, function* () {
1050
+ let { markedAt, solTx } = p;
1051
+ let res = yield trx.trx
1052
+ .updateTable(exports.BURN_TABLE)
1053
+ .set({ marked_burned_at: markedAt })
1054
+ .from(exports.SOL_TX_TABLE)
1055
+ .whereRef('burn.sol_tx_id', '=', 'sol_tx.id')
1056
+ .where('sol_tx.sig', '=', solTx)
1057
+ .executeTakeFirst();
1058
+ if (res) {
1059
+ log.debug(`buy burn set ${res.numUpdatedRows} ${solTx} -> marked_burned_at ${markedAt.toISOString()}`);
1060
+ }
1061
+ let res1 = yield trx.trx
1062
+ .updateTable(exports.GRANT_BURN_TABLE)
1063
+ .set({ marked_burned_at: markedAt })
1064
+ .from(exports.SOL_TX_TABLE)
1065
+ .whereRef('grant_burn.sol_tx_id', '=', 'sol_tx.id')
1066
+ .where('sol_tx.sig', '=', solTx)
1067
+ .executeTakeFirst();
1068
+ if (res1) {
1069
+ log.debug(`grant burn set ${res1.numUpdatedRows} ${solTx} -> marked_burned_at ${markedAt.toISOString()}`);
1070
+ }
1071
+ });
1072
+ },
1073
+ consumeAndLockBurnJobs(limit, lowerRndrThreshold, upperRndrThreshold, log = logger_1.consoleLogger) {
1074
+ return __awaiter(this, void 0, void 0, function* () {
1075
+ const trx = yield (0, base_2.begin)(db, log);
1076
+ const q = trx.trx
1077
+ .selectFrom(trx.trx
1078
+ .selectFrom(exports.JOB_TABLE)
1079
+ .select(({ fn, val, ref }) => [
1080
+ 'id',
1081
+ fn
1082
+ .sum('render_amt')
1083
+ .over((ob) => ob.orderBy(`completed_at`, `asc`))
1084
+ .as('total'),
1085
+ ])
1086
+ .where('burn_id', 'is', null)
1087
+ .where('grant_burn_id', 'is', null)
1088
+ .as('t'))
1089
+ .select('id')
1090
+ .where('total', '>=', lowerRndrThreshold)
1091
+ .where('total', '<=', upperRndrThreshold);
1092
+ log.debug(`outstanding jobs q: ${q.compile().sql} ${JSON.stringify({
1093
+ limit,
1094
+ lowerRndrThreshold,
1095
+ upperRndrThreshold,
1096
+ })}`);
1097
+ const idRs = yield q.execute();
1098
+ const ids = idRs.map((x) => x.id);
1099
+ log.debug(`${ids.length} candidate jobs for burn. locking up to ${limit} jobs`);
1100
+ if (ids.length == 0) {
1101
+ return { trx, jobs: [] };
1102
+ }
1103
+ const rows = yield trx.trx
1104
+ .selectFrom(exports.JOB_TABLE)
1105
+ .selectAll()
1106
+ .where('id', 'in', ids)
1107
+ .limit(limit)
1108
+ .forUpdate()
1109
+ .skipLocked()
1110
+ .execute();
1111
+ log.debug(`locked ${rows.length} jobs`);
1112
+ const jobs = [];
1113
+ for (const r of rows) {
1114
+ jobs.push({
1115
+ id: Number(r.id),
1116
+ completedAt: r.completed_at,
1117
+ userId: r.user_id,
1118
+ rndrUsed: BigInt(r.render_amt),
1119
+ });
1120
+ }
1121
+ return { trx, jobs };
1122
+ });
1123
+ },
1124
+ paymentMetrics(log) {
1125
+ return __awaiter(this, void 0, void 0, function* () {
1126
+ // Get the latest epochs for each channel
1127
+ const latestEpochs = yield db
1128
+ .selectFrom(exports.EPOCH_TABLE)
1129
+ .select(['id', 'ui', 'channel', 'start_time', 'end_time'])
1130
+ .where('channel', 'in', [
1131
+ 'availability',
1132
+ 'node_operator',
1133
+ 'render_compute_network',
1134
+ ])
1135
+ .distinctOn('channel')
1136
+ .where('saved_at', 'is not', null)
1137
+ .orderBy('channel')
1138
+ .orderBy('ui', 'desc')
1139
+ .execute();
1140
+ // Calculate distributed rewards for each channel
1141
+ let availabilityRewards = 0;
1142
+ let nodeOperatorRewards = 0;
1143
+ let renderComputeNetworkRewards = 0;
1144
+ let latestEpochId = 0;
1145
+ for (const epoch of latestEpochs) {
1146
+ if (!epoch.end_time) {
1147
+ log === null || log === void 0 ? void 0 : log.info(`Skipping epoch ${epoch.ui} for channel ${epoch.channel} - no end_time`);
1148
+ continue;
1149
+ }
1150
+ // Get total distributed rewards for this channel after epoch ended
1151
+ const transfersResult = yield db
1152
+ .selectFrom(exports.SOL_TRANSFER_TABLE)
1153
+ .innerJoin('sol_tx', 'sol_tx.id', `${exports.SOL_TRANSFER_TABLE}.sol_tx_id`)
1154
+ .select([(eb) => eb.fn.sum('amount_payed').as('total_distributed')])
1155
+ .where(`${exports.SOL_TRANSFER_TABLE}.channel`, '=', epoch.channel)
1156
+ .where('sol_tx.executed_at', '>', epoch.end_time)
1157
+ .executeTakeFirst();
1158
+ const totalDistributed = Number((transfersResult === null || transfersResult === void 0 ? void 0 : transfersResult.total_distributed) || 0);
1159
+ switch (epoch.channel) {
1160
+ case 'availability':
1161
+ availabilityRewards = totalDistributed;
1162
+ break;
1163
+ case 'node_operator':
1164
+ nodeOperatorRewards = totalDistributed;
1165
+ latestEpochId = Number(epoch.ui);
1166
+ break;
1167
+ case 'render_compute_network':
1168
+ renderComputeNetworkRewards = totalDistributed;
1169
+ break;
1170
+ }
1171
+ log === null || log === void 0 ? void 0 : log.info(`Channel ${epoch.channel}: ${totalDistributed} distributed after epoch ${epoch.ui}`);
1172
+ }
1173
+ return {
1174
+ latestEpochId,
1175
+ availabilityRewards,
1176
+ nodeOperatorRewards,
1177
+ renderComputeNetworkRewards,
1178
+ };
1179
+ });
1180
+ },
1181
+ incrBuyBurnMetrics(log = logger_1.consoleLogger) {
1182
+ var _a;
1183
+ return __awaiter(this, void 0, void 0, function* () {
1184
+ const res = yield db
1185
+ .selectFrom(exports.JOB_TABLE)
1186
+ .select('inserted_at')
1187
+ .orderBy('completed_at asc')
1188
+ .where('burn_id', 'is', null)
1189
+ .execute();
1190
+ if (res.length == 0) {
1191
+ return { outstandingJobs: 0 };
1192
+ }
1193
+ return {
1194
+ outstandingJobs: res.length,
1195
+ oldestJobInsertedAt: (_a = res[0].inserted_at) !== null && _a !== void 0 ? _a : undefined,
1196
+ };
1197
+ });
1198
+ },
1199
+ fetchBurns(db, f, log = logger_1.consoleLogger) {
1200
+ var _a, _b;
1201
+ return __awaiter(this, void 0, void 0, function* () {
1202
+ let q = db.trx
1203
+ .selectFrom('burn')
1204
+ .selectAll('burn')
1205
+ .innerJoin('sol_tx', 'sol_tx.id', 'burn.sol_tx_id')
1206
+ .select(['sol_tx.executed_at', 'sol_tx.sig']);
1207
+ if (!f.inclManual) {
1208
+ q = q.where('burn.usdc_spent', '>', String(0));
1209
+ }
1210
+ if (f.executedAfter) {
1211
+ q = q.where('sol_tx.executed_at', '>=', f.executedAfter);
1212
+ }
1213
+ if (f.executedBefore) {
1214
+ q = q.where('sol_tx.executed_at', '<=', f.executedBefore);
1215
+ }
1216
+ if (f.pricedAtBefore) {
1217
+ q = q.where('burn.priced_at', '<=', f.pricedAtBefore);
1218
+ }
1219
+ if (f.pricedAtAfter) {
1220
+ q = q.where('burn.priced_at', '>=', f.pricedAtAfter);
1221
+ }
1222
+ if (f.orderBy == 'pricedAt') {
1223
+ q = q.orderBy(['burn.priced_at']);
1224
+ }
1225
+ else if (f.orderBy == 'executedAt') {
1226
+ q = q.orderBy(['sol_tx.executed_at']);
1227
+ }
1228
+ log.info(`fetchBurns q ${q.compile().sql} ${JSON.stringify(f)}`);
1229
+ const burns = [];
1230
+ const burnIdToIdx = {};
1231
+ const comp = q.compile();
1232
+ const { rows } = yield (0, base_1.timedQuery)(pgPool, comp.sql, comp.parameters, 'fetchBurns', log);
1233
+ log.info(`fetchBurns len ${rows.length}`);
1234
+ for (const r of rows) {
1235
+ burns.push({
1236
+ jobs: [],
1237
+ id: Number(r.id),
1238
+ renderToUsdc: r.render_to_usdc,
1239
+ solTx: r.sig,
1240
+ executedAt: r.executed_at,
1241
+ pricedAt: r.priced_at,
1242
+ usdcSpent: BigInt((_a = r.usdc_spent) !== null && _a !== void 0 ? _a : 0),
1243
+ quoteAmt: BigInt((_b = r.quote_amt) !== null && _b !== void 0 ? _b : 0),
1244
+ burned: BigInt(r.burned),
1245
+ eurToUsdc: r.eur_to_usdc,
1246
+ markedBurnedAt: r.marked_burned_at,
1247
+ tags: r.tags ? r.tags.split(',') : [],
1248
+ });
1249
+ burnIdToIdx[r.id] = burns.length - 1;
1250
+ }
1251
+ if (f.inclJobs) {
1252
+ const jobRows = yield db.trx
1253
+ .selectFrom('job')
1254
+ .selectAll('job')
1255
+ .where('burn_id', 'in', rows.map((r) => r.id))
1256
+ .execute();
1257
+ log.info(`fetchBurns jobRows len ${jobRows.length}`);
1258
+ for (const r of jobRows) {
1259
+ burns[burnIdToIdx[r.burn_id]].jobs.push({
1260
+ id: Number(r.id),
1261
+ completedAt: r.completed_at,
1262
+ rndrUsed: BigInt(r.render_amt),
1263
+ obhUsed: r.obh_used ? Number(r.obh_used) : undefined,
1264
+ });
1265
+ }
1266
+ }
1267
+ return burns;
1268
+ });
1269
+ },
1270
+ createBridgeTransfers(db, bts, log = logger_1.consoleLogger) {
1271
+ return __awaiter(this, void 0, void 0, function* () {
1272
+ return createBridgeTransfers(db.trx, bts, log);
1273
+ });
1274
+ },
1275
+ getBridgeTransfers({ solKey, page, }, log = logger_1.consoleLogger) {
1276
+ return __awaiter(this, void 0, void 0, function* () {
1277
+ let q = db
1278
+ .selectFrom(exports.BRIDGE_TRANSFER_TABLE)
1279
+ .innerJoin(exports.EPOCH_TABLE, 'epoch.id', 'bridge_transfer.epoch_id')
1280
+ .innerJoin(exports.ENTITY_TABLE, 'entity.id', 'bridge_transfer.entity_id')
1281
+ .select([
1282
+ 'entity.sol_key',
1283
+ 'bridge_transfer.sequence',
1284
+ 'bridge_transfer.created_at',
1285
+ 'bridge_transfer.amount',
1286
+ 'bridge_transfer.upgrade_bracket',
1287
+ 'bridge_transfer.prior_supply',
1288
+ 'bridge_transfer.points',
1289
+ 'epoch.ui',
1290
+ ]);
1291
+ let limit = 10000;
1292
+ if (page && page.limit) {
1293
+ limit = page.limit;
1294
+ }
1295
+ q = q.limit(page.limit).orderBy(`${exports.BRIDGE_TRANSFER_TABLE}.id`);
1296
+ let offset = 0;
1297
+ if (page && page.cursor) {
1298
+ offset = Number(atob(page.cursor));
1299
+ q = q.offset(offset);
1300
+ }
1301
+ if (solKey) {
1302
+ q = q.where('entity.sol_key', '=', solKey);
1303
+ }
1304
+ const c = q.compile();
1305
+ log.debug(`fetch bridge transfers ${c.sql} params ${c.parameters}`);
1306
+ const res = yield q.execute();
1307
+ log.info(`bridge transfers ${res.length}`);
1308
+ return {
1309
+ bts: res.map((row) => {
1310
+ return {
1311
+ solKey: row.sol_key,
1312
+ seq: BigInt(row.sequence),
1313
+ createdAt: row.created_at,
1314
+ amount: BigInt(row.amount),
1315
+ upgradeBracket: row.upgrade_bracket
1316
+ ? Number(row.upgrade_bracket)
1317
+ : undefined,
1318
+ priorSupply: BigInt(row.prior_supply),
1319
+ points: row.points ? BigInt(row.points) : undefined,
1320
+ epochId: Number(row.ui),
1321
+ };
1322
+ }),
1323
+ cursor: res.length == limit ? btoa(`${res.length + offset}`) : undefined,
1324
+ };
1325
+ });
1326
+ },
1327
+ getLiabilitySolKeys(f) {
1328
+ return __awaiter(this, void 0, void 0, function* () {
1329
+ let q = db
1330
+ .selectFrom(exports.LIABILITY_TABLE)
1331
+ .innerJoin(exports.ENTITY_TABLE, `${exports.LIABILITY_TABLE}.entity_id`, 'entity.id')
1332
+ .select(({ fn }) => [
1333
+ (0, kysely_1.sql) `distinct
1334
+ (entity.sol_key)`.as('sol_key'),
1335
+ ])
1336
+ .where(`${exports.LIABILITY_TABLE}.channel`, '=', f.channel);
1337
+ if (f.epoch) {
1338
+ q = q.where('liability.epoch_id', '=', db
1339
+ .selectFrom('epoch')
1340
+ .select('id')
1341
+ .where('channel', '=', f.channel)
1342
+ .where('ui', '=', String(f.epoch)));
1343
+ }
1344
+ const ks = yield q.execute();
1345
+ const solKeys = {};
1346
+ for (const k of ks) {
1347
+ solKeys[k.sol_key] = {};
1348
+ }
1349
+ return solKeys;
1350
+ });
1351
+ },
1352
+ getTotalBurned(db) {
1353
+ var _a, _b;
1354
+ return __awaiter(this, void 0, void 0, function* () {
1355
+ const total = yield db.trx
1356
+ .selectFrom('burn')
1357
+ .select(({ fn }) => fn.sum('burned').as('total_burned'))
1358
+ .execute();
1359
+ return BigInt((_b = (_a = total[0]) === null || _a === void 0 ? void 0 : _a.total_burned) !== null && _b !== void 0 ? _b : 0);
1360
+ });
1361
+ },
1362
+ insertBurn(p, log = logger_1.consoleLogger) {
1363
+ return __awaiter(this, void 0, void 0, function* () {
1364
+ yield db.transaction().execute((trx) => __awaiter(this, void 0, void 0, function* () {
1365
+ var _a;
1366
+ const solTxId = yield getOrInsertTx(trx, { sig: p.solTx, executedAt: p.executedAt }, log);
1367
+ const { id } = yield trx
1368
+ .insertInto(exports.BURN_TABLE)
1369
+ .values({
1370
+ sol_tx_id: solTxId,
1371
+ priced_at: p.pricedAt,
1372
+ usdc_spent: p.usdcSpent,
1373
+ quote_amt: p.quoteAmt,
1374
+ burned: p.burned,
1375
+ marked_burned_at: p.markedBurnedAt,
1376
+ })
1377
+ //.onConflict((oc) => oc.column('sol_tx').doNothing())
1378
+ .returning((eb) => ['id as id'])
1379
+ .executeTakeFirstOrThrow();
1380
+ let num = BigInt(0);
1381
+ for (const { rndrUsed, completedAt, id: jobId, insertedAt, userId, } of p.jobs) {
1382
+ const res = yield trx
1383
+ .insertInto(exports.JOB_TABLE)
1384
+ .values({
1385
+ id: jobId,
1386
+ render_amt: rndrUsed,
1387
+ burn_id: id,
1388
+ completed_at: completedAt,
1389
+ inserted_at: insertedAt !== null && insertedAt !== void 0 ? insertedAt : new Date(),
1390
+ user_id: userId,
1391
+ })
1392
+ .onConflict((oc) => oc.column('id').doNothing())
1393
+ .executeTakeFirstOrThrow();
1394
+ num += (_a = res.numInsertedOrUpdatedRows) !== null && _a !== void 0 ? _a : BigInt(0);
1395
+ }
1396
+ log.debug(`burn id ${id} inserted ${num} of ${p.jobs.length} burn jobs`);
1397
+ }));
1398
+ });
1399
+ },
1400
+ fetchJobs(db, f, log = logger_1.consoleLogger) {
1401
+ return __awaiter(this, void 0, void 0, function* () {
1402
+ return yield fetchJobs1(db.trx, f, log);
1403
+ });
1404
+ },
1405
+ fetchLiabilityEpochs(db, log = logger_1.consoleLogger) {
1406
+ return __awaiter(this, void 0, void 0, function* () {
1407
+ const q = db.trx
1408
+ .selectFrom(exports.LIABILITY_TABLE)
1409
+ .select(({ fn }) => [
1410
+ `${exports.LIABILITY_TABLE}.channel`,
1411
+ fn.sum(`${exports.LIABILITY_TABLE}.amount_due`).as('amount_due'),
1412
+ ])
1413
+ .innerJoin(exports.EPOCH_TABLE, `${exports.EPOCH_TABLE}.id`, `${exports.LIABILITY_TABLE}.epoch_id`)
1414
+ .select(['ui', 'start_time', 'end_time'])
1415
+ .groupBy([
1416
+ 'liability.channel',
1417
+ 'epoch.ui',
1418
+ 'epoch.start_time',
1419
+ 'epoch.end_time',
1420
+ ])
1421
+ .orderBy(['epoch.start_time desc']);
1422
+ // Fetch node_operator SOL key metadata separately
1423
+ const nodeOpMetadataQuery = db.trx
1424
+ .selectFrom(exports.LIABILITY_TABLE)
1425
+ .select([`${exports.LIABILITY_TABLE}.obh_used`])
1426
+ .innerJoin(exports.EPOCH_TABLE, `${exports.EPOCH_TABLE}.id`, `${exports.LIABILITY_TABLE}.epoch_id`)
1427
+ .select([`${exports.EPOCH_TABLE}.ui as epoch_ui`])
1428
+ .innerJoin('entity', 'entity.id', `${exports.LIABILITY_TABLE}.entity_id`)
1429
+ .select(['entity.sol_key'])
1430
+ .where(`${exports.LIABILITY_TABLE}.channel`, '=', 'node_operator')
1431
+ .where('entity.sol_key', 'is not', null)
1432
+ .where(`${exports.LIABILITY_TABLE}.obh_used`, 'is not', null);
1433
+ log.debug(`fetchLiabilityEpochs ${q.compile().sql}`);
1434
+ log.debug(`nodeOpMetadata ${nodeOpMetadataQuery.compile().sql}`);
1435
+ const [rs, nodeOpMetadata] = yield Promise.all([
1436
+ q.execute(),
1437
+ nodeOpMetadataQuery.execute(),
1438
+ ]);
1439
+ // Group node operator metadata by epoch
1440
+ const metadataByEpoch = {};
1441
+ nodeOpMetadata.forEach((row) => {
1442
+ const epochId = Number(row.epoch_ui);
1443
+ if (!metadataByEpoch[epochId]) {
1444
+ metadataByEpoch[epochId] = {};
1445
+ }
1446
+ if (row.sol_key && row.obh_used !== null) {
1447
+ metadataByEpoch[epochId][row.sol_key] = {
1448
+ obhUsed: Number(row.obh_used),
1449
+ };
1450
+ }
1451
+ });
1452
+ return rs.map((r) => ({
1453
+ epochId: Number(r.ui),
1454
+ channel: r.channel,
1455
+ start: r.start_time,
1456
+ end: r.end_time,
1457
+ amountDue: Number(r.amount_due),
1458
+ metadataBySolKey: r.channel === 'node_operator'
1459
+ ? metadataByEpoch[Number(r.ui)] || {}
1460
+ : {},
1461
+ }));
1462
+ });
1463
+ },
1464
+ getBurnAdjustments(trx, ps, log = logger_1.consoleLogger) {
1465
+ return __awaiter(this, void 0, void 0, function* () {
1466
+ if (ps.toFill) {
1467
+ const q = trx.trx
1468
+ .selectFrom(exports.BURN_ADJUSTMENT_TABLE)
1469
+ .selectAll(exports.BURN_ADJUSTMENT_TABLE)
1470
+ .innerJoin(exports.JOB_TABLE, `${exports.JOB_TABLE}.id`, `${exports.BURN_ADJUSTMENT_TABLE}.job_id`)
1471
+ .select([`${exports.JOB_TABLE}.completed_at`, `${exports.JOB_TABLE}.render_amt`])
1472
+ .leftJoin(exports.BURN_TABLE, `${exports.BURN_TABLE}.burn_adjustment_id`, `${exports.BURN_ADJUSTMENT_TABLE}.id`)
1473
+ .select(({ fn, lit }) => [
1474
+ fn
1475
+ .sum(fn.coalesce(`${exports.BURN_TABLE}.to_burn`, lit(0)))
1476
+ .as('tot_to_burn'),
1477
+ fn
1478
+ .sum(fn.coalesce(`${exports.BURN_TABLE}.burned`, lit(0)))
1479
+ .as('tot_burned'),
1480
+ ])
1481
+ .groupBy([
1482
+ `${exports.BURN_ADJUSTMENT_TABLE}.id`,
1483
+ `${exports.JOB_TABLE}.completed_at`,
1484
+ `${exports.JOB_TABLE}.render_amt`,
1485
+ ])
1486
+ .havingRef((0, kysely_1.sql) `SUM(COALESCE("burn"."to_burn", 0)) - SUM(COALESCE("burn"."burned", 0))`, '<', `${exports.BURN_ADJUSTMENT_TABLE}.down_adj_to_burn`);
1487
+ log.info(`getBurnAdjustments ${q.compile().sql}`);
1488
+ const res = yield q.execute();
1489
+ return res.map((r) => ({
1490
+ id: Number(r.id),
1491
+ createdAt: r.created_at,
1492
+ jobId: Number(r.job_id),
1493
+ downAdjRndrUsed: Number(r.down_adj_rndr_used),
1494
+ downAdjToBurn: Number(r.down_adj_to_burn),
1495
+ adjusted: Number(r.tot_to_burn) - Number(r.tot_burned),
1496
+ job: {
1497
+ id: Number(r.job_id),
1498
+ completedAt: r.completed_at,
1499
+ rndrUsed: BigInt(r.render_amt),
1500
+ },
1501
+ }));
1502
+ }
1503
+ return [];
1504
+ });
1505
+ },
1506
+ insertPolygonUpgrade(db, p, log = logger_1.consoleLogger) {
1507
+ return __awaiter(this, void 0, void 0, function* () {
1508
+ const solTxId = yield getOrInsertTx(db.trx, {
1509
+ sig: p.solTx.sig,
1510
+ executedAt: p.solTx.executedAt,
1511
+ });
1512
+ yield db.trx
1513
+ .insertInto(exports.POLYGON_UPGRADE_TABLE)
1514
+ .values({
1515
+ eth_addr: p.ethAddr,
1516
+ sol_addr: p.solAddr,
1517
+ amount: p.amount,
1518
+ sol_tx_id: solTxId,
1519
+ })
1520
+ .execute();
1521
+ log.info(`insertPolygonUpgrade ${JSON.stringify(p)}`);
1522
+ return;
1523
+ });
1524
+ },
1525
+ fetchPolygonUpgrades(db, f, log = logger_1.consoleLogger) {
1526
+ return __awaiter(this, void 0, void 0, function* () {
1527
+ let query = db.trx
1528
+ .selectFrom('polygon_upgrade')
1529
+ .selectAll('polygon_upgrade')
1530
+ .innerJoin('sol_tx', 'sol_tx.id', 'polygon_upgrade.sol_tx_id')
1531
+ .select(['sol_tx.sig', 'sol_tx.executed_at'])
1532
+ .orderBy('sol_tx.executed_at', 'desc');
1533
+ if (f.executedAfter) {
1534
+ query = query.where('sol_tx.executed_at', '>=', f.executedAfter);
1535
+ }
1536
+ if (f.executedBefore) {
1537
+ query = query.where('sol_tx.executed_at', '<=', f.executedBefore);
1538
+ }
1539
+ const results = yield query.execute();
1540
+ log.info(`fetchPolygonUpgrades returned ${results.length} records`);
1541
+ return results.map((row) => ({
1542
+ ethAddr: row.eth_addr,
1543
+ solAddr: row.sol_addr,
1544
+ amount: BigInt(row.amount.toString()),
1545
+ solTx: {
1546
+ sig: row.sig,
1547
+ executedAt: row.executed_at,
1548
+ },
1549
+ }));
1550
+ });
1551
+ },
1552
+ getCurrentUserGrantSpend(db, f, log = logger_1.consoleLogger) {
1553
+ return __awaiter(this, void 0, void 0, function* () {
1554
+ return yield getCurrentUserGrantSpend(db.trx, f, log);
1555
+ });
1556
+ },
1557
+ deleteAll(log = logger_1.consoleLogger) {
1558
+ return __awaiter(this, void 0, void 0, function* () {
1559
+ if (config.database.includes('render')) {
1560
+ throw new Error('cannot nuke from deployed database. call from tests only');
1561
+ }
1562
+ const tx = yield (0, base_2.begin)(db, log);
1563
+ try {
1564
+ const res = yield Promise.all([
1565
+ tx.trx
1566
+ .deleteFrom(exports.SOL_TX_TABLE)
1567
+ .where('id', 'is not', null)
1568
+ .executeTakeFirst(),
1569
+ tx.trx.deleteFrom(exports.LIABILITY_TABLE).executeTakeFirstOrThrow(),
1570
+ tx.trx.deleteFrom(exports.SOL_TRANSFER_TABLE).executeTakeFirstOrThrow(),
1571
+ tx.trx
1572
+ .deleteFrom(exports.EPOCH_TABLE)
1573
+ .where('id', 'is not', null)
1574
+ .executeTakeFirst(),
1575
+ tx.trx
1576
+ .deleteFrom(exports.ENTITY_TABLE)
1577
+ .where('id', 'is not', null)
1578
+ .executeTakeFirst(),
1579
+ tx.trx
1580
+ .deleteFrom(exports.MANUAL_BURN_TABLE)
1581
+ .where('epoch_id', 'is not', null)
1582
+ .executeTakeFirst(),
1583
+ tx.trx
1584
+ .deleteFrom(exports.JOB_ID_TABLE)
1585
+ .where('id', 'is not', null)
1586
+ .executeTakeFirst(),
1587
+ tx.trx
1588
+ .deleteFrom(exports.JOB_TABLE)
1589
+ .where('id', 'is not', null)
1590
+ .executeTakeFirst(),
1591
+ tx.trx
1592
+ .deleteFrom(exports.BURN_TABLE)
1593
+ .where('id', 'is not', null)
1594
+ .executeTakeFirst(),
1595
+ ]);
1596
+ tx.commit();
1597
+ }
1598
+ catch (e) {
1599
+ log.error(`caught ${e}`);
1600
+ tx.rollback();
1601
+ }
1602
+ });
1603
+ },
1604
+ };
1605
+ };
1606
+ exports.pgClient = pgClient;
1607
+ //# sourceMappingURL=v2Client.js.map