@metamask-previews/account-tree-controller 10.0.1-preview-a2f6118d2 → 11.0.0-preview-df2073e
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 +15 -2
- package/dist/AccountTreeController-method-action-types.d.ts +19 -1
- package/dist/AccountTreeController-method-action-types.d.ts.map +1 -1
- package/dist/AccountTreeController-method-action-types.js.map +1 -1
- package/dist/AccountTreeController.d.ts +15 -0
- package/dist/AccountTreeController.d.ts.map +1 -1
- package/dist/AccountTreeController.js +110 -0
- package/dist/AccountTreeController.js.map +1 -1
- package/dist/errors.d.ts +16 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +18 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/rules/entropy.d.ts +8 -0
- package/dist/rules/entropy.d.ts.map +1 -1
- package/dist/rules/entropy.js +12 -3
- package/dist/rules/entropy.js.map +1 -1
- package/dist/types.d.ts +4 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -7,10 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [11.0.0]
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **BREAKING:** Add `AccountTreeController:removeAccountWallet` ([#10253](https://github.com/MetaMask/core/pull/10253))
|
|
15
|
+
- It removes all accounts in a non-primary wallet.
|
|
16
|
+
- It rejects removal of the primary HD wallet.
|
|
17
|
+
- We now need those new actions on the messenger `MultichainAccountService:removeMultichainAccountWallet`, `KeyringController:removeAccount` and `AccountsController:getAccounts`.
|
|
18
|
+
- Also reports errors for non-entropy account wallet removal failures, matching the pattern used by `MultichainAccountService:removeMultichainAccountWallet`.
|
|
19
|
+
|
|
10
20
|
### Changed
|
|
11
21
|
|
|
12
|
-
- Bump `@metamask/profile-sync-controller` from `^32.0.0` to `^
|
|
22
|
+
- Bump `@metamask/profile-sync-controller` from `^32.0.0` to `^33.0.0` ([#10184](https://github.com/MetaMask/core/pull/10184), [#10220](https://github.com/MetaMask/core/pull/10220), [#10348](https://github.com/MetaMask/core/pull/10348), [#10409](https://github.com/MetaMask/core/pull/10409), [#10418](https://github.com/MetaMask/core/pull/10418), [#10459](https://github.com/MetaMask/core/pull/10459))
|
|
13
23
|
- Bump `@metamask/utils` from `^11.12.0` to `^12.0.0` ([#10192](https://github.com/MetaMask/core/pull/10192))
|
|
24
|
+
- Bump `@metamask/keyring-controller` from `^28.0.0` to `^28.1.0` ([#10418](https://github.com/MetaMask/core/pull/10418))
|
|
25
|
+
- Bump `@metamask/multichain-account-service` from `^14.0.0` to `^14.1.0` ([#10459](https://github.com/MetaMask/core/pull/10459))
|
|
14
26
|
|
|
15
27
|
## [10.0.1]
|
|
16
28
|
|
|
@@ -721,7 +733,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
721
733
|
- Initial release ([#5847](https://github.com/MetaMask/core/pull/5847))
|
|
722
734
|
- Grouping accounts into 3 main categories: Entropy source, Snap ID, keyring types.
|
|
723
735
|
|
|
724
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/account-tree-controller@
|
|
736
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/account-tree-controller@11.0.0...HEAD
|
|
737
|
+
[11.0.0]: https://github.com/MetaMask/core/compare/@metamask/account-tree-controller@10.0.1...@metamask/account-tree-controller@11.0.0
|
|
725
738
|
[10.0.1]: https://github.com/MetaMask/core/compare/@metamask/account-tree-controller@10.0.0...@metamask/account-tree-controller@10.0.1
|
|
726
739
|
[10.0.0]: https://github.com/MetaMask/core/compare/@metamask/account-tree-controller@9.0.0...@metamask/account-tree-controller@10.0.0
|
|
727
740
|
[9.0.0]: https://github.com/MetaMask/core/compare/@metamask/account-tree-controller@8.1.0...@metamask/account-tree-controller@9.0.0
|
|
@@ -34,6 +34,24 @@ export type AccountTreeControllerIsInitializedAction = {
|
|
|
34
34
|
type: `AccountTreeController:isInitialized`;
|
|
35
35
|
handler: AccountTreeController['isInitialized'];
|
|
36
36
|
};
|
|
37
|
+
/**
|
|
38
|
+
* Removes an account wallet and all of its underlying accounts.
|
|
39
|
+
*
|
|
40
|
+
* The account tree is a derived view of AccountsController state, so this
|
|
41
|
+
* method intentionally does not mutate tree nodes directly. Account removal
|
|
42
|
+
* causes AccountsController to publish `accountsRemoved`, which lets
|
|
43
|
+
* `#handleAccountsRemoved` consistently prune tree nodes, reverse mappings,
|
|
44
|
+
* metadata, and selection state.
|
|
45
|
+
*
|
|
46
|
+
* @param walletId - Account wallet ID.
|
|
47
|
+
* @throws If the account tree has not been initialized.
|
|
48
|
+
* @throws If the wallet does not exist.
|
|
49
|
+
* @throws If the wallet belongs to the primary HD keyring.
|
|
50
|
+
*/
|
|
51
|
+
export type AccountTreeControllerRemoveAccountWalletAction = {
|
|
52
|
+
type: `AccountTreeController:removeAccountWallet`;
|
|
53
|
+
handler: AccountTreeController['removeAccountWallet'];
|
|
54
|
+
};
|
|
37
55
|
/**
|
|
38
56
|
* Gets the account wallet object from its ID.
|
|
39
57
|
*
|
|
@@ -262,5 +280,5 @@ export type AccountTreeControllerImportStateAction = {
|
|
|
262
280
|
/**
|
|
263
281
|
* Union of all AccountTreeController action types.
|
|
264
282
|
*/
|
|
265
|
-
export type AccountTreeControllerMethodActions = AccountTreeControllerInitAction | AccountTreeControllerReinitAction | AccountTreeControllerIsInitializedAction | AccountTreeControllerGetAccountWalletObjectAction | AccountTreeControllerGetAccountWalletObjectsAction | AccountTreeControllerGetAccountsFromSelectedAccountGroupAction | AccountTreeControllerGetAccountFromSelectedAccountGroupAction | AccountTreeControllerGetAccountGroupObjectAction | AccountTreeControllerGetAccountContextAction | AccountTreeControllerGetSelectedAccountGroupAction | AccountTreeControllerSetSelectedAccountGroupAction | AccountTreeControllerSetSelectedAccountGroupByAccountIdAction | AccountTreeControllerSetAccountGroupNameAction | AccountTreeControllerSetAccountWalletNameAction | AccountTreeControllerSetAccountGroupPinnedAction | AccountTreeControllerSetAccountGroupHiddenAction | AccountTreeControllerClearStateAction | AccountTreeControllerSyncWithUserStorageAction | AccountTreeControllerSyncWithUserStorageAtLeastOnceAction | AccountTreeControllerExportStateAction | AccountTreeControllerImportStateAction;
|
|
283
|
+
export type AccountTreeControllerMethodActions = AccountTreeControllerInitAction | AccountTreeControllerReinitAction | AccountTreeControllerIsInitializedAction | AccountTreeControllerRemoveAccountWalletAction | AccountTreeControllerGetAccountWalletObjectAction | AccountTreeControllerGetAccountWalletObjectsAction | AccountTreeControllerGetAccountsFromSelectedAccountGroupAction | AccountTreeControllerGetAccountFromSelectedAccountGroupAction | AccountTreeControllerGetAccountGroupObjectAction | AccountTreeControllerGetAccountContextAction | AccountTreeControllerGetSelectedAccountGroupAction | AccountTreeControllerSetSelectedAccountGroupAction | AccountTreeControllerSetSelectedAccountGroupByAccountIdAction | AccountTreeControllerSetAccountGroupNameAction | AccountTreeControllerSetAccountWalletNameAction | AccountTreeControllerSetAccountGroupPinnedAction | AccountTreeControllerSetAccountGroupHiddenAction | AccountTreeControllerClearStateAction | AccountTreeControllerSyncWithUserStorageAction | AccountTreeControllerSyncWithUserStorageAtLeastOnceAction | AccountTreeControllerExportStateAction | AccountTreeControllerImportStateAction;
|
|
266
284
|
//# sourceMappingURL=AccountTreeController-method-action-types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccountTreeController-method-action-types.d.ts","sourceRoot":"","sources":["../src/AccountTreeController-method-action-types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AccountTreeController-method-action-types.d.ts","sourceRoot":"","sources":["../src/AccountTreeController-method-action-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccountTreeController-method-action-types.js","sourceRoot":"","sources":["../src/AccountTreeController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { AccountTreeController } from './AccountTreeController.js';\n\n/**\n * Initialize the controller's state.\n *\n * It constructs the initial state of the account tree (tree nodes, nodes\n * names, metadata, etc..) and will automatically update the controller's\n * state with it.\n */\nexport type AccountTreeControllerInitAction = {\n type: `AccountTreeController:init`;\n handler: AccountTreeController['init'];\n};\n\n/**\n * Re-initialize the controller's state.\n *\n * This is done in one single (atomic) `update` block to avoid having a temporary\n * cleared state. Use this when you need to force a full re-init even if already initialized.\n */\nexport type AccountTreeControllerReinitAction = {\n type: `AccountTreeController:reinit`;\n handler: AccountTreeController['reinit'];\n};\n\n/**\n * Whether `init()` has completed and the account tree is ready to consume.\n * Returns false after `clearState()` until the next successful `init()`.\n *\n * @returns True when the controller has been initialized.\n */\nexport type AccountTreeControllerIsInitializedAction = {\n type: `AccountTreeController:isInitialized`;\n handler: AccountTreeController['isInitialized'];\n};\n\n/**\n * Gets the account wallet object from its ID.\n *\n * @param walletId - Account wallet ID.\n * @returns The account wallet object if found, undefined otherwise.\n */\nexport type AccountTreeControllerGetAccountWalletObjectAction = {\n type: `AccountTreeController:getAccountWalletObject`;\n handler: AccountTreeController['getAccountWalletObject'];\n};\n\n/**\n * Gets all account wallet objects.\n *\n * @returns All account wallet objects.\n */\nexport type AccountTreeControllerGetAccountWalletObjectsAction = {\n type: `AccountTreeController:getAccountWalletObjects`;\n handler: AccountTreeController['getAccountWalletObjects'];\n};\n\n/**\n * Gets all underlying accounts from the currently selected account\n * group.\n *\n * It also support account selector, which allows to filter specific\n * accounts given some criterias (account type, address, scopes, etc...).\n *\n * @param selector - Optional account selector.\n * @returns Underlying accounts for the currently selected account (filtered\n * by the selector if provided).\n */\nexport type AccountTreeControllerGetAccountsFromSelectedAccountGroupAction = {\n type: `AccountTreeController:getAccountsFromSelectedAccountGroup`;\n handler: AccountTreeController['getAccountsFromSelectedAccountGroup'];\n};\n\n/**\n * Gets an account from the currently selected account group, optionally\n * filtered by a CAIP-2 chain ID.\n *\n * This is the group-based replacement for both\n * `AccountsController:getSelectedAccount` and\n * `AccountsController:getSelectedMultichainAccount`.\n *\n * When no chain ID is provided, an account of the selected group is returned\n * using an EVM-priority rule: the first EVM account found in the group, or the\n * first account in the group if no EVM account is found. When a chain ID is\n * provided, the first account in the selected group whose scopes match the\n * given chain is returned.\n *\n * @param chainId - Optional CAIP-2 chain ID used to filter accounts by scope.\n * @returns The matching internal account from the selected group, or\n * undefined if no group is selected or no account matches.\n * @throws If `chainId` is provided but is not a valid CAIP-2 chain ID.\n */\nexport type AccountTreeControllerGetAccountFromSelectedAccountGroupAction = {\n type: `AccountTreeController:getAccountFromSelectedAccountGroup`;\n handler: AccountTreeController['getAccountFromSelectedAccountGroup'];\n};\n\n/**\n * Gets the account group object from its ID.\n *\n * @param groupId - Account group ID.\n * @returns The account group object if found, undefined otherwise.\n */\nexport type AccountTreeControllerGetAccountGroupObjectAction = {\n type: `AccountTreeController:getAccountGroupObject`;\n handler: AccountTreeController['getAccountGroupObject'];\n};\n\n/**\n * Gets the account's context which contains its wallet ID, group ID, and sort order.\n *\n * @param accountId - Account ID.\n * @returns The account context if found, undefined otherwise.\n */\nexport type AccountTreeControllerGetAccountContextAction = {\n type: `AccountTreeController:getAccountContext`;\n handler: AccountTreeController['getAccountContext'];\n};\n\n/**\n * Gets the currently selected account group ID.\n *\n * @returns The selected account group ID or empty string if none selected.\n */\nexport type AccountTreeControllerGetSelectedAccountGroupAction = {\n type: `AccountTreeController:getSelectedAccountGroup`;\n handler: AccountTreeController['getSelectedAccountGroup'];\n};\n\n/**\n * Sets the selected account group and updates the AccountsController selectedAccount accordingly.\n *\n * @param groupId - The account group ID to select.\n */\nexport type AccountTreeControllerSetSelectedAccountGroupAction = {\n type: `AccountTreeController:setSelectedAccountGroup`;\n handler: AccountTreeController['setSelectedAccountGroup'];\n};\n\n/**\n * Sets the selected account group and updates the AccountsController selectedAccount accordingly.\n *\n * @param accountId - The account ID to select the group for.\n */\nexport type AccountTreeControllerSetSelectedAccountGroupByAccountIdAction = {\n type: `AccountTreeController:setSelectedAccountGroupByAccountId`;\n handler: AccountTreeController['setSelectedAccountGroupByAccountId'];\n};\n\n/**\n * Sets a custom name for an account group.\n *\n * @param groupId - The account group ID.\n * @param name - The custom name to set.\n * @param autoHandleConflict - If true, automatically resolves name conflicts by adding a suffix. If false, throws on conflicts.\n * @throws If the account group ID is not found in the current tree.\n * @throws If the account group name already exists and autoHandleConflict is false.\n */\nexport type AccountTreeControllerSetAccountGroupNameAction = {\n type: `AccountTreeController:setAccountGroupName`;\n handler: AccountTreeController['setAccountGroupName'];\n};\n\n/**\n * Sets a custom name for an account wallet.\n *\n * @param walletId - The account wallet ID.\n * @param name - The custom name to set.\n * @throws If the account wallet ID is not found in the current tree.\n */\nexport type AccountTreeControllerSetAccountWalletNameAction = {\n type: `AccountTreeController:setAccountWalletName`;\n handler: AccountTreeController['setAccountWalletName'];\n};\n\n/**\n * Toggles the pinned state of an account group.\n *\n * @param groupId - The account group ID.\n * @param pinned - Whether the group should be pinned.\n * @throws If the account group ID is not found in the current tree.\n */\nexport type AccountTreeControllerSetAccountGroupPinnedAction = {\n type: `AccountTreeController:setAccountGroupPinned`;\n handler: AccountTreeController['setAccountGroupPinned'];\n};\n\n/**\n * Toggles the hidden state of an account group.\n *\n * @param groupId - The account group ID.\n * @param hidden - Whether the group should be hidden.\n * @throws If the account group ID is not found in the current tree.\n */\nexport type AccountTreeControllerSetAccountGroupHiddenAction = {\n type: `AccountTreeController:setAccountGroupHidden`;\n handler: AccountTreeController['setAccountGroupHidden'];\n};\n\n/**\n * Clears the controller state and resets to default values.\n * Also clears the backup and sync service state.\n */\nexport type AccountTreeControllerClearStateAction = {\n type: `AccountTreeController:clearState`;\n handler: AccountTreeController['clearState'];\n};\n\n/**\n * Bi-directionally syncs the account tree with user storage.\n * This will perform a full sync, including both pulling updates\n * from user storage and pushing local changes to user storage.\n * This also performs legacy account syncing if needed.\n *\n * IMPORTANT:\n * If a full sync is already in progress, it will return the ongoing promise.\n *\n * @returns A promise that resolves when the sync is complete.\n */\nexport type AccountTreeControllerSyncWithUserStorageAction = {\n type: `AccountTreeController:syncWithUserStorage`;\n handler: AccountTreeController['syncWithUserStorage'];\n};\n\n/**\n * Bi-directionally syncs the account tree with user storage.\n * This will ensure at least one full sync is ran, including both pulling updates\n * from user storage and pushing local changes to user storage.\n * This also performs legacy account syncing if needed.\n *\n * IMPORTANT:\n * If the first ever full sync is already in progress, it will return the ongoing promise.\n * If the first ever full sync was previously completed, it will NOT start a new sync, and will resolve immediately.\n *\n * @returns A promise that resolves when the first ever full sync is complete.\n */\nexport type AccountTreeControllerSyncWithUserStorageAtLeastOnceAction = {\n type: `AccountTreeController:syncWithUserStorageAtLeastOnce`;\n handler: AccountTreeController['syncWithUserStorageAtLeastOnce'];\n};\n\n/**\n * Produces a versioned snapshot of the current wallet and group state.\n *\n * When `options.includeSecrets` is `true`, `options.password` is required\n * and verified against the vault before any secret is read. Without\n * `includeSecrets`, only metadata (names, pinned, hidden) is exported and\n * no password is needed.\n *\n * @param options - Export options.\n * @returns A promise resolving to an `AccountTreeSnapshot`.\n * @throws If the vault is locked or the password is incorrect.\n */\nexport type AccountTreeControllerExportStateAction = {\n type: `AccountTreeController:exportState`;\n handler: AccountTreeController['exportState'];\n};\n\n/**\n * Applies a validated snapshot to the current state.\n *\n * Accepts an {@link AccountTreeSnapshot} only — untrusted wire data must be\n * parsed with {@link AccountTreeSnapshot.deserialize} first. Callers may\n * filter the snapshot with {@link AccountTreeSnapshot.filterWallets},\n * {@link AccountTreeSnapshot.filterGroups}, or\n * {@link AccountTreeSnapshot.filterAllGroups} before importing.\n *\n * New mnemonic wallets are imported via `MultichainAccountService` and new\n * private-key accounts via `KeyringController`. Metadata (name, pinned,\n * hidden) is applied to all existing and newly created wallets / groups.\n *\n * @param snapshot - The validated snapshot to import.\n * @returns A promise that resolves when the import is complete.\n */\nexport type AccountTreeControllerImportStateAction = {\n type: `AccountTreeController:importState`;\n handler: AccountTreeController['importState'];\n};\n\n/**\n * Union of all AccountTreeController action types.\n */\nexport type AccountTreeControllerMethodActions =\n | AccountTreeControllerInitAction\n | AccountTreeControllerReinitAction\n | AccountTreeControllerIsInitializedAction\n | AccountTreeControllerGetAccountWalletObjectAction\n | AccountTreeControllerGetAccountWalletObjectsAction\n | AccountTreeControllerGetAccountsFromSelectedAccountGroupAction\n | AccountTreeControllerGetAccountFromSelectedAccountGroupAction\n | AccountTreeControllerGetAccountGroupObjectAction\n | AccountTreeControllerGetAccountContextAction\n | AccountTreeControllerGetSelectedAccountGroupAction\n | AccountTreeControllerSetSelectedAccountGroupAction\n | AccountTreeControllerSetSelectedAccountGroupByAccountIdAction\n | AccountTreeControllerSetAccountGroupNameAction\n | AccountTreeControllerSetAccountWalletNameAction\n | AccountTreeControllerSetAccountGroupPinnedAction\n | AccountTreeControllerSetAccountGroupHiddenAction\n | AccountTreeControllerClearStateAction\n | AccountTreeControllerSyncWithUserStorageAction\n | AccountTreeControllerSyncWithUserStorageAtLeastOnceAction\n | AccountTreeControllerExportStateAction\n | AccountTreeControllerImportStateAction;\n"]}
|
|
1
|
+
{"version":3,"file":"AccountTreeController-method-action-types.js","sourceRoot":"","sources":["../src/AccountTreeController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { AccountTreeController } from './AccountTreeController.js';\n\n/**\n * Initialize the controller's state.\n *\n * It constructs the initial state of the account tree (tree nodes, nodes\n * names, metadata, etc..) and will automatically update the controller's\n * state with it.\n */\nexport type AccountTreeControllerInitAction = {\n type: `AccountTreeController:init`;\n handler: AccountTreeController['init'];\n};\n\n/**\n * Re-initialize the controller's state.\n *\n * This is done in one single (atomic) `update` block to avoid having a temporary\n * cleared state. Use this when you need to force a full re-init even if already initialized.\n */\nexport type AccountTreeControllerReinitAction = {\n type: `AccountTreeController:reinit`;\n handler: AccountTreeController['reinit'];\n};\n\n/**\n * Whether `init()` has completed and the account tree is ready to consume.\n * Returns false after `clearState()` until the next successful `init()`.\n *\n * @returns True when the controller has been initialized.\n */\nexport type AccountTreeControllerIsInitializedAction = {\n type: `AccountTreeController:isInitialized`;\n handler: AccountTreeController['isInitialized'];\n};\n\n/**\n * Removes an account wallet and all of its underlying accounts.\n *\n * The account tree is a derived view of AccountsController state, so this\n * method intentionally does not mutate tree nodes directly. Account removal\n * causes AccountsController to publish `accountsRemoved`, which lets\n * `#handleAccountsRemoved` consistently prune tree nodes, reverse mappings,\n * metadata, and selection state.\n *\n * @param walletId - Account wallet ID.\n * @throws If the account tree has not been initialized.\n * @throws If the wallet does not exist.\n * @throws If the wallet belongs to the primary HD keyring.\n */\nexport type AccountTreeControllerRemoveAccountWalletAction = {\n type: `AccountTreeController:removeAccountWallet`;\n handler: AccountTreeController['removeAccountWallet'];\n};\n\n/**\n * Gets the account wallet object from its ID.\n *\n * @param walletId - Account wallet ID.\n * @returns The account wallet object if found, undefined otherwise.\n */\nexport type AccountTreeControllerGetAccountWalletObjectAction = {\n type: `AccountTreeController:getAccountWalletObject`;\n handler: AccountTreeController['getAccountWalletObject'];\n};\n\n/**\n * Gets all account wallet objects.\n *\n * @returns All account wallet objects.\n */\nexport type AccountTreeControllerGetAccountWalletObjectsAction = {\n type: `AccountTreeController:getAccountWalletObjects`;\n handler: AccountTreeController['getAccountWalletObjects'];\n};\n\n/**\n * Gets all underlying accounts from the currently selected account\n * group.\n *\n * It also support account selector, which allows to filter specific\n * accounts given some criterias (account type, address, scopes, etc...).\n *\n * @param selector - Optional account selector.\n * @returns Underlying accounts for the currently selected account (filtered\n * by the selector if provided).\n */\nexport type AccountTreeControllerGetAccountsFromSelectedAccountGroupAction = {\n type: `AccountTreeController:getAccountsFromSelectedAccountGroup`;\n handler: AccountTreeController['getAccountsFromSelectedAccountGroup'];\n};\n\n/**\n * Gets an account from the currently selected account group, optionally\n * filtered by a CAIP-2 chain ID.\n *\n * This is the group-based replacement for both\n * `AccountsController:getSelectedAccount` and\n * `AccountsController:getSelectedMultichainAccount`.\n *\n * When no chain ID is provided, an account of the selected group is returned\n * using an EVM-priority rule: the first EVM account found in the group, or the\n * first account in the group if no EVM account is found. When a chain ID is\n * provided, the first account in the selected group whose scopes match the\n * given chain is returned.\n *\n * @param chainId - Optional CAIP-2 chain ID used to filter accounts by scope.\n * @returns The matching internal account from the selected group, or\n * undefined if no group is selected or no account matches.\n * @throws If `chainId` is provided but is not a valid CAIP-2 chain ID.\n */\nexport type AccountTreeControllerGetAccountFromSelectedAccountGroupAction = {\n type: `AccountTreeController:getAccountFromSelectedAccountGroup`;\n handler: AccountTreeController['getAccountFromSelectedAccountGroup'];\n};\n\n/**\n * Gets the account group object from its ID.\n *\n * @param groupId - Account group ID.\n * @returns The account group object if found, undefined otherwise.\n */\nexport type AccountTreeControllerGetAccountGroupObjectAction = {\n type: `AccountTreeController:getAccountGroupObject`;\n handler: AccountTreeController['getAccountGroupObject'];\n};\n\n/**\n * Gets the account's context which contains its wallet ID, group ID, and sort order.\n *\n * @param accountId - Account ID.\n * @returns The account context if found, undefined otherwise.\n */\nexport type AccountTreeControllerGetAccountContextAction = {\n type: `AccountTreeController:getAccountContext`;\n handler: AccountTreeController['getAccountContext'];\n};\n\n/**\n * Gets the currently selected account group ID.\n *\n * @returns The selected account group ID or empty string if none selected.\n */\nexport type AccountTreeControllerGetSelectedAccountGroupAction = {\n type: `AccountTreeController:getSelectedAccountGroup`;\n handler: AccountTreeController['getSelectedAccountGroup'];\n};\n\n/**\n * Sets the selected account group and updates the AccountsController selectedAccount accordingly.\n *\n * @param groupId - The account group ID to select.\n */\nexport type AccountTreeControllerSetSelectedAccountGroupAction = {\n type: `AccountTreeController:setSelectedAccountGroup`;\n handler: AccountTreeController['setSelectedAccountGroup'];\n};\n\n/**\n * Sets the selected account group and updates the AccountsController selectedAccount accordingly.\n *\n * @param accountId - The account ID to select the group for.\n */\nexport type AccountTreeControllerSetSelectedAccountGroupByAccountIdAction = {\n type: `AccountTreeController:setSelectedAccountGroupByAccountId`;\n handler: AccountTreeController['setSelectedAccountGroupByAccountId'];\n};\n\n/**\n * Sets a custom name for an account group.\n *\n * @param groupId - The account group ID.\n * @param name - The custom name to set.\n * @param autoHandleConflict - If true, automatically resolves name conflicts by adding a suffix. If false, throws on conflicts.\n * @throws If the account group ID is not found in the current tree.\n * @throws If the account group name already exists and autoHandleConflict is false.\n */\nexport type AccountTreeControllerSetAccountGroupNameAction = {\n type: `AccountTreeController:setAccountGroupName`;\n handler: AccountTreeController['setAccountGroupName'];\n};\n\n/**\n * Sets a custom name for an account wallet.\n *\n * @param walletId - The account wallet ID.\n * @param name - The custom name to set.\n * @throws If the account wallet ID is not found in the current tree.\n */\nexport type AccountTreeControllerSetAccountWalletNameAction = {\n type: `AccountTreeController:setAccountWalletName`;\n handler: AccountTreeController['setAccountWalletName'];\n};\n\n/**\n * Toggles the pinned state of an account group.\n *\n * @param groupId - The account group ID.\n * @param pinned - Whether the group should be pinned.\n * @throws If the account group ID is not found in the current tree.\n */\nexport type AccountTreeControllerSetAccountGroupPinnedAction = {\n type: `AccountTreeController:setAccountGroupPinned`;\n handler: AccountTreeController['setAccountGroupPinned'];\n};\n\n/**\n * Toggles the hidden state of an account group.\n *\n * @param groupId - The account group ID.\n * @param hidden - Whether the group should be hidden.\n * @throws If the account group ID is not found in the current tree.\n */\nexport type AccountTreeControllerSetAccountGroupHiddenAction = {\n type: `AccountTreeController:setAccountGroupHidden`;\n handler: AccountTreeController['setAccountGroupHidden'];\n};\n\n/**\n * Clears the controller state and resets to default values.\n * Also clears the backup and sync service state.\n */\nexport type AccountTreeControllerClearStateAction = {\n type: `AccountTreeController:clearState`;\n handler: AccountTreeController['clearState'];\n};\n\n/**\n * Bi-directionally syncs the account tree with user storage.\n * This will perform a full sync, including both pulling updates\n * from user storage and pushing local changes to user storage.\n * This also performs legacy account syncing if needed.\n *\n * IMPORTANT:\n * If a full sync is already in progress, it will return the ongoing promise.\n *\n * @returns A promise that resolves when the sync is complete.\n */\nexport type AccountTreeControllerSyncWithUserStorageAction = {\n type: `AccountTreeController:syncWithUserStorage`;\n handler: AccountTreeController['syncWithUserStorage'];\n};\n\n/**\n * Bi-directionally syncs the account tree with user storage.\n * This will ensure at least one full sync is ran, including both pulling updates\n * from user storage and pushing local changes to user storage.\n * This also performs legacy account syncing if needed.\n *\n * IMPORTANT:\n * If the first ever full sync is already in progress, it will return the ongoing promise.\n * If the first ever full sync was previously completed, it will NOT start a new sync, and will resolve immediately.\n *\n * @returns A promise that resolves when the first ever full sync is complete.\n */\nexport type AccountTreeControllerSyncWithUserStorageAtLeastOnceAction = {\n type: `AccountTreeController:syncWithUserStorageAtLeastOnce`;\n handler: AccountTreeController['syncWithUserStorageAtLeastOnce'];\n};\n\n/**\n * Produces a versioned snapshot of the current wallet and group state.\n *\n * When `options.includeSecrets` is `true`, `options.password` is required\n * and verified against the vault before any secret is read. Without\n * `includeSecrets`, only metadata (names, pinned, hidden) is exported and\n * no password is needed.\n *\n * @param options - Export options.\n * @returns A promise resolving to an `AccountTreeSnapshot`.\n * @throws If the vault is locked or the password is incorrect.\n */\nexport type AccountTreeControllerExportStateAction = {\n type: `AccountTreeController:exportState`;\n handler: AccountTreeController['exportState'];\n};\n\n/**\n * Applies a validated snapshot to the current state.\n *\n * Accepts an {@link AccountTreeSnapshot} only — untrusted wire data must be\n * parsed with {@link AccountTreeSnapshot.deserialize} first. Callers may\n * filter the snapshot with {@link AccountTreeSnapshot.filterWallets},\n * {@link AccountTreeSnapshot.filterGroups}, or\n * {@link AccountTreeSnapshot.filterAllGroups} before importing.\n *\n * New mnemonic wallets are imported via `MultichainAccountService` and new\n * private-key accounts via `KeyringController`. Metadata (name, pinned,\n * hidden) is applied to all existing and newly created wallets / groups.\n *\n * @param snapshot - The validated snapshot to import.\n * @returns A promise that resolves when the import is complete.\n */\nexport type AccountTreeControllerImportStateAction = {\n type: `AccountTreeController:importState`;\n handler: AccountTreeController['importState'];\n};\n\n/**\n * Union of all AccountTreeController action types.\n */\nexport type AccountTreeControllerMethodActions =\n | AccountTreeControllerInitAction\n | AccountTreeControllerReinitAction\n | AccountTreeControllerIsInitializedAction\n | AccountTreeControllerRemoveAccountWalletAction\n | AccountTreeControllerGetAccountWalletObjectAction\n | AccountTreeControllerGetAccountWalletObjectsAction\n | AccountTreeControllerGetAccountsFromSelectedAccountGroupAction\n | AccountTreeControllerGetAccountFromSelectedAccountGroupAction\n | AccountTreeControllerGetAccountGroupObjectAction\n | AccountTreeControllerGetAccountContextAction\n | AccountTreeControllerGetSelectedAccountGroupAction\n | AccountTreeControllerSetSelectedAccountGroupAction\n | AccountTreeControllerSetSelectedAccountGroupByAccountIdAction\n | AccountTreeControllerSetAccountGroupNameAction\n | AccountTreeControllerSetAccountWalletNameAction\n | AccountTreeControllerSetAccountGroupPinnedAction\n | AccountTreeControllerSetAccountGroupHiddenAction\n | AccountTreeControllerClearStateAction\n | AccountTreeControllerSyncWithUserStorageAction\n | AccountTreeControllerSyncWithUserStorageAtLeastOnceAction\n | AccountTreeControllerExportStateAction\n | AccountTreeControllerImportStateAction;\n"]}
|
|
@@ -70,6 +70,21 @@ export declare class AccountTreeController extends BaseController<typeof control
|
|
|
70
70
|
* @returns True when the controller has been initialized.
|
|
71
71
|
*/
|
|
72
72
|
isInitialized(): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Removes an account wallet and all of its underlying accounts.
|
|
75
|
+
*
|
|
76
|
+
* The account tree is a derived view of AccountsController state, so this
|
|
77
|
+
* method intentionally does not mutate tree nodes directly. Account removal
|
|
78
|
+
* causes AccountsController to publish `accountsRemoved`, which lets
|
|
79
|
+
* `#handleAccountsRemoved` consistently prune tree nodes, reverse mappings,
|
|
80
|
+
* metadata, and selection state.
|
|
81
|
+
*
|
|
82
|
+
* @param walletId - Account wallet ID.
|
|
83
|
+
* @throws If the account tree has not been initialized.
|
|
84
|
+
* @throws If the wallet does not exist.
|
|
85
|
+
* @throws If the wallet belongs to the primary HD keyring.
|
|
86
|
+
*/
|
|
87
|
+
removeAccountWallet(walletId: AccountWalletId): Promise<void>;
|
|
73
88
|
/**
|
|
74
89
|
* Gets the account wallet object from its ID.
|
|
75
90
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccountTreeController.d.ts","sourceRoot":"","sources":["../src/AccountTreeController.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,eAAe,EAGhB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"AccountTreeController.d.ts","sourceRoot":"","sources":["../src/AccountTreeController.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ import { assert, isCaipChainId } from '@metamask/utils';
|
|
|
5
5
|
import { formatAnalyticsEvent, traceFallback, } from './backup-and-sync/analytics/index.js';
|
|
6
6
|
import { BackupAndSyncService } from './backup-and-sync/service/index.js';
|
|
7
7
|
import { createSyncMutationTracker } from './backup-and-sync/utils/index.js';
|
|
8
|
+
import { reportRemoveAccountWalletError } from './errors.js';
|
|
8
9
|
import { ACCOUNT_TYPE_TO_SORT_ORDER, isAccountGroupNameUnique, isAccountGroupNameUniqueFromWallet, MAX_SORT_ORDER, } from './group.js';
|
|
9
10
|
import { projectLogger as log } from './logger.js';
|
|
10
11
|
import { EntropyRule } from './rules/entropy.js';
|
|
@@ -27,6 +28,7 @@ const MESSENGER_EXPOSED_METHODS = [
|
|
|
27
28
|
'setAccountGroupHidden',
|
|
28
29
|
'getAccountWalletObject',
|
|
29
30
|
'getAccountWalletObjects',
|
|
31
|
+
'removeAccountWallet',
|
|
30
32
|
'getAccountGroupObject',
|
|
31
33
|
'clearState',
|
|
32
34
|
'syncWithUserStorage',
|
|
@@ -316,6 +318,14 @@ export class AccountTreeController extends BaseController {
|
|
|
316
318
|
#getEntropyRule() {
|
|
317
319
|
return this.#rules[0];
|
|
318
320
|
}
|
|
321
|
+
/**
|
|
322
|
+
* Gets the entropy source ID of the primary HD keyring.
|
|
323
|
+
*
|
|
324
|
+
* @returns The primary entropy source ID, or `undefined` if no HD keyring exists.
|
|
325
|
+
*/
|
|
326
|
+
#getPrimaryEntropySource() {
|
|
327
|
+
return this.#getEntropyRule().getPrimaryEntropySource();
|
|
328
|
+
}
|
|
319
329
|
/**
|
|
320
330
|
* Rule for Snap-base wallets.
|
|
321
331
|
*
|
|
@@ -571,6 +581,106 @@ export class AccountTreeController extends BaseController {
|
|
|
571
581
|
group.metadata.lastSelected = 0;
|
|
572
582
|
}
|
|
573
583
|
}
|
|
584
|
+
/**
|
|
585
|
+
* Removes a non-multichain account wallet and all of its underlying accounts.
|
|
586
|
+
*
|
|
587
|
+
* @param wallet - The non-multichain account wallet to remove.
|
|
588
|
+
* @returns An object indicating success or failure, with failure details if applicable.
|
|
589
|
+
*/
|
|
590
|
+
async #removeNonMultichainAccountWallet(wallet) {
|
|
591
|
+
const failures = [];
|
|
592
|
+
// Snapshot IDs before the first removal. Each removeAccount call can
|
|
593
|
+
// synchronously publish accountsRemoved and mutate wallet.groups.
|
|
594
|
+
const accountIds = Object.values(wallet.groups).flatMap((group) => [
|
|
595
|
+
...group.accounts,
|
|
596
|
+
]);
|
|
597
|
+
const accounts = this.messenger.call('AccountsController:getAccounts', accountIds);
|
|
598
|
+
for (let i = 0; i < accountIds.length; i++) {
|
|
599
|
+
const id = accountIds[i];
|
|
600
|
+
const account = accounts[i];
|
|
601
|
+
if (!account) {
|
|
602
|
+
failures.push({ id, error: new Error('Account not found') });
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
try {
|
|
606
|
+
// For Snaps, SnapKeyring removes its local account before notifying the Snap
|
|
607
|
+
// and catches Snap-side failures, so this also provides forced cleanup
|
|
608
|
+
// for Snap accounts.
|
|
609
|
+
//
|
|
610
|
+
// For hardware wallets, removal is local and does not require the device
|
|
611
|
+
// to be connected.
|
|
612
|
+
await this.messenger.call('KeyringController:removeAccount', account.address);
|
|
613
|
+
}
|
|
614
|
+
catch (error) {
|
|
615
|
+
failures.push({ id, error });
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
return failures.length === 0 ? { ok: true } : { ok: false, failures };
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Removes an account wallet and all of its underlying accounts.
|
|
622
|
+
*
|
|
623
|
+
* The account tree is a derived view of AccountsController state, so this
|
|
624
|
+
* method intentionally does not mutate tree nodes directly. Account removal
|
|
625
|
+
* causes AccountsController to publish `accountsRemoved`, which lets
|
|
626
|
+
* `#handleAccountsRemoved` consistently prune tree nodes, reverse mappings,
|
|
627
|
+
* metadata, and selection state.
|
|
628
|
+
*
|
|
629
|
+
* @param walletId - Account wallet ID.
|
|
630
|
+
* @throws If the account tree has not been initialized.
|
|
631
|
+
* @throws If the wallet does not exist.
|
|
632
|
+
* @throws If the wallet belongs to the primary HD keyring.
|
|
633
|
+
*/
|
|
634
|
+
async removeAccountWallet(walletId) {
|
|
635
|
+
if (!this.#initialized) {
|
|
636
|
+
throw new Error('Account tree is not initialized');
|
|
637
|
+
}
|
|
638
|
+
// Track of failures during the removal process.
|
|
639
|
+
const failures = [];
|
|
640
|
+
this.#assertAccountWalletExists(walletId);
|
|
641
|
+
const wallet = this.state.accountTree.wallets[walletId];
|
|
642
|
+
if (wallet.type === AccountWalletType.Entropy) {
|
|
643
|
+
// Handle removal of entropy-based account wallets.
|
|
644
|
+
if (wallet.metadata.entropy.id === this.#getPrimaryEntropySource()) {
|
|
645
|
+
throw new Error('Cannot remove the primary account wallet');
|
|
646
|
+
}
|
|
647
|
+
await this.messenger.call('MultichainAccountService:removeMultichainAccountWallet', wallet.metadata.entropy.id);
|
|
648
|
+
}
|
|
649
|
+
else {
|
|
650
|
+
const result = await this.#removeNonMultichainAccountWallet(wallet);
|
|
651
|
+
if (!result.ok) {
|
|
652
|
+
failures.push(...result.failures);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
// Successful account removal normally prunes the wallet through
|
|
656
|
+
// #handleAccountsRemoved. If there's a leftover, it indicates that removal
|
|
657
|
+
// was not fully successful. This is a best-effort and may already have
|
|
658
|
+
// produced irreversible side effects.
|
|
659
|
+
const remainingWallet = this.getAccountWalletObject(walletId);
|
|
660
|
+
if (remainingWallet) {
|
|
661
|
+
let error = new Error('Account wallet removal is incomplete');
|
|
662
|
+
// The wallet still exists in the tree after the removal attempt. That's
|
|
663
|
+
// unexpected and indicates a failure in the removal process.
|
|
664
|
+
const remainingAccountIds = Object.values(remainingWallet.groups).flatMap((group) => group.accounts);
|
|
665
|
+
if (remainingAccountIds.length > 0) {
|
|
666
|
+
failures.push(
|
|
667
|
+
// Accounts still in the tree after all removals completed are also
|
|
668
|
+
// failures - either removal threw (already in result.failures) or the
|
|
669
|
+
// accountsRemoved event never arrived to prune them.
|
|
670
|
+
...remainingAccountIds.map((id) => ({
|
|
671
|
+
id,
|
|
672
|
+
error: new Error('Account was not removed from the tree'),
|
|
673
|
+
})));
|
|
674
|
+
}
|
|
675
|
+
if (remainingAccountIds.length === 0) {
|
|
676
|
+
// This should not occur through the normal event flow because
|
|
677
|
+
// #handleAccountsRemoved prunes an empty wallet atomically.
|
|
678
|
+
/* istanbul ignore next */
|
|
679
|
+
error = new Error('Account wallet remains in the tree without accounts');
|
|
680
|
+
}
|
|
681
|
+
reportRemoveAccountWalletError(this.messenger, error.message, error, failures);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
574
684
|
/**
|
|
575
685
|
* Gets the account wallet object from its ID.
|
|
576
686
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccountTreeController.js","sourceRoot":"","sources":["../src/AccountTreeController.ts"],"names":[],"mappings":"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","sourcesContent":["import { AccountWalletType, select } from '@metamask/account-api';\nimport type {\n AccountGroupId,\n AccountWalletId,\n AccountSelector,\n MultichainAccountWalletId,\n AccountGroupType,\n} from '@metamask/account-api';\nimport type { MultichainAccountWalletStatus } from '@metamask/account-api';\nimport type { AccountId } from '@metamask/accounts-controller';\nimport type { StateMetadata } from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport { isEvmAccountType } from '@metamask/keyring-api';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { assert, isCaipChainId } from '@metamask/utils';\nimport type { CaipChainId } from '@metamask/utils';\n\nimport type { BackupAndSyncEmitAnalyticsEventParams } from './backup-and-sync/analytics/index.js';\nimport {\n formatAnalyticsEvent,\n traceFallback,\n} from './backup-and-sync/analytics/index.js';\nimport { BackupAndSyncService } from './backup-and-sync/service/index.js';\nimport type { BackupAndSyncContext } from './backup-and-sync/types.js';\nimport { createSyncMutationTracker } from './backup-and-sync/utils/index.js';\nimport type { AccountGroupObject, AccountTypeOrderKey } from './group.js';\nimport {\n ACCOUNT_TYPE_TO_SORT_ORDER,\n isAccountGroupNameUnique,\n isAccountGroupNameUniqueFromWallet,\n MAX_SORT_ORDER,\n} from './group.js';\nimport { projectLogger as log } from './logger.js';\nimport type { Rule } from './rule.js';\nimport { EntropyRule } from './rules/entropy.js';\nimport { KeyringRule } from './rules/keyring.js';\nimport { SnapRule } from './rules/snap.js';\nimport { exportState } from './state/export.js';\nimport { importState } from './state/import.js';\nimport type { ExportStateOptions } from './state/payload.js';\nimport type { AccountTreeSnapshot } from './state/snapshot.js';\nimport type {\n AccountTreeControllerConfig,\n AccountTreeControllerInternalBackupAndSyncConfig,\n AccountTreeControllerMessenger,\n AccountTreeControllerState,\n} from './types.js';\nimport type { AccountWalletObject, AccountWalletObjectOf } from './wallet.js';\n\nexport const controllerName = 'AccountTreeController';\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'isInitialized',\n 'getSelectedAccountGroup',\n 'setSelectedAccountGroup',\n 'setSelectedAccountGroupByAccountId',\n 'getAccountsFromSelectedAccountGroup',\n 'getAccountFromSelectedAccountGroup',\n 'getAccountContext',\n 'setAccountWalletName',\n 'setAccountGroupName',\n 'setAccountGroupPinned',\n 'setAccountGroupHidden',\n 'getAccountWalletObject',\n 'getAccountWalletObjects',\n 'getAccountGroupObject',\n 'clearState',\n 'syncWithUserStorage',\n 'syncWithUserStorageAtLeastOnce',\n 'init',\n 'reinit',\n 'exportState',\n 'importState',\n] as const;\n\nconst accountTreeControllerMetadata: StateMetadata<AccountTreeControllerState> =\n {\n accountTree: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n selectedAccountGroup: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n isAccountTreeSyncingInProgress: {\n includeInStateLogs: false,\n persist: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n hasAccountTreeSyncingSyncedAtLeastOnce: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n accountGroupsMetadata: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n accountWalletsMetadata: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n };\n\n/**\n * Gets default state of the `AccountTreeController`.\n *\n * @returns The default state of the `AccountTreeController`.\n */\nexport function getDefaultAccountTreeControllerState(): AccountTreeControllerState {\n return {\n accountTree: {\n wallets: {},\n },\n selectedAccountGroup: '',\n isAccountTreeSyncingInProgress: false,\n hasAccountTreeSyncingSyncedAtLeastOnce: false,\n accountGroupsMetadata: {},\n accountWalletsMetadata: {},\n };\n}\n\n/**\n * Context for an account.\n */\nexport type AccountContext = {\n /**\n * Wallet ID associated to that account.\n */\n walletId: AccountWalletObject['id'];\n\n /**\n * Account group ID associated to that account.\n */\n groupId: AccountGroupObject['id'];\n\n /**\n * Sort order of the account.\n */\n sortOrder: (typeof ACCOUNT_TYPE_TO_SORT_ORDER)[AccountTypeOrderKey];\n};\n\nexport class AccountTreeController extends BaseController<\n typeof controllerName,\n AccountTreeControllerState,\n AccountTreeControllerMessenger\n> {\n readonly #accountIdToContext: Map<AccountId, AccountContext>;\n\n readonly #groupIdToWalletId: Map<AccountGroupId, AccountWalletId>;\n\n /**\n * Service responsible for all backup and sync operations.\n */\n readonly #backupAndSyncService: BackupAndSyncService;\n\n readonly #rules: [EntropyRule, SnapRule, KeyringRule];\n\n readonly #trace: TraceCallback;\n\n readonly #backupAndSyncConfig: AccountTreeControllerInternalBackupAndSyncConfig;\n\n /**\n * Callbacks to migrate hidden and pinned account information from the account order controller\n */\n readonly #accountOrderCallbacks:\n | AccountTreeControllerConfig['accountOrderCallbacks']\n | undefined;\n\n #initialized: boolean;\n\n /**\n * Constructor for AccountTreeController.\n *\n * @param options - The controller options.\n * @param options.messenger - The messenger object.\n * @param options.state - Initial state to set on this controller\n * @param options.config - Optional configuration for the controller.\n */\n\n constructor({\n messenger,\n state,\n config,\n }: {\n messenger: AccountTreeControllerMessenger;\n state?: Partial<AccountTreeControllerState>;\n config?: AccountTreeControllerConfig;\n }) {\n super({\n messenger,\n name: controllerName,\n metadata: accountTreeControllerMetadata,\n state: {\n ...getDefaultAccountTreeControllerState(),\n ...state,\n },\n });\n\n // This will be set to true upon the first `init` call.\n this.#initialized = false;\n\n // Reverse map to allow fast node access from an account ID.\n this.#accountIdToContext = new Map();\n\n // Reverse map to allow fast wallet node access from a group ID.\n this.#groupIdToWalletId = new Map();\n\n // Rules to apply to construct the wallets tree.\n this.#rules = [\n // 1. We group by entropy-source\n new EntropyRule(this.messenger),\n // 2. We group by Snap ID\n new SnapRule(this.messenger),\n // 3. We group by wallet type (this rule cannot fail and will group all non-matching accounts)\n new KeyringRule(this.messenger),\n ];\n\n // Initialize trace function\n this.#trace = config?.trace ?? traceFallback;\n\n // Initialize backup and sync config\n this.#backupAndSyncConfig = {\n emitAnalyticsEventFn: (event: BackupAndSyncEmitAnalyticsEventParams) => {\n return config?.backupAndSync?.onBackupAndSyncEvent?.(\n formatAnalyticsEvent(event),\n );\n },\n };\n\n // Used when migrating initial hidden/pinned state for groups (if available).\n this.#accountOrderCallbacks = config?.accountOrderCallbacks;\n\n // Initialize the backup and sync service\n this.#backupAndSyncService = new BackupAndSyncService(\n this.#createBackupAndSyncContext(),\n );\n\n // We build the initial tree (from the state), but this might get updated\n // after `init` got called. Having it available now, allow our consumers to\n // re-use the state that was already available before we restart/lock the\n // wallet.\n this.#initTreeContext(this.state.accountTree);\n\n this.messenger.subscribe('AccountsController:accountsAdded', (accounts) => {\n this.#handleAccountsAdded(accounts);\n });\n\n this.messenger.subscribe(\n 'AccountsController:accountsRemoved',\n (accountIds) => {\n this.#handleAccountsRemoved(accountIds);\n },\n );\n\n this.messenger.subscribe(\n 'AccountsController:selectedAccountChange',\n (account) => {\n this.#handleSelectedAccountChange(account);\n },\n );\n\n this.messenger.subscribe(\n 'UserStorageController:stateChange',\n (userStorageControllerState) => {\n this.#backupAndSyncService.handleUserStorageStateChange(\n userStorageControllerState,\n );\n },\n );\n\n this.messenger.subscribe(\n 'MultichainAccountService:walletStatusChange',\n (walletId, status) => {\n this.#handleMultichainAccountWalletStatusChange(walletId, status);\n },\n );\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Initialize the account tree from the given state.\n *\n * @param tree The account tree state to initialize from.\n */\n #initTreeContext(tree: AccountTreeControllerState['accountTree']): void {\n // Fetch persisted accounts from the `AccountsController`.\n const accounts = new Map(\n this.#listAccounts().map((account) => [account.id, account]),\n );\n\n for (const [walletId, wallet] of Object.entries(tree.wallets) as [\n AccountWalletId,\n AccountWalletObject,\n ][]) {\n for (const [groupId, group] of Object.entries(wallet.groups) as [\n AccountGroupId,\n AccountGroupObject,\n ][]) {\n this.#groupIdToWalletId.set(groupId, walletId);\n\n // We still need to go through accounts for the sort order.\n for (const accountId of group.accounts) {\n const account = accounts.get(accountId);\n\n // NOTE: The account should always be available, but if it is not, we\n // still let it inside the tree with a max sort order to avoid blocking\n // the entire tree construction.\n let sortOrder = MAX_SORT_ORDER;\n if (account) {\n sortOrder = ACCOUNT_TYPE_TO_SORT_ORDER[account.type];\n }\n\n this.#accountIdToContext.set(accountId, {\n walletId,\n groupId,\n sortOrder,\n });\n }\n }\n }\n }\n\n /**\n * Initialize the controller's state.\n *\n * It constructs the initial state of the account tree (tree nodes, nodes\n * names, metadata, etc..) and will automatically update the controller's\n * state with it.\n */\n init() {\n if (this.#initialized) {\n // We prevent re-initilializing the state multiple times. Though, we can use\n // `reinit` to re-init everything from scratch.\n return;\n }\n\n log('Initializing...');\n\n const wallets: AccountTreeControllerState['accountTree']['wallets'] = {};\n\n // Clear mappings for fresh rebuild.\n this.#accountIdToContext.clear();\n this.#groupIdToWalletId.clear();\n\n // Keep the current selected group to check if it's still part of the tree\n // after rebuilding it.\n const previousSelectedAccountGroup = this.state.selectedAccountGroup;\n\n // There's no guarantee that accounts would be sorted by their import time\n // with `listMultichainAccounts`. We have to sort them here before constructing\n // the tree.\n //\n // Because of the alignment mecanism, some accounts from the same group might not\n // have been imported at the same time, but at least of them should have been\n // imported at the right time, thus, inserting the group at the proper place too.\n //\n // Lastly, if one day we allow to have \"gaps\" in between groups, then this `sort`\n // won't be enough and we would have to use group properties instead (like group\n // index or maybe introduce a `importTime` at group level).\n const accounts = this.#listAccounts().sort(\n (a, b) => a.metadata.importTime - b.metadata.importTime,\n );\n\n // For now, we always re-compute all wallets, we do not re-use the existing state.\n for (const account of accounts) {\n this.#insert(wallets, account);\n }\n\n // Once we have the account tree, we can apply persisted metadata (names + UI states).\n let previousSelectedAccountGroupStillExists = false;\n this.update((state) => {\n state.accountTree.wallets = wallets;\n\n // Apply group metadata within the state update\n for (const wallet of Object.values(state.accountTree.wallets)) {\n this.#applyAccountWalletMetadata(state, wallet.id);\n\n // Used for default group default names (so we use human-indexing here).\n let nextNaturalNameIndex = 1;\n for (const group of Object.values(wallet.groups)) {\n this.#applyAccountGroupMetadata(state, wallet.id, group.id, {\n // We allow computed name when initializing the tree.\n // This will automatically handle account name migration for the very first init of the\n // tree. Once groups are created, their name will be persisted, thus, taking precedence\n // over the computed names (even if we re-init).\n allowComputedName: true,\n // FIXME: We should not need this kind of logic if we were not inserting accounts\n // 1 by 1. Instead, we should be inserting wallets and groups directly. This would\n // allow us to naturally insert a group in the tree AND update its metadata right\n // away...\n // But here, we have to wait for the entire group to be ready before updating\n // its metadata (mainly because we're dealing with single accounts rather than entire\n // groups).\n // That is why we need this kind of extra parameter.\n nextNaturalNameIndex,\n });\n\n if (group.id === previousSelectedAccountGroup) {\n previousSelectedAccountGroupStillExists = true;\n }\n nextNaturalNameIndex += 1;\n }\n }\n\n if (\n !previousSelectedAccountGroupStillExists ||\n previousSelectedAccountGroup === ''\n ) {\n // No group is selected yet OR group no longer exists, re-sync with the\n // AccountsController.\n state.selectedAccountGroup = this.#getDefaultSelectedAccountGroup(\n state.accountTree.wallets, // Re-use updated wallets with metadata here.\n );\n }\n });\n\n // We always fire the current selected group after init, even if it did not change, to ensure that\n // all subscribers are aware of it and can react accordingly (e.g. by fetching accounts from\n // the selected group on startup).\n log(`Selected (initial) group is: [${this.state.selectedAccountGroup}]`);\n this.messenger.publish(\n `${controllerName}:selectedAccountGroupChange`,\n this.state.selectedAccountGroup,\n previousSelectedAccountGroup,\n );\n\n this.#initialized = true;\n log('Initialized!');\n this.messenger.publish(`${controllerName}:initialized`, this.state);\n }\n\n /**\n * Re-initialize the controller's state.\n *\n * This is done in one single (atomic) `update` block to avoid having a temporary\n * cleared state. Use this when you need to force a full re-init even if already initialized.\n */\n reinit() {\n log('Re-initializing...');\n this.#initialized = false;\n this.init();\n }\n\n /**\n * Whether `init()` has completed and the account tree is ready to consume.\n * Returns false after `clearState()` until the next successful `init()`.\n *\n * @returns True when the controller has been initialized.\n */\n isInitialized(): boolean {\n return this.#initialized;\n }\n\n /**\n * Rule for entropy-base wallets.\n *\n * @returns The rule for entropy-based wallets.\n */\n #getEntropyRule(): EntropyRule {\n return this.#rules[0];\n }\n\n /**\n * Rule for Snap-base wallets.\n *\n * @returns The rule for snap-based wallets.\n */\n #getSnapRule(): SnapRule {\n return this.#rules[1];\n }\n\n /**\n * Rule for keyring-base wallets.\n *\n * This rule acts as a fallback and never fails since all accounts\n * comes from a keyring anyway.\n *\n * @returns The fallback rule for every accounts that did not match\n * any other rules.\n */\n #getKeyringRule(): KeyringRule {\n return this.#rules[2];\n }\n\n /**\n * Applies wallet metadata updates (name) by checking the persistent state\n * first, and then fallbacks to default values (based on the wallet's\n * type).\n *\n * @param state Controller state to update for persistence.\n * @param walletId The wallet ID to update.\n */\n #applyAccountWalletMetadata(\n state: AccountTreeControllerState,\n walletId: AccountWalletId,\n ) {\n const wallet = state.accountTree.wallets[walletId];\n const persistedMetadata = state.accountWalletsMetadata[walletId];\n\n // Apply persisted name if available (including empty strings)\n if (persistedMetadata?.name !== undefined) {\n wallet.metadata.name = persistedMetadata.name.value;\n } else if (!wallet.metadata.name) {\n // Generate default name if none exists\n if (wallet.type === AccountWalletType.Entropy) {\n wallet.metadata.name =\n this.#getEntropyRule().getDefaultAccountWalletName(wallet);\n } else if (wallet.type === AccountWalletType.Snap) {\n wallet.metadata.name =\n this.#getSnapRule().getDefaultAccountWalletName(wallet);\n } else {\n wallet.metadata.name =\n this.#getKeyringRule().getDefaultAccountWalletName(wallet);\n }\n log(`[${wallet.id}] Set default name to: \"${wallet.metadata.name}\"`);\n }\n }\n\n /**\n * Gets the appropriate rule instance for a given wallet type.\n *\n * @param wallet - The wallet object to get the rule for.\n * @returns The rule instance that handles the wallet's type.\n */\n #getRuleForWallet<WalletType extends AccountWalletType>(\n wallet: AccountWalletObjectOf<WalletType>,\n ): Rule<WalletType, AccountGroupType> {\n switch (wallet.type) {\n case AccountWalletType.Entropy:\n return this.#getEntropyRule() as unknown as Rule<\n WalletType,\n AccountGroupType\n >;\n case AccountWalletType.Snap:\n return this.#getSnapRule() as unknown as Rule<\n WalletType,\n AccountGroupType\n >;\n default:\n return this.#getKeyringRule() as unknown as Rule<\n WalletType,\n AccountGroupType\n >;\n }\n }\n\n /**\n * Gets the computed name of a group (using its associated accounts).\n *\n * @param wallet The wallet containing the group.\n * @param group The account group to update.\n * @returns The computed name for the group or '' if there's no compute named for this group.\n */\n #getComputedAccountGroupName(\n wallet: AccountWalletObject,\n group: AccountGroupObject,\n ): string {\n let proposedName = ''; // Empty means there's no computed name for this group.\n\n for (const id of group.accounts) {\n const account = this.messenger.call('AccountsController:getAccount', id);\n if (!account?.metadata.name.length) {\n continue;\n }\n\n // We only pick a new proposed name if we don't have one yet.\n if (!proposedName) {\n proposedName = account.metadata.name;\n }\n\n // But EVM accounts take precedence over any other computed names.\n if (isEvmAccountType(account.type)) {\n // So we just overwrite the proposed name and stop looping right away.\n proposedName = account.metadata.name;\n break;\n }\n }\n\n // If this name already exists for whatever reason, we rename it to resolve this conflict.\n if (\n proposedName.length &&\n !isAccountGroupNameUniqueFromWallet(wallet, group.id, proposedName)\n ) {\n proposedName = this.#resolveNameConflict(wallet, group.id, proposedName);\n }\n\n return proposedName;\n }\n\n /**\n * Gets the default name of a group.\n *\n * @param state Controller state to update for persistence.\n * @param wallet The wallet containing the group.\n * @param group The account group to update.\n * @param nextNaturalNameIndex The next natural name index for this group.\n * @returns The default name for the group.\n */\n #getDefaultAccountGroupName(\n state: AccountTreeControllerState,\n wallet: AccountWalletObject,\n group: AccountGroupObject,\n nextNaturalNameIndex?: number,\n ): string {\n // Get the appropriate rule for this wallet type\n const rule = this.#getRuleForWallet(wallet);\n\n // Get the prefix for groups of this wallet\n const namePrefix = rule.getDefaultAccountGroupPrefix(wallet);\n\n // Parse the highest account index being used (similar to accounts-controller)\n let highestNameIndex = 0;\n for (const { id: otherGroupId } of Object.values(\n wallet.groups,\n ) as AccountGroupObject[]) {\n // Skip the current group being processed\n if (otherGroupId === group.id) {\n continue;\n }\n\n // We always get the name from the persisted map, since `init` will clear the\n // `state.accountTree.wallets`, thus, given empty `group.metadata.name`.\n // NOTE: If the other group has not been named yet, we just use an empty name.\n const otherGroupName =\n state.accountGroupsMetadata[otherGroupId]?.name?.value ?? '';\n\n // Parse the existing group name to extract the numeric index\n const nameMatch = otherGroupName.match(/account\\s+(\\d+)$/iu);\n if (nameMatch) {\n const nameIndex = parseInt(nameMatch[1], 10);\n if (nameIndex > highestNameIndex) {\n highestNameIndex = nameIndex;\n }\n }\n }\n\n // We just use the highest known index no matter the wallet type.\n //\n // For entropy-based wallets (bip44), if a multichain account group with group index 1\n // is inserted before another one with group index 0, then the naming will be:\n // - \"Account 1\" (group index 1)\n // - \"Account 2\" (group index 0)\n // This naming makes more sense for the end-user.\n //\n // For other type of wallets, since those wallets can create arbitrary gaps, we still\n // rely on the highest know index to avoid back-filling account with \"old names\".\n let proposedNameIndex = Math.max(\n // Use + 1 to use the next available index.\n highestNameIndex + 1,\n // In case all accounts have been renamed differently than the usual \"Account <index>\"\n // pattern, we want to use the next \"natural\" index, which is just the number of groups\n // in that wallet (e.g. [\"Account A\", \"Another Account\"], next natural index would be\n // \"Account 3\" in this case).\n nextNaturalNameIndex ?? Object.keys(wallet.groups).length,\n );\n\n // Find a unique name by checking for conflicts and incrementing if needed\n let proposedNameExists: boolean;\n let proposedName = '';\n do {\n proposedName = `${namePrefix} ${proposedNameIndex}`;\n\n // Check if this name already exists in the wallet (excluding current group)\n proposedNameExists = !isAccountGroupNameUniqueFromWallet(\n wallet,\n group.id,\n proposedName,\n );\n\n /* istanbul ignore next */\n if (proposedNameExists) {\n proposedNameIndex += 1; // Try next number\n }\n } while (proposedNameExists);\n\n return proposedName;\n }\n\n /**\n * Applies group metadata updates (name, pinned, hidden flags) by checking\n * the persistent state first, and then fallbacks to default values (based\n * on the wallet's\n * type).\n *\n * @param state Controller state to update for persistence.\n * @param walletId The wallet ID containing the group.\n * @param groupId The account group ID to update.\n * @param namingOptions Options around account group naming.\n * @param namingOptions.allowComputedName Allow to use original account names to compute the default name.\n * @param namingOptions.nextNaturalNameIndex The next natural name index for this group (only used for default names).\n */\n #applyAccountGroupMetadata(\n state: AccountTreeControllerState,\n walletId: AccountWalletId,\n groupId: AccountGroupId,\n {\n allowComputedName,\n nextNaturalNameIndex,\n }: {\n allowComputedName?: boolean;\n nextNaturalNameIndex?: number;\n } = {},\n ) {\n const wallet = state.accountTree.wallets[walletId];\n const group = wallet.groups[groupId];\n const persistedGroupMetadata = state.accountGroupsMetadata[groupId];\n\n // Ensure metadata object exists once at the beginning\n state.accountGroupsMetadata[groupId] ??= {};\n\n // Apply persisted name if available (including empty strings)\n if (persistedGroupMetadata?.name !== undefined) {\n state.accountTree.wallets[walletId].groups[groupId].metadata.name =\n persistedGroupMetadata.name.value;\n } else if (!group.metadata.name) {\n let proposedName = '';\n\n // Computed names are usually only used for existing/old accounts. So this option\n // should be used only when we first initialize the tree.\n if (allowComputedName) {\n proposedName = this.#getComputedAccountGroupName(wallet, group);\n }\n\n // If we still don't have a valid name candidate, we fallback to a default name.\n if (!proposedName.length) {\n proposedName = this.#getDefaultAccountGroupName(\n state,\n wallet,\n group,\n nextNaturalNameIndex,\n );\n }\n\n state.accountTree.wallets[walletId].groups[groupId].metadata.name =\n proposedName;\n log(`[${group.id}] Set default name to: \"${group.metadata.name}\"`);\n\n // Persist the generated name to ensure consistency\n state.accountGroupsMetadata[groupId].name = {\n value: proposedName,\n // The `lastUpdatedAt` field is used for backup and sync, when comparing local names\n // with backed up names. In this case, the generated name should never take precedence\n // over a user-defined name, so we set `lastUpdatedAt` to 0.\n lastUpdatedAt: 0,\n };\n }\n\n // Apply persisted UI states\n if (persistedGroupMetadata?.pinned?.value !== undefined) {\n group.metadata.pinned = persistedGroupMetadata.pinned.value;\n } else {\n let isPinned = false;\n\n if (this.#accountOrderCallbacks?.isPinnedAccount) {\n isPinned = group.accounts.some((account) =>\n this.#accountOrderCallbacks?.isPinnedAccount?.(account),\n );\n }\n state.accountGroupsMetadata[groupId].pinned = {\n value: isPinned,\n lastUpdatedAt: 0,\n };\n // If any accounts was previously pinned, then we consider the group to be pinned as well.\n group.metadata.pinned = isPinned;\n }\n\n if (persistedGroupMetadata?.hidden?.value !== undefined) {\n group.metadata.hidden = persistedGroupMetadata.hidden.value;\n } else {\n let isHidden = false;\n\n if (this.#accountOrderCallbacks?.isHiddenAccount) {\n isHidden = group.accounts.some((account) =>\n this.#accountOrderCallbacks?.isHiddenAccount?.(account),\n );\n }\n state.accountGroupsMetadata[groupId].hidden = {\n value: isHidden,\n lastUpdatedAt: 0,\n };\n // If any accounts was previously hidden, then we consider the group to be hidden as well.\n group.metadata.hidden = isHidden;\n }\n\n // Apply persisted lastSelected (plain number, not synced).\n if (\n persistedGroupMetadata?.lastSelected !== undefined &&\n persistedGroupMetadata.lastSelected >= 0\n ) {\n group.metadata.lastSelected = persistedGroupMetadata.lastSelected;\n } else {\n // Automatiacally inject default value.\n state.accountGroupsMetadata[groupId].lastSelected = 0;\n\n group.metadata.lastSelected = 0;\n }\n }\n\n /**\n * Gets the account wallet object from its ID.\n *\n * @param walletId - Account wallet ID.\n * @returns The account wallet object if found, undefined otherwise.\n */\n getAccountWalletObject(\n walletId: AccountWalletId,\n ): AccountWalletObject | undefined {\n const wallet = this.state.accountTree.wallets[walletId];\n if (!wallet) {\n return undefined;\n }\n\n return wallet;\n }\n\n /**\n * Gets all account wallet objects.\n *\n * @returns All account wallet objects.\n */\n getAccountWalletObjects(): AccountWalletObject[] {\n return Object.values(this.state.accountTree.wallets);\n }\n\n /**\n * Gets all underlying accounts from the currently selected account\n * group.\n *\n * It also support account selector, which allows to filter specific\n * accounts given some criterias (account type, address, scopes, etc...).\n *\n * @param selector - Optional account selector.\n * @returns Underlying accounts for the currently selected account (filtered\n * by the selector if provided).\n */\n getAccountsFromSelectedAccountGroup(\n selector?: AccountSelector<InternalAccount>,\n ) {\n const groupId = this.getSelectedAccountGroup();\n if (!groupId) {\n return [];\n }\n\n const group = this.getAccountGroupObject(groupId);\n // We should never reach this part, so we cannot cover it either.\n /* istanbul ignore next */\n if (!group) {\n return [];\n }\n\n const accounts: InternalAccount[] = [];\n for (const id of group.accounts) {\n const account = this.messenger.call('AccountsController:getAccount', id);\n\n // For now, we're filtering undefined account, but I believe\n // throwing would be more appropriate here.\n if (account) {\n accounts.push(account);\n }\n }\n\n return selector ? select(accounts, selector) : accounts;\n }\n\n /**\n * Gets an account from the currently selected account group, optionally\n * filtered by a CAIP-2 chain ID.\n *\n * This is the group-based replacement for both\n * `AccountsController:getSelectedAccount` and\n * `AccountsController:getSelectedMultichainAccount`.\n *\n * When no chain ID is provided, an account of the selected group is returned\n * using an EVM-priority rule: the first EVM account found in the group, or the\n * first account in the group if no EVM account is found. When a chain ID is\n * provided, the first account in the selected group whose scopes match the\n * given chain is returned.\n *\n * @param chainId - Optional CAIP-2 chain ID used to filter accounts by scope.\n * @returns The matching internal account from the selected group, or\n * undefined if no group is selected or no account matches.\n * @throws If `chainId` is provided but is not a valid CAIP-2 chain ID.\n */\n getAccountFromSelectedAccountGroup(\n chainId?: CaipChainId,\n ): InternalAccount | undefined {\n const groupId = this.getSelectedAccountGroup();\n if (!groupId) {\n return undefined;\n }\n\n if (!chainId) {\n return this.#getAccountFromAccountGroupId(groupId);\n }\n\n if (!isCaipChainId(chainId)) {\n throw new Error(`Invalid CAIP-2 chain ID: ${String(chainId)}`);\n }\n\n const accounts = this.getAccountsFromSelectedAccountGroup({\n scopes: [chainId],\n });\n\n return accounts[0];\n }\n\n /**\n * Gets the account group object from its ID.\n *\n * @param groupId - Account group ID.\n * @returns The account group object if found, undefined otherwise.\n */\n getAccountGroupObject(\n groupId: AccountGroupId,\n ): AccountGroupObject | undefined {\n const walletId = this.#groupIdToWalletId.get(groupId);\n if (!walletId) {\n return undefined;\n }\n\n const wallet = this.getAccountWalletObject(walletId);\n return wallet?.groups[groupId];\n }\n\n /**\n * Gets the account's context which contains its wallet ID, group ID, and sort order.\n *\n * @param accountId - Account ID.\n * @returns The account context if found, undefined otherwise.\n */\n getAccountContext(accountId: AccountId): AccountContext | undefined {\n return this.#accountIdToContext.get(accountId);\n }\n\n /**\n * Handles \"AccountsController:accountsAdded\" event to insert\n * new accounts into the tree in a single state update.\n *\n * @param accounts - New accounts.\n */\n #handleAccountsAdded(accounts: InternalAccount[]): void {\n // We wait for the first `init` to be called to actually build up the tree and\n // mutate it. We expect the caller to first update the `AccountsController` state\n // to force the migration of accounts, and then call `init`.\n if (!this.#initialized) {\n return;\n }\n\n // Filter out accounts already known by the tree to avoid double-insertion.\n const newAccounts = accounts.filter(\n (account) => !this.#accountIdToContext.has(account.id),\n );\n\n if (newAccounts.length === 0) {\n return;\n }\n\n const createdGroups = new Map<AccountGroupId, AccountWalletId>();\n const updatedGroups = new Map<AccountGroupId, AccountWalletId>();\n\n this.update((state) => {\n for (const account of newAccounts) {\n const { walletId, groupId, created } = this.#insert(\n state.accountTree.wallets,\n account,\n );\n\n if (created) {\n createdGroups.set(groupId, walletId);\n } else if (!createdGroups.has(groupId)) {\n // ^ We check that the group has not been created in this same batch before adding it to the `updatedGroups`\n // map, to avoid sending both created and updated events for the same group:\n // - Account 1 + Account 2 + Account 3\n // - Account 1 and 3 belong to the same group\n // - Account 1 will create the group\n // - Account 3 will update the group (but we only want to send a created event, not an updated one)\n updatedGroups.set(groupId, walletId);\n }\n\n const wallet = state.accountTree.wallets[walletId];\n if (wallet) {\n this.#applyAccountWalletMetadata(state, walletId);\n this.#applyAccountGroupMetadata(state, walletId, groupId);\n }\n }\n });\n\n this.messenger.publish(\n `${controllerName}:accountTreeChange`,\n this.state.accountTree,\n );\n\n for (const [groupId, walletId] of createdGroups) {\n this.#publishAccountGroupCreated(walletId, groupId);\n }\n for (const [groupId, walletId] of updatedGroups) {\n this.#publishAccountGroupUpdated(walletId, groupId);\n }\n }\n\n /**\n * Handles \"AccountsController:accountsRemoved\" event to remove\n * given accounts from the tree in a single state update.\n *\n * @param accountIds - Removed account IDs.\n */\n #handleAccountsRemoved(accountIds: AccountId[]): void {\n // We wait for the first `init` to be called to actually build up the tree and\n // mutate it. We expect the caller to first update the `AccountsController` state\n // to force the migration of accounts, and then call `init`.\n if (!this.#initialized) {\n return;\n }\n\n const knownAccounts: { id: AccountId; context: AccountContext }[] = [];\n for (const id of accountIds) {\n const context = this.#accountIdToContext.get(id);\n if (context) {\n knownAccounts.push({ id, context });\n }\n }\n\n if (knownAccounts.length === 0) {\n return;\n }\n\n const previousSelectedAccountGroup = this.state.selectedAccountGroup;\n const updatedGroups = new Map<AccountGroupId, AccountWalletId>();\n const removedGroups = new Set<AccountGroupId>();\n\n this.update((state) => {\n for (const { id: accountId, context } of knownAccounts) {\n const { walletId, groupId } = context;\n const accounts =\n state.accountTree.wallets[walletId]?.groups[groupId]?.accounts;\n\n if (accounts) {\n const index = accounts.indexOf(accountId);\n if (index !== -1) {\n accounts.splice(index, 1);\n\n if (\n state.selectedAccountGroup === groupId &&\n accounts.length === 0\n ) {\n state.selectedAccountGroup = this.#getDefaultAccountGroupId(\n state.accountTree.wallets,\n );\n }\n }\n if (accounts.length === 0) {\n this.#pruneEmptyGroupAndWallet(state, walletId, groupId);\n\n // If the group gets pruned, we should not consider it as updated.\n updatedGroups.delete(groupId);\n removedGroups.add(groupId);\n } else {\n updatedGroups.set(groupId, walletId);\n }\n }\n }\n });\n\n // Clear reverse-mappings after the state update\n for (const { id } of knownAccounts) {\n this.#accountIdToContext.delete(id);\n }\n\n this.messenger.publish(\n `${controllerName}:accountTreeChange`,\n this.state.accountTree,\n );\n\n for (const [groupId, walletId] of updatedGroups) {\n this.#publishAccountGroupUpdated(walletId, groupId);\n }\n for (const groupId of removedGroups) {\n this.#publishAccountGroupRemoved(groupId);\n }\n\n const newSelectedAccountGroup = this.state.selectedAccountGroup;\n if (newSelectedAccountGroup !== previousSelectedAccountGroup) {\n this.messenger.publish(\n `${controllerName}:selectedAccountGroupChange`,\n newSelectedAccountGroup,\n previousSelectedAccountGroup,\n );\n }\n }\n\n /**\n * Helper method to prune a group if it holds no accounts and additionally\n * prune the wallet if it holds no groups. This action should take place\n * after a singular account removal.\n *\n * NOTE: This method should only be used for a group that we know to be empty.\n *\n * @param state - The AccountTreeController state to prune.\n * @param walletId - The wallet ID to prune, the wallet should be the parent of the associated group that holds the removed account.\n * @param groupId - The group ID to prune, the group should be the parent of the associated account that was removed.\n * @returns The updated state.\n */\n #pruneEmptyGroupAndWallet(\n state: AccountTreeControllerState,\n walletId: AccountWalletId,\n groupId: AccountGroupId,\n ) {\n const { wallets } = state.accountTree;\n\n delete wallets[walletId].groups[groupId];\n this.#groupIdToWalletId.delete(groupId);\n\n // Clean up metadata for the pruned group\n delete state.accountGroupsMetadata[groupId];\n\n if (Object.keys(wallets[walletId].groups).length === 0) {\n delete wallets[walletId];\n // Clean up metadata for the pruned wallet\n delete state.accountWalletsMetadata[walletId];\n }\n return state;\n }\n\n /**\n * Publishes the `:accountGroupCreated` event for a newly added group.\n * No-op if the group is not in state (defensive).\n *\n * @param walletId - The parent wallet ID.\n * @param groupId - The newly created group's ID.\n */\n #publishAccountGroupCreated(\n walletId: AccountWalletId,\n groupId: AccountGroupId,\n ): void {\n const group = this.state.accountTree.wallets[walletId]?.groups[groupId];\n if (group) {\n this.messenger.publish(`${controllerName}:accountGroupCreated`, group);\n }\n }\n\n /**\n * Publishes the `:accountGroupUpdated` event for an existing group.\n * No-op if the group is not in state (e.g. it was pruned).\n *\n * @param walletId - The parent wallet ID.\n * @param groupId - The updated group's ID.\n */\n #publishAccountGroupUpdated(\n walletId: AccountWalletId,\n groupId: AccountGroupId,\n ): void {\n const group = this.state.accountTree.wallets[walletId]?.groups[groupId];\n if (group) {\n this.messenger.publish(`${controllerName}:accountGroupUpdated`, group);\n }\n }\n\n /**\n * Publishes the `:accountGroupRemoved` event for a pruned group.\n *\n * @param groupId - The removed group's ID.\n */\n #publishAccountGroupRemoved(groupId: AccountGroupId): void {\n this.messenger.publish(`${controllerName}:accountGroupRemoved`, groupId);\n }\n\n /**\n * Insert an account inside an account tree.\n *\n * We go over multiple rules to try to \"match\" the account following\n * specific criterias. If a rule \"matches\" an account, then this\n * account get added into its proper account wallet and account group.\n *\n * @param wallets - Account tree.\n * @param account - The account to be inserted.\n * @returns The wallet ID, group ID, and whether the group has been created or not.\n */\n #insert(\n wallets: AccountTreeControllerState['accountTree']['wallets'],\n account: InternalAccount,\n ): { walletId: AccountWalletId; groupId: AccountGroupId; created: boolean } {\n const result =\n this.#getEntropyRule().match(account) ??\n this.#getSnapRule().match(account) ??\n this.#getKeyringRule().match(account); // This one cannot fail.\n\n // Update controller's state.\n const walletId = result.wallet.id;\n let wallet = wallets[walletId];\n if (!wallet) {\n log(`[${walletId}] Added as new wallet`);\n wallets[walletId] = {\n ...result.wallet,\n status: 'ready',\n groups: {},\n metadata: {\n name: '', // Will get updated later.\n ...result.wallet.metadata,\n },\n // We do need to type-cast since we're not narrowing `result` with\n // the union tag `result.wallet.type`.\n } as AccountWalletObject;\n wallet = wallets[walletId];\n\n // Trigger atomic sync for new wallet (only for entropy wallets)\n if (wallet.type === AccountWalletType.Entropy) {\n this.#backupAndSyncService.enqueueSingleWalletSync(walletId);\n }\n }\n\n const groupId = result.group.id;\n let group = wallet.groups[groupId];\n const { type, id } = account;\n const sortOrder = ACCOUNT_TYPE_TO_SORT_ORDER[type];\n const created = !group;\n\n if (!group) {\n log(`[${walletId}] Add new group: [${groupId}]`);\n wallet.groups[groupId] = {\n ...result.group,\n // Type-wise, we are guaranteed to always have at least 1 account.\n accounts: [id],\n metadata: {\n name: '',\n ...{ pinned: false, hidden: false, lastSelected: 0 }, // Default UI states\n ...result.group.metadata, // Allow rules to override defaults\n },\n // We do need to type-cast since we're not narrowing `result` with\n // the union tag `result.group.type`.\n } as AccountGroupObject;\n group = wallet.groups[groupId];\n\n // Map group ID to its containing wallet ID for efficient direct access\n this.#groupIdToWalletId.set(groupId, walletId);\n\n // Trigger atomic sync for new group (only for entropy wallets)\n if (wallet.type === AccountWalletType.Entropy) {\n this.#backupAndSyncService.enqueueSingleGroupSync(groupId);\n }\n } else {\n group.accounts.push(id);\n // We need to do this at every insertion because race conditions can happen\n // during the account creation process where one provider completes before the other.\n // The discovery process in the service can also lead to some accounts being created \"out of order\".\n const { accounts } = group;\n accounts.sort(\n /* istanbul ignore next: Comparator branch execution (a===id vs b===id)\n * and return attribution vary across engines; final ordering is covered\n * by behavior tests. Ignoring the entire comparator avoids flaky line\n * coverage without reducing scenario coverage.\n */\n (a, b) => {\n const aSortOrder =\n a === id ? sortOrder : this.#accountIdToContext.get(a)?.sortOrder;\n const bSortOrder =\n b === id ? sortOrder : this.#accountIdToContext.get(b)?.sortOrder;\n return (\n (aSortOrder ?? MAX_SORT_ORDER) - (bSortOrder ?? MAX_SORT_ORDER)\n );\n },\n );\n }\n log(\n `[${groupId}] Add new account: { id: \"${account.id}\", type: \"${account.type}\", address: \"${account.address}\"`,\n );\n\n // Update the reverse mapping for this account.\n this.#accountIdToContext.set(account.id, {\n walletId: wallet.id,\n groupId: group.id,\n sortOrder,\n });\n\n return { walletId: wallet.id, groupId: group.id, created };\n }\n\n /**\n * List all internal accounts.\n *\n * @returns The list of all internal accounts.\n */\n #listAccounts(): InternalAccount[] {\n return this.messenger.call('AccountsController:listMultichainAccounts');\n }\n\n /**\n * Asserts that a group exists in the current account tree.\n *\n * @param groupId - The account group ID to validate.\n * @throws Error if the group does not exist.\n */\n #assertAccountGroupExists(groupId: AccountGroupId): void {\n const exists = this.#groupIdToWalletId.has(groupId);\n if (!exists) {\n throw new Error('Account group not found in tree');\n }\n }\n\n /**\n * Asserts that a wallet exists in the current account tree.\n *\n * @param walletId - The account wallet ID to validate.\n * @throws Error if the wallet does not exist.\n */\n #assertAccountWalletExists(walletId: AccountWalletId): void {\n const exists = Boolean(this.state.accountTree.wallets[walletId]);\n if (!exists) {\n throw new Error('Account wallet not found in tree');\n }\n }\n\n /**\n * Asserts that an account group name is unique within the same wallet.\n *\n * @param groupId - The account group ID to exclude from the check.\n * @param name - The name to validate for uniqueness.\n * @throws Error if the name already exists in another group within the same wallet.\n */\n #assertAccountGroupNameIsUnique(groupId: AccountGroupId, name: string): void {\n if (!isAccountGroupNameUnique(this.state, groupId, name)) {\n throw new Error('Account group name already exists');\n }\n }\n\n /**\n * Gets the currently selected account group ID.\n *\n * @returns The selected account group ID or empty string if none selected.\n */\n getSelectedAccountGroup(): AccountGroupId | '' {\n return this.state.selectedAccountGroup;\n }\n\n /**\n * Sets the selected account group and updates the AccountsController selectedAccount accordingly.\n *\n * @param groupId - The account group ID to select.\n * @param forwardSelectedAccount - Whether to forward the selected account to AccountsController. Defaults to true.\n */\n #setSelectedAccountGroup(\n groupId: AccountGroupId,\n forwardSelectedAccount: boolean = true,\n ): void {\n const previousSelectedAccountGroup = this.state.selectedAccountGroup;\n\n // Idempotent check - if the same group is already selected, do nothing\n if (previousSelectedAccountGroup === groupId) {\n return;\n }\n\n // Find the first account in this group to select\n const accountToSelect = this.#getAccountFromAccountGroupId(groupId);\n if (!accountToSelect) {\n throw new Error('No accounts found in group');\n }\n\n this.update((state) => {\n // Update our selected account group first.\n state.selectedAccountGroup = groupId;\n\n // Then update its associated metadata (lastSelected timestamp) to keep\n // track of the most recently selected groups.\n const now = Date.now();\n\n /* istanbul ignore next */\n if (!state.accountGroupsMetadata[groupId]) {\n state.accountGroupsMetadata[groupId] = {};\n }\n state.accountGroupsMetadata[groupId].lastSelected = now;\n\n const walletId = this.#groupIdToWalletId.get(groupId);\n if (walletId) {\n state.accountTree.wallets[walletId].groups[\n groupId\n ].metadata.lastSelected = now;\n }\n });\n\n log(`Selected group is now: [${this.state.selectedAccountGroup}]`);\n\n this.messenger.publish(\n `${controllerName}:selectedAccountGroupChange`,\n groupId,\n previousSelectedAccountGroup,\n );\n\n if (forwardSelectedAccount) {\n // Update AccountsController - this will trigger selectedAccountChange event,\n // but our handler is idempotent so it won't cause infinite loop\n this.messenger.call(\n 'AccountsController:setSelectedAccount',\n accountToSelect.id,\n );\n\n log(`Selected account is now: ${accountToSelect.id}`);\n }\n }\n\n /**\n * Sets the selected account group and updates the AccountsController selectedAccount accordingly.\n *\n * @param groupId - The account group ID to select.\n */\n setSelectedAccountGroup(groupId: AccountGroupId): void {\n this.#setSelectedAccountGroup(groupId);\n }\n\n /**\n * Sets the selected account group and updates the AccountsController selectedAccount accordingly.\n *\n * @param accountId - The account ID to select the group for.\n */\n setSelectedAccountGroupByAccountId(accountId: AccountId): void {\n const context = this.#accountIdToContext.get(accountId);\n if (!context) {\n throw new Error('Account not found in the account tree');\n }\n this.setSelectedAccountGroup(context.groupId);\n }\n\n /**\n * Initializes the selectedAccountGroup based on the currently selected account from AccountsController.\n *\n * @param wallets - Wallets object to use for fallback logic\n * @returns The default selected account group ID or empty string if none selected.\n */\n #getDefaultSelectedAccountGroup(wallets: {\n [walletId: AccountWalletId]: AccountWalletObject;\n }): AccountGroupId | '' {\n const selectedAccount = this.messenger.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n if (selectedAccount?.id) {\n const accountMapping = this.#accountIdToContext.get(selectedAccount.id);\n if (accountMapping) {\n const { groupId } = accountMapping;\n\n return groupId;\n }\n }\n\n // Default to the default group in case of errors.\n return this.#getDefaultAccountGroupId(wallets);\n }\n\n /**\n * Handles selected account change from AccountsController.\n * Updates selectedAccountGroup to match the selected account.\n *\n * @param account - The newly selected account.\n */\n #handleSelectedAccountChange(account: InternalAccount): void {\n const accountMapping = this.#accountIdToContext.get(account.id);\n if (!accountMapping) {\n // Account not in tree yet, might be during initialization\n return;\n }\n\n const { groupId } = accountMapping;\n\n // Avoid infinite loop since this method is triggered by selected account change.\n const forwardSelectedAccount = false;\n this.#setSelectedAccountGroup(groupId, forwardSelectedAccount);\n }\n\n /**\n * Handles multichain account wallet status change from\n * the MultichainAccountService.\n *\n * @param walletId - Multichain account wallet ID.\n * @param walletStatus - New multichain account wallet status.\n */\n #handleMultichainAccountWalletStatusChange(\n walletId: MultichainAccountWalletId,\n walletStatus: MultichainAccountWalletStatus,\n ): void {\n this.update((state) => {\n const wallet = state.accountTree.wallets[walletId];\n\n if (wallet) {\n wallet.status = walletStatus;\n }\n });\n }\n\n /**\n * Gets account group object.\n *\n * @param groupId - The account group ID.\n * @returns The account group or undefined if not found.\n */\n #getAccountGroup(groupId: AccountGroupId): AccountGroupObject | undefined {\n const found = Object.values(this.state.accountTree.wallets).find(\n (wallet) => wallet.groups[groupId] !== undefined,\n );\n\n return found?.groups[groupId];\n }\n\n /**\n * Gets an account for the specified group using the EVM-priority rule.\n *\n * The account is the first EVM account found in the group, or the first\n * account in the group if no EVM account is found.\n *\n * @param groupId - The account group ID.\n * @returns The internal account in the group, or undefined if the group does\n * not exist or is empty.\n */\n #getAccountFromAccountGroupId(\n groupId: AccountGroupId,\n ): InternalAccount | undefined {\n const group = this.#getAccountGroup(groupId);\n\n if (group) {\n let candidateId: AccountId | undefined;\n for (const id of group.accounts) {\n const account = this.messenger.call(\n 'AccountsController:getAccount',\n id,\n );\n\n if (account) {\n candidateId ??= id;\n\n if (isEvmAccountType(account.type)) {\n // EVM accounts have a higher priority, so if we find any, we just\n // use that account!\n return account;\n }\n }\n }\n\n return candidateId\n ? this.messenger.call('AccountsController:getAccount', candidateId)\n : undefined;\n }\n\n return undefined;\n }\n\n /**\n * Gets the default group id by selecting the most recently selected non-empty group.\n * Groups that have never been explicitly selected (lastSelected === 0) are still\n * considered as fallbacks. When timestamps are equal, groups containing EVM accounts\n * are preferred as a tiebreaker.\n *\n * @param wallets - The wallets object to search.\n * @returns The ID of the most recently selected non-empty group, or an empty string if none found.\n */\n #getDefaultAccountGroupId(wallets: {\n [walletId: AccountWalletId]: AccountWalletObject;\n }): AccountGroupId | '' {\n let candidate: AccountGroupObject | undefined;\n\n for (const wallet of Object.values(wallets)) {\n for (const group of Object.values(wallet.groups)) {\n if (group.accounts.length === 0) {\n continue;\n }\n if (!candidate) {\n candidate = group;\n continue;\n }\n if (group.metadata.lastSelected > candidate.metadata.lastSelected) {\n candidate = group;\n } else if (\n group.metadata.lastSelected === candidate.metadata.lastSelected &&\n this.#hasEvmAccount(group) &&\n !this.#hasEvmAccount(candidate)\n ) {\n candidate = group;\n }\n }\n }\n return candidate?.id ?? '';\n }\n\n /**\n * Checks if a group contains at least one EVM account.\n *\n * @param group - The account group to check.\n * @returns True if the group contains an EVM account, false otherwise.\n */\n #hasEvmAccount(group: AccountGroupObject): boolean {\n for (const id of group.accounts) {\n const account = this.messenger.call('AccountsController:getAccount', id);\n if (account && isEvmAccountType(account.type)) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Resolves name conflicts by adding a suffix to make the name unique.\n *\n * @internal\n * @param wallet - The wallet to check within.\n * @param groupId - The account group ID to exclude from the check.\n * @param name - The desired name that has a conflict.\n * @returns A unique name with suffix added if necessary.\n */\n #resolveNameConflict(\n wallet: AccountWalletObject,\n groupId: AccountGroupId,\n name: string,\n ): string {\n let suffix = 2;\n let candidateName = `${name} (${suffix})`;\n\n // Keep incrementing suffix until we find a unique name\n while (\n !isAccountGroupNameUniqueFromWallet(wallet, groupId, candidateName)\n ) {\n suffix += 1;\n candidateName = `${name} (${suffix})`;\n }\n\n return candidateName;\n }\n\n /**\n * Sets a custom name for an account group.\n *\n * @param groupId - The account group ID.\n * @param name - The custom name to set.\n * @param autoHandleConflict - If true, automatically resolves name conflicts by adding a suffix. If false, throws on conflicts.\n * @throws If the account group ID is not found in the current tree.\n * @throws If the account group name already exists and autoHandleConflict is false.\n */\n setAccountGroupName(\n groupId: AccountGroupId,\n name: string,\n autoHandleConflict: boolean = false,\n ): void {\n // Validate that the group exists in the current tree\n this.#assertAccountGroupExists(groupId);\n\n const walletId = this.#groupIdToWalletId.get(groupId);\n assert(walletId, 'Account group not found in tree');\n\n const wallet = this.state.accountTree.wallets[walletId];\n let finalName = name;\n\n // Handle name conflicts based on the autoHandleConflict flag\n if (\n autoHandleConflict &&\n !isAccountGroupNameUniqueFromWallet(wallet, groupId, name)\n ) {\n finalName = this.#resolveNameConflict(wallet, groupId, name);\n } else {\n // Validate that the name is unique\n this.#assertAccountGroupNameIsUnique(groupId, finalName);\n }\n\n log(\n `[${groupId}] Set new name to: \"${finalName}\" (auto handle conflict: ${autoHandleConflict})`,\n );\n\n this.update((state) => {\n /* istanbul ignore next */\n if (!state.accountGroupsMetadata[groupId]) {\n state.accountGroupsMetadata[groupId] = {};\n }\n\n // Update persistent metadata\n state.accountGroupsMetadata[groupId].name = {\n value: finalName,\n lastUpdatedAt: Date.now(),\n };\n\n // Update tree node directly using efficient mapping\n state.accountTree.wallets[walletId].groups[groupId].metadata.name =\n finalName;\n });\n\n this.#publishAccountGroupUpdated(walletId, groupId);\n\n // Trigger atomic sync for group rename (only for groups from entropy wallets)\n if (wallet.type === AccountWalletType.Entropy) {\n this.#backupAndSyncService.enqueueSingleGroupSync(groupId);\n }\n }\n\n /**\n * Sets a custom name for an account wallet.\n *\n * @param walletId - The account wallet ID.\n * @param name - The custom name to set.\n * @throws If the account wallet ID is not found in the current tree.\n */\n setAccountWalletName(walletId: AccountWalletId, name: string): void {\n // Validate that the wallet exists in the current tree\n this.#assertAccountWalletExists(walletId);\n\n this.update((state) => {\n // Update persistent metadata\n state.accountWalletsMetadata[walletId] ??= {};\n state.accountWalletsMetadata[walletId].name = {\n value: name,\n lastUpdatedAt: Date.now(),\n };\n\n // Update tree node directly\n state.accountTree.wallets[walletId].metadata.name = name;\n });\n\n // Trigger atomic sync for wallet rename (only for groups from entropy wallets)\n if (\n this.state.accountTree.wallets[walletId].type ===\n AccountWalletType.Entropy\n ) {\n this.#backupAndSyncService.enqueueSingleWalletSync(walletId);\n }\n }\n\n /**\n * Toggles the pinned state of an account group.\n *\n * @param groupId - The account group ID.\n * @param pinned - Whether the group should be pinned.\n * @throws If the account group ID is not found in the current tree.\n */\n setAccountGroupPinned(groupId: AccountGroupId, pinned: boolean): void {\n // Validate that the group exists in the current tree\n this.#assertAccountGroupExists(groupId);\n\n const walletId = this.#groupIdToWalletId.get(groupId);\n\n this.update((state) => {\n /* istanbul ignore next */\n if (!state.accountGroupsMetadata[groupId]) {\n state.accountGroupsMetadata[groupId] = {};\n }\n\n // Update persistent metadata\n state.accountGroupsMetadata[groupId].pinned = {\n value: pinned,\n lastUpdatedAt: Date.now(),\n };\n\n // Update tree node directly using efficient mapping\n if (walletId) {\n state.accountTree.wallets[walletId].groups[groupId].metadata.pinned =\n pinned;\n }\n });\n\n if (walletId) {\n this.#publishAccountGroupUpdated(walletId, groupId);\n }\n\n // Trigger atomic sync for group pinning (only for groups from entropy wallets)\n if (\n walletId &&\n this.state.accountTree.wallets[walletId].type ===\n AccountWalletType.Entropy\n ) {\n this.#backupAndSyncService.enqueueSingleGroupSync(groupId);\n }\n }\n\n /**\n * Toggles the hidden state of an account group.\n *\n * @param groupId - The account group ID.\n * @param hidden - Whether the group should be hidden.\n * @throws If the account group ID is not found in the current tree.\n */\n setAccountGroupHidden(groupId: AccountGroupId, hidden: boolean): void {\n // Validate that the group exists in the current tree\n this.#assertAccountGroupExists(groupId);\n\n const walletId = this.#groupIdToWalletId.get(groupId);\n\n this.update((state) => {\n /* istanbul ignore next */\n if (!state.accountGroupsMetadata[groupId]) {\n state.accountGroupsMetadata[groupId] = {};\n }\n\n // Update persistent metadata\n state.accountGroupsMetadata[groupId].hidden = {\n value: hidden,\n lastUpdatedAt: Date.now(),\n };\n\n // Update tree node directly using efficient mapping\n if (walletId) {\n state.accountTree.wallets[walletId].groups[groupId].metadata.hidden =\n hidden;\n }\n });\n\n if (walletId) {\n this.#publishAccountGroupUpdated(walletId, groupId);\n }\n\n // Trigger atomic sync for group hiding (only for groups from entropy wallets)\n if (\n walletId &&\n this.state.accountTree.wallets[walletId].type ===\n AccountWalletType.Entropy\n ) {\n this.#backupAndSyncService.enqueueSingleGroupSync(groupId);\n }\n }\n\n /**\n * Clears the controller state and resets to default values.\n * Also clears the backup and sync service state.\n */\n clearState(): void {\n log('Clearing state');\n\n const previousSelectedAccountGroup = this.state.selectedAccountGroup;\n\n this.update(() => {\n return {\n ...getDefaultAccountTreeControllerState(),\n };\n });\n this.#backupAndSyncService.clearState();\n\n // Clear in-memory reverse-lookup Maps so stale data is not accessible\n // between this call and the next init().\n this.#accountIdToContext.clear();\n this.#groupIdToWalletId.clear();\n\n // Notify subscribers that the selected group has been cleared,\n // mirroring what #setSelectedAccountGroup does on normal transitions.\n this.messenger.publish(\n `${controllerName}:selectedAccountGroupChange`,\n '',\n previousSelectedAccountGroup,\n );\n\n // So we know we have to call `init` again.\n this.#initialized = false;\n this.messenger.publish(`${controllerName}:uninitialized`);\n }\n\n /**\n * Bi-directionally syncs the account tree with user storage.\n * This will perform a full sync, including both pulling updates\n * from user storage and pushing local changes to user storage.\n * This also performs legacy account syncing if needed.\n *\n * IMPORTANT:\n * If a full sync is already in progress, it will return the ongoing promise.\n *\n * @returns A promise that resolves when the sync is complete.\n */\n async syncWithUserStorage(): Promise<void> {\n return this.#backupAndSyncService.performFullSync();\n }\n\n /**\n * Bi-directionally syncs the account tree with user storage.\n * This will ensure at least one full sync is ran, including both pulling updates\n * from user storage and pushing local changes to user storage.\n * This also performs legacy account syncing if needed.\n *\n * IMPORTANT:\n * If the first ever full sync is already in progress, it will return the ongoing promise.\n * If the first ever full sync was previously completed, it will NOT start a new sync, and will resolve immediately.\n *\n * @returns A promise that resolves when the first ever full sync is complete.\n */\n async syncWithUserStorageAtLeastOnce(): Promise<void> {\n return this.#backupAndSyncService.performFullSyncAtLeastOnce();\n }\n\n /**\n * Produces a versioned snapshot of the current wallet and group state.\n *\n * When `options.includeSecrets` is `true`, `options.password` is required\n * and verified against the vault before any secret is read. Without\n * `includeSecrets`, only metadata (names, pinned, hidden) is exported and\n * no password is needed.\n *\n * @param options - Export options.\n * @returns A promise resolving to an `AccountTreeSnapshot`.\n * @throws If the vault is locked or the password is incorrect.\n */\n async exportState(\n options?: ExportStateOptions,\n ): Promise<AccountTreeSnapshot> {\n return exportState(\n { getState: () => this.state, messenger: this.messenger },\n options,\n );\n }\n\n /**\n * Applies a validated snapshot to the current state.\n *\n * Accepts an {@link AccountTreeSnapshot} only — untrusted wire data must be\n * parsed with {@link AccountTreeSnapshot.deserialize} first. Callers may\n * filter the snapshot with {@link AccountTreeSnapshot.filterWallets},\n * {@link AccountTreeSnapshot.filterGroups}, or\n * {@link AccountTreeSnapshot.filterAllGroups} before importing.\n *\n * New mnemonic wallets are imported via `MultichainAccountService` and new\n * private-key accounts via `KeyringController`. Metadata (name, pinned,\n * hidden) is applied to all existing and newly created wallets / groups.\n *\n * @param snapshot - The validated snapshot to import.\n * @returns A promise that resolves when the import is complete.\n */\n async importState(snapshot: AccountTreeSnapshot): Promise<void> {\n return importState(\n {\n getState: () => this.state,\n messenger: this.messenger,\n setWalletName: (id, name) => this.setAccountWalletName(id, name),\n setAccountGroupName: (id, name) =>\n this.setAccountGroupName(id, name, true),\n setAccountGroupPinned: (id, pinned) =>\n this.setAccountGroupPinned(id, pinned),\n setAccountGroupHidden: (id, hidden) =>\n this.setAccountGroupHidden(id, hidden),\n },\n snapshot,\n );\n }\n\n /**\n * Creates an backup and sync context for sync operations.\n * Used by the backup and sync service.\n *\n * @returns The backup and sync context.\n */\n #createBackupAndSyncContext(): BackupAndSyncContext {\n return {\n ...this.#backupAndSyncConfig,\n controller: this,\n messenger: this.messenger,\n controllerStateUpdateFn: this.update.bind(this),\n traceFn: this.#trace.bind(this),\n groupIdToWalletId: this.#groupIdToWalletId,\n mutationTracker: createSyncMutationTracker(),\n };\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"AccountTreeController.js","sourceRoot":"","sources":["../src/AccountTreeController.ts"],"names":[],"mappings":"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","sourcesContent":["import { AccountWalletType, select } from '@metamask/account-api';\nimport type {\n AccountGroupId,\n AccountWalletId,\n AccountSelector,\n MultichainAccountWalletId,\n AccountGroupType,\n} from '@metamask/account-api';\nimport type { MultichainAccountWalletStatus } from '@metamask/account-api';\nimport type { AccountId } from '@metamask/accounts-controller';\nimport type { StateMetadata } from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport type { EntropySourceId } from '@metamask/keyring-api';\nimport { isEvmAccountType } from '@metamask/keyring-api';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport { assert, isCaipChainId } from '@metamask/utils';\nimport type { CaipChainId } from '@metamask/utils';\n\nimport type { BackupAndSyncEmitAnalyticsEventParams } from './backup-and-sync/analytics/index.js';\nimport {\n formatAnalyticsEvent,\n traceFallback,\n} from './backup-and-sync/analytics/index.js';\nimport { BackupAndSyncService } from './backup-and-sync/service/index.js';\nimport type { BackupAndSyncContext } from './backup-and-sync/types.js';\nimport { createSyncMutationTracker } from './backup-and-sync/utils/index.js';\nimport type { RemoveAccountWalletFailure } from './errors.js';\nimport { reportRemoveAccountWalletError } from './errors.js';\nimport type { AccountGroupObject, AccountTypeOrderKey } from './group.js';\nimport {\n ACCOUNT_TYPE_TO_SORT_ORDER,\n isAccountGroupNameUnique,\n isAccountGroupNameUniqueFromWallet,\n MAX_SORT_ORDER,\n} from './group.js';\nimport { projectLogger as log } from './logger.js';\nimport type { Rule } from './rule.js';\nimport { EntropyRule } from './rules/entropy.js';\nimport { KeyringRule } from './rules/keyring.js';\nimport { SnapRule } from './rules/snap.js';\nimport { exportState } from './state/export.js';\nimport { importState } from './state/import.js';\nimport type { ExportStateOptions } from './state/payload.js';\nimport type { AccountTreeSnapshot } from './state/snapshot.js';\nimport type {\n AccountTreeControllerConfig,\n AccountTreeControllerInternalBackupAndSyncConfig,\n AccountTreeControllerMessenger,\n AccountTreeControllerState,\n} from './types.js';\nimport type { AccountWalletObject, AccountWalletObjectOf } from './wallet.js';\n\nexport const controllerName = 'AccountTreeController';\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'isInitialized',\n 'getSelectedAccountGroup',\n 'setSelectedAccountGroup',\n 'setSelectedAccountGroupByAccountId',\n 'getAccountsFromSelectedAccountGroup',\n 'getAccountFromSelectedAccountGroup',\n 'getAccountContext',\n 'setAccountWalletName',\n 'setAccountGroupName',\n 'setAccountGroupPinned',\n 'setAccountGroupHidden',\n 'getAccountWalletObject',\n 'getAccountWalletObjects',\n 'removeAccountWallet',\n 'getAccountGroupObject',\n 'clearState',\n 'syncWithUserStorage',\n 'syncWithUserStorageAtLeastOnce',\n 'init',\n 'reinit',\n 'exportState',\n 'importState',\n] as const;\n\nconst accountTreeControllerMetadata: StateMetadata<AccountTreeControllerState> =\n {\n accountTree: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n selectedAccountGroup: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n isAccountTreeSyncingInProgress: {\n includeInStateLogs: false,\n persist: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n hasAccountTreeSyncingSyncedAtLeastOnce: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n accountGroupsMetadata: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n accountWalletsMetadata: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n };\n\n/**\n * Gets default state of the `AccountTreeController`.\n *\n * @returns The default state of the `AccountTreeController`.\n */\nexport function getDefaultAccountTreeControllerState(): AccountTreeControllerState {\n return {\n accountTree: {\n wallets: {},\n },\n selectedAccountGroup: '',\n isAccountTreeSyncingInProgress: false,\n hasAccountTreeSyncingSyncedAtLeastOnce: false,\n accountGroupsMetadata: {},\n accountWalletsMetadata: {},\n };\n}\n\n/**\n * Context for an account.\n */\nexport type AccountContext = {\n /**\n * Wallet ID associated to that account.\n */\n walletId: AccountWalletObject['id'];\n\n /**\n * Account group ID associated to that account.\n */\n groupId: AccountGroupObject['id'];\n\n /**\n * Sort order of the account.\n */\n sortOrder: (typeof ACCOUNT_TYPE_TO_SORT_ORDER)[AccountTypeOrderKey];\n};\n\nexport class AccountTreeController extends BaseController<\n typeof controllerName,\n AccountTreeControllerState,\n AccountTreeControllerMessenger\n> {\n readonly #accountIdToContext: Map<AccountId, AccountContext>;\n\n readonly #groupIdToWalletId: Map<AccountGroupId, AccountWalletId>;\n\n /**\n * Service responsible for all backup and sync operations.\n */\n readonly #backupAndSyncService: BackupAndSyncService;\n\n readonly #rules: [EntropyRule, SnapRule, KeyringRule];\n\n readonly #trace: TraceCallback;\n\n readonly #backupAndSyncConfig: AccountTreeControllerInternalBackupAndSyncConfig;\n\n /**\n * Callbacks to migrate hidden and pinned account information from the account order controller\n */\n readonly #accountOrderCallbacks:\n | AccountTreeControllerConfig['accountOrderCallbacks']\n | undefined;\n\n #initialized: boolean;\n\n /**\n * Constructor for AccountTreeController.\n *\n * @param options - The controller options.\n * @param options.messenger - The messenger object.\n * @param options.state - Initial state to set on this controller\n * @param options.config - Optional configuration for the controller.\n */\n\n constructor({\n messenger,\n state,\n config,\n }: {\n messenger: AccountTreeControllerMessenger;\n state?: Partial<AccountTreeControllerState>;\n config?: AccountTreeControllerConfig;\n }) {\n super({\n messenger,\n name: controllerName,\n metadata: accountTreeControllerMetadata,\n state: {\n ...getDefaultAccountTreeControllerState(),\n ...state,\n },\n });\n\n // This will be set to true upon the first `init` call.\n this.#initialized = false;\n\n // Reverse map to allow fast node access from an account ID.\n this.#accountIdToContext = new Map();\n\n // Reverse map to allow fast wallet node access from a group ID.\n this.#groupIdToWalletId = new Map();\n\n // Rules to apply to construct the wallets tree.\n this.#rules = [\n // 1. We group by entropy-source\n new EntropyRule(this.messenger),\n // 2. We group by Snap ID\n new SnapRule(this.messenger),\n // 3. We group by wallet type (this rule cannot fail and will group all non-matching accounts)\n new KeyringRule(this.messenger),\n ];\n\n // Initialize trace function\n this.#trace = config?.trace ?? traceFallback;\n\n // Initialize backup and sync config\n this.#backupAndSyncConfig = {\n emitAnalyticsEventFn: (event: BackupAndSyncEmitAnalyticsEventParams) => {\n return config?.backupAndSync?.onBackupAndSyncEvent?.(\n formatAnalyticsEvent(event),\n );\n },\n };\n\n // Used when migrating initial hidden/pinned state for groups (if available).\n this.#accountOrderCallbacks = config?.accountOrderCallbacks;\n\n // Initialize the backup and sync service\n this.#backupAndSyncService = new BackupAndSyncService(\n this.#createBackupAndSyncContext(),\n );\n\n // We build the initial tree (from the state), but this might get updated\n // after `init` got called. Having it available now, allow our consumers to\n // re-use the state that was already available before we restart/lock the\n // wallet.\n this.#initTreeContext(this.state.accountTree);\n\n this.messenger.subscribe('AccountsController:accountsAdded', (accounts) => {\n this.#handleAccountsAdded(accounts);\n });\n\n this.messenger.subscribe(\n 'AccountsController:accountsRemoved',\n (accountIds) => {\n this.#handleAccountsRemoved(accountIds);\n },\n );\n\n this.messenger.subscribe(\n 'AccountsController:selectedAccountChange',\n (account) => {\n this.#handleSelectedAccountChange(account);\n },\n );\n\n this.messenger.subscribe(\n 'UserStorageController:stateChange',\n (userStorageControllerState) => {\n this.#backupAndSyncService.handleUserStorageStateChange(\n userStorageControllerState,\n );\n },\n );\n\n this.messenger.subscribe(\n 'MultichainAccountService:walletStatusChange',\n (walletId, status) => {\n this.#handleMultichainAccountWalletStatusChange(walletId, status);\n },\n );\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n }\n\n /**\n * Initialize the account tree from the given state.\n *\n * @param tree The account tree state to initialize from.\n */\n #initTreeContext(tree: AccountTreeControllerState['accountTree']): void {\n // Fetch persisted accounts from the `AccountsController`.\n const accounts = new Map(\n this.#listAccounts().map((account) => [account.id, account]),\n );\n\n for (const [walletId, wallet] of Object.entries(tree.wallets) as [\n AccountWalletId,\n AccountWalletObject,\n ][]) {\n for (const [groupId, group] of Object.entries(wallet.groups) as [\n AccountGroupId,\n AccountGroupObject,\n ][]) {\n this.#groupIdToWalletId.set(groupId, walletId);\n\n // We still need to go through accounts for the sort order.\n for (const accountId of group.accounts) {\n const account = accounts.get(accountId);\n\n // NOTE: The account should always be available, but if it is not, we\n // still let it inside the tree with a max sort order to avoid blocking\n // the entire tree construction.\n let sortOrder = MAX_SORT_ORDER;\n if (account) {\n sortOrder = ACCOUNT_TYPE_TO_SORT_ORDER[account.type];\n }\n\n this.#accountIdToContext.set(accountId, {\n walletId,\n groupId,\n sortOrder,\n });\n }\n }\n }\n }\n\n /**\n * Initialize the controller's state.\n *\n * It constructs the initial state of the account tree (tree nodes, nodes\n * names, metadata, etc..) and will automatically update the controller's\n * state with it.\n */\n init() {\n if (this.#initialized) {\n // We prevent re-initilializing the state multiple times. Though, we can use\n // `reinit` to re-init everything from scratch.\n return;\n }\n\n log('Initializing...');\n\n const wallets: AccountTreeControllerState['accountTree']['wallets'] = {};\n\n // Clear mappings for fresh rebuild.\n this.#accountIdToContext.clear();\n this.#groupIdToWalletId.clear();\n\n // Keep the current selected group to check if it's still part of the tree\n // after rebuilding it.\n const previousSelectedAccountGroup = this.state.selectedAccountGroup;\n\n // There's no guarantee that accounts would be sorted by their import time\n // with `listMultichainAccounts`. We have to sort them here before constructing\n // the tree.\n //\n // Because of the alignment mecanism, some accounts from the same group might not\n // have been imported at the same time, but at least of them should have been\n // imported at the right time, thus, inserting the group at the proper place too.\n //\n // Lastly, if one day we allow to have \"gaps\" in between groups, then this `sort`\n // won't be enough and we would have to use group properties instead (like group\n // index or maybe introduce a `importTime` at group level).\n const accounts = this.#listAccounts().sort(\n (a, b) => a.metadata.importTime - b.metadata.importTime,\n );\n\n // For now, we always re-compute all wallets, we do not re-use the existing state.\n for (const account of accounts) {\n this.#insert(wallets, account);\n }\n\n // Once we have the account tree, we can apply persisted metadata (names + UI states).\n let previousSelectedAccountGroupStillExists = false;\n this.update((state) => {\n state.accountTree.wallets = wallets;\n\n // Apply group metadata within the state update\n for (const wallet of Object.values(state.accountTree.wallets)) {\n this.#applyAccountWalletMetadata(state, wallet.id);\n\n // Used for default group default names (so we use human-indexing here).\n let nextNaturalNameIndex = 1;\n for (const group of Object.values(wallet.groups)) {\n this.#applyAccountGroupMetadata(state, wallet.id, group.id, {\n // We allow computed name when initializing the tree.\n // This will automatically handle account name migration for the very first init of the\n // tree. Once groups are created, their name will be persisted, thus, taking precedence\n // over the computed names (even if we re-init).\n allowComputedName: true,\n // FIXME: We should not need this kind of logic if we were not inserting accounts\n // 1 by 1. Instead, we should be inserting wallets and groups directly. This would\n // allow us to naturally insert a group in the tree AND update its metadata right\n // away...\n // But here, we have to wait for the entire group to be ready before updating\n // its metadata (mainly because we're dealing with single accounts rather than entire\n // groups).\n // That is why we need this kind of extra parameter.\n nextNaturalNameIndex,\n });\n\n if (group.id === previousSelectedAccountGroup) {\n previousSelectedAccountGroupStillExists = true;\n }\n nextNaturalNameIndex += 1;\n }\n }\n\n if (\n !previousSelectedAccountGroupStillExists ||\n previousSelectedAccountGroup === ''\n ) {\n // No group is selected yet OR group no longer exists, re-sync with the\n // AccountsController.\n state.selectedAccountGroup = this.#getDefaultSelectedAccountGroup(\n state.accountTree.wallets, // Re-use updated wallets with metadata here.\n );\n }\n });\n\n // We always fire the current selected group after init, even if it did not change, to ensure that\n // all subscribers are aware of it and can react accordingly (e.g. by fetching accounts from\n // the selected group on startup).\n log(`Selected (initial) group is: [${this.state.selectedAccountGroup}]`);\n this.messenger.publish(\n `${controllerName}:selectedAccountGroupChange`,\n this.state.selectedAccountGroup,\n previousSelectedAccountGroup,\n );\n\n this.#initialized = true;\n log('Initialized!');\n this.messenger.publish(`${controllerName}:initialized`, this.state);\n }\n\n /**\n * Re-initialize the controller's state.\n *\n * This is done in one single (atomic) `update` block to avoid having a temporary\n * cleared state. Use this when you need to force a full re-init even if already initialized.\n */\n reinit() {\n log('Re-initializing...');\n this.#initialized = false;\n this.init();\n }\n\n /**\n * Whether `init()` has completed and the account tree is ready to consume.\n * Returns false after `clearState()` until the next successful `init()`.\n *\n * @returns True when the controller has been initialized.\n */\n isInitialized(): boolean {\n return this.#initialized;\n }\n\n /**\n * Rule for entropy-base wallets.\n *\n * @returns The rule for entropy-based wallets.\n */\n #getEntropyRule(): EntropyRule {\n return this.#rules[0];\n }\n\n /**\n * Gets the entropy source ID of the primary HD keyring.\n *\n * @returns The primary entropy source ID, or `undefined` if no HD keyring exists.\n */\n #getPrimaryEntropySource(): EntropySourceId | undefined {\n return this.#getEntropyRule().getPrimaryEntropySource();\n }\n\n /**\n * Rule for Snap-base wallets.\n *\n * @returns The rule for snap-based wallets.\n */\n #getSnapRule(): SnapRule {\n return this.#rules[1];\n }\n\n /**\n * Rule for keyring-base wallets.\n *\n * This rule acts as a fallback and never fails since all accounts\n * comes from a keyring anyway.\n *\n * @returns The fallback rule for every accounts that did not match\n * any other rules.\n */\n #getKeyringRule(): KeyringRule {\n return this.#rules[2];\n }\n\n /**\n * Applies wallet metadata updates (name) by checking the persistent state\n * first, and then fallbacks to default values (based on the wallet's\n * type).\n *\n * @param state Controller state to update for persistence.\n * @param walletId The wallet ID to update.\n */\n #applyAccountWalletMetadata(\n state: AccountTreeControllerState,\n walletId: AccountWalletId,\n ) {\n const wallet = state.accountTree.wallets[walletId];\n const persistedMetadata = state.accountWalletsMetadata[walletId];\n\n // Apply persisted name if available (including empty strings)\n if (persistedMetadata?.name !== undefined) {\n wallet.metadata.name = persistedMetadata.name.value;\n } else if (!wallet.metadata.name) {\n // Generate default name if none exists\n if (wallet.type === AccountWalletType.Entropy) {\n wallet.metadata.name =\n this.#getEntropyRule().getDefaultAccountWalletName(wallet);\n } else if (wallet.type === AccountWalletType.Snap) {\n wallet.metadata.name =\n this.#getSnapRule().getDefaultAccountWalletName(wallet);\n } else {\n wallet.metadata.name =\n this.#getKeyringRule().getDefaultAccountWalletName(wallet);\n }\n log(`[${wallet.id}] Set default name to: \"${wallet.metadata.name}\"`);\n }\n }\n\n /**\n * Gets the appropriate rule instance for a given wallet type.\n *\n * @param wallet - The wallet object to get the rule for.\n * @returns The rule instance that handles the wallet's type.\n */\n #getRuleForWallet<WalletType extends AccountWalletType>(\n wallet: AccountWalletObjectOf<WalletType>,\n ): Rule<WalletType, AccountGroupType> {\n switch (wallet.type) {\n case AccountWalletType.Entropy:\n return this.#getEntropyRule() as unknown as Rule<\n WalletType,\n AccountGroupType\n >;\n case AccountWalletType.Snap:\n return this.#getSnapRule() as unknown as Rule<\n WalletType,\n AccountGroupType\n >;\n default:\n return this.#getKeyringRule() as unknown as Rule<\n WalletType,\n AccountGroupType\n >;\n }\n }\n\n /**\n * Gets the computed name of a group (using its associated accounts).\n *\n * @param wallet The wallet containing the group.\n * @param group The account group to update.\n * @returns The computed name for the group or '' if there's no compute named for this group.\n */\n #getComputedAccountGroupName(\n wallet: AccountWalletObject,\n group: AccountGroupObject,\n ): string {\n let proposedName = ''; // Empty means there's no computed name for this group.\n\n for (const id of group.accounts) {\n const account = this.messenger.call('AccountsController:getAccount', id);\n if (!account?.metadata.name.length) {\n continue;\n }\n\n // We only pick a new proposed name if we don't have one yet.\n if (!proposedName) {\n proposedName = account.metadata.name;\n }\n\n // But EVM accounts take precedence over any other computed names.\n if (isEvmAccountType(account.type)) {\n // So we just overwrite the proposed name and stop looping right away.\n proposedName = account.metadata.name;\n break;\n }\n }\n\n // If this name already exists for whatever reason, we rename it to resolve this conflict.\n if (\n proposedName.length &&\n !isAccountGroupNameUniqueFromWallet(wallet, group.id, proposedName)\n ) {\n proposedName = this.#resolveNameConflict(wallet, group.id, proposedName);\n }\n\n return proposedName;\n }\n\n /**\n * Gets the default name of a group.\n *\n * @param state Controller state to update for persistence.\n * @param wallet The wallet containing the group.\n * @param group The account group to update.\n * @param nextNaturalNameIndex The next natural name index for this group.\n * @returns The default name for the group.\n */\n #getDefaultAccountGroupName(\n state: AccountTreeControllerState,\n wallet: AccountWalletObject,\n group: AccountGroupObject,\n nextNaturalNameIndex?: number,\n ): string {\n // Get the appropriate rule for this wallet type\n const rule = this.#getRuleForWallet(wallet);\n\n // Get the prefix for groups of this wallet\n const namePrefix = rule.getDefaultAccountGroupPrefix(wallet);\n\n // Parse the highest account index being used (similar to accounts-controller)\n let highestNameIndex = 0;\n for (const { id: otherGroupId } of Object.values(\n wallet.groups,\n ) as AccountGroupObject[]) {\n // Skip the current group being processed\n if (otherGroupId === group.id) {\n continue;\n }\n\n // We always get the name from the persisted map, since `init` will clear the\n // `state.accountTree.wallets`, thus, given empty `group.metadata.name`.\n // NOTE: If the other group has not been named yet, we just use an empty name.\n const otherGroupName =\n state.accountGroupsMetadata[otherGroupId]?.name?.value ?? '';\n\n // Parse the existing group name to extract the numeric index\n const nameMatch = otherGroupName.match(/account\\s+(\\d+)$/iu);\n if (nameMatch) {\n const nameIndex = parseInt(nameMatch[1], 10);\n if (nameIndex > highestNameIndex) {\n highestNameIndex = nameIndex;\n }\n }\n }\n\n // We just use the highest known index no matter the wallet type.\n //\n // For entropy-based wallets (bip44), if a multichain account group with group index 1\n // is inserted before another one with group index 0, then the naming will be:\n // - \"Account 1\" (group index 1)\n // - \"Account 2\" (group index 0)\n // This naming makes more sense for the end-user.\n //\n // For other type of wallets, since those wallets can create arbitrary gaps, we still\n // rely on the highest know index to avoid back-filling account with \"old names\".\n let proposedNameIndex = Math.max(\n // Use + 1 to use the next available index.\n highestNameIndex + 1,\n // In case all accounts have been renamed differently than the usual \"Account <index>\"\n // pattern, we want to use the next \"natural\" index, which is just the number of groups\n // in that wallet (e.g. [\"Account A\", \"Another Account\"], next natural index would be\n // \"Account 3\" in this case).\n nextNaturalNameIndex ?? Object.keys(wallet.groups).length,\n );\n\n // Find a unique name by checking for conflicts and incrementing if needed\n let proposedNameExists: boolean;\n let proposedName = '';\n do {\n proposedName = `${namePrefix} ${proposedNameIndex}`;\n\n // Check if this name already exists in the wallet (excluding current group)\n proposedNameExists = !isAccountGroupNameUniqueFromWallet(\n wallet,\n group.id,\n proposedName,\n );\n\n /* istanbul ignore next */\n if (proposedNameExists) {\n proposedNameIndex += 1; // Try next number\n }\n } while (proposedNameExists);\n\n return proposedName;\n }\n\n /**\n * Applies group metadata updates (name, pinned, hidden flags) by checking\n * the persistent state first, and then fallbacks to default values (based\n * on the wallet's\n * type).\n *\n * @param state Controller state to update for persistence.\n * @param walletId The wallet ID containing the group.\n * @param groupId The account group ID to update.\n * @param namingOptions Options around account group naming.\n * @param namingOptions.allowComputedName Allow to use original account names to compute the default name.\n * @param namingOptions.nextNaturalNameIndex The next natural name index for this group (only used for default names).\n */\n #applyAccountGroupMetadata(\n state: AccountTreeControllerState,\n walletId: AccountWalletId,\n groupId: AccountGroupId,\n {\n allowComputedName,\n nextNaturalNameIndex,\n }: {\n allowComputedName?: boolean;\n nextNaturalNameIndex?: number;\n } = {},\n ) {\n const wallet = state.accountTree.wallets[walletId];\n const group = wallet.groups[groupId];\n const persistedGroupMetadata = state.accountGroupsMetadata[groupId];\n\n // Ensure metadata object exists once at the beginning\n state.accountGroupsMetadata[groupId] ??= {};\n\n // Apply persisted name if available (including empty strings)\n if (persistedGroupMetadata?.name !== undefined) {\n state.accountTree.wallets[walletId].groups[groupId].metadata.name =\n persistedGroupMetadata.name.value;\n } else if (!group.metadata.name) {\n let proposedName = '';\n\n // Computed names are usually only used for existing/old accounts. So this option\n // should be used only when we first initialize the tree.\n if (allowComputedName) {\n proposedName = this.#getComputedAccountGroupName(wallet, group);\n }\n\n // If we still don't have a valid name candidate, we fallback to a default name.\n if (!proposedName.length) {\n proposedName = this.#getDefaultAccountGroupName(\n state,\n wallet,\n group,\n nextNaturalNameIndex,\n );\n }\n\n state.accountTree.wallets[walletId].groups[groupId].metadata.name =\n proposedName;\n log(`[${group.id}] Set default name to: \"${group.metadata.name}\"`);\n\n // Persist the generated name to ensure consistency\n state.accountGroupsMetadata[groupId].name = {\n value: proposedName,\n // The `lastUpdatedAt` field is used for backup and sync, when comparing local names\n // with backed up names. In this case, the generated name should never take precedence\n // over a user-defined name, so we set `lastUpdatedAt` to 0.\n lastUpdatedAt: 0,\n };\n }\n\n // Apply persisted UI states\n if (persistedGroupMetadata?.pinned?.value !== undefined) {\n group.metadata.pinned = persistedGroupMetadata.pinned.value;\n } else {\n let isPinned = false;\n\n if (this.#accountOrderCallbacks?.isPinnedAccount) {\n isPinned = group.accounts.some((account) =>\n this.#accountOrderCallbacks?.isPinnedAccount?.(account),\n );\n }\n state.accountGroupsMetadata[groupId].pinned = {\n value: isPinned,\n lastUpdatedAt: 0,\n };\n // If any accounts was previously pinned, then we consider the group to be pinned as well.\n group.metadata.pinned = isPinned;\n }\n\n if (persistedGroupMetadata?.hidden?.value !== undefined) {\n group.metadata.hidden = persistedGroupMetadata.hidden.value;\n } else {\n let isHidden = false;\n\n if (this.#accountOrderCallbacks?.isHiddenAccount) {\n isHidden = group.accounts.some((account) =>\n this.#accountOrderCallbacks?.isHiddenAccount?.(account),\n );\n }\n state.accountGroupsMetadata[groupId].hidden = {\n value: isHidden,\n lastUpdatedAt: 0,\n };\n // If any accounts was previously hidden, then we consider the group to be hidden as well.\n group.metadata.hidden = isHidden;\n }\n\n // Apply persisted lastSelected (plain number, not synced).\n if (\n persistedGroupMetadata?.lastSelected !== undefined &&\n persistedGroupMetadata.lastSelected >= 0\n ) {\n group.metadata.lastSelected = persistedGroupMetadata.lastSelected;\n } else {\n // Automatiacally inject default value.\n state.accountGroupsMetadata[groupId].lastSelected = 0;\n\n group.metadata.lastSelected = 0;\n }\n }\n\n /**\n * Removes a non-multichain account wallet and all of its underlying accounts.\n *\n * @param wallet - The non-multichain account wallet to remove.\n * @returns An object indicating success or failure, with failure details if applicable.\n */\n async #removeNonMultichainAccountWallet(\n wallet: AccountWalletObject,\n ): Promise<\n { ok: true } | { ok: false; failures: RemoveAccountWalletFailure[] }\n > {\n const failures: RemoveAccountWalletFailure[] = [];\n\n // Snapshot IDs before the first removal. Each removeAccount call can\n // synchronously publish accountsRemoved and mutate wallet.groups.\n const accountIds = Object.values(wallet.groups).flatMap((group) => [\n ...group.accounts,\n ]);\n const accounts = this.messenger.call(\n 'AccountsController:getAccounts',\n accountIds,\n );\n\n for (let i = 0; i < accountIds.length; i++) {\n const id = accountIds[i];\n const account = accounts[i];\n\n if (!account) {\n failures.push({ id, error: new Error('Account not found') });\n continue;\n }\n\n try {\n // For Snaps, SnapKeyring removes its local account before notifying the Snap\n // and catches Snap-side failures, so this also provides forced cleanup\n // for Snap accounts.\n //\n // For hardware wallets, removal is local and does not require the device\n // to be connected.\n await this.messenger.call(\n 'KeyringController:removeAccount',\n account.address,\n );\n } catch (error) {\n failures.push({ id, error });\n }\n }\n\n return failures.length === 0 ? { ok: true } : { ok: false, failures };\n }\n\n /**\n * Removes an account wallet and all of its underlying accounts.\n *\n * The account tree is a derived view of AccountsController state, so this\n * method intentionally does not mutate tree nodes directly. Account removal\n * causes AccountsController to publish `accountsRemoved`, which lets\n * `#handleAccountsRemoved` consistently prune tree nodes, reverse mappings,\n * metadata, and selection state.\n *\n * @param walletId - Account wallet ID.\n * @throws If the account tree has not been initialized.\n * @throws If the wallet does not exist.\n * @throws If the wallet belongs to the primary HD keyring.\n */\n async removeAccountWallet(walletId: AccountWalletId): Promise<void> {\n if (!this.#initialized) {\n throw new Error('Account tree is not initialized');\n }\n\n // Track of failures during the removal process.\n const failures: RemoveAccountWalletFailure[] = [];\n\n this.#assertAccountWalletExists(walletId);\n const wallet = this.state.accountTree.wallets[walletId];\n\n if (wallet.type === AccountWalletType.Entropy) {\n // Handle removal of entropy-based account wallets.\n if (wallet.metadata.entropy.id === this.#getPrimaryEntropySource()) {\n throw new Error('Cannot remove the primary account wallet');\n }\n\n await this.messenger.call(\n 'MultichainAccountService:removeMultichainAccountWallet',\n wallet.metadata.entropy.id,\n );\n } else {\n const result = await this.#removeNonMultichainAccountWallet(wallet);\n\n if (!result.ok) {\n failures.push(...result.failures);\n }\n }\n\n // Successful account removal normally prunes the wallet through\n // #handleAccountsRemoved. If there's a leftover, it indicates that removal\n // was not fully successful. This is a best-effort and may already have\n // produced irreversible side effects.\n const remainingWallet = this.getAccountWalletObject(walletId);\n if (remainingWallet) {\n let error = new Error('Account wallet removal is incomplete');\n\n // The wallet still exists in the tree after the removal attempt. That's\n // unexpected and indicates a failure in the removal process.\n const remainingAccountIds = Object.values(remainingWallet.groups).flatMap(\n (group) => group.accounts,\n );\n if (remainingAccountIds.length > 0) {\n failures.push(\n // Accounts still in the tree after all removals completed are also\n // failures - either removal threw (already in result.failures) or the\n // accountsRemoved event never arrived to prune them.\n ...remainingAccountIds.map((id) => ({\n id,\n error: new Error('Account was not removed from the tree'),\n })),\n );\n }\n\n if (remainingAccountIds.length === 0) {\n // This should not occur through the normal event flow because\n // #handleAccountsRemoved prunes an empty wallet atomically.\n /* istanbul ignore next */\n error = new Error(\n 'Account wallet remains in the tree without accounts',\n );\n }\n\n reportRemoveAccountWalletError(\n this.messenger,\n error.message,\n error,\n failures,\n );\n }\n }\n\n /**\n * Gets the account wallet object from its ID.\n *\n * @param walletId - Account wallet ID.\n * @returns The account wallet object if found, undefined otherwise.\n */\n getAccountWalletObject(\n walletId: AccountWalletId,\n ): AccountWalletObject | undefined {\n const wallet = this.state.accountTree.wallets[walletId];\n if (!wallet) {\n return undefined;\n }\n\n return wallet;\n }\n\n /**\n * Gets all account wallet objects.\n *\n * @returns All account wallet objects.\n */\n getAccountWalletObjects(): AccountWalletObject[] {\n return Object.values(this.state.accountTree.wallets);\n }\n\n /**\n * Gets all underlying accounts from the currently selected account\n * group.\n *\n * It also support account selector, which allows to filter specific\n * accounts given some criterias (account type, address, scopes, etc...).\n *\n * @param selector - Optional account selector.\n * @returns Underlying accounts for the currently selected account (filtered\n * by the selector if provided).\n */\n getAccountsFromSelectedAccountGroup(\n selector?: AccountSelector<InternalAccount>,\n ) {\n const groupId = this.getSelectedAccountGroup();\n if (!groupId) {\n return [];\n }\n\n const group = this.getAccountGroupObject(groupId);\n // We should never reach this part, so we cannot cover it either.\n /* istanbul ignore next */\n if (!group) {\n return [];\n }\n\n const accounts: InternalAccount[] = [];\n for (const id of group.accounts) {\n const account = this.messenger.call('AccountsController:getAccount', id);\n\n // For now, we're filtering undefined account, but I believe\n // throwing would be more appropriate here.\n if (account) {\n accounts.push(account);\n }\n }\n\n return selector ? select(accounts, selector) : accounts;\n }\n\n /**\n * Gets an account from the currently selected account group, optionally\n * filtered by a CAIP-2 chain ID.\n *\n * This is the group-based replacement for both\n * `AccountsController:getSelectedAccount` and\n * `AccountsController:getSelectedMultichainAccount`.\n *\n * When no chain ID is provided, an account of the selected group is returned\n * using an EVM-priority rule: the first EVM account found in the group, or the\n * first account in the group if no EVM account is found. When a chain ID is\n * provided, the first account in the selected group whose scopes match the\n * given chain is returned.\n *\n * @param chainId - Optional CAIP-2 chain ID used to filter accounts by scope.\n * @returns The matching internal account from the selected group, or\n * undefined if no group is selected or no account matches.\n * @throws If `chainId` is provided but is not a valid CAIP-2 chain ID.\n */\n getAccountFromSelectedAccountGroup(\n chainId?: CaipChainId,\n ): InternalAccount | undefined {\n const groupId = this.getSelectedAccountGroup();\n if (!groupId) {\n return undefined;\n }\n\n if (!chainId) {\n return this.#getAccountFromAccountGroupId(groupId);\n }\n\n if (!isCaipChainId(chainId)) {\n throw new Error(`Invalid CAIP-2 chain ID: ${String(chainId)}`);\n }\n\n const accounts = this.getAccountsFromSelectedAccountGroup({\n scopes: [chainId],\n });\n\n return accounts[0];\n }\n\n /**\n * Gets the account group object from its ID.\n *\n * @param groupId - Account group ID.\n * @returns The account group object if found, undefined otherwise.\n */\n getAccountGroupObject(\n groupId: AccountGroupId,\n ): AccountGroupObject | undefined {\n const walletId = this.#groupIdToWalletId.get(groupId);\n if (!walletId) {\n return undefined;\n }\n\n const wallet = this.getAccountWalletObject(walletId);\n return wallet?.groups[groupId];\n }\n\n /**\n * Gets the account's context which contains its wallet ID, group ID, and sort order.\n *\n * @param accountId - Account ID.\n * @returns The account context if found, undefined otherwise.\n */\n getAccountContext(accountId: AccountId): AccountContext | undefined {\n return this.#accountIdToContext.get(accountId);\n }\n\n /**\n * Handles \"AccountsController:accountsAdded\" event to insert\n * new accounts into the tree in a single state update.\n *\n * @param accounts - New accounts.\n */\n #handleAccountsAdded(accounts: InternalAccount[]): void {\n // We wait for the first `init` to be called to actually build up the tree and\n // mutate it. We expect the caller to first update the `AccountsController` state\n // to force the migration of accounts, and then call `init`.\n if (!this.#initialized) {\n return;\n }\n\n // Filter out accounts already known by the tree to avoid double-insertion.\n const newAccounts = accounts.filter(\n (account) => !this.#accountIdToContext.has(account.id),\n );\n\n if (newAccounts.length === 0) {\n return;\n }\n\n const createdGroups = new Map<AccountGroupId, AccountWalletId>();\n const updatedGroups = new Map<AccountGroupId, AccountWalletId>();\n\n this.update((state) => {\n for (const account of newAccounts) {\n const { walletId, groupId, created } = this.#insert(\n state.accountTree.wallets,\n account,\n );\n\n if (created) {\n createdGroups.set(groupId, walletId);\n } else if (!createdGroups.has(groupId)) {\n // ^ We check that the group has not been created in this same batch before adding it to the `updatedGroups`\n // map, to avoid sending both created and updated events for the same group:\n // - Account 1 + Account 2 + Account 3\n // - Account 1 and 3 belong to the same group\n // - Account 1 will create the group\n // - Account 3 will update the group (but we only want to send a created event, not an updated one)\n updatedGroups.set(groupId, walletId);\n }\n\n const wallet = state.accountTree.wallets[walletId];\n if (wallet) {\n this.#applyAccountWalletMetadata(state, walletId);\n this.#applyAccountGroupMetadata(state, walletId, groupId);\n }\n }\n });\n\n this.messenger.publish(\n `${controllerName}:accountTreeChange`,\n this.state.accountTree,\n );\n\n for (const [groupId, walletId] of createdGroups) {\n this.#publishAccountGroupCreated(walletId, groupId);\n }\n for (const [groupId, walletId] of updatedGroups) {\n this.#publishAccountGroupUpdated(walletId, groupId);\n }\n }\n\n /**\n * Handles \"AccountsController:accountsRemoved\" event to remove\n * given accounts from the tree in a single state update.\n *\n * @param accountIds - Removed account IDs.\n */\n #handleAccountsRemoved(accountIds: AccountId[]): void {\n // We wait for the first `init` to be called to actually build up the tree and\n // mutate it. We expect the caller to first update the `AccountsController` state\n // to force the migration of accounts, and then call `init`.\n if (!this.#initialized) {\n return;\n }\n\n const knownAccounts: { id: AccountId; context: AccountContext }[] = [];\n for (const id of accountIds) {\n const context = this.#accountIdToContext.get(id);\n if (context) {\n knownAccounts.push({ id, context });\n }\n }\n\n if (knownAccounts.length === 0) {\n return;\n }\n\n const previousSelectedAccountGroup = this.state.selectedAccountGroup;\n const updatedGroups = new Map<AccountGroupId, AccountWalletId>();\n const removedGroups = new Set<AccountGroupId>();\n\n this.update((state) => {\n for (const { id: accountId, context } of knownAccounts) {\n const { walletId, groupId } = context;\n const accounts =\n state.accountTree.wallets[walletId]?.groups[groupId]?.accounts;\n\n if (accounts) {\n const index = accounts.indexOf(accountId);\n if (index !== -1) {\n accounts.splice(index, 1);\n\n if (\n state.selectedAccountGroup === groupId &&\n accounts.length === 0\n ) {\n state.selectedAccountGroup = this.#getDefaultAccountGroupId(\n state.accountTree.wallets,\n );\n }\n }\n if (accounts.length === 0) {\n this.#pruneEmptyGroupAndWallet(state, walletId, groupId);\n\n // If the group gets pruned, we should not consider it as updated.\n updatedGroups.delete(groupId);\n removedGroups.add(groupId);\n } else {\n updatedGroups.set(groupId, walletId);\n }\n }\n }\n });\n\n // Clear reverse-mappings after the state update\n for (const { id } of knownAccounts) {\n this.#accountIdToContext.delete(id);\n }\n\n this.messenger.publish(\n `${controllerName}:accountTreeChange`,\n this.state.accountTree,\n );\n\n for (const [groupId, walletId] of updatedGroups) {\n this.#publishAccountGroupUpdated(walletId, groupId);\n }\n for (const groupId of removedGroups) {\n this.#publishAccountGroupRemoved(groupId);\n }\n\n const newSelectedAccountGroup = this.state.selectedAccountGroup;\n if (newSelectedAccountGroup !== previousSelectedAccountGroup) {\n this.messenger.publish(\n `${controllerName}:selectedAccountGroupChange`,\n newSelectedAccountGroup,\n previousSelectedAccountGroup,\n );\n }\n }\n\n /**\n * Helper method to prune a group if it holds no accounts and additionally\n * prune the wallet if it holds no groups. This action should take place\n * after a singular account removal.\n *\n * NOTE: This method should only be used for a group that we know to be empty.\n *\n * @param state - The AccountTreeController state to prune.\n * @param walletId - The wallet ID to prune, the wallet should be the parent of the associated group that holds the removed account.\n * @param groupId - The group ID to prune, the group should be the parent of the associated account that was removed.\n * @returns The updated state.\n */\n #pruneEmptyGroupAndWallet(\n state: AccountTreeControllerState,\n walletId: AccountWalletId,\n groupId: AccountGroupId,\n ) {\n const { wallets } = state.accountTree;\n\n delete wallets[walletId].groups[groupId];\n this.#groupIdToWalletId.delete(groupId);\n\n // Clean up metadata for the pruned group\n delete state.accountGroupsMetadata[groupId];\n\n if (Object.keys(wallets[walletId].groups).length === 0) {\n delete wallets[walletId];\n // Clean up metadata for the pruned wallet\n delete state.accountWalletsMetadata[walletId];\n }\n return state;\n }\n\n /**\n * Publishes the `:accountGroupCreated` event for a newly added group.\n * No-op if the group is not in state (defensive).\n *\n * @param walletId - The parent wallet ID.\n * @param groupId - The newly created group's ID.\n */\n #publishAccountGroupCreated(\n walletId: AccountWalletId,\n groupId: AccountGroupId,\n ): void {\n const group = this.state.accountTree.wallets[walletId]?.groups[groupId];\n if (group) {\n this.messenger.publish(`${controllerName}:accountGroupCreated`, group);\n }\n }\n\n /**\n * Publishes the `:accountGroupUpdated` event for an existing group.\n * No-op if the group is not in state (e.g. it was pruned).\n *\n * @param walletId - The parent wallet ID.\n * @param groupId - The updated group's ID.\n */\n #publishAccountGroupUpdated(\n walletId: AccountWalletId,\n groupId: AccountGroupId,\n ): void {\n const group = this.state.accountTree.wallets[walletId]?.groups[groupId];\n if (group) {\n this.messenger.publish(`${controllerName}:accountGroupUpdated`, group);\n }\n }\n\n /**\n * Publishes the `:accountGroupRemoved` event for a pruned group.\n *\n * @param groupId - The removed group's ID.\n */\n #publishAccountGroupRemoved(groupId: AccountGroupId): void {\n this.messenger.publish(`${controllerName}:accountGroupRemoved`, groupId);\n }\n\n /**\n * Insert an account inside an account tree.\n *\n * We go over multiple rules to try to \"match\" the account following\n * specific criterias. If a rule \"matches\" an account, then this\n * account get added into its proper account wallet and account group.\n *\n * @param wallets - Account tree.\n * @param account - The account to be inserted.\n * @returns The wallet ID, group ID, and whether the group has been created or not.\n */\n #insert(\n wallets: AccountTreeControllerState['accountTree']['wallets'],\n account: InternalAccount,\n ): { walletId: AccountWalletId; groupId: AccountGroupId; created: boolean } {\n const result =\n this.#getEntropyRule().match(account) ??\n this.#getSnapRule().match(account) ??\n this.#getKeyringRule().match(account); // This one cannot fail.\n\n // Update controller's state.\n const walletId = result.wallet.id;\n let wallet = wallets[walletId];\n if (!wallet) {\n log(`[${walletId}] Added as new wallet`);\n wallets[walletId] = {\n ...result.wallet,\n status: 'ready',\n groups: {},\n metadata: {\n name: '', // Will get updated later.\n ...result.wallet.metadata,\n },\n // We do need to type-cast since we're not narrowing `result` with\n // the union tag `result.wallet.type`.\n } as AccountWalletObject;\n wallet = wallets[walletId];\n\n // Trigger atomic sync for new wallet (only for entropy wallets)\n if (wallet.type === AccountWalletType.Entropy) {\n this.#backupAndSyncService.enqueueSingleWalletSync(walletId);\n }\n }\n\n const groupId = result.group.id;\n let group = wallet.groups[groupId];\n const { type, id } = account;\n const sortOrder = ACCOUNT_TYPE_TO_SORT_ORDER[type];\n const created = !group;\n\n if (!group) {\n log(`[${walletId}] Add new group: [${groupId}]`);\n wallet.groups[groupId] = {\n ...result.group,\n // Type-wise, we are guaranteed to always have at least 1 account.\n accounts: [id],\n metadata: {\n name: '',\n ...{ pinned: false, hidden: false, lastSelected: 0 }, // Default UI states\n ...result.group.metadata, // Allow rules to override defaults\n },\n // We do need to type-cast since we're not narrowing `result` with\n // the union tag `result.group.type`.\n } as AccountGroupObject;\n group = wallet.groups[groupId];\n\n // Map group ID to its containing wallet ID for efficient direct access\n this.#groupIdToWalletId.set(groupId, walletId);\n\n // Trigger atomic sync for new group (only for entropy wallets)\n if (wallet.type === AccountWalletType.Entropy) {\n this.#backupAndSyncService.enqueueSingleGroupSync(groupId);\n }\n } else {\n group.accounts.push(id);\n // We need to do this at every insertion because race conditions can happen\n // during the account creation process where one provider completes before the other.\n // The discovery process in the service can also lead to some accounts being created \"out of order\".\n const { accounts } = group;\n accounts.sort(\n /* istanbul ignore next: Comparator branch execution (a===id vs b===id)\n * and return attribution vary across engines; final ordering is covered\n * by behavior tests. Ignoring the entire comparator avoids flaky line\n * coverage without reducing scenario coverage.\n */\n (a, b) => {\n const aSortOrder =\n a === id ? sortOrder : this.#accountIdToContext.get(a)?.sortOrder;\n const bSortOrder =\n b === id ? sortOrder : this.#accountIdToContext.get(b)?.sortOrder;\n return (\n (aSortOrder ?? MAX_SORT_ORDER) - (bSortOrder ?? MAX_SORT_ORDER)\n );\n },\n );\n }\n log(\n `[${groupId}] Add new account: { id: \"${account.id}\", type: \"${account.type}\", address: \"${account.address}\"`,\n );\n\n // Update the reverse mapping for this account.\n this.#accountIdToContext.set(account.id, {\n walletId: wallet.id,\n groupId: group.id,\n sortOrder,\n });\n\n return { walletId: wallet.id, groupId: group.id, created };\n }\n\n /**\n * List all internal accounts.\n *\n * @returns The list of all internal accounts.\n */\n #listAccounts(): InternalAccount[] {\n return this.messenger.call('AccountsController:listMultichainAccounts');\n }\n\n /**\n * Asserts that a group exists in the current account tree.\n *\n * @param groupId - The account group ID to validate.\n * @throws Error if the group does not exist.\n */\n #assertAccountGroupExists(groupId: AccountGroupId): void {\n const exists = this.#groupIdToWalletId.has(groupId);\n if (!exists) {\n throw new Error('Account group not found in tree');\n }\n }\n\n /**\n * Asserts that a wallet exists in the current account tree.\n *\n * @param walletId - The account wallet ID to validate.\n * @throws Error if the wallet does not exist.\n */\n #assertAccountWalletExists(walletId: AccountWalletId): void {\n const exists = Boolean(this.state.accountTree.wallets[walletId]);\n if (!exists) {\n throw new Error('Account wallet not found in tree');\n }\n }\n\n /**\n * Asserts that an account group name is unique within the same wallet.\n *\n * @param groupId - The account group ID to exclude from the check.\n * @param name - The name to validate for uniqueness.\n * @throws Error if the name already exists in another group within the same wallet.\n */\n #assertAccountGroupNameIsUnique(groupId: AccountGroupId, name: string): void {\n if (!isAccountGroupNameUnique(this.state, groupId, name)) {\n throw new Error('Account group name already exists');\n }\n }\n\n /**\n * Gets the currently selected account group ID.\n *\n * @returns The selected account group ID or empty string if none selected.\n */\n getSelectedAccountGroup(): AccountGroupId | '' {\n return this.state.selectedAccountGroup;\n }\n\n /**\n * Sets the selected account group and updates the AccountsController selectedAccount accordingly.\n *\n * @param groupId - The account group ID to select.\n * @param forwardSelectedAccount - Whether to forward the selected account to AccountsController. Defaults to true.\n */\n #setSelectedAccountGroup(\n groupId: AccountGroupId,\n forwardSelectedAccount: boolean = true,\n ): void {\n const previousSelectedAccountGroup = this.state.selectedAccountGroup;\n\n // Idempotent check - if the same group is already selected, do nothing\n if (previousSelectedAccountGroup === groupId) {\n return;\n }\n\n // Find the first account in this group to select\n const accountToSelect = this.#getAccountFromAccountGroupId(groupId);\n if (!accountToSelect) {\n throw new Error('No accounts found in group');\n }\n\n this.update((state) => {\n // Update our selected account group first.\n state.selectedAccountGroup = groupId;\n\n // Then update its associated metadata (lastSelected timestamp) to keep\n // track of the most recently selected groups.\n const now = Date.now();\n\n /* istanbul ignore next */\n if (!state.accountGroupsMetadata[groupId]) {\n state.accountGroupsMetadata[groupId] = {};\n }\n state.accountGroupsMetadata[groupId].lastSelected = now;\n\n const walletId = this.#groupIdToWalletId.get(groupId);\n if (walletId) {\n state.accountTree.wallets[walletId].groups[\n groupId\n ].metadata.lastSelected = now;\n }\n });\n\n log(`Selected group is now: [${this.state.selectedAccountGroup}]`);\n\n this.messenger.publish(\n `${controllerName}:selectedAccountGroupChange`,\n groupId,\n previousSelectedAccountGroup,\n );\n\n if (forwardSelectedAccount) {\n // Update AccountsController - this will trigger selectedAccountChange event,\n // but our handler is idempotent so it won't cause infinite loop\n this.messenger.call(\n 'AccountsController:setSelectedAccount',\n accountToSelect.id,\n );\n\n log(`Selected account is now: ${accountToSelect.id}`);\n }\n }\n\n /**\n * Sets the selected account group and updates the AccountsController selectedAccount accordingly.\n *\n * @param groupId - The account group ID to select.\n */\n setSelectedAccountGroup(groupId: AccountGroupId): void {\n this.#setSelectedAccountGroup(groupId);\n }\n\n /**\n * Sets the selected account group and updates the AccountsController selectedAccount accordingly.\n *\n * @param accountId - The account ID to select the group for.\n */\n setSelectedAccountGroupByAccountId(accountId: AccountId): void {\n const context = this.#accountIdToContext.get(accountId);\n if (!context) {\n throw new Error('Account not found in the account tree');\n }\n this.setSelectedAccountGroup(context.groupId);\n }\n\n /**\n * Initializes the selectedAccountGroup based on the currently selected account from AccountsController.\n *\n * @param wallets - Wallets object to use for fallback logic\n * @returns The default selected account group ID or empty string if none selected.\n */\n #getDefaultSelectedAccountGroup(wallets: {\n [walletId: AccountWalletId]: AccountWalletObject;\n }): AccountGroupId | '' {\n const selectedAccount = this.messenger.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n if (selectedAccount?.id) {\n const accountMapping = this.#accountIdToContext.get(selectedAccount.id);\n if (accountMapping) {\n const { groupId } = accountMapping;\n\n return groupId;\n }\n }\n\n // Default to the default group in case of errors.\n return this.#getDefaultAccountGroupId(wallets);\n }\n\n /**\n * Handles selected account change from AccountsController.\n * Updates selectedAccountGroup to match the selected account.\n *\n * @param account - The newly selected account.\n */\n #handleSelectedAccountChange(account: InternalAccount): void {\n const accountMapping = this.#accountIdToContext.get(account.id);\n if (!accountMapping) {\n // Account not in tree yet, might be during initialization\n return;\n }\n\n const { groupId } = accountMapping;\n\n // Avoid infinite loop since this method is triggered by selected account change.\n const forwardSelectedAccount = false;\n this.#setSelectedAccountGroup(groupId, forwardSelectedAccount);\n }\n\n /**\n * Handles multichain account wallet status change from\n * the MultichainAccountService.\n *\n * @param walletId - Multichain account wallet ID.\n * @param walletStatus - New multichain account wallet status.\n */\n #handleMultichainAccountWalletStatusChange(\n walletId: MultichainAccountWalletId,\n walletStatus: MultichainAccountWalletStatus,\n ): void {\n this.update((state) => {\n const wallet = state.accountTree.wallets[walletId];\n\n if (wallet) {\n wallet.status = walletStatus;\n }\n });\n }\n\n /**\n * Gets account group object.\n *\n * @param groupId - The account group ID.\n * @returns The account group or undefined if not found.\n */\n #getAccountGroup(groupId: AccountGroupId): AccountGroupObject | undefined {\n const found = Object.values(this.state.accountTree.wallets).find(\n (wallet) => wallet.groups[groupId] !== undefined,\n );\n\n return found?.groups[groupId];\n }\n\n /**\n * Gets an account for the specified group using the EVM-priority rule.\n *\n * The account is the first EVM account found in the group, or the first\n * account in the group if no EVM account is found.\n *\n * @param groupId - The account group ID.\n * @returns The internal account in the group, or undefined if the group does\n * not exist or is empty.\n */\n #getAccountFromAccountGroupId(\n groupId: AccountGroupId,\n ): InternalAccount | undefined {\n const group = this.#getAccountGroup(groupId);\n\n if (group) {\n let candidateId: AccountId | undefined;\n for (const id of group.accounts) {\n const account = this.messenger.call(\n 'AccountsController:getAccount',\n id,\n );\n\n if (account) {\n candidateId ??= id;\n\n if (isEvmAccountType(account.type)) {\n // EVM accounts have a higher priority, so if we find any, we just\n // use that account!\n return account;\n }\n }\n }\n\n return candidateId\n ? this.messenger.call('AccountsController:getAccount', candidateId)\n : undefined;\n }\n\n return undefined;\n }\n\n /**\n * Gets the default group id by selecting the most recently selected non-empty group.\n * Groups that have never been explicitly selected (lastSelected === 0) are still\n * considered as fallbacks. When timestamps are equal, groups containing EVM accounts\n * are preferred as a tiebreaker.\n *\n * @param wallets - The wallets object to search.\n * @returns The ID of the most recently selected non-empty group, or an empty string if none found.\n */\n #getDefaultAccountGroupId(wallets: {\n [walletId: AccountWalletId]: AccountWalletObject;\n }): AccountGroupId | '' {\n let candidate: AccountGroupObject | undefined;\n\n for (const wallet of Object.values(wallets)) {\n for (const group of Object.values(wallet.groups)) {\n if (group.accounts.length === 0) {\n continue;\n }\n if (!candidate) {\n candidate = group;\n continue;\n }\n if (group.metadata.lastSelected > candidate.metadata.lastSelected) {\n candidate = group;\n } else if (\n group.metadata.lastSelected === candidate.metadata.lastSelected &&\n this.#hasEvmAccount(group) &&\n !this.#hasEvmAccount(candidate)\n ) {\n candidate = group;\n }\n }\n }\n return candidate?.id ?? '';\n }\n\n /**\n * Checks if a group contains at least one EVM account.\n *\n * @param group - The account group to check.\n * @returns True if the group contains an EVM account, false otherwise.\n */\n #hasEvmAccount(group: AccountGroupObject): boolean {\n for (const id of group.accounts) {\n const account = this.messenger.call('AccountsController:getAccount', id);\n if (account && isEvmAccountType(account.type)) {\n return true;\n }\n }\n return false;\n }\n\n /**\n * Resolves name conflicts by adding a suffix to make the name unique.\n *\n * @internal\n * @param wallet - The wallet to check within.\n * @param groupId - The account group ID to exclude from the check.\n * @param name - The desired name that has a conflict.\n * @returns A unique name with suffix added if necessary.\n */\n #resolveNameConflict(\n wallet: AccountWalletObject,\n groupId: AccountGroupId,\n name: string,\n ): string {\n let suffix = 2;\n let candidateName = `${name} (${suffix})`;\n\n // Keep incrementing suffix until we find a unique name\n while (\n !isAccountGroupNameUniqueFromWallet(wallet, groupId, candidateName)\n ) {\n suffix += 1;\n candidateName = `${name} (${suffix})`;\n }\n\n return candidateName;\n }\n\n /**\n * Sets a custom name for an account group.\n *\n * @param groupId - The account group ID.\n * @param name - The custom name to set.\n * @param autoHandleConflict - If true, automatically resolves name conflicts by adding a suffix. If false, throws on conflicts.\n * @throws If the account group ID is not found in the current tree.\n * @throws If the account group name already exists and autoHandleConflict is false.\n */\n setAccountGroupName(\n groupId: AccountGroupId,\n name: string,\n autoHandleConflict: boolean = false,\n ): void {\n // Validate that the group exists in the current tree\n this.#assertAccountGroupExists(groupId);\n\n const walletId = this.#groupIdToWalletId.get(groupId);\n assert(walletId, 'Account group not found in tree');\n\n const wallet = this.state.accountTree.wallets[walletId];\n let finalName = name;\n\n // Handle name conflicts based on the autoHandleConflict flag\n if (\n autoHandleConflict &&\n !isAccountGroupNameUniqueFromWallet(wallet, groupId, name)\n ) {\n finalName = this.#resolveNameConflict(wallet, groupId, name);\n } else {\n // Validate that the name is unique\n this.#assertAccountGroupNameIsUnique(groupId, finalName);\n }\n\n log(\n `[${groupId}] Set new name to: \"${finalName}\" (auto handle conflict: ${autoHandleConflict})`,\n );\n\n this.update((state) => {\n /* istanbul ignore next */\n if (!state.accountGroupsMetadata[groupId]) {\n state.accountGroupsMetadata[groupId] = {};\n }\n\n // Update persistent metadata\n state.accountGroupsMetadata[groupId].name = {\n value: finalName,\n lastUpdatedAt: Date.now(),\n };\n\n // Update tree node directly using efficient mapping\n state.accountTree.wallets[walletId].groups[groupId].metadata.name =\n finalName;\n });\n\n this.#publishAccountGroupUpdated(walletId, groupId);\n\n // Trigger atomic sync for group rename (only for groups from entropy wallets)\n if (wallet.type === AccountWalletType.Entropy) {\n this.#backupAndSyncService.enqueueSingleGroupSync(groupId);\n }\n }\n\n /**\n * Sets a custom name for an account wallet.\n *\n * @param walletId - The account wallet ID.\n * @param name - The custom name to set.\n * @throws If the account wallet ID is not found in the current tree.\n */\n setAccountWalletName(walletId: AccountWalletId, name: string): void {\n // Validate that the wallet exists in the current tree\n this.#assertAccountWalletExists(walletId);\n\n this.update((state) => {\n // Update persistent metadata\n state.accountWalletsMetadata[walletId] ??= {};\n state.accountWalletsMetadata[walletId].name = {\n value: name,\n lastUpdatedAt: Date.now(),\n };\n\n // Update tree node directly\n state.accountTree.wallets[walletId].metadata.name = name;\n });\n\n // Trigger atomic sync for wallet rename (only for groups from entropy wallets)\n if (\n this.state.accountTree.wallets[walletId].type ===\n AccountWalletType.Entropy\n ) {\n this.#backupAndSyncService.enqueueSingleWalletSync(walletId);\n }\n }\n\n /**\n * Toggles the pinned state of an account group.\n *\n * @param groupId - The account group ID.\n * @param pinned - Whether the group should be pinned.\n * @throws If the account group ID is not found in the current tree.\n */\n setAccountGroupPinned(groupId: AccountGroupId, pinned: boolean): void {\n // Validate that the group exists in the current tree\n this.#assertAccountGroupExists(groupId);\n\n const walletId = this.#groupIdToWalletId.get(groupId);\n\n this.update((state) => {\n /* istanbul ignore next */\n if (!state.accountGroupsMetadata[groupId]) {\n state.accountGroupsMetadata[groupId] = {};\n }\n\n // Update persistent metadata\n state.accountGroupsMetadata[groupId].pinned = {\n value: pinned,\n lastUpdatedAt: Date.now(),\n };\n\n // Update tree node directly using efficient mapping\n if (walletId) {\n state.accountTree.wallets[walletId].groups[groupId].metadata.pinned =\n pinned;\n }\n });\n\n if (walletId) {\n this.#publishAccountGroupUpdated(walletId, groupId);\n }\n\n // Trigger atomic sync for group pinning (only for groups from entropy wallets)\n if (\n walletId &&\n this.state.accountTree.wallets[walletId].type ===\n AccountWalletType.Entropy\n ) {\n this.#backupAndSyncService.enqueueSingleGroupSync(groupId);\n }\n }\n\n /**\n * Toggles the hidden state of an account group.\n *\n * @param groupId - The account group ID.\n * @param hidden - Whether the group should be hidden.\n * @throws If the account group ID is not found in the current tree.\n */\n setAccountGroupHidden(groupId: AccountGroupId, hidden: boolean): void {\n // Validate that the group exists in the current tree\n this.#assertAccountGroupExists(groupId);\n\n const walletId = this.#groupIdToWalletId.get(groupId);\n\n this.update((state) => {\n /* istanbul ignore next */\n if (!state.accountGroupsMetadata[groupId]) {\n state.accountGroupsMetadata[groupId] = {};\n }\n\n // Update persistent metadata\n state.accountGroupsMetadata[groupId].hidden = {\n value: hidden,\n lastUpdatedAt: Date.now(),\n };\n\n // Update tree node directly using efficient mapping\n if (walletId) {\n state.accountTree.wallets[walletId].groups[groupId].metadata.hidden =\n hidden;\n }\n });\n\n if (walletId) {\n this.#publishAccountGroupUpdated(walletId, groupId);\n }\n\n // Trigger atomic sync for group hiding (only for groups from entropy wallets)\n if (\n walletId &&\n this.state.accountTree.wallets[walletId].type ===\n AccountWalletType.Entropy\n ) {\n this.#backupAndSyncService.enqueueSingleGroupSync(groupId);\n }\n }\n\n /**\n * Clears the controller state and resets to default values.\n * Also clears the backup and sync service state.\n */\n clearState(): void {\n log('Clearing state');\n\n const previousSelectedAccountGroup = this.state.selectedAccountGroup;\n\n this.update(() => {\n return {\n ...getDefaultAccountTreeControllerState(),\n };\n });\n this.#backupAndSyncService.clearState();\n\n // Clear in-memory reverse-lookup Maps so stale data is not accessible\n // between this call and the next init().\n this.#accountIdToContext.clear();\n this.#groupIdToWalletId.clear();\n\n // Notify subscribers that the selected group has been cleared,\n // mirroring what #setSelectedAccountGroup does on normal transitions.\n this.messenger.publish(\n `${controllerName}:selectedAccountGroupChange`,\n '',\n previousSelectedAccountGroup,\n );\n\n // So we know we have to call `init` again.\n this.#initialized = false;\n this.messenger.publish(`${controllerName}:uninitialized`);\n }\n\n /**\n * Bi-directionally syncs the account tree with user storage.\n * This will perform a full sync, including both pulling updates\n * from user storage and pushing local changes to user storage.\n * This also performs legacy account syncing if needed.\n *\n * IMPORTANT:\n * If a full sync is already in progress, it will return the ongoing promise.\n *\n * @returns A promise that resolves when the sync is complete.\n */\n async syncWithUserStorage(): Promise<void> {\n return this.#backupAndSyncService.performFullSync();\n }\n\n /**\n * Bi-directionally syncs the account tree with user storage.\n * This will ensure at least one full sync is ran, including both pulling updates\n * from user storage and pushing local changes to user storage.\n * This also performs legacy account syncing if needed.\n *\n * IMPORTANT:\n * If the first ever full sync is already in progress, it will return the ongoing promise.\n * If the first ever full sync was previously completed, it will NOT start a new sync, and will resolve immediately.\n *\n * @returns A promise that resolves when the first ever full sync is complete.\n */\n async syncWithUserStorageAtLeastOnce(): Promise<void> {\n return this.#backupAndSyncService.performFullSyncAtLeastOnce();\n }\n\n /**\n * Produces a versioned snapshot of the current wallet and group state.\n *\n * When `options.includeSecrets` is `true`, `options.password` is required\n * and verified against the vault before any secret is read. Without\n * `includeSecrets`, only metadata (names, pinned, hidden) is exported and\n * no password is needed.\n *\n * @param options - Export options.\n * @returns A promise resolving to an `AccountTreeSnapshot`.\n * @throws If the vault is locked or the password is incorrect.\n */\n async exportState(\n options?: ExportStateOptions,\n ): Promise<AccountTreeSnapshot> {\n return exportState(\n { getState: () => this.state, messenger: this.messenger },\n options,\n );\n }\n\n /**\n * Applies a validated snapshot to the current state.\n *\n * Accepts an {@link AccountTreeSnapshot} only — untrusted wire data must be\n * parsed with {@link AccountTreeSnapshot.deserialize} first. Callers may\n * filter the snapshot with {@link AccountTreeSnapshot.filterWallets},\n * {@link AccountTreeSnapshot.filterGroups}, or\n * {@link AccountTreeSnapshot.filterAllGroups} before importing.\n *\n * New mnemonic wallets are imported via `MultichainAccountService` and new\n * private-key accounts via `KeyringController`. Metadata (name, pinned,\n * hidden) is applied to all existing and newly created wallets / groups.\n *\n * @param snapshot - The validated snapshot to import.\n * @returns A promise that resolves when the import is complete.\n */\n async importState(snapshot: AccountTreeSnapshot): Promise<void> {\n return importState(\n {\n getState: () => this.state,\n messenger: this.messenger,\n setWalletName: (id, name) => this.setAccountWalletName(id, name),\n setAccountGroupName: (id, name) =>\n this.setAccountGroupName(id, name, true),\n setAccountGroupPinned: (id, pinned) =>\n this.setAccountGroupPinned(id, pinned),\n setAccountGroupHidden: (id, hidden) =>\n this.setAccountGroupHidden(id, hidden),\n },\n snapshot,\n );\n }\n\n /**\n * Creates an backup and sync context for sync operations.\n * Used by the backup and sync service.\n *\n * @returns The backup and sync context.\n */\n #createBackupAndSyncContext(): BackupAndSyncContext {\n return {\n ...this.#backupAndSyncConfig,\n controller: this,\n messenger: this.messenger,\n controllerStateUpdateFn: this.update.bind(this),\n traceFn: this.#trace.bind(this),\n groupIdToWalletId: this.#groupIdToWalletId,\n mutationTracker: createSyncMutationTracker(),\n };\n }\n}\n"]}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AccountId } from '@metamask/accounts-controller';
|
|
2
|
+
export { toErrorMessage } from './backup-and-sync/utils/errors.js';
|
|
3
|
+
export type RemoveAccountWalletFailure = {
|
|
4
|
+
id?: AccountId;
|
|
5
|
+
error: unknown;
|
|
6
|
+
};
|
|
7
|
+
export type RemoveAccountWalletFailureContext = {
|
|
8
|
+
failures: {
|
|
9
|
+
id?: string;
|
|
10
|
+
error: string;
|
|
11
|
+
}[];
|
|
12
|
+
};
|
|
13
|
+
export declare function reportRemoveAccountWalletError(messenger: {
|
|
14
|
+
captureException?: (error: Error) => void;
|
|
15
|
+
}, message: string, error: Error, failures: RemoveAccountWalletFailure[]): void;
|
|
16
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAK/D,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAEnE,MAAM,MAAM,0BAA0B,GAAG;IACvC,EAAE,CAAC,EAAE,SAAS,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG;IAC9C,QAAQ,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC5C,CAAC;AAEF,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE;IAAE,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CAAE,EACxD,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,0BAA0B,EAAE,GACrC,IAAI,CAcN"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { toErrorMessage } from './backup-and-sync/utils/errors.js';
|
|
2
|
+
import { projectLogger as log } from './logger.js';
|
|
3
|
+
export { toErrorMessage } from './backup-and-sync/utils/errors.js';
|
|
4
|
+
export function reportRemoveAccountWalletError(messenger, message, error, failures) {
|
|
5
|
+
const context = {
|
|
6
|
+
failures: failures.map((failure) => ({
|
|
7
|
+
...(failure.id !== undefined && { id: failure.id }),
|
|
8
|
+
error: toErrorMessage(failure.error),
|
|
9
|
+
})),
|
|
10
|
+
};
|
|
11
|
+
log('ERROR --', message, context);
|
|
12
|
+
console.error(message, { error, context });
|
|
13
|
+
const sentryError = Object.assign(new Error(message, { cause: error }), {
|
|
14
|
+
context,
|
|
15
|
+
});
|
|
16
|
+
messenger.captureException?.(sentryError);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,aAAa,IAAI,GAAG,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAWnE,MAAM,UAAU,8BAA8B,CAC5C,SAAwD,EACxD,OAAe,EACf,KAAY,EACZ,QAAsC;IAEtC,MAAM,OAAO,GAAsC;QACjD,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACnC,GAAG,CAAC,OAAO,CAAC,EAAE,KAAK,SAAS,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC;YACnD,KAAK,EAAE,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC;SACrC,CAAC,CAAC;KACJ,CAAC;IAEF,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAClC,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3C,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE;QACtE,OAAO;KACR,CAAC,CAAC;IACH,SAAS,CAAC,gBAAgB,EAAE,CAAC,WAAW,CAAC,CAAC;AAC5C,CAAC","sourcesContent":["import type { AccountId } from '@metamask/accounts-controller';\n\nimport { toErrorMessage } from './backup-and-sync/utils/errors.js';\nimport { projectLogger as log } from './logger.js';\n\nexport { toErrorMessage } from './backup-and-sync/utils/errors.js';\n\nexport type RemoveAccountWalletFailure = {\n id?: AccountId;\n error: unknown;\n};\n\nexport type RemoveAccountWalletFailureContext = {\n failures: { id?: string; error: string }[];\n};\n\nexport function reportRemoveAccountWalletError(\n messenger: { captureException?: (error: Error) => void },\n message: string,\n error: Error,\n failures: RemoveAccountWalletFailure[],\n): void {\n const context: RemoveAccountWalletFailureContext = {\n failures: failures.map((failure) => ({\n ...(failure.id !== undefined && { id: failure.id }),\n error: toErrorMessage(failure.error),\n })),\n };\n\n log('ERROR --', message, context);\n console.error(message, { error, context });\n const sentryError = Object.assign(new Error(message, { cause: error }), {\n context,\n });\n messenger.captureException?.(sentryError);\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { USER_STORAGE_GROUPS_FEATURE_KEY, USER_STORAGE_WALLETS_FEATURE_KEY, } fr
|
|
|
5
5
|
export type { AccountTreeControllerState, AccountTreeControllerGetStateAction, AccountTreeControllerActions, AccountTreeControllerStateChangeEvent, AccountTreeControllerAccountTreeChangeEvent, AccountTreeControllerSelectedAccountGroupChangeEvent, AccountTreeControllerAccountGroupCreatedEvent, AccountTreeControllerAccountGroupUpdatedEvent, AccountTreeControllerAccountGroupRemovedEvent, AccountTreeControllerInitializedEvent, AccountTreeControllerUninitializedEvent, AccountTreeControllerEvents, AccountTreeControllerMessenger, } from './types.js';
|
|
6
6
|
export type { AccountTreeControllerGetAccountWalletObjectAction, AccountTreeControllerGetAccountWalletObjectsAction, AccountTreeControllerGetAccountsFromSelectedAccountGroupAction, AccountTreeControllerGetAccountFromSelectedAccountGroupAction, AccountTreeControllerGetAccountGroupObjectAction, AccountTreeControllerGetAccountContextAction, AccountTreeControllerGetSelectedAccountGroupAction, AccountTreeControllerSetSelectedAccountGroupAction, AccountTreeControllerSetSelectedAccountGroupByAccountIdAction, AccountTreeControllerSetAccountGroupNameAction, AccountTreeControllerSetAccountWalletNameAction, AccountTreeControllerSetAccountGroupPinnedAction, AccountTreeControllerSetAccountGroupHiddenAction, AccountTreeControllerClearStateAction, AccountTreeControllerSyncWithUserStorageAction, AccountTreeControllerSyncWithUserStorageAtLeastOnceAction, AccountTreeControllerInitAction, AccountTreeControllerIsInitializedAction, AccountTreeControllerReinitAction, AccountTreeControllerExportStateAction, AccountTreeControllerImportStateAction, } from './AccountTreeController-method-action-types.js';
|
|
7
7
|
export type { AccountContext } from './AccountTreeController.js';
|
|
8
|
+
export type { RemoveAccountWalletFailure, RemoveAccountWalletFailureContext, } from './errors.js';
|
|
8
9
|
export { AccountTreeController, getDefaultAccountTreeControllerState, } from './AccountTreeController.js';
|
|
9
10
|
export type { AccountTreePayload, AccountTreePayloadStructType, AccountWalletMnemonicPayload, AccountWalletPrivateKeyPayload, AccountWalletMnemonicGroupEntry, AccountWalletPrivateKeyGroupEntry, AccountWalletPayloadId, AccountGroupPayloadId, AccountTreeSnapshotWallet, AccountTreeSnapshotGroup, ExportStateOptions, } from './state/payload.js';
|
|
10
11
|
export { AccountWalletPayloadType, AccountWalletPrivateKeyEncoding, AccountTreePayloadStruct, assertAccountTreePayload, } from './state/payload.js';
|
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,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,EACL,+BAA+B,EAC/B,gCAAgC,GACjC,MAAM,6CAA6C,CAAC;AAErD,YAAY,EACV,0BAA0B,EAC1B,mCAAmC,EACnC,4BAA4B,EAC5B,qCAAqC,EACrC,2CAA2C,EAC3C,oDAAoD,EACpD,6CAA6C,EAC7C,6CAA6C,EAC7C,6CAA6C,EAC7C,qCAAqC,EACrC,uCAAuC,EACvC,2BAA2B,EAC3B,8BAA8B,GAC/B,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,iDAAiD,EACjD,kDAAkD,EAClD,8DAA8D,EAC9D,6DAA6D,EAC7D,gDAAgD,EAChD,4CAA4C,EAC5C,kDAAkD,EAClD,kDAAkD,EAClD,6DAA6D,EAC7D,8CAA8C,EAC9C,+CAA+C,EAC/C,gDAAgD,EAChD,gDAAgD,EAChD,qCAAqC,EACrC,8CAA8C,EAC9C,yDAAyD,EACzD,+BAA+B,EAC/B,wCAAwC,EACxC,iCAAiC,EACjC,sCAAsC,EACtC,sCAAsC,GACvC,MAAM,gDAAgD,CAAC;AAExD,YAAY,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACvD,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,EACL,+BAA+B,EAC/B,gCAAgC,GACjC,MAAM,6CAA6C,CAAC;AAErD,YAAY,EACV,0BAA0B,EAC1B,mCAAmC,EACnC,4BAA4B,EAC5B,qCAAqC,EACrC,2CAA2C,EAC3C,oDAAoD,EACpD,6CAA6C,EAC7C,6CAA6C,EAC7C,6CAA6C,EAC7C,qCAAqC,EACrC,uCAAuC,EACvC,2BAA2B,EAC3B,8BAA8B,GAC/B,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,iDAAiD,EACjD,kDAAkD,EAClD,8DAA8D,EAC9D,6DAA6D,EAC7D,gDAAgD,EAChD,4CAA4C,EAC5C,kDAAkD,EAClD,kDAAkD,EAClD,6DAA6D,EAC7D,8CAA8C,EAC9C,+CAA+C,EAC/C,gDAAgD,EAChD,gDAAgD,EAChD,qCAAqC,EACrC,8CAA8C,EAC9C,yDAAyD,EACzD,+BAA+B,EAC/B,wCAAwC,EACxC,iCAAiC,EACjC,sCAAsC,EACtC,sCAAsC,GACvC,MAAM,gDAAgD,CAAC;AAExD,YAAY,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,YAAY,EACV,0BAA0B,EAC1B,iCAAiC,GAClC,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,qBAAqB,EACrB,oCAAoC,GACrC,MAAM,4BAA4B,CAAC;AAEpC,YAAY,EACV,kBAAkB,EAClB,4BAA4B,EAC5B,4BAA4B,EAC5B,8BAA8B,EAC9B,+BAA+B,EAC/B,iCAAiC,EACjC,sBAAsB,EACtB,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,wBAAwB,EACxB,+BAA+B,EAC/B,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,EACL,+BAA+B,EAC/B,gCAAgC,GACjC,MAAM,6CAA6C,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,EACL,+BAA+B,EAC/B,gCAAgC,GACjC,MAAM,6CAA6C,CAAC;AAgDrD,OAAO,EACL,qBAAqB,EACrB,oCAAoC,GACrC,MAAM,4BAA4B,CAAC;AAgBpC,OAAO,EACL,wBAAwB,EACxB,+BAA+B,EAC/B,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC","sourcesContent":["export type { AccountWalletObject } from './wallet.js';\nexport type { AccountGroupObject } from './group.js';\nexport { isAccountGroupNameUnique } from './group.js';\n\nexport {\n USER_STORAGE_GROUPS_FEATURE_KEY,\n USER_STORAGE_WALLETS_FEATURE_KEY,\n} from './backup-and-sync/user-storage/constants.js';\n\nexport type {\n AccountTreeControllerState,\n AccountTreeControllerGetStateAction,\n AccountTreeControllerActions,\n AccountTreeControllerStateChangeEvent,\n AccountTreeControllerAccountTreeChangeEvent,\n AccountTreeControllerSelectedAccountGroupChangeEvent,\n AccountTreeControllerAccountGroupCreatedEvent,\n AccountTreeControllerAccountGroupUpdatedEvent,\n AccountTreeControllerAccountGroupRemovedEvent,\n AccountTreeControllerInitializedEvent,\n AccountTreeControllerUninitializedEvent,\n AccountTreeControllerEvents,\n AccountTreeControllerMessenger,\n} from './types.js';\n\nexport type {\n AccountTreeControllerGetAccountWalletObjectAction,\n AccountTreeControllerGetAccountWalletObjectsAction,\n AccountTreeControllerGetAccountsFromSelectedAccountGroupAction,\n AccountTreeControllerGetAccountFromSelectedAccountGroupAction,\n AccountTreeControllerGetAccountGroupObjectAction,\n AccountTreeControllerGetAccountContextAction,\n AccountTreeControllerGetSelectedAccountGroupAction,\n AccountTreeControllerSetSelectedAccountGroupAction,\n AccountTreeControllerSetSelectedAccountGroupByAccountIdAction,\n AccountTreeControllerSetAccountGroupNameAction,\n AccountTreeControllerSetAccountWalletNameAction,\n AccountTreeControllerSetAccountGroupPinnedAction,\n AccountTreeControllerSetAccountGroupHiddenAction,\n AccountTreeControllerClearStateAction,\n AccountTreeControllerSyncWithUserStorageAction,\n AccountTreeControllerSyncWithUserStorageAtLeastOnceAction,\n AccountTreeControllerInitAction,\n AccountTreeControllerIsInitializedAction,\n AccountTreeControllerReinitAction,\n AccountTreeControllerExportStateAction,\n AccountTreeControllerImportStateAction,\n} from './AccountTreeController-method-action-types.js';\n\nexport type { AccountContext } from './AccountTreeController.js';\nexport type {\n RemoveAccountWalletFailure,\n RemoveAccountWalletFailureContext,\n} from './errors.js';\n\nexport {\n AccountTreeController,\n getDefaultAccountTreeControllerState,\n} from './AccountTreeController.js';\n\nexport type {\n AccountTreePayload,\n AccountTreePayloadStructType,\n AccountWalletMnemonicPayload,\n AccountWalletPrivateKeyPayload,\n AccountWalletMnemonicGroupEntry,\n AccountWalletPrivateKeyGroupEntry,\n AccountWalletPayloadId,\n AccountGroupPayloadId,\n AccountTreeSnapshotWallet,\n AccountTreeSnapshotGroup,\n ExportStateOptions,\n} from './state/payload.js';\n\nexport {\n AccountWalletPayloadType,\n AccountWalletPrivateKeyEncoding,\n AccountTreePayloadStruct,\n assertAccountTreePayload,\n} from './state/payload.js';\n\nexport { AccountTreeSnapshot } from './state/snapshot.js';\nexport { IdMap } from './state/id-map.js';\n"]}
|
package/dist/rules/entropy.d.ts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import { AccountGroupType, AccountWalletType } from '@metamask/account-api';
|
|
2
|
+
import type { EntropySourceId } from '@metamask/keyring-api';
|
|
2
3
|
import type { InternalAccount } from '@metamask/keyring-internal-api';
|
|
3
4
|
import type { AccountGroupObjectOf } from '../group.js';
|
|
4
5
|
import { BaseRule } from '../rule.js';
|
|
5
6
|
import type { Rule, RuleResult } from '../rule.js';
|
|
6
7
|
import type { AccountWalletObjectOf } from '../wallet.js';
|
|
7
8
|
export declare class EntropyRule extends BaseRule implements Rule<AccountWalletType.Entropy, AccountGroupType.MultichainAccount> {
|
|
9
|
+
#private;
|
|
8
10
|
readonly walletType = AccountWalletType.Entropy;
|
|
9
11
|
readonly groupType = AccountGroupType.MultichainAccount;
|
|
10
12
|
getEntropySourceIndex(entropySource: string): number;
|
|
13
|
+
/**
|
|
14
|
+
* The primary entropy source is the first HD keyring.
|
|
15
|
+
*
|
|
16
|
+
* @returns The primary HD keyring's entropy source ID, or `undefined` if none exists.
|
|
17
|
+
*/
|
|
18
|
+
getPrimaryEntropySource(): EntropySourceId | undefined;
|
|
11
19
|
match(account: InternalAccount): RuleResult<AccountWalletType.Entropy, AccountGroupType.MultichainAccount> | undefined;
|
|
12
20
|
getDefaultAccountWalletName(wallet: AccountWalletObjectOf<AccountWalletType.Entropy>): string;
|
|
13
21
|
getComputedAccountGroupName(group: AccountGroupObjectOf<AccountGroupType.MultichainAccount>): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entropy.d.ts","sourceRoot":"","sources":["../../src/rules/entropy.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EAIlB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"entropy.d.ts","sourceRoot":"","sources":["../../src/rules/entropy.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EAIlB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAG7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEtE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAE1D,qBAAa,WACX,SAAQ,QACR,YACE,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,CAAC,iBAAiB,CAAC;;IAErE,QAAQ,CAAC,UAAU,6BAA6B;IAEhD,QAAQ,CAAC,SAAS,sCAAsC;IAExD,qBAAqB,CAAC,aAAa,EAAE,MAAM,UAI1C;IAED;;;;OAIG;IACH,uBAAuB,IAAI,eAAe,GAAG,SAAS,CAErD;IAUD,KAAK,CACH,OAAO,EAAE,eAAe,GAEtB,UAAU,CAAC,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,CAAC,iBAAiB,CAAC,GACzE,SAAS,CA4CZ;IAED,2BAA2B,CACzB,MAAM,EAAE,qBAAqB,CAAC,iBAAiB,CAAC,OAAO,CAAC,GACvD,MAAM,CAQR;IAED,2BAA2B,CACzB,KAAK,EAAE,oBAAoB,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,GAC9D,MAAM,CAYR;IAED,4BAA4B,CAC1B,OAAO,EAAE,qBAAqB,CAAC,iBAAiB,CAAC,OAAO,CAAC,GACxD,MAAM,CAER;CACF"}
|
package/dist/rules/entropy.js
CHANGED
|
@@ -6,10 +6,19 @@ export class EntropyRule extends BaseRule {
|
|
|
6
6
|
walletType = AccountWalletType.Entropy;
|
|
7
7
|
groupType = AccountGroupType.MultichainAccount;
|
|
8
8
|
getEntropySourceIndex(entropySource) {
|
|
9
|
+
return this.#getHdKeyrings().findIndex((keyring) => keyring.metadata.id === entropySource);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* The primary entropy source is the first HD keyring.
|
|
13
|
+
*
|
|
14
|
+
* @returns The primary HD keyring's entropy source ID, or `undefined` if none exists.
|
|
15
|
+
*/
|
|
16
|
+
getPrimaryEntropySource() {
|
|
17
|
+
return this.#getHdKeyrings()[0]?.metadata.id;
|
|
18
|
+
}
|
|
19
|
+
#getHdKeyrings() {
|
|
9
20
|
const { keyrings } = this.messenger.call('KeyringController:getState');
|
|
10
|
-
return keyrings
|
|
11
|
-
.filter((keyring) => keyring.type === KeyringTypes.hd)
|
|
12
|
-
.findIndex((keyring) => keyring.metadata.id === entropySource);
|
|
21
|
+
return keyrings.filter((keyring) => keyring.type === KeyringTypes.hd);
|
|
13
22
|
}
|
|
14
23
|
match(account) {
|
|
15
24
|
if (!isBip44Account(account)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entropy.js","sourceRoot":"","sources":["../../src/rules/entropy.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"entropy.js","sourceRoot":"","sources":["../../src/rules/entropy.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n AccountGroupType,\n AccountWalletType,\n isBip44Account,\n toMultichainAccountGroupId,\n toMultichainAccountWalletId,\n} from '@metamask/account-api';\nimport { isEvmAccountType } from '@metamask/keyring-api';\nimport type { EntropySourceId } from '@metamask/keyring-api';\nimport type { KeyringObject } from '@metamask/keyring-controller';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\n\nimport type { AccountGroupObjectOf } from '../group.js';\nimport { BaseRule } from '../rule.js';\nimport type { Rule, RuleResult } from '../rule.js';\nimport type { AccountWalletObjectOf } from '../wallet.js';\n\nexport class EntropyRule\n extends BaseRule\n implements\n Rule<AccountWalletType.Entropy, AccountGroupType.MultichainAccount>\n{\n readonly walletType = AccountWalletType.Entropy;\n\n readonly groupType = AccountGroupType.MultichainAccount;\n\n getEntropySourceIndex(entropySource: string) {\n return this.#getHdKeyrings().findIndex(\n (keyring) => keyring.metadata.id === entropySource,\n );\n }\n\n /**\n * The primary entropy source is the first HD keyring.\n *\n * @returns The primary HD keyring's entropy source ID, or `undefined` if none exists.\n */\n getPrimaryEntropySource(): EntropySourceId | undefined {\n return this.#getHdKeyrings()[0]?.metadata.id;\n }\n\n #getHdKeyrings(): KeyringObject[] {\n const { keyrings } = this.messenger.call('KeyringController:getState');\n\n return keyrings.filter(\n (keyring) => keyring.type === (KeyringTypes.hd as string),\n );\n }\n\n match(\n account: InternalAccount,\n ):\n | RuleResult<AccountWalletType.Entropy, AccountGroupType.MultichainAccount>\n | undefined {\n if (!isBip44Account(account)) {\n return undefined;\n }\n\n const entropySource = account.options.entropy.id;\n const entropySourceIndex = this.getEntropySourceIndex(entropySource);\n if (entropySourceIndex === -1) {\n console.warn(\n `! Found an unknown entropy ID: \"${entropySource}\", account \"${account.id}\" won't be grouped by entropy.`,\n );\n return undefined;\n }\n\n const walletId = toMultichainAccountWalletId(entropySource);\n const groupId = toMultichainAccountGroupId(\n walletId,\n account.options.entropy.groupIndex,\n );\n\n return {\n wallet: {\n type: this.walletType,\n id: walletId,\n metadata: {\n entropy: {\n id: entropySource,\n },\n },\n },\n\n group: {\n type: this.groupType,\n id: groupId,\n metadata: {\n entropy: {\n groupIndex: account.options.entropy.groupIndex,\n },\n pinned: false,\n hidden: false,\n lastSelected: 0,\n },\n },\n };\n }\n\n getDefaultAccountWalletName(\n wallet: AccountWalletObjectOf<AccountWalletType.Entropy>,\n ): string {\n // NOTE: We have checked during the rule matching, so we can safely assume it will\n // well-defined here.\n const entropySourceIndex = this.getEntropySourceIndex(\n wallet.metadata.entropy.id,\n );\n\n return `Wallet ${entropySourceIndex + 1}`; // Use human indexing (starts at 1).\n }\n\n getComputedAccountGroupName(\n group: AccountGroupObjectOf<AccountGroupType.MultichainAccount>,\n ): string {\n // Only use EVM account names for multichain groups to avoid chain-specific names becoming group names.\n // Non-EVM account names should not be used as group names since groups represent multichain collections.\n for (const id of group.accounts) {\n const account = this.messenger.call('AccountsController:getAccount', id);\n\n if (account && isEvmAccountType(account.type)) {\n return account.metadata.name;\n }\n }\n\n return '';\n }\n\n getDefaultAccountGroupPrefix(\n _wallet: AccountWalletObjectOf<AccountWalletType.Entropy>,\n ): string {\n return 'Account';\n }\n}\n"]}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { AccountGroupId, AccountWalletId } from '@metamask/account-api';
|
|
2
|
-
import type { AccountId, AccountsControllerAccountsAddedEvent, AccountsControllerAccountsRemovedEvent, AccountsControllerGetAccountAction, AccountsControllerGetSelectedMultichainAccountAction, AccountsControllerListMultichainAccountsAction, AccountsControllerSelectedAccountChangeEvent, AccountsControllerSetSelectedAccountAction } from '@metamask/accounts-controller';
|
|
2
|
+
import type { AccountId, AccountsControllerAccountsAddedEvent, AccountsControllerAccountsRemovedEvent, AccountsControllerGetAccountAction, AccountsControllerGetAccountsAction, AccountsControllerGetSelectedMultichainAccountAction, AccountsControllerListMultichainAccountsAction, AccountsControllerSelectedAccountChangeEvent, AccountsControllerSetSelectedAccountAction } from '@metamask/accounts-controller';
|
|
3
3
|
import type { ControllerGetStateAction, ControllerStateChangeEvent } from '@metamask/base-controller';
|
|
4
4
|
import type { TraceCallback } from '@metamask/controller-utils';
|
|
5
|
-
import type { KeyringControllerGetStateAction, KeyringControllerVerifyPasswordAction, KeyringControllerWithControllerAction, KeyringControllerWithKeyringV2Action, KeyringControllerWithKeyringV2UnsafeAction } from '@metamask/keyring-controller';
|
|
5
|
+
import type { KeyringControllerGetStateAction, KeyringControllerRemoveAccountAction, KeyringControllerVerifyPasswordAction, KeyringControllerWithControllerAction, KeyringControllerWithKeyringV2Action, KeyringControllerWithKeyringV2UnsafeAction } from '@metamask/keyring-controller';
|
|
6
6
|
import type { Messenger } from '@metamask/messenger';
|
|
7
|
-
import type { MultichainAccountServiceCreateMultichainAccountGroupAction, MultichainAccountServiceCreateMultichainAccountGroupsAction, MultichainAccountServiceCreateMultichainAccountWalletAction } from '@metamask/multichain-account-service';
|
|
7
|
+
import type { MultichainAccountServiceCreateMultichainAccountGroupAction, MultichainAccountServiceCreateMultichainAccountGroupsAction, MultichainAccountServiceCreateMultichainAccountWalletAction, MultichainAccountServiceRemoveMultichainAccountWalletAction } from '@metamask/multichain-account-service';
|
|
8
8
|
import type { MultichainAccountServiceWalletStatusChangeEvent } from '@metamask/multichain-account-service';
|
|
9
9
|
import type { AuthenticationController, UserStorageController } from '@metamask/profile-sync-controller';
|
|
10
10
|
import type { SnapControllerGetSnapAction } from '@metamask/snaps-controllers';
|
|
@@ -36,7 +36,7 @@ export type AccountTreeControllerState = {
|
|
|
36
36
|
accountWalletsMetadata: Record<AccountWalletId, AccountTreeWalletPersistedMetadata>;
|
|
37
37
|
};
|
|
38
38
|
export type AccountTreeControllerGetStateAction = ControllerGetStateAction<typeof controllerName, AccountTreeControllerState>;
|
|
39
|
-
export type AllowedActions = AccountsControllerGetAccountAction | AccountsControllerGetSelectedMultichainAccountAction | AccountsControllerListMultichainAccountsAction | AccountsControllerSetSelectedAccountAction | KeyringControllerGetStateAction | KeyringControllerVerifyPasswordAction | SnapControllerGetSnapAction | UserStorageController.UserStorageControllerGetStateAction | UserStorageController.UserStorageControllerPerformGetStorageAction | UserStorageController.UserStorageControllerPerformGetStorageAllFeatureEntriesAction | UserStorageController.UserStorageControllerPerformSetStorageAction | UserStorageController.UserStorageControllerPerformBatchSetStorageAction | AuthenticationController.AuthenticationControllerGetSessionProfileAction | MultichainAccountServiceCreateMultichainAccountGroupAction | MultichainAccountServiceCreateMultichainAccountGroupsAction | MultichainAccountServiceCreateMultichainAccountWalletAction | KeyringControllerWithControllerAction | KeyringControllerWithKeyringV2Action | KeyringControllerWithKeyringV2UnsafeAction;
|
|
39
|
+
export type AllowedActions = AccountsControllerGetAccountAction | AccountsControllerGetAccountsAction | AccountsControllerGetSelectedMultichainAccountAction | AccountsControllerListMultichainAccountsAction | AccountsControllerSetSelectedAccountAction | KeyringControllerGetStateAction | KeyringControllerRemoveAccountAction | KeyringControllerVerifyPasswordAction | SnapControllerGetSnapAction | UserStorageController.UserStorageControllerGetStateAction | UserStorageController.UserStorageControllerPerformGetStorageAction | UserStorageController.UserStorageControllerPerformGetStorageAllFeatureEntriesAction | UserStorageController.UserStorageControllerPerformSetStorageAction | UserStorageController.UserStorageControllerPerformBatchSetStorageAction | AuthenticationController.AuthenticationControllerGetSessionProfileAction | MultichainAccountServiceCreateMultichainAccountGroupAction | MultichainAccountServiceCreateMultichainAccountGroupsAction | MultichainAccountServiceCreateMultichainAccountWalletAction | MultichainAccountServiceRemoveMultichainAccountWalletAction | KeyringControllerWithControllerAction | KeyringControllerWithKeyringV2Action | KeyringControllerWithKeyringV2UnsafeAction;
|
|
40
40
|
export type AccountTreeControllerActions = AccountTreeControllerGetStateAction | AccountTreeControllerMethodActions;
|
|
41
41
|
export type AccountTreeControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, AccountTreeControllerState>;
|
|
42
42
|
/**
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AccountGroupId, AccountWalletId } from '@metamask/account-api';\nimport type {\n AccountId,\n AccountsControllerAccountsAddedEvent,\n AccountsControllerAccountsRemovedEvent,\n AccountsControllerGetAccountAction,\n AccountsControllerGetSelectedMultichainAccountAction,\n AccountsControllerListMultichainAccountsAction,\n AccountsControllerSelectedAccountChangeEvent,\n AccountsControllerSetSelectedAccountAction,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport type {\n KeyringControllerGetStateAction,\n KeyringControllerVerifyPasswordAction,\n KeyringControllerWithControllerAction,\n KeyringControllerWithKeyringV2Action,\n KeyringControllerWithKeyringV2UnsafeAction,\n} from '@metamask/keyring-controller';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n MultichainAccountServiceCreateMultichainAccountGroupAction,\n MultichainAccountServiceCreateMultichainAccountGroupsAction,\n MultichainAccountServiceCreateMultichainAccountWalletAction,\n} from '@metamask/multichain-account-service';\nimport type { MultichainAccountServiceWalletStatusChangeEvent } from '@metamask/multichain-account-service';\nimport type {\n AuthenticationController,\n UserStorageController,\n} from '@metamask/profile-sync-controller';\nimport type { SnapControllerGetSnapAction } from '@metamask/snaps-controllers';\n\nimport type { AccountTreeControllerMethodActions } from './AccountTreeController-method-action-types.js';\nimport type { controllerName } from './AccountTreeController.js';\nimport type {\n BackupAndSyncAnalyticsEventPayload,\n BackupAndSyncEmitAnalyticsEventParams,\n} from './backup-and-sync/analytics/index.js';\nimport type {\n AccountGroupObject,\n AccountTreeGroupPersistedMetadata,\n} from './group.js';\nimport type {\n AccountWalletObject,\n AccountTreeWalletPersistedMetadata,\n} from './wallet.js';\n\n// Backward compatibility aliases using indexed access types\n/**\n * @deprecated Use AccountTreeGroupMetadata for tree objects or AccountTreeGroupPersistedMetadata for controller state\n */\nexport type AccountGroupMetadata = AccountGroupObject['metadata'];\n\n/**\n * @deprecated Use AccountTreeWalletMetadata for tree objects or AccountTreeWalletPersistedMetadata for controller state\n */\nexport type AccountWalletMetadata = AccountWalletObject['metadata'];\n\nexport type AccountTreeControllerState = {\n accountTree: {\n wallets: {\n // Wallets:\n [walletId: AccountWalletId]: AccountWalletObject;\n };\n };\n selectedAccountGroup: AccountGroupId | '';\n isAccountTreeSyncingInProgress: boolean;\n hasAccountTreeSyncingSyncedAtLeastOnce: boolean;\n /** Persistent metadata for account groups (names, pinning, hiding, sync timestamps) */\n accountGroupsMetadata: Record<\n AccountGroupId,\n AccountTreeGroupPersistedMetadata\n >;\n /** Persistent metadata for account wallets (names, sync timestamps) */\n accountWalletsMetadata: Record<\n AccountWalletId,\n AccountTreeWalletPersistedMetadata\n >;\n};\n\nexport type AccountTreeControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n AccountTreeControllerState\n>;\n\nexport type AllowedActions =\n | AccountsControllerGetAccountAction\n | AccountsControllerGetSelectedMultichainAccountAction\n | AccountsControllerListMultichainAccountsAction\n | AccountsControllerSetSelectedAccountAction\n | KeyringControllerGetStateAction\n | KeyringControllerVerifyPasswordAction\n | SnapControllerGetSnapAction\n | UserStorageController.UserStorageControllerGetStateAction\n | UserStorageController.UserStorageControllerPerformGetStorageAction\n | UserStorageController.UserStorageControllerPerformGetStorageAllFeatureEntriesAction\n | UserStorageController.UserStorageControllerPerformSetStorageAction\n | UserStorageController.UserStorageControllerPerformBatchSetStorageAction\n | AuthenticationController.AuthenticationControllerGetSessionProfileAction\n | MultichainAccountServiceCreateMultichainAccountGroupAction\n | MultichainAccountServiceCreateMultichainAccountGroupsAction\n | MultichainAccountServiceCreateMultichainAccountWalletAction\n | KeyringControllerWithControllerAction\n | KeyringControllerWithKeyringV2Action\n | KeyringControllerWithKeyringV2UnsafeAction;\n\nexport type AccountTreeControllerActions =\n | AccountTreeControllerGetStateAction\n | AccountTreeControllerMethodActions;\n\nexport type AccountTreeControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n AccountTreeControllerState\n>;\n\n/**\n * Represents the `AccountTreeController:accountTreeChange` event.\n * This event is emitted when nodes (wallets, groups, or accounts) are added or removed.\n */\nexport type AccountTreeControllerAccountTreeChangeEvent = {\n type: `${typeof controllerName}:accountTreeChange`;\n payload: [AccountTreeControllerState['accountTree']];\n};\n\n/**\n * Represents the `AccountTreeController:selectedAccountGroupChange` event.\n * This event is emitted when the selected account group changes.\n */\nexport type AccountTreeControllerSelectedAccountGroupChangeEvent = {\n type: `${typeof controllerName}:selectedAccountGroupChange`;\n payload: [AccountGroupId | '', AccountGroupId | ''];\n};\n\n/**\n * Represents the `AccountTreeController:accountGroupCreated` event.\n * This event is emitted when a new account group is added to the tree\n * after the controller has been initialized.\n */\nexport type AccountTreeControllerAccountGroupCreatedEvent = {\n type: `${typeof controllerName}:accountGroupCreated`;\n payload: [AccountGroupObject];\n};\n\n/**\n * Represents the `AccountTreeController:accountGroupUpdated` event.\n * This event is emitted when an existing account group's metadata or\n * membership changes after the controller has been initialized.\n */\nexport type AccountTreeControllerAccountGroupUpdatedEvent = {\n type: `${typeof controllerName}:accountGroupUpdated`;\n payload: [AccountGroupObject];\n};\n\n/**\n * Represents the `AccountTreeController:accountGroupRemoved` event.\n * This event is emitted when an account group is pruned from the tree\n * (its last account was removed) after the controller has been initialized.\n */\nexport type AccountTreeControllerAccountGroupRemovedEvent = {\n type: `${typeof controllerName}:accountGroupRemoved`;\n payload: [AccountGroupId];\n};\n\n/**\n * Represents the `AccountTreeController:initialized` event.\n * This event is emitted when the account tree has been fully built and is\n * ready to consume. It carries the full controller state at the moment of\n * initialization so that consumers do not need an extra `getState()` call.\n */\nexport type AccountTreeControllerInitializedEvent = {\n type: `${typeof controllerName}:initialized`;\n payload: [AccountTreeControllerState];\n};\n\n/**\n * Represents the `AccountTreeController:uninitialized` event.\n * This event is emitted when the account tree has been torn down via\n * `clearState()`, symmetric to `initialized`.\n */\nexport type AccountTreeControllerUninitializedEvent = {\n type: `${typeof controllerName}:uninitialized`;\n payload: [];\n};\n\nexport type AllowedEvents =\n | AccountsControllerAccountsAddedEvent\n | AccountsControllerAccountsRemovedEvent\n | AccountsControllerSelectedAccountChangeEvent\n | UserStorageController.UserStorageControllerStateChangeEvent\n | MultichainAccountServiceWalletStatusChangeEvent;\n\nexport type AccountTreeControllerEvents =\n | AccountTreeControllerStateChangeEvent\n | AccountTreeControllerAccountTreeChangeEvent\n | AccountTreeControllerSelectedAccountGroupChangeEvent\n | AccountTreeControllerAccountGroupCreatedEvent\n | AccountTreeControllerAccountGroupUpdatedEvent\n | AccountTreeControllerAccountGroupRemovedEvent\n | AccountTreeControllerInitializedEvent\n | AccountTreeControllerUninitializedEvent;\n\nexport type AccountTreeControllerMessenger = Messenger<\n typeof controllerName,\n AccountTreeControllerActions | AllowedActions,\n AccountTreeControllerEvents | AllowedEvents\n>;\n\nexport type AccountTreeControllerConfig = {\n trace?: TraceCallback;\n backupAndSync?: {\n onBackupAndSyncEvent?: (event: BackupAndSyncAnalyticsEventPayload) => void;\n };\n accountOrderCallbacks?: {\n isHiddenAccount?: (accountId: AccountId) => boolean;\n isPinnedAccount?: (accountId: AccountId) => boolean;\n };\n};\n\nexport type AccountTreeControllerInternalBackupAndSyncConfig = {\n emitAnalyticsEventFn: (event: BackupAndSyncEmitAnalyticsEventParams) => void;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AccountGroupId, AccountWalletId } from '@metamask/account-api';\nimport type {\n AccountId,\n AccountsControllerAccountsAddedEvent,\n AccountsControllerAccountsRemovedEvent,\n AccountsControllerGetAccountAction,\n AccountsControllerGetAccountsAction,\n AccountsControllerGetSelectedMultichainAccountAction,\n AccountsControllerListMultichainAccountsAction,\n AccountsControllerSelectedAccountChangeEvent,\n AccountsControllerSetSelectedAccountAction,\n} from '@metamask/accounts-controller';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport type { TraceCallback } from '@metamask/controller-utils';\nimport type {\n KeyringControllerGetStateAction,\n KeyringControllerRemoveAccountAction,\n KeyringControllerVerifyPasswordAction,\n KeyringControllerWithControllerAction,\n KeyringControllerWithKeyringV2Action,\n KeyringControllerWithKeyringV2UnsafeAction,\n} from '@metamask/keyring-controller';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n MultichainAccountServiceCreateMultichainAccountGroupAction,\n MultichainAccountServiceCreateMultichainAccountGroupsAction,\n MultichainAccountServiceCreateMultichainAccountWalletAction,\n MultichainAccountServiceRemoveMultichainAccountWalletAction,\n} from '@metamask/multichain-account-service';\nimport type { MultichainAccountServiceWalletStatusChangeEvent } from '@metamask/multichain-account-service';\nimport type {\n AuthenticationController,\n UserStorageController,\n} from '@metamask/profile-sync-controller';\nimport type { SnapControllerGetSnapAction } from '@metamask/snaps-controllers';\n\nimport type { AccountTreeControllerMethodActions } from './AccountTreeController-method-action-types.js';\nimport type { controllerName } from './AccountTreeController.js';\nimport type {\n BackupAndSyncAnalyticsEventPayload,\n BackupAndSyncEmitAnalyticsEventParams,\n} from './backup-and-sync/analytics/index.js';\nimport type {\n AccountGroupObject,\n AccountTreeGroupPersistedMetadata,\n} from './group.js';\nimport type {\n AccountWalletObject,\n AccountTreeWalletPersistedMetadata,\n} from './wallet.js';\n\n// Backward compatibility aliases using indexed access types\n/**\n * @deprecated Use AccountTreeGroupMetadata for tree objects or AccountTreeGroupPersistedMetadata for controller state\n */\nexport type AccountGroupMetadata = AccountGroupObject['metadata'];\n\n/**\n * @deprecated Use AccountTreeWalletMetadata for tree objects or AccountTreeWalletPersistedMetadata for controller state\n */\nexport type AccountWalletMetadata = AccountWalletObject['metadata'];\n\nexport type AccountTreeControllerState = {\n accountTree: {\n wallets: {\n // Wallets:\n [walletId: AccountWalletId]: AccountWalletObject;\n };\n };\n selectedAccountGroup: AccountGroupId | '';\n isAccountTreeSyncingInProgress: boolean;\n hasAccountTreeSyncingSyncedAtLeastOnce: boolean;\n /** Persistent metadata for account groups (names, pinning, hiding, sync timestamps) */\n accountGroupsMetadata: Record<\n AccountGroupId,\n AccountTreeGroupPersistedMetadata\n >;\n /** Persistent metadata for account wallets (names, sync timestamps) */\n accountWalletsMetadata: Record<\n AccountWalletId,\n AccountTreeWalletPersistedMetadata\n >;\n};\n\nexport type AccountTreeControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n AccountTreeControllerState\n>;\n\nexport type AllowedActions =\n | AccountsControllerGetAccountAction\n | AccountsControllerGetAccountsAction\n | AccountsControllerGetSelectedMultichainAccountAction\n | AccountsControllerListMultichainAccountsAction\n | AccountsControllerSetSelectedAccountAction\n | KeyringControllerGetStateAction\n | KeyringControllerRemoveAccountAction\n | KeyringControllerVerifyPasswordAction\n | SnapControllerGetSnapAction\n | UserStorageController.UserStorageControllerGetStateAction\n | UserStorageController.UserStorageControllerPerformGetStorageAction\n | UserStorageController.UserStorageControllerPerformGetStorageAllFeatureEntriesAction\n | UserStorageController.UserStorageControllerPerformSetStorageAction\n | UserStorageController.UserStorageControllerPerformBatchSetStorageAction\n | AuthenticationController.AuthenticationControllerGetSessionProfileAction\n | MultichainAccountServiceCreateMultichainAccountGroupAction\n | MultichainAccountServiceCreateMultichainAccountGroupsAction\n | MultichainAccountServiceCreateMultichainAccountWalletAction\n | MultichainAccountServiceRemoveMultichainAccountWalletAction\n | KeyringControllerWithControllerAction\n | KeyringControllerWithKeyringV2Action\n | KeyringControllerWithKeyringV2UnsafeAction;\n\nexport type AccountTreeControllerActions =\n | AccountTreeControllerGetStateAction\n | AccountTreeControllerMethodActions;\n\nexport type AccountTreeControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n AccountTreeControllerState\n>;\n\n/**\n * Represents the `AccountTreeController:accountTreeChange` event.\n * This event is emitted when nodes (wallets, groups, or accounts) are added or removed.\n */\nexport type AccountTreeControllerAccountTreeChangeEvent = {\n type: `${typeof controllerName}:accountTreeChange`;\n payload: [AccountTreeControllerState['accountTree']];\n};\n\n/**\n * Represents the `AccountTreeController:selectedAccountGroupChange` event.\n * This event is emitted when the selected account group changes.\n */\nexport type AccountTreeControllerSelectedAccountGroupChangeEvent = {\n type: `${typeof controllerName}:selectedAccountGroupChange`;\n payload: [AccountGroupId | '', AccountGroupId | ''];\n};\n\n/**\n * Represents the `AccountTreeController:accountGroupCreated` event.\n * This event is emitted when a new account group is added to the tree\n * after the controller has been initialized.\n */\nexport type AccountTreeControllerAccountGroupCreatedEvent = {\n type: `${typeof controllerName}:accountGroupCreated`;\n payload: [AccountGroupObject];\n};\n\n/**\n * Represents the `AccountTreeController:accountGroupUpdated` event.\n * This event is emitted when an existing account group's metadata or\n * membership changes after the controller has been initialized.\n */\nexport type AccountTreeControllerAccountGroupUpdatedEvent = {\n type: `${typeof controllerName}:accountGroupUpdated`;\n payload: [AccountGroupObject];\n};\n\n/**\n * Represents the `AccountTreeController:accountGroupRemoved` event.\n * This event is emitted when an account group is pruned from the tree\n * (its last account was removed) after the controller has been initialized.\n */\nexport type AccountTreeControllerAccountGroupRemovedEvent = {\n type: `${typeof controllerName}:accountGroupRemoved`;\n payload: [AccountGroupId];\n};\n\n/**\n * Represents the `AccountTreeController:initialized` event.\n * This event is emitted when the account tree has been fully built and is\n * ready to consume. It carries the full controller state at the moment of\n * initialization so that consumers do not need an extra `getState()` call.\n */\nexport type AccountTreeControllerInitializedEvent = {\n type: `${typeof controllerName}:initialized`;\n payload: [AccountTreeControllerState];\n};\n\n/**\n * Represents the `AccountTreeController:uninitialized` event.\n * This event is emitted when the account tree has been torn down via\n * `clearState()`, symmetric to `initialized`.\n */\nexport type AccountTreeControllerUninitializedEvent = {\n type: `${typeof controllerName}:uninitialized`;\n payload: [];\n};\n\nexport type AllowedEvents =\n | AccountsControllerAccountsAddedEvent\n | AccountsControllerAccountsRemovedEvent\n | AccountsControllerSelectedAccountChangeEvent\n | UserStorageController.UserStorageControllerStateChangeEvent\n | MultichainAccountServiceWalletStatusChangeEvent;\n\nexport type AccountTreeControllerEvents =\n | AccountTreeControllerStateChangeEvent\n | AccountTreeControllerAccountTreeChangeEvent\n | AccountTreeControllerSelectedAccountGroupChangeEvent\n | AccountTreeControllerAccountGroupCreatedEvent\n | AccountTreeControllerAccountGroupUpdatedEvent\n | AccountTreeControllerAccountGroupRemovedEvent\n | AccountTreeControllerInitializedEvent\n | AccountTreeControllerUninitializedEvent;\n\nexport type AccountTreeControllerMessenger = Messenger<\n typeof controllerName,\n AccountTreeControllerActions | AllowedActions,\n AccountTreeControllerEvents | AllowedEvents\n>;\n\nexport type AccountTreeControllerConfig = {\n trace?: TraceCallback;\n backupAndSync?: {\n onBackupAndSyncEvent?: (event: BackupAndSyncAnalyticsEventPayload) => void;\n };\n accountOrderCallbacks?: {\n isHiddenAccount?: (accountId: AccountId) => boolean;\n isPinnedAccount?: (accountId: AccountId) => boolean;\n };\n};\n\nexport type AccountTreeControllerInternalBackupAndSyncConfig = {\n emitAnalyticsEventFn: (event: BackupAndSyncEmitAnalyticsEventParams) => void;\n};\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metamask-previews/account-tree-controller",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "11.0.0-preview-df2073e",
|
|
4
4
|
"description": "Controller to group account together based on some pre-defined rules",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Ethereum",
|
|
@@ -53,10 +53,10 @@
|
|
|
53
53
|
"@metamask/accounts-controller": "^40.0.0",
|
|
54
54
|
"@metamask/base-controller": "^10.0.0",
|
|
55
55
|
"@metamask/keyring-api": "^24.0.0",
|
|
56
|
-
"@metamask/keyring-controller": "^28.
|
|
56
|
+
"@metamask/keyring-controller": "^28.1.0",
|
|
57
57
|
"@metamask/messenger": "^3.0.0",
|
|
58
|
-
"@metamask/multichain-account-service": "^14.
|
|
59
|
-
"@metamask/profile-sync-controller": "^
|
|
58
|
+
"@metamask/multichain-account-service": "^14.1.0",
|
|
59
|
+
"@metamask/profile-sync-controller": "^33.0.0",
|
|
60
60
|
"@metamask/snaps-controllers": "^19.0.0",
|
|
61
61
|
"@metamask/snaps-sdk": "^11.0.0",
|
|
62
62
|
"@metamask/snaps-utils": "^12.1.2",
|
|
@@ -66,17 +66,17 @@
|
|
|
66
66
|
"lodash-es": "^4.17.21"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
|
-
"@metamask/account-api": "^2.
|
|
70
|
-
"@metamask/auto-changelog": "^6.1
|
|
69
|
+
"@metamask/account-api": "^2.1.0",
|
|
70
|
+
"@metamask/auto-changelog": "^6.2.1",
|
|
71
71
|
"@metamask/eth-hd-keyring": "^15.0.0",
|
|
72
72
|
"@metamask/providers": "^22.1.0",
|
|
73
73
|
"@types/jest": "^30.0.0",
|
|
74
74
|
"@typescript/native": "npm:typescript@^7.0.2",
|
|
75
75
|
"deepmerge": "^4.2.2",
|
|
76
76
|
"jest": "^30.4.2",
|
|
77
|
-
"rimraf": "^
|
|
78
|
-
"ts-jest": "^29.4.
|
|
79
|
-
"tsx": "^4.
|
|
77
|
+
"rimraf": "^6.1.3",
|
|
78
|
+
"ts-jest": "^29.4.12",
|
|
79
|
+
"tsx": "^4.23.15",
|
|
80
80
|
"typedoc": "^0.25.13",
|
|
81
81
|
"typedoc-plugin-missing-exports": "^2.0.0",
|
|
82
82
|
"typescript": "npm:@typescript/typescript6@^6.0.2",
|