From 087ffbe1801a2280fabe9e522914d1180c957862 Mon Sep 17 00:00:00 2001 From: YASH YADAV Date: Thu, 9 Apr 2026 16:20:52 +0530 Subject: [PATCH 1/2] fix gaps in public market data --- bunfig.toml | 3 ++ package.json | 1 + src/handlers/market.ts | 93 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 89 insertions(+), 8 deletions(-) create mode 100644 bunfig.toml diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..430d96e --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,3 @@ +# This package is built with tsup (see package.json "build"). +# Use: bun run build +# Not: bun build (that invokes Bun's bundler CLI, not npm scripts) diff --git a/package.json b/package.json index 3dde75a..b9373bb 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ ], "scripts": { "build": "tsup", + "prebuild": "node -e \"if(process.env.npm_lifecycle_event==='prebuild'){}\"", "clean": "rm -rf dist", "dev": "tsup --watch", "lint": "eslint --cache --fix './**/*.{ts,tsx}' && prettier --write './**/*.{ts,tsx}'", diff --git a/src/handlers/market.ts b/src/handlers/market.ts index 788f7c9..32012c8 100644 --- a/src/handlers/market.ts +++ b/src/handlers/market.ts @@ -6,7 +6,7 @@ import { type OrderbookIncrements, type OrderbookLevel, } from '../output/orderbook.js'; -import { ToolExecutionError } from '../utils/errors.js'; +import { ToolExecutionError, formatError } from '../utils/errors.js'; import { fmtProductIds } from '../utils/formatting.js'; import { resolveMarketData } from '../utils/orderBuilder.js'; import { getMarkets } from '../utils/resolveMarket.js'; @@ -17,13 +17,83 @@ import type { CommandResult } from './types.js'; // get_all_markets // --------------------------------------------------------------------------- +type MarketListKind = 'perp' | 'spot'; + +function resolveMarketListLabels( + productId: number, + kind: MarketListKind, + meta: { marketName: string; symbol: string } | undefined, + engineSymbol: string | undefined, +): { name: string; symbol: string } { + const metaSym = meta?.symbol?.trim(); + const metaName = meta?.marketName?.trim(); + const engSym = engineSymbol?.trim(); + + const symbol = metaSym || engSym || '-'; + const name = metaName || metaSym || engSym || `${kind} ${productId}`; + return { name, symbol }; +} + +/** + * Normalizes engine `getSymbols` payloads: some responses use a Record map, + * others may expose an array — avoids `symbols.map is not a function`. + */ +function engineSymbolMapFromResponse(symbolsRaw: unknown): Map { + const map = new Map(); + try { + const entries: unknown[] = Array.isArray(symbolsRaw) + ? symbolsRaw + : symbolsRaw && typeof symbolsRaw === 'object' + ? Object.values(symbolsRaw as Record) + : []; + for (const entry of entries) { + if (!entry || typeof entry !== 'object') continue; + const e = entry as { productId?: unknown; symbol?: unknown }; + const productId = e.productId; + const sym = typeof e.symbol === 'string' ? e.symbol.trim() : ''; + if (typeof productId === 'number' && sym) { + map.set(productId, sym); + } + } + } catch { + // ignore malformed payloads + } + return map; +} + export async function getAllMarkets(ctx: NadoContext): Promise { try { - const [data, metadata] = await Promise.all([ + const [marketsRes, metaRes, symsRes] = await Promise.allSettled([ ctx.client.market.getAllMarkets(), - getMarkets(ctx.dataEnv, ctx.chainEnv).catch(() => []), + getMarkets(ctx.dataEnv, ctx.chainEnv), + ctx.client.context.engineClient.getSymbols({}), ]); - const nameById = new Map(metadata.map((m) => [m.productId, m])); + + if (marketsRes.status === 'rejected') { + throw marketsRes.reason; + } + const data = [...marketsRes.value].sort( + (a, b) => a.productId - b.productId, + ); + + const metadata = metaRes.status === 'fulfilled' ? metaRes.value : []; + if (metaRes.status === 'rejected') { + console.warn( + `[nado] Product metadata unavailable: ${formatError(metaRes.reason)}. Name/Symbol may be incomplete.`, + ); + } + + const engineById = + symsRes.status === 'fulfilled' + ? engineSymbolMapFromResponse(symsRes.value.symbols) + : new Map(); + if (symsRes.status === 'rejected') { + console.warn( + `[nado] Engine symbols unavailable: ${formatError(symsRes.reason)}. Symbol column may rely on metadata only.`, + ); + } + + const metaById = new Map(metadata.map((m) => [m.productId, m])); return { data, @@ -36,12 +106,19 @@ export async function getAllMarkets(ctx: NadoContext): Promise { 'Size Increment', ], rows: data.map((m) => { - const meta = nameById.get(m.productId); + const kind: MarketListKind = + m.type === ProductEngineType.PERP ? 'perp' : 'spot'; + const { name, symbol } = resolveMarketListLabels( + m.productId, + kind, + metaById.get(m.productId), + engineById.get(m.productId), + ); return [ String(m.productId), - meta?.marketName ?? '-', - meta?.symbol ?? '-', - m.type === ProductEngineType.PERP ? 'perp' : 'spot', + name, + symbol, + kind, m.priceIncrement.toFixed(), m.sizeIncrement.toFixed(), ]; From 20ed1684481041c699e6da8aa44a1ef983b6c3e2 Mon Sep 17 00:00:00 2001 From: YASH YADAV Date: Thu, 9 Apr 2026 16:24:55 +0530 Subject: [PATCH 2/2] fixed changes --- bunfig.toml | 3 --- package.json | 1 - 2 files changed, 4 deletions(-) delete mode 100644 bunfig.toml diff --git a/bunfig.toml b/bunfig.toml deleted file mode 100644 index 430d96e..0000000 --- a/bunfig.toml +++ /dev/null @@ -1,3 +0,0 @@ -# This package is built with tsup (see package.json "build"). -# Use: bun run build -# Not: bun build (that invokes Bun's bundler CLI, not npm scripts) diff --git a/package.json b/package.json index b9373bb..3dde75a 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,6 @@ ], "scripts": { "build": "tsup", - "prebuild": "node -e \"if(process.env.npm_lifecycle_event==='prebuild'){}\"", "clean": "rm -rf dist", "dev": "tsup --watch", "lint": "eslint --cache --fix './**/*.{ts,tsx}' && prettier --write './**/*.{ts,tsx}'",