import {z} from 'zod' export type SatributesSchema = 'Common' | 'Uncommon' | 'Rare' | 'Epic' | 'Legendary' | 'Black Uncommon' | 'Black Rare' | 'Black Epic' | 'Black Legendary' | 'Mythic' | 'Palindrome' | 'Uniform Palinception' | 'Perfect Palinception' | 'Paliblock Palindrome' | 'Vintage' | 'Nakamoto' | 'Block 9' | 'Block 9 450x' | 'Block 286' | 'Block 78' | 'Block 666' | 'First Transaction' | 'Pizza' | 'Taproot' | 'Alpha' | 'Omega' | 'JPEG' | 'Legacy' | 'Hitman'; export type GetApiV2OrdBtcRaresatsListingsArgs = {sortBy?: (Array<'priceAsc' | 'priceDesc' | 'listedAtAsc' | 'listedAtDesc' | 'blockNumberAsc' | 'blockNumberDesc' | 'blockTimeAsc' | 'blockTimeDesc' | 'satRangeAsc' | 'satRangeDesc' | 'unitPriceAsc' | 'unitPriceDesc'>) | undefined, limit?: number | undefined, offset?: number | undefined, satributes?: Array | undefined, minListedAt?: number | undefined, maxListedAt?: number | undefined, minPrice?: number | undefined, maxPrice?: number | undefined, minUtxoSize?: number | undefined, maxUtxoSize?: number | undefined, minSatRange?: number | undefined, maxSatRange?: number | undefined, minBlockNumber?: number | undefined, maxBlockNumber?: number | undefined, minBlockTimestamp?: number | undefined, maxBlockTimestamp?: number | undefined}; export type GetApiV2OrdBtcRaresatsListingsOptions = {baseUrl?: string | undefined, fetch?: typeof fetch | undefined}; export const satributesSchema = z.enum(["Common", "Uncommon", "Rare", "Epic", "Legendary", "Black Uncommon", "Black Rare", "Black Epic", "Black Legendary", "Mythic", "Palindrome", "Uniform Palinception", "Perfect Palinception", "Paliblock Palindrome", "Vintage", "Nakamoto", "Block 9", "Block 9 450x", "Block 286", "Block 78", "Block 666", "First Transaction", "Pizza", "Taproot", "Alpha", "Omega", "JPEG", "Legacy", "Hitman"]); export const satributesArraySchema = z.array(satributesSchema); export const blockInfoSchema = z.object({blockHash: z.string().optional(), blockHeight: z.number().optional(), blockTime: z.string().optional()}); export const rareSatsSatRanges = z.object({id: z.string().optional(), from: z.number().optional(), to: z.number().optional(), parentFrom: z.number().optional(), parentTo: z.number().optional(), satributes: satributesArraySchema.optional(), amount: z.number().optional(), sequence: z.number().optional(), unitPrice: z.number().optional(), blockInfo: blockInfoSchema.optional()}); export const rareSatsGetListingsItem = z.object({id: z.string().optional(), genesisTransaction: z.string().optional(), genesisTransactionBlockTime: z.string().optional(), genesisTransactionBlockHash: z.string().optional(), genesisTransactionBlockHeight: z.number().optional(), outputValue: z.number().optional(), owner: z.string().optional(), listed: z.boolean().optional(), listedAt: z.string().optional(), listedPrice: z.number().optional(), listedSellerReceiverAddress: z.string().optional(), minBlockHeight: z.number().optional(), maxBlockHeight: z.number().optional(), minBlockTime: z.string().optional(), maxBlockTime: z.string().optional(), minSatRange: z.number().optional(), maxSatRange: z.number().optional(), minUnitPrice: z.number().optional(), maxUnitPrice: z.number().optional(), satRanges: z.array(rareSatsSatRanges).optional()}); export const rareSatsGetListingsSchema = z.object({tokens: z.array(rareSatsGetListingsItem).optional()}); export const getApiV2OrdBtcRaresatsListingsResponse = z.array(rareSatsGetListingsSchema); 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 Listings * * GET /v2/ord/btc/raresats/listings */ export const getApiV2OrdBtcRaresatsListings = async (args: GetApiV2OrdBtcRaresatsListingsArgs, options?: GetApiV2OrdBtcRaresatsListingsOptions) => { const {baseUrl = "https://api-mainnet.magiceden.dev/v2", fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") for (const item of args.sortBy ?? []) query.append("sortBy", String(item)) if (args.limit != null) query.append("limit", String(args.limit)) if (args.offset != null) query.append("offset", String(args.offset)) for (const item of args.satributes ?? []) query.append("satributes", String(item)) if (args.minListedAt != null) query.append("minListedAt", String(args.minListedAt)) if (args.maxListedAt != null) query.append("maxListedAt", String(args.maxListedAt)) if (args.minPrice != null) query.append("minPrice", String(args.minPrice)) if (args.maxPrice != null) query.append("maxPrice", String(args.maxPrice)) if (args.minUtxoSize != null) query.append("minUtxoSize", String(args.minUtxoSize)) if (args.maxUtxoSize != null) query.append("maxUtxoSize", String(args.maxUtxoSize)) if (args.minSatRange != null) query.append("minSatRange", String(args.minSatRange)) if (args.maxSatRange != null) query.append("maxSatRange", String(args.maxSatRange)) if (args.minBlockNumber != null) query.append("minBlockNumber", String(args.minBlockNumber)) if (args.maxBlockNumber != null) query.append("maxBlockNumber", String(args.maxBlockNumber)) if (args.minBlockTimestamp != null) query.append("minBlockTimestamp", String(args.minBlockTimestamp)) if (args.maxBlockTimestamp != null) query.append("maxBlockTimestamp", String(args.maxBlockTimestamp)) const url = `${baseUrl.replace(/\/+$/, '')}/v2/ord/btc/raresats/listings${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(getApiV2OrdBtcRaresatsListingsResponse, await res.json()) };