@metamask-previews/money-account-controller 2.0.0-preview-0553ce5 → 2.0.0-preview-7ef511c85

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,21 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- ### Added
11
-
12
- - Add support for MPC-backed money accounts (MFA accounts) via `createMoneyAccount({ type: 'mpc' })` ([#10694](https://github.com/MetaMask/core/pull/10694))
13
- - Add `setDefaultMoneyAccount` and a persisted `defaultMoneyAccountId` state field, so consumers know which money account is preferred ([#10694](https://github.com/MetaMask/core/pull/10694))
14
-
15
10
  ### Changed
16
11
 
17
- - **BREAKING:** `createMoneyAccount` now takes a params object: `{ type: 'mpc' }` for the MPC-backed account (MFA), or `{ type?: 'mnemonic', entropySource }` (the default) for the `MoneyKeyring` account (SFA) for that entropy source ([#10694](https://github.com/MetaMask/core/pull/10694))
18
- - **BREAKING:** `MoneyAccount.options.entropy` is now a union of mnemonic and MPC entropy options (`MoneyAccountEntropyOptions`) ([#10694](https://github.com/MetaMask/core/pull/10694))
19
- - **BREAKING:** `getMoneyAccount()` with no selector now returns the default money account (`defaultMoneyAccountId`) instead of resolving the primary HD entropy source ([#10694](https://github.com/MetaMask/core/pull/10694))
20
- - Lookup by `{ entropySource }` is still supported, and lookup by `{ id }` was added.
21
12
  - Bump `@metamask/keyring-controller` from `^28.0.0` to `^28.2.0` ([#10418](https://github.com/MetaMask/core/pull/10418), [#10851](https://github.com/MetaMask/core/pull/10851))
22
13
  - Bump `@metamask/keyring-api` from `^24.0.0` to `^24.3.0` ([#10717](https://github.com/MetaMask/core/pull/10717), [#10792](https://github.com/MetaMask/core/pull/10792), [#10844](https://github.com/MetaMask/core/pull/10844))
23
14
  - Bump `@metamask/accounts-controller` from `^40.0.0` to `^40.1.0` ([#10851](https://github.com/MetaMask/core/pull/10851))
24
- - Bump `@metamask/base-controller` from `^10.0.0` to `^10.1.0` ([#10864](https://github.com/MetaMask/core/pull/10864))
25
15
 
26
16
  ## [2.0.0]
27
17
 
@@ -12,17 +12,10 @@ export type MoneyAccountControllerInitAction = {
12
12
  handler: MoneyAccountController['init'];
13
13
  };
14
14
  /**
15
- * Creates a money account. If an account already exists for the given
16
- * source, it is returned as-is (idempotent).
15
+ * Creates a money account for the given entropy source. If an account
16
+ * already exists for that entropy source, it is returned as-is (idempotent).
17
17
  *
18
- * The parameters determine the backing keyring:
19
- * - `{ type: 'mpc' }`: the MPC keyring (MFA account), which is created and
20
- * initialized if it does not exist yet.
21
- * - `{ type?: 'mnemonic', entropySource }` (the default): the `MoneyKeyring`
22
- * for that entropy source (SFA account), which is created if it does not
23
- * exist yet.
24
- *
25
- * @param params - The parameters for creating the money account.
18
+ * @param entropySource - The entropy source ID to create the money account for.
26
19
  * @returns The money account.
27
20
  */
28
21
  export type MoneyAccountControllerCreateMoneyAccountAction = {
@@ -30,21 +23,12 @@ export type MoneyAccountControllerCreateMoneyAccountAction = {
30
23
  handler: MoneyAccountController['createMoneyAccount'];
31
24
  };
32
25
  /**
33
- * Sets the default money account.
34
- *
35
- * @param id - The id of the money account to use as the default.
36
- */
37
- export type MoneyAccountControllerSetDefaultMoneyAccountAction = {
38
- type: `MoneyAccountController:setDefaultMoneyAccount`;
39
- handler: MoneyAccountController['setDefaultMoneyAccount'];
40
- };
41
- /**
42
- * Gets a money account by id, by entropy source, or the default one.
26
+ * Gets a money account by its associated entropy source ID. If no ID is
27
+ * provided, the primary entropy source will be used.
43
28
  *
44
29
  * @param selector - Selector options for getting the money account.
45
- * @param selector.id - The account id to look up. Takes precedence over `entropySource`.
46
- * @param selector.entropySource - The entropy source ID to get the money account for.
47
- * @returns The money account, or `undefined` if none matches.
30
+ * @param selector.entropySource - The entropy source ID to get the money account for. If not provided, the primary entropy source will be used.
31
+ * @returns The money account, or `undefined` if no account exists for the given entropy source.
48
32
  */
49
33
  export type MoneyAccountControllerGetMoneyAccountAction = {
50
34
  type: `MoneyAccountController:getMoneyAccount`;
@@ -64,5 +48,5 @@ export type MoneyAccountControllerClearStateAction = {
64
48
  /**
65
49
  * Union of all MoneyAccountController action types.
66
50
  */
67
- export type MoneyAccountControllerMethodActions = MoneyAccountControllerInitAction | MoneyAccountControllerCreateMoneyAccountAction | MoneyAccountControllerSetDefaultMoneyAccountAction | MoneyAccountControllerGetMoneyAccountAction | MoneyAccountControllerClearStateAction;
51
+ export type MoneyAccountControllerMethodActions = MoneyAccountControllerInitAction | MoneyAccountControllerCreateMoneyAccountAction | MoneyAccountControllerGetMoneyAccountAction | MoneyAccountControllerClearStateAction;
68
52
  //# sourceMappingURL=MoneyAccountController-method-action-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MoneyAccountController-method-action-types.d.ts","sourceRoot":"","sources":["../src/MoneyAccountController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAE1E;;;GAGG;AACH,MAAM,MAAM,gCAAgC,GAAG;IAC7C,IAAI,EAAE,6BAA6B,CAAC;IACpC,OAAO,EAAE,sBAAsB,CAAC,MAAM,CAAC,CAAC;CACzC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,8CAA8C,GAAG;IAC3D,IAAI,EAAE,2CAA2C,CAAC;IAClD,OAAO,EAAE,sBAAsB,CAAC,oBAAoB,CAAC,CAAC;CACvD,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,kDAAkD,GAAG;IAC/D,IAAI,EAAE,+CAA+C,CAAC;IACtD,OAAO,EAAE,sBAAsB,CAAC,wBAAwB,CAAC,CAAC;CAC3D,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,2CAA2C,GAAG;IACxD,IAAI,EAAE,wCAAwC,CAAC;IAC/C,OAAO,EAAE,sBAAsB,CAAC,iBAAiB,CAAC,CAAC;CACpD,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,sCAAsC,GAAG;IACnD,IAAI,EAAE,mCAAmC,CAAC;IAC1C,OAAO,EAAE,sBAAsB,CAAC,YAAY,CAAC,CAAC;CAC/C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mCAAmC,GAC3C,gCAAgC,GAChC,8CAA8C,GAC9C,kDAAkD,GAClD,2CAA2C,GAC3C,sCAAsC,CAAC"}
1
+ {"version":3,"file":"MoneyAccountController-method-action-types.d.ts","sourceRoot":"","sources":["../src/MoneyAccountController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAE1E;;;GAGG;AACH,MAAM,MAAM,gCAAgC,GAAG;IAC7C,IAAI,EAAE,6BAA6B,CAAC;IACpC,OAAO,EAAE,sBAAsB,CAAC,MAAM,CAAC,CAAC;CACzC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,8CAA8C,GAAG;IAC3D,IAAI,EAAE,2CAA2C,CAAC;IAClD,OAAO,EAAE,sBAAsB,CAAC,oBAAoB,CAAC,CAAC;CACvD,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,2CAA2C,GAAG;IACxD,IAAI,EAAE,wCAAwC,CAAC;IAC/C,OAAO,EAAE,sBAAsB,CAAC,iBAAiB,CAAC,CAAC;CACpD,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,sCAAsC,GAAG;IACnD,IAAI,EAAE,mCAAmC,CAAC;IAC1C,OAAO,EAAE,sBAAsB,CAAC,YAAY,CAAC,CAAC;CAC/C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mCAAmC,GAC3C,gCAAgC,GAChC,8CAA8C,GAC9C,2CAA2C,GAC3C,sCAAsC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"MoneyAccountController-method-action-types.js","sourceRoot":"","sources":["../src/MoneyAccountController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { MoneyAccountController } from './MoneyAccountController.js';\n\n/**\n * Initializes the controller by creating a money account for the primary\n * entropy source if one does not already exist.\n */\nexport type MoneyAccountControllerInitAction = {\n type: `MoneyAccountController:init`;\n handler: MoneyAccountController['init'];\n};\n\n/**\n * Creates a money account. If an account already exists for the given\n * source, it is returned as-is (idempotent).\n *\n * The parameters determine the backing keyring:\n * - `{ type: 'mpc' }`: the MPC keyring (MFA account), which is created and\n * initialized if it does not exist yet.\n * - `{ type?: 'mnemonic', entropySource }` (the default): the `MoneyKeyring`\n * for that entropy source (SFA account), which is created if it does not\n * exist yet.\n *\n * @param params - The parameters for creating the money account.\n * @returns The money account.\n */\nexport type MoneyAccountControllerCreateMoneyAccountAction = {\n type: `MoneyAccountController:createMoneyAccount`;\n handler: MoneyAccountController['createMoneyAccount'];\n};\n\n/**\n * Sets the default money account.\n *\n * @param id - The id of the money account to use as the default.\n */\nexport type MoneyAccountControllerSetDefaultMoneyAccountAction = {\n type: `MoneyAccountController:setDefaultMoneyAccount`;\n handler: MoneyAccountController['setDefaultMoneyAccount'];\n};\n\n/**\n * Gets a money account by id, by entropy source, or the default one.\n *\n * @param selector - Selector options for getting the money account.\n * @param selector.id - The account id to look up. Takes precedence over `entropySource`.\n * @param selector.entropySource - The entropy source ID to get the money account for.\n * @returns The money account, or `undefined` if none matches.\n */\nexport type MoneyAccountControllerGetMoneyAccountAction = {\n type: `MoneyAccountController:getMoneyAccount`;\n handler: MoneyAccountController['getMoneyAccount'];\n};\n\n/**\n * Resets the controller state to its default, removing all money accounts.\n *\n * Intended for use during a full app reset (e.g. when the user wipes all\n * wallet data). Does not interact with the keyring — the caller is\n * responsible for ensuring the associated keyring state is also cleared.\n */\nexport type MoneyAccountControllerClearStateAction = {\n type: `MoneyAccountController:clearState`;\n handler: MoneyAccountController['clearState'];\n};\n\n/**\n * Union of all MoneyAccountController action types.\n */\nexport type MoneyAccountControllerMethodActions =\n | MoneyAccountControllerInitAction\n | MoneyAccountControllerCreateMoneyAccountAction\n | MoneyAccountControllerSetDefaultMoneyAccountAction\n | MoneyAccountControllerGetMoneyAccountAction\n | MoneyAccountControllerClearStateAction;\n"]}
1
+ {"version":3,"file":"MoneyAccountController-method-action-types.js","sourceRoot":"","sources":["../src/MoneyAccountController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { MoneyAccountController } from './MoneyAccountController.js';\n\n/**\n * Initializes the controller by creating a money account for the primary\n * entropy source if one does not already exist.\n */\nexport type MoneyAccountControllerInitAction = {\n type: `MoneyAccountController:init`;\n handler: MoneyAccountController['init'];\n};\n\n/**\n * Creates a money account for the given entropy source. If an account\n * already exists for that entropy source, it is returned as-is (idempotent).\n *\n * @param entropySource - The entropy source ID to create the money account for.\n * @returns The money account.\n */\nexport type MoneyAccountControllerCreateMoneyAccountAction = {\n type: `MoneyAccountController:createMoneyAccount`;\n handler: MoneyAccountController['createMoneyAccount'];\n};\n\n/**\n * Gets a money account by its associated entropy source ID. If no ID is\n * provided, the primary entropy source will be used.\n *\n * @param selector - Selector options for getting the money account.\n * @param selector.entropySource - The entropy source ID to get the money account for. If not provided, the primary entropy source will be used.\n * @returns The money account, or `undefined` if no account exists for the given entropy source.\n */\nexport type MoneyAccountControllerGetMoneyAccountAction = {\n type: `MoneyAccountController:getMoneyAccount`;\n handler: MoneyAccountController['getMoneyAccount'];\n};\n\n/**\n * Resets the controller state to its default, removing all money accounts.\n *\n * Intended for use during a full app reset (e.g. when the user wipes all\n * wallet data). Does not interact with the keyring — the caller is\n * responsible for ensuring the associated keyring state is also cleared.\n */\nexport type MoneyAccountControllerClearStateAction = {\n type: `MoneyAccountController:clearState`;\n handler: MoneyAccountController['clearState'];\n};\n\n/**\n * Union of all MoneyAccountController action types.\n */\nexport type MoneyAccountControllerMethodActions =\n | MoneyAccountControllerInitAction\n | MoneyAccountControllerCreateMoneyAccountAction\n | MoneyAccountControllerGetMoneyAccountAction\n | MoneyAccountControllerClearStateAction;\n"]}
@@ -1,43 +1,20 @@
1
1
  import type { ControllerGetStateAction, ControllerStateChangeEvent } from '@metamask/base-controller';
2
2
  import { BaseController } from '@metamask/base-controller';
3
3
  import type { EntropySourceId } from '@metamask/keyring-api';
4
- import type { KeyringControllerGetStateAction, KeyringControllerWithControllerAction, KeyringControllerWithKeyringAction } from '@metamask/keyring-controller';
4
+ import type { KeyringControllerAddNewKeyringAction, KeyringControllerGetStateAction, KeyringControllerWithKeyringAction } from '@metamask/keyring-controller';
5
5
  import type { Messenger } from '@metamask/messenger';
6
6
  import type { MoneyAccountControllerMethodActions } from './MoneyAccountController-method-action-types.js';
7
7
  import type { MoneyAccount } from './types.js';
8
8
  export declare const controllerName = "MoneyAccountController";
9
- /**
10
- * Parameters for creating a money account.
11
- *
12
- * - `{ type: 'mpc' }`: create the MFA account backed by the MPC keyring.
13
- * - `{ type?: 'mnemonic', entropySource }` (the default): create the SFA
14
- * account backed by the `MoneyKeyring` for the given entropy source.
15
- */
16
- export type CreateMoneyAccountParams = {
17
- /**
18
- * The kind of money account to create. Defaults to `'mnemonic'`.
19
- */
20
- type?: 'mnemonic';
21
- /**
22
- * The entropy source ID of the SRP backing the account.
23
- */
24
- entropySource: EntropySourceId;
25
- } | {
26
- /**
27
- * The kind of money account to create.
28
- */
29
- type: 'mpc';
30
- };
31
9
  export type MoneyAccountControllerState = {
32
10
  moneyAccounts: {
33
11
  [id: MoneyAccount['id']]: MoneyAccount;
34
12
  };
35
- defaultMoneyAccountId: MoneyAccount['id'] | null;
36
13
  };
37
14
  export declare function getDefaultMoneyAccountControllerState(): MoneyAccountControllerState;
38
15
  export type MoneyAccountControllerGetStateAction = ControllerGetStateAction<typeof controllerName, MoneyAccountControllerState>;
39
16
  export type MoneyAccountControllerActions = MoneyAccountControllerGetStateAction | MoneyAccountControllerMethodActions;
40
- type AllowedActions = KeyringControllerGetStateAction | KeyringControllerWithControllerAction | KeyringControllerWithKeyringAction;
17
+ type AllowedActions = KeyringControllerGetStateAction | KeyringControllerAddNewKeyringAction | KeyringControllerWithKeyringAction;
41
18
  export type MoneyAccountControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, MoneyAccountControllerState>;
42
19
  export type MoneyAccountControllerEvents = MoneyAccountControllerStateChangeEvent;
43
20
  type AllowedEvents = never;
@@ -64,36 +41,22 @@ export declare class MoneyAccountController extends BaseController<typeof contro
64
41
  */
65
42
  init(): Promise<void>;
66
43
  /**
67
- * Creates a money account. If an account already exists for the given
68
- * source, it is returned as-is (idempotent).
69
- *
70
- * The parameters determine the backing keyring:
71
- * - `{ type: 'mpc' }`: the MPC keyring (MFA account), which is created and
72
- * initialized if it does not exist yet.
73
- * - `{ type?: 'mnemonic', entropySource }` (the default): the `MoneyKeyring`
74
- * for that entropy source (SFA account), which is created if it does not
75
- * exist yet.
44
+ * Creates a money account for the given entropy source. If an account
45
+ * already exists for that entropy source, it is returned as-is (idempotent).
76
46
  *
77
- * @param params - The parameters for creating the money account.
47
+ * @param entropySource - The entropy source ID to create the money account for.
78
48
  * @returns The money account.
79
49
  */
80
- createMoneyAccount(params: CreateMoneyAccountParams): Promise<MoneyAccount>;
81
- /**
82
- * Sets the default money account.
83
- *
84
- * @param id - The id of the money account to use as the default.
85
- */
86
- setDefaultMoneyAccount(id: MoneyAccount['id']): void;
50
+ createMoneyAccount(entropySource: EntropySourceId): Promise<MoneyAccount>;
87
51
  /**
88
- * Gets a money account by id, by entropy source, or the default one.
52
+ * Gets a money account by its associated entropy source ID. If no ID is
53
+ * provided, the primary entropy source will be used.
89
54
  *
90
55
  * @param selector - Selector options for getting the money account.
91
- * @param selector.id - The account id to look up. Takes precedence over `entropySource`.
92
- * @param selector.entropySource - The entropy source ID to get the money account for.
93
- * @returns The money account, or `undefined` if none matches.
56
+ * @param selector.entropySource - The entropy source ID to get the money account for. If not provided, the primary entropy source will be used.
57
+ * @returns The money account, or `undefined` if no account exists for the given entropy source.
94
58
  */
95
59
  getMoneyAccount(selector?: {
96
- id?: MoneyAccount['id'];
97
60
  entropySource?: EntropySourceId;
98
61
  }): MoneyAccount | undefined;
99
62
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"MoneyAccountController.d.ts","sourceRoot":"","sources":["../src/MoneyAccountController.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAE3B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAI3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EACV,+BAA+B,EAC/B,qCAAqC,EACrC,kCAAkC,EAEnC,MAAM,8BAA8B,CAAC;AAGtC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAIrD,OAAO,KAAK,EAAE,mCAAmC,EAAE,MAAM,iDAAiD,CAAC;AAC3G,OAAO,KAAK,EAAE,YAAY,EAA8B,MAAM,YAAY,CAAC;AAO3E,eAAO,MAAM,cAAc,2BAA2B,CAAC;AAEvD;;;;;;GAMG;AACH,MAAM,MAAM,wBAAwB,GAChC;IACE;;OAEG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAElB;;OAEG;IACH,aAAa,EAAE,eAAe,CAAC;CAChC,GACD;IACE;;OAEG;IACH,IAAI,EAAE,KAAK,CAAC;CACb,CAAC;AAEN,MAAM,MAAM,2BAA2B,GAAG;IACxC,aAAa,EAAE;QACb,CAAC,EAAE,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC;KACxC,CAAC;IACF,qBAAqB,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAClD,CAAC;AAiBF,wBAAgB,qCAAqC,IAAI,2BAA2B,CAKnF;AAqBD,MAAM,MAAM,oCAAoC,GAAG,wBAAwB,CACzE,OAAO,cAAc,EACrB,2BAA2B,CAC5B,CAAC;AAEF,MAAM,MAAM,6BAA6B,GACrC,oCAAoC,GACpC,mCAAmC,CAAC;AAExC,KAAK,cAAc,GACf,+BAA+B,GAC/B,qCAAqC,GACrC,kCAAkC,CAAC;AAEvC,MAAM,MAAM,sCAAsC,GAAG,0BAA0B,CAC7E,OAAO,cAAc,EACrB,2BAA2B,CAC5B,CAAC;AAEF,MAAM,MAAM,4BAA4B,GACtC,sCAAsC,CAAC;AAEzC,KAAK,aAAa,GAAG,KAAK,CAAC;AAE3B,MAAM,MAAM,+BAA+B,GAAG,SAAS,CACrD,OAAO,cAAc,EACrB,6BAA6B,GAAG,cAAc,EAC9C,4BAA4B,GAAG,aAAa,CAC7C,CAAC;AAYF;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,cAAc,CACxD,OAAO,cAAc,EACrB,2BAA2B,EAC3B,+BAA+B,CAChC;;IACC;;;;;;OAMG;IACH,YAAY,EACV,SAAS,EACT,KAAK,GACN,EAAE;QACD,SAAS,EAAE,+BAA+B,CAAC;QAC3C,KAAK,CAAC,EAAE,OAAO,CAAC,2BAA2B,CAAC,CAAC;KAC9C,EAeA;IAED;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAkB1B;IAED;;;;;;;;;;;;;OAaG;IACG,kBAAkB,CACtB,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,YAAY,CAAC,CAsBvB;IAED;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,IAAI,CAQnD;IAED;;;;;;;OAOG;IACH,eAAe,CACb,QAAQ,GAAE;QACR,EAAE,CAAC,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;QACxB,aAAa,CAAC,EAAE,eAAe,CAAC;KAC5B,GACL,YAAY,GAAG,SAAS,CAe1B;IAED;;;;;;OAMG;IACH,UAAU,IAAI,IAAI,CAKjB;CAkSF"}
1
+ {"version":3,"file":"MoneyAccountController.d.ts","sourceRoot":"","sources":["../src/MoneyAccountController.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAE3B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAO3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EACV,oCAAoC,EACpC,+BAA+B,EAC/B,kCAAkC,EAGnC,MAAM,8BAA8B,CAAC;AAMtC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAIrD,OAAO,KAAK,EAAE,mCAAmC,EAAE,MAAM,iDAAiD,CAAC;AAC3G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C,eAAO,MAAM,cAAc,2BAA2B,CAAC;AAEvD,MAAM,MAAM,2BAA2B,GAAG;IACxC,aAAa,EAAE;QACb,CAAC,EAAE,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC;KACxC,CAAC;CACH,CAAC;AAWF,wBAAgB,qCAAqC,IAAI,2BAA2B,CAInF;AASD,MAAM,MAAM,oCAAoC,GAAG,wBAAwB,CACzE,OAAO,cAAc,EACrB,2BAA2B,CAC5B,CAAC;AAEF,MAAM,MAAM,6BAA6B,GACrC,oCAAoC,GACpC,mCAAmC,CAAC;AAExC,KAAK,cAAc,GACf,+BAA+B,GAC/B,oCAAoC,GACpC,kCAAkC,CAAC;AAEvC,MAAM,MAAM,sCAAsC,GAAG,0BAA0B,CAC7E,OAAO,cAAc,EACrB,2BAA2B,CAC5B,CAAC;AAEF,MAAM,MAAM,4BAA4B,GACtC,sCAAsC,CAAC;AAEzC,KAAK,aAAa,GAAG,KAAK,CAAC;AAE3B,MAAM,MAAM,+BAA+B,GAAG,SAAS,CACrD,OAAO,cAAc,EACrB,6BAA6B,GAAG,cAAc,EAC9C,4BAA4B,GAAG,aAAa,CAC7C,CAAC;AAEF;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,cAAc,CACxD,OAAO,cAAc,EACrB,2BAA2B,EAC3B,+BAA+B,CAChC;;IAGC;;;;;;OAMG;IACH,YAAY,EACV,SAAS,EACT,KAAK,GACN,EAAE;QACD,SAAS,EAAE,+BAA+B,CAAC;QAC3C,KAAK,CAAC,EAAE,OAAO,CAAC,2BAA2B,CAAC,CAAC;KAC9C,EAiBA;IAED;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAiB1B;IAED;;;;;;OAMG;IACG,kBAAkB,CACtB,aAAa,EAAE,eAAe,GAC7B,OAAO,CAAC,YAAY,CAAC,CA6DvB;IAED;;;;;;;OAOG;IACH,eAAe,CACb,QAAQ,GAAE;QAAE,aAAa,CAAC,EAAE,eAAe,CAAA;KAAO,GACjD,YAAY,GAAG,SAAS,CAY1B;IAED;;;;;;OAMG;IACH,UAAU,IAAI,IAAI,CAIjB;CAiHF"}
@@ -2,9 +2,10 @@ import { getUUIDFromAddressOfNormalAccount } from '@metamask/accounts-controller
2
2
  import { BaseController } from '@metamask/base-controller';
3
3
  import { MONEY_DERIVATION_PATH } from '@metamask/eth-money-keyring';
4
4
  import { EthAccountType, EthMethod, EthScope } from '@metamask/keyring-api';
5
- import { KeyringTypes } from '@metamask/keyring-controller';
5
+ import { isKeyringNotFoundError, KeyringTypes, } from '@metamask/keyring-controller';
6
+ import { Mutex } from 'async-mutex';
6
7
  import { projectLogger as log } from './logger.js';
7
- import { isMoneyKeyring, isMpcKeyring, MPC_ENTROPY_SOURCE_ID, } from './utils.js';
8
+ import { isMoneyKeyring } from './utils.js';
8
9
  export const controllerName = 'MoneyAccountController';
9
10
  const moneyAccountControllerMetadata = {
10
11
  moneyAccounts: {
@@ -13,40 +14,23 @@ const moneyAccountControllerMetadata = {
13
14
  persist: true,
14
15
  usedInUi: true,
15
16
  },
16
- defaultMoneyAccountId: {
17
- includeInDebugSnapshot: true,
18
- includeInStateLogs: true,
19
- persist: true,
20
- usedInUi: true,
21
- },
22
17
  };
23
18
  export function getDefaultMoneyAccountControllerState() {
24
19
  return {
25
20
  moneyAccounts: {},
26
- defaultMoneyAccountId: null,
27
21
  };
28
22
  }
29
23
  const MESSENGER_EXPOSED_METHODS = [
30
24
  'createMoneyAccount',
31
25
  'getMoneyAccount',
32
- 'setDefaultMoneyAccount',
33
26
  'clearState',
34
27
  'init',
35
28
  ];
36
- /**
37
- * The signing methods supported by money accounts.
38
- */
39
- const MONEY_ACCOUNT_METHODS = [
40
- EthMethod.PersonalSign,
41
- EthMethod.SignTypedDataV1,
42
- EthMethod.SignTypedDataV3,
43
- EthMethod.SignTypedDataV4,
44
- // TODO: Update this once the `keyring-api` package supports `SignEip7702Authorization` method.
45
- ];
46
29
  /**
47
30
  * Controller for managing money accounts.
48
31
  */
49
32
  export class MoneyAccountController extends BaseController {
33
+ #lock;
50
34
  /**
51
35
  * Constructor for the MoneyAccountController.
52
36
  *
@@ -65,6 +49,7 @@ export class MoneyAccountController extends BaseController {
65
49
  },
66
50
  });
67
51
  this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
52
+ this.#lock = new Mutex();
68
53
  }
69
54
  /**
70
55
  * Initializes the controller by creating a money account for the primary
@@ -74,9 +59,7 @@ export class MoneyAccountController extends BaseController {
74
59
  this.#assertIsUnlocked();
75
60
  const primaryEntropySource = this.#getPrimaryEntropySource();
76
61
  if (primaryEntropySource) {
77
- const { id, address } = await this.createMoneyAccount({
78
- entropySource: primaryEntropySource,
79
- });
62
+ const { id, address } = await this.createMoneyAccount(primaryEntropySource);
80
63
  log(`Money keyring (entropy:${primaryEntropySource} - primary) account is: ${address} (${id})`);
81
64
  }
82
65
  else {
@@ -86,90 +69,20 @@ export class MoneyAccountController extends BaseController {
86
69
  }
87
70
  }
88
71
  /**
89
- * Creates a money account. If an account already exists for the given
90
- * source, it is returned as-is (idempotent).
72
+ * Creates a money account for the given entropy source. If an account
73
+ * already exists for that entropy source, it is returned as-is (idempotent).
91
74
  *
92
- * The parameters determine the backing keyring:
93
- * - `{ type: 'mpc' }`: the MPC keyring (MFA account), which is created and
94
- * initialized if it does not exist yet.
95
- * - `{ type?: 'mnemonic', entropySource }` (the default): the `MoneyKeyring`
96
- * for that entropy source (SFA account), which is created if it does not
97
- * exist yet.
98
- *
99
- * @param params - The parameters for creating the money account.
75
+ * @param entropySource - The entropy source ID to create the money account for.
100
76
  * @returns The money account.
101
77
  */
102
- async createMoneyAccount(params) {
78
+ async createMoneyAccount(entropySource) {
103
79
  this.#assertIsUnlocked();
104
- // Idempotent: return existing account if already in state. The stored
105
- // entropy source ID identifies the account for both account kinds.
106
- const entropySourceId = params.type === 'mpc' ? MPC_ENTROPY_SOURCE_ID : params.entropySource;
107
- const existingAccount = this.#getMoneyAccountByEntropySource(entropySourceId);
80
+ // Idempotent: return existing account if already in state.
81
+ const existingAccount = this.getMoneyAccount({ entropySource });
108
82
  if (existingAccount) {
109
83
  return existingAccount;
110
84
  }
111
- const account = params.type === 'mpc'
112
- ? await this.#createMpcKeyringAccount()
113
- : await this.#createMoneyKeyringAccount(params.entropySource);
114
- log(`Money account created: ${account.address} (${account.id}) for entropy source: ${entropySourceId}`);
115
- return account;
116
- }
117
- /**
118
- * Sets the default money account.
119
- *
120
- * @param id - The id of the money account to use as the default.
121
- */
122
- setDefaultMoneyAccount(id) {
123
- if (this.state.moneyAccounts[id] === undefined) {
124
- throw new Error(`Unknown money account: ${id}`);
125
- }
126
- this.update((state) => {
127
- state.defaultMoneyAccountId = id;
128
- });
129
- }
130
- /**
131
- * Gets a money account by id, by entropy source, or the default one.
132
- *
133
- * @param selector - Selector options for getting the money account.
134
- * @param selector.id - The account id to look up. Takes precedence over `entropySource`.
135
- * @param selector.entropySource - The entropy source ID to get the money account for.
136
- * @returns The money account, or `undefined` if none matches.
137
- */
138
- getMoneyAccount(selector = {}) {
139
- if (selector.id !== undefined) {
140
- return this.state.moneyAccounts[selector.id];
141
- }
142
- if (selector.entropySource !== undefined) {
143
- return this.#getMoneyAccountByEntropySource(selector.entropySource);
144
- }
145
- const defaultMoneyAccountId = this.state.defaultMoneyAccountId ?? null;
146
- if (defaultMoneyAccountId === null) {
147
- return undefined;
148
- }
149
- return this.state.moneyAccounts[defaultMoneyAccountId];
150
- }
151
- /**
152
- * Resets the controller state to its default, removing all money accounts.
153
- *
154
- * Intended for use during a full app reset (e.g. when the user wipes all
155
- * wallet data). Does not interact with the keyring — the caller is
156
- * responsible for ensuring the associated keyring state is also cleared.
157
- */
158
- clearState() {
159
- this.update((state) => {
160
- state.moneyAccounts = {};
161
- state.defaultMoneyAccountId = null;
162
- });
163
- }
164
- /**
165
- * Creates or reuses a `MoneyKeyring` account for the given entropy source.
166
- *
167
- * @param entropySource - The entropy source ID to create the money account for.
168
- * @returns The money account.
169
- */
170
- async #createMoneyKeyringAccount(entropySource) {
171
- const id = await this.#ensureMoneyKeyring(entropySource);
172
- const address = await this.#withMoneyKeyring(id, async (keyring) => {
85
+ const address = await this.#withKeyring(entropySource, async (keyring) => {
173
86
  // We're adding this logic to be defensive against the possibility of a money keyring
174
87
  // existing without any accounts, which shouldn't normally happen but we want to be
175
88
  // sure we can handle it if it does.
@@ -179,66 +92,10 @@ export class MoneyAccountController extends BaseController {
179
92
  const [moneyAddress] = accounts;
180
93
  return moneyAddress;
181
94
  }
182
- log(`Money keyring (id:${id}, entropy:${entropySource}) has no accounts, creating one...`);
95
+ log(`Money keyring (entropy:${entropySource}) has no accounts, creating one...`);
183
96
  const [moneyAddress] = await keyring.addAccounts(1);
184
97
  return moneyAddress;
185
98
  });
186
- return this.#createKeyringAccount({
187
- address,
188
- entropy: {
189
- type: 'mnemonic',
190
- id: entropySource,
191
- groupIndex: 0,
192
- derivationPath: MONEY_DERIVATION_PATH,
193
- },
194
- });
195
- }
196
- /**
197
- * Creates or reuses an account on the MPC keyring.
198
- *
199
- * The MPC keyring is an atomic keyring: its initialization is cheap when
200
- * already initialized, and long-running work is dispatched without holding
201
- * the keyring controller mutex.
202
- *
203
- * @returns The money account.
204
- */
205
- async #createMpcKeyringAccount() {
206
- const id = await this.#ensureMpcKeyring();
207
- const address = await this.#withMpcKeyring(id, async (keyring) => {
208
- // The keyring infers the setup mode (create or import) from its own
209
- // state. This is a no-op if the keyring is already initialized.
210
- await keyring.init();
211
- // We're adding this logic to be defensive against the possibility of an
212
- // MPC keyring existing without any accounts, which shouldn't normally
213
- // happen but we want to be sure we can handle it if it does.
214
- const accounts = await keyring.getAccounts();
215
- if (accounts.length > 0) {
216
- const [mpcAddress] = accounts;
217
- return mpcAddress;
218
- }
219
- log(`MPC keyring (${id}) has no accounts, adding one...`);
220
- const [mpcAddress] = await keyring.addAccounts(1);
221
- return mpcAddress;
222
- });
223
- return this.#createKeyringAccount({
224
- address,
225
- entropy: {
226
- type: 'mpc',
227
- id: MPC_ENTROPY_SOURCE_ID,
228
- },
229
- });
230
- }
231
- /**
232
- * Builds a money account for the given address and entropy options, stores
233
- * it in state, and returns it. If no default account is set, the new account
234
- * becomes the default.
235
- *
236
- * @param params - The parameters for creating the account.
237
- * @param params.address - The account address.
238
- * @param params.entropy - The entropy options of the backing keyring.
239
- * @returns The money account.
240
- */
241
- #createKeyringAccount({ address, entropy, }) {
242
99
  const account = {
243
100
  // This is an EVM account, so let's re-use the deterministic ID generation logic of
244
101
  // EVM accounts.
@@ -247,110 +104,114 @@ export class MoneyAccountController extends BaseController {
247
104
  address,
248
105
  scopes: [EthScope.Eoa],
249
106
  options: {
250
- entropy,
107
+ entropy: {
108
+ type: 'mnemonic',
109
+ id: entropySource,
110
+ groupIndex: 0,
111
+ derivationPath: MONEY_DERIVATION_PATH,
112
+ },
251
113
  exportable: false,
252
114
  },
253
- methods: [...MONEY_ACCOUNT_METHODS],
115
+ methods: [
116
+ EthMethod.PersonalSign,
117
+ EthMethod.SignTypedDataV1,
118
+ EthMethod.SignTypedDataV3,
119
+ EthMethod.SignTypedDataV4,
120
+ // TODO: Update this once the `keyring-api` package supports `SignEip7702Authorization` method.
121
+ ],
254
122
  };
123
+ // Store the account in state.
255
124
  this.update((state) => {
256
125
  state.moneyAccounts[account.id] = account;
257
- state.defaultMoneyAccountId ??= account.id;
258
126
  });
127
+ log(`Money keyring (entropy:${account.options.entropy.id}) account created: ${account.address} (${account.id})`);
259
128
  return account;
260
129
  }
261
130
  /**
262
- * Gets a money account by entropy source ID.
131
+ * Gets a money account by its associated entropy source ID. If no ID is
132
+ * provided, the primary entropy source will be used.
263
133
  *
264
- * @param entropySource - The entropy source ID.
265
- * @returns The matching account, if any.
134
+ * @param selector - Selector options for getting the money account.
135
+ * @param selector.entropySource - The entropy source ID to get the money account for. If not provided, the primary entropy source will be used.
136
+ * @returns The money account, or `undefined` if no account exists for the given entropy source.
266
137
  */
267
- #getMoneyAccountByEntropySource(entropySource) {
138
+ getMoneyAccount(selector = {}) {
139
+ const entropySource = selector.entropySource ?? this.#getPrimaryEntropySource();
140
+ if (entropySource === undefined) {
141
+ return undefined;
142
+ }
143
+ // We should never have more than one money account per entropy source, but if we
144
+ // do, just return the first one we find.
268
145
  return Object.values(this.state.moneyAccounts).find((account) => account.options.entropy.id === entropySource);
269
146
  }
270
147
  /**
271
- * Ensures a `MoneyKeyring` exists for the given entropy source, creating one
272
- * atomically if it does not, and returns its keyring ID.
273
- *
274
- * The check-or-create is performed within a single
275
- * `KeyringController:withController` transaction, which is mutually
276
- * exclusive and rolls back on error.
277
- *
278
- * @param entropySource - The entropy source ID identifying the target keyring.
279
- * @returns The keyring ID of the existing or newly created keyring.
280
- */
281
- async #ensureMoneyKeyring(entropySource) {
282
- return (await this.messenger.call('KeyringController:withController', async (restrictedController) => {
283
- const moneyKeyrings = restrictedController.keyrings.filter((entry) => isMoneyKeyring(entry.keyring) &&
284
- entry.keyring.entropySource === entropySource);
285
- if (moneyKeyrings.length > 0) {
286
- return moneyKeyrings[0].metadata.id;
287
- }
288
- log(`Money keyring (entropy:${entropySource}) not found, creating one...`);
289
- const entry = await restrictedController.addNewKeyring(KeyringTypes.money, { entropySource });
290
- return entry.metadata.id;
291
- }));
292
- }
293
- /**
294
- * Ensures the MPC keyring exists, creating it atomically if it does not, and
295
- * returns its keyring ID.
296
- *
297
- * The check-or-create is performed within a single
298
- * `KeyringController:withController` transaction, which is mutually
299
- * exclusive and rolls back on error.
148
+ * Resets the controller state to its default, removing all money accounts.
300
149
  *
301
- * @returns The keyring ID of the existing or newly created keyring.
150
+ * Intended for use during a full app reset (e.g. when the user wipes all
151
+ * wallet data). Does not interact with the keyring — the caller is
152
+ * responsible for ensuring the associated keyring state is also cleared.
302
153
  */
303
- async #ensureMpcKeyring() {
304
- return (await this.messenger.call('KeyringController:withController', async (restrictedController) => {
305
- const mpcKeyrings = restrictedController.keyrings.filter((entry) => isMpcKeyring(entry.keyring));
306
- if (mpcKeyrings.length > 1) {
307
- throw new Error('Multiple MPC keyrings found');
308
- }
309
- if (mpcKeyrings.length === 1) {
310
- return mpcKeyrings[0].metadata.id;
311
- }
312
- log('MPC keyring not found, creating one...');
313
- const entry = await restrictedController.addNewKeyring(KeyringTypes.mpc);
314
- return entry.metadata.id;
315
- }));
154
+ clearState() {
155
+ this.update((state) => {
156
+ state.moneyAccounts = {};
157
+ });
316
158
  }
317
159
  /**
318
- * Calls `KeyringController:withKeyring` for the keyring with the given ID.
160
+ * Calls `KeyringController:withKeyring` for the `MoneyKeyring` associated with the
161
+ * given entropy source, creating one first if it does not yet exist.
319
162
  *
320
- * @param id - The keyring metadata ID.
321
- * @param assertType - Verifies the resolved keyring has the expected type.
322
- * @param operation - Callback invoked with the resolved keyring.
163
+ * @param entropySource - The entropy source ID identifying the target keyring.
164
+ * @param operation - Callback invoked with the resolved `MoneyKeyring`.
323
165
  * @returns The value returned by `operation`.
324
166
  */
325
- async #withKeyring(id, assertType, operation) {
326
- return (await this.messenger.call('KeyringController:withKeyring', { id }, async ({ keyring }) => {
327
- if (!assertType(keyring)) {
328
- throw new Error(`Keyring ${id} has an unexpected type`);
167
+ async #withKeyring(entropySource, operation) {
168
+ // Filter to find a specific `MoneyKeyring` for the given entropy source.
169
+ const isMoneyKeyringForEntropySource = (keyring) => isMoneyKeyring(keyring) && keyring.entropySource === entropySource;
170
+ // We cannot use proper generic-type inference using the messenger
171
+ // here, so we have to use a type casts for `keyring` and the return type.
172
+ const withKeyring = async (selector, callback) => this.messenger.call('KeyringController:withKeyring', selector, async ({ keyring }) => callback(keyring));
173
+ // We have an extra lock here to avoid a race-condition where 2 calls to
174
+ // `#withKeyring` for the same entropy source happen at the same time, and
175
+ // both don't find an existing keyring, so they both try to create a new
176
+ // one, which creates multiple keyrings for the same entropy source.
177
+ // NOTE: We cannot use `createIfMissing` here either, since it's only supported
178
+ // for selectors by type (and we want to deprecate this option).
179
+ // TODO: Move this new pattern in the `KeyringController`.
180
+ return await this.#lock.runExclusive(async () => {
181
+ try {
182
+ return await withKeyring({
183
+ filter: isMoneyKeyringForEntropySource,
184
+ }, operation);
329
185
  }
330
- return operation(keyring);
331
- }));
186
+ catch (error) {
187
+ // Forward any unexpected errors, but if the error is that
188
+ // the keyring wasn't found, we'll create it below.
189
+ if (!isKeyringNotFoundError(error)) {
190
+ throw error;
191
+ }
192
+ // Create the keyring so we can use `withKeyring` to operate on it in the
193
+ // retry below.
194
+ log(`Money keyring (entropy:${entropySource}) not found, creating one...`);
195
+ const { id } = await this.#createMoneyKeyring(entropySource);
196
+ // Use the ID directly on the retry (we just created this keyring so we
197
+ // know exactly which one to target).
198
+ return await withKeyring({ id }, operation);
199
+ }
200
+ });
332
201
  }
333
202
  /**
334
- * Calls `KeyringController:withKeyring` for the `MoneyKeyring` with the
335
- * given ID.
203
+ * Adds a new money keyring for the given entropy source and returns its metadata.
336
204
  *
337
- * @param id - The keyring metadata ID.
338
- * @param operation - Callback invoked with the resolved `MoneyKeyring`.
339
- * @returns The value returned by `operation`.
340
- */
341
- async #withMoneyKeyring(id, operation) {
342
- return await this.#withKeyring(id, isMoneyKeyring, async (keyring) => operation(keyring));
343
- }
344
- /**
345
- * Calls `KeyringController:withKeyring` for the MPC keyring with the given
346
- * ID.
205
+ * NOTE: This function won't check if a money keyring for the given entropy source already
206
+ * exists!
347
207
  *
348
- * @param id - The keyring metadata ID.
349
- * @param operation - Callback invoked with the resolved MPC keyring.
350
- * @returns The value returned by `operation`.
208
+ * @param entropySource - The entropy source ID to create the money keyring for.
209
+ * @returns The metadata of the newly created money keyring.
351
210
  */
352
- async #withMpcKeyring(id, operation) {
353
- return await this.#withKeyring(id, isMpcKeyring, async (keyring) => operation(keyring));
211
+ #createMoneyKeyring(entropySource) {
212
+ return this.messenger.call('KeyringController:addNewKeyring', KeyringTypes.money, {
213
+ entropySource,
214
+ });
354
215
  }
355
216
  /**
356
217
  * Gets the primary entropy source ID.
@@ -1 +1 @@
1
- {"version":3,"file":"MoneyAccountController.js","sourceRoot":"","sources":["../src/MoneyAccountController.ts"],"names":[],"mappings":"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","sourcesContent":["import { getUUIDFromAddressOfNormalAccount } from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { MoneyKeyring } from '@metamask/eth-money-keyring';\nimport { MONEY_DERIVATION_PATH } from '@metamask/eth-money-keyring';\nimport { EthAccountType, EthMethod, EthScope } from '@metamask/keyring-api';\nimport type { EntropySourceId } from '@metamask/keyring-api';\nimport type {\n KeyringControllerGetStateAction,\n KeyringControllerWithControllerAction,\n KeyringControllerWithKeyringAction,\n KeyringMetadata,\n} from '@metamask/keyring-controller';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport { EthKeyring } from '@metamask/keyring-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport type { Hex } from '@metamask/utils';\n\nimport { projectLogger as log } from './logger.js';\nimport type { MoneyAccountControllerMethodActions } from './MoneyAccountController-method-action-types.js';\nimport type { MoneyAccount, MoneyAccountEntropyOptions } from './types.js';\nimport {\n isMoneyKeyring,\n isMpcKeyring,\n MPC_ENTROPY_SOURCE_ID,\n} from './utils.js';\n\nexport const controllerName = 'MoneyAccountController';\n\n/**\n * Parameters for creating a money account.\n *\n * - `{ type: 'mpc' }`: create the MFA account backed by the MPC keyring.\n * - `{ type?: 'mnemonic', entropySource }` (the default): create the SFA\n * account backed by the `MoneyKeyring` for the given entropy source.\n */\nexport type CreateMoneyAccountParams =\n | {\n /**\n * The kind of money account to create. Defaults to `'mnemonic'`.\n */\n type?: 'mnemonic';\n\n /**\n * The entropy source ID of the SRP backing the account.\n */\n entropySource: EntropySourceId;\n }\n | {\n /**\n * The kind of money account to create.\n */\n type: 'mpc';\n };\n\nexport type MoneyAccountControllerState = {\n moneyAccounts: {\n [id: MoneyAccount['id']]: MoneyAccount;\n };\n defaultMoneyAccountId: MoneyAccount['id'] | null;\n};\n\nconst moneyAccountControllerMetadata = {\n moneyAccounts: {\n includeInDebugSnapshot: false,\n includeInStateLogs: true,\n persist: true,\n usedInUi: true,\n },\n defaultMoneyAccountId: {\n includeInDebugSnapshot: true,\n includeInStateLogs: true,\n persist: true,\n usedInUi: true,\n },\n} satisfies StateMetadata<MoneyAccountControllerState>;\n\nexport function getDefaultMoneyAccountControllerState(): MoneyAccountControllerState {\n return {\n moneyAccounts: {},\n defaultMoneyAccountId: null,\n };\n}\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'createMoneyAccount',\n 'getMoneyAccount',\n 'setDefaultMoneyAccount',\n 'clearState',\n 'init',\n] as const;\n\n/**\n * The signing methods supported by money accounts.\n */\nconst MONEY_ACCOUNT_METHODS = [\n EthMethod.PersonalSign,\n EthMethod.SignTypedDataV1,\n EthMethod.SignTypedDataV3,\n EthMethod.SignTypedDataV4,\n // TODO: Update this once the `keyring-api` package supports `SignEip7702Authorization` method.\n] as const;\n\nexport type MoneyAccountControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n MoneyAccountControllerState\n>;\n\nexport type MoneyAccountControllerActions =\n | MoneyAccountControllerGetStateAction\n | MoneyAccountControllerMethodActions;\n\ntype AllowedActions =\n | KeyringControllerGetStateAction\n | KeyringControllerWithControllerAction\n | KeyringControllerWithKeyringAction;\n\nexport type MoneyAccountControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n MoneyAccountControllerState\n>;\n\nexport type MoneyAccountControllerEvents =\n MoneyAccountControllerStateChangeEvent;\n\ntype AllowedEvents = never;\n\nexport type MoneyAccountControllerMessenger = Messenger<\n typeof controllerName,\n MoneyAccountControllerActions | AllowedActions,\n MoneyAccountControllerEvents | AllowedEvents\n>;\n\n/**\n * The shape of the MPC keyring operations used by this controller. The MPC\n * keyring is an atomic keyring: `init` is cheap if the keyring is already\n * initialized, and long-running work is dispatched without holding the\n * keyring controller mutex.\n */\ntype MpcKeyringLike = EthKeyring & {\n init: () => Promise<void>;\n};\n\n/**\n * Controller for managing money accounts.\n */\nexport class MoneyAccountController extends BaseController<\n typeof controllerName,\n MoneyAccountControllerState,\n MoneyAccountControllerMessenger\n> {\n /**\n * Constructor for the MoneyAccountController.\n *\n * @param options - The options for constructing the controller.\n * @param options.messenger - The messenger to use for inter-controller communication.\n * @param options.state - The initial state of the controller. If not provided, the default state will be used.\n */\n constructor({\n messenger,\n state,\n }: {\n messenger: MoneyAccountControllerMessenger;\n state?: Partial<MoneyAccountControllerState>;\n }) {\n super({\n messenger,\n metadata: moneyAccountControllerMetadata,\n name: controllerName,\n state: {\n ...getDefaultMoneyAccountControllerState(),\n ...state,\n },\n });\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Initializes the controller by creating a money account for the primary\n * entropy source if one does not already exist.\n */\n async init(): Promise<void> {\n this.#assertIsUnlocked();\n\n const primaryEntropySource = this.#getPrimaryEntropySource();\n if (primaryEntropySource) {\n const { id, address } = await this.createMoneyAccount({\n entropySource: primaryEntropySource,\n });\n log(\n `Money keyring (entropy:${primaryEntropySource} - primary) account is: ${address} (${id})`,\n );\n } else {\n const message =\n 'No primary HD keyring found, skipping default Money account creation!';\n\n console.warn(message);\n log(`WARNING -- ${message}`);\n }\n }\n\n /**\n * Creates a money account. If an account already exists for the given\n * source, it is returned as-is (idempotent).\n *\n * The parameters determine the backing keyring:\n * - `{ type: 'mpc' }`: the MPC keyring (MFA account), which is created and\n * initialized if it does not exist yet.\n * - `{ type?: 'mnemonic', entropySource }` (the default): the `MoneyKeyring`\n * for that entropy source (SFA account), which is created if it does not\n * exist yet.\n *\n * @param params - The parameters for creating the money account.\n * @returns The money account.\n */\n async createMoneyAccount(\n params: CreateMoneyAccountParams,\n ): Promise<MoneyAccount> {\n this.#assertIsUnlocked();\n\n // Idempotent: return existing account if already in state. The stored\n // entropy source ID identifies the account for both account kinds.\n const entropySourceId =\n params.type === 'mpc' ? MPC_ENTROPY_SOURCE_ID : params.entropySource;\n const existingAccount =\n this.#getMoneyAccountByEntropySource(entropySourceId);\n if (existingAccount) {\n return existingAccount;\n }\n\n const account =\n params.type === 'mpc'\n ? await this.#createMpcKeyringAccount()\n : await this.#createMoneyKeyringAccount(params.entropySource);\n\n log(\n `Money account created: ${account.address} (${account.id}) for entropy source: ${entropySourceId}`,\n );\n return account;\n }\n\n /**\n * Sets the default money account.\n *\n * @param id - The id of the money account to use as the default.\n */\n setDefaultMoneyAccount(id: MoneyAccount['id']): void {\n if (this.state.moneyAccounts[id] === undefined) {\n throw new Error(`Unknown money account: ${id}`);\n }\n\n this.update((state) => {\n state.defaultMoneyAccountId = id;\n });\n }\n\n /**\n * Gets a money account by id, by entropy source, or the default one.\n *\n * @param selector - Selector options for getting the money account.\n * @param selector.id - The account id to look up. Takes precedence over `entropySource`.\n * @param selector.entropySource - The entropy source ID to get the money account for.\n * @returns The money account, or `undefined` if none matches.\n */\n getMoneyAccount(\n selector: {\n id?: MoneyAccount['id'];\n entropySource?: EntropySourceId;\n } = {},\n ): MoneyAccount | undefined {\n if (selector.id !== undefined) {\n return this.state.moneyAccounts[selector.id];\n }\n\n if (selector.entropySource !== undefined) {\n return this.#getMoneyAccountByEntropySource(selector.entropySource);\n }\n\n const defaultMoneyAccountId = this.state.defaultMoneyAccountId ?? null;\n if (defaultMoneyAccountId === null) {\n return undefined;\n }\n\n return this.state.moneyAccounts[defaultMoneyAccountId];\n }\n\n /**\n * Resets the controller state to its default, removing all money accounts.\n *\n * Intended for use during a full app reset (e.g. when the user wipes all\n * wallet data). Does not interact with the keyring — the caller is\n * responsible for ensuring the associated keyring state is also cleared.\n */\n clearState(): void {\n this.update((state) => {\n state.moneyAccounts = {};\n state.defaultMoneyAccountId = null;\n });\n }\n\n /**\n * Creates or reuses a `MoneyKeyring` account for the given entropy source.\n *\n * @param entropySource - The entropy source ID to create the money account for.\n * @returns The money account.\n */\n async #createMoneyKeyringAccount(\n entropySource: EntropySourceId,\n ): Promise<MoneyAccount> {\n const id = await this.#ensureMoneyKeyring(entropySource);\n\n const address = await this.#withMoneyKeyring(id, async (keyring) => {\n // We're adding this logic to be defensive against the possibility of a money keyring\n // existing without any accounts, which shouldn't normally happen but we want to be\n // sure we can handle it if it does.\n // If there are no accounts, we'll add one and then get the address.\n const accounts = await keyring.getAccounts();\n if (accounts.length > 0) {\n const [moneyAddress] = accounts;\n return moneyAddress;\n }\n\n log(\n `Money keyring (id:${id}, entropy:${entropySource}) has no accounts, creating one...`,\n );\n const [moneyAddress] = await keyring.addAccounts(1);\n return moneyAddress;\n });\n\n return this.#createKeyringAccount({\n address,\n entropy: {\n type: 'mnemonic',\n id: entropySource,\n groupIndex: 0,\n derivationPath: MONEY_DERIVATION_PATH,\n },\n });\n }\n\n /**\n * Creates or reuses an account on the MPC keyring.\n *\n * The MPC keyring is an atomic keyring: its initialization is cheap when\n * already initialized, and long-running work is dispatched without holding\n * the keyring controller mutex.\n *\n * @returns The money account.\n */\n async #createMpcKeyringAccount(): Promise<MoneyAccount> {\n const id = await this.#ensureMpcKeyring();\n\n const address = await this.#withMpcKeyring(id, async (keyring) => {\n // The keyring infers the setup mode (create or import) from its own\n // state. This is a no-op if the keyring is already initialized.\n await keyring.init();\n\n // We're adding this logic to be defensive against the possibility of an\n // MPC keyring existing without any accounts, which shouldn't normally\n // happen but we want to be sure we can handle it if it does.\n const accounts = await keyring.getAccounts();\n if (accounts.length > 0) {\n const [mpcAddress] = accounts;\n return mpcAddress;\n }\n\n log(`MPC keyring (${id}) has no accounts, adding one...`);\n const [mpcAddress] = await keyring.addAccounts(1);\n return mpcAddress;\n });\n\n return this.#createKeyringAccount({\n address,\n entropy: {\n type: 'mpc',\n id: MPC_ENTROPY_SOURCE_ID,\n },\n });\n }\n\n /**\n * Builds a money account for the given address and entropy options, stores\n * it in state, and returns it. If no default account is set, the new account\n * becomes the default.\n *\n * @param params - The parameters for creating the account.\n * @param params.address - The account address.\n * @param params.entropy - The entropy options of the backing keyring.\n * @returns The money account.\n */\n #createKeyringAccount({\n address,\n entropy,\n }: {\n address: Hex;\n entropy: MoneyAccountEntropyOptions;\n }): MoneyAccount {\n const account: MoneyAccount = {\n // This is an EVM account, so let's re-use the deterministic ID generation logic of\n // EVM accounts.\n id: getUUIDFromAddressOfNormalAccount(address),\n type: EthAccountType.Eoa,\n address,\n scopes: [EthScope.Eoa],\n options: {\n entropy,\n exportable: false,\n },\n methods: [...MONEY_ACCOUNT_METHODS],\n };\n\n this.update((state) => {\n state.moneyAccounts[account.id] = account;\n state.defaultMoneyAccountId ??= account.id;\n });\n\n return account;\n }\n\n /**\n * Gets a money account by entropy source ID.\n *\n * @param entropySource - The entropy source ID.\n * @returns The matching account, if any.\n */\n #getMoneyAccountByEntropySource(\n entropySource: EntropySourceId,\n ): MoneyAccount | undefined {\n return Object.values(this.state.moneyAccounts).find(\n (account) => account.options.entropy.id === entropySource,\n );\n }\n\n /**\n * Ensures a `MoneyKeyring` exists for the given entropy source, creating one\n * atomically if it does not, and returns its keyring ID.\n *\n * The check-or-create is performed within a single\n * `KeyringController:withController` transaction, which is mutually\n * exclusive and rolls back on error.\n *\n * @param entropySource - The entropy source ID identifying the target keyring.\n * @returns The keyring ID of the existing or newly created keyring.\n */\n async #ensureMoneyKeyring(entropySource: EntropySourceId): Promise<string> {\n return (await this.messenger.call(\n 'KeyringController:withController',\n async (restrictedController) => {\n const moneyKeyrings = restrictedController.keyrings.filter(\n (entry) =>\n isMoneyKeyring(entry.keyring) &&\n entry.keyring.entropySource === entropySource,\n );\n\n if (moneyKeyrings.length > 0) {\n return moneyKeyrings[0].metadata.id;\n }\n\n log(\n `Money keyring (entropy:${entropySource}) not found, creating one...`,\n );\n const entry = await restrictedController.addNewKeyring(\n KeyringTypes.money,\n { entropySource },\n );\n return entry.metadata.id;\n },\n )) as string;\n }\n\n /**\n * Ensures the MPC keyring exists, creating it atomically if it does not, and\n * returns its keyring ID.\n *\n * The check-or-create is performed within a single\n * `KeyringController:withController` transaction, which is mutually\n * exclusive and rolls back on error.\n *\n * @returns The keyring ID of the existing or newly created keyring.\n */\n async #ensureMpcKeyring(): Promise<string> {\n return (await this.messenger.call(\n 'KeyringController:withController',\n async (restrictedController) => {\n const mpcKeyrings = restrictedController.keyrings.filter((entry) =>\n isMpcKeyring(entry.keyring),\n );\n\n if (mpcKeyrings.length > 1) {\n throw new Error('Multiple MPC keyrings found');\n }\n\n if (mpcKeyrings.length === 1) {\n return mpcKeyrings[0].metadata.id;\n }\n\n log('MPC keyring not found, creating one...');\n const entry = await restrictedController.addNewKeyring(\n KeyringTypes.mpc,\n );\n return entry.metadata.id;\n },\n )) as string;\n }\n\n /**\n * Calls `KeyringController:withKeyring` for the keyring with the given ID.\n *\n * @param id - The keyring metadata ID.\n * @param assertType - Verifies the resolved keyring has the expected type.\n * @param operation - Callback invoked with the resolved keyring.\n * @returns The value returned by `operation`.\n */\n async #withKeyring<Result>(\n id: string,\n assertType: (keyring: EthKeyring) => boolean,\n operation: (keyring: EthKeyring) => Promise<Result>,\n ): Promise<Result> {\n return (await this.messenger.call(\n 'KeyringController:withKeyring',\n { id },\n async ({ keyring }) => {\n if (!assertType(keyring)) {\n throw new Error(`Keyring ${id} has an unexpected type`);\n }\n return operation(keyring);\n },\n )) as Result;\n }\n\n /**\n * Calls `KeyringController:withKeyring` for the `MoneyKeyring` with the\n * given ID.\n *\n * @param id - The keyring metadata ID.\n * @param operation - Callback invoked with the resolved `MoneyKeyring`.\n * @returns The value returned by `operation`.\n */\n async #withMoneyKeyring<Result>(\n id: string,\n operation: (keyring: MoneyKeyring) => Promise<Result>,\n ): Promise<Result> {\n return await this.#withKeyring(id, isMoneyKeyring, async (keyring) =>\n operation(keyring as MoneyKeyring),\n );\n }\n\n /**\n * Calls `KeyringController:withKeyring` for the MPC keyring with the given\n * ID.\n *\n * @param id - The keyring metadata ID.\n * @param operation - Callback invoked with the resolved MPC keyring.\n * @returns The value returned by `operation`.\n */\n async #withMpcKeyring<Result>(\n id: string,\n operation: (keyring: MpcKeyringLike) => Promise<Result>,\n ): Promise<Result> {\n return await this.#withKeyring(id, isMpcKeyring, async (keyring) =>\n operation(keyring as MpcKeyringLike),\n );\n }\n\n /**\n * Gets the primary entropy source ID.\n *\n * @returns The primary entropy source ID, or `undefined` if no HD keyring exists.\n */\n #getPrimaryEntropySource(): EntropySourceId | undefined {\n const { keyrings } = this.messenger.call('KeyringController:getState');\n const primaryHdKeyring = keyrings.find(\n (keyring) => keyring.type === KeyringTypes.hd,\n );\n return primaryHdKeyring?.metadata.id;\n }\n\n /**\n * Throws if the keyring is currently locked.\n */\n #assertIsUnlocked(): void {\n const { isUnlocked } = this.messenger.call('KeyringController:getState');\n if (!isUnlocked) {\n throw new Error(\n 'Cannot create a money account while the keyring is locked',\n );\n }\n }\n}\n"]}
1
+ {"version":3,"file":"MoneyAccountController.js","sourceRoot":"","sources":["../src/MoneyAccountController.ts"],"names":[],"mappings":"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","sourcesContent":["import { getUUIDFromAddressOfNormalAccount } from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type {\n MoneyKeyring,\n MoneyKeyringSerializedState,\n} from '@metamask/eth-money-keyring';\nimport { MONEY_DERIVATION_PATH } from '@metamask/eth-money-keyring';\nimport { EthAccountType, EthMethod, EthScope } from '@metamask/keyring-api';\nimport type { EntropySourceId } from '@metamask/keyring-api';\nimport type {\n KeyringControllerAddNewKeyringAction,\n KeyringControllerGetStateAction,\n KeyringControllerWithKeyringAction,\n KeyringMetadata,\n KeyringSelector,\n} from '@metamask/keyring-controller';\nimport {\n isKeyringNotFoundError,\n KeyringTypes,\n} from '@metamask/keyring-controller';\nimport { EthKeyring } from '@metamask/keyring-utils';\nimport type { Messenger } from '@metamask/messenger';\nimport { Mutex } from 'async-mutex';\n\nimport { projectLogger as log } from './logger.js';\nimport type { MoneyAccountControllerMethodActions } from './MoneyAccountController-method-action-types.js';\nimport type { MoneyAccount } from './types.js';\nimport { isMoneyKeyring } from './utils.js';\n\nexport const controllerName = 'MoneyAccountController';\n\nexport type MoneyAccountControllerState = {\n moneyAccounts: {\n [id: MoneyAccount['id']]: MoneyAccount;\n };\n};\n\nconst moneyAccountControllerMetadata = {\n moneyAccounts: {\n includeInDebugSnapshot: false,\n includeInStateLogs: true,\n persist: true,\n usedInUi: true,\n },\n} satisfies StateMetadata<MoneyAccountControllerState>;\n\nexport function getDefaultMoneyAccountControllerState(): MoneyAccountControllerState {\n return {\n moneyAccounts: {},\n };\n}\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'createMoneyAccount',\n 'getMoneyAccount',\n 'clearState',\n 'init',\n] as const;\n\nexport type MoneyAccountControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n MoneyAccountControllerState\n>;\n\nexport type MoneyAccountControllerActions =\n | MoneyAccountControllerGetStateAction\n | MoneyAccountControllerMethodActions;\n\ntype AllowedActions =\n | KeyringControllerGetStateAction\n | KeyringControllerAddNewKeyringAction\n | KeyringControllerWithKeyringAction;\n\nexport type MoneyAccountControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n MoneyAccountControllerState\n>;\n\nexport type MoneyAccountControllerEvents =\n MoneyAccountControllerStateChangeEvent;\n\ntype AllowedEvents = never;\n\nexport type MoneyAccountControllerMessenger = Messenger<\n typeof controllerName,\n MoneyAccountControllerActions | AllowedActions,\n MoneyAccountControllerEvents | AllowedEvents\n>;\n\n/**\n * Controller for managing money accounts.\n */\nexport class MoneyAccountController extends BaseController<\n typeof controllerName,\n MoneyAccountControllerState,\n MoneyAccountControllerMessenger\n> {\n readonly #lock: Mutex;\n\n /**\n * Constructor for the MoneyAccountController.\n *\n * @param options - The options for constructing the controller.\n * @param options.messenger - The messenger to use for inter-controller communication.\n * @param options.state - The initial state of the controller. If not provided, the default state will be used.\n */\n constructor({\n messenger,\n state,\n }: {\n messenger: MoneyAccountControllerMessenger;\n state?: Partial<MoneyAccountControllerState>;\n }) {\n super({\n messenger,\n metadata: moneyAccountControllerMetadata,\n name: controllerName,\n state: {\n ...getDefaultMoneyAccountControllerState(),\n ...state,\n },\n });\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n this.#lock = new Mutex();\n }\n\n /**\n * Initializes the controller by creating a money account for the primary\n * entropy source if one does not already exist.\n */\n async init(): Promise<void> {\n this.#assertIsUnlocked();\n\n const primaryEntropySource = this.#getPrimaryEntropySource();\n if (primaryEntropySource) {\n const { id, address } =\n await this.createMoneyAccount(primaryEntropySource);\n log(\n `Money keyring (entropy:${primaryEntropySource} - primary) account is: ${address} (${id})`,\n );\n } else {\n const message =\n 'No primary HD keyring found, skipping default Money account creation!';\n\n console.warn(message);\n log(`WARNING -- ${message}`);\n }\n }\n\n /**\n * Creates a money account for the given entropy source. If an account\n * already exists for that entropy source, it is returned as-is (idempotent).\n *\n * @param entropySource - The entropy source ID to create the money account for.\n * @returns The money account.\n */\n async createMoneyAccount(\n entropySource: EntropySourceId,\n ): Promise<MoneyAccount> {\n this.#assertIsUnlocked();\n\n // Idempotent: return existing account if already in state.\n const existingAccount = this.getMoneyAccount({ entropySource });\n if (existingAccount) {\n return existingAccount;\n }\n\n const address = await this.#withKeyring(entropySource, async (keyring) => {\n // We're adding this logic to be defensive against the possibility of a money keyring\n // existing without any accounts, which shouldn't normally happen but we want to be\n // sure we can handle it if it does.\n // If there are no accounts, we'll add one and then get the address.\n const accounts = await keyring.getAccounts();\n if (accounts.length > 0) {\n const [moneyAddress] = accounts;\n return moneyAddress;\n }\n\n log(\n `Money keyring (entropy:${entropySource}) has no accounts, creating one...`,\n );\n const [moneyAddress] = await keyring.addAccounts(1);\n return moneyAddress;\n });\n\n const account: MoneyAccount = {\n // This is an EVM account, so let's re-use the deterministic ID generation logic of\n // EVM accounts.\n id: getUUIDFromAddressOfNormalAccount(address),\n type: EthAccountType.Eoa,\n address,\n scopes: [EthScope.Eoa],\n options: {\n entropy: {\n type: 'mnemonic',\n id: entropySource,\n groupIndex: 0,\n derivationPath: MONEY_DERIVATION_PATH,\n },\n exportable: false,\n },\n methods: [\n EthMethod.PersonalSign,\n EthMethod.SignTypedDataV1,\n EthMethod.SignTypedDataV3,\n EthMethod.SignTypedDataV4,\n // TODO: Update this once the `keyring-api` package supports `SignEip7702Authorization` method.\n ],\n };\n\n // Store the account in state.\n this.update((state) => {\n state.moneyAccounts[account.id] = account;\n });\n\n log(\n `Money keyring (entropy:${account.options.entropy.id}) account created: ${account.address} (${account.id})`,\n );\n return account;\n }\n\n /**\n * Gets a money account by its associated entropy source ID. If no ID is\n * provided, the primary entropy source will be used.\n *\n * @param selector - Selector options for getting the money account.\n * @param selector.entropySource - The entropy source ID to get the money account for. If not provided, the primary entropy source will be used.\n * @returns The money account, or `undefined` if no account exists for the given entropy source.\n */\n getMoneyAccount(\n selector: { entropySource?: EntropySourceId } = {},\n ): MoneyAccount | undefined {\n const entropySource =\n selector.entropySource ?? this.#getPrimaryEntropySource();\n if (entropySource === undefined) {\n return undefined;\n }\n\n // We should never have more than one money account per entropy source, but if we\n // do, just return the first one we find.\n return Object.values(this.state.moneyAccounts).find(\n (account) => account.options.entropy.id === entropySource,\n );\n }\n\n /**\n * Resets the controller state to its default, removing all money accounts.\n *\n * Intended for use during a full app reset (e.g. when the user wipes all\n * wallet data). Does not interact with the keyring — the caller is\n * responsible for ensuring the associated keyring state is also cleared.\n */\n clearState(): void {\n this.update((state) => {\n state.moneyAccounts = {};\n });\n }\n\n /**\n * Calls `KeyringController:withKeyring` for the `MoneyKeyring` associated with the\n * given entropy source, creating one first if it does not yet exist.\n *\n * @param entropySource - The entropy source ID identifying the target keyring.\n * @param operation - Callback invoked with the resolved `MoneyKeyring`.\n * @returns The value returned by `operation`.\n */\n async #withKeyring<Result>(\n entropySource: EntropySourceId,\n operation: (keyring: MoneyKeyring) => Promise<Result>,\n ): Promise<Result> {\n // Filter to find a specific `MoneyKeyring` for the given entropy source.\n const isMoneyKeyringForEntropySource = (\n keyring: EthKeyring,\n ): keyring is MoneyKeyring =>\n isMoneyKeyring(keyring) && keyring.entropySource === entropySource;\n\n // We cannot use proper generic-type inference using the messenger\n // here, so we have to use a type casts for `keyring` and the return type.\n const withKeyring = async (\n selector: KeyringSelector<MoneyKeyring>,\n callback: (keyring: MoneyKeyring) => Promise<Result>,\n ): Promise<Result> =>\n this.messenger.call(\n 'KeyringController:withKeyring',\n selector,\n async ({ keyring }) => callback(keyring as MoneyKeyring),\n ) as Promise<Result>;\n\n // We have an extra lock here to avoid a race-condition where 2 calls to\n // `#withKeyring` for the same entropy source happen at the same time, and\n // both don't find an existing keyring, so they both try to create a new\n // one, which creates multiple keyrings for the same entropy source.\n // NOTE: We cannot use `createIfMissing` here either, since it's only supported\n // for selectors by type (and we want to deprecate this option).\n // TODO: Move this new pattern in the `KeyringController`.\n return await this.#lock.runExclusive(async () => {\n try {\n return await withKeyring(\n {\n filter: isMoneyKeyringForEntropySource,\n },\n operation,\n );\n } catch (error) {\n // Forward any unexpected errors, but if the error is that\n // the keyring wasn't found, we'll create it below.\n if (!isKeyringNotFoundError(error)) {\n throw error;\n }\n\n // Create the keyring so we can use `withKeyring` to operate on it in the\n // retry below.\n log(\n `Money keyring (entropy:${entropySource}) not found, creating one...`,\n );\n const { id } = await this.#createMoneyKeyring(entropySource);\n\n // Use the ID directly on the retry (we just created this keyring so we\n // know exactly which one to target).\n return await withKeyring({ id }, operation);\n }\n });\n }\n\n /**\n * Adds a new money keyring for the given entropy source and returns its metadata.\n *\n * NOTE: This function won't check if a money keyring for the given entropy source already\n * exists!\n *\n * @param entropySource - The entropy source ID to create the money keyring for.\n * @returns The metadata of the newly created money keyring.\n */\n #createMoneyKeyring(\n entropySource: EntropySourceId,\n ): Promise<KeyringMetadata> {\n return this.messenger.call(\n 'KeyringController:addNewKeyring',\n KeyringTypes.money,\n {\n entropySource,\n },\n );\n }\n\n /**\n * Gets the primary entropy source ID.\n *\n * @returns The primary entropy source ID, or `undefined` if no HD keyring exists.\n */\n #getPrimaryEntropySource(): EntropySourceId | undefined {\n const { keyrings } = this.messenger.call('KeyringController:getState');\n const primaryHdKeyring = keyrings.find(\n (keyring) => keyring.type === KeyringTypes.hd,\n );\n return primaryHdKeyring?.metadata.id;\n }\n\n /**\n * Throws if the keyring is currently locked.\n */\n #assertIsUnlocked(): void {\n const { isUnlocked } = this.messenger.call('KeyringController:getState');\n if (!isUnlocked) {\n throw new Error(\n 'Cannot create a money account while the keyring is locked',\n );\n }\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export type { MoneyAccount, MoneyAccountEntropyMpcOptions, MoneyAccountEntropyOptions, } from './types.js';
2
- export { MPC_ENTROPY_SOURCE_ID, isMoneyKeyring, isMpcKeyring, } from './utils.js';
1
+ export type { MoneyAccount } from './types.js';
2
+ export { isMoneyKeyring } from './utils.js';
3
3
  export { MoneyAccountController, controllerName, getDefaultMoneyAccountControllerState, } from './MoneyAccountController.js';
4
- export type { MoneyAccountControllerState, MoneyAccountControllerGetStateAction, MoneyAccountControllerActions, MoneyAccountControllerStateChangeEvent, MoneyAccountControllerEvents, MoneyAccountControllerMessenger, CreateMoneyAccountParams, } from './MoneyAccountController.js';
5
- export type { MoneyAccountControllerClearStateAction, MoneyAccountControllerCreateMoneyAccountAction, MoneyAccountControllerGetMoneyAccountAction, MoneyAccountControllerInitAction, MoneyAccountControllerSetDefaultMoneyAccountAction, } from './MoneyAccountController-method-action-types.js';
4
+ export type { MoneyAccountControllerState, MoneyAccountControllerGetStateAction, MoneyAccountControllerActions, MoneyAccountControllerStateChangeEvent, MoneyAccountControllerEvents, MoneyAccountControllerMessenger, } from './MoneyAccountController.js';
5
+ export type { MoneyAccountControllerClearStateAction, MoneyAccountControllerCreateMoneyAccountAction, MoneyAccountControllerGetMoneyAccountAction, MoneyAccountControllerInitAction, } from './MoneyAccountController-method-action-types.js';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,YAAY,EACZ,6BAA6B,EAC7B,0BAA0B,GAC3B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,qBAAqB,EACrB,cAAc,EACd,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,qCAAqC,GACtC,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,2BAA2B,EAC3B,oCAAoC,EACpC,6BAA6B,EAC7B,sCAAsC,EACtC,4BAA4B,EAC5B,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,sCAAsC,EACtC,8CAA8C,EAC9C,2CAA2C,EAC3C,gCAAgC,EAChC,kDAAkD,GACnD,MAAM,iDAAiD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,qCAAqC,GACtC,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,2BAA2B,EAC3B,oCAAoC,EACpC,6BAA6B,EAC7B,sCAAsC,EACtC,4BAA4B,EAC5B,+BAA+B,GAChC,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,sCAAsC,EACtC,8CAA8C,EAC9C,2CAA2C,EAC3C,gCAAgC,GACjC,MAAM,iDAAiD,CAAC"}
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { MPC_ENTROPY_SOURCE_ID, isMoneyKeyring, isMpcKeyring, } from './utils.js';
1
+ export { isMoneyKeyring } from './utils.js';
2
2
  export { MoneyAccountController, controllerName, getDefaultMoneyAccountControllerState, } from './MoneyAccountController.js';
3
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,qBAAqB,EACrB,cAAc,EACd,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,qCAAqC,GACtC,MAAM,6BAA6B,CAAC","sourcesContent":["export type {\n MoneyAccount,\n MoneyAccountEntropyMpcOptions,\n MoneyAccountEntropyOptions,\n} from './types.js';\nexport {\n MPC_ENTROPY_SOURCE_ID,\n isMoneyKeyring,\n isMpcKeyring,\n} from './utils.js';\nexport {\n MoneyAccountController,\n controllerName,\n getDefaultMoneyAccountControllerState,\n} from './MoneyAccountController.js';\nexport type {\n MoneyAccountControllerState,\n MoneyAccountControllerGetStateAction,\n MoneyAccountControllerActions,\n MoneyAccountControllerStateChangeEvent,\n MoneyAccountControllerEvents,\n MoneyAccountControllerMessenger,\n CreateMoneyAccountParams,\n} from './MoneyAccountController.js';\nexport type {\n MoneyAccountControllerClearStateAction,\n MoneyAccountControllerCreateMoneyAccountAction,\n MoneyAccountControllerGetMoneyAccountAction,\n MoneyAccountControllerInitAction,\n MoneyAccountControllerSetDefaultMoneyAccountAction,\n} from './MoneyAccountController-method-action-types.js';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,qCAAqC,GACtC,MAAM,6BAA6B,CAAC","sourcesContent":["export type { MoneyAccount } from './types.js';\nexport { isMoneyKeyring } from './utils.js';\nexport {\n MoneyAccountController,\n controllerName,\n getDefaultMoneyAccountControllerState,\n} from './MoneyAccountController.js';\nexport type {\n MoneyAccountControllerState,\n MoneyAccountControllerGetStateAction,\n MoneyAccountControllerActions,\n MoneyAccountControllerStateChangeEvent,\n MoneyAccountControllerEvents,\n MoneyAccountControllerMessenger,\n} from './MoneyAccountController.js';\nexport type {\n MoneyAccountControllerClearStateAction,\n MoneyAccountControllerCreateMoneyAccountAction,\n MoneyAccountControllerGetMoneyAccountAction,\n MoneyAccountControllerInitAction,\n} from './MoneyAccountController-method-action-types.js';\n"]}
package/dist/types.d.ts CHANGED
@@ -1,29 +1,8 @@
1
- import type { KeyringAccount, KeyringAccountEntropyMnemonicOptions, EntropySourceId } from '@metamask/keyring-api';
2
- /**
3
- * Entropy options for MPC-backed money accounts. The entropy source ID is a
4
- * static identifier, as the MPC architecture currently yields a single keyring
5
- * (and account) per wallet.
6
- */
7
- export type MoneyAccountEntropyMpcOptions = {
8
- type: 'mpc';
9
- /**
10
- * The entropy source ID (e.g. `entropy:mpc:_`).
11
- */
12
- id: EntropySourceId;
13
- };
14
- /**
15
- * Entropy options for money accounts.
16
- *
17
- * - `'mnemonic'`: the account is derived from a BIP-44 mnemonic (SRP). This is
18
- * the SFA (single-factor authentication) account.
19
- * - `'mpc'`: the account is backed by an MPC keyring. This is the MFA
20
- * (multi-factor authentication) account.
21
- */
22
- export type MoneyAccountEntropyOptions = KeyringAccountEntropyMnemonicOptions | MoneyAccountEntropyMpcOptions;
1
+ import type { KeyringAccount, KeyringAccountEntropyMnemonicOptions } from '@metamask/keyring-api';
23
2
  /** A money account represents an account managed by the MoneyAccountController. */
24
3
  export type MoneyAccount = Omit<KeyringAccount, 'options'> & {
25
4
  options: {
26
- entropy: MoneyAccountEntropyOptions;
5
+ entropy: KeyringAccountEntropyMnemonicOptions;
27
6
  exportable: false;
28
7
  };
29
8
  };
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,oCAAoC,EACpC,eAAe,EAChB,MAAM,uBAAuB,CAAC;AAE/B;;;;GAIG;AACH,MAAM,MAAM,6BAA6B,GAAG;IAC1C,IAAI,EAAE,KAAK,CAAC;IAEZ;;OAEG;IACH,EAAE,EAAE,eAAe,CAAC;CACrB,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,0BAA0B,GAClC,oCAAoC,GACpC,6BAA6B,CAAC;AAElC,mFAAmF;AACnF,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,GAAG;IAG3D,OAAO,EAAE;QACP,OAAO,EAAE,0BAA0B,CAAC;QACpC,UAAU,EAAE,KAAK,CAAC;KACnB,CAAC;CACH,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,oCAAoC,EACrC,MAAM,uBAAuB,CAAC;AAE/B,mFAAmF;AACnF,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,GAAG;IAG3D,OAAO,EAAE;QACP,OAAO,EAAE,oCAAoC,CAAC;QAC9C,UAAU,EAAE,KAAK,CAAC;KACnB,CAAC;CACH,CAAC"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n KeyringAccount,\n KeyringAccountEntropyMnemonicOptions,\n EntropySourceId,\n} from '@metamask/keyring-api';\n\n/**\n * Entropy options for MPC-backed money accounts. The entropy source ID is a\n * static identifier, as the MPC architecture currently yields a single keyring\n * (and account) per wallet.\n */\nexport type MoneyAccountEntropyMpcOptions = {\n type: 'mpc';\n\n /**\n * The entropy source ID (e.g. `entropy:mpc:_`).\n */\n id: EntropySourceId;\n};\n\n/**\n * Entropy options for money accounts.\n *\n * - `'mnemonic'`: the account is derived from a BIP-44 mnemonic (SRP). This is\n * the SFA (single-factor authentication) account.\n * - `'mpc'`: the account is backed by an MPC keyring. This is the MFA\n * (multi-factor authentication) account.\n */\nexport type MoneyAccountEntropyOptions =\n | KeyringAccountEntropyMnemonicOptions\n | MoneyAccountEntropyMpcOptions;\n\n/** A money account represents an account managed by the MoneyAccountController. */\nexport type MoneyAccount = Omit<KeyringAccount, 'options'> & {\n // We use stricter options for money accounts. They can be seen as BIP-44 accounts\n // and we make them non-exportable too.\n options: {\n entropy: MoneyAccountEntropyOptions;\n exportable: false;\n };\n};\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n KeyringAccount,\n KeyringAccountEntropyMnemonicOptions,\n} from '@metamask/keyring-api';\n\n/** A money account represents an account managed by the MoneyAccountController. */\nexport type MoneyAccount = Omit<KeyringAccount, 'options'> & {\n // We use stricter options for money accounts. They can be seen as BIP-44 accounts\n // and we make them non-exportable too.\n options: {\n entropy: KeyringAccountEntropyMnemonicOptions;\n exportable: false;\n };\n};\n"]}
package/dist/utils.d.ts CHANGED
@@ -1,11 +1,5 @@
1
1
  import type { MoneyKeyring } from '@metamask/eth-money-keyring';
2
2
  import { EthKeyring } from '@metamask/keyring-utils';
3
- /**
4
- * The static entropy source ID for MPC-backed money accounts. The MPC
5
- * architecture currently yields a single keyring (and account) per wallet, so
6
- * a static identifier is sufficient.
7
- */
8
- export declare const MPC_ENTROPY_SOURCE_ID: 'entropy:mpc:_';
9
3
  /**
10
4
  * Returns `true` if the given keyring is a {@link MoneyKeyring}.
11
5
  *
@@ -13,11 +7,4 @@ export declare const MPC_ENTROPY_SOURCE_ID: 'entropy:mpc:_';
13
7
  * @returns Whether the keyring is a `MoneyKeyring`.
14
8
  */
15
9
  export declare function isMoneyKeyring(keyring: EthKeyring): keyring is MoneyKeyring;
16
- /**
17
- * Returns `true` if the given keyring is an MPC keyring.
18
- *
19
- * @param keyring - The keyring to check.
20
- * @returns Whether the keyring is an MPC keyring.
21
- */
22
- export declare function isMpcKeyring(keyring: EthKeyring): boolean;
23
10
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAG,eAAwB,CAAC;AAE9D;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,IAAI,YAAY,CAE3E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAEzD"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAErD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,IAAI,YAAY,CAE3E"}
package/dist/utils.js CHANGED
@@ -1,10 +1,4 @@
1
1
  import { KeyringTypes } from '@metamask/keyring-controller';
2
- /**
3
- * The static entropy source ID for MPC-backed money accounts. The MPC
4
- * architecture currently yields a single keyring (and account) per wallet, so
5
- * a static identifier is sufficient.
6
- */
7
- export const MPC_ENTROPY_SOURCE_ID = 'entropy:mpc:_';
8
2
  /**
9
3
  * Returns `true` if the given keyring is a {@link MoneyKeyring}.
10
4
  *
@@ -14,13 +8,4 @@ export const MPC_ENTROPY_SOURCE_ID = 'entropy:mpc:_';
14
8
  export function isMoneyKeyring(keyring) {
15
9
  return keyring.type === KeyringTypes.money;
16
10
  }
17
- /**
18
- * Returns `true` if the given keyring is an MPC keyring.
19
- *
20
- * @param keyring - The keyring to check.
21
- * @returns Whether the keyring is an MPC keyring.
22
- */
23
- export function isMpcKeyring(keyring) {
24
- return keyring.type === KeyringTypes.mpc;
25
- }
26
11
  //# sourceMappingURL=utils.js.map
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAG5D;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,eAAwB,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAAmB;IAChD,OAAO,OAAO,CAAC,IAAI,KAAK,YAAY,CAAC,KAAK,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,OAAmB;IAC9C,OAAO,OAAO,CAAC,IAAI,KAAK,YAAY,CAAC,GAAG,CAAC;AAC3C,CAAC","sourcesContent":["import type { MoneyKeyring } from '@metamask/eth-money-keyring';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport { EthKeyring } from '@metamask/keyring-utils';\n\n/**\n * The static entropy source ID for MPC-backed money accounts. The MPC\n * architecture currently yields a single keyring (and account) per wallet, so\n * a static identifier is sufficient.\n */\nexport const MPC_ENTROPY_SOURCE_ID = 'entropy:mpc:_' as const;\n\n/**\n * Returns `true` if the given keyring is a {@link MoneyKeyring}.\n *\n * @param keyring - The keyring to check.\n * @returns Whether the keyring is a `MoneyKeyring`.\n */\nexport function isMoneyKeyring(keyring: EthKeyring): keyring is MoneyKeyring {\n return keyring.type === KeyringTypes.money;\n}\n\n/**\n * Returns `true` if the given keyring is an MPC keyring.\n *\n * @param keyring - The keyring to check.\n * @returns Whether the keyring is an MPC keyring.\n */\nexport function isMpcKeyring(keyring: EthKeyring): boolean {\n return keyring.type === KeyringTypes.mpc;\n}\n"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAG5D;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAAmB;IAChD,OAAO,OAAO,CAAC,IAAI,KAAK,YAAY,CAAC,KAAK,CAAC;AAC7C,CAAC","sourcesContent":["import type { MoneyKeyring } from '@metamask/eth-money-keyring';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport { EthKeyring } from '@metamask/keyring-utils';\n\n/**\n * Returns `true` if the given keyring is a {@link MoneyKeyring}.\n *\n * @param keyring - The keyring to check.\n * @returns Whether the keyring is a `MoneyKeyring`.\n */\nexport function isMoneyKeyring(keyring: EthKeyring): keyring is MoneyKeyring {\n return keyring.type === KeyringTypes.money;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask-previews/money-account-controller",
3
- "version": "2.0.0-preview-0553ce5",
3
+ "version": "2.0.0-preview-7ef511c85",
4
4
  "description": "MetaMask Money account controller",
5
5
  "keywords": [
6
6
  "Ethereum",
@@ -51,11 +51,12 @@
51
51
  },
52
52
  "dependencies": {
53
53
  "@metamask/accounts-controller": "^40.1.0",
54
- "@metamask/base-controller": "^10.1.0",
54
+ "@metamask/base-controller": "^10.0.0",
55
55
  "@metamask/eth-money-keyring": "^4.0.0",
56
56
  "@metamask/keyring-api": "^24.3.0",
57
57
  "@metamask/keyring-controller": "^28.2.0",
58
- "@metamask/messenger": "^3.0.0"
58
+ "@metamask/messenger": "^3.0.0",
59
+ "async-mutex": "^0.5.0"
59
60
  },
60
61
  "devDependencies": {
61
62
  "@metamask/auto-changelog": "^6.2.1",