Skip to main content

Recommended: JavaScript SDK with React Hooks

For new React apps, we recommend the JavaScript SDK with React Hooks (@dynamic-labs-sdk/react-hooks) instead of the legacy React SDK documented here. The JS SDK comes with many benefits such as a much smaller bundle size and other optimizations. Use the React quickstart (JavaScript SDK) to get started.
This is a React-only guide.

Standard

EIP-5792 defines a standard for smart contract wallets that introduced new JSON-RPC methods. These methods allow batched, gas-sponsored, and conditional transactions through a simple interface. These endpoints make it easier for dapps and wallets to interact with smart accounts without needing to understand account abstraction internals like ERC-4337. EIP-5792 introduced the following functions:
  • wallet_getCapabilities
  • wallet_sendCalls
  • wallet_getCallsStatus
  • wallet_showCallsStatus

Support

As of 04/2025 EIP-5792 is still rolling out, and you can find a list of wallets that support it here. The example below show how to handle wallet_getCapabilities for atomic (batch transactions) and paymaster support, and sendCalls with for a batched transaction.

Example

import { useDynamicContext } from '@dynamic-labs/sdk-react-core';
import { parseEther } from 'viem';

...
const { primaryWallet} = useDynamicContext();
...
const signAtomicSponsoredTransactionExample = async () => {
  if (primaryWallet) {
    const chainId = (await primaryWallet.getNetwork());
    const walletClient = await primaryWallet.getWalletClient();
    const capabilities = await walletClient.getCapabilities();
    if (capabilities  && capabilities[chainId])  {
      const chainCapabilities = capabilities[chainId];
      const paymasterServiceSupported = chainCapabilities.paymasterService?.supported;
      const atomicStatusSupported = chainCapabilities.atomic && (chainCapabilities.atomic.status ==  'ready' || chainCapabilities.atomic.status == 'supported');
      if (!atomicStatusSupported) {
        console.log('atomic is not supported for chainId:', chainId);
        return;
      }

      if (!paymasterServiceSupported) {
        console.log('paymaster is not supported for chainId:', chainId);
      }
      const callParams = {
        calls: [
          {
            to: '0x58e2C06939056c2fC760bE062Ef6dbbbCD4045e3',
            value: parseEther('0.001')
          },
          {
            to: '0x58e2C06939056c2fC760bE062Ef6dbbbCD4045e3',
            value: parseEther('0.001')
          },
        ]
      };

      if (paymasterServiceSupported) {
        callParams.capabilities = {
          paymasterService: {
            url: undefined
          }
        };
      }

      const result = await walletClient.sendCalls(callParams);
      return result;
    }
  }
};

Track status

After calling sendCalls, use getCallsStatus to check whether the batch has settled:
const status = await walletClient.getCallsStatus({ id: result.id });

if (status.status === 'success') {
  console.log('Batch executed:', status.receipts);
}
viem ≥ 2.28: waitForCallsStatus is available on the wallet client as a convenience wrapper that polls getCallsStatus internally and resolves once the batch reaches a terminal state. On older viem versions, poll getCallsStatus yourself in a loop with a delay.
Last modified on July 3, 2026