CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-wagmi

React Hooks for Ethereum providing reactive primitives for wallet connections, smart contract interactions, and blockchain data

Pending
Overview
Eval results
Files

batch.mddocs/

Atomic Batch Transactions

EIP-5792 atomic batch transaction support for executing multiple operations as a single unit. This module provides comprehensive functionality for atomic batch transactions, allowing multiple contract calls to be executed together with guaranteed atomicity.

Capabilities

useSendCalls

Hook to send multiple calls atomically using EIP-5792 batch transaction standard.

/**
 * Hook to send multiple calls atomically
 * @param parameters - Atomic batch calls configuration with mutation callbacks
 * @returns Send calls mutation with batch transaction state
 */
function useSendCalls<config = Config, context = unknown>(
  parameters?: UseSendCallsParameters<config, context>
): UseSendCallsReturnType<config, context>;

interface UseSendCallsParameters<config = Config, context = unknown> {
  config?: Config | config;
  mutation?: {
    onMutate?: (variables: SendCallsVariables) => Promise<context> | context;
    onError?: (error: SendCallsErrorType, variables: SendCallsVariables, context?: context) => Promise<void> | void;
    onSuccess?: (data: SendCallsData, variables: SendCallsVariables, context?: context) => Promise<void> | void;
    onSettled?: (data?: SendCallsData, error?: SendCallsErrorType, variables?: SendCallsVariables, context?: context) => Promise<void> | void;
  };
}

interface UseSendCallsReturnType<config = Config, context = unknown> {
  /** Send atomic batch calls */
  sendCalls: (variables: SendCallsVariables, options?: SendCallsMutateOptions) => void;
  /** Async version of sendCalls */
  sendCallsAsync: (variables: SendCallsVariables, options?: SendCallsMutateAsyncOptions) => Promise<SendCallsData>;
  /** Batch transaction data */
  data?: SendCallsData;
  /** Send calls error */
  error: SendCallsErrorType | null;
  /** Send calls status flags */
  isError: boolean;
  isIdle: boolean;
  isPending: boolean;
  isSuccess: boolean;
  /** Reset send calls state */
  reset: () => void;
  /** Current status */
  status: 'error' | 'idle' | 'pending' | 'success';
  /** Additional variables */
  variables?: SendCallsVariables;
}

interface SendCallsVariables {
  /** Array of calls to execute atomically */
  calls: Call[];
  /** Batch execution capabilities */
  capabilities?: WalletCapabilities;
  /** Chain ID for the batch */
  chainId?: number;
  /** Version of the batch call standard */
  version?: string;
}

interface Call {
  /** Target contract address */
  to?: Address;
  /** Call data */
  data?: Hex;
  /** Value to send with call */
  value?: bigint;
  /** Gas limit for this call */
  gas?: bigint;
  /** Chain ID for this specific call */
  chainId?: number;
}

interface SendCallsData {
  /** Batch identifier */
  id: string;
}

Usage Example:

import { useSendCalls, useAccount } from "wagmi";
import { encodeFunctionData, erc20Abi } from "viem";

function BatchTransfer() {
  const { address } = useAccount();
  const { sendCalls, data: batchId, isPending } = useSendCalls();

  const handleBatchTransfer = () => {
    if (!address) return;

    // Encode transfer calls
    const transferCall1 = encodeFunctionData({
      abi: erc20Abi,
      functionName: 'transfer',
      args: ['0x742d35Cc6634C0532925a3b8D', 1000000000000000000n], // 1 token
    });

    const transferCall2 = encodeFunctionData({
      abi: erc20Abi,
      functionName: 'transfer', 
      args: ['0x8ba1f109551bD432803012645Hac136c', 500000000000000000n], // 0.5 tokens
    });

    sendCalls({
      calls: [
        {
          to: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI
          data: transferCall1,
        },
        {
          to: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI
          data: transferCall2,
        },
      ],
    });
  };

  return (
    <div>
      <button onClick={handleBatchTransfer} disabled={!address || isPending}>
        {isPending ? 'Sending Batch...' : 'Send Batch Transfers'}
      </button>
      {batchId && <p>Batch ID: {batchId}</p>}
    </div>
  );
}

useCallsStatus

Hook to check the status of batched calls by their batch ID.

/**
 * Hook to check status of batched calls
 * @param parameters - Calls status query parameters
 * @returns Current status of the batched calls
 */
function useCallsStatus<config = Config, selectData = UseCallsStatusReturnType>(
  parameters: UseCallsStatusParameters<config, selectData>
): UseCallsStatusReturnType<selectData>;

interface UseCallsStatusParameters<config = Config, selectData = UseCallsStatusReturnType> {
  /** Batch ID to check status for */
  id: string;
  /** Chain ID where batch was submitted */
  chainId?: config['chains'][number]['id'];
  config?: Config | config;
  query?: {
    enabled?: boolean;
    staleTime?: number;
    gcTime?: number;
    refetchInterval?: number;
    select?: (data: UseCallsStatusReturnType) => selectData;
  };
}

interface UseCallsStatusReturnType {
  /** Current batch status */
  status: 'PENDING' | 'CONFIRMED' | 'FAILED';
  /** Individual call receipts */
  receipts?: CallReceipt[];
}

interface CallReceipt {
  /** Transaction hash for this call */
  transactionHash: Hash;
  /** Block hash */
  blockHash: Hash;
  /** Block number */
  blockNumber: bigint;
  /** Gas used */
  gasUsed: bigint;
  /** Call status */
  status: 'success' | 'reverted';
  /** Event logs */
  logs: Log[];
}

useWaitForCallsStatus

Hook to wait for batched calls to complete with polling support.

/**
 * Hook to wait for calls to complete
 * @param parameters - Wait for calls parameters
 * @returns Final status when calls complete
 */
function useWaitForCallsStatus<config = Config, selectData = UseWaitForCallsStatusReturnType>(
  parameters: UseWaitForCallsStatusParameters<config, selectData>
): UseWaitForCallsStatusReturnType<selectData>;

interface UseWaitForCallsStatusParameters<config = Config, selectData = UseWaitForCallsStatusReturnType> {
  /** Batch ID to wait for */
  id: string;
  /** Chain ID */
  chainId?: config['chains'][number]['id'];
  /** Polling interval in milliseconds */
  pollingInterval?: number;
  /** Timeout in milliseconds */
  timeout?: number;
  config?: Config | config;
  query?: {
    enabled?: boolean;
    gcTime?: number;
    refetchInterval?: number;
    retry?: boolean | number;
    select?: (data: UseWaitForCallsStatusReturnType) => selectData;
  };
}

type UseWaitForCallsStatusReturnType = UseCallsStatusReturnType;

Usage Example:

import { useSendCalls, useWaitForCallsStatus } from "wagmi";

function BatchWithStatus() {
  const { sendCalls, data: batchId } = useSendCalls();

  const { 
    data: status,
    isLoading,
    isSuccess,
    isError 
  } = useWaitForCallsStatus({
    id: batchId || '',
    query: { enabled: !!batchId }
  });

  const handleBatch = () => {
    sendCalls({
      calls: [
        { to: '0x742d35Cc6634C0532925a3b8D', value: 1000000000000000000n },
        { to: '0x8ba1f109551bD432803012645Hac136c', value: 500000000000000000n },
      ],
    });
  };

  return (
    <div>
      <button onClick={handleBatch}>Send Batch</button>
      
      {batchId && (
        <div>
          <p>Batch ID: {batchId}</p>
          {isLoading && <p>Waiting for confirmation...</p>}
          {isSuccess && (
            <div>
              <p>Status: {status?.status}</p>
              <p>Receipts: {status?.receipts?.length || 0}</p>
            </div>
          )}
          {isError && <p>Batch failed</p>}
        </div>
      )}
    </div>
  );
}

useShowCallsStatus

Hook to show calls status in the wallet UI for user visibility.

/**
 * Hook to show calls status in wallet UI
 * @param parameters - Show calls status configuration
 * @returns Show calls status mutation
 */
function useShowCallsStatus<config = Config, context = unknown>(
  parameters?: UseShowCallsStatusParameters<config, context>
): UseShowCallsStatusReturnType<config, context>;

interface UseShowCallsStatusParameters<config = Config, context = unknown> {
  config?: Config | config;
  mutation?: {
    onMutate?: (variables: ShowCallsStatusVariables) => Promise<context> | context;
    onError?: (error: ShowCallsStatusErrorType, variables: ShowCallsStatusVariables, context?: context) => Promise<void> | void;
    onSuccess?: (data: ShowCallsStatusData, variables: ShowCallsStatusVariables, context?: context) => Promise<void> | void;
    onSettled?: (data?: ShowCallsStatusData, error?: ShowCallsStatusErrorType, variables?: ShowCallsStatusVariables, context?: context) => Promise<void> | void;
  };
}

interface UseShowCallsStatusReturnType<config = Config, context = unknown> {
  /** Show calls status in wallet */
  showCallsStatus: (variables: ShowCallsStatusVariables, options?: ShowCallsStatusMutateOptions) => void;
  /** Async version of showCallsStatus */
  showCallsStatusAsync: (variables: ShowCallsStatusVariables, options?: ShowCallsStatusMutateAsyncOptions) => Promise<ShowCallsStatusData>;
  /** Show calls status data */
  data?: ShowCallsStatusData;
  /** Show calls status error */
  error: ShowCallsStatusErrorType | null;
  /** Show calls status flags */
  isError: boolean;
  isIdle: boolean;
  isPending: boolean;
  isSuccess: boolean;
  /** Reset show calls status state */
  reset: () => void;
  /** Current status */
  status: 'error' | 'idle' | 'pending' | 'success';
  /** Additional variables */
  variables?: ShowCallsStatusVariables;
}

interface ShowCallsStatusVariables {
  /** Batch ID to show status for */
  id: string;
}

type ShowCallsStatusData = boolean; // Whether wallet showed the status

useCapabilities

Hook to get wallet capabilities for batch transaction support.

/**
 * Hook to get wallet capabilities
 * @param parameters - Capabilities query parameters
 * @returns Available wallet capabilities
 */
function useCapabilities<config = Config, selectData = UseCapabilitiesReturnType>(
  parameters?: UseCapabilitiesParameters<config, selectData>
): UseCapabilitiesReturnType<selectData>;

interface UseCapabilitiesParameters<config = Config, selectData = UseCapabilitiesReturnType> {
  /** Account to get capabilities for */
  account?: Address;
  /** Chain ID */
  chainId?: config['chains'][number]['id'];
  config?: Config | config;
  query?: {
    enabled?: boolean;
    staleTime?: number;
    gcTime?: number;
    select?: (data: UseCapabilitiesReturnType) => selectData;
  };
}

interface UseCapabilitiesReturnType {
  [chainId: number]: WalletCapabilities;
}

interface WalletCapabilities {
  /** Atomic batch transaction support */
  atomicBatch?: {
    supported: boolean;
  };
  /** Paymaster support */
  paymasterService?: {
    supported: boolean;
  };
  /** Session key support */
  sessionKeys?: {
    supported: boolean;
  };
  /** Additional capabilities */
  [key: string]: unknown;
}

Usage Example:

import { useCapabilities, useAccount } from "wagmi";

function CapabilitiesChecker() {
  const { address } = useAccount();
  const { data: capabilities, isLoading } = useCapabilities({
    account: address,
  });

  if (isLoading) return <div>Checking capabilities...</div>;

  return (
    <div>
      <h3>Wallet Capabilities</h3>
      {capabilities && Object.entries(capabilities).map(([chainId, caps]) => (
        <div key={chainId}>
          <h4>Chain {chainId}</h4>
          <p>Atomic Batch: {caps.atomicBatch?.supported ? '✅' : '❌'}</p>
          <p>Paymaster: {caps.paymasterService?.supported ? '✅' : '❌'}</p>
          <p>Session Keys: {caps.sessionKeys?.supported ? '✅' : '❌'}</p>
        </div>
      ))}
    </div>
  );
}

useCall

Hook to execute a single call (part of the batch transaction system).

/**
 * Hook to execute a single call
 * @param parameters - Call execution parameters
 * @returns Call result
 */
function useCall<config = Config, selectData = UseCallReturnType>(
  parameters: UseCallParameters<config, selectData>
): UseCallReturnType<selectData>;

interface UseCallParameters<config = Config, selectData = UseCallReturnType> {
  /** Target address */
  to?: Address;
  /** Call data */
  data?: Hex;
  /** Value to send */
  value?: bigint;
  /** Account to call from */
  account?: Address;
  /** Block number to call at */
  blockNumber?: bigint;
  blockTag?: 'latest' | 'earliest' | 'pending' | 'safe' | 'finalized';
  /** Chain ID */
  chainId?: config['chains'][number]['id'];
  /** Gas limit */
  gas?: bigint;
  /** Gas price */
  gasPrice?: bigint;
  /** Max fee per gas */
  maxFeePerGas?: bigint;
  /** Max priority fee per gas */
  maxPriorityFeePerGas?: bigint;
  config?: Config | config;
  query?: {
    enabled?: boolean;
    staleTime?: number;
    select?: (data: UseCallReturnType) => selectData;
  };
}

type UseCallReturnType = Hex | undefined;

Advanced Batch Transaction Patterns

Multi-Token Batch Operations

import { useSendCalls, useCapabilities } from "wagmi";
import { encodeFunctionData, erc20Abi, parseEther } from "viem";

function MultiTokenBatch() {
  const { data: capabilities } = useCapabilities();
  const { sendCalls, isPending } = useSendCalls();

  const canBatch = capabilities?.[1]?.atomicBatch?.supported;

  const handleComplexBatch = () => {
    if (!canBatch) {
      alert('Wallet does not support atomic batch transactions');
      return;
    }

    // Create multiple token operations
    const approveUSDC = encodeFunctionData({
      abi: erc20Abi,
      functionName: 'approve',
      args: ['0x7f39C581F595B53c5cb19bD0b3f8DA6c935E2Ca0', parseEther('1000')],
    });

    const transferDAI = encodeFunctionData({
      abi: erc20Abi,
      functionName: 'transfer',
      args: ['0x742d35Cc6634C0532925a3b8D', parseEther('500')],
    });

    const transferUSDC = encodeFunctionData({
      abi: erc20Abi,
      functionName: 'transfer',
      args: ['0x8ba1f109551bD432803012645Hac136c', 1000000000n], // 1000 USDC
    });

    sendCalls({
      calls: [
        {
          to: '0xA0b86a33E6417C90CC5F6d2c4a29f9D7e5D8ecf0', // USDC
          data: approveUSDC,
        },
        {
          to: '0x6B175474E89094C44Da98b954EedeAC495271d0F', // DAI
          data: transferDAI,
        },
        {
          to: '0xA0b86a33E6417C90CC5F6d2c4a29f9D7e5D8ecf0', // USDC
          data: transferUSDC,
        },
      ],
    });
  };

  return (
    <div>
      <p>Batch Support: {canBatch ? '✅' : '❌'}</p>
      <button 
        onClick={handleComplexBatch} 
        disabled={!canBatch || isPending}
      >
        {isPending ? 'Processing...' : 'Execute Multi-Token Batch'}
      </button>
    </div>
  );
}

Batch Status Monitor

import { 
  useSendCalls, 
  useCallsStatus, 
  useShowCallsStatus 
} from "wagmi";
import { useState } from "react";

function BatchStatusMonitor() {
  const [batchIds, setBatchIds] = useState<string[]>([]);
  
  const { sendCalls } = useSendCalls({
    mutation: {
      onSuccess(data) {
        setBatchIds(prev => [...prev, data.id]);
      },
    },
  });

  const { showCallsStatus } = useShowCallsStatus();

  return (
    <div>
      <h3>Batch Status Monitor</h3>
      
      <button onClick={() => sendCalls({
        calls: [
          { to: '0x742d35Cc6634C0532925a3b8D', value: parseEther('0.01') }
        ]
      })}>
        Send New Batch
      </button>

      <div>
        <h4>Active Batches ({batchIds.length})</h4>
        {batchIds.map(id => (
          <BatchStatusItem 
            key={id} 
            batchId={id}
            onShowStatus={() => showCallsStatus({ id })}
          />
        ))}
      </div>
    </div>
  );
}

function BatchStatusItem({ 
  batchId, 
  onShowStatus 
}: { 
  batchId: string;
  onShowStatus: () => void;
}) {
  const { data: status, isLoading } = useCallsStatus({ id: batchId });

  return (
    <div style={{ border: '1px solid #ccc', padding: '8px', margin: '4px' }}>
      <p>ID: {batchId}</p>
      <p>Status: {isLoading ? 'Loading...' : status?.status}</p>
      <p>Receipts: {status?.receipts?.length || 0}</p>
      <button onClick={onShowStatus}>Show in Wallet</button>
    </div>
  );
}

Common Types

type Address = `0x${string}`;
type Hash = `0x${string}`;
type Hex = `0x${string}`;

interface Log {
  address: Address;
  topics: readonly Hash[];
  data: Hex;
  blockHash?: Hash;
  blockNumber?: bigint;
  transactionHash?: Hash;
  transactionIndex?: number;
  logIndex?: number;
  removed?: boolean;
}

interface SendCallsMutateOptions {
  onError?: (error: Error, variables: SendCallsVariables, context?: unknown) => void;
  onSuccess?: (data: SendCallsData, variables: SendCallsVariables, context?: unknown) => void;
  onSettled?: (data?: SendCallsData, error?: Error, variables?: SendCallsVariables, context?: unknown) => void;
}

interface ShowCallsStatusMutateOptions {
  onError?: (error: Error, variables: ShowCallsStatusVariables, context?: unknown) => void;
  onSuccess?: (data: boolean, variables: ShowCallsStatusVariables, context?: unknown) => void;
  onSettled?: (data?: boolean, error?: Error, variables?: ShowCallsStatusVariables, context?: unknown) => void;
}

type SendCallsErrorType = Error;
type ShowCallsStatusErrorType = Error;

interface BatchTransactionSummary {
  id: string;
  status: 'PENDING' | 'CONFIRMED' | 'FAILED';
  callCount: number;
  successCount: number;
  failureCount: number;
  totalGasUsed?: bigint;
  blockNumber?: bigint;
}

Install with Tessl CLI

npx tessl i tessl/npm-wagmi

docs

account.md

advanced.md

batch.md

blockchain.md

contracts.md

ens.md

gas-fees.md

index.md

signing.md

transactions.md

watch.md

tile.json