@render-foundation/utils 0.0.76 → 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.
- package/package.json +1 -1
- package/lib/cjs/client/onchain.js +0 -109
- package/lib/cjs/client/onchain.js.map +0 -1
- package/lib/cjs/client/pg/v1.js +0 -623
- package/lib/cjs/client/pg/v1.js.map +0 -1
- package/lib/cjs/client/pg/v2.js +0 -840
- package/lib/cjs/client/pg/v2.js.map +0 -1
- package/lib/cjs/client/pg/v2Client.js +0 -769
- package/lib/cjs/client/pg/v2Client.js.map +0 -1
- package/lib/cjs/client/price.js +0 -46
- package/lib/cjs/client/price.js.map +0 -1
- package/lib/cjs/client/render.js +0 -164
- package/lib/cjs/client/render.js.map +0 -1
- package/lib/cjs/client/squads.js +0 -204
- package/lib/cjs/client/squads.js.map +0 -1
- package/lib/cjs/client/trade.js +0 -127
- package/lib/cjs/client/trade.js.map +0 -1
- package/lib/cjs/client/wormhole.js +0 -69
- package/lib/cjs/client/wormhole.js.map +0 -1
- package/lib/cjs/dbTypes.js +0 -3
- package/lib/cjs/dbTypes.js.map +0 -1
- package/lib/cjs/dbTypesV2.js +0 -3
- package/lib/cjs/dbTypesV2.js.map +0 -1
- package/lib/cjs/errorReporter.js +0 -77
- package/lib/cjs/errorReporter.js.map +0 -1
- package/lib/cjs/index.js +0 -41
- package/lib/cjs/index.js.map +0 -1
- package/lib/cjs/logger.js +0 -21
- package/lib/cjs/logger.js.map +0 -1
- package/lib/esm/src/client/onchain.js +0 -100
- package/lib/esm/src/client/onchain.js.map +0 -1
- package/lib/esm/src/client/pg/v1.js +0 -559
- package/lib/esm/src/client/pg/v1.js.map +0 -1
- package/lib/esm/src/client/pg/v2.js +0 -774
- package/lib/esm/src/client/pg/v2.js.map +0 -1
- package/lib/esm/src/client/pg/v2Client.js +0 -709
- package/lib/esm/src/client/pg/v2Client.js.map +0 -1
- package/lib/esm/src/client/price.js +0 -32
- package/lib/esm/src/client/price.js.map +0 -1
- package/lib/esm/src/client/render.js +0 -138
- package/lib/esm/src/client/render.js.map +0 -1
- package/lib/esm/src/client/squads.js +0 -163
- package/lib/esm/src/client/squads.js.map +0 -1
- package/lib/esm/src/client/trade.js +0 -114
- package/lib/esm/src/client/trade.js.map +0 -1
- package/lib/esm/src/client/wormhole.js +0 -33
- package/lib/esm/src/client/wormhole.js.map +0 -1
- package/lib/esm/src/dbTypes.js +0 -2
- package/lib/esm/src/dbTypes.js.map +0 -1
- package/lib/esm/src/dbTypesV2.js +0 -2
- package/lib/esm/src/dbTypesV2.js.map +0 -1
- package/lib/esm/src/errorReporter.js +0 -68
- package/lib/esm/src/errorReporter.js.map +0 -1
- package/lib/esm/src/index.js +0 -12
- package/lib/esm/src/index.js.map +0 -1
- package/lib/esm/src/logger.js +0 -18
- package/lib/esm/src/logger.js.map +0 -1
- package/lib/esm/tsconfig.esm.tsbuildinfo +0 -1
- package/lib/types/src/client/onchain.d.ts +0 -19
- package/lib/types/src/client/onchain.d.ts.map +0 -1
- package/lib/types/src/client/pg/v1.d.ts +0 -163
- package/lib/types/src/client/pg/v1.d.ts.map +0 -1
- package/lib/types/src/client/pg/v2.d.ts +0 -35
- package/lib/types/src/client/pg/v2.d.ts.map +0 -1
- package/lib/types/src/client/pg/v2Client.d.ts +0 -142
- package/lib/types/src/client/pg/v2Client.d.ts.map +0 -1
- package/lib/types/src/client/price.d.ts +0 -11
- package/lib/types/src/client/price.d.ts.map +0 -1
- package/lib/types/src/client/render.d.ts +0 -19
- package/lib/types/src/client/render.d.ts.map +0 -1
- package/lib/types/src/client/squads.d.ts +0 -17
- package/lib/types/src/client/squads.d.ts.map +0 -1
- package/lib/types/src/client/trade.d.ts +0 -15
- package/lib/types/src/client/trade.d.ts.map +0 -1
- package/lib/types/src/client/wormhole.d.ts +0 -9
- package/lib/types/src/client/wormhole.d.ts.map +0 -1
- package/lib/types/src/dbTypes.d.ts +0 -123
- package/lib/types/src/dbTypes.d.ts.map +0 -1
- package/lib/types/src/dbTypesV2.d.ts +0 -109
- package/lib/types/src/dbTypesV2.d.ts.map +0 -1
- package/lib/types/src/errorReporter.d.ts +0 -12
- package/lib/types/src/errorReporter.d.ts.map +0 -1
- package/lib/types/src/index.d.ts +0 -12
- package/lib/types/src/index.d.ts.map +0 -1
- package/lib/types/src/logger.d.ts +0 -16
- 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
|