import {z} from 'zod' export type GetApiV1TokensTokenNameArgs = {tokenName: string}; export type GetApiV1TokensTokenNameOptions = {baseUrl?: string | undefined, fetch?: typeof fetch | undefined}; export const tokenPageInfoResponseDto = z.object({endCursor: z.string().nullable(), hasNextPage: z.boolean(), hasPreviousPage: z.boolean(), startCursor: z.string().nullable()}); export const tokenBadgeResponseDto = z.object({badgeName: z.string(), isActive: z.boolean()}); export const tokenBadgesResponseDto = z.object({engagement: z.array(tokenBadgeResponseDto), volume: z.array(tokenBadgeResponseDto)}); export const tokenPoolResponseDto = z.object({additionalKey: z.string().nullable().optional(), assets: z.object({}).nullable().optional(), badges: tokenBadgesResponseDto, bondingCurvePercentage: z.number().optional(), category: z.string().nullable().optional(), circulatingSupply: z.string(), collection: z.string().nullable().optional(), createdAt: z.string().optional(), creatorAddress: z.string().optional(), currentViewerCount: z.number().optional(), deltaSupply: z.string(), description: z.string().optional(), engagementBadge: z.string().nullable().optional(), facebookUrl: z.string().optional(), galaInPool: z.string(), galaPrice: z.string(), id: z.number().optional(), image: z.string().optional(), instagramUrl: z.string().optional(), isFinalized: z.number().optional(), isGraduated: z.boolean(), lastStreamedAt: z.string().nullable().optional(), marketCapGala: z.string(), marketCapUsd: z.string(), muxPlaybackId: z.string().nullable().optional(), muxStreamAspectRatio: z.string().nullable().optional(), muxStreamId: z.string().nullable().optional(), muxStreamStatus: z.string().nullable().optional(), nextLiveStreamAt: z.string().nullable().optional(), peakViewerCount: z.number().optional(), recordingsCount: z.number().optional(), redditUrl: z.string().optional(), reverseBondingCurveMaxFeePortion: z.string().nullable().optional(), reverseBondingCurveMinFeePortion: z.string().nullable().optional(), saleStartTime: z.number().optional(), streamLanguage: z.string().nullable().optional(), streamStartedAt: z.string().nullable().optional(), symbol: z.string().optional(), telegramUrl: z.string().optional(), tiktokUrl: z.string().optional(), tokenName: z.string().optional(), totalSecondsStreamed: z.number().optional(), twitterUrl: z.string().optional(), type: z.string().nullable().optional(), updatedAt: z.string().optional(), usdPrice: z.string(), vaultAddress: z.string().optional(), volume: z.string(), volume1h: z.string(), volumeBadge: z.string().nullable().optional(), websiteUrl: z.string().optional()}); export const tokenDetailsResponseDto = z.object({pageInfo: tokenPageInfoResponseDto, tokens: z.union([tokenPoolResponseDto, z.array(tokenPoolResponseDto)])}); export const getApiV1TokensTokenNameResponse = z.object({error: z.literal(false), message: z.string(), status: z.number(), data: tokenDetailsResponseDto}); 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 token details * * GET /v1/tokens/{tokenName} */ export const getApiV1TokensTokenName = async (args: GetApiV1TokensTokenNameArgs, options?: GetApiV1TokensTokenNameOptions) => { const {baseUrl = "https://lpad-backend.stage.defi.ovh.gala.com", fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") const url = `${baseUrl.replace(/\/+$/, '')}/v1/tokens/${encodeURIComponent(String(args.tokenName))}${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(getApiV1TokensTokenNameResponse, await res.json()) };