@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 +0 -10
- package/dist/MoneyAccountController-method-action-types.d.ts +8 -24
- package/dist/MoneyAccountController-method-action-types.d.ts.map +1 -1
- package/dist/MoneyAccountController-method-action-types.js.map +1 -1
- package/dist/MoneyAccountController.d.ts +10 -47
- package/dist/MoneyAccountController.d.ts.map +1 -1
- package/dist/MoneyAccountController.js +95 -234
- package/dist/MoneyAccountController.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +2 -23
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +0 -13
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +0 -15
- package/dist/utils.js.map +1 -1
- package/package.json +4 -3
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
|
|
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
|
|
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
|
-
*
|
|
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.
|
|
46
|
-
* @
|
|
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 |
|
|
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
|
|
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
|
|
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 {
|
|
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 |
|
|
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
|
|
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
|
|
47
|
+
* @param entropySource - The entropy source ID to create the money account for.
|
|
78
48
|
* @returns The money account.
|
|
79
49
|
*/
|
|
80
|
-
createMoneyAccount(
|
|
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
|
|
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.
|
|
92
|
-
* @
|
|
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;
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
78
|
+
async createMoneyAccount(entropySource) {
|
|
103
79
|
this.#assertIsUnlocked();
|
|
104
|
-
// Idempotent: return existing account if already in state.
|
|
105
|
-
|
|
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
|
|
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 (
|
|
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: [
|
|
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
|
|
265
|
-
* @
|
|
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
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
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
|
|
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
|
|
321
|
-
* @param
|
|
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(
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
335
|
-
* given ID.
|
|
203
|
+
* Adds a new money keyring for the given entropy source and returns its metadata.
|
|
336
204
|
*
|
|
337
|
-
*
|
|
338
|
-
*
|
|
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
|
|
349
|
-
* @
|
|
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
|
-
|
|
353
|
-
return
|
|
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
|
|
2
|
-
export {
|
|
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,
|
|
5
|
-
export type { MoneyAccountControllerClearStateAction, MoneyAccountControllerCreateMoneyAccountAction, MoneyAccountControllerGetMoneyAccountAction, MoneyAccountControllerInitAction,
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,
|
|
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 {
|
|
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":"
|
|
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
|
|
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:
|
|
5
|
+
entropy: KeyringAccountEntropyMnemonicOptions;
|
|
27
6
|
exportable: false;
|
|
28
7
|
};
|
|
29
8
|
};
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,oCAAoC,
|
|
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
|
|
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
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -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
|
|
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
|
|
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-
|
|
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.
|
|
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",
|