@metamask-previews/account-tree-controller 2.0.0-preview-3d9bbf60 → 2.0.0-preview-e98a6769
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -6
- package/dist/AccountTreeController.cjs +104 -219
- package/dist/AccountTreeController.cjs.map +1 -1
- package/dist/AccountTreeController.d.cts +12 -0
- package/dist/AccountTreeController.d.cts.map +1 -1
- package/dist/AccountTreeController.d.mts +12 -0
- package/dist/AccountTreeController.d.mts.map +1 -1
- package/dist/AccountTreeController.mjs +106 -221
- package/dist/AccountTreeController.mjs.map +1 -1
- package/dist/rules/entropy.cjs +69 -53
- package/dist/rules/entropy.cjs.map +1 -1
- package/dist/rules/entropy.d.cts +12 -24
- package/dist/rules/entropy.d.cts.map +1 -1
- package/dist/rules/entropy.d.mts +12 -24
- package/dist/rules/entropy.d.mts.map +1 -1
- package/dist/rules/entropy.mjs +67 -49
- package/dist/rules/entropy.mjs.map +1 -1
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +3 -3
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +3 -3
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -9,9 +9,8 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
11
|
};
|
|
12
|
-
var _AccountTreeController_instances, _AccountTreeController_accountIdToContext, _AccountTreeController_groupIdToWalletId, _AccountTreeController_backupAndSyncService, _AccountTreeController_rules, _AccountTreeController_trace, _AccountTreeController_backupAndSyncConfig, _AccountTreeController_accountOrderCallbacks, _AccountTreeController_initialized, _AccountTreeController_getSnapRule, _AccountTreeController_getKeyringRule,
|
|
13
|
-
import { AccountWalletType,
|
|
14
|
-
import { AccountGroupType } from "@metamask/account-api";
|
|
12
|
+
var _AccountTreeController_instances, _AccountTreeController_accountIdToContext, _AccountTreeController_groupIdToWalletId, _AccountTreeController_backupAndSyncService, _AccountTreeController_rules, _AccountTreeController_trace, _AccountTreeController_backupAndSyncConfig, _AccountTreeController_accountOrderCallbacks, _AccountTreeController_initialized, _AccountTreeController_getEntropyRule, _AccountTreeController_getSnapRule, _AccountTreeController_getKeyringRule, _AccountTreeController_applyAccountWalletMetadata, _AccountTreeController_getRuleForWallet, _AccountTreeController_getComputedAccountGroupName, _AccountTreeController_getDefaultAccountGroupName, _AccountTreeController_applyAccountGroupMetadata, _AccountTreeController_handleAccountAdded, _AccountTreeController_handleAccountRemoved, _AccountTreeController_pruneEmptyGroupAndWallet, _AccountTreeController_insert, _AccountTreeController_listAccounts, _AccountTreeController_assertAccountGroupExists, _AccountTreeController_assertAccountWalletExists, _AccountTreeController_assertAccountGroupNameIsUnique, _AccountTreeController_getDefaultSelectedAccountGroup, _AccountTreeController_handleSelectedAccountChange, _AccountTreeController_handleMultichainAccountWalletStatusChange, _AccountTreeController_getAccountGroup, _AccountTreeController_getDefaultAccountFromAccountGroupId, _AccountTreeController_getDefaultAccountGroupId, _AccountTreeController_registerMessageHandlers, _AccountTreeController_createBackupAndSyncContext;
|
|
13
|
+
import { AccountWalletType, select } from "@metamask/account-api";
|
|
15
14
|
import { BaseController } from "@metamask/base-controller";
|
|
16
15
|
import { isEvmAccountType } from "@metamask/keyring-api";
|
|
17
16
|
import { assert } from "@metamask/utils";
|
|
@@ -19,7 +18,7 @@ import { formatAnalyticsEvent, traceFallback } from "./backup-and-sync/analytics
|
|
|
19
18
|
import { BackupAndSyncService } from "./backup-and-sync/service/index.mjs";
|
|
20
19
|
import { ACCOUNT_TYPE_TO_SORT_ORDER, isAccountGroupNameUnique, isAccountGroupNameUniqueFromWallet, MAX_SORT_ORDER } from "./group.mjs";
|
|
21
20
|
import { projectLogger as log } from "./logger.mjs";
|
|
22
|
-
import {
|
|
21
|
+
import { EntropyRule } from "./rules/entropy.mjs";
|
|
23
22
|
import { KeyringRule } from "./rules/keyring.mjs";
|
|
24
23
|
import { SnapRule } from "./rules/snap.mjs";
|
|
25
24
|
export const controllerName = 'AccountTreeController';
|
|
@@ -115,7 +114,7 @@ export class AccountTreeController extends BaseController {
|
|
|
115
114
|
// Rules to apply to construct the wallets tree.
|
|
116
115
|
__classPrivateFieldSet(this, _AccountTreeController_rules, [
|
|
117
116
|
// 1. We group by entropy-source
|
|
118
|
-
|
|
117
|
+
new EntropyRule(this.messenger),
|
|
119
118
|
// 2. We group by Snap ID
|
|
120
119
|
new SnapRule(this.messenger),
|
|
121
120
|
// 3. We group by wallet type (this rule cannot fail and will group all non-matching accounts)
|
|
@@ -146,12 +145,6 @@ export class AccountTreeController extends BaseController {
|
|
|
146
145
|
this.messenger.subscribe('UserStorageController:stateChange', (userStorageControllerState) => {
|
|
147
146
|
__classPrivateFieldGet(this, _AccountTreeController_backupAndSyncService, "f").handleUserStorageStateChange(userStorageControllerState);
|
|
148
147
|
});
|
|
149
|
-
this.messenger.subscribe('MultichainAccountService:multichainAccountGroupCreated', (group) => {
|
|
150
|
-
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_handleMultichainAccountGroupCreatedOrUpdated).call(this, group);
|
|
151
|
-
});
|
|
152
|
-
this.messenger.subscribe('MultichainAccountService:multichainAccountGroupUpdated', (group) => {
|
|
153
|
-
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_handleMultichainAccountGroupCreatedOrUpdated).call(this, group);
|
|
154
|
-
});
|
|
155
148
|
this.messenger.subscribe('MultichainAccountService:walletStatusChange', (walletId, status) => {
|
|
156
149
|
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_handleMultichainAccountWalletStatusChange).call(this, walletId, status);
|
|
157
150
|
});
|
|
@@ -171,7 +164,6 @@ export class AccountTreeController extends BaseController {
|
|
|
171
164
|
return;
|
|
172
165
|
}
|
|
173
166
|
log('Initializing...');
|
|
174
|
-
// For now, we always re-compute all wallets, we do not re-use the existing state.
|
|
175
167
|
const wallets = {};
|
|
176
168
|
// Clear mappings for fresh rebuild.
|
|
177
169
|
__classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").clear();
|
|
@@ -179,12 +171,6 @@ export class AccountTreeController extends BaseController {
|
|
|
179
171
|
// Keep the current selected group to check if it's still part of the tree
|
|
180
172
|
// after rebuilding it.
|
|
181
173
|
const previousSelectedAccountGroup = this.state.accountTree.selectedAccountGroup;
|
|
182
|
-
// Insert all multichain account wallet/groups.
|
|
183
|
-
for (const wallet of __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getMultichainAccountWallets).call(this)) {
|
|
184
|
-
for (const group of wallet.getMultichainAccountGroups()) {
|
|
185
|
-
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_insertOrUpdateMultichainAccountWalletAndGroup).call(this, wallets, wallet, group);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
174
|
// There's no guarantee that accounts would be sorted by their import time
|
|
189
175
|
// with `listMultichainAccounts`. We have to sort them here before constructing
|
|
190
176
|
// the tree.
|
|
@@ -197,14 +183,9 @@ export class AccountTreeController extends BaseController {
|
|
|
197
183
|
// won't be enough and we would have to use group properties instead (like group
|
|
198
184
|
// index or maybe introduce a `importTime` at group level).
|
|
199
185
|
const accounts = __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_listAccounts).call(this).sort((a, b) => a.metadata.importTime - b.metadata.importTime);
|
|
200
|
-
//
|
|
186
|
+
// For now, we always re-compute all wallets, we do not re-use the existing state.
|
|
201
187
|
for (const account of accounts) {
|
|
202
|
-
|
|
203
|
-
// here, since we've already added wallets/groups for each of them.
|
|
204
|
-
if (isBip44Account(account)) {
|
|
205
|
-
continue;
|
|
206
|
-
}
|
|
207
|
-
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_insertAccount).call(this, wallets, account);
|
|
188
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_insert).call(this, wallets, account);
|
|
208
189
|
}
|
|
209
190
|
// Once we have the account tree, we can apply persisted metadata (names + UI states).
|
|
210
191
|
let previousSelectedAccountGroupStillExists = false;
|
|
@@ -575,19 +556,12 @@ export class AccountTreeController extends BaseController {
|
|
|
575
556
|
return __classPrivateFieldGet(this, _AccountTreeController_backupAndSyncService, "f").performFullSyncAtLeastOnce();
|
|
576
557
|
}
|
|
577
558
|
}
|
|
578
|
-
_AccountTreeController_accountIdToContext = new WeakMap(), _AccountTreeController_groupIdToWalletId = new WeakMap(), _AccountTreeController_backupAndSyncService = new WeakMap(), _AccountTreeController_rules = new WeakMap(), _AccountTreeController_trace = new WeakMap(), _AccountTreeController_backupAndSyncConfig = new WeakMap(), _AccountTreeController_accountOrderCallbacks = new WeakMap(), _AccountTreeController_initialized = new WeakMap(), _AccountTreeController_instances = new WeakSet(),
|
|
559
|
+
_AccountTreeController_accountIdToContext = new WeakMap(), _AccountTreeController_groupIdToWalletId = new WeakMap(), _AccountTreeController_backupAndSyncService = new WeakMap(), _AccountTreeController_rules = new WeakMap(), _AccountTreeController_trace = new WeakMap(), _AccountTreeController_backupAndSyncConfig = new WeakMap(), _AccountTreeController_accountOrderCallbacks = new WeakMap(), _AccountTreeController_initialized = new WeakMap(), _AccountTreeController_instances = new WeakSet(), _AccountTreeController_getEntropyRule = function _AccountTreeController_getEntropyRule() {
|
|
579
560
|
return __classPrivateFieldGet(this, _AccountTreeController_rules, "f")[0];
|
|
580
|
-
},
|
|
561
|
+
}, _AccountTreeController_getSnapRule = function _AccountTreeController_getSnapRule() {
|
|
581
562
|
return __classPrivateFieldGet(this, _AccountTreeController_rules, "f")[1];
|
|
582
|
-
},
|
|
583
|
-
|
|
584
|
-
case AccountWalletType.Entropy:
|
|
585
|
-
return getEntropyDefaultAccountWalletName(this.messenger, wallet);
|
|
586
|
-
case AccountWalletType.Snap:
|
|
587
|
-
return __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getSnapRule).call(this).getDefaultAccountWalletName(wallet);
|
|
588
|
-
default:
|
|
589
|
-
return __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getKeyringRule).call(this).getDefaultAccountWalletName(wallet);
|
|
590
|
-
}
|
|
563
|
+
}, _AccountTreeController_getKeyringRule = function _AccountTreeController_getKeyringRule() {
|
|
564
|
+
return __classPrivateFieldGet(this, _AccountTreeController_rules, "f")[2];
|
|
591
565
|
}, _AccountTreeController_applyAccountWalletMetadata = function _AccountTreeController_applyAccountWalletMetadata(state, walletId) {
|
|
592
566
|
const wallet = state.accountTree.wallets[walletId];
|
|
593
567
|
const persistedMetadata = state.accountWalletsMetadata[walletId];
|
|
@@ -597,9 +571,29 @@ _AccountTreeController_accountIdToContext = new WeakMap(), _AccountTreeControlle
|
|
|
597
571
|
}
|
|
598
572
|
else if (!wallet.metadata.name) {
|
|
599
573
|
// Generate default name if none exists
|
|
600
|
-
wallet.
|
|
574
|
+
if (wallet.type === AccountWalletType.Entropy) {
|
|
575
|
+
wallet.metadata.name =
|
|
576
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getEntropyRule).call(this).getDefaultAccountWalletName(wallet);
|
|
577
|
+
}
|
|
578
|
+
else if (wallet.type === AccountWalletType.Snap) {
|
|
579
|
+
wallet.metadata.name =
|
|
580
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getSnapRule).call(this).getDefaultAccountWalletName(wallet);
|
|
581
|
+
}
|
|
582
|
+
else {
|
|
583
|
+
wallet.metadata.name =
|
|
584
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getKeyringRule).call(this).getDefaultAccountWalletName(wallet);
|
|
585
|
+
}
|
|
601
586
|
log(`[${wallet.id}] Set default name to: "${wallet.metadata.name}"`);
|
|
602
587
|
}
|
|
588
|
+
}, _AccountTreeController_getRuleForWallet = function _AccountTreeController_getRuleForWallet(wallet) {
|
|
589
|
+
switch (wallet.type) {
|
|
590
|
+
case AccountWalletType.Entropy:
|
|
591
|
+
return __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getEntropyRule).call(this);
|
|
592
|
+
case AccountWalletType.Snap:
|
|
593
|
+
return __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getSnapRule).call(this);
|
|
594
|
+
default:
|
|
595
|
+
return __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getKeyringRule).call(this);
|
|
596
|
+
}
|
|
603
597
|
}, _AccountTreeController_getComputedAccountGroupName = function _AccountTreeController_getComputedAccountGroupName(wallet, group) {
|
|
604
598
|
let proposedName = ''; // Empty means there's no computed name for this group.
|
|
605
599
|
for (const id of group.accounts) {
|
|
@@ -624,18 +618,11 @@ _AccountTreeController_accountIdToContext = new WeakMap(), _AccountTreeControlle
|
|
|
624
618
|
proposedName = this.resolveNameConflict(wallet, group.id, proposedName);
|
|
625
619
|
}
|
|
626
620
|
return proposedName;
|
|
627
|
-
}, _AccountTreeController_getDefaultAccountGroupPrefix = function _AccountTreeController_getDefaultAccountGroupPrefix(wallet) {
|
|
628
|
-
switch (wallet.type) {
|
|
629
|
-
case AccountWalletType.Entropy:
|
|
630
|
-
return getEntropyDefaultAccountGroupPrefix();
|
|
631
|
-
case AccountWalletType.Snap:
|
|
632
|
-
return __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getSnapRule).call(this).getDefaultAccountGroupPrefix(wallet);
|
|
633
|
-
default:
|
|
634
|
-
return __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getKeyringRule).call(this).getDefaultAccountGroupPrefix(wallet);
|
|
635
|
-
}
|
|
636
621
|
}, _AccountTreeController_getDefaultAccountGroupName = function _AccountTreeController_getDefaultAccountGroupName(state, wallet, group, nextNaturalNameIndex) {
|
|
622
|
+
// Get the appropriate rule for this wallet type
|
|
623
|
+
const rule = __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getRuleForWallet).call(this, wallet);
|
|
637
624
|
// Get the prefix for groups of this wallet
|
|
638
|
-
const namePrefix =
|
|
625
|
+
const namePrefix = rule.getDefaultAccountGroupPrefix(wallet);
|
|
639
626
|
// Parse the highest account index being used (similar to accounts-controller)
|
|
640
627
|
let highestNameIndex = 0;
|
|
641
628
|
for (const { id: otherGroupId } of Object.values(wallet.groups)) {
|
|
@@ -761,15 +748,10 @@ _AccountTreeController_accountIdToContext = new WeakMap(), _AccountTreeControlle
|
|
|
761
748
|
if (!__classPrivateFieldGet(this, _AccountTreeController_initialized, "f")) {
|
|
762
749
|
return;
|
|
763
750
|
}
|
|
764
|
-
if (isBip44Account(account)) {
|
|
765
|
-
// We're skipping BIP-44 accounts since we rely on the `MultichainAccountService` to do
|
|
766
|
-
// the grouping of wallets/groups directly.
|
|
767
|
-
return;
|
|
768
|
-
}
|
|
769
751
|
// Check if this account is already known by the tree to avoid double-insertion.
|
|
770
752
|
if (!__classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").has(account.id)) {
|
|
771
753
|
this.update((state) => {
|
|
772
|
-
__classPrivateFieldGet(this, _AccountTreeController_instances, "m",
|
|
754
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_insert).call(this, state.accountTree.wallets, account);
|
|
773
755
|
const context = __classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").get(account.id);
|
|
774
756
|
if (context) {
|
|
775
757
|
const { walletId, groupId } = context;
|
|
@@ -792,40 +774,33 @@ _AccountTreeController_accountIdToContext = new WeakMap(), _AccountTreeControlle
|
|
|
792
774
|
const context = __classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").get(accountId);
|
|
793
775
|
if (context) {
|
|
794
776
|
const { walletId, groupId } = context;
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
let selectedAccountGroupChanged = false;
|
|
803
|
-
const previousSelectedAccountGroup = this.state.accountTree.selectedAccountGroup;
|
|
804
|
-
this.update((state) => {
|
|
805
|
-
const accounts = state.accountTree.wallets[walletId]?.groups[groupId].accounts;
|
|
806
|
-
// Effectively remove account from the group and state.
|
|
777
|
+
const previousSelectedAccountGroup = this.state.accountTree.selectedAccountGroup;
|
|
778
|
+
let selectedAccountGroupChanged = false;
|
|
779
|
+
this.update((state) => {
|
|
780
|
+
const accounts = state.accountTree.wallets[walletId]?.groups[groupId]?.accounts;
|
|
781
|
+
if (accounts) {
|
|
782
|
+
const index = accounts.indexOf(accountId);
|
|
783
|
+
if (index !== -1) {
|
|
807
784
|
accounts.splice(index, 1);
|
|
808
|
-
//
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
//
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
newSelectedAccountGroup;
|
|
817
|
-
selectedAccountGroupChanged =
|
|
818
|
-
newSelectedAccountGroup !== previousSelectedAccountGroup;
|
|
819
|
-
}
|
|
820
|
-
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_pruneEmptyGroupAndWallet).call(this, state, walletId, groupId);
|
|
785
|
+
// Check if we need to update selectedAccountGroup after removal
|
|
786
|
+
if (state.accountTree.selectedAccountGroup === groupId &&
|
|
787
|
+
accounts.length === 0) {
|
|
788
|
+
// The currently selected group is now empty, find a new group to select
|
|
789
|
+
const newSelectedAccountGroup = __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getDefaultAccountGroupId).call(this, state.accountTree.wallets);
|
|
790
|
+
state.accountTree.selectedAccountGroup = newSelectedAccountGroup;
|
|
791
|
+
selectedAccountGroupChanged =
|
|
792
|
+
newSelectedAccountGroup !== previousSelectedAccountGroup;
|
|
821
793
|
}
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
if (selectedAccountGroupChanged) {
|
|
826
|
-
this.messenger.publish(`${controllerName}:selectedAccountGroupChange`, this.state.accountTree.selectedAccountGroup, previousSelectedAccountGroup);
|
|
794
|
+
}
|
|
795
|
+
if (accounts.length === 0) {
|
|
796
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_pruneEmptyGroupAndWallet).call(this, state, walletId, groupId);
|
|
827
797
|
}
|
|
828
798
|
}
|
|
799
|
+
});
|
|
800
|
+
this.messenger.publish(`${controllerName}:accountTreeChange`, this.state.accountTree);
|
|
801
|
+
// Emit selectedAccountGroupChange event if the selected group changed
|
|
802
|
+
if (selectedAccountGroupChanged) {
|
|
803
|
+
this.messenger.publish(`${controllerName}:selectedAccountGroupChange`, this.state.accountTree.selectedAccountGroup, previousSelectedAccountGroup);
|
|
829
804
|
}
|
|
830
805
|
// Clear reverse-mapping for that account.
|
|
831
806
|
__classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").delete(accountId);
|
|
@@ -842,23 +817,9 @@ _AccountTreeController_accountIdToContext = new WeakMap(), _AccountTreeControlle
|
|
|
842
817
|
delete state.accountWalletsMetadata[walletId];
|
|
843
818
|
}
|
|
844
819
|
return state;
|
|
845
|
-
},
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
* and return attribution vary across engines; final ordering is covered
|
|
849
|
-
* by behavior tests. Ignoring the entire comparator avoids flaky line
|
|
850
|
-
* coverage without reducing scenario coverage.
|
|
851
|
-
*/
|
|
852
|
-
(a, b) => {
|
|
853
|
-
const aSortOrder = __classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").get(a)?.sortOrder;
|
|
854
|
-
const bSortOrder = __classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").get(b)?.sortOrder;
|
|
855
|
-
return (aSortOrder ?? MAX_SORT_ORDER) - (bSortOrder ?? MAX_SORT_ORDER);
|
|
856
|
-
});
|
|
857
|
-
}, _AccountTreeController_insertAccount = function _AccountTreeController_insertAccount(wallets, account) {
|
|
858
|
-
// Those are owned by the `MultichainAccountService`, so they should be already handled
|
|
859
|
-
// by `#insertOrUpdateMultichainAccountWalletAndGroup` method.
|
|
860
|
-
assert(!isBip44Account(account), 'BIP-44 accounts cannot be inserted explicitly');
|
|
861
|
-
const result = __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getSnapRule).call(this).match(account) ??
|
|
820
|
+
}, _AccountTreeController_insert = function _AccountTreeController_insert(wallets, account) {
|
|
821
|
+
const result = __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getEntropyRule).call(this).match(account) ??
|
|
822
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getSnapRule).call(this).match(account) ??
|
|
862
823
|
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getKeyringRule).call(this).match(account); // This one cannot fail.
|
|
863
824
|
// Update controller's state.
|
|
864
825
|
const walletId = result.wallet.id;
|
|
@@ -877,119 +838,62 @@ _AccountTreeController_accountIdToContext = new WeakMap(), _AccountTreeControlle
|
|
|
877
838
|
// the union tag `result.wallet.type`.
|
|
878
839
|
};
|
|
879
840
|
wallet = wallets[walletId];
|
|
841
|
+
// Trigger atomic sync for new wallet (only for entropy wallets)
|
|
842
|
+
if (wallet.type === AccountWalletType.Entropy) {
|
|
843
|
+
__classPrivateFieldGet(this, _AccountTreeController_backupAndSyncService, "f").enqueueSingleWalletSync(walletId);
|
|
844
|
+
}
|
|
880
845
|
}
|
|
881
846
|
const groupId = result.group.id;
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
const group = {
|
|
886
|
-
...result.group,
|
|
887
|
-
// Type-wise, we are guaranteed to always have at least 1 account.
|
|
888
|
-
accounts: [account.id],
|
|
889
|
-
metadata: {
|
|
890
|
-
name: '',
|
|
891
|
-
...{ pinned: false, hidden: false },
|
|
892
|
-
...result.group.metadata, // Allow rules to override defaults
|
|
893
|
-
},
|
|
894
|
-
// We do need to type-cast since we're not narrowing `result` with
|
|
895
|
-
// the union tag `result.group.type`.
|
|
896
|
-
};
|
|
897
|
-
wallet.groups[groupId] = group;
|
|
898
|
-
// Map group ID to its containing wallet ID for efficient direct access
|
|
899
|
-
__classPrivateFieldGet(this, _AccountTreeController_groupIdToWalletId, "f").set(groupId, walletId);
|
|
900
|
-
log(`[${groupId}] Add new account: { id: "${account.id}", type: "${account.type}", address: "${account.address}"`);
|
|
901
|
-
// Update the reverse mapping for this account.
|
|
902
|
-
__classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").set(account.id, {
|
|
903
|
-
walletId: wallet.id,
|
|
904
|
-
groupId: group.id,
|
|
905
|
-
sortOrder: ACCOUNT_TYPE_TO_SORT_ORDER[account.type],
|
|
906
|
-
});
|
|
907
|
-
// We need to do this at every insertion because race conditions can happen
|
|
908
|
-
// during the account creation process where one provider completes before the other.
|
|
909
|
-
// The discovery process in the service can also lead to some accounts being created "out of order".
|
|
910
|
-
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_sortAccountsOfGroup).call(this, group);
|
|
911
|
-
}, _AccountTreeController_insertOrUpdateMultichainAccountWalletAndGroup = function _AccountTreeController_insertOrUpdateMultichainAccountWalletAndGroup(wallets, multichainAccountWallet, multichainAccountGroup) {
|
|
912
|
-
const walletId = multichainAccountWallet.id;
|
|
913
|
-
const groupId = multichainAccountGroup.id;
|
|
914
|
-
let wallet = null;
|
|
915
|
-
let group = null;
|
|
916
|
-
// Check type, mainly to infer proper wallet object type.
|
|
917
|
-
const walletObject = wallets[walletId];
|
|
918
|
-
if (walletObject && walletObject.type === AccountWalletType.Entropy) {
|
|
919
|
-
wallet = walletObject;
|
|
920
|
-
group = wallet.groups[groupId];
|
|
921
|
-
}
|
|
922
|
-
// We always re-use the account list from the group (if accounts get
|
|
923
|
-
// added/removed/re-ordered within the group).
|
|
924
|
-
const accounts = multichainAccountGroup.getAccounts();
|
|
925
|
-
const accountIds = accounts
|
|
926
|
-
// For now, we need this type-cast because `getAccounts` do not have the same
|
|
927
|
-
// type-constraint (uses string[] instead of [string; ...string])
|
|
928
|
-
.map((account) => account.id);
|
|
929
|
-
// Create the group object first, to inject it in the wallet in case this wallet is
|
|
930
|
-
// not part of the tree yet.
|
|
847
|
+
let group = wallet.groups[groupId];
|
|
848
|
+
const { type, id } = account;
|
|
849
|
+
const sortOrder = ACCOUNT_TYPE_TO_SORT_ORDER[type];
|
|
931
850
|
if (!group) {
|
|
932
|
-
group
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
851
|
+
log(`[${walletId}] Add new group: [${groupId}]`);
|
|
852
|
+
wallet.groups[groupId] = {
|
|
853
|
+
...result.group,
|
|
854
|
+
// Type-wise, we are guaranteed to always have at least 1 account.
|
|
855
|
+
accounts: [id],
|
|
936
856
|
metadata: {
|
|
937
|
-
entropy: {
|
|
938
|
-
groupIndex: multichainAccountGroup.groupIndex,
|
|
939
|
-
},
|
|
940
857
|
name: '',
|
|
941
|
-
pinned: false,
|
|
942
|
-
|
|
943
|
-
},
|
|
944
|
-
};
|
|
945
|
-
}
|
|
946
|
-
else {
|
|
947
|
-
// We clear existing contexts for previous accounts of that group because:
|
|
948
|
-
// - Accounts might have been removed
|
|
949
|
-
// - Accounts context mapping will get updated below
|
|
950
|
-
group.accounts.forEach((accountId) => __classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").delete(accountId));
|
|
951
|
-
group.accounts = accountIds;
|
|
952
|
-
}
|
|
953
|
-
if (!wallet) {
|
|
954
|
-
wallet = {
|
|
955
|
-
id: multichainAccountWallet.id,
|
|
956
|
-
type: multichainAccountWallet.type,
|
|
957
|
-
status: multichainAccountWallet.status,
|
|
958
|
-
groups: {
|
|
959
|
-
[group.id]: group,
|
|
960
|
-
},
|
|
961
|
-
metadata: {
|
|
962
|
-
entropy: {
|
|
963
|
-
id: multichainAccountWallet.entropySource,
|
|
964
|
-
},
|
|
965
|
-
name: '', // Will get updated later.
|
|
858
|
+
...{ pinned: false, hidden: false },
|
|
859
|
+
...result.group.metadata, // Allow rules to override defaults
|
|
966
860
|
},
|
|
861
|
+
// We do need to type-cast since we're not narrowing `result` with
|
|
862
|
+
// the union tag `result.group.type`.
|
|
967
863
|
};
|
|
968
|
-
|
|
969
|
-
//
|
|
970
|
-
__classPrivateFieldGet(this,
|
|
864
|
+
group = wallet.groups[groupId];
|
|
865
|
+
// Map group ID to its containing wallet ID for efficient direct access
|
|
866
|
+
__classPrivateFieldGet(this, _AccountTreeController_groupIdToWalletId, "f").set(groupId, walletId);
|
|
867
|
+
// Trigger atomic sync for new group (only for entropy wallets)
|
|
868
|
+
if (wallet.type === AccountWalletType.Entropy) {
|
|
869
|
+
__classPrivateFieldGet(this, _AccountTreeController_backupAndSyncService, "f").enqueueSingleGroupSync(groupId);
|
|
870
|
+
}
|
|
971
871
|
}
|
|
972
872
|
else {
|
|
973
|
-
|
|
974
|
-
//
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
873
|
+
group.accounts.push(id);
|
|
874
|
+
// We need to do this at every insertion because race conditions can happen
|
|
875
|
+
// during the account creation process where one provider completes before the other.
|
|
876
|
+
// The discovery process in the service can also lead to some accounts being created "out of order".
|
|
877
|
+
const { accounts } = group;
|
|
878
|
+
accounts.sort(
|
|
879
|
+
/* istanbul ignore next: Comparator branch execution (a===id vs b===id)
|
|
880
|
+
* and return attribution vary across engines; final ordering is covered
|
|
881
|
+
* by behavior tests. Ignoring the entire comparator avoids flaky line
|
|
882
|
+
* coverage without reducing scenario coverage.
|
|
883
|
+
*/
|
|
884
|
+
(a, b) => {
|
|
885
|
+
const aSortOrder = a === id ? sortOrder : __classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").get(a)?.sortOrder;
|
|
886
|
+
const bSortOrder = b === id ? sortOrder : __classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").get(b)?.sortOrder;
|
|
887
|
+
return ((aSortOrder ?? MAX_SORT_ORDER) - (bSortOrder ?? MAX_SORT_ORDER));
|
|
985
888
|
});
|
|
986
889
|
}
|
|
987
|
-
|
|
988
|
-
//
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
890
|
+
log(`[${groupId}] Add new account: { id: "${account.id}", type: "${account.type}", address: "${account.address}"`);
|
|
891
|
+
// Update the reverse mapping for this account.
|
|
892
|
+
__classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").set(account.id, {
|
|
893
|
+
walletId: wallet.id,
|
|
894
|
+
groupId: group.id,
|
|
895
|
+
sortOrder,
|
|
896
|
+
});
|
|
993
897
|
}, _AccountTreeController_listAccounts = function _AccountTreeController_listAccounts() {
|
|
994
898
|
return this.messenger.call('AccountsController:listMultichainAccounts');
|
|
995
899
|
}, _AccountTreeController_assertAccountGroupExists = function _AccountTreeController_assertAccountGroupExists(groupId) {
|
|
@@ -1034,25 +938,6 @@ _AccountTreeController_accountIdToContext = new WeakMap(), _AccountTreeControlle
|
|
|
1034
938
|
state.accountTree.selectedAccountGroup = groupId;
|
|
1035
939
|
});
|
|
1036
940
|
this.messenger.publish(`${controllerName}:selectedAccountGroupChange`, groupId, previousSelectedAccountGroup);
|
|
1037
|
-
}, _AccountTreeController_handleMultichainAccountGroupCreatedOrUpdated = function _AccountTreeController_handleMultichainAccountGroupCreatedOrUpdated(multichainAccountGroup) {
|
|
1038
|
-
// We wait for the first `init` to be called to actually build up the tree and
|
|
1039
|
-
// mutate it. We expect the caller to first update the `AccountsController` state
|
|
1040
|
-
// to force the migration of accounts, and then call `init`.
|
|
1041
|
-
if (!__classPrivateFieldGet(this, _AccountTreeController_initialized, "f")) {
|
|
1042
|
-
return;
|
|
1043
|
-
}
|
|
1044
|
-
this.update((state) => {
|
|
1045
|
-
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_insertOrUpdateMultichainAccountWalletAndGroup).call(this, state.accountTree.wallets, multichainAccountGroup.wallet, multichainAccountGroup);
|
|
1046
|
-
const wallet = state.accountTree.wallets[multichainAccountGroup.wallet.id];
|
|
1047
|
-
if (wallet) {
|
|
1048
|
-
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_applyAccountWalletMetadata).call(this, state, wallet.id);
|
|
1049
|
-
const group = wallet.groups[multichainAccountGroup.id];
|
|
1050
|
-
if (group) {
|
|
1051
|
-
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_applyAccountGroupMetadata).call(this, state, wallet.id, group.id);
|
|
1052
|
-
}
|
|
1053
|
-
}
|
|
1054
|
-
});
|
|
1055
|
-
this.messenger.publish(`${controllerName}:accountTreeChange`, this.state.accountTree);
|
|
1056
941
|
}, _AccountTreeController_handleMultichainAccountWalletStatusChange = function _AccountTreeController_handleMultichainAccountWalletStatusChange(walletId, walletStatus) {
|
|
1057
942
|
this.update((state) => {
|
|
1058
943
|
const wallet = state.accountTree.wallets[walletId];
|