@metamask-previews/account-tree-controller 0.7.0-preview-0fca3de → 0.7.0-preview-af4e47c0
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 +9 -0
- package/dist/AccountTreeController.cjs +183 -36
- package/dist/AccountTreeController.cjs.map +1 -1
- package/dist/AccountTreeController.d.cts +32 -0
- package/dist/AccountTreeController.d.cts.map +1 -1
- package/dist/AccountTreeController.d.mts +32 -0
- package/dist/AccountTreeController.d.mts.map +1 -1
- package/dist/AccountTreeController.mjs +183 -36
- package/dist/AccountTreeController.mjs.map +1 -1
- package/dist/group.cjs.map +1 -1
- package/dist/group.d.cts +19 -8
- package/dist/group.d.cts.map +1 -1
- package/dist/group.d.mts +19 -8
- package/dist/group.d.mts.map +1 -1
- package/dist/group.mjs.map +1 -1
- package/dist/rules/entropy.cjs +2 -0
- package/dist/rules/entropy.cjs.map +1 -1
- package/dist/rules/entropy.d.cts.map +1 -1
- package/dist/rules/entropy.d.mts.map +1 -1
- package/dist/rules/entropy.mjs +2 -0
- package/dist/rules/entropy.mjs.map +1 -1
- package/dist/rules/keyring.cjs +4 -1
- package/dist/rules/keyring.cjs.map +1 -1
- package/dist/rules/keyring.d.cts.map +1 -1
- package/dist/rules/keyring.d.mts.map +1 -1
- package/dist/rules/keyring.mjs +4 -1
- package/dist/rules/keyring.mjs.map +1 -1
- package/dist/rules/snap.cjs +4 -1
- package/dist/rules/snap.cjs.map +1 -1
- package/dist/rules/snap.d.cts.map +1 -1
- package/dist/rules/snap.d.mts.map +1 -1
- package/dist/rules/snap.mjs +4 -1
- package/dist/rules/snap.mjs.map +1 -1
- package/dist/type-utils.cjs +3 -0
- package/dist/type-utils.cjs.map +1 -0
- package/dist/type-utils.d.cts +24 -0
- package/dist/type-utils.d.cts.map +1 -0
- package/dist/type-utils.d.mts +24 -0
- package/dist/type-utils.d.mts.map +1 -0
- package/dist/type-utils.mjs +2 -0
- package/dist/type-utils.mjs.map +1 -0
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +14 -1
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +14 -1
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/wallet.cjs.map +1 -1
- package/dist/wallet.d.cts +16 -9
- package/dist/wallet.d.cts.map +1 -1
- package/dist/wallet.d.mts +16 -9
- package/dist/wallet.d.mts.map +1 -1
- package/dist/wallet.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -9,7 +9,7 @@ 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_rules, _AccountTreeController_getEntropyRule, _AccountTreeController_getSnapRule, _AccountTreeController_getKeyringRule,
|
|
12
|
+
var _AccountTreeController_instances, _AccountTreeController_accountIdToContext, _AccountTreeController_groupIdToWalletId, _AccountTreeController_rules, _AccountTreeController_getEntropyRule, _AccountTreeController_getSnapRule, _AccountTreeController_getKeyringRule, _AccountTreeController_applyAccountWalletMetadata, _AccountTreeController_applyAccountGroupMetadata, _AccountTreeController_handleAccountAdded, _AccountTreeController_handleAccountRemoved, _AccountTreeController_insert, _AccountTreeController_listAccounts, _AccountTreeController_assertAccountGroupExists, _AccountTreeController_assertAccountWalletExists, _AccountTreeController_getDefaultSelectedAccountGroup, _AccountTreeController_handleSelectedAccountChange, _AccountTreeController_getAccountGroup, _AccountTreeController_getDefaultAccountFromAccountGroupId, _AccountTreeController_getDefaultAccountGroupId, _AccountTreeController_registerMessageHandlers;
|
|
13
13
|
import { AccountWalletType } from "@metamask/account-api";
|
|
14
14
|
import { BaseController } from "@metamask/base-controller";
|
|
15
15
|
import { isEvmAccountType } from "@metamask/keyring-api";
|
|
@@ -23,6 +23,14 @@ const accountTreeControllerMetadata = {
|
|
|
23
23
|
persist: false,
|
|
24
24
|
anonymous: false,
|
|
25
25
|
},
|
|
26
|
+
accountGroupsMetadata: {
|
|
27
|
+
persist: true,
|
|
28
|
+
anonymous: false,
|
|
29
|
+
},
|
|
30
|
+
accountWalletsMetadata: {
|
|
31
|
+
persist: true,
|
|
32
|
+
anonymous: false,
|
|
33
|
+
},
|
|
26
34
|
};
|
|
27
35
|
/**
|
|
28
36
|
* Gets default state of the `AccountTreeController`.
|
|
@@ -35,6 +43,8 @@ export function getDefaultAccountTreeControllerState() {
|
|
|
35
43
|
wallets: {},
|
|
36
44
|
selectedAccountGroup: '',
|
|
37
45
|
},
|
|
46
|
+
accountGroupsMetadata: {},
|
|
47
|
+
accountWalletsMetadata: {},
|
|
38
48
|
};
|
|
39
49
|
}
|
|
40
50
|
export class AccountTreeController extends BaseController {
|
|
@@ -57,9 +67,12 @@ export class AccountTreeController extends BaseController {
|
|
|
57
67
|
});
|
|
58
68
|
_AccountTreeController_instances.add(this);
|
|
59
69
|
_AccountTreeController_accountIdToContext.set(this, void 0);
|
|
70
|
+
// Mapping for direct tree node access
|
|
71
|
+
_AccountTreeController_groupIdToWalletId.set(this, void 0);
|
|
60
72
|
_AccountTreeController_rules.set(this, void 0);
|
|
61
73
|
// Reverse map to allow fast node access from an account ID.
|
|
62
74
|
__classPrivateFieldSet(this, _AccountTreeController_accountIdToContext, new Map(), "f");
|
|
75
|
+
__classPrivateFieldSet(this, _AccountTreeController_groupIdToWalletId, new Map(), "f");
|
|
63
76
|
// Rules to apply to construct the wallets tree.
|
|
64
77
|
__classPrivateFieldSet(this, _AccountTreeController_rules, [
|
|
65
78
|
// 1. We group by entropy-source
|
|
@@ -82,15 +95,18 @@ export class AccountTreeController extends BaseController {
|
|
|
82
95
|
}
|
|
83
96
|
init() {
|
|
84
97
|
const wallets = {};
|
|
98
|
+
// Clear mappings for fresh rebuild
|
|
99
|
+
__classPrivateFieldGet(this, _AccountTreeController_accountIdToContext, "f").clear();
|
|
100
|
+
__classPrivateFieldGet(this, _AccountTreeController_groupIdToWalletId, "f").clear();
|
|
85
101
|
// For now, we always re-compute all wallets, we do not re-use the existing state.
|
|
86
102
|
for (const account of __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_listAccounts).call(this)) {
|
|
87
103
|
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_insert).call(this, wallets, account);
|
|
88
104
|
}
|
|
89
|
-
// Once we have the account tree, we can
|
|
105
|
+
// Once we have the account tree, we can apply persisted metadata (names + UI states).
|
|
90
106
|
for (const wallet of Object.values(wallets)) {
|
|
91
|
-
__classPrivateFieldGet(this, _AccountTreeController_instances, "m",
|
|
107
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_applyAccountWalletMetadata).call(this, wallet);
|
|
92
108
|
for (const group of Object.values(wallet.groups)) {
|
|
93
|
-
__classPrivateFieldGet(this, _AccountTreeController_instances, "m",
|
|
109
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_applyAccountGroupMetadata).call(this, wallet, group);
|
|
94
110
|
}
|
|
95
111
|
}
|
|
96
112
|
this.update((state) => {
|
|
@@ -146,47 +162,164 @@ export class AccountTreeController extends BaseController {
|
|
|
146
162
|
// but our handler is idempotent so it won't cause infinite loop
|
|
147
163
|
this.messagingSystem.call('AccountsController:setSelectedAccount', accountToSelect);
|
|
148
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Sets a custom name for an account group.
|
|
167
|
+
*
|
|
168
|
+
* @param groupId - The account group ID.
|
|
169
|
+
* @param name - The custom name to set.
|
|
170
|
+
* @throws If the account group ID is not found in the current tree.
|
|
171
|
+
*/
|
|
172
|
+
setAccountGroupName(groupId, name) {
|
|
173
|
+
// Validate that the group exists in the current tree
|
|
174
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_assertAccountGroupExists).call(this, groupId);
|
|
175
|
+
this.update((state) => {
|
|
176
|
+
var _a;
|
|
177
|
+
// Update persistent metadata
|
|
178
|
+
(_a = state.accountGroupsMetadata)[groupId] ?? (_a[groupId] = {});
|
|
179
|
+
state.accountGroupsMetadata[groupId].name = {
|
|
180
|
+
value: name,
|
|
181
|
+
lastUpdatedAt: Date.now(),
|
|
182
|
+
};
|
|
183
|
+
// Update tree node directly using efficient mapping
|
|
184
|
+
const walletId = __classPrivateFieldGet(this, _AccountTreeController_groupIdToWalletId, "f").get(groupId);
|
|
185
|
+
if (walletId) {
|
|
186
|
+
state.accountTree.wallets[walletId].groups[groupId].metadata.name =
|
|
187
|
+
name;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Sets a custom name for an account wallet.
|
|
193
|
+
*
|
|
194
|
+
* @param walletId - The account wallet ID.
|
|
195
|
+
* @param name - The custom name to set.
|
|
196
|
+
* @throws If the account wallet ID is not found in the current tree.
|
|
197
|
+
*/
|
|
198
|
+
setAccountWalletName(walletId, name) {
|
|
199
|
+
// Validate that the wallet exists in the current tree
|
|
200
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_assertAccountWalletExists).call(this, walletId);
|
|
201
|
+
this.update((state) => {
|
|
202
|
+
var _a;
|
|
203
|
+
// Update persistent metadata
|
|
204
|
+
(_a = state.accountWalletsMetadata)[walletId] ?? (_a[walletId] = {});
|
|
205
|
+
state.accountWalletsMetadata[walletId].name = {
|
|
206
|
+
value: name,
|
|
207
|
+
lastUpdatedAt: Date.now(),
|
|
208
|
+
};
|
|
209
|
+
// Update tree node directly
|
|
210
|
+
state.accountTree.wallets[walletId].metadata.name = name;
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Toggles the pinned state of an account group.
|
|
215
|
+
*
|
|
216
|
+
* @param groupId - The account group ID.
|
|
217
|
+
* @param pinned - Whether the group should be pinned.
|
|
218
|
+
* @throws If the account group ID is not found in the current tree.
|
|
219
|
+
*/
|
|
220
|
+
setAccountGroupPinned(groupId, pinned) {
|
|
221
|
+
// Validate that the group exists in the current tree
|
|
222
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_assertAccountGroupExists).call(this, groupId);
|
|
223
|
+
this.update((state) => {
|
|
224
|
+
var _a;
|
|
225
|
+
// Update persistent metadata
|
|
226
|
+
(_a = state.accountGroupsMetadata)[groupId] ?? (_a[groupId] = {});
|
|
227
|
+
state.accountGroupsMetadata[groupId].pinned = {
|
|
228
|
+
value: pinned,
|
|
229
|
+
lastUpdatedAt: Date.now(),
|
|
230
|
+
};
|
|
231
|
+
// Update tree node directly using efficient mapping
|
|
232
|
+
const walletId = __classPrivateFieldGet(this, _AccountTreeController_groupIdToWalletId, "f").get(groupId);
|
|
233
|
+
if (walletId) {
|
|
234
|
+
state.accountTree.wallets[walletId].groups[groupId].metadata.pinned =
|
|
235
|
+
pinned;
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Toggles the hidden state of an account group.
|
|
241
|
+
*
|
|
242
|
+
* @param groupId - The account group ID.
|
|
243
|
+
* @param hidden - Whether the group should be hidden.
|
|
244
|
+
* @throws If the account group ID is not found in the current tree.
|
|
245
|
+
*/
|
|
246
|
+
setAccountGroupHidden(groupId, hidden) {
|
|
247
|
+
// Validate that the group exists in the current tree
|
|
248
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_assertAccountGroupExists).call(this, groupId);
|
|
249
|
+
this.update((state) => {
|
|
250
|
+
var _a;
|
|
251
|
+
// Update persistent metadata
|
|
252
|
+
(_a = state.accountGroupsMetadata)[groupId] ?? (_a[groupId] = {});
|
|
253
|
+
state.accountGroupsMetadata[groupId].hidden = {
|
|
254
|
+
value: hidden,
|
|
255
|
+
lastUpdatedAt: Date.now(),
|
|
256
|
+
};
|
|
257
|
+
// Update tree node directly using efficient mapping
|
|
258
|
+
const walletId = __classPrivateFieldGet(this, _AccountTreeController_groupIdToWalletId, "f").get(groupId);
|
|
259
|
+
if (walletId) {
|
|
260
|
+
state.accountTree.wallets[walletId].groups[groupId].metadata.hidden =
|
|
261
|
+
hidden;
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
}
|
|
149
265
|
}
|
|
150
|
-
_AccountTreeController_accountIdToContext = new WeakMap(), _AccountTreeController_rules = new WeakMap(), _AccountTreeController_instances = new WeakSet(), _AccountTreeController_getEntropyRule = function _AccountTreeController_getEntropyRule() {
|
|
266
|
+
_AccountTreeController_accountIdToContext = new WeakMap(), _AccountTreeController_groupIdToWalletId = new WeakMap(), _AccountTreeController_rules = new WeakMap(), _AccountTreeController_instances = new WeakSet(), _AccountTreeController_getEntropyRule = function _AccountTreeController_getEntropyRule() {
|
|
151
267
|
return __classPrivateFieldGet(this, _AccountTreeController_rules, "f")[0];
|
|
152
268
|
}, _AccountTreeController_getSnapRule = function _AccountTreeController_getSnapRule() {
|
|
153
269
|
return __classPrivateFieldGet(this, _AccountTreeController_rules, "f")[1];
|
|
154
270
|
}, _AccountTreeController_getKeyringRule = function _AccountTreeController_getKeyringRule() {
|
|
155
271
|
return __classPrivateFieldGet(this, _AccountTreeController_rules, "f")[2];
|
|
156
|
-
},
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
wallet.metadata.name =
|
|
162
|
-
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getEntropyRule).call(this).getDefaultAccountWalletName(wallet);
|
|
163
|
-
}
|
|
164
|
-
else if (wallet.type === AccountWalletType.Snap) {
|
|
165
|
-
wallet.metadata.name =
|
|
166
|
-
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getSnapRule).call(this).getDefaultAccountWalletName(wallet);
|
|
272
|
+
}, _AccountTreeController_applyAccountWalletMetadata = function _AccountTreeController_applyAccountWalletMetadata(wallet) {
|
|
273
|
+
const persistedMetadata = this.state.accountWalletsMetadata[wallet.id];
|
|
274
|
+
// Apply persisted name if available
|
|
275
|
+
if (persistedMetadata?.name?.value) {
|
|
276
|
+
wallet.metadata.name = persistedMetadata.name.value;
|
|
167
277
|
}
|
|
168
|
-
else {
|
|
169
|
-
|
|
170
|
-
|
|
278
|
+
else if (!wallet.metadata.name) {
|
|
279
|
+
// Generate default name if none exists
|
|
280
|
+
if (wallet.type === AccountWalletType.Entropy) {
|
|
281
|
+
wallet.metadata.name =
|
|
282
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getEntropyRule).call(this).getDefaultAccountWalletName(wallet);
|
|
283
|
+
}
|
|
284
|
+
else if (wallet.type === AccountWalletType.Snap) {
|
|
285
|
+
wallet.metadata.name =
|
|
286
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getSnapRule).call(this).getDefaultAccountWalletName(wallet);
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
wallet.metadata.name =
|
|
290
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getKeyringRule).call(this).getDefaultAccountWalletName(wallet);
|
|
291
|
+
}
|
|
171
292
|
}
|
|
172
|
-
},
|
|
173
|
-
|
|
174
|
-
|
|
293
|
+
}, _AccountTreeController_applyAccountGroupMetadata = function _AccountTreeController_applyAccountGroupMetadata(wallet, group) {
|
|
294
|
+
const persistedMetadata = this.state.accountGroupsMetadata[group.id];
|
|
295
|
+
// Apply persisted name if available
|
|
296
|
+
if (persistedMetadata?.name?.value) {
|
|
297
|
+
group.metadata.name = persistedMetadata.name.value;
|
|
175
298
|
}
|
|
176
|
-
if (
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
299
|
+
else if (!group.metadata.name) {
|
|
300
|
+
// Generate default name if none exists
|
|
301
|
+
if (wallet.type === AccountWalletType.Entropy) {
|
|
302
|
+
group.metadata.name = __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getEntropyRule).call(this).getDefaultAccountGroupName(
|
|
303
|
+
// Get the group from the wallet, to get the proper type inference.
|
|
304
|
+
wallet.groups[group.id]);
|
|
305
|
+
}
|
|
306
|
+
else if (wallet.type === AccountWalletType.Snap) {
|
|
307
|
+
group.metadata.name = __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getSnapRule).call(this).getDefaultAccountGroupName(
|
|
308
|
+
// Same here.
|
|
309
|
+
wallet.groups[group.id]);
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
group.metadata.name = __classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_getKeyringRule).call(this).getDefaultAccountGroupName(
|
|
313
|
+
// Same here.
|
|
314
|
+
wallet.groups[group.id]);
|
|
315
|
+
}
|
|
180
316
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
wallet.groups[group.id]);
|
|
317
|
+
// Apply persisted UI states
|
|
318
|
+
if (persistedMetadata?.pinned?.value !== undefined) {
|
|
319
|
+
group.metadata.pinned = persistedMetadata.pinned.value;
|
|
185
320
|
}
|
|
186
|
-
|
|
187
|
-
group.metadata.
|
|
188
|
-
// Same here.
|
|
189
|
-
wallet.groups[group.id]);
|
|
321
|
+
if (persistedMetadata?.hidden?.value !== undefined) {
|
|
322
|
+
group.metadata.hidden = persistedMetadata.hidden.value;
|
|
190
323
|
}
|
|
191
324
|
}, _AccountTreeController_handleAccountAdded = function _AccountTreeController_handleAccountAdded(account) {
|
|
192
325
|
this.update((state) => {
|
|
@@ -196,10 +329,10 @@ _AccountTreeController_accountIdToContext = new WeakMap(), _AccountTreeControlle
|
|
|
196
329
|
const { walletId, groupId } = context;
|
|
197
330
|
const wallet = state.accountTree.wallets[walletId];
|
|
198
331
|
if (wallet) {
|
|
199
|
-
__classPrivateFieldGet(this, _AccountTreeController_instances, "m",
|
|
332
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_applyAccountWalletMetadata).call(this, wallet);
|
|
200
333
|
const group = wallet.groups[groupId];
|
|
201
334
|
if (group) {
|
|
202
|
-
__classPrivateFieldGet(this, _AccountTreeController_instances, "m",
|
|
335
|
+
__classPrivateFieldGet(this, _AccountTreeController_instances, "m", _AccountTreeController_applyAccountGroupMetadata).call(this, wallet, group);
|
|
203
336
|
}
|
|
204
337
|
}
|
|
205
338
|
}
|
|
@@ -257,11 +390,15 @@ _AccountTreeController_accountIdToContext = new WeakMap(), _AccountTreeControlle
|
|
|
257
390
|
metadata: {
|
|
258
391
|
name: '',
|
|
259
392
|
...result.group.metadata,
|
|
393
|
+
pinned: false,
|
|
394
|
+
hidden: false, // Default UI state
|
|
260
395
|
},
|
|
261
396
|
// We do need to type-cast since we're not narrowing `result` with
|
|
262
397
|
// the union tag `result.group.type`.
|
|
263
398
|
};
|
|
264
399
|
group = wallet.groups[groupId];
|
|
400
|
+
// Map group ID to its containing wallet ID for efficient direct access
|
|
401
|
+
__classPrivateFieldGet(this, _AccountTreeController_groupIdToWalletId, "f").set(groupId, walletId);
|
|
265
402
|
}
|
|
266
403
|
else {
|
|
267
404
|
group.accounts.push(account.id);
|
|
@@ -273,6 +410,16 @@ _AccountTreeController_accountIdToContext = new WeakMap(), _AccountTreeControlle
|
|
|
273
410
|
});
|
|
274
411
|
}, _AccountTreeController_listAccounts = function _AccountTreeController_listAccounts() {
|
|
275
412
|
return this.messagingSystem.call('AccountsController:listMultichainAccounts');
|
|
413
|
+
}, _AccountTreeController_assertAccountGroupExists = function _AccountTreeController_assertAccountGroupExists(groupId) {
|
|
414
|
+
const exists = __classPrivateFieldGet(this, _AccountTreeController_groupIdToWalletId, "f").has(groupId);
|
|
415
|
+
if (!exists) {
|
|
416
|
+
throw new Error(`Account group with ID "${groupId}" not found in tree`);
|
|
417
|
+
}
|
|
418
|
+
}, _AccountTreeController_assertAccountWalletExists = function _AccountTreeController_assertAccountWalletExists(walletId) {
|
|
419
|
+
const exists = Boolean(this.state.accountTree.wallets[walletId]);
|
|
420
|
+
if (!exists) {
|
|
421
|
+
throw new Error(`Account wallet with ID "${walletId}" not found in tree`);
|
|
422
|
+
}
|
|
276
423
|
}, _AccountTreeController_getDefaultSelectedAccountGroup = function _AccountTreeController_getDefaultSelectedAccountGroup(wallets) {
|
|
277
424
|
const selectedAccount = this.messagingSystem.call('AccountsController:getSelectedAccount');
|
|
278
425
|
if (selectedAccount && selectedAccount.id) {
|
|
@@ -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 { AccountWalletType } 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 { isEvmAccountType } from '@metamask/keyring-api';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\n\nimport type { AccountGroupObject } from './group';\nimport { EntropyRule } from './rules/entropy';\nimport { KeyringRule } from './rules/keyring';\nimport { SnapRule } from './rules/snap';\nimport type {\n AccountTreeControllerMessenger,\n AccountTreeControllerState,\n} from './types';\nimport type { AccountWalletObject } from './wallet';\nimport { AccountTreeWallet } from './wallet';\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: AccountWalletObject['id'];\n\n /**\n * Account group ID associated to that account.\n */\n groupId: AccountGroupObject['id'];\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: [EntropyRule, SnapRule, KeyringRule];\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.#rules = [\n // 1. We group by entropy-source\n new EntropyRule(this.messagingSystem),\n // 2. We group by Snap ID\n new SnapRule(this.messagingSystem),\n // 3. We group by wallet type (this rule cannot fail and will group all non-matching accounts)\n new KeyringRule(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 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 #getEntropyRule(): EntropyRule {\n return this.#rules[0];\n }\n\n #getSnapRule(): SnapRule {\n return this.#rules[1];\n }\n\n #getKeyringRule(): KeyringRule {\n return this.#rules[2];\n }\n\n #renameAccountWalletIfNeeded(wallet: AccountWalletObject) {\n if (wallet.metadata.name) {\n return;\n }\n\n if (wallet.type === AccountWalletType.Entropy) {\n wallet.metadata.name =\n this.#getEntropyRule().getDefaultAccountWalletName(wallet);\n } else if (wallet.type === AccountWalletType.Snap) {\n wallet.metadata.name =\n this.#getSnapRule().getDefaultAccountWalletName(wallet);\n } else {\n wallet.metadata.name =\n this.#getKeyringRule().getDefaultAccountWalletName(wallet);\n }\n }\n\n #renameAccountGroupIfNeeded(\n wallet: AccountWalletObject,\n group: AccountGroupObject,\n ) {\n if (group.metadata.name) {\n return;\n }\n\n if (wallet.type === AccountWalletType.Entropy) {\n group.metadata.name = this.#getEntropyRule().getDefaultAccountGroupName(\n // Get the group from the wallet, to get the proper type inference.\n wallet.groups[group.id],\n );\n } else if (wallet.type === AccountWalletType.Snap) {\n group.metadata.name = this.#getSnapRule().getDefaultAccountGroupName(\n // Same here.\n wallet.groups[group.id],\n );\n } else {\n group.metadata.name = this.#getKeyringRule().getDefaultAccountGroupName(\n // Same here.\n wallet.groups[group.id],\n );\n }\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.#getDefaultAccountGroupId(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 const result =\n this.#getEntropyRule().match(account) ??\n this.#getSnapRule().match(account) ??\n this.#getKeyringRule().match(account); // This one cannot fail.\n\n // Update controller's state.\n const walletId = result.wallet.id;\n let wallet = wallets[walletId];\n if (!wallet) {\n wallets[walletId] = {\n ...result.wallet,\n groups: {},\n metadata: {\n name: '', // Will get updated later.\n ...result.wallet.metadata,\n },\n // We do need to type-cast since we're not narrowing `result` with\n // the union tag `result.wallet.type`.\n } as AccountWalletObject;\n wallet = wallets[walletId];\n }\n\n const groupId = result.group.id;\n let group = wallet.groups[groupId];\n if (!group) {\n wallet.groups[groupId] = {\n ...result.group,\n // Type-wise, we are guaranteed to always have at least 1 account.\n accounts: [account.id],\n metadata: {\n name: '',\n ...result.group.metadata,\n },\n // We do need to type-cast since we're not narrowing `result` with\n // the union tag `result.group.type`.\n } as AccountGroupObject;\n group = wallet.groups[groupId];\n } else {\n group.accounts.push(account.id);\n }\n\n // Update the reverse mapping for this account.\n this.#accountIdToContext.set(account.id, {\n walletId: wallet.id,\n groupId: group.id,\n });\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.#getDefaultAccountFromAccountGroupId(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 * 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 default group in case of errors.\n return this.#getDefaultAccountGroupId(wallets);\n }\n\n /**\n * Handles selected account change from AccountsController.\n * Updates selectedAccountGroup to match the selected account.\n *\n * @param account - The newly selected account.\n */\n #handleSelectedAccountChange(account: InternalAccount): void {\n const accountMapping = this.#accountIdToContext.get(account.id);\n if (!accountMapping) {\n // Account not in tree yet, might be during initialization\n return;\n }\n\n const { groupId } = accountMapping;\n 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 account group.\n *\n * @param groupId - The account group ID.\n * @returns The account group or undefined if not found.\n */\n #getAccountGroup(groupId: AccountGroupId): AccountGroupObject | undefined {\n const found = Object.values(this.state.accountTree.wallets).find(\n (wallet) => wallet.groups[groupId] !== undefined,\n );\n\n return found?.groups[groupId];\n }\n\n /**\n * Gets the default account for 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 #getDefaultAccountFromAccountGroupId(\n groupId: AccountGroupId,\n ): AccountId | undefined {\n const group = this.#getAccountGroup(groupId);\n\n if (group) {\n let candidate;\n for (const id of group.accounts) {\n const account = this.messagingSystem.call(\n 'AccountsController:getAccount',\n id,\n );\n\n if (!candidate) {\n candidate = id;\n }\n if (account && isEvmAccountType(account.type)) {\n // EVM accounts have a higher priority, so if we find any, we just\n // use that account!\n return account.id;\n }\n }\n\n return candidate;\n }\n\n return undefined;\n }\n\n /**\n * Gets the default group id, which is either, the first non-empty group that contains an EVM account or\n * just the first non-empty group with any accounts.\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 #getDefaultAccountGroupId(wallets: {\n [walletId: AccountWalletId]: AccountWalletObject;\n }): AccountGroupId | '' {\n let candidate: AccountGroupId | '' = '';\n\n for (const wallet of Object.values(wallets)) {\n for (const group of Object.values(wallet.groups)) {\n // We only update the candidate with the first non-empty group, but still\n // try to find a group that contains an EVM account (the `candidate` is\n // our fallback).\n if (candidate === '' && group.accounts.length > 0) {\n candidate = group.id;\n }\n\n for (const id of group.accounts) {\n const account = this.messagingSystem.call(\n 'AccountsController:getAccount',\n id,\n );\n\n if (account && isEvmAccountType(account.type)) {\n // EVM accounts have a higher priority, so if we find any, we just\n // use that group!\n return group.id;\n }\n }\n }\n }\n return candidate;\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"]}
|
|
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 { AccountWalletType } 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 { isEvmAccountType } from '@metamask/keyring-api';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\n\nimport type { AccountGroupObject } from './group';\nimport { EntropyRule } from './rules/entropy';\nimport { KeyringRule } from './rules/keyring';\nimport { SnapRule } from './rules/snap';\nimport type {\n AccountTreeControllerMessenger,\n AccountTreeControllerState,\n} from './types';\nimport type { AccountWalletObject } from './wallet';\nimport { AccountTreeWallet } from './wallet';\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 accountGroupsMetadata: {\n persist: true,\n anonymous: false,\n },\n accountWalletsMetadata: {\n persist: true,\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 accountGroupsMetadata: {},\n accountWalletsMetadata: {},\n };\n}\n\n/**\n * Context for an account.\n */\nexport type AccountContext = {\n /**\n * Wallet ID associated to that account.\n */\n walletId: AccountWalletObject['id'];\n\n /**\n * Account group ID associated to that account.\n */\n groupId: AccountGroupObject['id'];\n};\n\nexport class AccountTreeController extends BaseController<\n typeof controllerName,\n AccountTreeControllerState,\n AccountTreeControllerMessenger\n> {\n readonly #accountIdToContext: Map<AccountId, AccountContext>;\n\n // Mapping for direct tree node access\n readonly #groupIdToWalletId: Map<AccountGroupId, AccountWalletId>;\n\n readonly #rules: [EntropyRule, SnapRule, KeyringRule];\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 this.#groupIdToWalletId = new Map();\n\n // Rules to apply to construct the wallets tree.\n this.#rules = [\n // 1. We group by entropy-source\n new EntropyRule(this.messagingSystem),\n // 2. We group by Snap ID\n new SnapRule(this.messagingSystem),\n // 3. We group by wallet type (this rule cannot fail and will group all non-matching accounts)\n new KeyringRule(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 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 // Clear mappings for fresh rebuild\n this.#accountIdToContext.clear();\n this.#groupIdToWalletId.clear();\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 apply persisted metadata (names + UI states).\n for (const wallet of Object.values(wallets)) {\n this.#applyAccountWalletMetadata(wallet);\n\n for (const group of Object.values(wallet.groups)) {\n this.#applyAccountGroupMetadata(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 #getEntropyRule(): EntropyRule {\n return this.#rules[0];\n }\n\n #getSnapRule(): SnapRule {\n return this.#rules[1];\n }\n\n #getKeyringRule(): KeyringRule {\n return this.#rules[2];\n }\n\n #applyAccountWalletMetadata(wallet: AccountWalletObject) {\n const persistedMetadata = this.state.accountWalletsMetadata[wallet.id];\n\n // Apply persisted name if available\n if (persistedMetadata?.name?.value) {\n wallet.metadata.name = persistedMetadata.name.value;\n } else if (!wallet.metadata.name) {\n // Generate default name if none exists\n if (wallet.type === AccountWalletType.Entropy) {\n wallet.metadata.name =\n this.#getEntropyRule().getDefaultAccountWalletName(wallet);\n } else if (wallet.type === AccountWalletType.Snap) {\n wallet.metadata.name =\n this.#getSnapRule().getDefaultAccountWalletName(wallet);\n } else {\n wallet.metadata.name =\n this.#getKeyringRule().getDefaultAccountWalletName(wallet);\n }\n }\n }\n\n #applyAccountGroupMetadata(\n wallet: AccountWalletObject,\n group: AccountGroupObject,\n ) {\n const persistedMetadata = this.state.accountGroupsMetadata[group.id];\n\n // Apply persisted name if available\n if (persistedMetadata?.name?.value) {\n group.metadata.name = persistedMetadata.name.value;\n } else if (!group.metadata.name) {\n // Generate default name if none exists\n if (wallet.type === AccountWalletType.Entropy) {\n group.metadata.name = this.#getEntropyRule().getDefaultAccountGroupName(\n // Get the group from the wallet, to get the proper type inference.\n wallet.groups[group.id],\n );\n } else if (wallet.type === AccountWalletType.Snap) {\n group.metadata.name = this.#getSnapRule().getDefaultAccountGroupName(\n // Same here.\n wallet.groups[group.id],\n );\n } else {\n group.metadata.name = this.#getKeyringRule().getDefaultAccountGroupName(\n // Same here.\n wallet.groups[group.id],\n );\n }\n }\n\n // Apply persisted UI states\n if (persistedMetadata?.pinned?.value !== undefined) {\n group.metadata.pinned = persistedMetadata.pinned.value;\n }\n if (persistedMetadata?.hidden?.value !== undefined) {\n group.metadata.hidden = persistedMetadata.hidden.value;\n }\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.#applyAccountWalletMetadata(wallet);\n\n const group = wallet.groups[groupId];\n if (group) {\n this.#applyAccountGroupMetadata(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.#getDefaultAccountGroupId(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 const result =\n this.#getEntropyRule().match(account) ??\n this.#getSnapRule().match(account) ??\n this.#getKeyringRule().match(account); // This one cannot fail.\n\n // Update controller's state.\n const walletId = result.wallet.id;\n let wallet = wallets[walletId];\n if (!wallet) {\n wallets[walletId] = {\n ...result.wallet,\n groups: {},\n metadata: {\n name: '', // Will get updated later.\n ...result.wallet.metadata,\n },\n // We do need to type-cast since we're not narrowing `result` with\n // the union tag `result.wallet.type`.\n } as AccountWalletObject;\n wallet = wallets[walletId];\n }\n\n const groupId = result.group.id;\n let group = wallet.groups[groupId];\n if (!group) {\n wallet.groups[groupId] = {\n ...result.group,\n // Type-wise, we are guaranteed to always have at least 1 account.\n accounts: [account.id],\n metadata: {\n name: '',\n ...result.group.metadata,\n pinned: false, // Default UI state\n hidden: false, // Default UI state\n },\n // We do need to type-cast since we're not narrowing `result` with\n // the union tag `result.group.type`.\n } as AccountGroupObject;\n group = wallet.groups[groupId];\n\n // Map group ID to its containing wallet ID for efficient direct access\n this.#groupIdToWalletId.set(groupId, walletId);\n } else {\n group.accounts.push(account.id);\n }\n\n // Update the reverse mapping for this account.\n this.#accountIdToContext.set(account.id, {\n walletId: wallet.id,\n groupId: group.id,\n });\n }\n\n #listAccounts(): InternalAccount[] {\n return this.messagingSystem.call(\n 'AccountsController:listMultichainAccounts',\n );\n }\n\n /**\n * Asserts that a group exists in the current account tree.\n *\n * @param groupId - The account group ID to validate.\n * @throws Error if the group does not exist.\n */\n #assertAccountGroupExists(groupId: AccountGroupId): void {\n const exists = this.#groupIdToWalletId.has(groupId);\n if (!exists) {\n throw new Error(`Account group with ID \"${groupId}\" not found in tree`);\n }\n }\n\n /**\n * Asserts that a wallet exists in the current account tree.\n *\n * @param walletId - The account wallet ID to validate.\n * @throws Error if the wallet does not exist.\n */\n #assertAccountWalletExists(walletId: AccountWalletId): void {\n const exists = Boolean(this.state.accountTree.wallets[walletId]);\n if (!exists) {\n throw new Error(`Account wallet with ID \"${walletId}\" not found in tree`);\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.#getDefaultAccountFromAccountGroupId(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 * 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 default group in case of errors.\n return this.#getDefaultAccountGroupId(wallets);\n }\n\n /**\n * Handles selected account change from AccountsController.\n * Updates selectedAccountGroup to match the selected account.\n *\n * @param account - The newly selected account.\n */\n #handleSelectedAccountChange(account: InternalAccount): void {\n const accountMapping = this.#accountIdToContext.get(account.id);\n if (!accountMapping) {\n // Account not in tree yet, might be during initialization\n return;\n }\n\n const { groupId } = accountMapping;\n 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 account group.\n *\n * @param groupId - The account group ID.\n * @returns The account group or undefined if not found.\n */\n #getAccountGroup(groupId: AccountGroupId): AccountGroupObject | undefined {\n const found = Object.values(this.state.accountTree.wallets).find(\n (wallet) => wallet.groups[groupId] !== undefined,\n );\n\n return found?.groups[groupId];\n }\n\n /**\n * Gets the default account for 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 #getDefaultAccountFromAccountGroupId(\n groupId: AccountGroupId,\n ): AccountId | undefined {\n const group = this.#getAccountGroup(groupId);\n\n if (group) {\n let candidate;\n for (const id of group.accounts) {\n const account = this.messagingSystem.call(\n 'AccountsController:getAccount',\n id,\n );\n\n if (!candidate) {\n candidate = id;\n }\n if (account && isEvmAccountType(account.type)) {\n // EVM accounts have a higher priority, so if we find any, we just\n // use that account!\n return account.id;\n }\n }\n\n return candidate;\n }\n\n return undefined;\n }\n\n /**\n * Gets the default group id, which is either, the first non-empty group that contains an EVM account or\n * just the first non-empty group with any accounts.\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 #getDefaultAccountGroupId(wallets: {\n [walletId: AccountWalletId]: AccountWalletObject;\n }): AccountGroupId | '' {\n let candidate: AccountGroupId | '' = '';\n\n for (const wallet of Object.values(wallets)) {\n for (const group of Object.values(wallet.groups)) {\n // We only update the candidate with the first non-empty group, but still\n // try to find a group that contains an EVM account (the `candidate` is\n // our fallback).\n if (candidate === '' && group.accounts.length > 0) {\n candidate = group.id;\n }\n\n for (const id of group.accounts) {\n const account = this.messagingSystem.call(\n 'AccountsController:getAccount',\n id,\n );\n\n if (account && isEvmAccountType(account.type)) {\n // EVM accounts have a higher priority, so if we find any, we just\n // use that group!\n return group.id;\n }\n }\n }\n }\n return candidate;\n }\n\n /**\n * Sets a custom name for an account group.\n *\n * @param groupId - The account group ID.\n * @param name - The custom name to set.\n * @throws If the account group ID is not found in the current tree.\n */\n setAccountGroupName(groupId: AccountGroupId, name: string): void {\n // Validate that the group exists in the current tree\n this.#assertAccountGroupExists(groupId);\n\n this.update((state) => {\n // Update persistent metadata\n state.accountGroupsMetadata[groupId] ??= {};\n state.accountGroupsMetadata[groupId].name = {\n value: name,\n lastUpdatedAt: Date.now(),\n };\n\n // Update tree node directly using efficient mapping\n const walletId = this.#groupIdToWalletId.get(groupId);\n if (walletId) {\n state.accountTree.wallets[walletId].groups[groupId].metadata.name =\n name;\n }\n });\n }\n\n /**\n * Sets a custom name for an account wallet.\n *\n * @param walletId - The account wallet ID.\n * @param name - The custom name to set.\n * @throws If the account wallet ID is not found in the current tree.\n */\n setAccountWalletName(walletId: AccountWalletId, name: string): void {\n // Validate that the wallet exists in the current tree\n this.#assertAccountWalletExists(walletId);\n\n this.update((state) => {\n // Update persistent metadata\n state.accountWalletsMetadata[walletId] ??= {};\n state.accountWalletsMetadata[walletId].name = {\n value: name,\n lastUpdatedAt: Date.now(),\n };\n\n // Update tree node directly\n state.accountTree.wallets[walletId].metadata.name = name;\n });\n }\n\n /**\n * Toggles the pinned state of an account group.\n *\n * @param groupId - The account group ID.\n * @param pinned - Whether the group should be pinned.\n * @throws If the account group ID is not found in the current tree.\n */\n setAccountGroupPinned(groupId: AccountGroupId, pinned: boolean): void {\n // Validate that the group exists in the current tree\n this.#assertAccountGroupExists(groupId);\n\n this.update((state) => {\n // Update persistent metadata\n state.accountGroupsMetadata[groupId] ??= {};\n state.accountGroupsMetadata[groupId].pinned = {\n value: pinned,\n lastUpdatedAt: Date.now(),\n };\n\n // Update tree node directly using efficient mapping\n const walletId = this.#groupIdToWalletId.get(groupId);\n if (walletId) {\n state.accountTree.wallets[walletId].groups[groupId].metadata.pinned =\n pinned;\n }\n });\n }\n\n /**\n * Toggles the hidden state of an account group.\n *\n * @param groupId - The account group ID.\n * @param hidden - Whether the group should be hidden.\n * @throws If the account group ID is not found in the current tree.\n */\n setAccountGroupHidden(groupId: AccountGroupId, hidden: boolean): void {\n // Validate that the group exists in the current tree\n this.#assertAccountGroupExists(groupId);\n\n this.update((state) => {\n // Update persistent metadata\n state.accountGroupsMetadata[groupId] ??= {};\n state.accountGroupsMetadata[groupId].hidden = {\n value: hidden,\n lastUpdatedAt: Date.now(),\n };\n\n // Update tree node directly using efficient mapping\n const walletId = this.#groupIdToWalletId.get(groupId);\n if (walletId) {\n state.accountTree.wallets[walletId].groups[groupId].metadata.hidden =\n hidden;\n }\n });\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"]}
|
package/dist/group.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"group.cjs","sourceRoot":"","sources":["../src/group.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"group.cjs","sourceRoot":"","sources":["../src/group.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAiCa,QAAA,0BAA0B,GAAW,SAAS,CAAC;AA6D5D;;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,IAAI,CAAC;IAC1B,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,GAAG,CAAC,EAAE;YACzB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;SACvD;QAED,4CAA4C;QAC5C,OAAO,uBAAA,IAAI,iEAAY,MAAhB,IAAI,EAAa,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;CACF;AApED,4CAoEC;kPAvBa,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 {\n AccountGroupType,\n MultichainAccountGroupId,\n} from '@metamask/account-api';\nimport type { AccountGroup, AccountGroupId } from '@metamask/account-api';\nimport type { AccountId } from '@metamask/accounts-controller';\nimport type { InternalAccount } from '@metamask/keyring-internal-api';\n\nimport type {\n UpdatableField,\n ExtractRequiredFieldValues,\n} from './type-utils.js';\nimport type { AccountTreeControllerMessenger } from './types';\nimport type { AccountTreeWallet } from './wallet';\n\n/**\n * Persisted metadata for account groups (stored in controller state for persistence/sync).\n */\nexport type AccountGroupPersistedMetadata = {\n /** Custom name set by user, overrides default naming logic */\n name?: UpdatableField<string>;\n /** Whether this group is pinned in the UI */\n pinned?: UpdatableField<boolean>;\n /** Whether this group is hidden in the UI */\n hidden?: UpdatableField<boolean>;\n};\n\n/**\n * Tree metadata for account groups (required plain values extracted from persisted metadata).\n */\nexport type AccountGroupTreeMetadata =\n ExtractRequiredFieldValues<AccountGroupPersistedMetadata>;\n\nexport const DEFAULT_ACCOUNT_GROUP_NAME: string = 'Default';\n\n/**\n * Type constraint for a {@link AccountGroupObject}. If one of its union-members\n * does not match this contraint, {@link AccountGroupObject} will resolve\n * to `never`.\n */\ntype IsAccountGroupObject<\n Type extends {\n type: AccountGroupType;\n id: AccountGroupId;\n accounts: AccountId[];\n metadata: AccountGroupTreeMetadata;\n },\n> = Type;\n\n/**\n * Multichain-account group object.\n */\nexport type AccountGroupMultichainAccountObject = {\n type: AccountGroupType.MultichainAccount;\n id: MultichainAccountGroupId;\n // Blockchain Accounts (at least 1 account per multichain-accounts):\n accounts: [AccountId, ...AccountId[]];\n metadata: AccountGroupTreeMetadata & {\n entropy: {\n groupIndex: number;\n };\n };\n};\n\n/**\n * Multichain-account group object.\n */\nexport type AccountGroupSingleAccountObject = {\n type: AccountGroupType.SingleAccount;\n id: AccountGroupId;\n // Blockchain Accounts (1 account per group):\n accounts: [AccountId];\n metadata: AccountGroupTreeMetadata;\n};\n\n/**\n * Account group object.\n */\nexport type AccountGroupObject = IsAccountGroupObject<\n AccountGroupMultichainAccountObject | AccountGroupSingleAccountObject\n>;\n\nexport type AccountGroupObjectOf<GroupType extends AccountGroupType> = Extract<\n | {\n type: AccountGroupType.MultichainAccount;\n object: AccountGroupMultichainAccountObject;\n }\n | {\n type: AccountGroupType.SingleAccount;\n object: AccountGroupSingleAccountObject;\n },\n { type: GroupType }\n>['object'];\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 type(): AccountGroupType {\n return this.#group.type;\n }\n\n get name(): string {\n return this.#group.metadata.name;\n }\n\n getAccountIds(): [InternalAccount['id'], ...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 > 1) {\n throw new Error('Group contains more than 1 account');\n }\n\n // A group always have at least one account.\n return this.#getAccount(accountIds[0]);\n }\n}\n"]}
|
package/dist/group.d.cts
CHANGED
|
@@ -2,8 +2,24 @@ import type { AccountGroupType, MultichainAccountGroupId } from "@metamask/accou
|
|
|
2
2
|
import type { AccountGroup, AccountGroupId } from "@metamask/account-api";
|
|
3
3
|
import type { AccountId } from "@metamask/accounts-controller";
|
|
4
4
|
import type { InternalAccount } from "@metamask/keyring-internal-api";
|
|
5
|
+
import type { UpdatableField, ExtractRequiredFieldValues } from "./type-utils.cjs";
|
|
5
6
|
import type { AccountTreeControllerMessenger } from "./types.cjs";
|
|
6
7
|
import type { AccountTreeWallet } from "./wallet.cjs";
|
|
8
|
+
/**
|
|
9
|
+
* Persisted metadata for account groups (stored in controller state for persistence/sync).
|
|
10
|
+
*/
|
|
11
|
+
export type AccountGroupPersistedMetadata = {
|
|
12
|
+
/** Custom name set by user, overrides default naming logic */
|
|
13
|
+
name?: UpdatableField<string>;
|
|
14
|
+
/** Whether this group is pinned in the UI */
|
|
15
|
+
pinned?: UpdatableField<boolean>;
|
|
16
|
+
/** Whether this group is hidden in the UI */
|
|
17
|
+
hidden?: UpdatableField<boolean>;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Tree metadata for account groups (required plain values extracted from persisted metadata).
|
|
21
|
+
*/
|
|
22
|
+
export type AccountGroupTreeMetadata = ExtractRequiredFieldValues<AccountGroupPersistedMetadata>;
|
|
7
23
|
export declare const DEFAULT_ACCOUNT_GROUP_NAME: string;
|
|
8
24
|
/**
|
|
9
25
|
* Type constraint for a {@link AccountGroupObject}. If one of its union-members
|
|
@@ -14,9 +30,7 @@ type IsAccountGroupObject<Type extends {
|
|
|
14
30
|
type: AccountGroupType;
|
|
15
31
|
id: AccountGroupId;
|
|
16
32
|
accounts: AccountId[];
|
|
17
|
-
metadata:
|
|
18
|
-
name: string;
|
|
19
|
-
};
|
|
33
|
+
metadata: AccountGroupTreeMetadata;
|
|
20
34
|
}> = Type;
|
|
21
35
|
/**
|
|
22
36
|
* Multichain-account group object.
|
|
@@ -25,8 +39,7 @@ export type AccountGroupMultichainAccountObject = {
|
|
|
25
39
|
type: AccountGroupType.MultichainAccount;
|
|
26
40
|
id: MultichainAccountGroupId;
|
|
27
41
|
accounts: [AccountId, ...AccountId[]];
|
|
28
|
-
metadata: {
|
|
29
|
-
name: string;
|
|
42
|
+
metadata: AccountGroupTreeMetadata & {
|
|
30
43
|
entropy: {
|
|
31
44
|
groupIndex: number;
|
|
32
45
|
};
|
|
@@ -39,9 +52,7 @@ export type AccountGroupSingleAccountObject = {
|
|
|
39
52
|
type: AccountGroupType.SingleAccount;
|
|
40
53
|
id: AccountGroupId;
|
|
41
54
|
accounts: [AccountId];
|
|
42
|
-
metadata:
|
|
43
|
-
name: string;
|
|
44
|
-
};
|
|
55
|
+
metadata: AccountGroupTreeMetadata;
|
|
45
56
|
};
|
|
46
57
|
/**
|
|
47
58
|
* Account group object.
|
package/dist/group.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"group.d.cts","sourceRoot":"","sources":["../src/group.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,wBAAwB,EACzB,8BAA8B;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,8BAA8B;AAC1E,OAAO,KAAK,EAAE,SAAS,EAAE,sCAAsC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAEtE,OAAO,KAAK,EAAE,8BAA8B,EAAE,oBAAgB;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAiB;AAElD,eAAO,MAAM,0BAA0B,EAAE,MAAkB,CAAC;AAE5D;;;;GAIG;AACH,KAAK,oBAAoB,CACvB,IAAI,SAAS;IACX,IAAI,EAAE,gBAAgB,CAAC;IACvB,EAAE,EAAE,cAAc,CAAC;IACnB,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,QAAQ,EAAE
|
|
1
|
+
{"version":3,"file":"group.d.cts","sourceRoot":"","sources":["../src/group.ts"],"names":[],"mappings":"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"}
|
package/dist/group.d.mts
CHANGED
|
@@ -2,8 +2,24 @@ import type { AccountGroupType, MultichainAccountGroupId } from "@metamask/accou
|
|
|
2
2
|
import type { AccountGroup, AccountGroupId } from "@metamask/account-api";
|
|
3
3
|
import type { AccountId } from "@metamask/accounts-controller";
|
|
4
4
|
import type { InternalAccount } from "@metamask/keyring-internal-api";
|
|
5
|
+
import type { UpdatableField, ExtractRequiredFieldValues } from "./type-utils.mjs";
|
|
5
6
|
import type { AccountTreeControllerMessenger } from "./types.mjs";
|
|
6
7
|
import type { AccountTreeWallet } from "./wallet.mjs";
|
|
8
|
+
/**
|
|
9
|
+
* Persisted metadata for account groups (stored in controller state for persistence/sync).
|
|
10
|
+
*/
|
|
11
|
+
export type AccountGroupPersistedMetadata = {
|
|
12
|
+
/** Custom name set by user, overrides default naming logic */
|
|
13
|
+
name?: UpdatableField<string>;
|
|
14
|
+
/** Whether this group is pinned in the UI */
|
|
15
|
+
pinned?: UpdatableField<boolean>;
|
|
16
|
+
/** Whether this group is hidden in the UI */
|
|
17
|
+
hidden?: UpdatableField<boolean>;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Tree metadata for account groups (required plain values extracted from persisted metadata).
|
|
21
|
+
*/
|
|
22
|
+
export type AccountGroupTreeMetadata = ExtractRequiredFieldValues<AccountGroupPersistedMetadata>;
|
|
7
23
|
export declare const DEFAULT_ACCOUNT_GROUP_NAME: string;
|
|
8
24
|
/**
|
|
9
25
|
* Type constraint for a {@link AccountGroupObject}. If one of its union-members
|
|
@@ -14,9 +30,7 @@ type IsAccountGroupObject<Type extends {
|
|
|
14
30
|
type: AccountGroupType;
|
|
15
31
|
id: AccountGroupId;
|
|
16
32
|
accounts: AccountId[];
|
|
17
|
-
metadata:
|
|
18
|
-
name: string;
|
|
19
|
-
};
|
|
33
|
+
metadata: AccountGroupTreeMetadata;
|
|
20
34
|
}> = Type;
|
|
21
35
|
/**
|
|
22
36
|
* Multichain-account group object.
|
|
@@ -25,8 +39,7 @@ export type AccountGroupMultichainAccountObject = {
|
|
|
25
39
|
type: AccountGroupType.MultichainAccount;
|
|
26
40
|
id: MultichainAccountGroupId;
|
|
27
41
|
accounts: [AccountId, ...AccountId[]];
|
|
28
|
-
metadata: {
|
|
29
|
-
name: string;
|
|
42
|
+
metadata: AccountGroupTreeMetadata & {
|
|
30
43
|
entropy: {
|
|
31
44
|
groupIndex: number;
|
|
32
45
|
};
|
|
@@ -39,9 +52,7 @@ export type AccountGroupSingleAccountObject = {
|
|
|
39
52
|
type: AccountGroupType.SingleAccount;
|
|
40
53
|
id: AccountGroupId;
|
|
41
54
|
accounts: [AccountId];
|
|
42
|
-
metadata:
|
|
43
|
-
name: string;
|
|
44
|
-
};
|
|
55
|
+
metadata: AccountGroupTreeMetadata;
|
|
45
56
|
};
|
|
46
57
|
/**
|
|
47
58
|
* Account group object.
|
package/dist/group.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"group.d.mts","sourceRoot":"","sources":["../src/group.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,wBAAwB,EACzB,8BAA8B;AAC/B,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,8BAA8B;AAC1E,OAAO,KAAK,EAAE,SAAS,EAAE,sCAAsC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,uCAAuC;AAEtE,OAAO,KAAK,EAAE,8BAA8B,EAAE,oBAAgB;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,qBAAiB;AAElD,eAAO,MAAM,0BAA0B,EAAE,MAAkB,CAAC;AAE5D;;;;GAIG;AACH,KAAK,oBAAoB,CACvB,IAAI,SAAS;IACX,IAAI,EAAE,gBAAgB,CAAC;IACvB,EAAE,EAAE,cAAc,CAAC;IACnB,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,QAAQ,EAAE
|
|
1
|
+
{"version":3,"file":"group.d.mts","sourceRoot":"","sources":["../src/group.ts"],"names":[],"mappings":"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"}
|