@render-foundation/utils 0.0.231 → 0.0.232-beta.0

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 (34) hide show
  1. package/lib/cjs/client/dispersed.js +123 -0
  2. package/lib/cjs/client/dispersed.js.map +1 -0
  3. package/lib/cjs/client/pg/v2Client.js +122 -222
  4. package/lib/cjs/client/pg/v2Client.js.map +1 -1
  5. package/lib/cjs/index.js +5 -2
  6. package/lib/cjs/index.js.map +1 -1
  7. package/lib/esm/src/client/dispersed.js +108 -0
  8. package/lib/esm/src/client/dispersed.js.map +1 -0
  9. package/lib/esm/src/client/pg/v2Client.js +109 -214
  10. package/lib/esm/src/client/pg/v2Client.js.map +1 -1
  11. package/lib/esm/src/index.js +5 -2
  12. package/lib/esm/src/index.js.map +1 -1
  13. package/lib/esm/tsconfig.esm.tsbuildinfo +1 -1
  14. package/lib/types/src/client/dispersed.d.ts +91 -0
  15. package/lib/types/src/client/dispersed.d.ts.map +1 -0
  16. package/lib/types/src/client/pg/v2Client.d.ts +31 -41
  17. package/lib/types/src/client/pg/v2Client.d.ts.map +1 -1
  18. package/lib/types/src/dbTypesV2.d.ts +16 -40
  19. package/lib/types/src/dbTypesV2.d.ts.map +1 -1
  20. package/lib/types/src/index.d.ts +2 -2
  21. package/lib/types/src/index.d.ts.map +1 -1
  22. package/package.json +1 -1
  23. package/lib/cjs/burn/burnAnalysis.js +0 -101
  24. package/lib/cjs/burn/burnAnalysis.js.map +0 -1
  25. package/lib/cjs/burn/burnCalculations.js +0 -140
  26. package/lib/cjs/burn/burnCalculations.js.map +0 -1
  27. package/lib/esm/src/burn/burnAnalysis.js +0 -90
  28. package/lib/esm/src/burn/burnAnalysis.js.map +0 -1
  29. package/lib/esm/src/burn/burnCalculations.js +0 -124
  30. package/lib/esm/src/burn/burnCalculations.js.map +0 -1
  31. package/lib/types/src/burn/burnAnalysis.d.ts +0 -51
  32. package/lib/types/src/burn/burnAnalysis.d.ts.map +0 -1
  33. package/lib/types/src/burn/burnCalculations.d.ts +0 -52
  34. package/lib/types/src/burn/burnCalculations.d.ts.map +0 -1
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.dispersedClient = exports.DispersedConflictError = void 0;
16
+ const logger_1 = require("../logger");
17
+ const node_fetch_1 = __importDefault(require("node-fetch"));
18
+ /**
19
+ * Dispersed Token Burn API client (M2M OAuth2 client_credentials).
20
+ *
21
+ * Thin transport only: it mints/caches the bearer token and posts the two burn
22
+ * endpoints (claim, settle). It does NOT price RENDER, sum obligations, or do
23
+ * any burn math — the consumer owns that (incl. the `settled_amount == Σ
24
+ * obligation amounts` invariant). Amounts are passed through as decimal strings.
25
+ *
26
+ * Contract: see docs/dispersed-burn.md. Authoritative spec at
27
+ * `{apiBaseUrl}/openapi.json` (tag "Burn Ledger").
28
+ */
29
+ // Both scopes, space-delimited, requested on every token mint.
30
+ const SCOPES = 'burn_ledger_claims.create.all burn_ledger_settlements.create.all';
31
+ // Re-mint a little before the token actually expires.
32
+ const TOKEN_REFRESH_MARGIN_MS = 60000;
33
+ /**
34
+ * Thrown on a 409 from settle: the claim is missing/expired/released/already
35
+ * settled, an obligation mismatch, an amount mismatch, or a tx_signature reused
36
+ * with a different payload. Nothing was written. Do NOT re-burn — reconcile.
37
+ */
38
+ class DispersedConflictError extends Error {
39
+ constructor(body) {
40
+ super(`dispersed 409 conflict: ${body}`);
41
+ this.body = body;
42
+ this.status = 409;
43
+ this.name = 'DispersedConflictError';
44
+ }
45
+ }
46
+ exports.DispersedConflictError = DispersedConflictError;
47
+ const dispersedClient = (cfg, fetchImpl = node_fetch_1.default) => {
48
+ let cached;
49
+ const mintToken = () => __awaiter(void 0, void 0, void 0, function* () {
50
+ const res = yield fetchImpl(`${cfg.authBaseUrl}/token`, {
51
+ method: 'POST',
52
+ headers: { 'Content-Type': 'application/json' },
53
+ body: JSON.stringify({
54
+ grant_type: 'client_credentials',
55
+ client_id: cfg.clientId,
56
+ client_secret: cfg.clientSecret,
57
+ scope: SCOPES,
58
+ }),
59
+ });
60
+ if (res.status !== 200) {
61
+ throw new Error(`dispersed token mint failed. code: ${res.status} body: ${JSON.stringify(yield res.text())}`);
62
+ }
63
+ const json = (yield res.json());
64
+ cached = {
65
+ token: json.access_token,
66
+ expiresAt: Date.now() + json.expires_in * 1000,
67
+ };
68
+ return cached.token;
69
+ });
70
+ const getToken = () => __awaiter(void 0, void 0, void 0, function* () {
71
+ if (cached && Date.now() < cached.expiresAt - TOKEN_REFRESH_MARGIN_MS) {
72
+ return cached.token;
73
+ }
74
+ return mintToken();
75
+ });
76
+ // POST with bearer; one transparent re-mint+retry on 401 (a dropped daily run
77
+ // is expensive, so it's worth recovering from a token that died mid-flight).
78
+ const authedPost = (path, body) => __awaiter(void 0, void 0, void 0, function* () {
79
+ const doPost = (token) => fetchImpl(`${cfg.apiBaseUrl}${path}`, {
80
+ method: 'POST',
81
+ headers: {
82
+ 'Content-Type': 'application/json',
83
+ Authorization: `Bearer ${token}`,
84
+ },
85
+ body: JSON.stringify(body),
86
+ });
87
+ let res = yield doPost(yield getToken());
88
+ if (res.status === 401) {
89
+ cached = undefined;
90
+ res = yield doPost(yield mintToken());
91
+ }
92
+ return res;
93
+ });
94
+ return {
95
+ claim({ from, to, limit }, log = logger_1.consoleLogger) {
96
+ return __awaiter(this, void 0, void 0, function* () {
97
+ const res = yield authedPost('/v1/burn-ledger-claims', Object.assign({ executor_id: cfg.executorId, from: from.toISOString(), to: to.toISOString() }, (limit !== undefined ? { limit } : {})));
98
+ if (res.status !== 201) {
99
+ throw new Error(`dispersed claim failed. code: ${res.status} body: ${JSON.stringify(yield res.text())}`);
100
+ }
101
+ const result = (yield res.json());
102
+ log.info(`dispersed claim ${result.claim.uuid}: ${result.claimed_count} obligations, expires ${result.claim.claim_expires_at}`);
103
+ return result;
104
+ });
105
+ },
106
+ settle(req, log = logger_1.consoleLogger) {
107
+ return __awaiter(this, void 0, void 0, function* () {
108
+ const res = yield authedPost('/v1/burn-ledger-settlements', req);
109
+ if (res.status === 409) {
110
+ throw new DispersedConflictError(yield res.text());
111
+ }
112
+ if (res.status !== 201 && res.status !== 200) {
113
+ throw new Error(`dispersed settle failed. code: ${res.status} body: ${JSON.stringify(yield res.text())}`);
114
+ }
115
+ const result = (yield res.json());
116
+ log.info(`dispersed settle ${result.settlement.uuid} for tx ${req.tx_signature} (replay=${result.idempotent_replay})`);
117
+ return result;
118
+ });
119
+ },
120
+ };
121
+ };
122
+ exports.dispersedClient = dispersedClient;
123
+ //# sourceMappingURL=dispersed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispersed.js","sourceRoot":"","sources":["../../../src/client/dispersed.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.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.TX_BURN_ADJUSTMENT_TABLE = exports.JOB_BURN_ADJUSTMENT_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;
38
+ exports.pgClient = exports.batchFinishedAtMedian = exports.DISPERSED_SETTLEMENT_TABLE = 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
39
  const kysely_1 = require("kysely");
40
40
  const logger_1 = require("../../logger");
41
41
  const pg_1 = require("pg");
@@ -47,21 +47,19 @@ exports.MANUAL_BURN_TABLE = 'manual_burn';
47
47
  exports.ENTITY_TABLE = 'entity';
48
48
  exports.SOL_TRANSFER_TABLE = 'sol_transfer1';
49
49
  exports.LIABILITY_TABLE = 'liability';
50
- exports.LIABILITY_ADJUSTMENT_TABLE = 'liability_adjustment';
51
- exports.LIABILITY_ADJUSTMENT_BATCH_TABLE = 'liability_adjustment_batch';
52
50
  exports.JOB_ID_TABLE = 'job_id';
53
51
  exports.JOB_TABLE = 'job';
54
52
  exports.BURN_TABLE = 'burn';
55
53
  exports.BRIDGE_TRANSFER_TABLE = 'bridge_transfer';
56
54
  exports.NETWORK_REVENUE_TABLE = 'network_revenue';
57
- exports.JOB_BURN_ADJUSTMENT_TABLE = 'job_burn_adjustment';
58
- exports.TX_BURN_ADJUSTMENT_TABLE = 'tx_burn_adjustment';
55
+ exports.BURN_ADJUSTMENT_TABLE = 'burn_adjustment';
59
56
  exports.ENTITY_EPOCH_INFO_TABLE = 'entity_epoch_info';
60
57
  exports.POLYGON_UPGRADE_TABLE = 'polygon_upgrade';
61
58
  exports.CURRENT_USER_GRANT_SPEND_TABLE = 'current_user_grant_spend';
62
59
  exports.USER_GRANT_SPEND_TABLE = 'user_grant_spend';
63
60
  exports.GRANT_BURN_ID_TABLE = 'grant_burn_id';
64
61
  exports.GRANT_BURN_TABLE = 'grant_burn';
62
+ exports.DISPERSED_SETTLEMENT_TABLE = 'dispersed_settlement';
65
63
  BigInt.prototype.toJSON = function () {
66
64
  return this.toString();
67
65
  };
@@ -358,11 +356,7 @@ const pgClient = (config) => {
358
356
  sig: solTx,
359
357
  executedAt,
360
358
  }, log);
361
- // sol_transfer1 already has UNIQUE(sol_tx_id, from_entity_id,
362
- // to_entity_id, symbol). Without ON CONFLICT a retry of the record step
363
- // throws a unique violation and wedges the BullMQ job; make it an
364
- // idempotent no-op and re-fetch the existing id instead.
365
- let transferRow = yield db
359
+ const { id } = yield db
366
360
  .insertInto(exports.SOL_TRANSFER_TABLE)
367
361
  .values({
368
362
  id: dbId,
@@ -373,23 +367,9 @@ const pgClient = (config) => {
373
367
  symbol,
374
368
  amount_payed: amountPayed,
375
369
  })
376
- .onConflict((oc) => oc
377
- .columns(['sol_tx_id', 'from_entity_id', 'to_entity_id', 'symbol'])
378
- .doNothing())
379
370
  .returning((eb) => ['id as id'])
380
- .executeTakeFirst();
381
- if (!transferRow) {
382
- log.warn(`sol_transfer for sol_tx_id ${solTxId} ${fromEntityId}->${toEntityId} ${symbol} already exists; reusing existing id (idempotent retry)`);
383
- transferRow = yield db
384
- .selectFrom(exports.SOL_TRANSFER_TABLE)
385
- .select((eb) => ['id as id'])
386
- .where('sol_tx_id', '=', solTxId)
387
- .where('from_entity_id', '=', fromEntityId)
388
- .where('to_entity_id', '=', toEntityId)
389
- .where('symbol', '=', symbol)
390
- .executeTakeFirstOrThrow();
391
- }
392
- transferId = BigInt(transferRow.id);
371
+ .executeTakeFirstOrThrow();
372
+ transferId = BigInt(id);
393
373
  }
394
374
  ids.push({ transferId, liabilityId });
395
375
  }
@@ -711,36 +691,9 @@ const pgClient = (config) => {
711
691
  }
712
692
  return b.as('x');
713
693
  }, (join) => join.onRef('y.sol_key', '=', 'x.sol_key'))
714
- // Standing per-wallet/channel corrections (migration 36). NO epoch filter — an adjustment is
715
- // a permanent delta on outstanding, not tied to a payout window; payments net it via `payed`.
716
- .fullJoin((eb) => {
717
- let b = eb
718
- .selectFrom(exports.LIABILITY_ADJUSTMENT_TABLE)
719
- .select(({ fn }) => fn.sum(`amount_adjustment`).as('adj'))
720
- .innerJoin(exports.ENTITY_TABLE, `${exports.LIABILITY_ADJUSTMENT_TABLE}.entity_id`, 'entity.id')
721
- .select(['entity.sol_key'])
722
- .groupBy('entity.sol_key');
723
- if (f.banned) {
724
- b = b.where('entity.banned', '=', true);
725
- }
726
- else {
727
- b = b.where('entity.banned', '=', false);
728
- }
729
- if (f.channels && f.channels.length > 0) {
730
- b = b.where((eb) => eb.or(f.channels.map((c) => eb('liability_adjustment.channel', '=', c))));
731
- }
732
- else {
733
- b = b.where((eb) => eb.or([
734
- eb('liability_adjustment.channel', '=', 'node_operator'),
735
- eb('liability_adjustment.channel', '=', 'availability'),
736
- ]));
737
- }
738
- return b.as('a');
739
- }, (join) => join.on((0, kysely_1.sql) `"a"."sol_key" = coalesce("y"."sol_key", "x"."sol_key")`))
740
694
  .select(({ fn }) => [
741
- fn.coalesce('y.sol_key', 'x.sol_key', 'a.sol_key').as('sol_key'),
742
- (0, kysely_1.sql) `${fn.coalesce(`x.due`, (0, kysely_1.sql) `0`)} +
743
- ${fn.coalesce(`a.adj`, (0, kysely_1.sql) `0`)} -
695
+ fn.coalesce('y.sol_key', 'x.sol_key').as('sol_key'),
696
+ (0, kysely_1.sql) `${fn.coalesce(`x.due`, (0, kysely_1.sql) `0`)} -
744
697
  ${fn.coalesce(`y.payed`, (0, kysely_1.sql) `0`)}`.as('out'),
745
698
  ])
746
699
  .as('z'))
@@ -761,59 +714,6 @@ const pgClient = (config) => {
761
714
  return out;
762
715
  });
763
716
  },
764
- addLiabilityAdjustments(batch, rows, log = logger_1.consoleLogger) {
765
- return __awaiter(this, void 0, void 0, function* () {
766
- return yield db.transaction().execute((trx) => __awaiter(this, void 0, void 0, function* () {
767
- var _a;
768
- // Upsert the batch by its label (idempotent re-runs; label is the run identity).
769
- const b = yield trx
770
- .insertInto(exports.LIABILITY_ADJUSTMENT_BATCH_TABLE)
771
- .values({
772
- label: batch.label,
773
- description: batch.description,
774
- created_by: batch.createdBy,
775
- })
776
- .onConflict((oc) => oc.column('label').doUpdateSet({
777
- description: batch.description,
778
- created_by: batch.createdBy,
779
- }))
780
- .returning('id')
781
- .executeTakeFirstOrThrow();
782
- const batchId = BigInt(b.id);
783
- let inserted = 0;
784
- let skipped = 0;
785
- let net = BigInt(0);
786
- let positive = BigInt(0);
787
- let negative = BigInt(0);
788
- for (const r of rows) {
789
- const entityId = yield getOrInsertEntity(trx, { solKey: r.solKey }, log);
790
- const res = yield trx
791
- .insertInto(exports.LIABILITY_ADJUSTMENT_TABLE)
792
- .values({
793
- entity_id: entityId,
794
- channel: r.channel,
795
- amount_adjustment: r.amountAdjustment,
796
- batch_id: batchId,
797
- })
798
- // unique (entity_id, channel, batch_id) → a re-run of the same batch is a no-op
799
- .onConflict((oc) => oc.columns(['entity_id', 'channel', 'batch_id']).doNothing())
800
- .executeTakeFirst();
801
- if (((_a = res.numInsertedOrUpdatedRows) !== null && _a !== void 0 ? _a : BigInt(0)) > BigInt(0))
802
- inserted++;
803
- else
804
- skipped++;
805
- net += r.amountAdjustment;
806
- if (r.amountAdjustment > BigInt(0))
807
- positive += r.amountAdjustment;
808
- else
809
- negative += r.amountAdjustment;
810
- }
811
- log.info(`liability_adjustment batch '${batch.label}' (id ${batchId}): ` +
812
- `inserted ${inserted}, skipped ${skipped}, net ${net} (+${positive} / ${negative})`);
813
- return { batchId, inserted, skipped, net, positive, negative };
814
- }));
815
- });
816
- },
817
717
  fetchNodeOperatorEpoch(epochId, log = logger_1.consoleLogger) {
818
718
  var _a;
819
719
  return __awaiter(this, void 0, void 0, function* () {
@@ -1124,7 +1024,7 @@ const pgClient = (config) => {
1124
1024
  let buyBurnId;
1125
1025
  let grantBurnId;
1126
1026
  if (p.buyBurn) {
1127
- const { burned, usdcSpent, eurToUsdc, renderToUsdc, quoteAmt, tags, jobBurnAdjustmentId, txBurnAdjustmentId, toBurn, fromEscrowCredit, } = p.buyBurn;
1027
+ const { burned, usdcSpent, eurToUsdc, renderToUsdc, quoteAmt, tags, burnAdjustmentId, toBurn, } = p.buyBurn;
1128
1028
  let pricedAt = p.buyBurn.pricedAt;
1129
1029
  if (!pricedAt) {
1130
1030
  const jobs = yield fetchJobs1(trx.trx, { ids: p.jobs.map((j) => String(j.id)) }, log);
@@ -1143,30 +1043,17 @@ const pgClient = (config) => {
1143
1043
  quote_amt: quoteAmt,
1144
1044
  burned: burned,
1145
1045
  tags: tags.join(','),
1146
- job_burn_adjustment_id: jobBurnAdjustmentId,
1147
- tx_burn_adjustment_id: txBurnAdjustmentId,
1046
+ burn_adjustment_id: burnAdjustmentId,
1148
1047
  to_burn: toBurn,
1149
- from_escrow_credit: fromEscrowCredit !== null && fromEscrowCredit !== void 0 ? fromEscrowCredit : 0,
1150
1048
  };
1151
1049
  log.debug(`inserting burn ${JSON.stringify(v)}`);
1152
- // Idempotent on sol_tx_id (uniq_burn_sol_tx_id, migration 27): a retry of
1153
- // the record step for the same on-chain burn is a safe no-op. On conflict
1154
- // executeTakeFirst() returns undefined, so re-fetch the existing id.
1155
- let burnRow = yield trx.trx
1050
+ const { id } = yield trx.trx
1156
1051
  .insertInto(exports.BURN_TABLE)
1157
1052
  .values(v)
1158
- .onConflict((oc) => oc.column('sol_tx_id').doNothing())
1053
+ //.onConflict((oc) => oc.column('sol_tx').doNothing())
1159
1054
  .returning((eb) => ['id as id'])
1160
- .executeTakeFirst();
1161
- if (!burnRow) {
1162
- log.warn(`burn for sol_tx_id ${solTxId} already exists; reusing existing id (idempotent retry)`);
1163
- burnRow = yield trx.trx
1164
- .selectFrom(exports.BURN_TABLE)
1165
- .select((eb) => ['id as id'])
1166
- .where('sol_tx_id', '=', solTxId)
1167
- .executeTakeFirstOrThrow();
1168
- }
1169
- buyBurnId = Number(burnRow.id);
1055
+ .executeTakeFirstOrThrow();
1056
+ buyBurnId = Number(id);
1170
1057
  }
1171
1058
  if (p.grantBurn) {
1172
1059
  const { burned, tags } = p.grantBurn;
@@ -1176,22 +1063,12 @@ const pgClient = (config) => {
1176
1063
  tags: tags === null || tags === void 0 ? void 0 : tags.join(','),
1177
1064
  };
1178
1065
  log.debug(`inserting grant burn ${JSON.stringify(v)}`);
1179
- // Idempotent on sol_tx_id (uniq_grant_burn_sol_tx_id, migration 27).
1180
- let grantBurnRow = yield trx.trx
1066
+ const { id } = yield trx.trx
1181
1067
  .insertInto(exports.GRANT_BURN_TABLE)
1182
1068
  .values(v)
1183
- .onConflict((oc) => oc.column('sol_tx_id').doNothing())
1184
1069
  .returning((eb) => ['id as id'])
1185
- .executeTakeFirst();
1186
- if (!grantBurnRow) {
1187
- log.warn(`grant_burn for sol_tx_id ${solTxId} already exists; reusing existing id (idempotent retry)`);
1188
- grantBurnRow = yield trx.trx
1189
- .selectFrom(exports.GRANT_BURN_TABLE)
1190
- .select((eb) => ['id as id'])
1191
- .where('sol_tx_id', '=', solTxId)
1192
- .executeTakeFirstOrThrow();
1193
- }
1194
- grantBurnId = Number(grantBurnRow.id);
1070
+ .executeTakeFirstOrThrow();
1071
+ grantBurnId = Number(id);
1195
1072
  }
1196
1073
  const burnId = buyBurnId;
1197
1074
  const grantId = grantBurnId !== null && grantBurnId !== void 0 ? grantBurnId : buyBurnId;
@@ -1710,6 +1587,73 @@ const pgClient = (config) => {
1710
1587
  }));
1711
1588
  });
1712
1589
  },
1590
+ insertDispersedOutbox(p, log = logger_1.consoleLogger) {
1591
+ var _a, _b;
1592
+ return __awaiter(this, void 0, void 0, function* () {
1593
+ const res = yield db
1594
+ .insertInto(exports.DISPERSED_SETTLEMENT_TABLE)
1595
+ .values({
1596
+ tx_signature: p.txSignature,
1597
+ claim_uuid: p.claimUuid,
1598
+ obligation_uuids: p.obligationUuids,
1599
+ settled_amount: p.settledAmount,
1600
+ burned_amount: p.burnedAmount,
1601
+ executed_at: p.executedAt,
1602
+ eur_render: (_a = p.eurRender) !== null && _a !== void 0 ? _a : null,
1603
+ last_valid_block_height: (_b = p.lastValidBlockHeight) !== null && _b !== void 0 ? _b : null,
1604
+ })
1605
+ .onConflict((oc) => oc.column('tx_signature').doNothing())
1606
+ .executeTakeFirst();
1607
+ log.debug(`dispersed outbox tx ${p.txSignature}: ${res.numInsertedOrUpdatedRows} row(s)`);
1608
+ });
1609
+ },
1610
+ markDispersedSettled(txSignature, p, log = logger_1.consoleLogger) {
1611
+ return __awaiter(this, void 0, void 0, function* () {
1612
+ yield db
1613
+ .updateTable(exports.DISPERSED_SETTLEMENT_TABLE)
1614
+ .set({ settled_at: new Date(), idempotent_replay: p.idempotentReplay })
1615
+ .where('tx_signature', '=', txSignature)
1616
+ .execute();
1617
+ log.debug(`dispersed settled tx ${txSignature}`);
1618
+ });
1619
+ },
1620
+ getUnsettledDispersed(log = logger_1.consoleLogger) {
1621
+ return __awaiter(this, void 0, void 0, function* () {
1622
+ const rows = yield db
1623
+ .selectFrom(exports.DISPERSED_SETTLEMENT_TABLE)
1624
+ .selectAll()
1625
+ .where('settled_at', 'is', null)
1626
+ .execute();
1627
+ log.debug(`dispersed outbox: ${rows.length} unsettled`);
1628
+ return rows.map((r) => {
1629
+ var _a;
1630
+ return ({
1631
+ txSignature: r.tx_signature,
1632
+ claimUuid: r.claim_uuid,
1633
+ obligationUuids: r.obligation_uuids,
1634
+ settledAmount: r.settled_amount,
1635
+ burnedAmount: r.burned_amount,
1636
+ executedAt: r.executed_at,
1637
+ eurRender: (_a = r.eur_render) !== null && _a !== void 0 ? _a : undefined,
1638
+ // int8 comes back as a string from pg; block heights are well within JS safe-integer range.
1639
+ lastValidBlockHeight: r.last_valid_block_height != null
1640
+ ? Number(r.last_valid_block_height)
1641
+ : undefined,
1642
+ });
1643
+ });
1644
+ });
1645
+ },
1646
+ voidDispersedOutbox(txSignature, log = logger_1.consoleLogger) {
1647
+ return __awaiter(this, void 0, void 0, function* () {
1648
+ const res = yield db
1649
+ .deleteFrom(exports.DISPERSED_SETTLEMENT_TABLE)
1650
+ .where('tx_signature', '=', txSignature)
1651
+ // Never delete a row we already settled — void only applies to pending (un-landed) rows.
1652
+ .where('settled_at', 'is', null)
1653
+ .executeTakeFirst();
1654
+ log.debug(`dispersed outbox void tx ${txSignature}: ${res.numDeletedRows} row(s)`);
1655
+ });
1656
+ },
1713
1657
  fetchJobs(db, f, log = logger_1.consoleLogger) {
1714
1658
  return __awaiter(this, void 0, void 0, function* () {
1715
1659
  return yield fetchJobs1(db.trx, f, log);
@@ -1779,90 +1723,46 @@ const pgClient = (config) => {
1779
1723
  }));
1780
1724
  });
1781
1725
  },
1782
- createTxBurnAdjustment(trx, p, log = logger_1.consoleLogger) {
1726
+ getBurnAdjustments(trx, ps, log = logger_1.consoleLogger) {
1783
1727
  return __awaiter(this, void 0, void 0, function* () {
1784
- // Idempotent per sol_tx_id (unique) — a re-run for the same bad tx is a no-op.
1785
- const row = yield trx.trx
1786
- .insertInto(exports.TX_BURN_ADJUSTMENT_TABLE)
1787
- .values({
1788
- sol_tx_id: p.solTxId,
1789
- surplus_render: p.surplusRender,
1790
- description: p.description,
1791
- })
1792
- .onConflict((oc) => oc.column('sol_tx_id').doNothing())
1793
- .returning('id')
1794
- .executeTakeFirst();
1795
- if (!row) {
1796
- log.info(`tx_burn_adjustment for sol_tx ${p.solTxId} already exists — skipped`);
1797
- return undefined;
1728
+ if (ps.toFill) {
1729
+ const q = trx.trx
1730
+ .selectFrom(exports.BURN_ADJUSTMENT_TABLE)
1731
+ .selectAll(exports.BURN_ADJUSTMENT_TABLE)
1732
+ .innerJoin(exports.JOB_TABLE, `${exports.JOB_TABLE}.id`, `${exports.BURN_ADJUSTMENT_TABLE}.job_id`)
1733
+ .select([`${exports.JOB_TABLE}.completed_at`, `${exports.JOB_TABLE}.render_amt`])
1734
+ .leftJoin(exports.BURN_TABLE, `${exports.BURN_TABLE}.burn_adjustment_id`, `${exports.BURN_ADJUSTMENT_TABLE}.id`)
1735
+ .select(({ fn, lit }) => [
1736
+ fn
1737
+ .sum(fn.coalesce(`${exports.BURN_TABLE}.to_burn`, lit(0)))
1738
+ .as('tot_to_burn'),
1739
+ fn
1740
+ .sum(fn.coalesce(`${exports.BURN_TABLE}.burned`, lit(0)))
1741
+ .as('tot_burned'),
1742
+ ])
1743
+ .groupBy([
1744
+ `${exports.BURN_ADJUSTMENT_TABLE}.id`,
1745
+ `${exports.JOB_TABLE}.completed_at`,
1746
+ `${exports.JOB_TABLE}.render_amt`,
1747
+ ])
1748
+ .havingRef((0, kysely_1.sql) `SUM(COALESCE("burn"."to_burn", 0)) - SUM(COALESCE("burn"."burned", 0))`, '<', `${exports.BURN_ADJUSTMENT_TABLE}.down_adj_to_burn`);
1749
+ log.info(`getBurnAdjustments ${q.compile().sql}`);
1750
+ const res = yield q.execute();
1751
+ return res.map((r) => ({
1752
+ id: Number(r.id),
1753
+ createdAt: r.created_at,
1754
+ jobId: Number(r.job_id),
1755
+ downAdjRndrUsed: Number(r.down_adj_rndr_used),
1756
+ downAdjToBurn: Number(r.down_adj_to_burn),
1757
+ adjusted: Number(r.tot_to_burn) - Number(r.tot_burned),
1758
+ job: {
1759
+ id: Number(r.job_id),
1760
+ completedAt: r.completed_at,
1761
+ rndrUsed: BigInt(r.render_amt),
1762
+ },
1763
+ }));
1798
1764
  }
1799
- log.info(`created tx_burn_adjustment ${row.id}: ${p.surplusRender} RENDER surplus (sol_tx ${p.solTxId})`);
1800
- return Number(row.id);
1801
- });
1802
- },
1803
- getJobBurnAdjustments(trx, ps, log = logger_1.consoleLogger) {
1804
- return __awaiter(this, void 0, void 0, function* () {
1805
- if (!ps.toFill)
1806
- return [];
1807
- const q = trx.trx
1808
- .selectFrom(exports.JOB_BURN_ADJUSTMENT_TABLE)
1809
- .selectAll(exports.JOB_BURN_ADJUSTMENT_TABLE)
1810
- .innerJoin(exports.JOB_TABLE, `${exports.JOB_TABLE}.id`, `${exports.JOB_BURN_ADJUSTMENT_TABLE}.job_id`)
1811
- .select([`${exports.JOB_TABLE}.completed_at`, `${exports.JOB_TABLE}.render_amt`])
1812
- .leftJoin(exports.BURN_TABLE, `${exports.BURN_TABLE}.job_burn_adjustment_id`, `${exports.JOB_BURN_ADJUSTMENT_TABLE}.id`)
1813
- .select(({ fn, lit }) => [
1814
- fn.sum(fn.coalesce(`${exports.BURN_TABLE}.to_burn`, lit(0))).as('tot_to_burn'),
1815
- fn.sum(fn.coalesce(`${exports.BURN_TABLE}.burned`, lit(0))).as('tot_burned'),
1816
- ])
1817
- .groupBy([
1818
- `${exports.JOB_BURN_ADJUSTMENT_TABLE}.id`,
1819
- `${exports.JOB_TABLE}.completed_at`,
1820
- `${exports.JOB_TABLE}.render_amt`,
1821
- ]);
1822
- log.info(`getJobBurnAdjustments ${q.compile().sql}`);
1823
- const res = yield q.execute();
1824
- return res
1825
- .map((r) => ({
1826
- id: Number(r.id),
1827
- createdAt: r.created_at,
1828
- jobId: Number(r.job_id),
1829
- downAdjRndrUsed: Number(r.down_adj_rndr_used),
1830
- downAdjToBurn: Number(r.down_adj_to_burn),
1831
- adjusted: Number(r.tot_to_burn) - Number(r.tot_burned),
1832
- job: {
1833
- id: Number(r.job_id),
1834
- completedAt: r.completed_at,
1835
- rndrUsed: BigInt(r.render_amt),
1836
- },
1837
- }))
1838
- .filter((a) => a.adjusted < a.downAdjToBurn);
1839
- });
1840
- },
1841
- getTxBurnAdjustments(trx, ps, log = logger_1.consoleLogger) {
1842
- return __awaiter(this, void 0, void 0, function* () {
1843
- if (!ps.toFill)
1844
- return [];
1845
- const q = trx.trx
1846
- .selectFrom(exports.TX_BURN_ADJUSTMENT_TABLE)
1847
- .selectAll(exports.TX_BURN_ADJUSTMENT_TABLE)
1848
- .leftJoin(exports.BURN_TABLE, `${exports.BURN_TABLE}.tx_burn_adjustment_id`, `${exports.TX_BURN_ADJUSTMENT_TABLE}.id`)
1849
- .select(({ fn, lit }) => [
1850
- fn
1851
- .sum(fn.coalesce(`${exports.BURN_TABLE}.from_escrow_credit`, lit(0)))
1852
- .as('tot_from_escrow'),
1853
- ])
1854
- .groupBy(`${exports.TX_BURN_ADJUSTMENT_TABLE}.id`);
1855
- log.info(`getTxBurnAdjustments ${q.compile().sql}`);
1856
- const res = yield q.execute();
1857
- return res
1858
- .map((r) => ({
1859
- id: Number(r.id),
1860
- createdAt: r.created_at,
1861
- solTxId: Number(r.sol_tx_id),
1862
- surplusRender: Number(r.surplus_render),
1863
- consumed: Number(r.tot_from_escrow),
1864
- }))
1865
- .filter((a) => a.consumed < a.surplusRender);
1765
+ return [];
1866
1766
  });
1867
1767
  },
1868
1768
  insertPolygonUpgrade(db, p, log = logger_1.consoleLogger) {