import {z} from 'zod' export type DataQuery = {type: 'tron', fromBlock: number, toBlock?: number | undefined, parentBlockHash?: string | undefined, includeAllBlocks?: boolean | undefined, fields?: ({block?: ({number?: boolean | undefined, hash?: boolean | undefined, parentHash?: boolean | undefined, txTrieRoot?: boolean | undefined, version?: boolean | undefined, timestamp?: boolean | undefined, witnessAddress?: boolean | undefined, witnessSignature?: boolean | undefined}) | undefined, transaction?: ({transactionIndex?: boolean | undefined, hash?: boolean | undefined, type?: boolean | undefined, ret?: boolean | undefined, signature?: boolean | undefined, parameter?: boolean | undefined, permissionId?: boolean | undefined, refBlockBytes?: boolean | undefined, refBlockHash?: boolean | undefined, feeLimit?: boolean | undefined, expiration?: boolean | undefined, timestamp?: boolean | undefined, rawDataHex?: boolean | undefined, fee?: boolean | undefined, contractResult?: boolean | undefined, contractAddress?: boolean | undefined, resMessage?: boolean | undefined, withdrawAmount?: boolean | undefined, unfreezeAmount?: boolean | undefined, withdrawExpireAmount?: boolean | undefined, cancelUnfreezeV2Amount?: boolean | undefined, result?: boolean | undefined, energyFee?: boolean | undefined, energyUsage?: boolean | undefined, energyUsageTotal?: boolean | undefined, netUsage?: boolean | undefined, netFee?: boolean | undefined, originEnergyUsage?: boolean | undefined, energyPenaltyTotal?: boolean | undefined}) | undefined, log?: ({transactionIndex?: boolean | undefined, logIndex?: boolean | undefined, address?: boolean | undefined, data?: boolean | undefined, topics?: boolean | undefined}) | undefined, internalTransaction?: ({transactionIndex?: boolean | undefined, internalTransactionIndex?: boolean | undefined, hash?: boolean | undefined, callerAddress?: boolean | undefined, transferToAddress?: boolean | undefined, callValueInfo?: boolean | undefined, note?: boolean | undefined, rejected?: boolean | undefined, extra?: boolean | undefined}) | undefined}) | undefined, transactions?: (Array<{type?: Array | undefined, logs?: boolean | undefined, internalTransactions?: boolean | undefined}>) | undefined, transferTransactions?: (Array<{owner?: Array | undefined, to?: Array | undefined, logs?: boolean | undefined, internalTransactions?: boolean | undefined}>) | undefined, transferAssetTransactions?: (Array<{owner?: Array | undefined, to?: Array | undefined, asset?: Array | undefined, logs?: boolean | undefined, internalTransactions?: boolean | undefined}>) | undefined, triggerSmartContractTransactions?: (Array<{owner?: Array | undefined, contract?: Array | undefined, sighash?: Array | undefined, logs?: boolean | undefined, internalTransactions?: boolean | undefined}>) | undefined, logs?: (Array<{address?: Array | undefined, topic0?: Array | undefined, topic1?: Array | undefined, topic2?: Array | undefined, topic3?: Array | undefined, transaction?: boolean | undefined}>) | undefined, internalTransactions?: (Array<{caller?: Array | undefined, transferTo?: Array | undefined, transaction?: boolean | undefined}>) | undefined}; export type CreateApiStreamArgs = {body: DataQuery}; export type CreateApiStreamOptions = {baseUrl?: string | undefined, fetch?: typeof fetch | undefined}; export const block = z.object({header: z.object({number: z.number().int().optional(), hash: z.string().optional(), parentHash: z.string().optional(), txTrieRoot: z.string().optional(), version: z.number().int().optional(), timestamp: z.number().int().optional(), witnessAddress: z.string().optional(), witnessSignature: z.string().optional()}).optional(), transactions: z.array(z.object({transactionIndex: z.number().int().optional(), hash: z.string().optional(), type: z.string().optional(), ret: z.array(z.object({contractRet: z.string().optional()})).optional(), signature: z.array(z.string()).optional(), parameter: z.object({type_url: z.string().optional(), value: z.object({}).optional()}).optional(), permissionId: z.number().int().nullable().optional(), refBlockBytes: z.string().optional(), refBlockHash: z.string().optional(), feeLimit: z.string().nullable().optional(), expiration: z.number().int().optional(), timestamp: z.number().int().nullable().optional(), rawDataHex: z.string().optional(), fee: z.string().nullable().optional(), contractResult: z.string().optional(), contractAddress: z.string().nullable().optional(), resMessage: z.string().nullable().optional(), withdrawAmount: z.string().nullable().optional(), unfreezeAmount: z.string().nullable().optional(), withdrawExpireAmount: z.string().nullable().optional(), cancelUnfreezeV2Amount: z.object({}).nullable().optional(), result: z.string().nullable().optional(), energyFee: z.string().nullable().optional(), energyUsage: z.string().nullable().optional(), energyUsageTotal: z.string().nullable().optional(), netUsage: z.string().nullable().optional(), netFee: z.string().nullable().optional(), originEnergyUsage: z.string().nullable().optional(), energyPenaltyTotal: z.string().nullable().optional()})).optional(), logs: z.array(z.object({transactionIndex: z.number().int().optional(), logIndex: z.number().int().optional(), address: z.string().optional(), data: z.string().nullable().optional(), topics: z.array(z.string()).optional()})).optional(), internalTransactions: z.array(z.object({transactionIndex: z.number().int().optional(), internalTransactionIndex: z.number().int().optional(), hash: z.string().optional(), callerAddress: z.string().optional(), transferToAddress: z.string().optional(), callValueInfo: z.array(z.object({callValue: z.number().int().nullable().optional(), tokenId: z.string().nullable().optional()})).optional(), note: z.string().optional(), rejected: z.boolean().nullable().optional(), extra: z.string().nullable().optional()})).optional()}); export const createApiStreamResponse = z.array(block); 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 }; /** * Stream Blocks * * POST /stream */ export const createApiStream = async (args: CreateApiStreamArgs, options?: CreateApiStreamOptions) => { const {baseUrl = "https://portal.sqd.dev/datasets/bitcoin-mainnet", fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") const url = `${baseUrl.replace(/\/+$/, '')}/stream${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(createApiStreamResponse, await res.json()) };