Skip to main content

Create an account management Snap

Create an account management Snap to connect to custom EVM accounts.

Prerequisites

Steps

1. Install the Keyring API

Install the @metamask/keyring-api module in your project directory using Yarn or npm:

yarn add @metamask/keyring-api

or

npm install @metamask/keyring-api

2. Add permissions

Specify the following permissions in your Snap manifest file:

snap.manifest.json
"initialPermissions": {
"endowment:keyring": {
"allowedOrigins": [
"https://<dapp domain>"
]
},
"endowment:rpc": {
"dapps": true
},
"snap_manageAccounts": {},
"snap_manageState": {}
},

Add a list of dapp URLs allowed to call Keyring API methods on your Snap using the endowment:keyring permission.

3. Implement the Account Management API

Implement the Account Management API in your Snap. Make sure to limit the methods exposed to dapps.

class MySnapKeyring implements Keyring {
// Implement the required methods here.
}

4. Handle requests submitted by MetaMask

MetaMask submits EVM requests from dapps using the keyring_submitRequest method of the Keyring API. See the EVM methods for externally owned accounts and ERC-4337 accounts.

The following is an example of a personal_sign request:

{
"id": "d6e23af6-4bea-48dd-aeb0-7d3c30ea67f9",
"scope": "",
"account": "69438371-bef3-4957-9f91-c3f22c1d75f3",
"request": {
"method": "personal_sign",
"params": [
"0x4578616d706c652060706572736f6e616c5f7369676e60206d657373616765",
"0x5874174dcf1ab6F7Efd8496f4f09404CD1c5bA84"
]
}
}

The request includes:

  • id - The unique identifier for the request.
  • scope - The CAIP-2 chain ID of the selected chain. Currently, this property is always an empty string. Your Snap should use the chain ID present in the request object instead.
  • account - The ID of the account that should handle the request.
  • request - The request object.

Your Snap must respond with either a synchronous or asynchronous result:

return { pending: false, result }

5. Notify MetaMask about events

Notify MetaMask when Account Management API events take place, using the emitSnapKeyringEvent() helper function.

For example, when an account is created:

try {
emitSnapKeyringEvent(snap, KeyringEvent.AccountCreated, { account })
// Update your Snap's state.
} catch (error) {
// Handle the error.
}

MetaMask returns an error if the account already exists or the account object is invalid.

6. Expose the Account Management API

Create an onKeyringRequest entry point handler method to expose the Account Management API methods to MetaMask and your dapp:

export const onKeyringRequest: OnKeyringRequestHandler = async ({
origin,
request,
}) => {
// Add custom logic here.
return handleKeyringRequest(keyring, request)
}

7. Create a companion dapp

Create a companion dapp to provide a user interface for your account management Snap, enabling them to create and interact with custom EVM accounts.

Example

See the example account management Snap source code for more information.