1Branch0Tags
GL
glucryptoReserve only trade targets in price trigger profil...
4a63a6312 days ago20Commits
typescript
import { fetchHyperliquidDexMetaAndAssetCtxs, fetchHyperliquidPerpMarketInfo, fetchHyperliquidResolvedMarketDescriptor, fetchHyperliquidSizeDecimals, fetchHyperliquidSpotMarketInfo, normalizeHyperliquidMetaSymbol, type HyperliquidEnvironment, type HyperliquidResolvedMarketDescriptor, } from "opentool/adapters/hyperliquid"; import { normalizeSymbol } from "../config"; export function isSpotSymbol(value: string) { return value.includes("/") || value.includes(":"); } export async function readObservedPrice(params: { environment: HyperliquidEnvironment; symbol: string; mids: Record<string, string | number>; }) { const symbol = normalizeSymbol(params.symbol); const descriptor = await fetchHyperliquidResolvedMarketDescriptor({ environment: params.environment, symbol, mids: params.mids, }); const midRaw = params.mids[descriptor.marketDataCoin]; const midPrice = typeof midRaw === "number" ? midRaw : typeof midRaw === "string" ? Number.parseFloat(midRaw) : Number.NaN; if (Number.isFinite(midPrice) && midPrice > 0) { return midPrice; } if (descriptor.kind === "spot" || descriptor.kind === "spotIndex") { const marketInfo = await fetchHyperliquidSpotMarketInfo({ environment: params.environment, base: descriptor.base ?? symbol, quote: descriptor.quote ?? "USDC", mids: params.mids, }); return marketInfo.price; } if (descriptor.dex) { const data = (await fetchHyperliquidDexMetaAndAssetCtxs( params.environment, descriptor.dex, )) as [{ universe?: Array<{ name?: string }> }, Array<Record<string, unknown>>]; const universe = Array.isArray(data?.[0]?.universe) ? data[0].universe : []; const contexts = Array.isArray(data?.[1]) ? data[1] : []; const target = normalizeHyperliquidMetaSymbol(descriptor.orderSymbol).toUpperCase(); const idx = universe.findIndex( (entry) => normalizeHyperliquidMetaSymbol(entry?.name ?? "").toUpperCase() === target, ); const ctx = idx >= 0 ? contexts[idx] : null; const fallbackRaw = ctx?.markPx ?? ctx?.midPx ?? ctx?.oraclePx; const fallbackPrice = typeof fallbackRaw === "number" ? fallbackRaw : typeof fallbackRaw === "string" ? Number.parseFloat(fallbackRaw) : Number.NaN; if (Number.isFinite(fallbackPrice) && fallbackPrice > 0) { return fallbackPrice; } } else { const marketInfo = await fetchHyperliquidPerpMarketInfo({ environment: params.environment, symbol: descriptor.orderSymbol, }); return marketInfo.price; } throw new Error(`Unable to resolve a live price for ${params.symbol}.`); } export async function readOrderSizeDecimals(params: { environment: HyperliquidEnvironment; descriptor: HyperliquidResolvedMarketDescriptor; }) { if (!params.descriptor.dex) { return fetchHyperliquidSizeDecimals({ environment: params.environment, symbol: params.descriptor.orderSymbol, }); } const data = (await fetchHyperliquidDexMetaAndAssetCtxs( params.environment, params.descriptor.dex, )) as [{ universe?: Array<{ name?: string; szDecimals?: number | string }> }, Array<Record<string, unknown>>]; const universe = Array.isArray(data?.[0]?.universe) ? data[0].universe : []; const target = normalizeHyperliquidMetaSymbol(params.descriptor.orderSymbol).toUpperCase(); const entry = universe.find( (item) => normalizeHyperliquidMetaSymbol(item?.name ?? "").toUpperCase() === target, ) ?? null; const rawDecimals = entry?.szDecimals; const sizeDecimals = typeof rawDecimals === "number" ? rawDecimals : typeof rawDecimals === "string" ? Number.parseFloat(rawDecimals) : Number.NaN; if (!Number.isFinite(sizeDecimals)) { throw new Error(`No size decimals found for ${params.descriptor.orderSymbol}.`); } return sizeDecimals; }