@render-foundation/utils 0.0.77 → 0.0.78

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 (86) hide show
  1. package/package.json +1 -1
  2. package/lib/cjs/client/onchain.js +0 -109
  3. package/lib/cjs/client/onchain.js.map +0 -1
  4. package/lib/cjs/client/pg/v1.js +0 -623
  5. package/lib/cjs/client/pg/v1.js.map +0 -1
  6. package/lib/cjs/client/pg/v2.js +0 -840
  7. package/lib/cjs/client/pg/v2.js.map +0 -1
  8. package/lib/cjs/client/pg/v2Client.js +0 -770
  9. package/lib/cjs/client/pg/v2Client.js.map +0 -1
  10. package/lib/cjs/client/price.js +0 -46
  11. package/lib/cjs/client/price.js.map +0 -1
  12. package/lib/cjs/client/render.js +0 -164
  13. package/lib/cjs/client/render.js.map +0 -1
  14. package/lib/cjs/client/squads.js +0 -204
  15. package/lib/cjs/client/squads.js.map +0 -1
  16. package/lib/cjs/client/trade.js +0 -127
  17. package/lib/cjs/client/trade.js.map +0 -1
  18. package/lib/cjs/client/wormhole.js +0 -69
  19. package/lib/cjs/client/wormhole.js.map +0 -1
  20. package/lib/cjs/dbTypes.js +0 -3
  21. package/lib/cjs/dbTypes.js.map +0 -1
  22. package/lib/cjs/dbTypesV2.js +0 -3
  23. package/lib/cjs/dbTypesV2.js.map +0 -1
  24. package/lib/cjs/errorReporter.js +0 -77
  25. package/lib/cjs/errorReporter.js.map +0 -1
  26. package/lib/cjs/index.js +0 -41
  27. package/lib/cjs/index.js.map +0 -1
  28. package/lib/cjs/logger.js +0 -21
  29. package/lib/cjs/logger.js.map +0 -1
  30. package/lib/esm/src/client/onchain.js +0 -100
  31. package/lib/esm/src/client/onchain.js.map +0 -1
  32. package/lib/esm/src/client/pg/v1.js +0 -559
  33. package/lib/esm/src/client/pg/v1.js.map +0 -1
  34. package/lib/esm/src/client/pg/v2.js +0 -774
  35. package/lib/esm/src/client/pg/v2.js.map +0 -1
  36. package/lib/esm/src/client/pg/v2Client.js +0 -710
  37. package/lib/esm/src/client/pg/v2Client.js.map +0 -1
  38. package/lib/esm/src/client/price.js +0 -32
  39. package/lib/esm/src/client/price.js.map +0 -1
  40. package/lib/esm/src/client/render.js +0 -138
  41. package/lib/esm/src/client/render.js.map +0 -1
  42. package/lib/esm/src/client/squads.js +0 -163
  43. package/lib/esm/src/client/squads.js.map +0 -1
  44. package/lib/esm/src/client/trade.js +0 -114
  45. package/lib/esm/src/client/trade.js.map +0 -1
  46. package/lib/esm/src/client/wormhole.js +0 -33
  47. package/lib/esm/src/client/wormhole.js.map +0 -1
  48. package/lib/esm/src/dbTypes.js +0 -2
  49. package/lib/esm/src/dbTypes.js.map +0 -1
  50. package/lib/esm/src/dbTypesV2.js +0 -2
  51. package/lib/esm/src/dbTypesV2.js.map +0 -1
  52. package/lib/esm/src/errorReporter.js +0 -68
  53. package/lib/esm/src/errorReporter.js.map +0 -1
  54. package/lib/esm/src/index.js +0 -12
  55. package/lib/esm/src/index.js.map +0 -1
  56. package/lib/esm/src/logger.js +0 -18
  57. package/lib/esm/src/logger.js.map +0 -1
  58. package/lib/esm/tsconfig.esm.tsbuildinfo +0 -1
  59. package/lib/types/src/client/onchain.d.ts +0 -19
  60. package/lib/types/src/client/onchain.d.ts.map +0 -1
  61. package/lib/types/src/client/pg/v1.d.ts +0 -163
  62. package/lib/types/src/client/pg/v1.d.ts.map +0 -1
  63. package/lib/types/src/client/pg/v2.d.ts +0 -35
  64. package/lib/types/src/client/pg/v2.d.ts.map +0 -1
  65. package/lib/types/src/client/pg/v2Client.d.ts +0 -142
  66. package/lib/types/src/client/pg/v2Client.d.ts.map +0 -1
  67. package/lib/types/src/client/price.d.ts +0 -11
  68. package/lib/types/src/client/price.d.ts.map +0 -1
  69. package/lib/types/src/client/render.d.ts +0 -19
  70. package/lib/types/src/client/render.d.ts.map +0 -1
  71. package/lib/types/src/client/squads.d.ts +0 -17
  72. package/lib/types/src/client/squads.d.ts.map +0 -1
  73. package/lib/types/src/client/trade.d.ts +0 -15
  74. package/lib/types/src/client/trade.d.ts.map +0 -1
  75. package/lib/types/src/client/wormhole.d.ts +0 -9
  76. package/lib/types/src/client/wormhole.d.ts.map +0 -1
  77. package/lib/types/src/dbTypes.d.ts +0 -123
  78. package/lib/types/src/dbTypes.d.ts.map +0 -1
  79. package/lib/types/src/dbTypesV2.d.ts +0 -109
  80. package/lib/types/src/dbTypesV2.d.ts.map +0 -1
  81. package/lib/types/src/errorReporter.d.ts +0 -12
  82. package/lib/types/src/errorReporter.d.ts.map +0 -1
  83. package/lib/types/src/index.d.ts +0 -12
  84. package/lib/types/src/index.d.ts.map +0 -1
  85. package/lib/types/src/logger.d.ts +0 -16
  86. package/lib/types/src/logger.d.ts.map +0 -1
@@ -1,774 +0,0 @@
1
- import { Pool } from 'pg';
2
- import { Kysely, NoResultError, PostgresDialect, sql, } from 'kysely';
3
- import { consoleLogger } from '../../logger';
4
- import { transferTypToChan, } from './v1';
5
- const transferFromDBV2 = (o) => {
6
- return {
7
- id: o.id,
8
- solKey: o.sol_key,
9
- solTx: o.sig,
10
- sqTx: o.sq_tx,
11
- createdAt: o.created_at,
12
- payedAt: o.executed_at,
13
- amountDue: BigInt(o.amount_due),
14
- amountPayed: o.amount_payed ? BigInt(o.amount_payed) : undefined,
15
- fromSolKey: o.from_sol_key,
16
- channel: o.channel,
17
- symbol: o.symbol,
18
- operatorRewards: o.channel == 'node_operator'
19
- ? {
20
- epochId: o.ui,
21
- startTime: o.start_time,
22
- endTime: o.end_time,
23
- }
24
- : undefined,
25
- computeClientRewards: o.channel == 'open_compute'
26
- ? {
27
- epochId: o.ui,
28
- deviceId: o.device_id,
29
- }
30
- : undefined,
31
- upgradeRewards: o.channel == 'upgrade'
32
- ? {
33
- epochId: o.ui,
34
- epochStartTime: o.start_time,
35
- points: BigInt(o.points),
36
- }
37
- : undefined,
38
- availabilityRewards: o.channel == 'availability'
39
- ? {
40
- epochId: o.ui,
41
- deviceId: o.device_id,
42
- }
43
- : undefined,
44
- };
45
- };
46
- export const SOL_TX_TABLE = 'sol_tx';
47
- export const EPOCH_TABLE = 'epoch';
48
- export const MANUAL_BURN_TABLE = 'manual_burn';
49
- export const ENTITY_TABLE = 'entity';
50
- export const SOL_TRANSFER_TABLE = 'sol_transfer';
51
- export const SOL_TRANSFER_INFO_TABLE = 'sol_transfer_info';
52
- export const JOB_ID_TABLE = 'job_id';
53
- export const JOB_TABLE = 'job';
54
- export const BURN_TABLE = 'burn';
55
- export const pgClient = (config) => {
56
- const dialect = new PostgresDialect({
57
- pool: new Pool({
58
- ...config,
59
- port: config.port ?? 5432,
60
- max: config.max ?? 30,
61
- //idleTimeoutMillis: 0,
62
- //connectionTimeoutMillis: 0,
63
- }),
64
- });
65
- // Database interface is passed to Kysely's constructor, and from now on, Kysely
66
- // knows your database structure.
67
- // Dialect is passed to Kysely's constructor, and from now on, Kysely knows how
68
- // to communicate with your database.
69
- const db = new Kysely({
70
- dialect,
71
- });
72
- const getOrInsertEntity = async (db, p, log = consoleLogger) => {
73
- const res = (await db
74
- .selectFrom(ENTITY_TABLE)
75
- .select('id')
76
- .where('sol_key', '=', p.solKey)
77
- .executeTakeFirst());
78
- if (res) {
79
- log.debug(`already found entity ${res.id}`);
80
- return res.id;
81
- }
82
- const { id } = (await db
83
- .insertInto(ENTITY_TABLE)
84
- .values({
85
- sol_key: p.solKey,
86
- })
87
- .onConflict((oc) => oc.column('sol_key').doNothing())
88
- .returning((eb) => ['id as id'])
89
- .executeTakeFirst());
90
- log.debug(`inserted entity ${id}`);
91
- return id;
92
- };
93
- const getOrInsertTx = async (db, p, log = consoleLogger) => {
94
- const res = await db
95
- .selectFrom(SOL_TX_TABLE)
96
- .select('id')
97
- .where('sig', '=', p.sig)
98
- .executeTakeFirst();
99
- if (res) {
100
- log.debug(`already found tx ${res.id}`);
101
- return res.id;
102
- }
103
- const { id } = (await db
104
- .insertInto(SOL_TX_TABLE)
105
- .values({
106
- sig: p.sig,
107
- executed_at: p.executedAt,
108
- })
109
- .onConflict((oc) => oc.column('sig').doNothing())
110
- .returning((eb) => ['id as id'])
111
- .executeTakeFirst());
112
- log.debug(`inserted tx ${id}`);
113
- return id;
114
- };
115
- const getOrInsertEpoch = async (db, p, log = consoleLogger) => {
116
- const res = await db
117
- .selectFrom(EPOCH_TABLE)
118
- .select('id')
119
- .where('ui', '=', String(p.uiEpochId))
120
- .where('channel', '=', p.channel)
121
- .executeTakeFirst();
122
- if (res) {
123
- log.debug(`already found epoch ${res.id}`);
124
- return res.id;
125
- }
126
- const { id } = (await db
127
- .insertInto(EPOCH_TABLE)
128
- .values({
129
- ui: p.uiEpochId,
130
- channel: p.channel,
131
- start_time: p.startTime,
132
- end_time: p.endTime,
133
- saved_at: p.channel == 'node_operator' ? new Date() : undefined,
134
- })
135
- .onConflict((oc) => oc.columns(['ui', 'channel']).doNothing())
136
- .returning((eb) => ['id as id'])
137
- .executeTakeFirst());
138
- log.debug(`inserted epoch ${id}`);
139
- return id;
140
- };
141
- const updateTotalRndr = async (db, p, totalRndr, savedAt, log) => {
142
- const res = (await db
143
- .updateTable(EPOCH_TABLE)
144
- .set({
145
- total_rndr: totalRndr,
146
- saved_at: savedAt,
147
- })
148
- .where('channel', '=', p.channel)
149
- .where('ui', '=', String(p.uiEpochId))
150
- .executeTakeFirst());
151
- log.info(`set ${res.numUpdatedRows} rows. channel: ${p.channel}, ui: ${p.uiEpochId} -> totalRndr ${totalRndr} `);
152
- };
153
- const createTransfers = async (db, transfers, log = consoleLogger) => {
154
- const epochIds = [];
155
- for (const t of transfers) {
156
- if (!t.computeClientRewards &&
157
- !t.upgradeRewards &&
158
- !t.operatorRewards &&
159
- !t.availabilityRewards &&
160
- !t.channel) {
161
- log.warn(`malformed transfer doesnt have type ${JSON.stringify(t, (key, value) => typeof value === 'bigint' ? value.toString() : value)}`);
162
- continue;
163
- }
164
- let solTxId;
165
- if (t.solTx) {
166
- solTxId = await getOrInsertTx(db, {
167
- sig: t.solTx,
168
- executedAt: t.payedAt,
169
- }, log);
170
- }
171
- let entityId;
172
- if (t.solKey) {
173
- entityId = await getOrInsertEntity(db, { solKey: t.solKey }, log);
174
- }
175
- log.info(`inserting transfer ${JSON.stringify(t, (key, value) => typeof value === 'bigint' ? value.toString() : value)}`);
176
- let fromEntityId;
177
- if (t.fromSolKey) {
178
- fromEntityId = await getOrInsertEntity(db, { solKey: t.fromSolKey }, log);
179
- }
180
- const { id: transferId } = (await db
181
- .insertInto(SOL_TRANSFER_TABLE)
182
- .values({
183
- sol_tx_id: solTxId,
184
- from_entity_id: fromEntityId,
185
- to_entity_id: entityId,
186
- channel: t.channel
187
- ? t.channel
188
- : transferTypToChan((() => {
189
- if (t.operatorRewards) {
190
- return 'node_operator_rewards';
191
- }
192
- else if (t.upgradeRewards) {
193
- return 'upgrade_rewards';
194
- }
195
- else if (t.availabilityRewards) {
196
- return 'availability_rewards';
197
- }
198
- return 'open_compute_rewards';
199
- })()),
200
- symbol: t.symbol ?? 'RENDER',
201
- created_at: t.createdAt,
202
- amount_due: BigInt(t.amountDue),
203
- amount_payed: t.amountPayed ? BigInt(t.amountPayed) : 0,
204
- })
205
- .returning((eb) => ['id as id'])
206
- .executeTakeFirst());
207
- let epochId;
208
- let deviceId;
209
- let points;
210
- let startTime;
211
- let endTime;
212
- let channel;
213
- if (t.operatorRewards) {
214
- log.info(`inserting operator rewards ${transferId}`);
215
- epochId = t.operatorRewards.epochId;
216
- startTime = t.operatorRewards.startTime;
217
- endTime = t.operatorRewards.endTime;
218
- channel = 'node_operator';
219
- }
220
- else if (t.computeClientRewards) {
221
- log.info(`inserting compute client rewards ${transferId}`);
222
- epochId = t.computeClientRewards.epochId;
223
- deviceId = t.computeClientRewards.deviceId;
224
- channel = 'open_compute';
225
- }
226
- else if (t.upgradeRewards) {
227
- log.info(`inserting upgrade rewards ${transferId}`);
228
- channel = 'upgrade';
229
- epochId = t.upgradeRewards.epochId;
230
- points = t.upgradeRewards.points;
231
- }
232
- else if (t.availabilityRewards) {
233
- log.info(`inserting availability rewards ${transferId}`);
234
- channel = 'availability';
235
- epochId = t.availabilityRewards.epochId;
236
- deviceId = t.availabilityRewards.deviceId;
237
- }
238
- else if (t.channel) {
239
- channel = t.channel;
240
- }
241
- let epochIdDb;
242
- if (epochId != null) {
243
- epochIdDb = await getOrInsertEpoch(db, {
244
- channel,
245
- startTime,
246
- endTime,
247
- uiEpochId: epochId,
248
- }, log);
249
- }
250
- if (epochIdDb || deviceId || points) {
251
- await db
252
- .insertInto(SOL_TRANSFER_INFO_TABLE)
253
- .values({
254
- transfer_id: transferId,
255
- device_id: deviceId,
256
- points,
257
- epoch_id: epochIdDb ? BigInt(epochIdDb) : null,
258
- })
259
- .executeTakeFirst();
260
- }
261
- epochIds.push({ epochDbId: epochIdDb });
262
- }
263
- return epochIds;
264
- };
265
- return {
266
- db,
267
- async saveNodeOperatorEpoch(epochId, transfers, jobIds, totalRndr, log = consoleLogger) {
268
- await db
269
- .transaction()
270
- .setIsolationLevel('repeatable read')
271
- .execute(async (trx) => {
272
- const epochDbIds = await createTransfers(trx, transfers, log);
273
- log.info(`inserted transfers`);
274
- for (const id of jobIds) {
275
- await trx
276
- .insertInto(JOB_ID_TABLE)
277
- .values({
278
- id: BigInt(id),
279
- epoch_id: epochDbIds[0].epochDbId,
280
- })
281
- .executeTakeFirstOrThrow();
282
- }
283
- const now = new Date();
284
- await updateTotalRndr(db, { uiEpochId: epochId, channel: 'node_operator' }, totalRndr, now, log);
285
- log.debug(`saved epoch`);
286
- /*const now = new Date(Date.now())
287
- const res = await trx
288
- .updateTable(EPOCH_TABLE)
289
- .set({
290
- saved_at: now,
291
- total_rndr: totalRndr,
292
- })
293
- .where('channel')
294
- .where('ui', '=', epochId.toString())
295
- .where('', '=')
296
- .executeTakeFirstOrThrow()*/
297
- });
298
- return;
299
- },
300
- async getLatestNodeOperatorEpoch(log = consoleLogger) {
301
- const now = new Date(Date.now());
302
- try {
303
- const res = await db
304
- .selectFrom(EPOCH_TABLE)
305
- .selectAll()
306
- .where('channel', '=', 'node_operator')
307
- .where('end_time', '<=', now)
308
- .where('saved_at', 'is', null)
309
- .orderBy('end_time asc')
310
- .limit(1)
311
- .executeTakeFirstOrThrow();
312
- return {
313
- epochId: BigInt(res.ui),
314
- startedAt: res.start_time,
315
- endedAt: res.end_time,
316
- savedAt: res.saved_at ?? undefined,
317
- };
318
- }
319
- catch (e) {
320
- if (e instanceof NoResultError) {
321
- log.info(`no node operator epoch found`);
322
- return undefined;
323
- }
324
- throw e;
325
- }
326
- },
327
- async getOutstanding(f, log = consoleLogger) {
328
- const { typ, nullKey, due } = f;
329
- //select sol_key, sum(amount_due)-sum(amount_payed) from transfer group by sol_key;
330
- let q = db
331
- .selectFrom(SOL_TRANSFER_TABLE)
332
- .innerJoin(ENTITY_TABLE, 'sol_transfer.to_entity_id', 'entity.id')
333
- .select(({ fn, val, ref }) => [
334
- 'entity.sol_key',
335
- sql `${fn.sum('sol_transfer.amount_due')} -
336
- ${fn.sum('sol_transfer.amount_payed')}`.as('due'),
337
- ])
338
- .where('sol_transfer.channel', '=', transferTypToChan(typ))
339
- .groupBy(['entity.sol_key']);
340
- if (!nullKey) {
341
- q = q.where('entity.sol_key', 'is not', null);
342
- }
343
- if (due) {
344
- q = q.having(({ fn, ref }) => sql `${fn.sum('sol_transfer.amount_due')} -
345
- ${fn.sum('sol_transfer.amount_payed')}
346
- >
347
- 0`);
348
- }
349
- const res = await q.execute();
350
- log.info(`outstanding query ${q.compile().sql} params ${JSON.stringify(f)} ${res.length} rows`);
351
- const out = {};
352
- for (const r of res) {
353
- out[r.sol_key ?? ''] = BigInt(r.due);
354
- }
355
- return out;
356
- },
357
- async fetchTransfers(f, log = consoleLogger) {
358
- let base = db
359
- .selectFrom(SOL_TRANSFER_TABLE)
360
- .selectAll(SOL_TRANSFER_TABLE)
361
- .leftJoin(SOL_TRANSFER_INFO_TABLE, 'sol_transfer_info.transfer_id', 'sol_transfer.id')
362
- .select(['device_id', 'points'])
363
- .leftJoin(SOL_TX_TABLE, 'sol_tx.id', 'sol_transfer.sol_tx_id')
364
- .select(['sol_tx.sig', 'sol_tx.executed_at'])
365
- .leftJoin(ENTITY_TABLE, 'entity.id', 'sol_transfer.to_entity_id')
366
- .select(['entity.sol_key'])
367
- .leftJoin(`${ENTITY_TABLE} as fe`, 'fe.id', 'sol_transfer.from_entity_id')
368
- .select(['fe.sol_key as from_sol_key'])
369
- .leftJoin(EPOCH_TABLE, 'epoch.id', 'sol_transfer_info.epoch_id')
370
- .select(['epoch.ui', 'epoch.start_time', 'epoch.end_time']);
371
- if (f.typ) {
372
- base = base.where('sol_transfer.channel', '=', transferTypToChan(f.typ));
373
- }
374
- if (f.start) {
375
- base = base.where('sol_tx.executed_at', '>=', f.start);
376
- }
377
- if (f.end) {
378
- base = base.where('sol_tx.executed_at', '<=', f.end);
379
- }
380
- if (f.solKey) {
381
- base = base.where('entity.sol_key', '=', f.solKey);
382
- }
383
- if (f.payed != undefined) {
384
- base = base.where('sol_transfer.sol_tx_id', f.payed ? 'is not' : 'is', null);
385
- }
386
- if (f.createdBefore != undefined) {
387
- base = base.where('sol_transfer.created_at', '<=', f.createdBefore);
388
- }
389
- if (f.epochId) {
390
- base = base.where('epoch.ui', '=', String(f.epochId));
391
- }
392
- if (f.sort) {
393
- base = base.orderBy('entity.sol_key asc');
394
- }
395
- log.info(`fetching ${base.compile().sql} params ${JSON.stringify(f)}`);
396
- const res = await base.execute();
397
- log.info(`fetched ${res.length} transfers`);
398
- return res.map((r) => transferFromDBV2(r));
399
- },
400
- async payoutTransfers(idToAmt, payedAt, solTx, log = consoleLogger) {
401
- await db
402
- .transaction()
403
- .setIsolationLevel('repeatable read')
404
- .execute(async (tx) => {
405
- const alreadyUpdatedIds = (await tx
406
- .selectFrom(SOL_TRANSFER_TABLE)
407
- .innerJoin(SOL_TX_TABLE, 'sol_transfer.sol_tx_id', 'sol_tx.id')
408
- .select(['sol_transfer.id'])
409
- .where('sol_transfer.id', 'in', Object.keys(idToAmt))
410
- .where('sol_tx.sig', 'is not', null)
411
- .execute()).map(({ id }) => id);
412
- for (const [id, amt] of Object.entries(idToAmt)) {
413
- if (alreadyUpdatedIds.includes(id)) {
414
- log.info(`transfer ${id} already marked payed out. skipping`);
415
- continue;
416
- }
417
- const solTxId = await getOrInsertTx(tx, { sig: solTx, executedAt: payedAt }, log);
418
- const res = await tx
419
- .updateTable(SOL_TRANSFER_TABLE)
420
- .set({
421
- sol_tx_id: solTxId,
422
- amount_payed: amt,
423
- })
424
- .where('id', '=', id.toString())
425
- .executeTakeFirstOrThrow();
426
- log.info(`marked ${res.numUpdatedRows} transfer payed out`);
427
- }
428
- });
429
- },
430
- async payoutTransfer(id, payedAt, solTx, amtPayed, log = consoleLogger) {
431
- await db
432
- .transaction()
433
- .setIsolationLevel('repeatable read')
434
- .execute(async (tx) => {
435
- const solTxId = await getOrInsertTx(tx, { sig: solTx, executedAt: payedAt }, log);
436
- const res = await tx
437
- .updateTable(SOL_TRANSFER_TABLE)
438
- .set({
439
- sol_tx_id: solTxId,
440
- amount_payed: amtPayed,
441
- })
442
- .where('id', '=', id.toString())
443
- .executeTakeFirst();
444
- log.info(`marked ${res.numUpdatedRows} transfer payed out`);
445
- });
446
- },
447
- async createTransfers(transfers, log = consoleLogger) {
448
- await db
449
- .transaction()
450
- .setIsolationLevel('repeatable read')
451
- .execute(async (trx) => {
452
- await createTransfers(trx, transfers, log);
453
- });
454
- },
455
- async fetchInfoForEpoch(epochId, log = consoleLogger) {
456
- const q = db
457
- .selectFrom(JOB_ID_TABLE)
458
- .innerJoin(EPOCH_TABLE, 'epoch.id', 'job_id.epoch_id')
459
- .leftJoin(MANUAL_BURN_TABLE, 'manual_burn.epoch_id', 'epoch.id')
460
- .where('epoch.ui', '=', String(epochId))
461
- .where('epoch.channel', '=', 'node_operator')
462
- .select([
463
- 'job_id.id',
464
- 'epoch.total_rndr',
465
- 'epoch.start_time',
466
- 'epoch.end_time',
467
- 'manual_burn.burned',
468
- 'manual_burn.tx_sig',
469
- ])
470
- .orderBy('job_id.id asc');
471
- log.debug(`fetch epoch info q ${q.compile().sql} epochId ${epochId}`);
472
- const res = await q.execute();
473
- if (res.length == 0) {
474
- throw new Error(`epoch ${epochId} not found`);
475
- }
476
- return {
477
- jobIds: res.map((r) => Number(r.id)),
478
- totalRndr: BigInt(res[0].total_rndr),
479
- startTime: res[0].start_time,
480
- endTime: res[0].end_time,
481
- burned: BigInt(res[0].burned ?? 0),
482
- burnTx: res[0].tx_sig,
483
- };
484
- },
485
- async updateComputeClientSolKey(deviceId, solKey, log = consoleLogger) {
486
- const q = db
487
- .updateTable(`${ENTITY_TABLE} as e`)
488
- .set({
489
- sol_key: solKey,
490
- })
491
- .from(`${SOL_TRANSFER_TABLE} as t`)
492
- .innerJoin(SOL_TRANSFER_INFO_TABLE, 'sol_transfer_info.transfer_id', 't.id')
493
- //.whereRef('t.id', '=', 'o.transfer_id')
494
- .where('e.sol_key', 'is', null)
495
- .where('sol_transfer_info.device_id', '=', deviceId);
496
- const sql = await q.compile();
497
- log.info(`sql ${sql.sql} params ${sql.parameters}`);
498
- const res = await q.executeTakeFirstOrThrow();
499
- log.info(`updated ${res.numUpdatedRows} device-id sol_keys`);
500
- },
501
- async markJobsBurnt(trx, p, log = consoleLogger) {
502
- const solTxId = await getOrInsertTx(trx, { sig: p.solTx, executedAt: p.executedAt }, log);
503
- const { id } = await trx
504
- .insertInto(BURN_TABLE)
505
- .values({
506
- sol_tx_id: solTxId,
507
- priced_at: p.pricedAt,
508
- usdc_spent: p.usdcSpent,
509
- quote_amt: p.quoteAmt,
510
- burned: p.burned,
511
- })
512
- //.onConflict((oc) => oc.column('sol_tx').doNothing())
513
- .returning((eb) => ['id as id'])
514
- .executeTakeFirstOrThrow();
515
- const jobIdsStr = p.jobsIds.map(String);
516
- const res = await trx
517
- .updateTable(JOB_TABLE)
518
- .where('id', 'in', jobIdsStr)
519
- .set('burn_id', id)
520
- .executeTakeFirstOrThrow();
521
- log.debug(`set burn_id on ${res.numUpdatedRows} jobs`);
522
- return;
523
- },
524
- async fetchBurns(f, log = consoleLogger) {
525
- let q = db
526
- .selectFrom('burn')
527
- .selectAll('burn')
528
- .innerJoin('sol_tx', 'sol_tx.id', 'burn.sol_tx_id')
529
- .select(['sol_tx.executed_at', 'sol_tx.sig']);
530
- if (!f.inclManual) {
531
- q = q.where('burn.usdc_spent', '>', String(0));
532
- }
533
- if (f.start) {
534
- q = q.where('sol_tx.executed_at', '>=', f.start);
535
- }
536
- if (f.end) {
537
- q = q.where('sol_tx.executed_at', '<=', f.end);
538
- }
539
- log.info(`fetchBurns q ${q.compile().sql}`);
540
- const burns = [];
541
- const rows = await q.execute();
542
- log.info(`fetchBurns len ${rows.length}`);
543
- for (const r of rows) {
544
- burns.push({
545
- jobs: [],
546
- id: Number(r.id),
547
- solTx: r.sig,
548
- executedAt: r.executed_at,
549
- pricedAt: r.priced_at,
550
- usdcSpent: BigInt(r.usdc_spent ?? 0),
551
- quoteAmt: BigInt(r.quote_amt ?? 0),
552
- burned: BigInt(r.burned),
553
- markedBurnedAt: r.marked_burned_at,
554
- });
555
- }
556
- return burns;
557
- },
558
- async backfillBurn(p, log = consoleLogger) {
559
- await db.transaction().execute(async (trx) => {
560
- const solTxId = await getOrInsertTx(trx, { sig: p.solTx, executedAt: p.executedAt }, log);
561
- const { id } = await trx
562
- .insertInto(BURN_TABLE)
563
- .values({
564
- sol_tx_id: solTxId,
565
- priced_at: p.pricedAt,
566
- usdc_spent: p.usdcSpent,
567
- quote_amt: p.quoteAmt,
568
- burned: p.burned,
569
- marked_burned_at: p.markedBurnedAt,
570
- })
571
- //.onConflict((oc) => oc.column('sol_tx').doNothing())
572
- .returning((eb) => ['id as id'])
573
- .executeTakeFirstOrThrow();
574
- let num = BigInt(0);
575
- for (const { rndrUsed, completedAt, id: jobId, insertedAt } of p.jobs) {
576
- const res = await trx
577
- .insertInto(JOB_TABLE)
578
- .values({
579
- id: jobId,
580
- render_amt: rndrUsed,
581
- burn_id: id,
582
- completed_at: completedAt,
583
- inserted_at: insertedAt ?? new Date(),
584
- })
585
- .onConflict((oc) => oc.column('id').doNothing())
586
- .executeTakeFirstOrThrow();
587
- num += res.numInsertedOrUpdatedRows ?? BigInt(0);
588
- }
589
- log.debug(`burn id ${id} inserted ${num} of ${p.jobs.length} burn jobs`);
590
- });
591
- },
592
- async produceBurnedJobs(jobs, log = consoleLogger) {
593
- await db.transaction().execute(async (trx) => {
594
- let num = BigInt(0);
595
- for (const { amount, completedAt, jobId } of jobs) {
596
- const res = await trx
597
- .insertInto(JOB_TABLE)
598
- .values({
599
- id: jobId,
600
- render_amt: amount,
601
- completed_at: completedAt,
602
- inserted_at: new Date(Date.now()),
603
- })
604
- .onConflict((oc) => oc.column('id').doNothing())
605
- .executeTakeFirstOrThrow();
606
- num += res.numInsertedOrUpdatedRows ?? BigInt(0);
607
- }
608
- log.debug(`inserted ${num} of ${jobs.length} burn jobs`);
609
- });
610
- },
611
- async markJobsBurned(p, log = consoleLogger) {
612
- let { markedAt, solTx } = p;
613
- let res = await db
614
- .updateTable(BURN_TABLE)
615
- .set({ marked_burned_at: markedAt })
616
- .from(SOL_TX_TABLE)
617
- .whereRef('burn.sol_tx_id', '=', 'sol_tx.id')
618
- .where('sol_tx.sig', '=', solTx)
619
- .executeTakeFirstOrThrow();
620
- log.debug(`set ${res.numUpdatedRows} ${solTx} -> marked_burned_at ${markedAt.toISOString()}`);
621
- },
622
- async consumeAndLockBurnJobs(limit, lowerRndrThreshold, upperRndrThreshold, log = consoleLogger) {
623
- const trx = await begin(db);
624
- const q = trx.trx
625
- .selectFrom(trx.trx
626
- .selectFrom(JOB_TABLE)
627
- .select(({ fn, val, ref }) => [
628
- 'id',
629
- fn
630
- .sum('render_amt')
631
- .over((ob) => ob.orderBy(`completed_at`, `asc`))
632
- .as('total'),
633
- ])
634
- .where('burn_id', 'is', null)
635
- .as('t'))
636
- .select('id')
637
- .where('total', '>', lowerRndrThreshold)
638
- .where('total', '<', upperRndrThreshold);
639
- log.debug(`outstanding jobs q: ${q.compile().sql} ${JSON.stringify({
640
- limit,
641
- lowerRndrThreshold,
642
- upperRndrThreshold,
643
- })}`);
644
- const idRs = await q.execute();
645
- const ids = idRs.map((x) => x.id);
646
- log.debug(`${ids.length} candidate jobs for burn. locking up to ${limit} jobs`);
647
- if (ids.length == 0) {
648
- return { trx, jobs: [] };
649
- }
650
- const rows = await trx.trx
651
- .selectFrom(JOB_TABLE)
652
- .selectAll()
653
- .where('id', 'in', ids)
654
- .limit(limit)
655
- .forUpdate()
656
- .skipLocked()
657
- .execute();
658
- log.debug(`locked ${rows.length} jobs`);
659
- const jobs = [];
660
- for (const r of rows) {
661
- jobs.push({
662
- id: Number(r.id),
663
- completedAt: r.completed_at,
664
- rndrUsed: BigInt(r.render_amt),
665
- });
666
- }
667
- return { trx, jobs };
668
- },
669
- async incrBuyBurnMetrics(log = consoleLogger) {
670
- const res = await db
671
- .selectFrom(JOB_TABLE)
672
- .select('completed_at')
673
- .orderBy('completed_at asc')
674
- .where('burn_id', 'is', null)
675
- .execute();
676
- if (res.length == 0) {
677
- return { outstandingJobs: 0 };
678
- }
679
- return {
680
- outstandingJobs: res.length,
681
- oldestJobFinishedAt: res[0].completed_at ?? undefined,
682
- };
683
- },
684
- async deleteAll() {
685
- if (config.database.includes('render')) {
686
- throw new Error('cannot nuke from deployed database. call from tests only');
687
- }
688
- await Promise.all([
689
- db
690
- .deleteFrom(SOL_TX_TABLE)
691
- .where('id', 'is not', null)
692
- .executeTakeFirst(),
693
- db
694
- .deleteFrom(SOL_TRANSFER_TABLE)
695
- .where('id', 'is not', null)
696
- .executeTakeFirst(),
697
- db
698
- .deleteFrom(SOL_TRANSFER_INFO_TABLE)
699
- .where('transfer_id', 'is not', null)
700
- .executeTakeFirst(),
701
- db
702
- .deleteFrom(EPOCH_TABLE)
703
- .where('id', 'is not', null)
704
- .executeTakeFirst(),
705
- db
706
- .deleteFrom(ENTITY_TABLE)
707
- .where('id', 'is not', null)
708
- .executeTakeFirst(),
709
- db
710
- .deleteFrom(MANUAL_BURN_TABLE)
711
- .where('epoch_id', 'is not', null)
712
- .executeTakeFirst(),
713
- db
714
- .deleteFrom(JOB_ID_TABLE)
715
- .where('id', 'is not', null)
716
- .executeTakeFirst(),
717
- db.deleteFrom(JOB_TABLE).where('id', 'is not', null).executeTakeFirst(),
718
- db
719
- .deleteFrom(BURN_TABLE)
720
- .where('id', 'is not', null)
721
- .executeTakeFirst(),
722
- ]);
723
- },
724
- };
725
- };
726
- async function begin(db) {
727
- const connection = new Deferred();
728
- const result = new Deferred();
729
- // Do NOT await this line.
730
- db.transaction()
731
- .setIsolationLevel('repeatable read')
732
- .execute((trx) => {
733
- connection.resolve(trx);
734
- return result.promise;
735
- })
736
- .catch((err) => {
737
- // Don't do anything here. Just swallow the exception.
738
- });
739
- const trx = await connection.promise;
740
- return {
741
- trx,
742
- commit() {
743
- result.resolve(null);
744
- },
745
- rollback() {
746
- result.reject(new Error('rollback'));
747
- },
748
- };
749
- }
750
- export class Deferred {
751
- #promise;
752
- #resolve;
753
- #reject;
754
- constructor() {
755
- this.#promise = new Promise((resolve, reject) => {
756
- this.#reject = reject;
757
- this.#resolve = resolve;
758
- });
759
- }
760
- get promise() {
761
- return this.#promise;
762
- }
763
- resolve = (value) => {
764
- if (this.#resolve) {
765
- this.#resolve(value);
766
- }
767
- };
768
- reject = (reason) => {
769
- if (this.#reject) {
770
- this.#reject(reason);
771
- }
772
- };
773
- }
774
- //# sourceMappingURL=v2.js.map