Skip to main content

Delegation Toolkit documentation

Embed MetaMask smart accounts into your dapp, enabling new user experiences.

MetaMask Smart Accounts quickstart

This page demonstrates how to get started quickly with the MetaMask Smart Accounts, and send the first user operation.

Prerequisites

Install and set up the Delegation Toolkit.

Steps

1. 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(),
})

2. 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'),
})

3. Create a MetaMask smart account

Create a MetaMask smart account to send first user operation.

This example configures a Hybrid smart account:

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 },
})

4. Send a user operation

Send a user operation using Viem's sendUserOperation method.

See send 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,
})