Skip to main content

Snaps documentation

Create a custom mini app that runs inside the MetaMask extension.

Custom EVM accounts

The Keyring API integrates custom EVM accounts inside MetaMask. You can use the Keyring API to display custom accounts, such as multi-party computation (MPC) accounts and ERC-4337 accounts, alongside regular MetaMask accounts in the user interface:

Account management Snap accounts in MetaMask UI

To use the Keyring API, you first implement the API in an account management Snap (also known as an "account Snap"). You can then call Keyring API methods from a companion dapp to enable users to create and interact with the custom accounts.

System context diagram

The following diagram shows the system context when interacting with accounts managed by an account management Snap:

Use to submit requests
and manage accounts

Start requests

Use to manage
requests and accounts

Submit requests

Manage requests
and accounts

Submit requests and
manage accounts

Notify about account
and request events

User

MetaMask

Dapp

Snap companion dapp

Snap

The diagram contains the following components:

  • User - The user interacting with the dapp, the Snap companion dapp, and MetaMask.
  • Dapp - The dapp requesting an action to be performed on an account.
  • MetaMask - The wallet the dapp connects to. MetaMask routes requests to the account management Snap and lets the user perform some level of account management.
  • Snap - The account management Snap that implements the Keyring API to manage the user's accounts and handle requests that use these accounts.
  • Snap companion dapp - The Snap's user interface component that allows the user to interact with the Snap to manage accounts and requests.

Account management Snap installation flow

The first process a user encounters when using an account management Snap is the Snap installation flow. This process can be initiated through MetaMask's or the Snap companion dapp. The flow looks like the following:

Snap companion dappSnapMetaMaskSnap companion dappSnapMetaMaskalt[Optional]UserAdd account Snap1Display suggested Snaps2Select Snap3Open in a new tab4Install Snap?5Display permissions dialog6Approve permissions7OK8User

The MetaMask account selection modal has an option called Add account Snap. This option shows a list of account management Snaps. Each Snap redirects the user to the companion dapp that contains the user interface to configure and manage the Snap.

Custom account creation flow

Once the account management Snap is installed, the user can use the Snap companion dapp to create or import custom accounts. The flow looks like the following:

Snap companion dappSnapMetaMaskSnap companion dappSnapMetaMaskUserCreate new account1Custom logic to createaccount2keyring_createAccount(options)3Custom logic to createaccount4snap_manageAccounts("notify:accountCreated", account)5Approve account creation6OK7OK8Done9User

The companion dapp presents a user interface allowing the user to configure their custom account. The dapp creates an account using keyring_createAccount.

The Snap keeps track of the accounts that it creates using snap_manageState. Once the Snap has created an account, it notifies MetaMask using snap_manageAccounts.

Once the Snap has created an account, that account can be used to sign messages and transactions.

Transaction flows

The Keyring API supports two flows for handling requests: synchronous and asynchronous.

In general, you should use the asynchronous flow when the request requires user interaction (for example, using a hardware key or a threshold signature scheme) or when the request takes a long time to complete. You should use the synchronous flow for any other use case.

Synchronous transaction flow

The synchronous flow looks like the following:

SnapMetaMaskDappSnapMetaMaskDappUserCreate new sign request1ethereum.request(request)2Display request to user3Approve request4keyring_submitRequest(request)5Custom logic to handlerequest6{ pending: false, result }7result8Done9User

The flow starts when a user or dapp initiates a sign request. At that point, MetaMask detects that this interaction is requested for an account controlled by the account management Snap.

After the user approves the transaction in MetaMask, MetaMask calls keyring_submitRequest, which receives the original RPC request and returns a response with pending set to false, and result set to the requested signature.

Asynchronous transaction flow

The asynchronous flow looks like the following:

Snap companion dappSnapMetaMaskDappSnap companion dappSnapMetaMaskDappalt[There is a redirect URL]UserCreate new sign request1ethereum.request(request)2Display request to user3Approve request4keyring_submitRequest(request)5Save request to Snap'sstate6{ pending: true, redirect? }7Acknowledge redirection8Open redirect URL in a new tab9keyring_getRequest(id)10request11Custom logic to handlerequest12keyring_approveRequest(id,data?)13Custom logic to handlerequest14snap_manageAccounts("notify:requestApproved", { id, result })15result16OK17OK18Done19User

The flow starts the same way as the synchronous flow: a user or dapp initiates a sign request. After approval, MetaMask calls keyring_submitRequest.

Since the Snap doesn't answer the request directly, it stores the pending request in its internal state using snap_manageState. The Snap sends a { pending: true, redirect? } response to indicate that the request will be handled asynchronously. This response can optionally contain a redirect URL that MetaMask will open in a new tab to allow the user to interact with the Snap companion dapp.

The companion dapp gets the Snap's pending request using keyring_getRequest. It resolves the request using keyring_approveRequest, and the Snap resolves the request using snap_manageAccounts, notifying MetaMask of the result.

EOA methods

An account management Snap can implement the following methods to support dapp requests from externally owned accounts (EOAs):

Account abstraction (ERC-4337)

Flask Only
This feature is experimental and only available in MetaMask Flask, the canary distribution of MetaMask.

Account abstraction, specified by EIP-4337, introduces user operations and enables users to manage smart contract accounts containing arbitrary verification logic. Users can use these ERC-4337 accounts instead of externally owned accounts as primary accounts.

An account management Snap can implement the following methods to support dapp requests from ERC-4337 accounts:

The user operation signing flow in an ERC-4337 compatible account Snap looks like the following:

SnapMetaMaskDappSnapMetaMaskDappCurrently, only one transaction peruserOp is supportedalt[The account is already deployed][The account is not deployed and theinitCode is not present]alt[The gas isn't set]Transaction intents1eth_prepareUserOperation(transaction intents)2userOp details3Check if account is already deployed4Remove the initCode if set5Throw an error (without the exact reason)6Estimate and set gas values7Estimate and set gas fees8eth_patchUserOperation(userOp object)9Partial userOp object10Update paymasterAndData andremove dummy signature11eth_signUserOperation(userOp object, entrypoint)12Signature13Update userOp's signature14Submit userOp to bundler and waitfor transaction hash15Transaction hash16

See the ERC-4337 methods for more information about their parameters and response details.

Examples

See the following example account management Snap implementations: