> For the complete documentation index, see [llms.txt](/llms.txt).

# Create an account management Snap

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

see also

- [Custom EVM accounts](/snaps/features/custom-evm-accounts/)
- [Create an account management companion dapp](/snaps/features/custom-evm-accounts/create-companion-dapp/)
- [Account management Snap security guidelines](/snaps/features/custom-evm-accounts/security/)
- [Keyring API reference](/snaps/reference/keyring-api/)

## Prerequisites[​](#prerequisites "Direct link to Prerequisites")

- Set up a Snap. See the [Snaps quickstart](/snaps/get-started/quickstart/) and [how to develop a Snap](/snaps/how-to/publish-a-snap/).
- Read the [account management Snap security guidelines](/snaps/features/custom-evm-accounts/security/).

## Steps[​](#steps "Direct link to Steps")

### 1. Install the Keyring API[​](#1-install-the-keyring-api "Direct link to 1. Install the Keyring API")

Install the [@metamask/keyring-api](https://github.com/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[​](#2-add-permissions "Direct link to 2. Add permissions")

Specify the following [permissions](/snaps/how-to/request-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](/snaps/reference/permissions/#endowmentkeyring) permission.

### 3. Implement the Account Management API[​](#3-implement-the-account-management-api "Direct link to 3. Implement the Account Management API")

Implement the [Account Management API](/snaps/reference/keyring-api/account-management/) in your Snap. Make sure to [limit the methods exposed to dapps](/snaps/features/custom-evm-accounts/security/#limit-the-methods-exposed-to-dapps).

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

```

### 4. Handle requests submitted by MetaMask[​](#4-handle-requests-submitted-by-metamask "Direct link to 4. Handle requests submitted by MetaMask")

MetaMask submits EVM requests from dapps using the [keyring_submitRequest](/snaps/reference/keyring-api/account-management/#keyring%5Fsubmitrequest)method of the Keyring API. See the EVM methods for [externally owned accounts](/snaps/reference/keyring-api/chain-methods/#eoa-methods)and [ERC-4337 accounts](/snaps/reference/keyring-api/chain-methods/#erc-4337-methods).

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:

- Synchronous
- Asynchronous

```
return { pending: false, result }

```

```
return { pending: true, redirect: { message, url } }

```

The redirect message and URL are displayed to the user to help them continue the transaction flow.

### 5. Notify MetaMask about events[​](#5-notify-metamask-about-events "Direct link to 5. Notify MetaMask about events")

Notify MetaMask when [Account Management API events](/snaps/reference/keyring-api/account-management/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[​](#6-expose-the-account-management-api "Direct link to 6. Expose the Account Management API")

Create an [onKeyringRequest](/snaps/reference/entry-points/#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[​](#7-create-a-companion-dapp "Direct link to 7. Create a companion dapp")

[Create a companion dapp](/snaps/features/custom-evm-accounts/create-companion-dapp/) to provide a user interface for your account management Snap, enabling them to create and interact with custom EVM accounts.

## Example[​](#example "Direct link to Example")

See the [example account management Snap source code](https://github.com/MetaMask/snap-simple-keyring/tree/main/packages/snap)for more information.
