Skip to main content

About the Keyring API

Flask Only
This feature is only available in MetaMask Flask, the canary distribution of MetaMask.
API documentation

See the Keyring API reference for all the Keyring API methods.

The Snaps Keyring API integrates custom EVM accounts inside MetaMask. Previously, you needed a companion dapp to display custom EVM accounts, such multi-party computation (MPC) accounts. Now you can display these custom accounts alongside regular MetaMask accounts in the UI:

Keyring Snap accounts in Metamask UI

Create a Keyring Snap to integrate custom EVM accounts in MetaMask. Your dapp can then use the eth_requestAccounts MetaMask JSON-RPC API method to connect to the custom accounts, and seamlessly interact with them using other JSON-RPC methods.

Terminology

The following terminology is used across the Keyring API:

  • Blockchain account: An object in a single blockchain, representing an account, with its balance, nonce, and other account details.
  • Request: A request from a dapp to MetaMask.
  • Keyring account: An account model that represents one or more blockchain accounts.
  • Keyring Snap: A Snap that implements the Keyring API.
  • Keyring request: A request from MetaMask to a Keyring Snap. MetaMask wraps the original request sent by the dapp and adds some metadata to it.

Components diagram

The following diagram shows the components you encounter when interacting with accounts managed by a Keyring Snap:

  • User: The user interacting with the Snap, the 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 Keyring Snaps and lets the user perform some level of account management.
  • Snap: A Snap that implements the Keyring API to manage the user's accounts, and to handle requests that use these accounts.
  • Snap UI: The Snap's UI component that allows the user to interact with the Snap to perform custom operations on accounts and requests.

Keyring interface

The first step to create a Keyring Snap is to implement the Keyring interface. This interface describes all the methods necessary to make your custom EVM accounts work inside MetaMask with your own logic.

The following sections describe the different flows that the Keyring interface handles.

Snap account creation flow

The first interaction between users and the Keyring Snap is the Snap account creation process. The flow looks like the following:

The MetaMask account selection modal has an option called Add Snap account:

Add Snap account option

This option shows a list of Keyring Snaps. Each Snap redirects the user to the companion dapp that contains all the UI to configure and manage the Snap.

The dapp presents a custom UI allowing the user to configure their custom EVM account. The dapp uses the createAccount method of the KeyringSnapRpcClient, which calls the Keyring interface's method of the same name. You can find an example of this in the example Keyring Snap companion dapp.

The createAccount method of the Keyring interface creates the account based on the parameters passed to the method. The Snap keeps track of the accounts that it creates using snap_manageState. Once the Snap has created an account, it notifies MetaMask using the createAccount sub-method of snap_manageAccounts. You can find an example of this process in the example companion dapp.

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

Synchronous signing flow

If the Keyring Snap can sign transactions directly, it implements a simple synchronous signing flow. If the Snap needs a third party such as a hardware key or a second account's signature (for example, in a threshold signature scheme), it implements an asynchronous signing flow. The synchronous flow looks like the following:

See the example Keyring Snap companion dapp for a full example.

The flow starts when a dapp calls a MetaMask JSON-RPC method, or when the user initiates a new funds transfer from the MetaMask UI. At that point, MetaMask detects that this interaction is requested for an account controlled by the Keyring Snap.

After the user approves the transaction in the UI, MetaMask calls the submitRequest method of the Keyring interface. submitRequest receives the original RPC request, and returns a SubmitRequestResponse with pending set to false, and result set to the requested signature.

important

If the Keyring Snap receives an eth_sendTransaction request, it should treat it like an eth_signTransaction request. That is, the Snap is responsible for providing the signature in the response, and MetaMask is responsible for broadcasting the transaction.

Asynchronous signing flow

If the Keyring Snap implements a complex scheme such as threshold signing, it implements an asynchronous signing flow with more Keyring methods. The asynchronous flow looks like the following:

The flow starts the same way as the synchronous flow: a dapp or user initiates a request to sign a transaction or arbitrary data. After approval, the submitRequest method of the Snap's Keyring interface is called.

Since the Snap doesn't answer the request directly, it stores the pending request in its internal state using snap_manageState. This list of pending requests is returned when the listRequests or getRequest methods of the Keyring interface are called.

After storing the pending request, the Snap creates a pop-up using snap_dialog instructing the user to go to the companion dapp's URL.

The dapp lists the Snap's pending requests using an RPC call facilitated by the listRequests method of the KeyringSnapRpcClient. The user can then act on those requests using whatever process applies to the Snap.

Once the signing process completes, the companion dapp resolves the request using the approveRequest method of the KeyringSnapRpcClient, which calls the Keyring interface's method of the same name. This method receives the request's ID and final result.

When approveRequest is called, it can resolve the pending request by using the submitResponse sub-method of snap_manageAccounts.