CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-wagmi--core

VanillaJS library for Ethereum blockchain interactions with reactive primitives and utilities for building Ethereum applications

Pending
Overview
Eval results
Files

tanstack-query.mddocs/

TanStack Query Integration

First-class TanStack Query support with query options, mutation options, and caching strategies.

Overview

@wagmi/core provides comprehensive TanStack Query integration through the /query export. This integration offers optimized caching, background refetching, and reactive data management for all blockchain operations.

Core Query Functions

Query Options for Read Operations

Generate TanStack Query options for read operations that automatically handle caching and refetching.

/**
 * Query options for balance queries
 * @param config - Wagmi configuration
 * @param options - Balance query options
 * @returns TanStack Query options
 */
function getBalanceQueryOptions<config extends Config>(
  config: config,
  options: GetBalanceOptions<config>
): QueryOptions<GetBalanceData, GetBalanceErrorType>;

interface GetBalanceOptions<config extends Config> {
  /** Account address */
  address: Address;
  /** Token contract address (optional) */
  token?: Address;
  /** Chain ID */
  chainId?: config['chains'][number]['id'];
  /** Query configuration */
  query?: {
    enabled?: boolean;
    staleTime?: number;
    gcTime?: number;
  };
}

type GetBalanceData = {
  decimals: number;
  formatted: string;
  symbol: string;
  value: bigint;
};

/**
 * Query key for balance queries
 * @param parameters - Balance parameters
 * @returns Query key array
 */
function getBalanceQueryKey(parameters?: GetBalanceParameters): GetBalanceQueryKey;

type GetBalanceQueryKey = readonly ['balance', GetBalanceParameters];

type GetBalanceQueryFnData = GetBalanceReturnType;

Usage Example:

import { useQuery } from '@tanstack/react-query'
import { getBalanceQueryOptions } from '@wagmi/core/query'

// In React component
function BalanceDisplay({ address }: { address: Address }) {
  const { data: balance, isLoading, error } = useQuery(
    getBalanceQueryOptions(config, {
      address,
      query: {
        staleTime: 1000 * 60, // 1 minute
        enabled: !!address,
      },
    })
  )

  if (isLoading) return <div>Loading balance...</div>
  if (error) return <div>Error loading balance</div>
  if (!balance) return null

  return (
    <div>
      Balance: {balance.formatted} {balance.symbol}
    </div>
  )
}

// In vanilla JavaScript
import { QueryClient } from '@tanstack/query-core'

const queryClient = new QueryClient()

const balance = await queryClient.fetchQuery(
  getBalanceQueryOptions(config, {
    address: '0x742d35Cc6601C2F3Ac5e5c7A9d16e4e6Be4e6e9e',
  })
)
console.log('Balance:', balance.formatted)

Contract Read Query Options

Query options for contract read operations.

/**
 * Query options for contract reads
 * @param config - Wagmi configuration
 * @param options - Contract read options
 * @returns TanStack Query options
 */
function readContractQueryOptions<config extends Config>(
  config: config,
  options: ReadContractOptions<config>
): QueryOptions<ReadContractData, ReadContractErrorType>;

interface ReadContractOptions<config extends Config> {
  /** Contract address */
  address: Address;
  /** Contract ABI */
  abi: Abi;
  /** Function name */
  functionName: string;
  /** Function arguments */
  args?: readonly unknown[];
  /** Chain ID */
  chainId?: config['chains'][number]['id'];
  /** Query configuration */
  query?: {
    enabled?: boolean;
    staleTime?: number;
    gcTime?: number;
  };
}

type ReadContractData = any; // Depends on contract function

/**
 * Query key for contract reads
 * @param parameters - Contract read parameters
 * @returns Query key array
 */
function readContractQueryKey(parameters?: ReadContractParameters): ReadContractQueryKey;

type ReadContractQueryKey = readonly ['readContract', ReadContractParameters];

/**
 * Query options for multiple contract reads
 * @param config - Wagmi configuration
 * @param options - Multiple contract read options
 * @returns TanStack Query options
 */
function readContractsQueryOptions<config extends Config>(
  config: config,
  options: ReadContractsOptions<config>
): QueryOptions<ReadContractsData, ReadContractsErrorType>;

interface ReadContractsOptions<config extends Config> {
  /** Array of contract calls */
  contracts: readonly {
    address: Address;
    abi: Abi;
    functionName: string;
    args?: readonly unknown[];
  }[];
  /** Chain ID */
  chainId?: config['chains'][number]['id'];
  /** Allow failures */
  allowFailure?: boolean;
  /** Query configuration */
  query?: {
    enabled?: boolean;
    staleTime?: number;
    gcTime?: number;
  };
}

type ReadContractsData = ReadContractsReturnType;

Usage Example:

import { useQuery } from '@tanstack/react-query'
import { readContractQueryOptions } from '@wagmi/core/query'

// Single contract read
function TokenName({ address }: { address: Address }) {
  const { data: name } = useQuery(
    readContractQueryOptions(config, {
      address,
      abi: erc20Abi,
      functionName: 'name',
      query: {
        staleTime: 1000 * 60 * 60, // 1 hour (name rarely changes)
      },
    })
  )

  return <div>Token: {name}</div>
}

// Multiple contract reads
function TokenInfo({ address }: { address: Address }) {
  const { data: tokenData } = useQuery(
    readContractsQueryOptions(config, {
      contracts: [
        { address, abi: erc20Abi, functionName: 'name' },
        { address, abi: erc20Abi, functionName: 'symbol' },
        { address, abi: erc20Abi, functionName: 'decimals' },
        { address, abi: erc20Abi, functionName: 'totalSupply' },
      ],
    })
  )

  if (!tokenData) return null

  return (
    <div>
      <div>Name: {tokenData[0].result}</div>
      <div>Symbol: {tokenData[1].result}</div>
      <div>Decimals: {tokenData[2].result}</div>
      <div>Total Supply: {tokenData[3].result?.toString()}</div>
    </div>
  )
}

Blockchain Data Query Options

Query options for blockchain data like blocks, transactions, and network information.

/**
 * Query options for block data
 * @param config - Wagmi configuration
 * @param options - Block query options
 * @returns TanStack Query options
 */
function getBlockQueryOptions<config extends Config>(
  config: config,
  options: GetBlockOptions<config>
): QueryOptions<GetBlockData, GetBlockErrorType>;

interface GetBlockOptions<config extends Config> {
  /** Block number */
  blockNumber?: bigint;
  /** Block hash */
  blockHash?: Hash;
  /** Block tag */
  blockTag?: 'latest' | 'earliest' | 'pending' | 'safe' | 'finalized';
  /** Include transactions */
  includeTransactions?: boolean;
  /** Chain ID */
  chainId?: config['chains'][number]['id'];
  /** Query configuration */
  query?: {
    enabled?: boolean;
    staleTime?: number;
    gcTime?: number;
  };
}

type GetBlockData = GetBlockReturnType;

/**
 * Query options for block number
 * @param config - Wagmi configuration
 * @param options - Block number options
 * @returns TanStack Query options
 */
function getBlockNumberQueryOptions<config extends Config>(
  config: config,
  options: GetBlockNumberOptions<config>
): QueryOptions<GetBlockNumberData, GetBlockNumberErrorType>;

interface GetBlockNumberOptions<config extends Config> {
  /** Chain ID */
  chainId?: config['chains'][number]['id'];
  /** Query configuration */
  query?: {
    enabled?: boolean;
    staleTime?: number;
    gcTime?: number;
    refetchInterval?: number; // Auto-refetch for latest block
  };
}

type GetBlockNumberData = bigint;

/**
 * Query options for transaction data
 * @param config - Wagmi configuration
 * @param options - Transaction query options
 * @returns TanStack Query options
 */
function getTransactionQueryOptions<config extends Config>(
  config: config,
  options: GetTransactionOptions<config>
): QueryOptions<GetTransactionData, GetTransactionErrorType>;

interface GetTransactionOptions<config extends Config> {
  /** Transaction hash */
  hash: Hash;
  /** Chain ID */
  chainId?: config['chains'][number]['id'];
  /** Query configuration */
  query?: {
    enabled?: boolean;
    staleTime?: number;
    gcTime?: number;
  };
}

type GetTransactionData = GetTransactionReturnType;

/**
 * Query options for transaction receipt
 * @param config - Wagmi configuration
 * @param options - Transaction receipt options
 * @returns TanStack Query options
 */
function getTransactionReceiptQueryOptions<config extends Config>(
  config: config,
  options: GetTransactionReceiptOptions<config>
): QueryOptions<GetTransactionReceiptData, GetTransactionReceiptErrorType>;

interface GetTransactionReceiptOptions<config extends Config> {
  /** Transaction hash */
  hash: Hash;
  /** Chain ID */
  chainId?: config['chains'][number]['id'];
  /** Query configuration */
  query?: {
    enabled?: boolean;
    staleTime?: number;
    gcTime?: number;
  };
}

type GetTransactionReceiptData = GetTransactionReceiptReturnType;

Additional Query Options

Additional blockchain operations and client query options.

/**
 * Query options for arbitrary contract calls
 * @param config - Wagmi configuration  
 * @param options - Call options
 * @returns TanStack Query options
 */
function callQueryOptions<config extends Config>(
  config: config,
  options: CallOptions<config>
): QueryOptions<CallData, CallErrorType>;

/**
 * Query options for Merkle proofs
 * @param config - Wagmi configuration
 * @param options - Proof options  
 * @returns TanStack Query options
 */
function getProofQueryOptions<config extends Config>(
  config: config,
  options: GetProofOptions<config>
): QueryOptions<GetProofData, GetProofErrorType>;

/**
 * Query options for connector clients
 * @param config - Wagmi configuration
 * @param options - Connector client options
 * @returns TanStack Query options
 */
function getConnectorClientQueryOptions<config extends Config>(
  config: config,
  options: GetConnectorClientOptions<config>
): QueryOptions<GetConnectorClientData, GetConnectorClientErrorType>;

/**
 * Query options for wallet clients
 * @param config - Wagmi configuration
 * @param options - Wallet client options
 * @returns TanStack Query options  
 */
function getWalletClientQueryOptions<config extends Config>(
  config: config,
  options: GetWalletClientOptions<config>
): QueryOptions<GetWalletClientData, GetWalletClientErrorType>;

Mutation Options for Write Operations

Generate TanStack Query mutation options for write operations like transactions and contract interactions.

/**
 * Mutation options for sending transactions
 * @param config - Wagmi configuration
 * @returns TanStack Query mutation options
 */
function sendTransactionMutationOptions<config extends Config>(
  config: config
): MutationOptions<SendTransactionData, SendTransactionErrorType, SendTransactionVariables>;

interface SendTransactionVariables {
  /** Target address */
  to?: Address;
  /** Transaction data */
  data?: Hex;
  /** Gas limit */
  gas?: bigint;
  /** Gas price */
  gasPrice?: bigint;
  /** Max fee per gas */
  maxFeePerGas?: bigint;
  /** Max priority fee per gas */
  maxPriorityFeePerGas?: bigint;
  /** Nonce */
  nonce?: number;
  /** Value to send */
  value?: bigint;
  /** Chain ID */
  chainId?: number;
}

type SendTransactionData = Hash;

type SendTransactionMutate = (variables: SendTransactionVariables) => void;
type SendTransactionMutateAsync = (variables: SendTransactionVariables) => Promise<SendTransactionData>;

/**
 * Mutation options for contract writes
 * @param config - Wagmi configuration
 * @returns TanStack Query mutation options
 */
function writeContractMutationOptions<config extends Config>(
  config: config
): MutationOptions<WriteContractData, WriteContractErrorType, WriteContractVariables>;

interface WriteContractVariables {
  /** Contract address */
  address: Address;
  /** Contract ABI */
  abi: Abi;
  /** Function name */
  functionName: string;
  /** Function arguments */
  args?: readonly unknown[];
  /** Chain ID */
  chainId?: number;
  /** Gas options */
  gas?: bigint;
  gasPrice?: bigint;
  maxFeePerGas?: bigint;
  maxPriorityFeePerGas?: bigint;
  /** Transaction value */
  value?: bigint;
}

type WriteContractData = Hash;

type WriteContractMutate = (variables: WriteContractVariables) => void;
type WriteContractMutateAsync = (variables: WriteContractVariables) => Promise<WriteContractData>;

/**
 * Mutation options for wallet connection
 * @param config - Wagmi configuration
 * @returns TanStack Query mutation options
 */
function connectMutationOptions<config extends Config>(
  config: config
): MutationOptions<ConnectData, ConnectErrorType, ConnectVariables>;

interface ConnectVariables {
  /** Connector to connect with */
  connector: Connector | CreateConnectorFn;
  /** Chain ID to connect to */
  chainId?: number;
}

type ConnectData = {
  accounts: readonly [Address, ...Address[]];
  chainId: number;
};

type ConnectMutate = (variables: ConnectVariables) => void;
type ConnectMutateAsync = (variables: ConnectVariables) => Promise<ConnectData>;

Usage Example:

import { useMutation, useQueryClient } from '@tanstack/react-query'
import { sendTransactionMutationOptions, getBalanceQueryKey } from '@wagmi/core/query'

function SendTransactionButton() {
  const queryClient = useQueryClient()
  
  const {
    mutate: sendTransaction,
    mutateAsync: sendTransactionAsync,
    isPending,
    error,
  } = useMutation({
    ...sendTransactionMutationOptions(config),
    onSuccess: (hash) => {
      console.log('Transaction sent:', hash)
      // Invalidate balance queries to refetch
      queryClient.invalidateQueries({
        queryKey: getBalanceQueryKey(),
      })
    },
  })

  const handleSend = () => {
    sendTransaction({
      to: '0x742d35Cc6601C2F3Ac5e5c7A9d16e4e6Be4e6e9e',
      value: parseEther('0.1'),
    })
  }

  const handleSendAsync = async () => {
    try {
      const hash = await sendTransactionAsync({
        to: '0x742d35Cc6601C2F3Ac5e5c7A9d16e4e6Be4e6e9e',
        value: parseEther('0.1'),
      })
      console.log('Transaction sent:', hash)
    } catch (error) {
      console.error('Transaction failed:', error)
    }
  }

  return (
    <div>
      <button onClick={handleSend} disabled={isPending}>
        {isPending ? 'Sending...' : 'Send Transaction'}
      </button>
      <button onClick={handleSendAsync} disabled={isPending}>
        Send Async
      </button>
      {error && <div>Error: {error.message}</div>}
    </div>
  )
}

Advanced Query Options

Infinite Queries

For paginated data like contract events or transaction lists.

/**
 * Infinite query options for contract reads
 * @param config - Wagmi configuration
 * @param options - Infinite query options
 * @returns TanStack Query infinite options
 */
function infiniteReadContractsQueryOptions<config extends Config>(
  config: config,
  options: InfiniteReadContractsOptions<config>
): InfiniteQueryOptions<InfiniteReadContractsData, InfiniteReadContractsErrorType>;

interface InfiniteReadContractsOptions<config extends Config> {
  /** Array of contract calls with pagination */
  contracts: (pageParam: unknown) => readonly {
    address: Address;
    abi: Abi;
    functionName: string;
    args?: readonly unknown[];
  }[];
  /** Chain ID */
  chainId?: config['chains'][number]['id'];
  /** Query configuration */
  query?: {
    enabled?: boolean;
    staleTime?: number;
    gcTime?: number;
    getNextPageParam?: (lastPage: any, allPages: any[]) => unknown;
    getPreviousPageParam?: (firstPage: any, allPages: any[]) => unknown;
  };
}

type InfiniteReadContractsData = {
  pages: ReadContractsReturnType[];
  pageParams: unknown[];
};

type InfiniteReadContractsQueryKey = readonly ['infiniteReadContracts', InfiniteReadContractsOptions];

type InfiniteReadContractsQueryFnData = ReadContractsReturnType;

Query Utilities

Utility functions for working with query keys and caching.

/**
 * Hash function for query keys
 * @param queryKey - Query key to hash
 * @returns Hash string
 */
function hashFn(queryKey: QueryKey): string;

/**
 * Structural sharing for query data
 * @param oldData - Previous data
 * @param newData - New data
 * @returns Optimized data with structural sharing
 */
function structuralSharing<T>(oldData: T | undefined, newData: T): T;

type QueryKey = readonly unknown[];

Usage Example:

import { hashFn, structuralSharing } from '@wagmi/core/query'

// Custom query with optimized caching
const customQueryOptions = {
  queryKey: ['custom', 'data'],
  queryFn: async () => {
    // Fetch data
    return await fetchCustomData()
  },
  select: (data: any) => structuralSharing(undefined, data),
  queryKeyHashFn: hashFn,
}

// Use with QueryClient
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      queryKeyHashFn: hashFn,
      structuralSharing,
    },
  },
})

Complete Integration Example

Here's a comprehensive example showing how to use TanStack Query with wagmi:

import { QueryClient, useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import {
  getBalanceQueryOptions,
  readContractQueryOptions,
  writeContractMutationOptions,
  getBalanceQueryKey,
} from '@wagmi/core/query'

// Set up QueryClient with wagmi optimizations
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 1000 * 60, // 1 minute
      gcTime: 1000 * 60 * 60 * 24, // 24 hours
    },
  },
})

// React component example
function TokenManager({ tokenAddress, userAddress }: {
  tokenAddress: Address
  userAddress: Address
}) {
  const queryClient = useQueryClient()

  // Query user's token balance
  const { data: balance, isLoading: balanceLoading } = useQuery(
    getBalanceQueryOptions(config, {
      address: userAddress,
      token: tokenAddress,
      query: {
        enabled: !!userAddress && !!tokenAddress,
        staleTime: 1000 * 30, // 30 seconds for balance
      },
    })
  )

  // Query token metadata
  const { data: tokenName } = useQuery(
    readContractQueryOptions(config, {
      address: tokenAddress,
      abi: erc20Abi,
      functionName: 'name',
      query: {
        enabled: !!tokenAddress,
        staleTime: 1000 * 60 * 60, // 1 hour for token name
      },
    })
  )

  // Mutation for token transfer
  const {
    mutate: transfer,
    isPending: transferPending,
    error: transferError,
  } = useMutation({
    ...writeContractMutationOptions(config),
    onSuccess: (hash) => {
      console.log('Transfer successful:', hash)
      
      // Invalidate and refetch balance
      queryClient.invalidateQueries({
        queryKey: getBalanceQueryKey({ address: userAddress, token: tokenAddress }),
      })
      
      // Optimistically update balance (optional)
      queryClient.setQueryData(
        getBalanceQueryKey({ address: userAddress, token: tokenAddress }),
        (oldBalance: any) => {
          if (!oldBalance) return oldBalance
          return {
            ...oldBalance,
            value: oldBalance.value - transferAmount, // Subtract transferred amount
            formatted: formatUnits(oldBalance.value - transferAmount, oldBalance.decimals),
          }
        }
      )
    },
    onError: (error) => {
      console.error('Transfer failed:', error)
    },
  })

  const handleTransfer = (to: Address, amount: bigint) => {
    transfer({
      address: tokenAddress,
      abi: erc20Abi,
      functionName: 'transfer',
      args: [to, amount],
    })
  }

  if (balanceLoading) return <div>Loading...</div>

  return (
    <div>
      <h3>{tokenName}</h3>
      <p>Balance: {balance?.formatted} {balance?.symbol}</p>
      
      <button 
        onClick={() => handleTransfer('0xRecipient', parseUnits('10', balance?.decimals || 18))}
        disabled={transferPending}
      >
        {transferPending ? 'Transferring...' : 'Transfer 10 tokens'}
      </button>
      
      {transferError && (
        <div>Error: {transferError.message}</div>
      )}
    </div>
  )
}

// App setup
function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <TokenManager 
        tokenAddress="0xA0b86a33E6411c0B7f8C4b5d3e1B9d3e8b4a4e6f"
        userAddress="0x742d35Cc6601C2F3Ac5e5c7A9d16e4e6Be4e6e9e"
      />
    </QueryClientProvider>
  )
}

This integration provides:

  • Automatic caching and background refetching
  • Optimistic updates for better UX
  • Query invalidation after mutations
  • Type safety with wagmi's typed functions
  • Efficient data fetching and synchronization

Install with Tessl CLI

npx tessl i tessl/npm-wagmi--core

docs

account-chain-state.md

advanced-features.md

blockchain-data-reading.md

configuration.md

connection-management.md

contract-interactions.md

ens-operations.md

event-watching.md

index.md

signing-verification.md

tanstack-query.md

transaction-management.md

tile.json