Skip to main content
The Transaction components provide a high-level wrap around the entire transaction flow. It handles the transaction lifecycle, including gas estimation, fee sponsorship, and status updates.

Quick start

The Transaction component now supports a simplified shorthand version to streamline the integration process for developers. Instead of manually defining each subcomponent and prop, you can render Transaction without children, and it will automatically include our suggested implementation — complete with the TransactionButton and TransactionToast components. If you’d like more customization, follow the implementation guide for our Transaction components below.
import { Transaction } from "@coinbase/onchainkit/transaction"

const calls = [...];

<Transaction calls={calls} />

Props

type TransactionProps = {
  calls?: Calls | Contracts | Array<Call | ContractFunctionParameters>; // An array of calls to be made in the transaction
  capabilities?: WalletCapabilities; // @deprecated Use `isSponsored` instead
  chainId?: number; // The chainId for the transaction
  children?: ReactNode; // The child components to be rendered within the transaction component
  className?: string; // An optional CSS class name for styling the component
  isSponsored?: boolean; // Whether the transactions are sponsored (default: false)
  onError?: (e: TransactionError) => void; // An optional callback function that handles transaction errors
  onStatus?: (lifecycleStatus: LifecycleStatus) => void; // An optional callback function that exposes the component lifecycle state
  onSuccess?: (response: TransactionResponseType) => void; // An optional callback function that exposes the transaction receipts
  resetAfter?: number; // An optional time (in ms) after which to reset the component
} & (
  | {
      children: ReactNode;
      disabled?: never; // An optional prop to disable submit button. Only available when children are not provided
    }
  | {
      children?: never;
      disabled?: boolean; // An optional prop to disable submit button. Only available when children are not provided
    }
);

Walkthrough

1

Add calls

Execute one or multiple transactions using the Transaction component. You can pass transactions in either Call or ContractFunctionParameters format. The component will automatically apply batching logic if the user’s wallet supports it.

Types

import { useCallback } from 'react';
import { Avatar, Name } from '@coinbase/onchainkit/identity';
import { 
  Transaction, 
  TransactionButton,
  TransactionSponsor,
  TransactionStatus,
  TransactionStatusAction,
  TransactionStatusLabel,
} from '@coinbase/onchainkit/transaction'; 
import type { LifecycleStatus } from '@coinbase/onchainkit/transaction';
import { Wallet, ConnectWallet } from '@coinbase/onchainkit/wallet';
import { useAccount } from 'wagmi';
import { calls } from '@/calls'; 

// ---cut-start---

const BASE_SEPOLIA_CHAIN_ID = 84532;
// ---cut-end---

export default function TransactionComponents() {
const { address } = useAccount();

    const handleOnStatus = useCallback((status: LifecycleStatus) => {
      console.log('LifecycleStatus', status);
    }, []);

    return address ? (
      <Transaction
        chainId={BASE_SEPOLIA_CHAIN_ID}
        calls={calls}
        onStatus={handleOnStatus}
      >
        <TransactionButton />
        <TransactionSponsor />
        <TransactionStatus>
          <TransactionStatusLabel />
          <TransactionStatusAction />
        </TransactionStatus>
      </Transaction>
    ) : (
      <Wallet>
        <ConnectWallet>
          <Avatar className='h-6 w-6' />
          <Name />
        </ConnectWallet>
      </Wallet>
    );

};

2

Listen to LifecycleStatus

Take full control of your transactions data with the LifecycleStatus object via the onStatus prop. This TypeScript object provides statusName and statusData to keep you informed.
import { useCallback } from 'react';
import {
  Transaction,
  TransactionButton,
  TransactionSponsor,
  TransactionStatus,
  TransactionToast,
  TransactionToastIcon,
  TransactionToastLabel,
  TransactionToastAction,
} from '@coinbase/onchainkit/transaction';
import {contracts} from '@/contracts';
// ---cut-before---

import type { LifecycleStatus } from '@coinbase/onchainkit/transaction'; 

// omitted for brevity

const handleOnStatus = useCallback((status: LifecycleStatus) => {  
  console.log('Transaction status:', status); 
}, []); 

// omitted for brevity

// Usage in component
<Transaction
  contracts={contracts}
  onStatus={handleOnStatus}
>
  <TransactionButton />
  <TransactionSponsor />
  <TransactionToast>
    <TransactionToastIcon />
    <TransactionToastLabel />
    <TransactionToastAction />
  </TransactionToast>
</Transaction>
The Lifecycle Status features seven states for the transaction experience.
import type { TransactionError } from "@coinbase/onchainkit/transaction";
import type { Address, TransactionReceipt } from "viem";
// ---cut-before---
type LifecycleStatus =
  | {
      statusName: 'init';
      statusData: null;
    }
  | {
      statusName: 'error';
      statusData: TransactionError;
    }
  | {
      statusName: 'transactionIdle'; // initial status prior to the mutation function executing
      statusData: null;
    }
  | {
      statusName: 'buildingTransaction'; // resolving calls or contracts promise
      statusData: null;
    }
  | {
      statusName: 'transactionPending'; // if the mutation is currently executing
      statusData: null;
    }
  | {
      statusName: 'transactionLegacyExecuted';
      statusData: {
        transactionHashList: string[];
      };
    }
  | {
      statusName: 'success'; // if the last mutation attempt was successful
      statusData: {
        transactionReceipts: TransactionReceipt[];
      };
    };
3

Sponsor with Paymaster capabilities

To sponsor your transactions with Paymaster capabilities, configure your OnchainKitProvider with the appropriate config.paymaster URL, then pass isSponsored={true} to the Transaction component.Obtain a Paymaster and Bundler endpoint from the Coinbase Developer Platform.
OnchainKit Paymaster and Bundler endpoint
<OnchainKitProvider
  config={{ 
    paymaster: process.env.PAYMASTER_ENDPOINT, 
  }}
>
Next, pass isSponsored={true} to the Transaction component.
import { Transaction, TransactionButton, TransactionSponsor } from "@coinbase/onchainkit/transaction"
// ---cut-before---
// omitted for brevity
<Transaction
  isSponsored={true}
  contracts={contracts}
>
  <TransactionButton />
  <TransactionSponsor />
</Transaction>

Using calls with Promises

Calls also accepts asynchronous functions that are resolved on each button click. This can be useful if you’re calling an API to retrieve transaction data. These functions must resolve to Call[] or ContractFunctionParameters[]. In the example the calls data will be fetched from api.transaction.com when the user clicks the Transaction Button.
import { Transaction, TransactionButton, LifecycleStatus} from '@coinbase/onchainkit/transaction';
import { baseSepolia } from 'wagmi/chains';

// ---cut-before---

const callsCallback = async () => { 
  const res = await fetch('api.transaction.com/createTransaction'); 
  const callData = await res.json(); 
  return callData; 
} 

export default function TransactionWithCalls() {

  return (
    <Transaction
      chainId={baseSepolia.id}
      calls={callsCallback} 
      onStatus={(status: LifecycleStatus) => console.log('Transaction status:', status)}
    >
      <TransactionButton />
    </Transaction>
  );
}

Components

OnchainKit transaction anatomy component diagram
The components are designed to work together hierarchically. For each component, ensure the following:
  • <Transaction /> - Serves as the main container for all transaction-related components.
  • <TransactionButton /> - Handles the transaction initiation process.
  • <TransactionSponsor /> - Displays information about the sponsorship of transaction gas fees.
  • <TransactionStatus /> - Contains transaction status information and actions.
  • <TransactionStatusLabel /> - Displays the current status of the transaction.
  • <TransactionStatusAction /> - Provides additional actions based on the transaction status.
  • <TransactionToast /> - Displays a toast notification for the transaction status.
  • <TransactionToastIcon /> - Displays an icon in the transaction toast notification.
  • <TransactionToastLabel /> - Displays the label text in the transaction toast notification.
  • <TransactionToastAction /> - Provides additional actions within the transaction toast notification.

Advanced Customization

Custom Transaction Button with Render Props

For complete control over the transaction button rendering, use the render prop on TransactionButton. This allows you to implement custom UI while maintaining all transaction functionality:
import { TransactionButton } from '@coinbase/onchainkit/transaction';

<TransactionButton
  render={({ status, onSubmit, isDisabled }) => (
    <button
      onClick={onSubmit}
      disabled={isDisabled}
      className="my-custom-transaction-button"
    >
      {status === 'pending' ? 'Processing...' : 'Submit Transaction'}
    </button>
  )}
/>

Component Props

TransactionButtonProps

type TransactionButtonProps = {
  className?: string; // An optional CSS class name for styling the button component
  disabled?: boolean; // A optional prop to disable the submit button
  text?: ReactNode; // An optional text to be displayed in the button component
  errorOverride?: TransactionButtonOverride; // Optional overrides for text and onClick handler in error state
  successOverride?: TransactionButtonOverride; // Optional overrides for text and onClick handler in success state
  pendingOverride?: Pick<TransactionButtonOverride, 'text'>; // Optional overrides for text in pending state
  render?: (params: {
    status: 'default' | 'success' | 'error' | 'pending';
    onSubmit: () => void;
    onSuccess: () => void;
    isDisabled: boolean;
    context: TransactionContextType;
  }) => ReactNode; // Custom render function for complete control of button rendering
};

TransactionSponsorProps

type TransactionSponsorProps = {
  className?: string; // An optional CSS class name for styling the sponsor component
};

TransactionStatusProps

type TransactionStatusProps = {
  children?: ReactNode; // The child components to be rendered within the status component
  className?: string; // An optional CSS class name for styling the status component
};

TransactionStatusActionProps

type TransactionStatusActionProps = {
  className?: string; // An optional CSS class name for styling
};

TransactionStatusLabelProps

type TransactionStatusLabelProps = {
  className?: string; // An optional CSS class name for styling
};

TransactionToastProps

type TransactionToastProps = {
  children?: ReactNode; // The child components to be rendered within the toast component
  className?: string; // An optional CSS class name for styling the toast component
  duration?: number; // An optional value to customize time until toast disappears
  position?: 'top-center' | 'top-right' | 'bottom-center' | 'bottom-right'; // An optional position property to specify the toast's position on the screen
};

TransactionToastActionProps

type TransactionToastActionProps = {
  className?: string; // An optional CSS class name for styling
};

TransactionToastIconProps

type TransactionToastIconProps = {
  className?: string; // An optional CSS class name for styling
};

TransactionToastLabelProps

type TransactionToastLabelProps = {
  className?: string; // An optional CSS class name for styling
};

Supporting Types

type Call = { to: Hex; data?: Hex; value?: bigint };

type LifecycleStatus =
  | { statusName: 'init'; statusData: null }
  | { statusName: 'error'; statusData: TransactionError }
  | { statusName: 'transactionIdle'; statusData: null }
  | { statusName: 'buildingTransaction'; statusData: null }
  | { statusName: 'transactionPending'; statusData: null }
  | { statusName: 'transactionLegacyExecuted'; statusData: { transactionHashList: Address[] } }
  | { statusName: 'success'; statusData: { transactionReceipts: TransactionReceipt[] } }
  | { statusName: 'reset'; statusData: null };

type TransactionError = {
  code: string; // The error code representing the type of transaction error
  error: string; // The error message providing details about the transaction error
  message: string; // The error message providing details about the transaction error
};

type TransactionResponseType = {
  transactionReceipts: TransactionReceipt[];
};