Repository Public
1import dns from 'node:dns';2import net from 'node:net';3import { config } from './config.ts';4import { migrate } from './db.ts';5import { buildServer } from './server.ts';6import { startAgentEngine } from './agents/live.ts';7import { startPerpAgentEngine } from './agents/perp-live.ts'; // v6 perp agents8import { assertFresh, getSeries, type Interval, type MarketSymbol } from './market/index.ts';9import { startMarketWorker } from './market/worker.ts';10import { startWorkers } from './worker.ts';11import { startDerivativesWorker } from './derivatives/worker.ts';12import { startLiveWorker } from './derivatives/live.ts';13import { startCollateralWorker } from './derivatives/collateral.ts';14import { startGmxWorker } from './derivatives/gmx-live.ts'; // v815import { startAlerts } from './alerts/dispatcher.ts'; // v6-alerts16import { capabilitiesLine } from './capabilities.ts'; // v817import { labStatus } from './agents/lab.ts'; // v81819// Node's default happy-eyeballs gives each address only 250 ms: on this network that makes public RPC connections fail at random.20dns.setDefaultResultOrder('ipv4first');21net.setDefaultAutoSelectFamilyAttemptTimeout(2500);2223await migrate();24const app = await buildServer();25await app.listen({ port: config.port, host: config.host });26if (config.workers) {27 startWorkers(); startMarketWorker();28 startDerivativesWorker(); // paper accounts only: public market data in, simulated fills out; no signer, no venue trading endpoint29 startLiveWorker(); // venue accounts: reconciliation only (reads); with no authorized account it does nothing30 startCollateralWorker(); // deposits and withdrawals in flight: venue ledger + the wallet's own chain records (reads; re-sends only already signed withdrawals)31 startGmxWorker(); // v8 GMX: tracks the wallet's own orders on-chain until executed, cancelled or frozen (reads; relays only already signed transactions)32 await startAlerts(); // v6-alerts: ONE dispatcher tailing the audit chain, risk events and research log; read-only on those tables33 // trading agents: decisions only on bars the market engine declares fresh, complete and consistent across sources34 startAgentEngine({35 series: async (s, i, limit) => (await getSeries(s as MarketSymbol, i as Interval, { limit })).bars,36 assertFresh: async (s, i) => { await assertFresh(s as MarketSymbol, i as Interval); },37 });38 startPerpAgentEngine(); // v6 perp agents (paper only): venue bars + funding in, simulated orders on their paper accounts out39}40console.log(`sp-wallet api listening on ${config.host}:${config.port} origin=${config.origin} broadcast=${config.broadcast ? 'on' : 'OFF'}`);41// v8: which optional capabilities are on, and which variable is missing for the others (names only, never a value)42console.log(`[startup] ${capabilitiesLine()}`);43void labStatus().then((l) => console.log(`[startup] strategy sandbox: ${l.mode}${l.ok ? ' (confined, self-test passed)' : ` — ${l.reason}${l.mode === 'unavailable' ? ' — signals and backtests will NOT run' : ''}`}`));44for (const sig of ['SIGINT', 'SIGTERM'] as const) process.on(sig, () => { void app.close().then(() => process.exit(0)); });45