// Token market check: price, change, volume and liquidity from DexScreener. Zero dependencies. import { pathToFileURL } from "node:url"; const API = "https://api.dexscreener.com"; const num = (v) => (Number.isFinite(Number(v)) && v !== null && v !== undefined ? Number(v) : null); export async function tokenMarket(chain, address) { if (!chain || !address) throw new Error("Usage: token.mjs "); if (!/^[a-z0-9-]+$/i.test(chain) || !/^[A-Za-z0-9]+$/.test(address)) throw new Error("Invalid chain or address"); const res = await fetch(`${API}/tokens/v1/${chain}/${address}`, { headers: { accept: "application/json" } }); if (!res.ok) throw new Error(`DexScreener answered ${res.status}`); const pairs = (await res.json()) ?? []; const mine = (Array.isArray(pairs) ? pairs : []).filter( (p) => p?.baseToken?.address?.toLowerCase() === address.toLowerCase(), ); const list = mine.length ? mine : Array.isArray(pairs) ? pairs : []; if (!list.length) throw new Error(`No trading pairs found for ${address} on ${chain}`); const best = list.reduce((a, b) => ((num(b.liquidity?.usd) ?? 0) > (num(a.liquidity?.usd) ?? 0) ? b : a)); return { source: "dexscreener", fetchedAt: new Date().toISOString(), chainId: best.chainId, address: best.baseToken.address, symbol: best.baseToken.symbol, name: best.baseToken.name, priceUsd: num(best.priceUsd), change: { m5: num(best.priceChange?.m5), h1: num(best.priceChange?.h1), h6: num(best.priceChange?.h6), h24: num(best.priceChange?.h24), }, volume24hUsd: num(best.volume?.h24), txns24h: { buys: num(best.txns?.h24?.buys), sells: num(best.txns?.h24?.sells) }, liquidityUsd: num(best.liquidity?.usd), marketCapUsd: num(best.marketCap), fdvUsd: num(best.fdv), pairCount: list.length, bestPair: { dexId: best.dexId, pairAddress: best.pairAddress, quoteSymbol: best.quoteToken?.symbol ?? null, url: best.url, createdAt: best.pairCreatedAt ? new Date(best.pairCreatedAt).toISOString() : null, }, }; } if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) { tokenMarket(process.argv[2], process.argv[3]) .then((r) => console.log(JSON.stringify(r, null, 2))) .catch((e) => { console.log(JSON.stringify({ error: String(e?.message ?? e) })); process.exit(1); }); }