import {z} from 'zod' export type GetApiMarketsTickersArgs = {addresses?: Array | undefined, symbols?: Array | undefined}; export type GetApiMarketsTickersOptions = {baseUrl?: string | undefined, fetch?: typeof fetch | undefined}; export const marketDataStatus = z.enum(["fresh", "stale"]); export const jitDataStatus = z.enum(["available", "stale", "unavailable"]); export const tradingCapacityLimitingFactor = z.enum(["reserve", "openInterest", "both", "notApplicable"]); export const tradingCapacityResponse = z.object({marketDataStatus: marketDataStatus, jitDataStatus: jitDataStatus, limitingFactor: tradingCapacityLimitingFactor, jitAvailableLiquidity: z.string(), baseAvailableLiquidity: z.string(), availableLiquidity: z.string()}); export const marketTickerResponse = z.object({capacityShort: tradingCapacityResponse, capacityLong: tradingCapacityResponse, netRateShort: z.string(), netRateLong: z.string(), borrowingRateShort: z.string(), borrowingRateLong: z.string(), fundingRateShort: z.string(), fundingRateLong: z.string(), poolAmountShortUsd: z.string(), poolAmountLongUsd: z.string(), availableLiquidityShort: z.string(), availableLiquidityLong: z.string(), shortInterestUsdMark: z.string(), longInterestUsdMark: z.string(), shortInterestUsd: z.string(), longInterestUsd: z.string(), shortInterestInTokens: z.string(), longInterestInTokens: z.string(), priceChangePercent24hBps: z.string(), priceChange24h: z.string(), close24h: z.string(), open24h: z.string(), low24h: z.string(), high24h: z.string(), markPrice: z.string(), maxPrice: z.string(), minPrice: z.string(), marketTokenAddress: z.string(), symbol: z.string()}); export const getApiMarketsTickersResponse = z.array(marketTickerResponse); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * GET /markets/tickers */ export const getApiMarketsTickers = async (args: GetApiMarketsTickersArgs, options?: GetApiMarketsTickersOptions) => { const {baseUrl = "https://arbitrum.gmxapi.io/v1", fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") for (const item of args.addresses ?? []) query.append("addresses", String(item)) for (const item of args.symbols ?? []) query.append("symbols", String(item)) const url = `${baseUrl.replace(/\/+$/, '')}/markets/tickers${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(getApiMarketsTickersResponse, await res.json()) };