All checks were successful
deploy / deploy (push) Successful in 46s
Proof: targeted verifier salt cache and executor/dashboard tests pass; npm test passes 244/244; operator dashboard bundle builds; git diff --check passes. Assumptions: a 500 ms verifier salt freshness bound with 250 ms background prefetch is conservative for quote-response signing, and stale or malformed salt must block signing instead of using cached data. Still fake: venue-native terminal fill ids and fee-complete realized PnL remain unavailable.
82 lines
2.2 KiB
JavaScript
82 lines
2.2 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
|
|
import { createVerifierSaltCache } from '../src/core/verifier-salt-cache.mjs';
|
|
|
|
test('verifier salt cache reuses a fresh salt without calling the verifier hot path', async () => {
|
|
let nowMs = 1_000;
|
|
let calls = 0;
|
|
const cache = createVerifierSaltCache({
|
|
loadSalt: async () => {
|
|
calls += 1;
|
|
return '252812b3';
|
|
},
|
|
maxAgeMs: 500,
|
|
now: () => nowMs,
|
|
});
|
|
|
|
const refreshed = await cache.getFreshSalt();
|
|
nowMs += 100;
|
|
const cached = await cache.getFreshSalt();
|
|
|
|
assert.equal(calls, 1);
|
|
assert.equal(refreshed.source, 'refresh');
|
|
assert.equal(cached.source, 'cache');
|
|
assert.equal(cached.currentSaltHex, '252812b3');
|
|
assert.equal(cached.ageMs, 100);
|
|
});
|
|
|
|
test('verifier salt cache refreshes a stale salt before returning it', async () => {
|
|
let nowMs = 1_000;
|
|
const salts = ['252812b3', '252812b4'];
|
|
const cache = createVerifierSaltCache({
|
|
loadSalt: async () => salts.shift(),
|
|
maxAgeMs: 500,
|
|
now: () => nowMs,
|
|
});
|
|
|
|
const first = await cache.getFreshSalt();
|
|
nowMs += 501;
|
|
const second = await cache.getFreshSalt();
|
|
|
|
assert.equal(first.currentSaltHex, '252812b3');
|
|
assert.equal(second.currentSaltHex, '252812b4');
|
|
assert.equal(second.source, 'refresh');
|
|
assert.equal(second.ageMs, 0);
|
|
});
|
|
|
|
test('verifier salt cache fails closed when stale salt refresh fails', async () => {
|
|
let nowMs = 1_000;
|
|
let fail = false;
|
|
const cache = createVerifierSaltCache({
|
|
loadSalt: async () => {
|
|
if (fail) throw new Error('rpc unavailable');
|
|
return '252812b3';
|
|
},
|
|
maxAgeMs: 500,
|
|
now: () => nowMs,
|
|
});
|
|
|
|
await cache.getFreshSalt();
|
|
nowMs += 501;
|
|
fail = true;
|
|
|
|
await assert.rejects(
|
|
() => cache.getFreshSalt(),
|
|
/rpc unavailable/,
|
|
);
|
|
assert.equal(cache.getState().fresh, false);
|
|
assert.equal(cache.getState().last_refresh_error.message, 'rpc unavailable');
|
|
});
|
|
|
|
test('verifier salt cache rejects malformed salts before signing can use them', async () => {
|
|
const cache = createVerifierSaltCache({
|
|
loadSalt: async () => 'not-a-salt',
|
|
});
|
|
|
|
await assert.rejects(
|
|
() => cache.getFreshSalt(),
|
|
/current_salt must be 4 bytes in hex/,
|
|
);
|
|
assert.equal(cache.getState().has_cached_salt, false);
|
|
});
|