Skip to content

Commit 42541ee

Browse files
authored
feat: add optional createAccounts method based on KeyringV2 (#448)
Adding a new optional `createAccounts` method that we could already leverage today without having the full implementation of `KeyringV2`. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Touches core account-creation pathways and introduces batch mutation with rollback and locking, which could affect state consistency and Snap interactions if edge cases are missed. > > **Overview** > Introduces an optional `Keyring.createAccounts` method plus a new `keyring_createAccounts` RPC (`KeyringRpcMethod.CreateAccounts`) that accepts typed v2 `CreateAccountOptions` and returns an array of accounts. > > Wires the new RPC end-to-end: `keyring-snap-sdk` dispatches `keyring_createAccounts` (and errors when unimplemented), `keyring-snap-client` adds `KeyringClient.createAccounts`, and `SnapKeyring` implements batch creation by validating/adding returned accounts to internal state (without per-account `notify:accountCreated`), enforcing idempotency, rejecting duplicates/unsupported generic accounts, rolling back Snap state via `deleteAccount` on failure, and serializing concurrent calls via an `async-mutex` lock. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 7ec3108. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 66b3005 commit 42541ee

File tree

14 files changed

+1020
-31
lines changed

14 files changed

+1020
-31
lines changed

packages/keyring-api/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
- Add `Keyring.createAccounts` optional method ([#448](https://github.com/MetaMask/accounts/pull/448))
13+
- This method is part of the keyring v2 specification and set as optional for backwards compatibility.
14+
- This method can be used to create one or more accounts using the new keyring v2 account creation typed options.
15+
- Add RPC support for this method through `KeyringRpcMethod.CreateAccounts`.
1216
- Add support for account derivations using range of indices in `KeyringV2` ([#451](https://github.com/MetaMask/accounts/pull/451))
1317
- Add `bip44:derive-index-range` capability to `KeyringCapabilities`.
1418
- Add `AccountCreationType.Bip44DeriveIndexRange` and `CreateAccountBip44DeriveIndexRangeOptions`.

packages/keyring-api/src/api/keyring.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type { Paginated, Pagination } from './pagination';
1313
import type { KeyringRequest } from './request';
1414
import type { KeyringResponse } from './response';
1515
import type { Transaction } from './transaction';
16+
import type { CreateAccountOptions } from './v2';
1617

1718
/**
1819
* Keyring interface.
@@ -56,6 +57,19 @@ export type Keyring = {
5657
options?: Record<string, Json> & MetaMaskOptions,
5758
): Promise<KeyringAccount>;
5859

60+
/**
61+
* Creates one or more new accounts according to the provided options.
62+
*
63+
* Deterministic account creation MUST be idempotent, meaning that for
64+
* deterministic algorithms, like BIP-44, calling this method with the same
65+
* options should always return the same accounts, even if the accounts
66+
* already exist in the keyring.
67+
*
68+
* @param options - Options describing how to create the account(s).
69+
* @returns A promise that resolves to an array of the created account objects.
70+
*/
71+
createAccounts?(options: CreateAccountOptions): Promise<KeyringAccount[]>;
72+
5973
/**
6074
* Lists the assets of an account (fungibles and non-fungibles) represented
6175
* by their respective CAIP-19:

packages/keyring-api/src/rpc.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
PaginationStruct,
2929
CaipAccountIdStruct,
3030
DiscoveredAccountStruct,
31+
CreateAccountOptionsStruct,
3132
} from './api';
3233

3334
/**
@@ -36,6 +37,7 @@ import {
3637
export enum KeyringRpcMethod {
3738
// Account management
3839
CreateAccount = 'keyring_createAccount',
40+
CreateAccounts = 'keyring_createAccounts',
3941
DeleteAccount = 'keyring_deleteAccount',
4042
DiscoverAccounts = 'keyring_discoverAccounts',
4143
ExportAccount = 'keyring_exportAccount',
@@ -126,6 +128,23 @@ export const CreateAccountResponseStruct = KeyringAccountStruct;
126128

127129
export type CreateAccountResponse = Infer<typeof CreateAccountResponseStruct>;
128130

131+
// ----------------------------------------------------------------------------
132+
// Create accounts
133+
134+
export const CreateAccountsRequestStruct = object({
135+
...CommonHeader,
136+
method: literal('keyring_createAccounts'),
137+
params: object({
138+
options: CreateAccountOptionsStruct,
139+
}),
140+
});
141+
142+
export type CreateAccountsRequest = Infer<typeof CreateAccountsRequestStruct>;
143+
144+
export const CreateAccountsResponseStruct = array(KeyringAccountStruct);
145+
146+
export type CreateAccountsResponse = Infer<typeof CreateAccountsResponseStruct>;
147+
129148
// ----------------------------------------------------------------------------
130149
// Set selected accounts
131150

packages/keyring-snap-bridge/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Add `SnapKeyring.createAccounts` method ([#448](https://github.com/MetaMask/accounts/pull/448))
13+
- This method can be used to create one or more accounts using the new keyring v2 account creation typed options.
14+
- Generic accounts will be filtered out if they are not allowed by the keyring configuration.
15+
1016
### Changed
1117

1218
- Bump `@metamask/snaps-controllers` from `^14.0.1` to `^17.2.0` ([#422](https://github.com/MetaMask/accounts/pull/422))

packages/keyring-snap-bridge/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"@metamask/superstruct": "^3.1.0",
4949
"@metamask/utils": "^11.1.0",
5050
"@types/uuid": "^9.0.8",
51+
"async-mutex": "^0.5.0",
5152
"uuid": "^9.0.1"
5253
},
5354
"devDependencies": {

0 commit comments

Comments
 (0)