import test from 'node:test'; import assert from 'node:assert/strict'; import { buildInventorySnapshot } from '../src/core/inventory.mjs'; import { routeHistoryRecord } from '../src/core/history-records.mjs'; import { insertHistoryEvents, pruneRawNearIntentsQuoteHistory } from '../src/lib/postgres.mjs'; test('inventory snapshot keeps pending funding out of spendable balances', () => { const snapshot = buildInventorySnapshot({ accountId: 'solver.near', balances: { 'nep141:btc.omft.near': '1000', 'nep141:eure.omft.near': '2000', }, recentDeposits: [ { asset_id: 'nep141:eure.omft.near', amount: '300', status: 'PENDING', }, ], trackedWithdrawals: [ { withdrawal_hash: 'wd-1', asset_id: 'nep141:btc.omft.near', amount: '25', status: 'PENDING', }, ], assetRegistry: new Map([ ['nep141:btc.omft.near', { decimals: 8 }], ['nep141:eure.omft.near', { decimals: 18 }], ]), observedAt: '2026-04-02T10:00:00.000Z', }); assert.equal(snapshot.spendable['nep141:eure.omft.near'], '2000'); assert.equal(snapshot.pending_inbound['nep141:eure.omft.near'], '300'); assert.equal(snapshot.pending_outbound['nep141:btc.omft.near'], '25'); }); test('history writer routes decision events into the decision table family', () => { const routed = routeHistoryRecord({ topic: 'decision.trade_decision', event: { event_id: 'evt-1', event_type: 'trade_decision', venue: 'near-intents', schema_version: 1, ingested_at: '2026-04-02T10:00:00.000Z', payload: { decision_id: 'decision-1', quote_id: 'quote-1', pair: 'a->b', direction: 'btc_to_eure', decision: 'rejected', decision_reason: 'strategy_disarmed', }, }, }); assert.equal(routed.table, 'trade_decisions'); assert.equal(routed.record.decision_key, 'decision-1'); assert.equal(routed.record.quote_id, 'quote-1'); }); test('bulk history insert writes multiple routed events in one table statement', async () => { const queries = []; const pool = { async query(sql, params) { queries.push({ sql, params }); return { rows: [ { event_id: params[0] }, { event_id: params[12] }, ], rowCount: 2, }; }, }; const result = await insertHistoryEvents(pool, [ { table: 'trade_decisions', topic: 'decision.trade_decision', event: historyEvent('evt-1', { decision_id: 'decision-1', quote_id: 'quote-1' }), record: { quote_id: 'quote-1', pair: 'a->b', decision_key: 'decision-1' }, }, { table: 'trade_decisions', topic: 'decision.trade_decision', event: historyEvent('evt-2', { decision_id: 'decision-2', quote_id: 'quote-2' }), record: { quote_id: 'quote-2', pair: 'a->b', decision_key: 'decision-2' }, }, ]); assert.equal(queries.length, 1); assert.match(queries[0].sql, /INSERT INTO trade_decisions/); assert.match(queries[0].sql, /RETURNING event_id/); assert.equal(queries[0].params.length, 24); assert.deepEqual([...result.insertedEventIds].sort(), ['evt-1', 'evt-2']); }); test('raw quote retention preserves rows linked to maker lifecycle evidence', async () => { const queries = []; const pool = { async query(sql, params) { queries.push({ sql, params }); return { rows: [], rowCount: 42 }; }, }; const result = await pruneRawNearIntentsQuoteHistory(pool, { now: '2026-05-21T12:00:00.000Z', retainRecentMs: 6 * 60 * 60 * 1000, batchSize: 123, }); assert.equal(result.deletedCount, 42); assert.equal(result.cutoff, '2026-05-21T06:00:00.000Z'); assert.equal(result.batchSize, 123); assert.equal(queries.length, 1); assert.match(queries[0].sql, /DELETE FROM raw_near_intents_quotes/); assert.match(queries[0].sql, /trade_decisions/); assert.match(queries[0].sql, /execute_trade_commands/); assert.match(queries[0].sql, /trade_execution_results/); assert.match(queries[0].sql, /quote_outcome_attributions/); assert.deepEqual(queries[0].params, ['2026-05-21T06:00:00.000Z', 123]); }); test('raw quote retention drains multiple bounded batches when firehose backlog exceeds one batch', async () => { const rowCounts = [500_000, 500_000, 12]; const queries = []; const pool = { async query(sql, params) { queries.push({ sql, params }); return { rows: [], rowCount: rowCounts.shift() ?? 0 }; }, }; const result = await pruneRawNearIntentsQuoteHistory(pool, { now: '2026-05-21T12:00:00.000Z', retainRecentMs: 30 * 60 * 1000, batchSize: 500_000, maxBatches: 20, }); assert.equal(result.deletedCount, 1_000_012); assert.equal(result.cutoff, '2026-05-21T11:30:00.000Z'); assert.equal(result.batchSize, 500_000); assert.equal(result.maxBatches, 20); assert.equal(result.batches, 3); assert.equal(queries.length, 3); for (const query of queries) { assert.match(query.sql, /DELETE FROM raw_near_intents_quotes/); assert.deepEqual(query.params, ['2026-05-21T11:30:00.000Z', 500_000]); } }); function historyEvent(eventId, payload) { return { event_id: eventId, event_type: 'trade_decision', venue: 'near-intents', source: 'strategy-engine', observed_at: '2026-04-02T10:00:00.000Z', ingested_at: '2026-04-02T10:00:00.001Z', payload, }; }