All checks were successful
deploy / deploy (push) Successful in 1m13s
Proof: Raw NEAR Intents quote retention now keeps only a 30 minute raw firehose window and drains up to 10M stale unlinked raw rows per pass. Targeted raw retention tests, full npm test, and operator dashboard bundle build pass. Assumptions: raw quote firehose rows are debug evidence, while normalized quote demand, decisions, commands, executor results, outcomes, inventory, pricing, and DB config remain the durable trading evidence. Still fake: venue-native terminal fill ids and fee-complete realized PnL remain unavailable; raw quote firehose rows truncated during emergency recovery are intentionally no longer readable.
170 lines
5.3 KiB
JavaScript
170 lines
5.3 KiB
JavaScript
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,
|
|
};
|
|
}
|