import type { Abi, ContractFunctionArgs, ContractFunctionName } from 'viem' import { type ReadContractErrorType, type ReadContractParameters, type ReadContractReturnType, readContract, } from '../actions/readContract.js' import type { Config } from '../createConfig.js' import type { ScopeKeyParameter } from '../types/properties.js' import type { QueryOptions, QueryParameter } from '../types/query.js' import type { UnionExactPartial } from '../types/utils.js' import { filterQueryOptions, structuralSharing } from './utils.js' export type ReadContractOptions< abi extends Abi | readonly unknown[], functionName extends ContractFunctionName, args extends ContractFunctionArgs, config extends Config, selectData = ReadContractData, > = UnionExactPartial> & ScopeKeyParameter & QueryParameter< ReadContractQueryFnData, ReadContractErrorType, selectData, ReadContractQueryKey > export function readContractQueryOptions< config extends Config, const abi extends Abi | readonly unknown[], functionName extends ContractFunctionName, const args extends ContractFunctionArgs, selectData = ReadContractData, >( config: config, options: ReadContractOptions = {} as any, ): ReadContractQueryOptions { return { ...options.query, enabled: Boolean( Boolean(options.address || ('code' in options && options.code)) && options.abi && options.functionName && (options.query?.enabled ?? true), ), // TODO: Support `signal` once Viem actions allow passthrough // https://tkdodo.eu/blog/why-you-want-react-query#bonus-cancellation queryFn: async (context) => { if (!options.abi) throw new Error('abi is required') const [, { scopeKey: _, ...parameters }] = context.queryKey if (!parameters.functionName) throw new Error('functionName is required') const result = await readContract(config, { ...(parameters as any), abi: options.abi, address: parameters.address, code: 'code' in parameters && parameters.code ? parameters.code : undefined, functionName: parameters.functionName, }) return result as ReadContractData }, queryKey: readContractQueryKey(options as any) as any, structuralSharing, } as ReadContractQueryOptions } export type ReadContractQueryFnData< abi extends Abi | readonly unknown[], functionName extends ContractFunctionName, args extends ContractFunctionArgs, > = ReadContractReturnType export type ReadContractData< abi extends Abi | readonly unknown[], functionName extends ContractFunctionName, args extends ContractFunctionArgs, > = ReadContractQueryFnData export function readContractQueryKey< config extends Config, const abi extends Abi | readonly unknown[], functionName extends ContractFunctionName, args extends ContractFunctionArgs, >( options: UnionExactPartial< ReadContractParameters > & ScopeKeyParameter = {} as any, ) { return ['readContract', filterQueryOptions(options)] as const } export type ReadContractQueryKey< abi extends Abi | readonly unknown[], functionName extends ContractFunctionName, args extends ContractFunctionArgs, config extends Config, > = ReturnType> export type ReadContractQueryOptions< abi extends Abi | readonly unknown[], functionName extends ContractFunctionName, args extends ContractFunctionArgs, config extends Config, selectData = ReadContractData, > = QueryOptions< ReadContractQueryFnData, ReadContractErrorType, selectData, ReadContractQueryKey >