Skip to content

[Delegation Toolkit] Add MetaMask Smart Accounts quickstart #2132

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion delegation-toolkit/get-started/cli-quickstart.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Get started with the MetaMask Delegation Toolkit using the `@metamask/create-gator-app` CLI.
sidebar_position: 4
sidebar_position: 5
sidebar_label: CLI quickstart
---

Expand Down
156 changes: 156 additions & 0 deletions delegation-toolkit/get-started/delegation-quickstart.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
---
description: Get started quickly with the MetaMask Delegation Toolkit.
sidebar_position: 3
sidebar_label: Delegation quickstart
---

# Delegation Toolkit quickstart

This page demonstrates how to get started quickly with the MetaMask Delegation Toolkit, by creating a delegator account and completing the delegation lifecycle (creating, signing, and redeeming a delegation).

## Prerequisites

[Install and set up the Delegation Toolkit.](install.md)

## Steps

### 1. Set up a Public Client

Set up a [Viem Public Client](https://viem.sh/docs/clients/public) using Viem's `createPublicClient` function. This client will let the delegator account query the signer's account state and interact with smart contracts.

```typescript
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](https://viem.sh/account-abstraction/clients/bundler) using Viem's `createBundlerClient` function. This lets you use the bundler service to estimate gas for user operations and submit transactions to the network.

```typescript
import { createBundlerClient } from 'viem/account-abstraction'

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

### 3. Create a delegator account

[Create a delegator smart account](../how-to/create-smart-account/index.md) to set up a delegation.

This example configures a [Hybrid](../how-to/create-smart-account/configure-accounts-signers.md#configure-a-hybrid-smart-account) delegator account:

```typescript
import { Implementation, toMetaMaskSmartAccount } from '@metamask/delegation-toolkit'
import { privateKeyToAccount } from 'viem/accounts'

const delegatorAccount = privateKeyToAccount('0x...')

const delegatorSmartAccount = await toMetaMaskSmartAccount({
client: publicClient,
implementation: Implementation.Hybrid,
deployParams: [delegatorAccount.address, [], [], []],
deploySalt: '0x',
signatory: { account: delegatorAccount },
})
```

### 4. Create a delegate account

Create a delegate account to receive the delegation. The delegate can be either a smart account or an externally owned account (EOA).

This example uses a smart account:

```typescript
import { Implementation, toMetaMaskSmartAccount } from '@metamask/delegation-toolkit'
import { privateKeyToAccount } from 'viem/accounts'

const delegateAccount = privateKeyToAccount('0x...')

const delegateSmartAccount = await toMetaMaskSmartAccount({
client: publicClient,
implementation: Implementation.Hybrid,
deployParams: [delegateAccount.address, [], [], []],
deploySalt: '0x',
signatory: { account: delegateAccount },
})
```

### 5. Create a delegation

[Create a root delegation](../how-to/create-delegation/index.md#create-a-root-delegation) from the delegator account to the delegate account.

This example passes an empty `caveats` array, which means the delegate can perform any action on the delegator's behalf. We recommend [restricting the delegation](../how-to/create-delegation/restrict-delegation.md) by adding caveat enforcers.

:::warning Important

Before creating a delegation, ensure that the delegator account has been deployed. If the account is not deployed, redeeming the delegation will fail.

:::

```typescript
import { createDelegation } from '@metamask/delegation-toolkit'

const delegation = createDelegation({
to: delegateSmartAccount.address,
from: delegatorSmartAccount.address,
caveats: [], // Empty caveats array - we recommend adding appropriate restrictions.
})
```

### 6. Sign the delegation

[Sign the delegation](../how-to/create-delegation/index.md#sign-a-delegation) using the [`signDelegation`](../reference/api/smart-account.md#signdelegation) method from `MetaMaskSmartAccount`. Alternatively, you can use the Delegation Toolkit's [`signDelegation`](../reference/api/delegation.md#signdelegation) utility. The signed delegation will be used later to perform actions on behalf of the delegator.

```typescript
const signature = await delegatorSmartAccount.signDelegation({
delegation,
})

const signedDelegation = {
...delegation,
signature,
}
```

### 7. Redeem the delegation

The delegate account can now [redeem the delegation](../how-to/redeem-delegation.md). The redeem transaction is sent to the `DelegationManager` contract, which validates the delegation and executes actions on the delegator's behalf.

To prepare the calldata for the redeem transaction, use the [`redeemDelegation`](../reference/api/delegation.md#redeemdelegation) utility function from the Delegation Toolkit.

```typescript
import { createExecution } from '@metamask/delegation-toolkit'
import { DelegationManager } from '@metamask/delegation-toolkit/contracts'
import { SINGLE_DEFAULT_MODE } from '@metamask/delegation-toolkit/utils'
import { zeroAddress } from 'viem'

const delegations = [signedDelegation]

const executions = createExecution({ target: zeroAddress })

const redeemDelegationCalldata = DelegationManager.encode.redeemDelegations({
delegations: [delegations],
modes: [SINGLE_DEFAULT_MODE],
executions: [executions],
})

const userOperationHash = await bundlerClient.sendUserOperation({
account: delegateSmartAccount,
calls: [
{
to: delegateSmartAccount.address,
data: redeemDelegationCalldata,
},
],
maxFeePerGas: 1n,
maxPriorityFeePerGas: 1n,
})
```
2 changes: 1 addition & 1 deletion delegation-toolkit/get-started/eip7702-quickstart.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Upgrade an externally owned account (EOA) to a smart account
sidebar_position: 3
sidebar_position: 4
sidebar_label: EIP-7702 quickstart
---

Expand Down
163 changes: 41 additions & 122 deletions delegation-toolkit/get-started/quickstart.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
---
description: Get started quickly with the MetaMask Delegation Toolkit.
description: Get started quickly with the MetaMask Smart Accounts
sidebar_position: 2
sidebar_label: Quickstart
---

# Delegation Toolkit quickstart
# MetaMask Smart Accounts quickstart

This page demonstrates how to get started quickly with the MetaMask Delegation Toolkit,
by creating a delegator account and completing the delegation lifecycle (creating, signing, and redeeming a delegation).
This page demonstrates how to get started quickly with the MetaMask Smart Accounts, and send the first user operation.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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


## Prerequisites

Expand All @@ -17,157 +16,77 @@ by creating a delegator account and completing the delegation lifecycle (creatin

### 1. Set up a Public Client

Set up a [Viem Public Client](https://viem.sh/docs/clients/public) using Viem's `createPublicClient` function.
This client will let the delegator account query the signer's account state and interact with smart contracts.
Set up a [Viem Public Client](https://viem.sh/docs/clients/public) using Viem's `createPublicClient` function. This client will let the smart account query the signer's account state and interact with blockchain network.

```typescript
import { createPublicClient, http } from "viem";
import { sepolia as chain } from "viem/chains";
import { createPublicClient, http } from 'viem'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import { createPublicClient, http } from 'viem'
import { createPublicClient, http } from "viem"

We try to use double quotes consistently throughout the doc site. This applies to the rest of the code samples on this page.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's my habit of saving files frequently, and since Prettier is configured to use single quotes, it keeps formatting them that way. Maybe we should consider changing the config?

Prettier configuration: https://github.com/MetaMask/metamask-docs/blob/main/.prettierrc

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](https://viem.sh/account-abstraction/clients/bundler) using Viem's `createBundlerClient` function.
This lets you use the bundler service to estimate gas for user operations and submit transactions to the network.
Set up a [Viem Bundler Client](https://viem.sh/account-abstraction/clients/bundler) using Viem's `createBundlerClient` function. This lets you use the bundler service to estimate gas for user operations and submit transactions to the network.

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

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

### 3. Create a delegator account
### 3. Create a MetaMask smart account

[Create a delegator smart account](../how-to/create-smart-account/index.md) to set up a delegation.
[Create a MetaMask smart account](../how-to/create-smart-account/index.md) to send first user operation.
Copy link
Contributor

@alexandratran alexandratran Jul 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[Create a MetaMask smart account](../how-to/create-smart-account/index.md) to send first user operation.
[Create a MetaMask smart account](../how-to/create-smart-account/index.md) to send the first user operation.


This example configures a [Hybrid](../how-to/create-smart-account/configure-accounts-signers.md#configure-a-hybrid-smart-account) delegator account:
This example configures a [Hybrid](../how-to/create-smart-account/configure-accounts-signers.md#configure-a-hybrid-smart-account) smart account:

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

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

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

### 4. Create a delegate account

Create a delegate account to receive the delegation.
The delegate can be either a smart account or an externally owned account (EOA).

This example uses a smart account:

```typescript
import {
Implementation,
toMetaMaskSmartAccount,
} from "@metamask/delegation-toolkit";
import { privateKeyToAccount } from "viem/accounts";
### 4. Send a user operation

const delegateAccount = privateKeyToAccount("0x...");
Send a user operation using Viem's [`sendUserOperation`](https://viem.sh/account-abstraction/actions/bundler/sendUserOperation) method.

const delegateSmartAccount = await toMetaMaskSmartAccount({
client: publicClient,
implementation: Implementation.Hybrid,
deployParams: [delegateAccount.address, [], [], []],
deploySalt: "0x",
signatory: { account: delegateAccount },
});
```
See [send user operation](./../how-to/send-user-operation.md) to learn how to estimate fee per gas, and wait for the transaction receipt.

### 5. Create a delegation
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.

[Create a root delegation](../how-to/create-delegation/index.md#create-a-root-delegation) from the
delegator account to the delegate account.
```ts
import { parseEther } from 'viem'

This example passes an empty `caveats` array, which means the delegate can perform any action on the delegator's behalf.
We recommend [restricting the delegation](../how-to/create-delegation/restrict-delegation.md) by adding caveat enforcers.

:::warning Important

Before creating a delegation, ensure that the delegator account has
been deployed. If the account is not deployed, redeeming the delegation will fail.

:::

```typescript
import { createDelegation } from "@metamask/delegation-toolkit";

const delegation = createDelegation({
to: delegateSmartAccount.address,
from: delegatorSmartAccount.address,
caveats: [] // Empty caveats array - we recommend adding appropriate restrictions.
});
```

### 6. Sign the delegation

[Sign the delegation](../how-to/create-delegation/index.md#sign-a-delegation) using the [`signDelegation`](../reference/api/smart-account.md#signdelegation) method from `MetaMaskSmartAccount`.
Alternatively, you can use the Delegation Toolkit's [`signDelegation`](../reference/api/delegation.md#signdelegation) utility.
The signed delegation will be used later to perform actions on behalf of the delegator.

```typescript
const signature = await delegatorSmartAccount.signDelegation({
delegation
});

const signedDelegation = {
...delegation,
signature,
};
```

### 7. Redeem the delegation

The delegate account can now [redeem the delegation](../how-to/redeem-delegation.md).
The redeem transaction is sent to the `DelegationManager` contract, which validates the delegation and
executes actions on the delegator's behalf.

To prepare the calldata for the redeem transaction, use the [`redeemDelegation`](../reference/api/delegation.md#redeemdelegation) utility function from the Delegation Toolkit.

```typescript
import { createExecution } from "@metamask/delegation-toolkit";
import { DelegationManager } from "@metamask/delegation-toolkit/contracts";
import { SINGLE_DEFAULT_MODE } from "@metamask/delegation-toolkit/utils";
import { zeroAddress } from "viem";

const delegations = [ signedDelegation ];

const executions = createExecution({ target: zeroAddress });

const redeemDelegationCalldata = DelegationManager.encode.redeemDelegations({
delegations: [ delegations ],
modes: [ SINGLE_DEFAULT_MODE ],
executions: [ executions ]
});
// 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: delegateSmartAccount,
account: smartAccount,
calls: [
{
to: delegateSmartAccount.address,
data: redeemDelegationCalldata
}
to: '0x1234567890123456789012345678901234567890',
value: parseEther('1'),
},
],
maxFeePerGas: 1n,
maxPriorityFeePerGas: 1n,
});
```
maxFeePerGas,
maxPriorityFeePerGas,
})
```
2 changes: 1 addition & 1 deletion delegation-toolkit/get-started/supported-networks.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Supported networks
sidebar_label: Supported networks
description: Supported networks for Delegation Toolkit.
sidebar_position: 5
sidebar_position: 6
---

The following tables display the networks supported by each version of the MetaMask Delegation Toolkit.
Expand Down
Loading