# Keyring API Architecture
## Terminology
Let's introduce some terminology used across the Keyring API:
- **Blockchain account**: An object in a single blockchain, representing an
account, with its balance, nonce, etc.
- **Request**: A request sent by a dapp to MetaMask.
- **Keyring account**: Is an account model that represents one or more
blockchain accounts.
- **Account Snap**: A Snap that implements the Keyring API.
- **Keyring Snap**: Same as Account Snap.
- **Keyring request**: A request from MetaMask to an account Snap to perform an
action on, or using, a keyring account. It wraps the original request sent by
the dapp and adds some metadata to it.
## System context diagram
In most use cases, we will encounter the following systems when interacting
with an account managed by an account Snap:
```mermaid
graph TD
User -->|Uses to submit requests
and manage accounts| MetaMask
User -->|Starts requests| Dapp
User -->|Uses to manage
requests and accounts| Site
Dapp -->|Submits requests| MetaMask
Site[Snap Companion Dapp] -->|Manages requests
and accounts| MetaMask
MetaMask -->|Submits requests and
manages accounts| Snap
Snap -->|Notifies about account
and request events| MetaMask
```
- **User**: The web3 user interacting with the dapp, the Snap companion dapp,
and MetaMask.
- **Dapp**: The web3 application that is requesting an action to be performed
on an account.
- **MetaMask**: The web3 provider that dapps connect to. It routes requests to
the account 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 Companion Dapp**: The Snap's UI component that allows the user to
interact with the Snap to manage accounts and requests.
## Components diagram
This components diagram shows the internal components of MetaMask and **can be
ignored by account Snap developers.**
```mermaid
graph TD
Site[Snap Companion Dapp] ------>|Manages requests
and accounts| SnapController
User -->|Uses to submit requests
and manage accounts| UI
Dapp --->|Submits requests| TransactionsController
subgraph MetaMask
UI -->|Manages accounts| KeyringController
UI -->|Submits requests| TransactionsController
TransactionsController -->|Submits requests| KeyringController
KeyringController -->|Submits requests and
manages accounts| SnapKeyring
SnapKeyring -->|Submits requests and
manages accounts| SnapController
end
SnapController -->|Submits requests and
manages accounts| Snap
Snap -->|Notifies about account
and request events| SnapController
SnapController -->|Notifies about account
and request events| SnapKeyring
```
## Snap installation
The account creation flow is the initial process that a user will encounter
when using an account Snap. It can be initiated by the "Add account Snap"
button in MetaMask's accounts list or by the Snap companion dapp.
```mermaid
sequenceDiagram
autonumber
actor User
participant MetaMask
participant Snap
participant Site as Snap Companion Dapp
alt Optional
User ->>+ MetaMask: Add new account Snap
MetaMask ->> MetaMask: Display suggested Snaps
User ->> MetaMask: Select Snap
MetaMask ->> Site: Open in a new tab
deactivate MetaMask
end
Site ->>+ MetaMask: Install Snap?
MetaMask ->> MetaMask: Display permissions dialog
User ->> MetaMask: Approve permissions
MetaMask -->>- Site: OK
```
## Account creation
Once your account Snap is installed, the user can use the Snap companion dapp
to create or import accounts.
```mermaid
sequenceDiagram
autonumber
actor User
participant MetaMask
participant Snap
participant Site as Snap Companion Dapp
User ->>+ Site: Create new account
Site ->> Site: Custom logic to create account
Site ->>+ Snap: keyring_createAccount(options?)
Snap ->> Snap: Custom logic to create account
Snap ->>+ MetaMask: snap_manageAccounts("notify:accountCreated", account)
User ->> MetaMask: Approve account creation
MetaMask -->>- Snap: OK
Snap -->>- Site: OK
Site -->>- User: Done
```
## Transaction flows
The Keyring API supports two different types of flows for handling requests:
synchronous and asynchronous. The choice of which flow to implement depends on
the use case of the account Snap.
In general, the asynchronous flow should be used when the request requires user
interaction or when the request will take a long time to complete. The
synchronous flow should be preferred for any other use case.
### Asynchronous transaction flow
In the asynchronous transaction flow, MetaMask sends a keyring request to the
account Snap, and the account Snap responds with a `{ pending: true, redirect?
}` response to indicate that the keyring 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 keyring
Snap companion dapp.
Once the account Snap has completed the request, it sends a notification to
MetaMask with the result of the request.
```mermaid
sequenceDiagram
autonumber
actor User
participant Dapp
participant MetaMask
participant Snap
participant Site as Snap Companion Dapp
User ->>+ Dapp: Create new sign request
Dapp ->>+ MetaMask: ethereum.request(request)
MetaMask ->> MetaMask: Display request to user
User ->> MetaMask: Approve request
MetaMask ->>+ Snap: keyring_submitRequest(request)
Snap ->> Snap: Save request to Snap's state
Snap -->>- MetaMask: { pending: true, redirect? }
alt There is a redirect URL
User ->> MetaMask: Acknowledge redirection
MetaMask ->>+ Site: Open redirect URL in a new tab
end
deactivate MetaMask
Site ->>+ Snap: keyring_getRequests(id)
Snap -->>- Site: request
Site ->> Site: Custom logic to handle request
Site ->>+ Snap: keyring_approveRequest(id, data?)
Snap ->> Snap: Custom logic to handle request
Snap ->>+ MetaMask: snap_manageAccounts("notify:requestApproved", { id, result })
MetaMask -->> Dapp: result
MetaMask -->>- Snap: OK
Snap -->>- Site: OK
deactivate Site
Dapp -->>- User: Done
```
### Synchronous transaction flow
In the synchronous transaction flow, MetaMask sends a keyring request to the
account Snap, and the account Snap responds with a `{ pending: false, result }`
response that contains the result of the request.
```mermaid
sequenceDiagram
autonumber
actor User
participant Dapp
participant MetaMask
participant Snap
User ->>+ Dapp: Create new sign request
Dapp ->>+ MetaMask: ethereum.request(request)
alt Is EIP-4337 account?
MetaMask ->>+ Snap: keyring_submitRequest({request, method: eth_prepareUserOperation})
Snap ->> Snap: Custom logic to prepare request
Snap -->>- MetaMask: { request }
MetaMask ->>+ Snap: keyring_submitRequest({request, method: eth_patchUserOperation})
Snap -->>- MetaMask: { paymasterAndData?, calldata?, callGasLimit?, verificationGasLimit?, preVerificationGas? }
alt If calldata was changed
MetaMask ->>+ Snap: keyring_submitRequest({request, method: eth_decodeUserOperationCallData})
Snap -->>- MetaMask: { intents }
end
end
MetaMask ->> MetaMask: Display request to user
User ->> MetaMask: Approve request
MetaMask ->>+ Snap: keyring_submitRequest(request)
Snap ->> Snap: Custom logic to handle request
Snap -->>- MetaMask: { pending: false, result }
MetaMask -->>- Dapp: result
Dapp -->>- User: Done
```