@metamask-previews/account-tree-controller 0.6.0-preview-bd86fa14 → 0.7.0-preview-3f5f144a

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.
Files changed (120) hide show
  1. package/CHANGELOG.md +21 -1
  2. package/dist/AccountTreeController.cjs +195 -41
  3. package/dist/AccountTreeController.cjs.map +1 -1
  4. package/dist/AccountTreeController.d.cts +31 -40
  5. package/dist/AccountTreeController.d.cts.map +1 -1
  6. package/dist/AccountTreeController.d.mts +31 -40
  7. package/dist/AccountTreeController.d.mts.map +1 -1
  8. package/dist/AccountTreeController.mjs +193 -39
  9. package/dist/AccountTreeController.mjs.map +1 -1
  10. package/dist/AccountTreeGroup.cjs +44 -35
  11. package/dist/AccountTreeGroup.cjs.map +1 -1
  12. package/dist/AccountTreeGroup.d.cts +15 -22
  13. package/dist/AccountTreeGroup.d.cts.map +1 -1
  14. package/dist/AccountTreeGroup.d.mts +15 -22
  15. package/dist/AccountTreeGroup.d.mts.map +1 -1
  16. package/dist/AccountTreeGroup.mjs +42 -33
  17. package/dist/AccountTreeGroup.mjs.map +1 -1
  18. package/dist/AccountTreeRule.cjs +37 -0
  19. package/dist/AccountTreeRule.cjs.map +1 -0
  20. package/dist/AccountTreeRule.d.cts +53 -0
  21. package/dist/AccountTreeRule.d.cts.map +1 -0
  22. package/dist/AccountTreeRule.d.mts +53 -0
  23. package/dist/AccountTreeRule.d.mts.map +1 -0
  24. package/dist/AccountTreeRule.mjs +33 -0
  25. package/dist/AccountTreeRule.mjs.map +1 -0
  26. package/dist/AccountTreeWallet.cjs +53 -26
  27. package/dist/AccountTreeWallet.cjs.map +1 -1
  28. package/dist/AccountTreeWallet.d.cts +26 -21
  29. package/dist/AccountTreeWallet.d.cts.map +1 -1
  30. package/dist/AccountTreeWallet.d.mts +26 -21
  31. package/dist/AccountTreeWallet.d.mts.map +1 -1
  32. package/dist/AccountTreeWallet.mjs +52 -25
  33. package/dist/AccountTreeWallet.mjs.map +1 -1
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +1 -1
  36. package/dist/index.d.cts.map +1 -1
  37. package/dist/index.d.mts +1 -1
  38. package/dist/index.d.mts.map +1 -1
  39. package/dist/index.mjs.map +1 -1
  40. package/dist/rules/entropy.cjs +68 -0
  41. package/dist/rules/entropy.cjs.map +1 -0
  42. package/dist/rules/entropy.d.cts +13 -0
  43. package/dist/rules/entropy.d.cts.map +1 -0
  44. package/dist/rules/entropy.d.mts +13 -0
  45. package/dist/rules/entropy.d.mts.map +1 -0
  46. package/dist/rules/entropy.mjs +64 -0
  47. package/dist/rules/entropy.mjs.map +1 -0
  48. package/dist/rules/keyring.cjs +86 -0
  49. package/dist/rules/keyring.cjs.map +1 -0
  50. package/dist/rules/keyring.d.cts +21 -0
  51. package/dist/rules/keyring.d.cts.map +1 -0
  52. package/dist/rules/keyring.d.mts +21 -0
  53. package/dist/rules/keyring.d.mts.map +1 -0
  54. package/dist/rules/keyring.mjs +81 -0
  55. package/dist/rules/keyring.mjs.map +1 -0
  56. package/dist/rules/snap.cjs +58 -0
  57. package/dist/rules/snap.cjs.map +1 -0
  58. package/dist/rules/snap.d.cts +22 -0
  59. package/dist/rules/snap.d.cts.map +1 -0
  60. package/dist/rules/snap.d.mts +22 -0
  61. package/dist/rules/snap.d.mts.map +1 -0
  62. package/dist/rules/snap.mjs +54 -0
  63. package/dist/rules/snap.mjs.map +1 -0
  64. package/dist/types.cjs +3 -0
  65. package/dist/types.cjs.map +1 -0
  66. package/dist/types.d.cts +83 -0
  67. package/dist/types.d.cts.map +1 -0
  68. package/dist/types.d.mts +83 -0
  69. package/dist/types.d.mts.map +1 -0
  70. package/dist/types.mjs +2 -0
  71. package/dist/types.mjs.map +1 -0
  72. package/package.json +4 -4
  73. package/dist/rules/EntropySourceWalletRule.cjs +0 -100
  74. package/dist/rules/EntropySourceWalletRule.cjs.map +0 -1
  75. package/dist/rules/EntropySourceWalletRule.d.cts +0 -19
  76. package/dist/rules/EntropySourceWalletRule.d.cts.map +0 -1
  77. package/dist/rules/EntropySourceWalletRule.d.mts +0 -19
  78. package/dist/rules/EntropySourceWalletRule.d.mts.map +0 -1
  79. package/dist/rules/EntropySourceWalletRule.mjs +0 -95
  80. package/dist/rules/EntropySourceWalletRule.mjs.map +0 -1
  81. package/dist/rules/KeyringWalletRule.cjs +0 -99
  82. package/dist/rules/KeyringWalletRule.cjs.map +0 -1
  83. package/dist/rules/KeyringWalletRule.d.cts +0 -18
  84. package/dist/rules/KeyringWalletRule.d.cts.map +0 -1
  85. package/dist/rules/KeyringWalletRule.d.mts +0 -18
  86. package/dist/rules/KeyringWalletRule.d.mts.map +0 -1
  87. package/dist/rules/KeyringWalletRule.mjs +0 -94
  88. package/dist/rules/KeyringWalletRule.mjs.map +0 -1
  89. package/dist/rules/SnapWalletRule.cjs +0 -70
  90. package/dist/rules/SnapWalletRule.cjs.map +0 -1
  91. package/dist/rules/SnapWalletRule.d.cts +0 -10
  92. package/dist/rules/SnapWalletRule.d.cts.map +0 -1
  93. package/dist/rules/SnapWalletRule.d.mts +0 -10
  94. package/dist/rules/SnapWalletRule.d.mts.map +0 -1
  95. package/dist/rules/SnapWalletRule.mjs +0 -66
  96. package/dist/rules/SnapWalletRule.mjs.map +0 -1
  97. package/dist/rules/WalletRule.cjs +0 -13
  98. package/dist/rules/WalletRule.cjs.map +0 -1
  99. package/dist/rules/WalletRule.d.cts +0 -37
  100. package/dist/rules/WalletRule.d.cts.map +0 -1
  101. package/dist/rules/WalletRule.d.mts +0 -37
  102. package/dist/rules/WalletRule.d.mts.map +0 -1
  103. package/dist/rules/WalletRule.mjs +0 -9
  104. package/dist/rules/WalletRule.mjs.map +0 -1
  105. package/dist/rules/index.cjs +0 -21
  106. package/dist/rules/index.cjs.map +0 -1
  107. package/dist/rules/index.d.cts +0 -5
  108. package/dist/rules/index.d.cts.map +0 -1
  109. package/dist/rules/index.d.mts +0 -5
  110. package/dist/rules/index.d.mts.map +0 -1
  111. package/dist/rules/index.mjs +0 -5
  112. package/dist/rules/index.mjs.map +0 -1
  113. package/dist/rules/utils.cjs +0 -15
  114. package/dist/rules/utils.cjs.map +0 -1
  115. package/dist/rules/utils.d.cts +0 -11
  116. package/dist/rules/utils.d.cts.map +0 -1
  117. package/dist/rules/utils.d.mts +0 -11
  118. package/dist/rules/utils.d.mts.map +0 -1
  119. package/dist/rules/utils.mjs +0 -11
  120. package/dist/rules/utils.mjs.map +0 -1
@@ -9,10 +9,14 @@ 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_reverse, _AccountTreeController_rules, _AccountTreeController_wallets, _AccountTreeController_handleAccountAdded, _AccountTreeController_handleAccountRemoved, _AccountTreeController_insert, _AccountTreeController_listAccounts;
12
+ var _AccountTreeController_instances, _AccountTreeController_accountIdToContext, _AccountTreeController_rules, _AccountTreeController_categoryToRule, _AccountTreeController_getDefaultSelectedAccountGroup, _AccountTreeController_renameAccountWalletIfNeeded, _AccountTreeController_renameAccountGroupIfNeeded, _AccountTreeController_handleAccountAdded, _AccountTreeController_handleAccountRemoved, _AccountTreeController_insert, _AccountTreeController_listAccounts, _AccountTreeController_handleSelectedAccountChange, _AccountTreeController_getFirstAccountInGroup, _AccountTreeController_findFirstNonEmptyGroup, _AccountTreeController_registerMessageHandlers;
13
+ import { AccountWalletCategory } from "@metamask/account-api";
13
14
  import { BaseController } from "@metamask/base-controller";
14
- import { EntropySourceWalletRule, SnapWalletRule, KeyringWalletRule } from "./rules/index.mjs";
15
- const controllerName = 'AccountTreeController';
15
+ import { AccountTreeWallet } from "./AccountTreeWallet.mjs";
16
+ import { EntropyRule } from "./rules/entropy.mjs";
17
+ import { KeyringRule } from "./rules/keyring.mjs";
18
+ import { SnapRule } from "./rules/snap.mjs";
19
+ export const controllerName = 'AccountTreeController';
16
20
  const accountTreeControllerMetadata = {
17
21
  accountTree: {
18
22
  persist: false,
@@ -28,6 +32,7 @@ export function getDefaultAccountTreeControllerState() {
28
32
  return {
29
33
  accountTree: {
30
34
  wallets: {},
35
+ selectedAccountGroup: '',
31
36
  },
32
37
  };
33
38
  }
@@ -50,20 +55,24 @@ export class AccountTreeController extends BaseController {
50
55
  },
51
56
  });
52
57
  _AccountTreeController_instances.add(this);
53
- _AccountTreeController_reverse.set(this, void 0);
58
+ _AccountTreeController_accountIdToContext.set(this, void 0);
54
59
  _AccountTreeController_rules.set(this, void 0);
55
- _AccountTreeController_wallets.set(this, void 0);
56
- __classPrivateFieldSet(this, _AccountTreeController_wallets, new Map(), "f");
60
+ _AccountTreeController_categoryToRule.set(this, void 0);
57
61
  // Reverse map to allow fast node access from an account ID.
58
- __classPrivateFieldSet(this, _AccountTreeController_reverse, new Map(), "f");
62
+ __classPrivateFieldSet(this, _AccountTreeController_accountIdToContext, new Map(), "f");
59
63
  // Rules to apply to construct the wallets tree.
64
+ __classPrivateFieldSet(this, _AccountTreeController_categoryToRule, {
65
+ [AccountWalletCategory.Entropy]: new EntropyRule(this.messagingSystem),
66
+ [AccountWalletCategory.Snap]: new SnapRule(this.messagingSystem),
67
+ [AccountWalletCategory.Keyring]: new KeyringRule(this.messagingSystem),
68
+ }, "f");
60
69
  __classPrivateFieldSet(this, _AccountTreeController_rules, [
61
70
  // 1. We group by entropy-source
62
- new EntropySourceWalletRule(this.messagingSystem),
71
+ __classPrivateFieldGet(this, _AccountTreeController_categoryToRule, "f")[AccountWalletCategory.Entropy],
63
72
  // 2. We group by Snap ID
64
- new SnapWalletRule(this.messagingSystem),
73
+ __classPrivateFieldGet(this, _AccountTreeController_categoryToRule, "f")[AccountWalletCategory.Snap],
65
74
  // 3. We group by wallet type (this rule cannot fail and will group all non-matching accounts)
66
- new KeyringWalletRule(this.messagingSystem),
75
+ __classPrivateFieldGet(this, _AccountTreeController_categoryToRule, "f")[AccountWalletCategory.Keyring],
67
76
  ], "f");
68
77
  this.messagingSystem.subscribe('AccountsController:accountAdded', (account) => {
69
78
  __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_handleAccountAdded).call(this, account);
@@ -71,6 +80,10 @@ export class AccountTreeController extends BaseController {
71
80
  this.messagingSystem.subscribe('AccountsController:accountRemoved', (accountId) => {
72
81
  __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_handleAccountRemoved).call(this, accountId);
73
82
  });
83
+ this.messagingSystem.subscribe('AccountsController:selectedAccountChange', (account) => {
84
+ __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_handleSelectedAccountChange).call(this, account);
85
+ });
86
+ __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_registerMessageHandlers).call(this);
74
87
  }
75
88
  init() {
76
89
  const wallets = {};
@@ -78,62 +91,165 @@ export class AccountTreeController extends BaseController {
78
91
  for (const account of __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_listAccounts).call(this)) {
79
92
  __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_insert).call(this, wallets, account);
80
93
  }
94
+ // Once we have the account tree, we can compute the name.
95
+ for (const wallet of Object.values(wallets)) {
96
+ __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_renameAccountWalletIfNeeded).call(this, wallet);
97
+ for (const group of Object.values(wallet.groups)) {
98
+ __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_renameAccountGroupIfNeeded).call(this, wallet, group);
99
+ }
100
+ }
81
101
  this.update((state) => {
82
102
  state.accountTree.wallets = wallets;
103
+ if (state.accountTree.selectedAccountGroup === '') {
104
+ // No group is selected yet, re-sync with the AccountsController.
105
+ state.accountTree.selectedAccountGroup =
106
+ __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getDefaultSelectedAccountGroup).call(this, wallets);
107
+ }
83
108
  });
84
109
  }
85
- getWallet(id) {
86
- return __classPrivateFieldGet(this, _AccountTreeController_wallets, "f").get(id);
110
+ getAccountWallet(walletId) {
111
+ const wallet = this.state.accountTree.wallets[walletId];
112
+ if (!wallet) {
113
+ return undefined;
114
+ }
115
+ return new AccountTreeWallet({ messenger: this.messagingSystem, wallet });
87
116
  }
88
- getWallets() {
89
- return Array.from(__classPrivateFieldGet(this, _AccountTreeController_wallets, "f").values());
117
+ getAccountWallets() {
118
+ return Object.values(this.state.accountTree.wallets).map((wallet) => {
119
+ return new AccountTreeWallet({ messenger: this.messagingSystem, wallet });
120
+ });
121
+ }
122
+ /**
123
+ * Gets the currently selected account group ID.
124
+ *
125
+ * @returns The selected account group ID or empty string if none selected.
126
+ */
127
+ getSelectedAccountGroup() {
128
+ return this.state.accountTree.selectedAccountGroup;
129
+ }
130
+ /**
131
+ * Sets the selected account group and updates the AccountsController selectedAccount accordingly.
132
+ *
133
+ * @param groupId - The account group ID to select.
134
+ */
135
+ setSelectedAccountGroup(groupId) {
136
+ const currentSelectedGroup = this.state.accountTree.selectedAccountGroup;
137
+ // Idempotent check - if the same group is already selected, do nothing
138
+ if (currentSelectedGroup === groupId) {
139
+ return;
140
+ }
141
+ // Find the first account in this group to select
142
+ const accountToSelect = __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getFirstAccountInGroup).call(this, groupId);
143
+ if (!accountToSelect) {
144
+ throw new Error(`No accounts found in group: ${groupId}`);
145
+ }
146
+ // Update our state first
147
+ this.update((state) => {
148
+ state.accountTree.selectedAccountGroup = groupId;
149
+ });
150
+ // Update AccountsController - this will trigger selectedAccountChange event,
151
+ // but our handler is idempotent so it won't cause infinite loop
152
+ this.messagingSystem.call('AccountsController:setSelectedAccount', accountToSelect);
90
153
  }
91
154
  }
92
- _AccountTreeController_reverse = new WeakMap(), _AccountTreeController_rules = new WeakMap(), _AccountTreeController_wallets = new WeakMap(), _AccountTreeController_instances = new WeakSet(), _AccountTreeController_handleAccountAdded = function _AccountTreeController_handleAccountAdded(account) {
155
+ _AccountTreeController_accountIdToContext = new WeakMap(), _AccountTreeController_rules = new WeakMap(), _AccountTreeController_categoryToRule = new WeakMap(), _AccountTreeController_instances = new WeakSet(), _AccountTreeController_getDefaultSelectedAccountGroup = function _AccountTreeController_getDefaultSelectedAccountGroup(wallets) {
156
+ const selectedAccount = this.messagingSystem.call('AccountsController:getSelectedAccount');
157
+ if (selectedAccount && selectedAccount.id) {
158
+ const accountMapping = __classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").get(selectedAccount.id);
159
+ if (accountMapping) {
160
+ const { groupId } = accountMapping;
161
+ return groupId;
162
+ }
163
+ }
164
+ // Default to the first non-empty group in case of errors.
165
+ return __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_findFirstNonEmptyGroup).call(this, wallets);
166
+ }, _AccountTreeController_renameAccountWalletIfNeeded = function _AccountTreeController_renameAccountWalletIfNeeded(wallet) {
167
+ if (wallet.metadata.name) {
168
+ return;
169
+ }
170
+ const rule = __classPrivateFieldGet(this, _AccountTreeController_categoryToRule, "f")[wallet.metadata.type];
171
+ wallet.metadata.name = rule.getDefaultAccountWalletName(wallet);
172
+ }, _AccountTreeController_renameAccountGroupIfNeeded = function _AccountTreeController_renameAccountGroupIfNeeded(wallet, group) {
173
+ if (group.metadata.name) {
174
+ return;
175
+ }
176
+ const rule = __classPrivateFieldGet(this, _AccountTreeController_categoryToRule, "f")[wallet.metadata.type];
177
+ group.metadata.name = rule.getDefaultAccountGroupName(group);
178
+ }, _AccountTreeController_handleAccountAdded = function _AccountTreeController_handleAccountAdded(account) {
93
179
  this.update((state) => {
94
180
  __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_insert).call(this, state.accountTree.wallets, account);
181
+ const context = __classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").get(account.id);
182
+ if (context) {
183
+ const { walletId, groupId } = context;
184
+ const wallet = state.accountTree.wallets[walletId];
185
+ if (wallet) {
186
+ __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_renameAccountWalletIfNeeded).call(this, wallet);
187
+ const group = wallet.groups[groupId];
188
+ if (group) {
189
+ __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_renameAccountGroupIfNeeded).call(this, wallet, group);
190
+ }
191
+ }
192
+ }
95
193
  });
96
194
  }, _AccountTreeController_handleAccountRemoved = function _AccountTreeController_handleAccountRemoved(accountId) {
97
- const found = __classPrivateFieldGet(this, _AccountTreeController_reverse, "f").get(accountId);
98
- if (found) {
99
- const { walletId, groupId } = found;
195
+ const context = __classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").get(accountId);
196
+ if (context) {
197
+ const { walletId, groupId } = context;
100
198
  this.update((state) => {
101
- const { accounts } = state.accountTree.wallets[walletId].groups[groupId];
102
- const index = accounts.indexOf(accountId);
103
- if (index !== -1) {
104
- accounts.splice(index, 1);
199
+ const accounts = state.accountTree.wallets[walletId]?.groups[groupId]?.accounts;
200
+ if (accounts) {
201
+ const index = accounts.indexOf(accountId);
202
+ if (index !== -1) {
203
+ accounts.splice(index, 1);
204
+ // Check if we need to update selectedAccountGroup after removal
205
+ if (state.accountTree.selectedAccountGroup === groupId &&
206
+ accounts.length === 0) {
207
+ // The currently selected group is now empty, find a new group to select
208
+ state.accountTree.selectedAccountGroup =
209
+ __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_findFirstNonEmptyGroup).call(this, state.accountTree.wallets);
210
+ }
211
+ }
105
212
  }
106
213
  });
214
+ // Clear reverse-mapping for that account.
215
+ __classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").delete(accountId);
107
216
  }
108
217
  }, _AccountTreeController_insert = function _AccountTreeController_insert(wallets, account) {
109
218
  for (const rule of __classPrivateFieldGet(this, _AccountTreeController_rules, "f")) {
110
- const match = rule.match(account);
111
- if (!match) {
219
+ const result = rule.match(account);
220
+ if (!result) {
112
221
  // No match for that rule, we go to the next one.
113
222
  continue;
114
223
  }
115
- const { wallet, group } = match;
116
- // Update in-memory wallet/group instances.
117
- __classPrivateFieldGet(this, _AccountTreeController_wallets, "f").set(wallet.id, wallet);
118
224
  // Update controller's state.
119
- if (!wallets[wallet.id]) {
120
- wallets[wallet.id] = {
121
- id: wallet.id,
122
- groups: {
123
- [group.id]: {
124
- id: group.id,
125
- accounts: [],
126
- metadata: { name: group.getDefaultName() },
127
- },
225
+ const walletId = result.wallet.id;
226
+ let wallet = wallets[walletId];
227
+ if (!wallet) {
228
+ wallets[walletId] = {
229
+ id: walletId,
230
+ groups: {},
231
+ metadata: {
232
+ name: '',
233
+ ...result.wallet.metadata,
128
234
  },
235
+ };
236
+ wallet = wallets[walletId];
237
+ }
238
+ const groupId = result.group.id;
239
+ let group = wallet.groups[groupId];
240
+ if (!group) {
241
+ wallet.groups[groupId] = {
242
+ id: groupId,
243
+ accounts: [],
129
244
  metadata: {
130
- name: wallet.getDefaultName(),
245
+ name: '', // Will get updated later.
131
246
  },
132
247
  };
248
+ group = wallet.groups[groupId];
133
249
  }
134
- wallets[wallet.id].groups[group.id].accounts.push(account.id);
250
+ group.accounts.push(account.id);
135
251
  // Update the reverse mapping for this account.
136
- __classPrivateFieldGet(this, _AccountTreeController_reverse, "f").set(account.id, {
252
+ __classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").set(account.id, {
137
253
  walletId: wallet.id,
138
254
  groupId: group.id,
139
255
  });
@@ -141,5 +257,43 @@ _AccountTreeController_reverse = new WeakMap(), _AccountTreeController_rules = n
141
257
  }
142
258
  }, _AccountTreeController_listAccounts = function _AccountTreeController_listAccounts() {
143
259
  return this.messagingSystem.call('AccountsController:listMultichainAccounts');
260
+ }, _AccountTreeController_handleSelectedAccountChange = function _AccountTreeController_handleSelectedAccountChange(account) {
261
+ const accountMapping = __classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").get(account.id);
262
+ if (!accountMapping) {
263
+ // Account not in tree yet, might be during initialization
264
+ return;
265
+ }
266
+ const { groupId } = accountMapping;
267
+ const currentSelectedGroup = this.state.accountTree.selectedAccountGroup;
268
+ // Idempotent check - if the same group is already selected, do nothing
269
+ if (currentSelectedGroup === groupId) {
270
+ return;
271
+ }
272
+ // Update selectedAccountGroup to match the selected account
273
+ this.update((state) => {
274
+ state.accountTree.selectedAccountGroup = groupId;
275
+ });
276
+ }, _AccountTreeController_getFirstAccountInGroup = function _AccountTreeController_getFirstAccountInGroup(groupId) {
277
+ for (const wallet of Object.values(this.state.accountTree.wallets)) {
278
+ if (wallet.groups[groupId]) {
279
+ const group = wallet.groups[groupId];
280
+ if (group && group.accounts.length > 0) {
281
+ return group.accounts[0];
282
+ }
283
+ }
284
+ }
285
+ return undefined;
286
+ }, _AccountTreeController_findFirstNonEmptyGroup = function _AccountTreeController_findFirstNonEmptyGroup(wallets) {
287
+ for (const wallet of Object.values(wallets)) {
288
+ for (const group of Object.values(wallet.groups)) {
289
+ if (group.accounts.length > 0) {
290
+ return group.id;
291
+ }
292
+ }
293
+ }
294
+ return '';
295
+ }, _AccountTreeController_registerMessageHandlers = function _AccountTreeController_registerMessageHandlers() {
296
+ this.messagingSystem.registerActionHandler(`${controllerName}:getSelectedAccountGroup`, this.getSelectedAccountGroup.bind(this));
297
+ this.messagingSystem.registerActionHandler(`${controllerName}:setSelectedAccountGroup`, this.setSelectedAccountGroup.bind(this));
144
298
  };
145
299
  //# sourceMappingURL=AccountTreeController.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"AccountTreeController.mjs","sourceRoot":"","sources":["../src/AccountTreeController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccountGroupId, AccountWalletId } from '@metamask/account-api';\nimport type {\n AccountId,\n AccountsControllerAccountAddedEvent,\n AccountsControllerAccountRemovedEvent,\n AccountsControllerGetAccountAction,\n AccountsControllerListMultichainAccountsAction,\n} from '@metamask/accounts-controller';\nimport type { StateMetadata } from '@metamask/base-controller';\nimport {\n type ControllerGetStateAction,\n type ControllerStateChangeEvent,\n type RestrictedMessenger,\n BaseController,\n} from '@metamask/base-controller';\nimport type { KeyringControllerGetStateAction } from '@metamask/keyring-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { GetSnap as SnapControllerGetSnap } from '@metamask/snaps-controllers';\n\nimport type { AccountTreeWallet } from './AccountTreeWallet';\nimport type { WalletRule } from './rules';\nimport {\n EntropySourceWalletRule,\n SnapWalletRule,\n KeyringWalletRule,\n} from './rules';\n\nconst controllerName = 'AccountTreeController';\n\ntype AccountReverseMapping = {\n walletId: AccountWalletId;\n groupId: AccountGroupId;\n};\n\n// Do not export this one, we just use it to have a common type interface between group and wallet metadata.\ntype Metadata = {\n name: string;\n};\n\nexport type AccountWalletMetadata = Metadata;\n\nexport type AccountGroupMetadata = Metadata;\n\nexport type AccountGroupObject = {\n id: AccountGroupId;\n // Blockchain Accounts:\n accounts: AccountId[];\n metadata: AccountGroupMetadata;\n};\n\nexport type AccountWalletObject = {\n id: AccountWalletId;\n // Account groups OR Multichain accounts (once available).\n groups: {\n [groupId: AccountGroupId]: AccountGroupObject;\n };\n metadata: AccountWalletMetadata;\n};\n\nexport type AccountTreeControllerState = {\n accountTree: {\n wallets: {\n // Wallets:\n [walletId: AccountWalletId]: AccountWalletObject;\n };\n };\n};\n\nexport type AccountTreeControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n AccountTreeControllerState\n>;\n\nexport type AllowedActions =\n | AccountsControllerGetAccountAction\n | AccountsControllerListMultichainAccountsAction\n | KeyringControllerGetStateAction\n | SnapControllerGetSnap;\n\nexport type AccountTreeControllerActions = never;\n\nexport type AccountTreeControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n AccountTreeControllerState\n>;\n\nexport type AllowedEvents =\n | AccountsControllerAccountAddedEvent\n | AccountsControllerAccountRemovedEvent;\n\nexport type AccountTreeControllerEvents = AccountTreeControllerStateChangeEvent;\n\nexport type AccountTreeControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n AccountTreeControllerActions | AllowedActions,\n AccountTreeControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\nconst accountTreeControllerMetadata: StateMetadata<AccountTreeControllerState> =\n {\n accountTree: {\n persist: false, // We do re-recompute this state everytime.\n anonymous: false,\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 };\n}\n\nexport class AccountTreeController extends BaseController<\n typeof controllerName,\n AccountTreeControllerState,\n AccountTreeControllerMessenger\n> {\n readonly #reverse: Map<AccountId, AccountReverseMapping>;\n\n readonly #rules: WalletRule[];\n\n readonly #wallets: Map<AccountWalletId, AccountTreeWallet>;\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 */\n constructor({\n messenger,\n state,\n }: {\n messenger: AccountTreeControllerMessenger;\n state?: Partial<AccountTreeControllerState>;\n }) {\n super({\n messenger,\n name: controllerName,\n metadata: accountTreeControllerMetadata,\n state: {\n ...getDefaultAccountTreeControllerState(),\n ...state,\n },\n });\n this.#wallets = new Map();\n\n // Reverse map to allow fast node access from an account ID.\n this.#reverse = new Map();\n\n // Rules to apply to construct the wallets tree.\n this.#rules = [\n // 1. We group by entropy-source\n new EntropySourceWalletRule(this.messagingSystem),\n // 2. We group by Snap ID\n new SnapWalletRule(this.messagingSystem),\n // 3. We group by wallet type (this rule cannot fail and will group all non-matching accounts)\n new KeyringWalletRule(this.messagingSystem),\n ];\n\n this.messagingSystem.subscribe(\n 'AccountsController:accountAdded',\n (account) => {\n this.#handleAccountAdded(account);\n },\n );\n\n this.messagingSystem.subscribe(\n 'AccountsController:accountRemoved',\n (accountId) => {\n this.#handleAccountRemoved(accountId);\n },\n );\n }\n\n init() {\n const wallets = {};\n\n // For now, we always re-compute all wallets, we do not re-use the existing state.\n for (const account of this.#listAccounts()) {\n this.#insert(wallets, account);\n }\n\n this.update((state) => {\n state.accountTree.wallets = wallets;\n });\n }\n\n getWallet(id: AccountWalletId): AccountTreeWallet | undefined {\n return this.#wallets.get(id);\n }\n\n getWallets(): AccountTreeWallet[] {\n return Array.from(this.#wallets.values());\n }\n\n #handleAccountAdded(account: InternalAccount) {\n this.update((state) => {\n this.#insert(state.accountTree.wallets, account);\n });\n }\n\n #handleAccountRemoved(accountId: AccountId) {\n const found = this.#reverse.get(accountId);\n\n if (found) {\n const { walletId, groupId } = found;\n this.update((state) => {\n const { accounts } =\n state.accountTree.wallets[walletId].groups[groupId];\n\n const index = accounts.indexOf(accountId);\n if (index !== -1) {\n accounts.splice(index, 1);\n }\n });\n }\n }\n\n #insert(\n wallets: { [walletId: AccountWalletId]: AccountWalletObject },\n account: InternalAccount,\n ) {\n for (const rule of this.#rules) {\n const match = rule.match(account);\n\n if (!match) {\n // No match for that rule, we go to the next one.\n continue;\n }\n\n const { wallet, group } = match;\n\n // Update in-memory wallet/group instances.\n this.#wallets.set(wallet.id, wallet);\n\n // Update controller's state.\n if (!wallets[wallet.id]) {\n wallets[wallet.id] = {\n id: wallet.id,\n groups: {\n [group.id]: {\n id: group.id,\n accounts: [],\n metadata: { name: group.getDefaultName() },\n },\n },\n metadata: {\n name: wallet.getDefaultName(),\n },\n };\n }\n wallets[wallet.id].groups[group.id].accounts.push(account.id);\n\n // Update the reverse mapping for this account.\n this.#reverse.set(account.id, {\n walletId: wallet.id,\n groupId: group.id,\n });\n\n return;\n }\n }\n\n #listAccounts(): InternalAccount[] {\n return this.messagingSystem.call(\n 'AccountsController:listMultichainAccounts',\n );\n }\n}\n"]}
1
+ {"version":3,"file":"AccountTreeController.mjs","sourceRoot":"","sources":["../src/AccountTreeController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AccountGroupId, AccountWalletId } from '@metamask/account-api';\nimport { AccountWalletCategory } 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 { InternalAccount } from '@metamask/keyring-internal-api';\n\nimport type { AccountTreeRule } from './AccountTreeRule';\nimport { AccountTreeWallet } from './AccountTreeWallet';\nimport { EntropyRule } from './rules/entropy';\nimport { KeyringRule } from './rules/keyring';\nimport { SnapRule } from './rules/snap';\nimport type {\n AccountGroupObject,\n AccountTreeControllerMessenger,\n AccountTreeControllerState,\n AccountWalletObject,\n} from './types';\n\nexport const controllerName = 'AccountTreeController';\n\nconst accountTreeControllerMetadata: StateMetadata<AccountTreeControllerState> =\n {\n accountTree: {\n persist: false, // We do re-recompute this state everytime.\n anonymous: false,\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 selectedAccountGroup: '',\n },\n };\n}\n\n/**\n * Context for an account.\n */\nexport type AccountContext = {\n /**\n * Wallet ID associated to that account.\n */\n walletId: AccountWalletId;\n\n /**\n * Account group ID associated to that account.\n */\n groupId: AccountGroupId;\n};\n\nexport class AccountTreeController extends BaseController<\n typeof controllerName,\n AccountTreeControllerState,\n AccountTreeControllerMessenger\n> {\n readonly #accountIdToContext: Map<AccountId, AccountContext>;\n\n readonly #rules: AccountTreeRule[];\n\n readonly #categoryToRule: Record<AccountWalletCategory, AccountTreeRule>;\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 */\n constructor({\n messenger,\n state,\n }: {\n messenger: AccountTreeControllerMessenger;\n state?: Partial<AccountTreeControllerState>;\n }) {\n super({\n messenger,\n name: controllerName,\n metadata: accountTreeControllerMetadata,\n state: {\n ...getDefaultAccountTreeControllerState(),\n ...state,\n },\n });\n\n // Reverse map to allow fast node access from an account ID.\n this.#accountIdToContext = new Map();\n\n // Rules to apply to construct the wallets tree.\n this.#categoryToRule = {\n [AccountWalletCategory.Entropy]: new EntropyRule(this.messagingSystem),\n [AccountWalletCategory.Snap]: new SnapRule(this.messagingSystem),\n [AccountWalletCategory.Keyring]: new KeyringRule(this.messagingSystem),\n } as const;\n this.#rules = [\n // 1. We group by entropy-source\n this.#categoryToRule[AccountWalletCategory.Entropy],\n // 2. We group by Snap ID\n this.#categoryToRule[AccountWalletCategory.Snap],\n // 3. We group by wallet type (this rule cannot fail and will group all non-matching accounts)\n this.#categoryToRule[AccountWalletCategory.Keyring],\n ];\n\n this.messagingSystem.subscribe(\n 'AccountsController:accountAdded',\n (account) => {\n this.#handleAccountAdded(account);\n },\n );\n\n this.messagingSystem.subscribe(\n 'AccountsController:accountRemoved',\n (accountId) => {\n this.#handleAccountRemoved(accountId);\n },\n );\n\n this.messagingSystem.subscribe(\n 'AccountsController:selectedAccountChange',\n (account) => {\n this.#handleSelectedAccountChange(account);\n },\n );\n\n this.#registerMessageHandlers();\n }\n\n init() {\n const wallets: AccountTreeControllerState['accountTree']['wallets'] = {};\n\n // For now, we always re-compute all wallets, we do not re-use the existing state.\n for (const account of this.#listAccounts()) {\n this.#insert(wallets, account);\n }\n\n // Once we have the account tree, we can compute the name.\n for (const wallet of Object.values(wallets)) {\n this.#renameAccountWalletIfNeeded(wallet);\n\n for (const group of Object.values(wallet.groups)) {\n this.#renameAccountGroupIfNeeded(wallet, group);\n }\n }\n\n this.update((state) => {\n state.accountTree.wallets = wallets;\n\n if (state.accountTree.selectedAccountGroup === '') {\n // No group is selected yet, re-sync with the AccountsController.\n state.accountTree.selectedAccountGroup =\n this.#getDefaultSelectedAccountGroup(wallets);\n }\n });\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.messagingSystem.call(\n 'AccountsController:getSelectedAccount',\n );\n if (selectedAccount && 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 first non-empty group in case of errors.\n return this.#findFirstNonEmptyGroup(wallets);\n }\n\n #renameAccountWalletIfNeeded(wallet: AccountWalletObject) {\n if (wallet.metadata.name) {\n return;\n }\n\n const rule = this.#categoryToRule[wallet.metadata.type];\n wallet.metadata.name = rule.getDefaultAccountWalletName(wallet);\n }\n\n #renameAccountGroupIfNeeded(\n wallet: AccountWalletObject,\n group: AccountGroupObject,\n ) {\n if (group.metadata.name) {\n return;\n }\n\n const rule = this.#categoryToRule[wallet.metadata.type];\n group.metadata.name = rule.getDefaultAccountGroupName(group);\n }\n\n getAccountWallet(walletId: AccountWalletId): AccountTreeWallet | undefined {\n const wallet = this.state.accountTree.wallets[walletId];\n if (!wallet) {\n return undefined;\n }\n\n return new AccountTreeWallet({ messenger: this.messagingSystem, wallet });\n }\n\n getAccountWallets(): AccountTreeWallet[] {\n return Object.values(this.state.accountTree.wallets).map((wallet) => {\n return new AccountTreeWallet({ messenger: this.messagingSystem, wallet });\n });\n }\n\n #handleAccountAdded(account: InternalAccount) {\n this.update((state) => {\n this.#insert(state.accountTree.wallets, account);\n\n const context = this.#accountIdToContext.get(account.id);\n if (context) {\n const { walletId, groupId } = context;\n\n const wallet = state.accountTree.wallets[walletId];\n if (wallet) {\n this.#renameAccountWalletIfNeeded(wallet);\n\n const group = wallet.groups[groupId];\n if (group) {\n this.#renameAccountGroupIfNeeded(wallet, group);\n }\n }\n }\n });\n }\n\n #handleAccountRemoved(accountId: AccountId) {\n const context = this.#accountIdToContext.get(accountId);\n\n if (context) {\n const { walletId, groupId } = context;\n\n this.update((state) => {\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 // Check if we need to update selectedAccountGroup after removal\n if (\n state.accountTree.selectedAccountGroup === groupId &&\n accounts.length === 0\n ) {\n // The currently selected group is now empty, find a new group to select\n state.accountTree.selectedAccountGroup =\n this.#findFirstNonEmptyGroup(state.accountTree.wallets);\n }\n }\n }\n });\n\n // Clear reverse-mapping for that account.\n this.#accountIdToContext.delete(accountId);\n }\n }\n\n #insert(\n wallets: AccountTreeControllerState['accountTree']['wallets'],\n account: InternalAccount,\n ) {\n for (const rule of this.#rules) {\n const result = rule.match(account);\n\n if (!result) {\n // No match for that rule, we go to the next one.\n continue;\n }\n\n // Update controller's state.\n const walletId = result.wallet.id;\n let wallet = wallets[walletId];\n if (!wallet) {\n wallets[walletId] = {\n id: walletId,\n groups: {},\n metadata: {\n name: '', // Will get updated later.\n ...result.wallet.metadata,\n },\n };\n wallet = wallets[walletId];\n }\n\n const groupId = result.group.id;\n let group = wallet.groups[groupId];\n if (!group) {\n wallet.groups[groupId] = {\n id: groupId,\n accounts: [],\n metadata: {\n name: '', // Will get updated later.\n },\n };\n group = wallet.groups[groupId];\n }\n\n group.accounts.push(account.id);\n\n // Update the reverse mapping for this account.\n this.#accountIdToContext.set(account.id, {\n walletId: wallet.id,\n groupId: group.id,\n });\n\n return;\n }\n }\n\n #listAccounts(): InternalAccount[] {\n return this.messagingSystem.call(\n 'AccountsController:listMultichainAccounts',\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.accountTree.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 */\n setSelectedAccountGroup(groupId: AccountGroupId): void {\n const currentSelectedGroup = this.state.accountTree.selectedAccountGroup;\n\n // Idempotent check - if the same group is already selected, do nothing\n if (currentSelectedGroup === groupId) {\n return;\n }\n\n // Find the first account in this group to select\n const accountToSelect = this.#getFirstAccountInGroup(groupId);\n if (!accountToSelect) {\n throw new Error(`No accounts found in group: ${groupId}`);\n }\n\n // Update our state first\n this.update((state) => {\n state.accountTree.selectedAccountGroup = groupId;\n });\n\n // Update AccountsController - this will trigger selectedAccountChange event,\n // but our handler is idempotent so it won't cause infinite loop\n this.messagingSystem.call(\n 'AccountsController:setSelectedAccount',\n accountToSelect,\n );\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 const currentSelectedGroup = this.state.accountTree.selectedAccountGroup;\n\n // Idempotent check - if the same group is already selected, do nothing\n if (currentSelectedGroup === groupId) {\n return;\n }\n\n // Update selectedAccountGroup to match the selected account\n this.update((state) => {\n state.accountTree.selectedAccountGroup = groupId;\n });\n }\n\n /**\n * Gets the first account ID in the specified group.\n *\n * @param groupId - The account group ID.\n * @returns The first account ID in the group, or undefined if no accounts found.\n */\n #getFirstAccountInGroup(groupId: AccountGroupId): AccountId | undefined {\n for (const wallet of Object.values(this.state.accountTree.wallets)) {\n if (wallet.groups[groupId]) {\n const group = wallet.groups[groupId];\n if (group && group.accounts.length > 0) {\n return group.accounts[0];\n }\n }\n }\n return undefined;\n }\n\n /**\n * Finds the first non-empty group in the given wallets object.\n *\n * @param wallets - The wallets object to search.\n * @returns The ID of the first non-empty group, or an empty string if no groups are found.\n */\n #findFirstNonEmptyGroup(wallets: {\n [walletId: AccountWalletId]: AccountWalletObject;\n }): AccountGroupId | '' {\n for (const wallet of Object.values(wallets)) {\n for (const group of Object.values(wallet.groups)) {\n if (group.accounts.length > 0) {\n return group.id;\n }\n }\n }\n return '';\n }\n\n /**\n * Registers message handlers for the AccountTreeController.\n */\n #registerMessageHandlers(): void {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getSelectedAccountGroup`,\n this.getSelectedAccountGroup.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:setSelectedAccountGroup`,\n this.setSelectedAccountGroup.bind(this),\n );\n }\n}\n"]}
@@ -10,49 +10,58 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  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");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _MutableAccountTreeGroup_accounts;
13
+ var _AccountTreeGroup_instances, _AccountTreeGroup_messenger, _AccountTreeGroup_group, _AccountTreeGroup_wallet, _AccountTreeGroup_getAccount;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.MutableAccountTreeGroup = exports.DEFAULT_ACCOUNT_GROUP_NAME = void 0;
16
- const account_api_1 = require("@metamask/account-api");
15
+ exports.AccountTreeGroup = exports.DEFAULT_ACCOUNT_GROUP_NAME = void 0;
17
16
  exports.DEFAULT_ACCOUNT_GROUP_NAME = 'Default';
18
- // This class is meant to be used internally by every rules. It exposes mutable operations
19
- // which should not leak outside of this package.
20
- class MutableAccountTreeGroup {
21
- constructor(messenger, wallet, id) {
22
- _MutableAccountTreeGroup_accounts.set(this, void 0);
23
- this.id = (0, account_api_1.toAccountGroupId)(wallet.id, id);
24
- this.wallet = wallet;
25
- this.messenger = messenger;
26
- __classPrivateFieldSet(this, _MutableAccountTreeGroup_accounts, new Set(), "f");
17
+ /**
18
+ * Account group coming from the {@link AccountTreeController}.
19
+ */
20
+ class AccountTreeGroup {
21
+ constructor({ messenger, wallet, group, }) {
22
+ _AccountTreeGroup_instances.add(this);
23
+ _AccountTreeGroup_messenger.set(this, void 0);
24
+ _AccountTreeGroup_group.set(this, void 0);
25
+ _AccountTreeGroup_wallet.set(this, void 0);
26
+ __classPrivateFieldSet(this, _AccountTreeGroup_messenger, messenger, "f");
27
+ __classPrivateFieldSet(this, _AccountTreeGroup_group, group, "f");
28
+ __classPrivateFieldSet(this, _AccountTreeGroup_wallet, wallet, "f");
27
29
  }
28
- getAccountIds() {
29
- return Array.from(__classPrivateFieldGet(this, _MutableAccountTreeGroup_accounts, "f")); // FIXME: Should we force the copy here?
30
+ get id() {
31
+ return __classPrivateFieldGet(this, _AccountTreeGroup_group, "f").id;
30
32
  }
31
- getAccounts() {
32
- const accounts = [];
33
- for (const id of __classPrivateFieldGet(this, _MutableAccountTreeGroup_accounts, "f")) {
34
- const account = this.getAccount(id);
35
- // FIXME: I'm really not sure we should skip those but... We could be
36
- // "de-sync" with the AccountsController and might have some dangling
37
- // account IDs.
38
- if (!account) {
39
- console.warn(`! Unable to get account: "${id}"`);
40
- continue;
41
- }
42
- accounts.push(account);
43
- }
44
- return accounts;
33
+ get wallet() {
34
+ return __classPrivateFieldGet(this, _AccountTreeGroup_wallet, "f");
35
+ }
36
+ get name() {
37
+ return __classPrivateFieldGet(this, _AccountTreeGroup_group, "f").metadata.name;
38
+ }
39
+ getAccountIds() {
40
+ return __classPrivateFieldGet(this, _AccountTreeGroup_group, "f").accounts;
45
41
  }
46
42
  getAccount(id) {
47
- return this.messenger.call('AccountsController:getAccount', id);
43
+ return __classPrivateFieldGet(this, _AccountTreeGroup_messenger, "f").call('AccountsController:getAccount', id);
48
44
  }
49
- addAccount(account) {
50
- __classPrivateFieldGet(this, _MutableAccountTreeGroup_accounts, "f").add(account.id);
45
+ getAccounts() {
46
+ return __classPrivateFieldGet(this, _AccountTreeGroup_group, "f").accounts.map((id) => __classPrivateFieldGet(this, _AccountTreeGroup_instances, "m", _AccountTreeGroup_getAccount).call(this, id));
51
47
  }
52
- getDefaultName() {
53
- return exports.DEFAULT_ACCOUNT_GROUP_NAME;
48
+ getOnlyAccount() {
49
+ const accountIds = this.getAccountIds();
50
+ if (accountIds.length === 0) {
51
+ throw new Error('Group contains no account');
52
+ }
53
+ if (accountIds.length > 1) {
54
+ throw new Error('Group contains more than 1 account');
55
+ }
56
+ return __classPrivateFieldGet(this, _AccountTreeGroup_instances, "m", _AccountTreeGroup_getAccount).call(this, accountIds[0]);
54
57
  }
55
58
  }
56
- exports.MutableAccountTreeGroup = MutableAccountTreeGroup;
57
- _MutableAccountTreeGroup_accounts = new WeakMap();
59
+ exports.AccountTreeGroup = AccountTreeGroup;
60
+ _AccountTreeGroup_messenger = new WeakMap(), _AccountTreeGroup_group = new WeakMap(), _AccountTreeGroup_wallet = new WeakMap(), _AccountTreeGroup_instances = new WeakSet(), _AccountTreeGroup_getAccount = function _AccountTreeGroup_getAccount(id) {
61
+ const account = this.getAccount(id);
62
+ if (!account) {
63
+ throw new Error(`Unable to get account with ID: "${id}"`);
64
+ }
65
+ return account;
66
+ };
58
67
  //# sourceMappingURL=AccountTreeGroup.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"AccountTreeGroup.cjs","sourceRoot":"","sources":["../src/AccountTreeGroup.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,uDAK+B;AAKlB,QAAA,0BAA0B,GAAW,SAAS,CAAC;AAiB5D,0FAA0F;AAC1F,iDAAiD;AACjD,MAAa,uBAAuB;IASlC,YACE,SAAyC,EACzC,MAAsC,EACtC,EAAU;QALH,oDAA0B;QAOjC,IAAI,CAAC,EAAE,GAAG,IAAA,8BAAgB,EAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAE3B,uBAAA,IAAI,qCAAa,IAAI,GAAG,EAAE,MAAA,CAAC;IAC7B,CAAC;IAED,aAAa;QACX,OAAO,KAAK,CAAC,IAAI,CAAC,uBAAA,IAAI,yCAAU,CAAC,CAAC,CAAC,wCAAwC;IAC7E,CAAC;IAED,WAAW;QACT,MAAM,QAAQ,GAAG,EAAE,CAAC;QAEpB,KAAK,MAAM,EAAE,IAAI,uBAAA,IAAI,yCAAU,EAAE;YAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;YAEpC,qEAAqE;YACrE,qEAAqE;YACrE,eAAe;YACf,IAAI,CAAC,OAAO,EAAE;gBACZ,OAAO,CAAC,IAAI,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;gBACjD,SAAS;aACV;YACD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;SACxB;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,UAAU,CAAC,EAAa;QACtB,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,+BAA+B,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,UAAU,CAAC,OAAwB;QACjC,uBAAA,IAAI,yCAAU,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;IAED,cAAc;QACZ,OAAO,kCAA0B,CAAC;IACpC,CAAC;CACF;AAtDD,0DAsDC","sourcesContent":["import {\n toAccountGroupId,\n type AccountGroup,\n type AccountGroupId,\n type AccountWallet,\n} from '@metamask/account-api';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\nimport type { AccountId } from '@metamask/keyring-utils';\nimport type { AccountTreeControllerMessenger } from 'src';\n\nexport const DEFAULT_ACCOUNT_GROUP_NAME: string = 'Default';\n\n/**\n * Account group coming from the {@link AccountTreeController}.\n */\nexport type AccountTreeGroup = {\n /**\n * Account IDs for that account group.\n */\n getAccountIds(): AccountId[];\n\n /**\n * Gets the default name for that account group.\n */\n getDefaultName(): string;\n} & AccountGroup<InternalAccount>;\n\n// This class is meant to be used internally by every rules. It exposes mutable operations\n// which should not leak outside of this package.\nexport class MutableAccountTreeGroup implements AccountTreeGroup {\n readonly id: AccountGroupId;\n\n readonly wallet: AccountWallet<InternalAccount>;\n\n readonly messenger: AccountTreeControllerMessenger;\n\n readonly #accounts: Set<AccountId>;\n\n constructor(\n messenger: AccountTreeControllerMessenger,\n wallet: AccountWallet<InternalAccount>,\n id: string,\n ) {\n this.id = toAccountGroupId(wallet.id, id);\n this.wallet = wallet;\n this.messenger = messenger;\n\n this.#accounts = new Set();\n }\n\n getAccountIds(): AccountId[] {\n return Array.from(this.#accounts); // FIXME: Should we force the copy here?\n }\n\n getAccounts(): InternalAccount[] {\n const accounts = [];\n\n for (const id of this.#accounts) {\n const account = this.getAccount(id);\n\n // FIXME: I'm really not sure we should skip those but... We could be\n // \"de-sync\" with the AccountsController and might have some dangling\n // account IDs.\n if (!account) {\n console.warn(`! Unable to get account: \"${id}\"`);\n continue;\n }\n accounts.push(account);\n }\n return accounts;\n }\n\n getAccount(id: AccountId): InternalAccount | undefined {\n return this.messenger.call('AccountsController:getAccount', id);\n }\n\n addAccount(account: InternalAccount) {\n this.#accounts.add(account.id);\n }\n\n getDefaultName(): string {\n return DEFAULT_ACCOUNT_GROUP_NAME;\n }\n}\n"]}
1
+ {"version":3,"file":"AccountTreeGroup.cjs","sourceRoot":"","sources":["../src/AccountTreeGroup.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AASa,QAAA,0BAA0B,GAAW,SAAS,CAAC;AAE5D;;GAEG;AACH,MAAa,gBAAgB;IAO3B,YAAY,EACV,SAAS,EACT,MAAM,EACN,KAAK,GAKN;;QAdQ,8CAA2C;QAE3C,0CAA2B;QAE3B,2CAA2B;QAWlC,uBAAA,IAAI,+BAAc,SAAS,MAAA,CAAC;QAC5B,uBAAA,IAAI,2BAAU,KAAK,MAAA,CAAC;QACpB,uBAAA,IAAI,4BAAW,MAAM,MAAA,CAAC;IACxB,CAAC;IAED,IAAI,EAAE;QACJ,OAAO,uBAAA,IAAI,+BAAO,CAAC,EAAE,CAAC;IACxB,CAAC;IAED,IAAI,MAAM;QACR,OAAO,uBAAA,IAAI,gCAAQ,CAAC;IACtB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,uBAAA,IAAI,+BAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;IACnC,CAAC;IAED,aAAa;QACX,OAAO,uBAAA,IAAI,+BAAO,CAAC,QAAQ,CAAC;IAC9B,CAAC;IAED,UAAU,CAAC,EAAU;QACnB,OAAO,uBAAA,IAAI,mCAAW,CAAC,IAAI,CAAC,+BAA+B,EAAE,EAAE,CAAC,CAAC;IACnE,CAAC;IAWD,WAAW;QACT,OAAO,uBAAA,IAAI,+BAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,uBAAA,IAAI,iEAAY,MAAhB,IAAI,EAAa,EAAE,CAAC,CAAC,CAAC;IAChE,CAAC;IAED,cAAc;QACZ,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QAExC,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE;YAC3B,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;SAC9C;QACD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE;YACzB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;SACvD;QAED,OAAO,uBAAA,IAAI,iEAAY,MAAhB,IAAI,EAAa,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;CACF;AAlED,4CAkEC;kPAzBa,EAAU;IACpB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAEpC,IAAI,CAAC,OAAO,EAAE;QACZ,MAAM,IAAI,KAAK,CAAC,mCAAmC,EAAE,GAAG,CAAC,CAAC;KAC3D;IACD,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["import { type AccountGroup, type AccountGroupId } from '@metamask/account-api';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\n\nimport type { AccountTreeWallet } from './AccountTreeWallet';\nimport type {\n AccountGroupObject,\n AccountTreeControllerMessenger,\n} from './types';\n\nexport const DEFAULT_ACCOUNT_GROUP_NAME: string = 'Default';\n\n/**\n * Account group coming from the {@link AccountTreeController}.\n */\nexport class AccountTreeGroup implements AccountGroup<InternalAccount> {\n readonly #messenger: AccountTreeControllerMessenger;\n\n readonly #group: AccountGroupObject;\n\n readonly #wallet: AccountTreeWallet;\n\n constructor({\n messenger,\n wallet,\n group,\n }: {\n messenger: AccountTreeControllerMessenger;\n wallet: AccountTreeWallet;\n group: AccountGroupObject;\n }) {\n this.#messenger = messenger;\n this.#group = group;\n this.#wallet = wallet;\n }\n\n get id(): AccountGroupId {\n return this.#group.id;\n }\n\n get wallet(): AccountTreeWallet {\n return this.#wallet;\n }\n\n get name(): string {\n return this.#group.metadata.name;\n }\n\n getAccountIds(): InternalAccount['id'][] {\n return this.#group.accounts;\n }\n\n getAccount(id: string): InternalAccount | undefined {\n return this.#messenger.call('AccountsController:getAccount', id);\n }\n\n #getAccount(id: string): InternalAccount {\n const account = this.getAccount(id);\n\n if (!account) {\n throw new Error(`Unable to get account with ID: \"${id}\"`);\n }\n return account;\n }\n\n getAccounts(): InternalAccount[] {\n return this.#group.accounts.map((id) => this.#getAccount(id));\n }\n\n getOnlyAccount(): InternalAccount {\n const accountIds = this.getAccountIds();\n\n if (accountIds.length === 0) {\n throw new Error('Group contains no account');\n }\n if (accountIds.length > 1) {\n throw new Error('Group contains more than 1 account');\n }\n\n return this.#getAccount(accountIds[0]);\n }\n}\n"]}
@@ -1,31 +1,24 @@
1
- import { type AccountGroup, type AccountGroupId, type AccountWallet } from "@metamask/account-api";
1
+ import { type AccountGroup, type AccountGroupId } from "@metamask/account-api";
2
2
  import type { InternalAccount } from "@metamask/keyring-internal-api";
3
- import type { AccountId } from "@metamask/keyring-utils";
4
- import type { AccountTreeControllerMessenger } from "src";
3
+ import type { AccountTreeWallet } from "./AccountTreeWallet.cjs";
4
+ import type { AccountGroupObject, AccountTreeControllerMessenger } from "./types.cjs";
5
5
  export declare const DEFAULT_ACCOUNT_GROUP_NAME: string;
6
6
  /**
7
7
  * Account group coming from the {@link AccountTreeController}.
8
8
  */
9
- export type AccountTreeGroup = {
10
- /**
11
- * Account IDs for that account group.
12
- */
13
- getAccountIds(): AccountId[];
14
- /**
15
- * Gets the default name for that account group.
16
- */
17
- getDefaultName(): string;
18
- } & AccountGroup<InternalAccount>;
19
- export declare class MutableAccountTreeGroup implements AccountTreeGroup {
9
+ export declare class AccountTreeGroup implements AccountGroup<InternalAccount> {
20
10
  #private;
21
- readonly id: AccountGroupId;
22
- readonly wallet: AccountWallet<InternalAccount>;
23
- readonly messenger: AccountTreeControllerMessenger;
24
- constructor(messenger: AccountTreeControllerMessenger, wallet: AccountWallet<InternalAccount>, id: string);
25
- getAccountIds(): AccountId[];
11
+ constructor({ messenger, wallet, group, }: {
12
+ messenger: AccountTreeControllerMessenger;
13
+ wallet: AccountTreeWallet;
14
+ group: AccountGroupObject;
15
+ });
16
+ get id(): AccountGroupId;
17
+ get wallet(): AccountTreeWallet;
18
+ get name(): string;
19
+ getAccountIds(): InternalAccount['id'][];
20
+ getAccount(id: string): InternalAccount | undefined;
26
21
  getAccounts(): InternalAccount[];
27
- getAccount(id: AccountId): InternalAccount | undefined;
28
- addAccount(account: InternalAccount): void;
29
- getDefaultName(): string;
22
+ getOnlyAccount(): InternalAccount;
30
23
  }
31
24
  //# sourceMappingURL=AccountTreeGroup.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AccountTreeGroup.d.cts","sourceRoot":"","sources":["../src/AccountTreeGroup.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,8BAA8B;AAC/B,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,gCAAgC;AACzD,OAAO,KAAK,EAAE,8BAA8B,EAAE,YAAY;AAE1D,eAAO,MAAM,0BAA0B,EAAE,MAAkB,CAAC;AAE5D;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;OAEG;IACH,aAAa,IAAI,SAAS,EAAE,CAAC;IAE7B;;OAEG;IACH,cAAc,IAAI,MAAM,CAAC;CAC1B,GAAG,YAAY,CAAC,eAAe,CAAC,CAAC;AAIlC,qBAAa,uBAAwB,YAAW,gBAAgB;;IAC9D,QAAQ,CAAC,EAAE,EAAE,cAAc,CAAC;IAE5B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAEhD,QAAQ,CAAC,SAAS,EAAE,8BAA8B,CAAC;gBAKjD,SAAS,EAAE,8BAA8B,EACzC,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,EACtC,EAAE,EAAE,MAAM;IASZ,aAAa,IAAI,SAAS,EAAE;IAI5B,WAAW,IAAI,eAAe,EAAE;IAkBhC,UAAU,CAAC,EAAE,EAAE,SAAS,GAAG,eAAe,GAAG,SAAS;IAItD,UAAU,CAAC,OAAO,EAAE,eAAe;IAInC,cAAc,IAAI,MAAM;CAGzB"}
1
+ {"version":3,"file":"AccountTreeGroup.d.cts","sourceRoot":"","sources":["../src/AccountTreeGroup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,cAAc,EAAE,8BAA8B;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAEtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,gCAA4B;AAC7D,OAAO,KAAK,EACV,kBAAkB,EAClB,8BAA8B,EAC/B,oBAAgB;AAEjB,eAAO,MAAM,0BAA0B,EAAE,MAAkB,CAAC;AAE5D;;GAEG;AACH,qBAAa,gBAAiB,YAAW,YAAY,CAAC,eAAe,CAAC;;gBAOxD,EACV,SAAS,EACT,MAAM,EACN,KAAK,GACN,EAAE;QACD,SAAS,EAAE,8BAA8B,CAAC;QAC1C,MAAM,EAAE,iBAAiB,CAAC;QAC1B,KAAK,EAAE,kBAAkB,CAAC;KAC3B;IAMD,IAAI,EAAE,IAAI,cAAc,CAEvB;IAED,IAAI,MAAM,IAAI,iBAAiB,CAE9B;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,aAAa,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE;IAIxC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAanD,WAAW,IAAI,eAAe,EAAE;IAIhC,cAAc,IAAI,eAAe;CAYlC"}
@@ -1,31 +1,24 @@
1
- import { type AccountGroup, type AccountGroupId, type AccountWallet } from "@metamask/account-api";
1
+ import { type AccountGroup, type AccountGroupId } from "@metamask/account-api";
2
2
  import type { InternalAccount } from "@metamask/keyring-internal-api";
3
- import type { AccountId } from "@metamask/keyring-utils";
4
- import type { AccountTreeControllerMessenger } from "src";
3
+ import type { AccountTreeWallet } from "./AccountTreeWallet.mjs";
4
+ import type { AccountGroupObject, AccountTreeControllerMessenger } from "./types.mjs";
5
5
  export declare const DEFAULT_ACCOUNT_GROUP_NAME: string;
6
6
  /**
7
7
  * Account group coming from the {@link AccountTreeController}.
8
8
  */
9
- export type AccountTreeGroup = {
10
- /**
11
- * Account IDs for that account group.
12
- */
13
- getAccountIds(): AccountId[];
14
- /**
15
- * Gets the default name for that account group.
16
- */
17
- getDefaultName(): string;
18
- } & AccountGroup<InternalAccount>;
19
- export declare class MutableAccountTreeGroup implements AccountTreeGroup {
9
+ export declare class AccountTreeGroup implements AccountGroup<InternalAccount> {
20
10
  #private;
21
- readonly id: AccountGroupId;
22
- readonly wallet: AccountWallet<InternalAccount>;
23
- readonly messenger: AccountTreeControllerMessenger;
24
- constructor(messenger: AccountTreeControllerMessenger, wallet: AccountWallet<InternalAccount>, id: string);
25
- getAccountIds(): AccountId[];
11
+ constructor({ messenger, wallet, group, }: {
12
+ messenger: AccountTreeControllerMessenger;
13
+ wallet: AccountTreeWallet;
14
+ group: AccountGroupObject;
15
+ });
16
+ get id(): AccountGroupId;
17
+ get wallet(): AccountTreeWallet;
18
+ get name(): string;
19
+ getAccountIds(): InternalAccount['id'][];
20
+ getAccount(id: string): InternalAccount | undefined;
26
21
  getAccounts(): InternalAccount[];
27
- getAccount(id: AccountId): InternalAccount | undefined;
28
- addAccount(account: InternalAccount): void;
29
- getDefaultName(): string;
22
+ getOnlyAccount(): InternalAccount;
30
23
  }
31
24
  //# sourceMappingURL=AccountTreeGroup.d.mts.map