Skip to main content

Overview

The EvmSmartAccount is an EVM smart contract account that supports account abstraction features like user operations, batch transactions, and paymasters. It requires one or more owner accounts for signing.

Type Definition

type EvmSmartAccount = {
  address: Address;
  name?: string;
  type: "evm-smart";
  owners: EvmAccount[];
  policies?: string[];
  transfer: (options: SmartAccountTransferOptions) => Promise<SendUserOperationReturnType>;
  listTokenBalances: (options: Omit<ListTokenBalancesOptions, "address">) => Promise<ListTokenBalancesResult>;
  sendUserOperation: <callData>(options: Omit<SendUserOperationOptions<callData>, "smartAccount">) => Promise<SendUserOperationReturnType>;
  waitForUserOperation: (options: Omit<WaitForUserOperationOptions, "smartAccountAddress">) => Promise<WaitForUserOperationReturnType>;
  getUserOperation: (options: Omit<GetUserOperationOptions, "smartAccount">) => Promise<UserOperation>;
  requestFaucet: (options: Omit<RequestFaucetOptions, "address">) => Promise<RequestFaucetResult>;
  quoteSwap: (options: SmartAccountQuoteSwapOptions) => Promise<SmartAccountQuoteSwapResult>;
  swap: (options: SmartAccountSwapOptions) => Promise<SmartAccountSwapResult>;
  signTypedData: (options: SignTypedDataOptions & { network: string }) => Promise<Hex>;
  useSpendPermission: (options: UseSpendPermissionOptions) => Promise<SendUserOperationReturnType>;
  useNetwork: <Network>(network: Network) => Promise<NetworkScopedEvmSmartAccount<Network>>;
};

Properties

address
Address
required
The smart account’s contract address.
name
string
Optional name for the smart account.
type
'evm-smart'
required
Identifier for the smart account type.
owners
EvmAccount[]
required
Array of owner accounts that can sign for this smart account. Currently supports one owner, but will be extended to support multiple owners in the future.
policies
string[]
Array of Policy IDs that apply to the smart account (includes both project-level and account-level policies).

Methods

sendUserOperation

Sends a user operation (batch of calls) to the network.
options
object
required
userOpHash
Hex
The user operation hash.
smartAccountAddress
Address
The smart account address.
status
string
The status of the user operation.
import { parseEther } from "viem";

const result = await smartAccount.sendUserOperation({
  network: "base-sepolia",
  calls: [
    {
      to: "0x4252e0c9A3da5A2700e7d91cb50aEf522D0C6Fe8",
      value: parseEther("0.000001"),
      data: "0x",
    },
    {
      to: "0x1234567890123456789012345678901234567890",
      value: parseEther("0.000002"),
      data: "0x",
    },
  ],
});

waitForUserOperation

Waits for a user operation to be confirmed on-chain.
options
object
required
status
string
The final status of the user operation.
transactionHash
Hex
The transaction hash if the user operation was successful.
const result = await smartAccount.sendUserOperation({ ... });

const receipt = await smartAccount.waitForUserOperation({
  userOpHash: result.userOpHash,
  network: "base-sepolia",
});

console.log("Transaction hash:", receipt.transactionHash);

getUserOperation

Retrieves details of a user operation by its hash.
options
object
required
userOperation
UserOperation
The user operation details.
const userOp = await smartAccount.getUserOperation({
  userOpHash: "0x...",
  network: "base-sepolia",
});

console.log("Calls:", userOp.calls);
console.log("Status:", userOp.status);

transfer

Transfers native tokens or ERC-20 tokens using a user operation.
options
SmartAccountTransferOptions
required
userOpHash
Hex
The user operation hash.
import { parseEther } from "viem";

const result = await smartAccount.transfer({
  network: "base-sepolia",
  to: "0x4252e0c9A3da5A2700e7d91cb50aEf522D0C6Fe8",
  amount: parseEther("0.001"),
});

listTokenBalances

Lists token balances for the smart account.
options
object
required
balances
TokenBalance[]
Array of token balances.
const { balances } = await smartAccount.listTokenBalances({
  network: "base-sepolia",
});

requestFaucet

Requests testnet funds from a faucet.
options
object
required
transactionHash
Hex
The faucet transaction hash.
const result = await smartAccount.requestFaucet({
  network: "base-sepolia",
  token: "eth",
});

quoteSwap

Gets a quote for swapping tokens via the smart account.
options
SmartAccountQuoteSwapOptions
required
quote
SmartAccountSwapQuote
The swap quote with execute method.
import { parseEther } from "viem";

const quote = await smartAccount.quoteSwap({
  network: "base",
  fromToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
  toToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
  fromAmount: parseEther("1"),
});

swap

Executes a token swap via the smart account.
options
SmartAccountSwapOptions
required
Swap options or quote from quoteSwap.
userOpHash
Hex
The user operation hash.
// Using a quote
const quote = await smartAccount.quoteSwap({ ... });
const result = await smartAccount.swap(quote);

// Or execute directly from the quote
const result = await quote.execute();

signTypedData

Signs EIP-712 typed data with signature wrapping for smart accounts.
options
object
required
signature
Hex
The wrapped signature.
const signature = await smartAccount.signTypedData({
  network: "base-sepolia",
  domain: {
    name: "MyDapp",
    version: "1",
    chainId: 84532,
  },
  types: {
    Message: [
      { name: "content", type: "string" },
    ],
  },
  primaryType: "Message",
  message: {
    content: "Hello, world!",
  },
});

useSpendPermission

Uses a spend permission to transfer tokens via a user operation.
options
UseSpendPermissionOptions
required
Spend permission usage options.
userOpHash
Hex
The user operation hash.
const result = await smartAccount.useSpendPermission({
  network: "base-sepolia",
  spendPermission: { ... },
});

useNetwork

Returns a network-scoped smart account.
network
string
required
The network name.
NetworkScopedEvmSmartAccount
NetworkScopedEvmSmartAccount
A network-scoped smart account.
const baseSmartAccount = await smartAccount.useNetwork("base-sepolia");

const result = await baseSmartAccount.transfer({
  to: "0x...",
  amount: parseEther("0.001"),
});

Creating a Smart Account

Smart accounts are created through the CdpClient with an owner account:
import { CdpClient } from "@coinbase/cdp-sdk";

const cdp = new CdpClient();

// Create an owner account
const owner = await cdp.evm.createAccount();

// Create a smart account with the owner
const smartAccount = await cdp.evm.createSmartAccount({
  owner,
});

Batch Transactions

Smart accounts support batching multiple calls into a single user operation:
import { parseEther } from "viem";

const result = await smartAccount.sendUserOperation({
  network: "base-sepolia",
  calls: [
    // Transfer ETH
    {
      to: "0x4252e0c9A3da5A2700e7d91cb50aEf522D0C6Fe8",
      value: parseEther("0.000001"),
      data: "0x",
    },
    // Call a contract
    {
      to: "0x1234567890123456789012345678901234567890",
      value: 0n,
      data: "0xabcdef...", // encoded function call
    },
  ],
});

Gas Sponsorship with Paymaster

const result = await smartAccount.sendUserOperation({
  network: "base-sepolia",
  calls: [...],
  paymasterUrl: "https://paymaster.example.com",
});

Build docs developers (and LLMs) love