unrip/test/near-intents-ws.test.mjs
philipp d5a7325e48
All checks were successful
deploy / deploy (push) Successful in 32s
Reconnect quote ingest after websocket errors
Proof: NEAR Intents quote ingest now schedules reconnect on websocket error even when the runtime does not emit close; regression test, dashboard build, and full npm test pass.

Assumptions: The observed live ingest outage after the 0.49 percent rollout was caused by the startup socket_error path leaving the websocket disconnected; reconnecting preserves the existing pair filter and topics without changing trading size or funds exposure.

Still fake: Venue-native terminal fill events, fee attribution, realized per-trade PnL, and full inventory-skew strategy controls remain incomplete.
2026-04-12 17:30:19 +02:00

98 lines
2.4 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { startNearIntentsWs } from '../src/venues/near-intents/ws.mjs';
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function installMockWebSocket() {
const original = globalThis.WebSocket;
const instances = [];
class MockWebSocket {
static CONNECTING = 0;
static OPEN = 1;
static CLOSING = 2;
static CLOSED = 3;
constructor(url, options) {
this.url = url;
this.options = options;
this.readyState = MockWebSocket.CONNECTING;
this.sent = [];
this.listeners = new Map();
instances.push(this);
}
addEventListener(type, listener) {
const existing = this.listeners.get(type) || [];
existing.push(listener);
this.listeners.set(type, existing);
}
send(payload) {
this.sent.push(payload);
}
close() {
if (this.readyState === MockWebSocket.CLOSED) return;
this.readyState = MockWebSocket.CLOSED;
this.emit('close', {});
}
open() {
this.readyState = MockWebSocket.OPEN;
this.emit('open', {});
}
error(error = new Error('socket failed')) {
this.emit('error', error);
}
emit(type, event) {
for (const listener of this.listeners.get(type) || []) listener(event);
}
}
globalThis.WebSocket = MockWebSocket;
return {
instances,
restore() {
globalThis.WebSocket = original;
},
};
}
test('near intents ingest reconnects after websocket error before open without runtime close', async () => {
const mock = installMockWebSocket();
const producer = { sendJson: async () => {} };
const client = await startNearIntentsWs({
apiKey: 'api-key',
wsUrl: 'wss://relay.example/ws',
pairFilter: ['btc', 'eure'],
producer,
rawTopic: 'raw.near_intents.quote',
normalizedTopic: 'norm.swap_demand',
reconnectDelayMs: 1,
});
try {
assert.equal(mock.instances.length, 1);
mock.instances[0].error(new Error('network failed'));
await delay(10);
assert.equal(client.getState().connected, false);
assert.ok(client.getState().reconnect_count >= 2);
assert.ok(mock.instances.length >= 2);
mock.instances[1].open();
assert.equal(client.getState().connected, true);
assert.equal(mock.instances[1].sent.length, 2);
} finally {
client.close();
mock.restore();
}
});