unrip/test/trading-config.test.mjs
philipp c94d651fc9
Some checks failed
deploy / deploy (push) Failing after 38s
Normalize Gnosis bridge chain for USDC
Proof: Gnosis NEAR Intents assets now persist bridge chain eth:100, repo seed corrects legacy USDC chain rows, and tests prove USDC is not inventory-enabled until a pair activation enables it.

Assumptions: NEAR Intents bridge deposit_address uses eth:100 for Gnosis funding handles while dashboard blockchain labels remain gnosis.

Still fake: USDC deposit credit and live solver fills are not proven by this change; supported_tokens RPC remains upstream-unavailable.
2026-05-13 15:47:23 +02:00

703 lines
24 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { evaluateTradeOpportunity } from '../src/core/strategy.mjs';
import {
CURRENT_EURE_ASSET_ID,
CURRENT_NBTC_ASSET_ID,
CURRENT_USDC_ASSET_ID,
LEGACY_OMFT_BTC_ASSET_ID,
normalizeOneClickToken,
} from '../src/core/trading-config.mjs';
import {
createPairStrategyConfigVersion,
enableObserveOnlyPair,
importSupportedAssets,
loadAssetCatalogSummary,
loadTradingConfig,
pauseTradingPair,
seedTradingConfig,
setTradingPairMode,
} from '../src/lib/postgres.mjs';
test('1Click token normalizer preserves live asset fields', () => {
const token = normalizeOneClickToken({
assetId: CURRENT_NBTC_ASSET_ID,
decimals: 8,
blockchain: 'near',
symbol: 'BTC',
price: 80293,
priceUpdatedAt: '2026-05-12T16:25:00.425Z',
contractAddress: 'nbtc.bridge.near',
});
assert.equal(token.assetId, CURRENT_NBTC_ASSET_ID);
assert.equal(token.decimals, 8);
assert.equal(token.symbol, 'BTC');
assert.equal(token.latestPrice, '80293');
assert.equal(token.priceUpdatedAt, '2026-05-12T16:25:00.425Z');
});
test('1Click token normalizer maps Gnosis assets to bridge chain id', () => {
const token = normalizeOneClickToken({
assetId: CURRENT_USDC_ASSET_ID,
decimals: 6,
blockchain: 'gnosis',
symbol: 'USDC',
price: 1,
priceUpdatedAt: '2026-05-12T16:25:00.425Z',
contractAddress: '0x2a22f9c3b484c3629090feed35f17ff8f88f76f0',
});
assert.equal(token.blockchain, 'gnosis');
assert.equal(token.chain, 'eth:100');
});
test('supported token import is idempotent, does not enable inventory, and retires missing assets', async () => {
const pool = createMemoryPool();
const first = await importSupportedAssets(pool, {
fetchedAt: '2026-05-12T16:30:00.000Z',
response: [
token(CURRENT_NBTC_ASSET_ID, 'BTC', 8),
token(CURRENT_EURE_ASSET_ID, 'EURe', 18),
],
});
assert.equal(first.added_count, 2);
assert.equal(pool.assets.get(CURRENT_NBTC_ASSET_ID).enabled_for_inventory, false);
assert.equal(Object.hasOwn(first, 'raw_response'), false);
const second = await importSupportedAssets(pool, {
fetchedAt: '2026-05-12T16:31:00.000Z',
response: [
token(CURRENT_NBTC_ASSET_ID, 'BTC', 8),
token(CURRENT_EURE_ASSET_ID, 'EURe', 18),
],
});
assert.equal(second.added_count, 0);
assert.equal(second.unchanged_count, 2);
const third = await importSupportedAssets(pool, {
fetchedAt: '2026-05-12T16:32:00.000Z',
response: [
{ ...token(CURRENT_NBTC_ASSET_ID, 'BTC', 8), price: 81000 },
],
});
assert.equal(third.updated_count, 1);
assert.equal(third.retired_count, 1);
assert.equal(pool.assets.get(CURRENT_EURE_ASSET_ID).supported, false);
assert.equal(pool.assets.get(CURRENT_EURE_ASSET_ID).retired_at, '2026-05-12T16:32:00.000Z');
});
test('asset catalog summary omits raw token payloads from bootstrap rows', async () => {
const pool = createMemoryPool();
await importSupportedAssets(pool, {
fetchedAt: '2026-05-12T16:30:00.000Z',
response: [{
...token(CURRENT_NBTC_ASSET_ID, 'BTC', 8),
routes: Array.from({ length: 100 }, (_, index) => ({ route: index, detail: 'not for bootstrap' })),
}],
});
const summary = await loadAssetCatalogSummary(pool, { limit: 250 });
const [asset] = summary.items;
assert.equal(summary.counts.known, 1);
assert.equal(asset.asset_id, CURRENT_NBTC_ASSET_ID);
assert.equal(asset.raw_payload_available, true);
assert.equal(Object.hasOwn(asset, 'raw_payload'), false);
assert.equal(Object.hasOwn(asset, 'rawPayload'), false);
});
test('seeded DB config preserves current nBTC/EURe pair, 49 bps edge, and legacy BTC tracking', async () => {
const pool = createMemoryPool();
await seedTradingConfig(pool, { now: '2026-05-12T16:35:00.000Z' });
await seedTradingConfig(pool, { now: '2026-05-12T16:36:00.000Z' });
const snapshot = await loadTradingConfig(pool);
assert.equal(snapshot.ok, true);
assert.equal(snapshot.activePair, `${CURRENT_NBTC_ASSET_ID}->${CURRENT_EURE_ASSET_ID}`);
assert.equal(snapshot.pairs.length, 2);
assert.equal(snapshot.pairByKey.get(snapshot.activePair).strategyConfig.edgeBps, 49);
assert.equal(snapshot.trackedAssetIds.includes(LEGACY_OMFT_BTC_ASSET_ID), true);
assert.equal(snapshot.assetRegistry.get(CURRENT_USDC_ASSET_ID).chain, 'eth:100');
assert.equal(snapshot.trackedAssetIds.includes(CURRENT_USDC_ASSET_ID), false);
assert.equal([...snapshot.makerPairKeys].some((pair) => pair.includes(LEGACY_OMFT_BTC_ASSET_ID)), false);
});
test('repo seed corrects legacy USDC Gnosis chain without inventory-enabling it', async () => {
const pool = createMemoryPool();
pool.assets.set(CURRENT_USDC_ASSET_ID, {
asset_id: CURRENT_USDC_ASSET_ID,
venue: 'near-intents',
symbol: 'USDC',
label: 'USDC',
decimals: 6,
blockchain: 'gnosis',
chain: 'gnosis',
contract_address: '0x2a22f9c3b484c3629090feed35f17ff8f88f76f0',
latest_price: '1',
price_updated_at: '2026-05-12T16:25:00.425Z',
supported: true,
retired_at: null,
enabled_for_inventory: false,
role: null,
withdraw_address: '',
raw_payload: { source: 'legacy_test_row' },
last_supported_at: '2026-05-12T16:25:00.425Z',
updated_at: '2026-05-12T16:25:00.425Z',
});
await seedTradingConfig(pool, { now: '2026-05-12T16:35:00.000Z' });
const snapshot = await loadTradingConfig(pool);
const usdc = snapshot.assetRegistry.get(CURRENT_USDC_ASSET_ID);
assert.equal(usdc.chain, 'eth:100');
assert.equal(usdc.enabledForInventory, false);
});
test('missing DB pair config fails closed', async () => {
const snapshot = await loadTradingConfig(createMemoryPool());
assert.equal(snapshot.ok, false);
assert.equal(snapshot.blockReason, 'no_enabled_pairs');
assert.equal(snapshot.enabledPairKeys.size, 0);
});
test('edge update creates a new active strategy version', async () => {
const pool = createMemoryPool();
await seedTradingConfig(pool);
const next = await createPairStrategyConfigVersion(pool, {
pairId: `${CURRENT_NBTC_ASSET_ID}->${CURRENT_EURE_ASSET_ID}`,
edgeBps: 75,
maxNotional: '42',
changedBy: 'test',
reason: 'test edge update',
});
const snapshot = await loadTradingConfig(pool);
const versions = [...pool.strategyConfigs.values()]
.filter((row) => row.pair_id === `${CURRENT_NBTC_ASSET_ID}->${CURRENT_EURE_ASSET_ID}`);
assert.equal(next.version, 2);
assert.equal(snapshot.pairByKey.get(`${CURRENT_NBTC_ASSET_ID}->${CURRENT_EURE_ASSET_ID}`).strategyConfig.edgeBps, 75);
assert.equal(snapshot.pairByKey.get(`${CURRENT_NBTC_ASSET_ID}->${CURRENT_EURE_ASSET_ID}`).strategyConfig.maxNotional, '42');
assert.equal(versions.find((row) => row.version === 1).active, false);
});
test('strategy config update rejects invalid max notional', async () => {
const pool = createMemoryPool();
await seedTradingConfig(pool);
await assert.rejects(
createPairStrategyConfigVersion(pool, {
pairId: `${CURRENT_NBTC_ASSET_ID}->${CURRENT_EURE_ASSET_ID}`,
edgeBps: 75,
maxNotional: '0',
}),
/max_notional must be greater than zero/,
);
});
test('observe-only enable does not downgrade an active trading pair', async () => {
const pool = createMemoryPool();
await seedTradingConfig(pool);
const pairId = `${CURRENT_NBTC_ASSET_ID}->${CURRENT_EURE_ASSET_ID}`;
const pair = await enableObserveOnlyPair(pool, {
assetIn: CURRENT_NBTC_ASSET_ID,
assetOut: CURRENT_EURE_ASSET_ID,
changedBy: 'test',
reason: 'avoid downgrade',
});
const snapshot = await loadTradingConfig(pool);
assert.equal(pair.pairId, pairId);
assert.equal(pair.mode, 'both');
assert.equal(snapshot.pairByKey.get(pairId).makerEnabled, true);
assert.equal(snapshot.pairByKey.get(pairId).takerEnabled, true);
});
test('observe-only enable creates a non-trading tracked pair', async () => {
const pool = createMemoryPool();
await seedTradingConfig(pool);
const pair = await enableObserveOnlyPair(pool, {
assetIn: LEGACY_OMFT_BTC_ASSET_ID,
assetOut: CURRENT_EURE_ASSET_ID,
changedBy: 'test',
reason: 'watch legacy route',
});
const snapshot = await loadTradingConfig(pool);
assert.equal(pair.mode, 'observe_only');
assert.equal(snapshot.pairByKey.get(`${LEGACY_OMFT_BTC_ASSET_ID}->${CURRENT_EURE_ASSET_ID}`).observeEnabled, true);
assert.equal(snapshot.pairByKey.get(`${LEGACY_OMFT_BTC_ASSET_ID}->${CURRENT_EURE_ASSET_ID}`).makerEnabled, false);
assert.equal(snapshot.pairByKey.get(`${LEGACY_OMFT_BTC_ASSET_ID}->${CURRENT_EURE_ASSET_ID}`).takerEnabled, false);
});
test('repo seed does not re-enable pair runtime flags already stored in DB', async () => {
const pool = createMemoryPool();
await seedTradingConfig(pool);
const pairId = `${CURRENT_NBTC_ASSET_ID}->${CURRENT_EURE_ASSET_ID}`;
const routeId = `${pairId}:btc-eur-reference`;
Object.assign(pool.pairs.get(pairId), {
mode: 'observe_only',
enabled: false,
status: 'disabled',
});
Object.assign(pool.routes.get(routeId), {
enabled: false,
});
await seedTradingConfig(pool);
const snapshot = await loadTradingConfig(pool);
const pair = snapshot.pairByKey.get(pairId);
assert.equal(pair.enabled, false);
assert.equal(pair.mode, 'observe_only');
assert.equal(pair.status, 'disabled');
assert.equal(pool.routes.get(routeId).enabled, false);
assert.equal(pair.priceRoute, null);
assert.equal(pair.makerEnabled, false);
assert.equal(pair.takerEnabled, false);
});
test('pair mode updates activate a directed pair without inventing a price route', async () => {
const pool = createMemoryPool();
await seedTradingConfig(pool);
const pairId = `${LEGACY_OMFT_BTC_ASSET_ID}->${CURRENT_EURE_ASSET_ID}`;
await enableObserveOnlyPair(pool, {
assetIn: LEGACY_OMFT_BTC_ASSET_ID,
assetOut: CURRENT_EURE_ASSET_ID,
changedBy: 'test',
reason: 'watch legacy route',
});
const updated = await setTradingPairMode(pool, {
pairId,
mode: 'maker',
edgeBps: 75,
maxNotional: '25',
changedBy: 'test',
reason: 'operator activation test',
});
const snapshot = await loadTradingConfig(pool);
const pair = snapshot.pairByKey.get(pairId);
assert.equal(updated.mode, 'maker');
assert.equal(updated.strategyConfig.edgeBps, 75);
assert.equal(updated.strategyConfig.maxNotional, '25');
assert.equal(pair.enabled, true);
assert.equal(pair.makerEnabled, true);
assert.equal(pair.strategyConfig.edgeBps, 75);
assert.equal(pair.strategyConfig.maxNotional, '25');
assert.equal(pair.canTrade, false);
assert.equal(pair.blockReason, 'price_route_missing');
});
test('pair mode activation wires known BTC/USDC route and inventory tracking', async () => {
const pool = createMemoryPool();
await seedTradingConfig(pool);
const pairId = `${CURRENT_NBTC_ASSET_ID}->${CURRENT_USDC_ASSET_ID}`;
await setTradingPairMode(pool, {
pairId,
mode: 'maker',
edgeBps: 49,
maxNotional: '150',
changedBy: 'test',
reason: 'operator btc usdc activation test',
});
const snapshot = await loadTradingConfig(pool);
const pair = snapshot.pairByKey.get(pairId);
assert.equal(pair.canTrade, true);
assert.equal(pair.blockReason, null);
assert.equal(pair.priceRoute.source, 'btc_usdc_reference');
assert.equal(pair.priceRoute.baseAssetId, CURRENT_NBTC_ASSET_ID);
assert.equal(pair.priceRoute.quoteAssetId, CURRENT_USDC_ASSET_ID);
assert.equal(snapshot.assetRegistry.get(CURRENT_USDC_ASSET_ID).enabledForInventory, true);
assert.equal(snapshot.trackedAssetIds.includes(CURRENT_USDC_ASSET_ID), true);
});
test('pair mode activation rejects invalid initial edge config', async () => {
const pool = createMemoryPool();
await seedTradingConfig(pool);
await assert.rejects(
setTradingPairMode(pool, {
assetIn: LEGACY_OMFT_BTC_ASSET_ID,
assetOut: CURRENT_EURE_ASSET_ID,
mode: 'both',
edgeBps: 0,
}),
/edge_bps must be a positive integer/,
);
});
test('pair pause disables trading without deleting strategy config or seed restoring it', async () => {
const pool = createMemoryPool();
await seedTradingConfig(pool);
const pairId = `${CURRENT_NBTC_ASSET_ID}->${CURRENT_EURE_ASSET_ID}`;
const paused = await pauseTradingPair(pool, {
pairId,
changedBy: 'test',
reason: 'operator pause test',
});
await seedTradingConfig(pool);
const snapshot = await loadTradingConfig(pool);
const pair = snapshot.pairByKey.get(pairId);
assert.equal(paused.status, 'disabled');
assert.equal(pair.enabled, false);
assert.equal(pair.mode, 'both');
assert.equal(pair.status, 'disabled');
assert.equal(pair.strategyConfig.edgeBps, 49);
assert.equal(pair.makerEnabled, false);
assert.equal(pair.takerEnabled, false);
});
test('pair mode activation requires both assets to be registered', async () => {
const pool = createMemoryPool();
await seedTradingConfig(pool);
await assert.rejects(
setTradingPairMode(pool, {
assetIn: CURRENT_NBTC_ASSET_ID,
assetOut: 'nep141:not-imported.near',
mode: 'maker',
}),
/asset_out is not registered/,
);
});
test('strategy uses DB pair config for current pair and persists config version', async () => {
const pool = createMemoryPool();
const snapshot = await seedTradingConfig(pool);
const result = evaluateTradeOpportunity({
demandEvent: {
payload: {
quote_id: 'quote-db-1',
pair: `${CURRENT_NBTC_ASSET_ID}->${CURRENT_EURE_ASSET_ID}`,
asset_in: CURRENT_NBTC_ASSET_ID,
asset_out: CURRENT_EURE_ASSET_ID,
request_kind: 'exact_in',
amount_in: '5000',
min_deadline_ms: '60000',
},
},
priceEvent: priceEvent(),
inventoryEvent: inventoryEvent(),
config: snapshot,
armed: true,
now: Date.parse('2026-05-12T16:35:05.000Z'),
});
assert.equal(result.decision.decision, 'actionable');
assert.equal(result.decision.edge_bps, '49');
assert.equal(result.decision.pair_config_version, '1');
assert.equal(result.command.quote_output.amount_out, '4975500000000000000');
assert.equal(result.command.pair_config_id, `${CURRENT_NBTC_ASSET_ID}->${CURRENT_EURE_ASSET_ID}:v1`);
});
function token(assetId, symbol, decimals) {
return {
assetId,
decimals,
blockchain: symbol === 'EURe' ? 'gnosis' : 'near',
symbol,
price: symbol === 'EURe' ? 1.17 : 80293,
priceUpdatedAt: '2026-05-12T16:25:00.425Z',
contractAddress: assetId.replace(/^nep141:/, ''),
};
}
function priceEvent() {
return {
ingested_at: '2026-05-12T16:35:00.000Z',
payload: {
price_id: 'price-db-1',
pair: `${CURRENT_NBTC_ASSET_ID}->${CURRENT_EURE_ASSET_ID}`,
eur_per_btc: '100000.00000000',
eure_per_btc: '100000.00000000',
btc_per_eur: '0.000010000000',
btc_per_eure: '0.000010000000',
source_used: 'kraken',
},
};
}
function inventoryEvent() {
return {
ingested_at: '2026-05-12T16:35:00.000Z',
payload: {
inventory_id: 'inventory-db-1',
spendable: {
[CURRENT_NBTC_ASSET_ID]: '1000000',
[CURRENT_EURE_ASSET_ID]: '10000000000000000000',
[LEGACY_OMFT_BTC_ASSET_ID]: '0',
},
pending_inbound: {
[CURRENT_NBTC_ASSET_ID]: '0',
[CURRENT_EURE_ASSET_ID]: '0',
[LEGACY_OMFT_BTC_ASSET_ID]: '0',
},
},
};
}
function createMemoryPool() {
return {
assets: new Map(),
pairs: new Map(),
strategyConfigs: new Map(),
routes: new Map(),
importRuns: new Map(),
audit: [],
async query(sql, params = []) {
if (/CREATE TABLE|CREATE (UNIQUE )?INDEX/i.test(sql)) return { rows: [], rowCount: 0 };
if (/SELECT \* FROM trading_assets\s*$/i.test(sql)) return rows(this.assets);
if (/SELECT\s+asset_id,[\s\S]+raw_payload_available[\s\S]+FROM trading_assets/i.test(sql)) {
return selectAssetCatalogRows(this, params);
}
if (/SELECT \*\s+FROM trading_assets\s+ORDER BY/i.test(sql)) return rows(this.assets);
if (/INSERT INTO trading_assets/i.test(sql)) return insertAsset(this, params);
if (/UPDATE trading_assets[\s\S]+enabled_for_inventory = true/i.test(sql)) {
return enableInventoryAssets(this, params);
}
if (/UPDATE trading_assets/i.test(sql)) return retireAssets(this, params);
if (/INSERT INTO supported_asset_import_runs/i.test(sql)) return insertImportRun(this, params);
if (/SELECT \*\s+FROM supported_asset_import_runs/i.test(sql)) {
return { rows: [...this.importRuns.values()].slice(-1), rowCount: this.importRuns.size ? 1 : 0 };
}
if (/COUNT\(\*\)::INT AS known_count/i.test(sql)) {
const assets = [...this.assets.values()];
return {
rows: [{
known_count: assets.length,
supported_count: assets.filter((asset) => asset.supported).length,
retired_count: assets.filter((asset) => asset.retired_at || !asset.supported).length,
inventory_enabled_count: assets.filter((asset) => asset.enabled_for_inventory).length,
}],
rowCount: 1,
};
}
if (/INSERT INTO trading_pairs/i.test(sql)) return insertPair(this, params, sql);
if (/SELECT \*\s+FROM trading_pairs\s+WHERE pair_id = \$1/i.test(sql)) {
const row = this.pairs.get(params[0]);
return { rows: row ? [row] : [], rowCount: row ? 1 : 0 };
}
if (/SELECT \*\s+FROM trading_pairs/i.test(sql)) return rows(this.pairs);
if (/INSERT INTO pair_strategy_configs/i.test(sql)) return insertStrategyConfig(this, params);
if (/SELECT \*\s+FROM pair_strategy_configs\s+WHERE active = true/i.test(sql)) {
return { rows: [...this.strategyConfigs.values()].filter((row) => row.active), rowCount: 0 };
}
if (/SELECT \*\s+FROM pair_strategy_configs\s+WHERE pair_id = \$1 AND active = true/i.test(sql)) {
const active = [...this.strategyConfigs.values()]
.filter((row) => row.pair_id === params[0] && row.active)
.sort((left, right) => right.version - left.version)[0];
return { rows: active ? [active] : [], rowCount: active ? 1 : 0 };
}
if (/UPDATE pair_strategy_configs SET active = false/i.test(sql)) {
let count = 0;
for (const row of this.strategyConfigs.values()) {
if (row.pair_id === params[0] && row.active) {
row.active = false;
count += 1;
}
}
return { rows: [], rowCount: count };
}
if (/INSERT INTO pair_price_routes/i.test(sql)) return insertRoute(this, params, sql);
if (/SELECT \*\s+FROM pair_price_routes/i.test(sql)) {
return { rows: [...this.routes.values()].filter((row) => row.enabled), rowCount: 0 };
}
if (/INSERT INTO pair_config_audit_log/i.test(sql)) {
this.audit.push(params);
return { rows: [], rowCount: 1 };
}
throw new Error(`unhandled SQL in memory pool: ${sql}`);
},
};
}
function rows(map) {
return { rows: [...map.values()], rowCount: map.size };
}
function selectAssetCatalogRows(pool, params) {
const limit = Math.max(1, Number(params[0]) || 50);
const selected = [...pool.assets.values()]
.sort((left, right) => String(left.symbol).localeCompare(String(right.symbol))
|| String(left.asset_id).localeCompare(String(right.asset_id)))
.slice(0, limit)
.map((row) => ({
asset_id: row.asset_id,
venue: row.venue,
symbol: row.symbol,
label: row.label,
decimals: row.decimals,
blockchain: row.blockchain,
chain: row.chain,
contract_address: row.contract_address,
latest_price: row.latest_price,
price_updated_at: row.price_updated_at,
supported: row.supported,
retired_at: row.retired_at,
enabled_for_inventory: row.enabled_for_inventory,
role: row.role,
withdraw_address: row.withdraw_address,
raw_payload_available: Object.keys(row.raw_payload || {}).length > 0,
updated_at: row.updated_at,
}));
return { rows: selected, rowCount: selected.length };
}
function insertAsset(pool, params) {
const seed = params.length === 16;
const [
assetId,
venue,
symbol,
label,
decimals,
blockchain,
chain,
contractAddress,
latestPrice,
priceUpdatedAt,
] = params;
const previous = pool.assets.get(assetId);
const row = {
...(previous || {}),
asset_id: assetId,
venue,
symbol,
label,
decimals,
blockchain,
chain,
contract_address: contractAddress,
latest_price: latestPrice,
price_updated_at: priceUpdatedAt,
supported: seed ? (previous?.supported || params[10]) : true,
retired_at: null,
enabled_for_inventory: seed ? previous?.enabled_for_inventory === true || params[11] === true : previous?.enabled_for_inventory === true,
role: seed ? params[12] : previous?.role || null,
withdraw_address: seed ? params[13] : previous?.withdraw_address || '',
raw_payload: JSON.parse(seed ? params[14] : params[10]),
last_supported_at: seed ? params[15] : params[11],
updated_at: seed ? params[15] : params[11],
};
pool.assets.set(assetId, row);
return { rows: [], rowCount: previous ? 0 : 1 };
}
function retireAssets(pool, params) {
const [retiredAt, importedIds] = params;
let count = 0;
for (const row of pool.assets.values()) {
if (row.venue === 'near-intents' && row.supported && !importedIds.includes(row.asset_id)) {
row.supported = false;
row.retired_at ||= retiredAt;
row.updated_at = retiredAt;
count += 1;
}
}
return { rows: [], rowCount: count };
}
function enableInventoryAssets(pool, params) {
const [assetIds, updatedAt] = params;
let count = 0;
for (const assetId of assetIds) {
const row = pool.assets.get(assetId);
if (!row) continue;
row.enabled_for_inventory = true;
row.updated_at = updatedAt;
count += 1;
}
return { rows: [], rowCount: count };
}
function insertImportRun(pool, params) {
const row = {
run_id: params[0],
source_url: params[1],
fetched_at: params[2],
status: params[3],
token_count: params[4],
added_count: params[5],
updated_count: params[6],
unchanged_count: params[7],
retired_count: params[8],
raw_response_hash: params[9],
error: params[10],
raw_response: params[11] == null ? null : JSON.parse(params[11]),
};
pool.importRuns.set(row.run_id, row);
return { rows: [], rowCount: 1 };
}
function insertPair(pool, params, sql = '') {
const previous = pool.pairs.get(params[0]);
const row = {
pair_id: params[0],
venue: params[1],
asset_in: params[2],
asset_out: params[3],
mode: /mode = trading_pairs\.mode/i.test(sql) && previous ? previous.mode : params[4],
enabled: /enabled = trading_pairs\.enabled/i.test(sql) && previous ? previous.enabled : params[5],
status: /status = trading_pairs\.status/i.test(sql) && previous ? previous.status : params[6],
created_at: params[7],
updated_at: params[7],
};
pool.pairs.set(row.pair_id, row);
return { rows: [], rowCount: 1 };
}
function insertStrategyConfig(pool, params) {
const configId = params[0];
if (pool.strategyConfigs.has(configId)) return { rows: [], rowCount: 0 };
const row = {
config_id: configId,
pair_id: params[1],
version: params[2],
active: params[3],
edge_bps: params[4],
max_notional: params[5],
min_notional: params[6],
slippage_bps: params[7],
min_deadline_ms: params[8],
price_max_age_ms: params[9],
inventory_max_age_ms: params[10],
request_default_notional: params[11],
request_max_notional: params[12],
request_max_slippage_bps: params[13],
created_by: params[14],
reason: params[15],
created_at: '2026-05-12T16:35:00.000Z',
};
pool.strategyConfigs.set(configId, row);
return { rows: [], rowCount: 1 };
}
function insertRoute(pool, params, sql = '') {
const previous = pool.routes.get(params[0]);
const row = {
route_id: params[0],
pair_id: params[1],
source: params[2],
base_asset_id: params[3],
quote_asset_id: params[4],
route_config: JSON.parse(params[5]),
max_age_ms: params[6],
enabled: /enabled = pair_price_routes\.enabled/i.test(sql) && previous ? previous.enabled : params[7],
created_at: params[8],
updated_at: params[8],
};
pool.routes.set(row.route_id, row);
return { rows: [], rowCount: 1 };
}