import test from 'node:test'; import assert from 'node:assert/strict'; import { readFileSync } from 'node:fs'; const source = readFileSync(new URL('../src/apps/trade-executor.mjs', import.meta.url), 'utf8'); test('trade executor dispatches each execute command once', () => { const calls = source.match(/await handleCommand\(event\);/g) || []; assert.equal(calls.length, 1); }); test('own request preflight suppresses maker quote responses to avoid self-matching', () => { assert.match(source, /withMakerSuppressed/); assert.match(source, /own_request_preflight_in_progress/); assert.match(source, /avoid self-matching/); }); test('trade executor fails closed on stale execute commands before relay submission', () => { assert.match(source, /classifyExecuteCommandExpiry/); assert.match(source, /stale_execute_command/); assert.match(source, /deadline elapsed before relay submission/); }); test('trade executor exposes summarized durable command state', () => { assert.match(source, /stateStore\.getSummary\(\{ limit: 50 \}\)/); assert.doesNotMatch(source, /durable_state:\s*stateStore\.getState\(\)/); }); test('trade executor records hot path timing in result payloads', () => { assert.match(source, /node:perf_hooks/); assert.match(source, /startExecutorTiming\(event\)/); assert.match(source, /executor_timing/); assert.match(source, /command_to_executor_ms/); assert.match(source, /current_salt_ms/); assert.match(source, /sign_ms/); assert.match(source, /relay_response_ms/); assert.match(source, /executor_total_ms/); assert.match(source, /withExecutorTiming\(\{[\s\S]*?result_code: 'submission_failed'/); }); test('trade executor uses bounded verifier salt cache instead of per-command salt RPC', () => { assert.match(source, /createVerifierSaltCache/); assert.match(source, /verifierSaltCache\.start\(\)/); assert.match(source, /verifierSaltCache\.getCachedFreshSalt\(\)/); assert.match(source, /verifier_salt_unavailable/); assert.match(source, /fresh verifier salt unavailable; command was not signed or relayed/); assert.match(source, /current_salt_source/); assert.match(source, /current_salt_age_ms/); assert.match(source, /current_salt_unavailable_reason/); assert.match(source, /verifier_salt_cache: verifierSaltCache\.getState\(\)/); assert.match(source, /verifierSaltCache\.stop\(\)/); assert.doesNotMatch(source, /verifierSaltCache\.getFreshSalt\(\)/); assert.doesNotMatch(source, /await verifierClient\.currentSalt\(\);/); const expiryIndex = source.indexOf('const expiry = classifyExecuteCommandExpiry(event);'); const saltLookupIndex = source.indexOf('verifierSaltCache.getCachedFreshSalt()'); const saltUnavailableIndex = source.indexOf("result_code: 'verifier_salt_unavailable'"); const signIndex = source.indexOf('buildQuoteResponseSubmission({'); const relayIndex = source.indexOf("relayClient.request('quote_response'"); assert.ok(expiryIndex > 0 && expiryIndex < saltLookupIndex); assert.ok(saltUnavailableIndex > 0 && saltUnavailableIndex < signIndex); assert.ok(saltUnavailableIndex < relayIndex); }); test('trade executor exposes queue delay and salt rejection state', () => { assert.match(source, /createExecutorQueueDelayTracker/); assert.match(source, /recordExecutorQueueDelay\(timing, payload\)/); assert.match(source, /executor_queue_delay: executorQueueDelayTracker\.getState\(\)/); assert.match(source, /salt_unavailable_reject_count/); assert.match(source, /last_salt_unavailable_at/); });