@render-foundation/utils 0.0.253 → 0.0.254
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/lib/cjs/client/pg/base.js.map +1 -1
- package/lib/cjs/client/pg/v2Client.js +199 -206
- package/lib/cjs/client/pg/v2Client.js.map +1 -1
- package/lib/cjs/index.js +2 -4
- package/lib/cjs/index.js.map +1 -1
- package/lib/cjs/tsconfig.cjs.tsbuildinfo +1 -0
- package/lib/esm/src/client/pg/base.js.map +1 -1
- package/lib/esm/src/client/pg/v2Client.js +189 -194
- package/lib/esm/src/client/pg/v2Client.js.map +1 -1
- package/lib/esm/src/index.js +1 -1
- package/lib/esm/src/index.js.map +1 -1
- package/lib/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/lib/types/src/client/pg/base.d.ts +5 -1
- package/lib/types/src/client/pg/base.d.ts.map +1 -1
- package/lib/types/src/client/pg/v2Client.d.ts +12 -63
- package/lib/types/src/client/pg/v2Client.d.ts.map +1 -1
- package/lib/types/src/dbTypesV2.d.ts +0 -3
- package/lib/types/src/dbTypesV2.d.ts.map +1 -1
- package/lib/types/src/index.d.ts +2 -2
- package/lib/types/src/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/lib/cjs/burn/burnCalculations.js +0 -140
- package/lib/cjs/burn/burnCalculations.js.map +0 -1
- package/lib/esm/src/burn/burnCalculations.js +0 -124
- package/lib/esm/src/burn/burnCalculations.js.map +0 -1
- package/lib/types/src/burn/burnCalculations.d.ts +0 -52
- package/lib/types/src/burn/burnCalculations.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../../src/client/pg/base.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AACA,2BAA6C;AAE7C,yCACC;AAAC,MAAM,CAAC,SAAiB,CAAC,MAAM,GAAG;IAClC,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAA;AACxB,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../../src/client/pg/base.ts"],"names":[],"mappings":"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"}
|
|
@@ -35,7 +35,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
35
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
36
|
};
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
-
exports.pgClient = exports.batchFinishedAtMedian = exports.
|
|
38
|
+
exports.pgClient = exports.batchFinishedAtMedian = exports.foldGrantAllotment = exports.CREDIT_DECIMALS = exports.EUR_TO_CREDITS = exports.DISPERSED_BURN_CORRECTION_TABLE = exports.DISPERSED_SETTLEMENT_TABLE = exports.GRANT_BURN_TABLE = exports.GRANT_BURN_ID_TABLE = exports.OTOY_GRANT_TABLE = exports.USER_GRANT_SPEND_TABLE = exports.CURRENT_USER_GRANT_SPEND_TABLE = exports.POLYGON_UPGRADE_TABLE = exports.ENTITY_EPOCH_INFO_TABLE = exports.BURN_CORRECTION_TABLE = exports.NETWORK_REVENUE_TABLE = exports.BRIDGE_TRANSFER_TABLE = exports.BURN_TABLE = exports.JOB_TABLE = exports.JOB_ID_TABLE = exports.LIABILITY_ADJUSTMENT_BATCH_TABLE = exports.LIABILITY_ADJUSTMENT_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
39
|
const kysely_1 = require("kysely");
|
|
40
40
|
const logger_1 = require("../../logger");
|
|
41
41
|
const pg_1 = require("pg");
|
|
@@ -71,117 +71,36 @@ BigInt.prototype.toJSON = function () {
|
|
|
71
71
|
// confirmed_amount = EUR, despite the column name); 1 render credit = EUR 0.25, so credits = EUR x 4.
|
|
72
72
|
// job.render_amt / user_grant_spend.render_spent_delta are credits x 1e8.
|
|
73
73
|
exports.EUR_TO_CREDITS = BigInt(4);
|
|
74
|
-
// Grant accounting window: otoy_grant mirrors OTOY RFG issuances from this date. Consumption against the
|
|
75
|
-
// window counts EVERY job the user ran in it — buy-and-burn jobs consumed OTOY credits exactly like
|
|
76
|
-
// emissions-funded ones (counting only emissions-attributed spend over-issued ~2.58M credits, 2026-08-04).
|
|
77
|
-
exports.GRANT_WINDOW_START = '2025-05-01';
|
|
78
74
|
exports.CREDIT_DECIMALS = BigInt(100000000); // 1e8
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
t: e.t,
|
|
98
|
-
amount: e.amt,
|
|
99
|
-
reversed: BigInt(0),
|
|
100
|
-
drawnEmissions: BigInt(0),
|
|
101
|
-
drawnMisrouted: BigInt(0),
|
|
102
|
-
expired: BigInt(0),
|
|
103
|
-
left: BigInt(0),
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
let claw = -e.amt; // clawback hits remaining capacity oldest-first; excess is dropped
|
|
108
|
-
for (const b of buckets) {
|
|
109
|
-
if (claw <= BigInt(0))
|
|
110
|
-
break;
|
|
111
|
-
const take = remaining(b) < claw ? remaining(b) : claw;
|
|
112
|
-
if (take > BigInt(0)) {
|
|
113
|
-
b.reversed += take;
|
|
114
|
-
claw -= take;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
else {
|
|
120
|
-
let need = -e.amt;
|
|
121
|
-
const total = need;
|
|
122
|
-
let emissionsLeft = (_c = e.emissions) !== null && _c !== void 0 ? _c : need; // no split provided -> count it all as emissions
|
|
123
|
-
let jobEm = BigInt(0);
|
|
124
|
-
let jobMis = BigInt(0);
|
|
125
|
-
for (const b of buckets) {
|
|
126
|
-
if (need <= BigInt(0))
|
|
127
|
-
break;
|
|
128
|
-
if (b.t + lookback < e.t)
|
|
129
|
-
continue; // grant expired before this job ran
|
|
130
|
-
const take = remaining(b) < need ? remaining(b) : need;
|
|
131
|
-
if (take <= BigInt(0))
|
|
132
|
-
continue;
|
|
133
|
-
const em = emissionsLeft < take ? emissionsLeft : take;
|
|
134
|
-
b.drawnEmissions += em;
|
|
135
|
-
b.drawnMisrouted += take - em;
|
|
136
|
-
jobEm += em;
|
|
137
|
-
jobMis += take - em;
|
|
138
|
-
emissionsLeft -= em;
|
|
139
|
-
need -= take;
|
|
140
|
-
}
|
|
141
|
-
beyond += need;
|
|
142
|
-
jobs.push({
|
|
143
|
-
id: e.id,
|
|
144
|
-
t: e.t,
|
|
145
|
-
need: total,
|
|
146
|
-
drawnEmissions: jobEm,
|
|
147
|
-
drawnMisrouted: jobMis,
|
|
148
|
-
beyond: need,
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
let avail = BigInt(0);
|
|
153
|
-
let expired = BigInt(0);
|
|
154
|
-
let usedEmissions = BigInt(0);
|
|
155
|
-
let usedMisrouted = BigInt(0);
|
|
75
|
+
/**
|
|
76
|
+
* Pure core of the grant allotment: fold a user's OTOY grants against what's already been spent.
|
|
77
|
+
*
|
|
78
|
+
* consumed = attributedSpend (spend already stamped with an otoy_grant_id)
|
|
79
|
+
* + correctionSettled (jobs whose grant is already being settled by a burn_correction)
|
|
80
|
+
*
|
|
81
|
+
* The correctionSettled term is the DOUBLE-SPEND GUARD: an escrow_credit correction means we're
|
|
82
|
+
* recovering that job's dollars from escrow, so its grant is already committed. Counting it here stops
|
|
83
|
+
* the same grant from also funding a future emissions burn.
|
|
84
|
+
*
|
|
85
|
+
* fifoGrantId = the oldest grant still holding room, i.e. the one the next spend draws from.
|
|
86
|
+
*/
|
|
87
|
+
const foldGrantAllotment = (grants, attributedSpend, correctionSettled) => {
|
|
88
|
+
const granted = grants.reduce((s, g) => s + g.amountCredits, BigInt(0));
|
|
89
|
+
const consumed = (attributedSpend > BigInt(0) ? attributedSpend : BigInt(0)) +
|
|
90
|
+
(correctionSettled > BigInt(0) ? correctionSettled : BigInt(0));
|
|
91
|
+
const avail = granted > consumed ? granted - consumed : BigInt(0);
|
|
92
|
+
let drawn = consumed;
|
|
156
93
|
let fifoGrantId;
|
|
157
|
-
for (const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (b.t + lookback < now) {
|
|
162
|
-
b.expired = rem;
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
b.left = rem;
|
|
166
|
-
avail += rem;
|
|
167
|
-
if (fifoGrantId === undefined && rem > BigInt(0) && b.grantId !== undefined)
|
|
168
|
-
fifoGrantId = b.grantId;
|
|
94
|
+
for (const g of grants) {
|
|
95
|
+
if (drawn < g.amountCredits) {
|
|
96
|
+
fifoGrantId = g.id;
|
|
97
|
+
break;
|
|
169
98
|
}
|
|
170
|
-
|
|
99
|
+
drawn -= g.amountCredits;
|
|
171
100
|
}
|
|
172
|
-
return {
|
|
173
|
-
avail,
|
|
174
|
-
beyondGrants: beyond,
|
|
175
|
-
jobCharged: usedEmissions + usedMisrouted,
|
|
176
|
-
usedEmissions,
|
|
177
|
-
usedMisrouted,
|
|
178
|
-
expired,
|
|
179
|
-
buckets,
|
|
180
|
-
jobs,
|
|
181
|
-
fifoGrantId,
|
|
182
|
-
};
|
|
101
|
+
return { granted, consumed, avail, fifoGrantId };
|
|
183
102
|
};
|
|
184
|
-
exports.
|
|
103
|
+
exports.foldGrantAllotment = foldGrantAllotment;
|
|
185
104
|
const base_2 = require("./base");
|
|
186
105
|
const moment_1 = __importDefault(require("moment"));
|
|
187
106
|
pg.types.setTypeParser(1114, (str) => moment_1.default.utc(str).toDate());
|
|
@@ -309,54 +228,66 @@ const pgClient = (config) => {
|
|
|
309
228
|
// Spendable grant per user, straight off otoy_grant (FIFO), net of what's already been spent or
|
|
310
229
|
// already settled by a burn correction. See GrantAllotment for the units + the double-spend guard.
|
|
311
230
|
const getGrantAllotments = (db, p, log = logger_1.consoleLogger) => __awaiter(void 0, void 0, void 0, function* () {
|
|
312
|
-
var _b, _c;
|
|
231
|
+
var _b, _c, _d;
|
|
313
232
|
const out = {};
|
|
314
233
|
if (!p.userIds.length)
|
|
315
234
|
return out;
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
235
|
+
const grants = yield db
|
|
236
|
+
.selectFrom(exports.OTOY_GRANT_TABLE)
|
|
237
|
+
.select(['id', 'user_id', 'amount_credits', 'otoy_created_at'])
|
|
238
|
+
.where('user_id', 'in', p.userIds)
|
|
239
|
+
.orderBy('otoy_created_at', 'asc')
|
|
240
|
+
.orderBy('id', 'asc')
|
|
241
|
+
.execute();
|
|
242
|
+
if (!grants.length)
|
|
243
|
+
return out;
|
|
244
|
+
// Anything already booked against a pool grant, in EITHER direction:
|
|
245
|
+
// - negative delta = spend drawn from the grant (this mechanism)
|
|
246
|
+
// - positive delta = the grant was CREDITED into current_user_grant_spend (the one-off canary
|
|
247
|
+
// route). That balance is already handed to the caller separately, so leaving it in the pool too
|
|
248
|
+
// would hand out the same grant twice.
|
|
249
|
+
// Hence abs(): both directions retire pool capacity.
|
|
250
|
+
const spent = yield db
|
|
251
|
+
.selectFrom(exports.USER_GRANT_SPEND_TABLE)
|
|
252
|
+
.select((eb) => [
|
|
253
|
+
'user_id',
|
|
254
|
+
eb.fn.sum((0, kysely_1.sql) `abs(render_spent_delta)`).as('net'),
|
|
255
|
+
])
|
|
256
|
+
.where('user_id', 'in', p.userIds)
|
|
257
|
+
.where('otoy_grant_id', 'is not', null)
|
|
258
|
+
.groupBy('user_id')
|
|
259
|
+
.execute();
|
|
260
|
+
// jobs already settled by a burn correction — their grant is spoken for (double-spend guard)
|
|
261
|
+
const corrected = yield db
|
|
262
|
+
.selectFrom(`${exports.JOB_TABLE} as j`)
|
|
263
|
+
.innerJoin(`${exports.BURN_CORRECTION_TABLE} as bc`, 'bc.job_id', 'j.id')
|
|
264
|
+
.select((eb) => ['j.user_id as user_id', eb.fn.sum('j.render_amt').as('amt')])
|
|
265
|
+
.where('j.user_id', 'in', p.userIds)
|
|
266
|
+
.groupBy('j.user_id')
|
|
267
|
+
.execute();
|
|
268
|
+
const spentBy = new Map(spent.map((r) => { var _a; return [r.user_id, BigInt((_a = r.net) !== null && _a !== void 0 ? _a : 0)]; }));
|
|
269
|
+
const corrBy = new Map(corrected.map((r) => { var _a; return [r.user_id, BigInt((_a = r.amt) !== null && _a !== void 0 ? _a : 0)]; }));
|
|
270
|
+
for (const g of grants) {
|
|
271
|
+
const u = g.user_id;
|
|
272
|
+
const cur = (_b = out[u]) !== null && _b !== void 0 ? _b : (out[u] = { userId: u, granted: BigInt(0), consumed: BigInt(0), avail: BigInt(0), grants: [] });
|
|
273
|
+
// amount_credits is numeric EUR — truncate to whole base units after the x4 conversion
|
|
274
|
+
const credits = (BigInt(Math.round(Number(g.amount_credits) * 1e8)) * exports.EUR_TO_CREDITS);
|
|
275
|
+
cur.granted += credits;
|
|
276
|
+
cur.grants.push({
|
|
277
|
+
id: Number(g.id),
|
|
278
|
+
amountCredits: credits,
|
|
279
|
+
createdAt: g.otoy_created_at ? new Date(g.otoy_created_at) : null,
|
|
344
280
|
});
|
|
345
|
-
byUser.set(r.u, arr);
|
|
346
281
|
}
|
|
347
|
-
for (const
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
};
|
|
357
|
-
if (f.beyondGrants > BigInt(0)) {
|
|
358
|
-
log.info(`grant allotment ${u}: ${f.beyondGrants} beyond grants (purchase-paid at the time), ` +
|
|
359
|
-
`${f.expired} expired past the ${exports.GRANT_LOOKBACK_DAYS}d window — avail ${f.avail}`);
|
|
282
|
+
for (const u of Object.keys(out)) {
|
|
283
|
+
const attributed = (_c = spentBy.get(u)) !== null && _c !== void 0 ? _c : BigInt(0); // abs() — spend drawn or grant already credited
|
|
284
|
+
const viaCorrection = (_d = corrBy.get(u)) !== null && _d !== void 0 ? _d : BigInt(0);
|
|
285
|
+
const f = (0, exports.foldGrantAllotment)(out[u].grants, attributed, viaCorrection);
|
|
286
|
+
out[u].granted = f.granted;
|
|
287
|
+
out[u].consumed = f.consumed;
|
|
288
|
+
out[u].avail = f.avail;
|
|
289
|
+
if (viaCorrection > BigInt(0)) {
|
|
290
|
+
log.info(`grant allotment ${u}: granted ${f.granted} - attributed ${attributed} - correction-settled ${viaCorrection} = ${f.avail}`);
|
|
360
291
|
}
|
|
361
292
|
}
|
|
362
293
|
return out;
|
|
@@ -441,7 +372,7 @@ const pgClient = (config) => {
|
|
|
441
372
|
const sequenceNumbers = [];
|
|
442
373
|
const dbEpochIds = [];
|
|
443
374
|
for (const bt of bts) {
|
|
444
|
-
let { solKey: toSolKey, seq, createdAt, amount, upgradeBracket, priorSupply, points, epochId,
|
|
375
|
+
let { solKey: toSolKey, seq, createdAt, amount, upgradeBracket, priorSupply, points, epochId, } = bt;
|
|
445
376
|
let entityId;
|
|
446
377
|
if (toSolKey && toSolKey != '') {
|
|
447
378
|
entityId = yield getOrInsertEntity(db, { solKey: toSolKey });
|
|
@@ -462,7 +393,6 @@ const pgClient = (config) => {
|
|
|
462
393
|
prior_supply: priorSupply,
|
|
463
394
|
points: points,
|
|
464
395
|
epoch_id: dbEpochId,
|
|
465
|
-
sender: sender,
|
|
466
396
|
})
|
|
467
397
|
.onConflict((oc) => oc.column('sequence').doUpdateSet({
|
|
468
398
|
created_at: createdAt,
|
|
@@ -472,7 +402,6 @@ const pgClient = (config) => {
|
|
|
472
402
|
points: points,
|
|
473
403
|
epoch_id: dbEpochId,
|
|
474
404
|
entity_id: entityId,
|
|
475
|
-
sender: sender,
|
|
476
405
|
}))
|
|
477
406
|
.returning('sequence');
|
|
478
407
|
const c = q.compile();
|
|
@@ -1227,7 +1156,7 @@ const pgClient = (config) => {
|
|
|
1227
1156
|
});
|
|
1228
1157
|
},
|
|
1229
1158
|
insertGrantSpend(db, p, log = logger_1.consoleLogger) {
|
|
1230
|
-
var _a, _b, _c
|
|
1159
|
+
var _a, _b, _c;
|
|
1231
1160
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1232
1161
|
const existing = yield getCurrentUserGrantSpend(db.trx, { userId: p.userId }, log);
|
|
1233
1162
|
const diff = {
|
|
@@ -1254,13 +1183,16 @@ const pgClient = (config) => {
|
|
|
1254
1183
|
return;
|
|
1255
1184
|
}
|
|
1256
1185
|
}
|
|
1257
|
-
// FIFO-attribute this spend to the user's oldest
|
|
1258
|
-
//
|
|
1259
|
-
//
|
|
1186
|
+
// FIFO-attribute this spend to the user's oldest OTOY grant that still has room. Stamping
|
|
1187
|
+
// otoy_grant_id is what makes getGrantAllotments count it as consumed — an unattributed row
|
|
1188
|
+
// would leave the grant looking unspent and let it fund a second burn.
|
|
1260
1189
|
let otoyGrantId = p.otoyGrantId;
|
|
1261
1190
|
if (otoyGrantId === undefined && p.renderSpentDelta < BigInt(0)) {
|
|
1262
1191
|
const allots = yield getGrantAllotments(db.trx, { userIds: [p.userId] }, log);
|
|
1263
|
-
|
|
1192
|
+
const a = allots[p.userId];
|
|
1193
|
+
if (a) {
|
|
1194
|
+
otoyGrantId = (0, exports.foldGrantAllotment)(a.grants, a.consumed, BigInt(0)).fifoGrantId;
|
|
1195
|
+
}
|
|
1264
1196
|
}
|
|
1265
1197
|
const v = {
|
|
1266
1198
|
user_id: p.userId,
|
|
@@ -1286,7 +1218,7 @@ const pgClient = (config) => {
|
|
|
1286
1218
|
user_id: p.userId,
|
|
1287
1219
|
render_spent: p.renderSpentDelta,
|
|
1288
1220
|
description: p.description,
|
|
1289
|
-
perpetual: (
|
|
1221
|
+
perpetual: (_c = p.perpetual) !== null && _c !== void 0 ? _c : false,
|
|
1290
1222
|
})
|
|
1291
1223
|
.onConflict((oc) => oc.column('user_id').doUpdateSet(diff))
|
|
1292
1224
|
.returning((eb) => [
|
|
@@ -1631,75 +1563,138 @@ const pgClient = (config) => {
|
|
|
1631
1563
|
fetchBurnsPage(db, f, log = logger_1.consoleLogger) {
|
|
1632
1564
|
var _a;
|
|
1633
1565
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1634
|
-
const
|
|
1635
|
-
|
|
1636
|
-
.
|
|
1637
|
-
.
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
if (f.
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1566
|
+
const params = [];
|
|
1567
|
+
const p = (v) => {
|
|
1568
|
+
params.push(v);
|
|
1569
|
+
return `$${params.length}`;
|
|
1570
|
+
};
|
|
1571
|
+
// Decode cursor — supports new {t,id,ea} format and legacy bare-id format.
|
|
1572
|
+
let cursorEa;
|
|
1573
|
+
let cursorType;
|
|
1574
|
+
let cursorId;
|
|
1575
|
+
if (f.cursor) {
|
|
1576
|
+
const raw = atob(f.cursor);
|
|
1577
|
+
try {
|
|
1578
|
+
const c = JSON.parse(raw);
|
|
1579
|
+
cursorEa = new Date(c.ea);
|
|
1580
|
+
cursorType = c.t;
|
|
1581
|
+
cursorId = c.id;
|
|
1582
|
+
}
|
|
1583
|
+
catch (_b) {
|
|
1584
|
+
// Legacy cursor: bare burn.id — treat as buy-burn cursor.
|
|
1585
|
+
cursorId = Number(raw);
|
|
1586
|
+
cursorType = 'buy';
|
|
1587
|
+
}
|
|
1652
1588
|
}
|
|
1589
|
+
// Shared WHERE fragments pushed into each union leg for index use.
|
|
1590
|
+
const dateFilters = [];
|
|
1591
|
+
if (f.executedAfter)
|
|
1592
|
+
dateFilters.push(`st.executed_at >= ${p(f.executedAfter)}`);
|
|
1593
|
+
if (f.executedBefore)
|
|
1594
|
+
dateFilters.push(`st.executed_at <= ${p(f.executedBefore)}`);
|
|
1595
|
+
const sigFilter = f.sig ? `st.sig = ${p(f.sig)}` : '';
|
|
1596
|
+
// Buy-burn leg
|
|
1597
|
+
const buyWhere = [...dateFilters];
|
|
1598
|
+
if (!f.inclManual)
|
|
1599
|
+
buyWhere.push('b.usdc_spent > 0');
|
|
1600
|
+
if (sigFilter)
|
|
1601
|
+
buyWhere.push(sigFilter);
|
|
1653
1602
|
if (f.jobId !== undefined) {
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1603
|
+
buyWhere.push(`b.id IN (SELECT burn_id FROM job WHERE id = ${p(f.jobId)})`);
|
|
1604
|
+
}
|
|
1605
|
+
const buyWhereClause = buyWhere.length ? `WHERE ${buyWhere.join(' AND ')}` : '';
|
|
1606
|
+
const buySql = `
|
|
1607
|
+
SELECT 'buy'::text AS type, b.id::bigint AS sortid, b.id AS id,
|
|
1608
|
+
st.executed_at, b.priced_at, b.burned::text AS burned,
|
|
1609
|
+
b.usdc_spent::text AS usdc_spent, b.quote_amt::text AS quote_amt,
|
|
1610
|
+
b.tags, st.sig, b.render_to_usdc, b.eur_to_usdc,
|
|
1611
|
+
coalesce(b.from_escrow_usdc, 0)::text AS from_escrow_usdc,
|
|
1612
|
+
b.down_correction_id, b.escrow_correction_id,
|
|
1613
|
+
b.marked_burned_at
|
|
1614
|
+
FROM burn b
|
|
1615
|
+
INNER JOIN sol_tx st ON st.id = b.sol_tx_id
|
|
1616
|
+
${buyWhereClause}`;
|
|
1617
|
+
// Grant-burn leg
|
|
1618
|
+
const grantWhere = [...dateFilters];
|
|
1619
|
+
if (sigFilter)
|
|
1620
|
+
grantWhere.push(sigFilter);
|
|
1621
|
+
if (f.jobId !== undefined) {
|
|
1622
|
+
grantWhere.push(`gb.id IN (SELECT grant_burn_id FROM job WHERE id = ${p(f.jobId)})`);
|
|
1623
|
+
}
|
|
1624
|
+
const grantWhereClause = grantWhere.length ? `WHERE ${grantWhere.join(' AND ')}` : '';
|
|
1625
|
+
const grantSql = `
|
|
1626
|
+
SELECT 'grant'::text AS type, gb.id::bigint AS sortid, gb.id AS id,
|
|
1627
|
+
st.executed_at, null::timestamp AS priced_at, gb.burned::text AS burned,
|
|
1628
|
+
'0' AS usdc_spent, '0' AS quote_amt,
|
|
1629
|
+
gb.tags, st.sig, null::float8 AS render_to_usdc, null::float8 AS eur_to_usdc,
|
|
1630
|
+
'0' AS from_escrow_usdc,
|
|
1631
|
+
null::bigint AS down_correction_id, null::bigint AS escrow_correction_id,
|
|
1632
|
+
gb.marked_burned_at
|
|
1633
|
+
FROM grant_burn gb
|
|
1634
|
+
INNER JOIN sol_tx st ON st.id = gb.sol_tx_id
|
|
1635
|
+
${grantWhereClause}`;
|
|
1636
|
+
// Cursor filter on the outer query — row comparison for deterministic paging.
|
|
1637
|
+
let cursorFilter = '';
|
|
1638
|
+
if (cursorEa && cursorType && cursorId !== undefined) {
|
|
1639
|
+
cursorFilter = `WHERE (u.executed_at, u.type, u.sortid) > (${p(cursorEa)}, ${p(cursorType)}, ${p(cursorId)})`;
|
|
1640
|
+
}
|
|
1641
|
+
else if (cursorId !== undefined) {
|
|
1642
|
+
// Legacy cursor fallback: only buy burns, ordered by id.
|
|
1643
|
+
cursorFilter = `WHERE u.type = 'buy' AND u.sortid > ${p(cursorId)}`;
|
|
1664
1644
|
}
|
|
1665
1645
|
const limit = (_a = f.limit) !== null && _a !== void 0 ? _a : 1000;
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1646
|
+
const sql = `
|
|
1647
|
+
SELECT u.* FROM (
|
|
1648
|
+
${buySql}
|
|
1649
|
+
UNION ALL
|
|
1650
|
+
${grantSql}
|
|
1651
|
+
) u
|
|
1652
|
+
${cursorFilter}
|
|
1653
|
+
ORDER BY u.executed_at ASC, u.type, u.sortid
|
|
1654
|
+
LIMIT ${p(limit)}`;
|
|
1655
|
+
const { rows } = yield (0, base_1.timedQuery)(pgPool, sql, params, 'fetchBurnsPage', log);
|
|
1669
1656
|
const burns = rows.map((r) => {
|
|
1670
|
-
var _a, _b;
|
|
1657
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1671
1658
|
return ({
|
|
1672
1659
|
jobs: [],
|
|
1673
1660
|
id: Number(r.id),
|
|
1674
|
-
|
|
1661
|
+
type: r.type,
|
|
1662
|
+
renderToUsdc: (_a = r.render_to_usdc) !== null && _a !== void 0 ? _a : undefined,
|
|
1675
1663
|
solTx: r.sig,
|
|
1676
1664
|
executedAt: r.executed_at,
|
|
1677
|
-
pricedAt: r.priced_at,
|
|
1678
|
-
usdcSpent: BigInt((
|
|
1679
|
-
quoteAmt: BigInt((
|
|
1665
|
+
pricedAt: (_b = r.priced_at) !== null && _b !== void 0 ? _b : undefined,
|
|
1666
|
+
usdcSpent: BigInt((_c = r.usdc_spent) !== null && _c !== void 0 ? _c : 0),
|
|
1667
|
+
quoteAmt: BigInt((_d = r.quote_amt) !== null && _d !== void 0 ? _d : 0),
|
|
1680
1668
|
burned: BigInt(r.burned),
|
|
1681
|
-
eurToUsdc: r.eur_to_usdc,
|
|
1669
|
+
eurToUsdc: (_e = r.eur_to_usdc) !== null && _e !== void 0 ? _e : undefined,
|
|
1682
1670
|
markedBurnedAt: r.marked_burned_at,
|
|
1683
1671
|
tags: r.tags ? r.tags.split(',') : [],
|
|
1672
|
+
fromEscrowUsdc: BigInt((_f = r.from_escrow_usdc) !== null && _f !== void 0 ? _f : 0),
|
|
1673
|
+
downCorrectionId: r.down_correction_id ? Number(r.down_correction_id) : undefined,
|
|
1674
|
+
escrowCorrectionId: r.escrow_correction_id ? Number(r.escrow_correction_id) : undefined,
|
|
1684
1675
|
});
|
|
1685
1676
|
});
|
|
1686
1677
|
return {
|
|
1687
1678
|
burns,
|
|
1688
|
-
// Only hand back a cursor on a full page; a short page means we're done.
|
|
1689
1679
|
cursor: burns.length === limit
|
|
1690
|
-
? btoa(
|
|
1680
|
+
? btoa(JSON.stringify({
|
|
1681
|
+
ea: rows[burns.length - 1].executed_at,
|
|
1682
|
+
t: rows[burns.length - 1].type,
|
|
1683
|
+
id: rows[burns.length - 1].sortid,
|
|
1684
|
+
}))
|
|
1691
1685
|
: undefined,
|
|
1692
1686
|
};
|
|
1693
1687
|
});
|
|
1694
1688
|
},
|
|
1695
|
-
fetchBurnJobs(db, burnId, log = logger_1.consoleLogger) {
|
|
1689
|
+
fetchBurnJobs(db, burnId, burnType = 'buy', log = logger_1.consoleLogger) {
|
|
1696
1690
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1691
|
+
const fk = burnType === 'grant' ? 'grant_burn_id' : 'burn_id';
|
|
1697
1692
|
const rows = yield db.trx
|
|
1698
1693
|
.selectFrom('job')
|
|
1699
1694
|
.selectAll('job')
|
|
1700
|
-
.where(
|
|
1695
|
+
.where(fk, '=', String(burnId))
|
|
1701
1696
|
.execute();
|
|
1702
|
-
log.debug(`fetchBurnJobs
|
|
1697
|
+
log.debug(`fetchBurnJobs ${burnType} ${burnId} -> ${rows.length} jobs`);
|
|
1703
1698
|
return rows.map((r) => ({
|
|
1704
1699
|
id: Number(r.id),
|
|
1705
1700
|
completedAt: r.completed_at,
|
|
@@ -2031,7 +2026,7 @@ const pgClient = (config) => {
|
|
|
2031
2026
|
// took the room), the whole txn rolls back and we return {inserted:false} — the caller must NOT
|
|
2032
2027
|
// broadcast (no row, no counter change, no burn).
|
|
2033
2028
|
return yield db.transaction().execute((trx) => __awaiter(this, void 0, void 0, function* () {
|
|
2034
|
-
var _a, _b, _c, _d, _e, _f, _g
|
|
2029
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
2035
2030
|
const res = yield trx
|
|
2036
2031
|
.insertInto(exports.DISPERSED_SETTLEMENT_TABLE)
|
|
2037
2032
|
.values({
|
|
@@ -2046,12 +2041,10 @@ const pgClient = (config) => {
|
|
|
2046
2041
|
usdc_spent: (_c = p.usdcSpent) !== null && _c !== void 0 ? _c : null,
|
|
2047
2042
|
correction_id: (_d = p.correctionId) !== null && _d !== void 0 ? _d : null,
|
|
2048
2043
|
correction_render: (_e = p.correctionRender) !== null && _e !== void 0 ? _e : null,
|
|
2049
|
-
usage_from: (_f = p.usageFrom) !== null && _f !== void 0 ? _f : null,
|
|
2050
|
-
usage_to: (_g = p.usageTo) !== null && _g !== void 0 ? _g : null,
|
|
2051
2044
|
})
|
|
2052
2045
|
.onConflict((oc) => oc.column('tx_signature').doNothing())
|
|
2053
2046
|
.executeTakeFirst();
|
|
2054
|
-
const inserted = ((
|
|
2047
|
+
const inserted = ((_f = res.numInsertedOrUpdatedRows) !== null && _f !== void 0 ? _f : BigInt(0)) > BigInt(0);
|
|
2055
2048
|
// Only reserve when the row was actually inserted (a tx_signature conflict is a no-op → no double
|
|
2056
2049
|
// count) and it drew a correction.
|
|
2057
2050
|
if (inserted &&
|
|
@@ -2066,7 +2059,7 @@ const pgClient = (config) => {
|
|
|
2066
2059
|
.where('id', '=', String(p.correctionId))
|
|
2067
2060
|
.where((eb) => eb((0, kysely_1.sql) `consumed_render + ${p.correctionRender}::numeric`, '<=', eb.ref('amount_render')))
|
|
2068
2061
|
.executeTakeFirst();
|
|
2069
|
-
if (((
|
|
2062
|
+
if (((_g = upd.numUpdatedRows) !== null && _g !== void 0 ? _g : BigInt(0)) === BigInt(0)) {
|
|
2070
2063
|
// Would exceed amount_render (concurrent draw won the room) — roll back the whole txn.
|
|
2071
2064
|
log.warn(`dispersed correction ${p.correctionId}: draw ${p.correctionRender} would over-consume; rejecting outbox insert for tx ${p.txSignature}`);
|
|
2072
2065
|
throw new DispersedCorrectionRejected();
|