Repository Public
1// Odos has no adapter: the company permanently shut down its quoting/routing API on 2026-07-30 (docs/swap/providers/odos.md).2// This READ-ONLY probe re-checks that state, so the decision can be revisited the day it changes. It asks only for public3// metadata (GET), never for a quote with a wallet address, and builds nothing.4// Exit 0 = still offline (expected). Exit 1 = something answers again: re-read the official site before doing anything.5// Run: npx tsx scripts/smoke-swap-odos.mts6const probes: [label: string, url: string][] = [7 ['API: supported chains', 'https://api.odos.xyz/info/chains'],8 ['API: v2 router info (Ethereum)', 'https://api.odos.xyz/info/router/v2/1'],9 ['API: v3 quote endpoint', 'https://api.odos.xyz/sor/quote/v3'],10 ['Enterprise API: supported chains', 'https://enterprise-api.odos.xyz/info/chains'],11 ['Documentation', 'https://docs.odos.xyz/'],12];13let alive = 0;14console.log(`Odos liveness probe ${new Date().toISOString()}`);15for (const [label, url] of probes) {16 const t0 = Date.now();17 try {18 const r = await fetch(url, { headers: { accept: 'application/json' }, signal: AbortSignal.timeout(10_000) });19 const text = (await r.text()).replace(/\s+/g, ' ').slice(0, 80);20 if (r.ok) alive++;21 console.log(`${r.ok ? 'ALIVE ' : 'offline'} ${label.padEnd(34)} HTTP ${r.status} ${Date.now() - t0} ms ${JSON.stringify(text)}`);22 } catch (e) { console.log(`offline ${label.padEnd(34)} ${(e as Error).name}: ${(e as Error).message} ${Date.now() - t0} ms`); }23}24try {25 const html = await (await fetch('https://odos.xyz/', { signal: AbortSignal.timeout(10_000) })).text();26 console.log(`official site title: ${JSON.stringify(/<title>([^<]*)<\/title>/.exec(html)?.[1] ?? null)}`);27} catch (e) { console.log(`official site unreachable: ${(e as Error).message}`); }28console.log(alive ? `${alive} endpoint(s) answer again — Odos must be re-evaluated from its official documentation` : 'Odos API is offline, as announced: no adapter, no quotes');29process.exit(alive ? 1 : 0);30