From 0e7a02755750d092db59ff78523fedc412e35901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CAyushBherwani1998=E2=80=9D?= <“ayush.bherwani1998@gmail.com”> Date: Wed, 3 Sep 2025 10:56:10 +0530 Subject: [PATCH 1/6] add deploy smart account guide --- .../smart-accounts/create-smart-account.md | 2 +- .../smart-accounts/deploy-smart-account.md | 160 ++++++++++++++++++ .../smart-accounts/send-user-operation.md | 2 +- gator-sidebar.js | 1 + .../how-to/send-user-operation.md | 2 +- .../how-to/send-user-operation.md | 2 +- .../how-to/send-user-operation.md | 2 +- .../how-to/send-user-operation.md | 2 +- 8 files changed, 167 insertions(+), 6 deletions(-) create mode 100644 delegation-toolkit/guides/smart-accounts/deploy-smart-account.md diff --git a/delegation-toolkit/guides/smart-accounts/create-smart-account.md b/delegation-toolkit/guides/smart-accounts/create-smart-account.md index 9d9468b30c4..df2eca55cc7 100644 --- a/delegation-toolkit/guides/smart-accounts/create-smart-account.md +++ b/delegation-toolkit/guides/smart-accounts/create-smart-account.md @@ -413,7 +413,7 @@ export const walletClient = createWalletClient({ With a MetaMask smart account, you can perform the following functions: -- In conjunction with [Viem Account Abstraction clients](../configure.md), deploy the smart account +- In conjunction with [Viem Account Abstraction clients](../configure.md), [deploy the smart account](deploy-smart-account.md) and [send user operations](send-user-operation.md). - [Create delegations](../delegation/execute-on-smart-accounts-behalf.md) that can be used to grant specific rights and permissions to other accounts. Smart accounts that create delegations are called *delegator accounts*. diff --git a/delegation-toolkit/guides/smart-accounts/deploy-smart-account.md b/delegation-toolkit/guides/smart-accounts/deploy-smart-account.md new file mode 100644 index 00000000000..88bbedff2c4 --- /dev/null +++ b/delegation-toolkit/guides/smart-accounts/deploy-smart-account.md @@ -0,0 +1,160 @@ +--- +description: Learn how to deploy a MetaMask smart account. +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +# Deploy a smart account + +You can deploy MetaMask Smart Accounts in two different ways. You can either deploy the smart account automatically when sending +the first user operation, or use a manual approach. + +## Prerequisites + +- [Install and set up the Delegation Toolkit.](../../get-started/install.md) +- [Configure the Delegation Toolkit.](../configure.md) +- [Create a MetaMask smart account](create-smart-account.md) + +## Sending first user operation + +Whenever you send the first user operation, it checks whether the smart account is already deployed. If the account +is not deployed, the `initCode` is added to the user operation to ensure the smart account is deployed within the +same operation. Internally, the `initCode` is encoded using the factory and factory data. + + + + +```typescript +import { bundlerClient, smartAccount } from "./config.ts"; +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 +}); +``` + + + + + +```typescript +import { createPublicClient, http } from "viem"; +import { createBundlerClient } from "viem/account-abstraction"; +import { sepolia as chain } from "viem/chains"; +import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; +import { + Implementation, + toMetaMaskSmartAccount, +} from "@metamask/delegation-toolkit"; + + +const publicClient = createPublicClient({ + chain, + transport: http() +}); + +const privateKey = generatePrivateKey(); +const account = privateKeyToAccount(privateKey); + +export const smartAccount = await toMetaMaskSmartAccount({ + client: publicClient, + implementation: Implementation.Hybrid, + deployParams: [account.address, [], [], []], + deploySalt: "0x", + signatory: { account }, +}); + +export const bundlerClient = createBundlerClient({ + client: publicClient, + transport: http("https://public.pimlico.io/v2/11155111/rpc") +}); +``` + + + + +## Manual approach + +To use the manual approach, you can call the MetaMask Smart Account [`getFactoryArgs`](../../reference/api/smart-account#getfactoryargs) +method to retrieve the `factory` and `factoryData`. This allows you to use a relay account to sponsor the deployment without needing a paymaster. + +The `factory` represents the contract address responsible for deploying the smart account, while `factoryData` contains the +calldata that will be executed by the `factory` to deploy the smart account. + +The relay account can be either an externally owned account (EOA) or another smart account. This example uses an EOA. + + + + +```typescript +import { walletClient, smartAccount } from "./config.ts"; + +const { factory, factoryData } = await smartAccount.getFactoryArgs(); + +// Deploy smart account using relay account. +const hash = await walletClient.sendTransaction({ + to: factory, + data: factoryData, +}) +``` + + + + + +```typescript +import { createPublicClient, createWalletClient, http } from "viem"; +import { sepolia as chain } from "viem/chains"; +import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"; +import { + Implementation, + toMetaMaskSmartAccount, +} from "@metamask/delegation-toolkit"; + + +const publicClient = createPublicClient({ + chain, + transport: http() +}); + +const privateKey = generatePrivateKey(); +const account = privateKeyToAccount(privateKey); + +export const smartAccount = await toMetaMaskSmartAccount({ + client: publicClient, + implementation: Implementation.Hybrid, + deployParams: [account.address, [], [], []], + deploySalt: "0x", + signatory: { account }, +}); + +const relayAccountPrivateKey = "0x121.."; +const relayAccount = privateKeyToAccount(relayAccountPrivateKey) + +export const walletClient = createWalletClient({ + account: relayAccount, + chain, + transport: http() +}) +``` + + + + +## Next steps + +- See [Send a user operation](send-user-operation.md) to learn how to send user operations. +- See [Send a gasless transaction](send-gasless-transaction.md) to learn how to use gasless paymaster. \ No newline at end of file diff --git a/delegation-toolkit/guides/smart-accounts/send-user-operation.md b/delegation-toolkit/guides/smart-accounts/send-user-operation.md index 767685d1403..28b00b22b6c 100644 --- a/delegation-toolkit/guides/smart-accounts/send-user-operation.md +++ b/delegation-toolkit/guides/smart-accounts/send-user-operation.md @@ -93,7 +93,7 @@ export const smartAccount = await toMetaMaskSmartAccount({ export const bundlerClient = createBundlerClient({ client: publicClient, - transport: http("https://public.pimlico.io/v2/1/rpc") + transport: http("https://public.pimlico.io/v2/11155111/rpc") }); ``` diff --git a/gator-sidebar.js b/gator-sidebar.js index 879740e6dcb..3dfcc3f8025 100644 --- a/gator-sidebar.js +++ b/gator-sidebar.js @@ -58,6 +58,7 @@ const sidebar = { collapsed: false, items: [ 'guides/smart-accounts/create-smart-account', + 'guides/smart-accounts/deploy-smart-account', 'guides/smart-accounts/send-user-operation', 'guides/smart-accounts/send-gasless-transaction', 'guides/smart-accounts/generate-multisig-signature', diff --git a/gator_versioned_docs/version-0.10.1/how-to/send-user-operation.md b/gator_versioned_docs/version-0.10.1/how-to/send-user-operation.md index dfeafe19d78..861b791be48 100644 --- a/gator_versioned_docs/version-0.10.1/how-to/send-user-operation.md +++ b/gator_versioned_docs/version-0.10.1/how-to/send-user-operation.md @@ -91,7 +91,7 @@ export const smartAccount = await toMetaMaskSmartAccount({ export const bundlerClient = createBundlerClient({ publicClient, - transport: http("https://public.pimlico.io/v2/1/rpc") + transport: http("https://public.pimlico.io/v2/11155111/rpc") }); ``` diff --git a/gator_versioned_docs/version-0.10.2/how-to/send-user-operation.md b/gator_versioned_docs/version-0.10.2/how-to/send-user-operation.md index dfeafe19d78..861b791be48 100644 --- a/gator_versioned_docs/version-0.10.2/how-to/send-user-operation.md +++ b/gator_versioned_docs/version-0.10.2/how-to/send-user-operation.md @@ -91,7 +91,7 @@ export const smartAccount = await toMetaMaskSmartAccount({ export const bundlerClient = createBundlerClient({ publicClient, - transport: http("https://public.pimlico.io/v2/1/rpc") + transport: http("https://public.pimlico.io/v2/11155111/rpc") }); ``` diff --git a/gator_versioned_docs/version-0.11.0/how-to/send-user-operation.md b/gator_versioned_docs/version-0.11.0/how-to/send-user-operation.md index 99ba5c6064a..58453c59164 100644 --- a/gator_versioned_docs/version-0.11.0/how-to/send-user-operation.md +++ b/gator_versioned_docs/version-0.11.0/how-to/send-user-operation.md @@ -94,7 +94,7 @@ export const smartAccount = await toMetaMaskSmartAccount({ export const bundlerClient = createBundlerClient({ client: publicClient, - transport: http("https://public.pimlico.io/v2/1/rpc") + transport: http("https://public.pimlico.io/v2/11155111/rpc") }); ``` diff --git a/gator_versioned_docs/version-0.12.0/how-to/send-user-operation.md b/gator_versioned_docs/version-0.12.0/how-to/send-user-operation.md index 343580b956e..d0b97800aa6 100644 --- a/gator_versioned_docs/version-0.12.0/how-to/send-user-operation.md +++ b/gator_versioned_docs/version-0.12.0/how-to/send-user-operation.md @@ -94,7 +94,7 @@ export const smartAccount = await toMetaMaskSmartAccount({ export const bundlerClient = createBundlerClient({ client: publicClient, - transport: http("https://public.pimlico.io/v2/1/rpc") + transport: http("https://public.pimlico.io/v2/11155111/rpc") }); ``` From d8520306e430febf2d4fcf7a077668d27dad168f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CAyushBherwani1998=E2=80=9D?= <“ayush.bherwani1998@gmail.com”> Date: Wed, 3 Sep 2025 11:15:18 +0530 Subject: [PATCH 2/6] update lineaSepolia to sepolia --- .../version-0.10.1/how-to/send-user-operation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gator_versioned_docs/version-0.10.1/how-to/send-user-operation.md b/gator_versioned_docs/version-0.10.1/how-to/send-user-operation.md index 861b791be48..7f9e610585d 100644 --- a/gator_versioned_docs/version-0.10.1/how-to/send-user-operation.md +++ b/gator_versioned_docs/version-0.10.1/how-to/send-user-operation.md @@ -67,7 +67,7 @@ const userOperationHash = await bundlerClient.sendUserOperation({ ```typescript import { createPublicClient, http } from "viem"; import { createBundlerClient } from "viem/account-abstraction"; -import { lineaSepolia as chain } from "viem/chains"; +import { sepolia as chain } from "viem/chains"; import { Implementation, toMetaMaskSmartAccount, From 2b33b340778825a84fad69e4244cafda5f67218a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CAyushBherwani1998=E2=80=9D?= <“ayush.bherwani1998@gmail.com”> Date: Wed, 3 Sep 2025 11:17:44 +0530 Subject: [PATCH 3/6] resolve cursor bot comments --- .../version-0.10.1/how-to/send-user-operation.md | 2 +- .../version-0.10.2/how-to/send-user-operation.md | 2 +- .../version-0.11.0/how-to/send-user-operation.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gator_versioned_docs/version-0.10.1/how-to/send-user-operation.md b/gator_versioned_docs/version-0.10.1/how-to/send-user-operation.md index 7f9e610585d..67e84e52d4b 100644 --- a/gator_versioned_docs/version-0.10.1/how-to/send-user-operation.md +++ b/gator_versioned_docs/version-0.10.1/how-to/send-user-operation.md @@ -91,7 +91,7 @@ export const smartAccount = await toMetaMaskSmartAccount({ export const bundlerClient = createBundlerClient({ publicClient, - transport: http("https://public.pimlico.io/v2/11155111/rpc") + transport: http("https://public.pimlico.io/v2/59141/rpc") }); ``` diff --git a/gator_versioned_docs/version-0.10.2/how-to/send-user-operation.md b/gator_versioned_docs/version-0.10.2/how-to/send-user-operation.md index 861b791be48..b2d02f882e9 100644 --- a/gator_versioned_docs/version-0.10.2/how-to/send-user-operation.md +++ b/gator_versioned_docs/version-0.10.2/how-to/send-user-operation.md @@ -91,7 +91,7 @@ export const smartAccount = await toMetaMaskSmartAccount({ export const bundlerClient = createBundlerClient({ publicClient, - transport: http("https://public.pimlico.io/v2/11155111/rpc") + transport: http("https://public.pimlico.io/v2/59141/rpc") }); ``` diff --git a/gator_versioned_docs/version-0.11.0/how-to/send-user-operation.md b/gator_versioned_docs/version-0.11.0/how-to/send-user-operation.md index 58453c59164..5027f60c12d 100644 --- a/gator_versioned_docs/version-0.11.0/how-to/send-user-operation.md +++ b/gator_versioned_docs/version-0.11.0/how-to/send-user-operation.md @@ -94,7 +94,7 @@ export const smartAccount = await toMetaMaskSmartAccount({ export const bundlerClient = createBundlerClient({ client: publicClient, - transport: http("https://public.pimlico.io/v2/11155111/rpc") + transport: http("https://public.pimlico.io/v2/59141/rpc") }); ``` From 16342ec9d019aeaad60b3528a2d70d3aa033f8b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CAyushBherwani1998=E2=80=9D?= <“ayush.bherwani1998@gmail.com”> Date: Wed, 3 Sep 2025 11:40:29 +0530 Subject: [PATCH 4/6] revert sepolia change --- .../version-0.10.1/how-to/send-user-operation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gator_versioned_docs/version-0.10.1/how-to/send-user-operation.md b/gator_versioned_docs/version-0.10.1/how-to/send-user-operation.md index 67e84e52d4b..b2d02f882e9 100644 --- a/gator_versioned_docs/version-0.10.1/how-to/send-user-operation.md +++ b/gator_versioned_docs/version-0.10.1/how-to/send-user-operation.md @@ -67,7 +67,7 @@ const userOperationHash = await bundlerClient.sendUserOperation({ ```typescript import { createPublicClient, http } from "viem"; import { createBundlerClient } from "viem/account-abstraction"; -import { sepolia as chain } from "viem/chains"; +import { lineaSepolia as chain } from "viem/chains"; import { Implementation, toMetaMaskSmartAccount, From 94fa0eb0cddec9abd8b2bee614e0e5cd9bd6b57c Mon Sep 17 00:00:00 2001 From: Ayush Bherwani Date: Thu, 4 Sep 2025 10:53:06 +0530 Subject: [PATCH 5/6] Apply suggestions from code review Co-authored-by: Alexandra Carrillo <12214231+alexandratran@users.noreply.github.com> --- .../smart-accounts/deploy-smart-account.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/delegation-toolkit/guides/smart-accounts/deploy-smart-account.md b/delegation-toolkit/guides/smart-accounts/deploy-smart-account.md index 88bbedff2c4..a62c0ab74ad 100644 --- a/delegation-toolkit/guides/smart-accounts/deploy-smart-account.md +++ b/delegation-toolkit/guides/smart-accounts/deploy-smart-account.md @@ -7,20 +7,20 @@ import TabItem from "@theme/TabItem"; # Deploy a smart account -You can deploy MetaMask Smart Accounts in two different ways. You can either deploy the smart account automatically when sending -the first user operation, or use a manual approach. +You can deploy MetaMask Smart Accounts in two different ways. You can either deploy a smart account automatically when sending +the first user operation, or manually deploy the account. ## Prerequisites - [Install and set up the Delegation Toolkit.](../../get-started/install.md) - [Configure the Delegation Toolkit.](../configure.md) -- [Create a MetaMask smart account](create-smart-account.md) +- [Create a MetaMask smart account.](create-smart-account.md) -## Sending first user operation +## Deploy with the first user operation -Whenever you send the first user operation, it checks whether the smart account is already deployed. If the account -is not deployed, the `initCode` is added to the user operation to ensure the smart account is deployed within the -same operation. Internally, the `initCode` is encoded using the factory and factory data. +When you send the first user operation from a smart account, the Delegation Toolkit checks whether the account is already deployed. If the account +is not deployed, the toolkit adds the `initCode` to the user operation to deploy the account within the +same operation. Internally, the `initCode` is encoded using the `factory` and `factoryData`. @@ -86,10 +86,10 @@ export const bundlerClient = createBundlerClient({ -## Manual approach +## Deploy manually -To use the manual approach, you can call the MetaMask Smart Account [`getFactoryArgs`](../../reference/api/smart-account#getfactoryargs) -method to retrieve the `factory` and `factoryData`. This allows you to use a relay account to sponsor the deployment without needing a paymaster. +To deploy a smart account manually, call the [`getFactoryArgs`](../../reference/api/smart-account.md#getfactoryargs) +method from the smart account to retrieve the `factory` and `factoryData`. This allows you to use a relay account to sponsor the deployment without needing a paymaster. The `factory` represents the contract address responsible for deploying the smart account, while `factoryData` contains the calldata that will be executed by the `factory` to deploy the smart account. From 402922637e5f4b0a3bacb1f25b2e0420ad92e6e0 Mon Sep 17 00:00:00 2001 From: Ayush Bherwani Date: Thu, 4 Sep 2025 11:02:48 +0530 Subject: [PATCH 6/6] Accept review suggestions Co-authored-by: Alexandra Carrillo <12214231+alexandratran@users.noreply.github.com> --- .../guides/smart-accounts/deploy-smart-account.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/delegation-toolkit/guides/smart-accounts/deploy-smart-account.md b/delegation-toolkit/guides/smart-accounts/deploy-smart-account.md index a62c0ab74ad..23e8b70ceab 100644 --- a/delegation-toolkit/guides/smart-accounts/deploy-smart-account.md +++ b/delegation-toolkit/guides/smart-accounts/deploy-smart-account.md @@ -156,5 +156,5 @@ export const walletClient = createWalletClient({ ## Next steps -- See [Send a user operation](send-user-operation.md) to learn how to send user operations. -- See [Send a gasless transaction](send-gasless-transaction.md) to learn how to use gasless paymaster. \ No newline at end of file +- Learn more about [sending user operations](send-user-operation.md). +- To sponsor gas for end users, see how to [send a gasless transaction](send-gasless-transaction.md). \ No newline at end of file