@render-foundation/utils 0.0.256 → 0.0.258
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/dispersed.js.map +1 -1
- package/lib/cjs/client/pg/base.js.map +1 -1
- package/lib/cjs/client/pg/v2Client.js +121 -89
- package/lib/cjs/client/pg/v2Client.js.map +1 -1
- package/lib/esm/src/client/dispersed.js.map +1 -1
- package/lib/esm/src/client/pg/base.js.map +1 -1
- package/lib/esm/src/client/pg/v2Client.js +107 -74
- package/lib/esm/src/client/pg/v2Client.js.map +1 -1
- package/lib/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/lib/types/src/client/dispersed.d.ts +0 -3
- package/lib/types/src/client/dispersed.d.ts.map +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 +1 -8
- package/lib/types/src/client/pg/v2Client.d.ts.map +1 -1
- package/lib/types/src/dbTypesV2.d.ts +0 -9
- package/lib/types/src/dbTypesV2.d.ts.map +1 -1
- package/lib/types/src/index.d.ts +1 -1
- package/lib/types/src/index.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1506,6 +1506,7 @@ export const pgClient = (config) => {
|
|
|
1506
1506
|
eurToUsdc: r.eur_to_usdc,
|
|
1507
1507
|
markedBurnedAt: r.marked_burned_at,
|
|
1508
1508
|
tags: r.tags ? r.tags.split(',') : [],
|
|
1509
|
+
fromEscrowUsdc: BigInt(r.from_escrow_usdc ?? 0),
|
|
1509
1510
|
});
|
|
1510
1511
|
burnIdToIdx[r.id] = burns.length - 1;
|
|
1511
1512
|
}
|
|
@@ -1528,70 +1529,133 @@ export const pgClient = (config) => {
|
|
|
1528
1529
|
return burns;
|
|
1529
1530
|
},
|
|
1530
1531
|
async fetchBurnsPage(db, f, log = consoleLogger) {
|
|
1531
|
-
const
|
|
1532
|
-
|
|
1533
|
-
.
|
|
1534
|
-
.
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
if (f.
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1532
|
+
const params = [];
|
|
1533
|
+
const p = (v) => {
|
|
1534
|
+
params.push(v);
|
|
1535
|
+
return `$${params.length}`;
|
|
1536
|
+
};
|
|
1537
|
+
// Decode cursor — supports new {t,id,ea} format and legacy bare-id format.
|
|
1538
|
+
let cursorEa;
|
|
1539
|
+
let cursorType;
|
|
1540
|
+
let cursorId;
|
|
1541
|
+
if (f.cursor) {
|
|
1542
|
+
const raw = atob(f.cursor);
|
|
1543
|
+
try {
|
|
1544
|
+
const c = JSON.parse(raw);
|
|
1545
|
+
cursorEa = c.ea;
|
|
1546
|
+
cursorType = c.t;
|
|
1547
|
+
cursorId = c.id;
|
|
1548
|
+
}
|
|
1549
|
+
catch {
|
|
1550
|
+
// Legacy cursor: bare burn.id — treat as buy-burn cursor.
|
|
1551
|
+
cursorId = Number(raw);
|
|
1552
|
+
cursorType = 'buy';
|
|
1553
|
+
}
|
|
1549
1554
|
}
|
|
1555
|
+
// Shared WHERE fragments pushed into each union leg for index use.
|
|
1556
|
+
const dateFilters = [];
|
|
1557
|
+
if (f.executedAfter)
|
|
1558
|
+
dateFilters.push(`st.executed_at >= ${p(f.executedAfter)}`);
|
|
1559
|
+
if (f.executedBefore)
|
|
1560
|
+
dateFilters.push(`st.executed_at <= ${p(f.executedBefore)}`);
|
|
1561
|
+
const sigFilter = f.sig ? `st.sig = ${p(f.sig)}` : '';
|
|
1562
|
+
// Buy-burn leg
|
|
1563
|
+
const buyWhere = [...dateFilters];
|
|
1564
|
+
if (!f.inclManual)
|
|
1565
|
+
buyWhere.push('b.usdc_spent > 0');
|
|
1566
|
+
if (sigFilter)
|
|
1567
|
+
buyWhere.push(sigFilter);
|
|
1550
1568
|
if (f.jobId !== undefined) {
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1569
|
+
buyWhere.push(`b.id IN (SELECT burn_id FROM job WHERE id = ${p(f.jobId)})`);
|
|
1570
|
+
}
|
|
1571
|
+
const buyWhereClause = buyWhere.length ? `WHERE ${buyWhere.join(' AND ')}` : '';
|
|
1572
|
+
const buySql = `
|
|
1573
|
+
SELECT 'buy'::text AS type, b.id::bigint AS sortid, b.id AS id,
|
|
1574
|
+
st.executed_at, st.executed_at::text AS executed_at_raw, b.priced_at, b.burned::text AS burned,
|
|
1575
|
+
b.usdc_spent::text AS usdc_spent, b.quote_amt::text AS quote_amt,
|
|
1576
|
+
b.tags, st.sig, b.render_to_usdc, b.eur_to_usdc,
|
|
1577
|
+
coalesce(b.from_escrow_usdc, 0)::text AS from_escrow_usdc,
|
|
1578
|
+
b.down_correction_id, b.escrow_correction_id,
|
|
1579
|
+
b.marked_burned_at
|
|
1580
|
+
FROM burn b
|
|
1581
|
+
INNER JOIN sol_tx st ON st.id = b.sol_tx_id
|
|
1582
|
+
${buyWhereClause}`;
|
|
1583
|
+
// Grant-burn leg
|
|
1584
|
+
const grantWhere = [...dateFilters];
|
|
1585
|
+
if (sigFilter)
|
|
1586
|
+
grantWhere.push(sigFilter);
|
|
1587
|
+
if (f.jobId !== undefined) {
|
|
1588
|
+
grantWhere.push(`gb.id IN (SELECT grant_burn_id FROM job WHERE id = ${p(f.jobId)})`);
|
|
1589
|
+
}
|
|
1590
|
+
const grantWhereClause = grantWhere.length ? `WHERE ${grantWhere.join(' AND ')}` : '';
|
|
1591
|
+
const grantSql = `
|
|
1592
|
+
SELECT 'grant'::text AS type, gb.id::bigint AS sortid, gb.id AS id,
|
|
1593
|
+
st.executed_at, st.executed_at::text AS executed_at_raw, null::timestamp AS priced_at, gb.burned::text AS burned,
|
|
1594
|
+
'0' AS usdc_spent, '0' AS quote_amt,
|
|
1595
|
+
gb.tags, st.sig, null::float8 AS render_to_usdc, null::float8 AS eur_to_usdc,
|
|
1596
|
+
'0' AS from_escrow_usdc,
|
|
1597
|
+
null::bigint AS down_correction_id, null::bigint AS escrow_correction_id,
|
|
1598
|
+
gb.marked_burned_at
|
|
1599
|
+
FROM grant_burn gb
|
|
1600
|
+
INNER JOIN sol_tx st ON st.id = gb.sol_tx_id
|
|
1601
|
+
${grantWhereClause}`;
|
|
1602
|
+
// Cursor filter on the outer query — row comparison for deterministic paging.
|
|
1603
|
+
let cursorFilter = '';
|
|
1604
|
+
if (cursorEa && cursorType && cursorId !== undefined) {
|
|
1605
|
+
cursorFilter = `WHERE (u.executed_at, u.type, u.sortid) > (${p(cursorEa)}, ${p(cursorType)}, ${p(cursorId)})`;
|
|
1606
|
+
}
|
|
1607
|
+
else if (cursorId !== undefined) {
|
|
1608
|
+
// Legacy cursor fallback: only buy burns, ordered by id.
|
|
1609
|
+
cursorFilter = `WHERE u.type = 'buy' AND u.sortid > ${p(cursorId)}`;
|
|
1561
1610
|
}
|
|
1562
1611
|
const limit = f.limit ?? 1000;
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1612
|
+
const sql = `
|
|
1613
|
+
SELECT u.* FROM (
|
|
1614
|
+
${buySql}
|
|
1615
|
+
UNION ALL
|
|
1616
|
+
${grantSql}
|
|
1617
|
+
) u
|
|
1618
|
+
${cursorFilter}
|
|
1619
|
+
ORDER BY u.executed_at ASC, u.type, u.sortid
|
|
1620
|
+
LIMIT ${p(limit)}`;
|
|
1621
|
+
const { rows } = await timedQuery(pgPool, sql, params, 'fetchBurnsPage', log);
|
|
1566
1622
|
const burns = rows.map((r) => ({
|
|
1567
1623
|
jobs: [],
|
|
1568
1624
|
id: Number(r.id),
|
|
1569
|
-
|
|
1625
|
+
type: r.type,
|
|
1626
|
+
renderToUsdc: r.render_to_usdc ?? undefined,
|
|
1570
1627
|
solTx: r.sig,
|
|
1571
1628
|
executedAt: r.executed_at,
|
|
1572
|
-
pricedAt: r.priced_at,
|
|
1629
|
+
pricedAt: r.priced_at ?? undefined,
|
|
1573
1630
|
usdcSpent: BigInt(r.usdc_spent ?? 0),
|
|
1574
1631
|
quoteAmt: BigInt(r.quote_amt ?? 0),
|
|
1575
1632
|
burned: BigInt(r.burned),
|
|
1576
|
-
eurToUsdc: r.eur_to_usdc,
|
|
1633
|
+
eurToUsdc: r.eur_to_usdc ?? undefined,
|
|
1577
1634
|
markedBurnedAt: r.marked_burned_at,
|
|
1578
1635
|
tags: r.tags ? r.tags.split(',') : [],
|
|
1636
|
+
fromEscrowUsdc: BigInt(r.from_escrow_usdc ?? 0),
|
|
1637
|
+
downCorrectionId: r.down_correction_id ? Number(r.down_correction_id) : undefined,
|
|
1638
|
+
escrowCorrectionId: r.escrow_correction_id ? Number(r.escrow_correction_id) : undefined,
|
|
1579
1639
|
}));
|
|
1580
1640
|
return {
|
|
1581
1641
|
burns,
|
|
1582
|
-
// Only hand back a cursor on a full page; a short page means we're done.
|
|
1583
1642
|
cursor: burns.length === limit
|
|
1584
|
-
? btoa(
|
|
1643
|
+
? btoa(JSON.stringify({
|
|
1644
|
+
ea: rows[burns.length - 1].executed_at_raw,
|
|
1645
|
+
t: rows[burns.length - 1].type,
|
|
1646
|
+
id: rows[burns.length - 1].sortid,
|
|
1647
|
+
}))
|
|
1585
1648
|
: undefined,
|
|
1586
1649
|
};
|
|
1587
1650
|
},
|
|
1588
|
-
async fetchBurnJobs(db, burnId, log = consoleLogger) {
|
|
1651
|
+
async fetchBurnJobs(db, burnId, burnType = 'buy', log = consoleLogger) {
|
|
1652
|
+
const fk = burnType === 'grant' ? 'grant_burn_id' : 'burn_id';
|
|
1589
1653
|
const rows = await db.trx
|
|
1590
1654
|
.selectFrom('job')
|
|
1591
1655
|
.selectAll('job')
|
|
1592
|
-
.where(
|
|
1656
|
+
.where(fk, '=', String(burnId))
|
|
1593
1657
|
.execute();
|
|
1594
|
-
log.debug(`fetchBurnJobs
|
|
1658
|
+
log.debug(`fetchBurnJobs ${burnType} ${burnId} -> ${rows.length} jobs`);
|
|
1595
1659
|
return rows.map((r) => ({
|
|
1596
1660
|
id: Number(r.id),
|
|
1597
1661
|
completedAt: r.completed_at,
|
|
@@ -1612,8 +1676,8 @@ export const pgClient = (config) => {
|
|
|
1612
1676
|
.innerJoin('sol_tx', 'sol_tx.id', 'burn.sol_tx_id')
|
|
1613
1677
|
.select(({ fn }) => [
|
|
1614
1678
|
dayExpr.as('day'),
|
|
1615
|
-
|
|
1616
|
-
|
|
1679
|
+
sql `SUM(burn.burned + CASE WHEN COALESCE(burn.from_escrow_usdc, 0) > 0 AND burn.render_to_usdc > 0 THEN (burn.from_escrow_usdc::numeric / burn.render_to_usdc * 100)::bigint ELSE 0 END)`.as('render_burned'),
|
|
1680
|
+
sql `SUM(burn.usdc_spent + COALESCE(burn.from_escrow_usdc, 0))`.as('usdc_spent'),
|
|
1617
1681
|
fn.count('burn.id').as('burn_count'),
|
|
1618
1682
|
])
|
|
1619
1683
|
.groupBy(sql `date_trunc('day', sol_tx.executed_at)`)
|
|
@@ -1893,21 +1957,6 @@ export const pgClient = (config) => {
|
|
|
1893
1957
|
});
|
|
1894
1958
|
},
|
|
1895
1959
|
async insertDispersedOutbox(p, log = consoleLogger) {
|
|
1896
|
-
// Check if dispersed_obligation table exists BEFORE the transaction so a missing table never
|
|
1897
|
-
// poisons the txn (PG aborts the entire transaction on any error, even a caught one).
|
|
1898
|
-
let hasObligationTable = false;
|
|
1899
|
-
if (p.obligations?.length) {
|
|
1900
|
-
try {
|
|
1901
|
-
const { rows } = await timedQuery(pgPool, `SELECT 1 FROM information_schema.tables WHERE table_name = 'dispersed_obligation' LIMIT 1`, [], 'checkObligationTable', log);
|
|
1902
|
-
hasObligationTable = rows.length > 0;
|
|
1903
|
-
}
|
|
1904
|
-
catch {
|
|
1905
|
-
hasObligationTable = false;
|
|
1906
|
-
}
|
|
1907
|
-
if (!hasObligationTable) {
|
|
1908
|
-
log.warn(`dispersed obligations: table not found (migration 44 pending); skipping for tx ${p.txSignature}`);
|
|
1909
|
-
}
|
|
1910
|
-
}
|
|
1911
1960
|
// The outbox row is the durable, crash-safe anchor persisted BEFORE broadcast. When it carries a
|
|
1912
1961
|
// burn-correction draw, we increment consumed_render in the SAME transaction as the insert, bounded
|
|
1913
1962
|
// so it can never exceed amount_render. Row + counter are therefore atomic and inseparable: no
|
|
@@ -1915,7 +1964,7 @@ export const pgClient = (config) => {
|
|
|
1915
1964
|
// (decremented again by voidDispersedOutbox). If the bounded increment can't fit (a concurrent draw
|
|
1916
1965
|
// took the room), the whole txn rolls back and we return {inserted:false} — the caller must NOT
|
|
1917
1966
|
// broadcast (no row, no counter change, no burn).
|
|
1918
|
-
|
|
1967
|
+
return await db.transaction().execute(async (trx) => {
|
|
1919
1968
|
const res = await trx
|
|
1920
1969
|
.insertInto(DISPERSED_SETTLEMENT_TABLE)
|
|
1921
1970
|
.values({
|
|
@@ -1956,29 +2005,13 @@ export const pgClient = (config) => {
|
|
|
1956
2005
|
throw new DispersedCorrectionRejected();
|
|
1957
2006
|
}
|
|
1958
2007
|
}
|
|
1959
|
-
|
|
1960
|
-
for (const o of p.obligations) {
|
|
1961
|
-
await trx
|
|
1962
|
-
.insertInto('dispersed_obligation')
|
|
1963
|
-
.values({
|
|
1964
|
-
settlement_tx_sig: p.txSignature,
|
|
1965
|
-
uuid: o.uuid,
|
|
1966
|
-
amount_eur: o.amountEur,
|
|
1967
|
-
opened_at: o.openedAt,
|
|
1968
|
-
authorization_uuid: o.authorizationUuid ?? null,
|
|
1969
|
-
})
|
|
1970
|
-
.onConflict((oc) => oc.column('uuid').doNothing())
|
|
1971
|
-
.execute();
|
|
1972
|
-
}
|
|
1973
|
-
}
|
|
1974
|
-
log.debug(`dispersed outbox tx ${p.txSignature}: ${res.numInsertedOrUpdatedRows} row(s), ${hasObligationTable ? (p.obligations?.length ?? 0) : 0} obligations`);
|
|
2008
|
+
log.debug(`dispersed outbox tx ${p.txSignature}: ${res.numInsertedOrUpdatedRows} row(s)`);
|
|
1975
2009
|
return { inserted };
|
|
1976
2010
|
}).catch((e) => {
|
|
1977
2011
|
if (e instanceof DispersedCorrectionRejected)
|
|
1978
2012
|
return { inserted: false };
|
|
1979
2013
|
throw e;
|
|
1980
2014
|
});
|
|
1981
|
-
return result;
|
|
1982
2015
|
},
|
|
1983
2016
|
async getOutstandingDispersedCorrection(log = consoleLogger) {
|
|
1984
2017
|
// consumed_render is the atomic source of truth; outstanding = amount_render - consumed_render.
|