Skip to main content

MetaMask Smart Accounts quickstart

You can get started quickly with MetaMask Smart Accounts by creating your first smart account and sending a user operation.

Prerequisites

  • Install Node.js v18 or later.
  • Install Yarn, npm, or another package manager.

Steps

1. Install the toolkit

Install the MetaMask Delegation Toolkit:

npm install @metamask/delegation-toolkit

2. Set up a Public Client

Set up a Viem Public Client using Viem's createPublicClient function. This client will let the smart account query the signer's account state and interact with blockchain network.

import { createPublicClient, http } from "viem";
import { sepolia as chain } from "viem/chains";

const publicClient = createPublicClient({
chain,
transport: http(),
});

3. Set up a Bundler Client

Set up a Viem Bundler Client using Viem's createBundlerClient function. This lets you use the bundler service to estimate gas for user operations and submit transactions to the network.

import { createBundlerClient } from "viem/account-abstraction";

const bundlerClient = createBundlerClient({
client: publicClient,
transport: http("https://your-bundler-rpc.com"),
});

4. Create a MetaMask smart account

Create a MetaMask smart account to send the first user operation.

This example configures a Hybrid smart account, which is a flexible smart account implementation that supports both an externally owned account (EOA) owner and any number of passkey (WebAuthn) signers:

import { Implementation, toMetaMaskSmartAccount } from "@metamask/delegation-toolkit";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount("0x...");

const smartAccount = await toMetaMaskSmartAccount({
client: publicClient,
implementation: Implementation.Hybrid,
deployParams: [account.address, [], [], []],
deploySalt: "0x",
signatory: { account },
});

5. Send a user operation

Send a user operation using Viem's sendUserOperation method.

See Send a user operation to learn how to estimate fee per gas, and wait for the transaction receipt.

The smart account will remain counterfactual until the first user operation. If the smart account is not deployed, it will be automatically deployed upon the sending first user operation.

import { parseEther } from "viem";

// Appropriate fee per gas must be determined for the specific bundler being used.
const maxFeePerGas = 1n;
const maxPriorityFeePerGas = 1n;

const userOperationHash = await bundlerClient.sendUserOperation({
account: smartAccount,
calls: [
{
to: "0x1234567890123456789012345678901234567890",
value: parseEther("1"),
},
],
maxFeePerGas,
maxPriorityFeePerGas,
});

Next steps