@metamask/accounts-controller 13.0.0 → 15.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +34 -1
- package/dist/AccountsController.js +4 -3
- package/dist/AccountsController.mjs +3 -2
- package/dist/{chunk-JNCGDLI7.mjs → chunk-3R7MA6KV.mjs} +188 -56
- package/dist/chunk-3R7MA6KV.mjs.map +1 -0
- package/dist/{chunk-HS62N4JH.js → chunk-7CWWNB3P.js} +204 -72
- package/dist/chunk-7CWWNB3P.js.map +1 -0
- package/dist/{chunk-KCST55AQ.js → chunk-EIQ5DUI6.js} +10 -17
- package/dist/chunk-EIQ5DUI6.js.map +1 -0
- package/dist/chunk-IBSI66UQ.js +65 -0
- package/dist/chunk-IBSI66UQ.js.map +1 -0
- package/dist/chunk-QAHRSXGM.mjs +65 -0
- package/dist/chunk-QAHRSXGM.mjs.map +1 -0
- package/dist/chunk-UJIPPGP6.js +19 -0
- package/dist/chunk-UJIPPGP6.js.map +1 -0
- package/dist/{chunk-E7SBT5BV.mjs → chunk-YNILZSBK.mjs} +11 -18
- package/dist/chunk-YNILZSBK.mjs.map +1 -0
- package/dist/chunk-ZNSHBDHA.mjs +19 -0
- package/dist/chunk-ZNSHBDHA.mjs.map +1 -0
- package/dist/index.js +8 -3
- package/dist/index.mjs +7 -2
- package/dist/tests/mocks.js +8 -0
- package/dist/tests/mocks.js.map +1 -0
- package/dist/tests/mocks.mjs +8 -0
- package/dist/tests/mocks.mjs.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/AccountsController.d.ts +39 -4
- package/dist/types/AccountsController.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/tests/mocks.d.ts +17 -0
- package/dist/types/tests/mocks.d.ts.map +1 -0
- package/dist/types/utils.d.ts +19 -0
- package/dist/types/utils.d.ts.map +1 -1
- package/dist/utils.js +7 -2
- package/dist/utils.mjs +6 -1
- package/package.json +10 -10
- package/dist/chunk-E7SBT5BV.mjs.map +0 -1
- package/dist/chunk-HS62N4JH.js.map +0 -1
- package/dist/chunk-JNCGDLI7.mjs.map +0 -1
- package/dist/chunk-KCST55AQ.js.map +0 -1
@@ -3,13 +3,25 @@
|
|
3
3
|
|
4
4
|
|
5
5
|
|
6
|
-
var
|
6
|
+
var _chunkEIQ5DUI6js = require('./chunk-EIQ5DUI6.js');
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
var _chunkUJIPPGP6js = require('./chunk-UJIPPGP6.js');
|
7
11
|
|
8
12
|
// src/AccountsController.ts
|
9
13
|
var _basecontroller = require('@metamask/base-controller');
|
10
14
|
var _ethsnapkeyring = require('@metamask/eth-snap-keyring');
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
11
19
|
var _keyringapi = require('@metamask/keyring-api');
|
12
20
|
var _keyringcontroller = require('@metamask/keyring-controller');
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
var _utils = require('@metamask/utils');
|
13
25
|
var controllerName = "AccountsController";
|
14
26
|
var accountsControllerMetadata = {
|
15
27
|
internalAccounts: {
|
@@ -23,7 +35,7 @@ var defaultState = {
|
|
23
35
|
selectedAccount: ""
|
24
36
|
}
|
25
37
|
};
|
26
|
-
var _generateInternalAccountForNonSnapAccount, generateInternalAccountForNonSnapAccount_fn, _listSnapAccounts, listSnapAccounts_fn, _listNormalAccounts, listNormalAccounts_fn, _handleOnKeyringStateChange, handleOnKeyringStateChange_fn, _handleOnSnapStateChange, handleOnSnapStateChange_fn, _getAccountsByKeyringType, getAccountsByKeyringType_fn,
|
38
|
+
var _generateInternalAccountForNonSnapAccount, generateInternalAccountForNonSnapAccount_fn, _listSnapAccounts, listSnapAccounts_fn, _listNormalAccounts, listNormalAccounts_fn, _handleOnKeyringStateChange, handleOnKeyringStateChange_fn, _handleOnSnapStateChange, handleOnSnapStateChange_fn, _getAccountsByKeyringType, getAccountsByKeyringType_fn, _getLastSelectedAccount, getLastSelectedAccount_fn, _isAccountCompatibleWithChain, isAccountCompatibleWithChain_fn, _handleNewAccountAdded, handleNewAccountAdded_fn, _handleAccountRemoved, handleAccountRemoved_fn, _populateExistingMetadata, populateExistingMetadata_fn, _registerMessageHandlers, registerMessageHandlers_fn;
|
27
39
|
var AccountsController = class extends _basecontroller.BaseController {
|
28
40
|
/**
|
29
41
|
* Constructor for AccountsController.
|
@@ -51,13 +63,13 @@ var AccountsController = class extends _basecontroller.BaseController {
|
|
51
63
|
* @param type - The type of the account.
|
52
64
|
* @returns The generated internal account.
|
53
65
|
*/
|
54
|
-
|
66
|
+
_chunkUJIPPGP6js.__privateAdd.call(void 0, this, _generateInternalAccountForNonSnapAccount);
|
55
67
|
/**
|
56
68
|
* Returns a list of internal accounts created using the SnapKeyring.
|
57
69
|
*
|
58
70
|
* @returns A promise that resolves to an array of InternalAccount objects.
|
59
71
|
*/
|
60
|
-
|
72
|
+
_chunkUJIPPGP6js.__privateAdd.call(void 0, this, _listSnapAccounts);
|
61
73
|
/**
|
62
74
|
* Returns a list of normal accounts.
|
63
75
|
* Note: listNormalAccounts is a temporary method until the keyrings all implement the InternalAccount interface.
|
@@ -65,57 +77,73 @@ var AccountsController = class extends _basecontroller.BaseController {
|
|
65
77
|
*
|
66
78
|
* @returns A Promise that resolves to an array of InternalAccount objects.
|
67
79
|
*/
|
68
|
-
|
80
|
+
_chunkUJIPPGP6js.__privateAdd.call(void 0, this, _listNormalAccounts);
|
69
81
|
/**
|
70
82
|
* Handles changes in the keyring state, specifically when new accounts are added or removed.
|
71
83
|
*
|
72
84
|
* @param keyringState - The new state of the keyring controller.
|
73
85
|
*/
|
74
|
-
|
86
|
+
_chunkUJIPPGP6js.__privateAdd.call(void 0, this, _handleOnKeyringStateChange);
|
75
87
|
/**
|
76
88
|
* Handles the change in SnapControllerState by updating the metadata of accounts that have a snap enabled.
|
77
89
|
*
|
78
90
|
* @param snapState - The new SnapControllerState.
|
79
91
|
*/
|
80
|
-
|
92
|
+
_chunkUJIPPGP6js.__privateAdd.call(void 0, this, _handleOnSnapStateChange);
|
81
93
|
/**
|
82
94
|
* Returns the list of accounts for a given keyring type.
|
83
95
|
* @param keyringType - The type of keyring.
|
84
96
|
* @returns The list of accounts associcated with this keyring type.
|
85
97
|
*/
|
86
|
-
|
98
|
+
_chunkUJIPPGP6js.__privateAdd.call(void 0, this, _getAccountsByKeyringType);
|
87
99
|
/**
|
88
|
-
* Returns the
|
89
|
-
*
|
90
|
-
* @
|
100
|
+
* Returns the last selected account from the given array of accounts.
|
101
|
+
*
|
102
|
+
* @param accounts - An array of InternalAccount objects.
|
103
|
+
* @returns The InternalAccount object that was last selected, or undefined if the array is empty.
|
91
104
|
*/
|
92
|
-
|
105
|
+
_chunkUJIPPGP6js.__privateAdd.call(void 0, this, _getLastSelectedAccount);
|
106
|
+
/**
|
107
|
+
* Checks if an account is compatible with a given chain namespace.
|
108
|
+
* @private
|
109
|
+
* @param account - The account to check compatibility for.
|
110
|
+
* @param chainId - The CAIP2 to check compatibility with.
|
111
|
+
* @returns Returns true if the account is compatible with the chain namespace, otherwise false.
|
112
|
+
*/
|
113
|
+
_chunkUJIPPGP6js.__privateAdd.call(void 0, this, _isAccountCompatibleWithChain);
|
93
114
|
/**
|
94
115
|
* Handles the addition of a new account to the controller.
|
95
116
|
* If the account is not a Snap Keyring account, generates an internal account for it and adds it to the controller.
|
96
117
|
* If the account is a Snap Keyring account, retrieves the account from the keyring and adds it to the controller.
|
97
118
|
* @param account - The address and keyring type object of the new account.
|
98
119
|
*/
|
99
|
-
|
120
|
+
_chunkUJIPPGP6js.__privateAdd.call(void 0, this, _handleNewAccountAdded);
|
100
121
|
/**
|
101
122
|
* Handles the removal of an account from the internal accounts list.
|
102
123
|
* @param accountId - The ID of the account to be removed.
|
103
124
|
*/
|
104
|
-
|
125
|
+
_chunkUJIPPGP6js.__privateAdd.call(void 0, this, _handleAccountRemoved);
|
126
|
+
/**
|
127
|
+
* Retrieves the value of a specific metadata key for an existing account.
|
128
|
+
* @param accountId - The ID of the account.
|
129
|
+
* @param metadataKey - The key of the metadata to retrieve.
|
130
|
+
* @returns The value of the specified metadata key, or undefined if the account or metadata key does not exist.
|
131
|
+
*/
|
132
|
+
_chunkUJIPPGP6js.__privateAdd.call(void 0, this, _populateExistingMetadata);
|
105
133
|
/**
|
106
134
|
* Registers message handlers for the AccountsController.
|
107
135
|
* @private
|
108
136
|
*/
|
109
|
-
|
137
|
+
_chunkUJIPPGP6js.__privateAdd.call(void 0, this, _registerMessageHandlers);
|
110
138
|
this.messagingSystem.subscribe(
|
111
139
|
"SnapController:stateChange",
|
112
|
-
(snapStateState) =>
|
140
|
+
(snapStateState) => _chunkUJIPPGP6js.__privateMethod.call(void 0, this, _handleOnSnapStateChange, handleOnSnapStateChange_fn).call(this, snapStateState)
|
113
141
|
);
|
114
142
|
this.messagingSystem.subscribe(
|
115
143
|
"KeyringController:stateChange",
|
116
|
-
(keyringState) =>
|
144
|
+
(keyringState) => _chunkUJIPPGP6js.__privateMethod.call(void 0, this, _handleOnKeyringStateChange, handleOnKeyringStateChange_fn).call(this, keyringState)
|
117
145
|
);
|
118
|
-
|
146
|
+
_chunkUJIPPGP6js.__privateMethod.call(void 0, this, _registerMessageHandlers, registerMessageHandlers_fn).call(this);
|
119
147
|
}
|
120
148
|
/**
|
121
149
|
* Returns the internal account object for the given account ID, if it exists.
|
@@ -127,12 +155,31 @@ var AccountsController = class extends _basecontroller.BaseController {
|
|
127
155
|
return this.state.internalAccounts.accounts[accountId];
|
128
156
|
}
|
129
157
|
/**
|
130
|
-
* Returns an array of all internal accounts.
|
158
|
+
* Returns an array of all evm internal accounts.
|
131
159
|
*
|
132
160
|
* @returns An array of InternalAccount objects.
|
133
161
|
*/
|
134
162
|
listAccounts() {
|
135
|
-
|
163
|
+
const accounts = Object.values(this.state.internalAccounts.accounts);
|
164
|
+
return accounts.filter((account) => _keyringapi.isEvmAccountType.call(void 0, account.type));
|
165
|
+
}
|
166
|
+
/**
|
167
|
+
* Returns an array of all internal accounts.
|
168
|
+
*
|
169
|
+
* @param chainId - The chain ID.
|
170
|
+
* @returns An array of InternalAccount objects.
|
171
|
+
*/
|
172
|
+
listMultichainAccounts(chainId) {
|
173
|
+
const accounts = Object.values(this.state.internalAccounts.accounts);
|
174
|
+
if (!chainId) {
|
175
|
+
return accounts;
|
176
|
+
}
|
177
|
+
if (!_utils.isCaipChainId.call(void 0, chainId)) {
|
178
|
+
throw new Error(`Invalid CAIP-2 chain ID: ${String(chainId)}`);
|
179
|
+
}
|
180
|
+
return accounts.filter(
|
181
|
+
(account) => _chunkUJIPPGP6js.__privateMethod.call(void 0, this, _isAccountCompatibleWithChain, isAccountCompatibleWithChain_fn).call(this, account, chainId)
|
182
|
+
);
|
136
183
|
}
|
137
184
|
/**
|
138
185
|
* Returns the internal account object for the given account ID.
|
@@ -153,7 +200,8 @@ var AccountsController = class extends _basecontroller.BaseController {
|
|
153
200
|
name: "",
|
154
201
|
keyring: {
|
155
202
|
type: ""
|
156
|
-
}
|
203
|
+
},
|
204
|
+
importTime: 0
|
157
205
|
}
|
158
206
|
};
|
159
207
|
}
|
@@ -164,12 +212,42 @@ var AccountsController = class extends _basecontroller.BaseController {
|
|
164
212
|
return account;
|
165
213
|
}
|
166
214
|
/**
|
167
|
-
* Returns the selected
|
215
|
+
* Returns the last selected evm account.
|
168
216
|
*
|
169
217
|
* @returns The selected internal account.
|
170
218
|
*/
|
171
219
|
getSelectedAccount() {
|
172
|
-
|
220
|
+
const selectedAccount = this.getAccountExpect(
|
221
|
+
this.state.internalAccounts.selectedAccount
|
222
|
+
);
|
223
|
+
if (_keyringapi.isEvmAccountType.call(void 0, selectedAccount.type)) {
|
224
|
+
return selectedAccount;
|
225
|
+
}
|
226
|
+
const accounts = this.listAccounts();
|
227
|
+
if (!accounts.length) {
|
228
|
+
throw new Error("No EVM accounts");
|
229
|
+
}
|
230
|
+
return _chunkUJIPPGP6js.__privateMethod.call(void 0, this, _getLastSelectedAccount, getLastSelectedAccount_fn).call(this, accounts);
|
231
|
+
}
|
232
|
+
/**
|
233
|
+
* __WARNING The return value may be undefined if there isn't an account for that chain id.__
|
234
|
+
*
|
235
|
+
* Retrieves the last selected account by chain ID.
|
236
|
+
*
|
237
|
+
* @param chainId - The chain ID to filter the accounts.
|
238
|
+
* @returns The last selected account compatible with the specified chain ID or undefined.
|
239
|
+
*/
|
240
|
+
getSelectedMultichainAccount(chainId) {
|
241
|
+
if (!chainId) {
|
242
|
+
return this.getAccountExpect(this.state.internalAccounts.selectedAccount);
|
243
|
+
}
|
244
|
+
if (!_utils.isCaipChainId.call(void 0, chainId)) {
|
245
|
+
throw new Error(`Invalid CAIP-2 chain ID: ${chainId}`);
|
246
|
+
}
|
247
|
+
const accounts = Object.values(this.state.internalAccounts.accounts).filter(
|
248
|
+
(account) => _chunkUJIPPGP6js.__privateMethod.call(void 0, this, _isAccountCompatibleWithChain, isAccountCompatibleWithChain_fn).call(this, account, chainId)
|
249
|
+
);
|
250
|
+
return _chunkUJIPPGP6js.__privateMethod.call(void 0, this, _getLastSelectedAccount, getLastSelectedAccount_fn).call(this, accounts);
|
173
251
|
}
|
174
252
|
/**
|
175
253
|
* Returns the account with the specified address.
|
@@ -193,6 +271,12 @@ var AccountsController = class extends _basecontroller.BaseController {
|
|
193
271
|
currentState.internalAccounts.accounts[account.id].metadata.lastSelected = Date.now();
|
194
272
|
currentState.internalAccounts.selectedAccount = account.id;
|
195
273
|
});
|
274
|
+
if (_keyringapi.isEvmAccountType.call(void 0, account.type)) {
|
275
|
+
this.messagingSystem.publish(
|
276
|
+
"AccountsController:selectedEvmAccountChange",
|
277
|
+
account
|
278
|
+
);
|
279
|
+
}
|
196
280
|
this.messagingSystem.publish(
|
197
281
|
"AccountsController:selectedAccountChange",
|
198
282
|
account
|
@@ -217,8 +301,9 @@ var AccountsController = class extends _basecontroller.BaseController {
|
|
217
301
|
...account,
|
218
302
|
metadata: { ...account.metadata, name: accountName }
|
219
303
|
};
|
220
|
-
|
221
|
-
internalAccount;
|
304
|
+
const newState = _chunkEIQ5DUI6js.deepCloneDraft.call(void 0, currentState);
|
305
|
+
newState.internalAccounts.accounts[accountId] = internalAccount;
|
306
|
+
return newState;
|
222
307
|
});
|
223
308
|
}
|
224
309
|
/**
|
@@ -228,19 +313,15 @@ var AccountsController = class extends _basecontroller.BaseController {
|
|
228
313
|
* @returns A Promise that resolves when the accounts have been updated.
|
229
314
|
*/
|
230
315
|
async updateAccounts() {
|
231
|
-
const snapAccounts = await
|
232
|
-
const normalAccounts =
|
233
|
-
(account) => !snapAccounts.find(
|
234
|
-
(snapAccount) => snapAccount.address === account.address
|
235
|
-
)
|
236
|
-
);
|
316
|
+
const snapAccounts = await _chunkUJIPPGP6js.__privateMethod.call(void 0, this, _listSnapAccounts, listSnapAccounts_fn).call(this);
|
317
|
+
const normalAccounts = await _chunkUJIPPGP6js.__privateMethod.call(void 0, this, _listNormalAccounts, listNormalAccounts_fn).call(this);
|
237
318
|
const keyringTypes = /* @__PURE__ */ new Map();
|
238
319
|
const previousAccounts = this.state.internalAccounts.accounts;
|
239
320
|
const accounts = [
|
240
321
|
...normalAccounts,
|
241
322
|
...snapAccounts
|
242
323
|
].reduce((internalAccountMap, internalAccount) => {
|
243
|
-
const keyringTypeName =
|
324
|
+
const keyringTypeName = _chunkEIQ5DUI6js.keyringTypeToName.call(void 0,
|
244
325
|
internalAccount.metadata.keyring.type
|
245
326
|
);
|
246
327
|
const keyringAccountIndex = keyringTypes.get(keyringTypeName) ?? 0;
|
@@ -254,14 +335,17 @@ var AccountsController = class extends _basecontroller.BaseController {
|
|
254
335
|
...internalAccount,
|
255
336
|
metadata: {
|
256
337
|
...internalAccount.metadata,
|
257
|
-
name:
|
258
|
-
|
338
|
+
name: _chunkUJIPPGP6js.__privateMethod.call(void 0, this, _populateExistingMetadata, populateExistingMetadata_fn).call(this, existingAccount?.id, "name") ?? `${keyringTypeName} ${keyringAccountIndex + 1}`,
|
339
|
+
importTime: _chunkUJIPPGP6js.__privateMethod.call(void 0, this, _populateExistingMetadata, populateExistingMetadata_fn).call(this, existingAccount?.id, "importTime") ?? Date.now(),
|
340
|
+
lastSelected: _chunkUJIPPGP6js.__privateMethod.call(void 0, this, _populateExistingMetadata, populateExistingMetadata_fn).call(this, existingAccount?.id, "lastSelected") ?? 0
|
259
341
|
}
|
260
342
|
};
|
261
343
|
return internalAccountMap;
|
262
344
|
}, {});
|
263
345
|
this.update((currentState) => {
|
264
|
-
|
346
|
+
const newState = _chunkEIQ5DUI6js.deepCloneDraft.call(void 0, currentState);
|
347
|
+
newState.internalAccounts.accounts = accounts;
|
348
|
+
return newState;
|
265
349
|
});
|
266
350
|
}
|
267
351
|
/**
|
@@ -272,15 +356,44 @@ var AccountsController = class extends _basecontroller.BaseController {
|
|
272
356
|
loadBackup(backup) {
|
273
357
|
if (backup.internalAccounts) {
|
274
358
|
this.update((currentState) => {
|
275
|
-
|
359
|
+
const newState = _chunkEIQ5DUI6js.deepCloneDraft.call(void 0, currentState);
|
360
|
+
newState.internalAccounts = backup.internalAccounts;
|
361
|
+
return newState;
|
276
362
|
});
|
277
363
|
}
|
278
364
|
}
|
365
|
+
/**
|
366
|
+
* Returns the next account number for a given keyring type.
|
367
|
+
* @param keyringType - The type of keyring.
|
368
|
+
* @returns An object containing the account prefix and index to use.
|
369
|
+
*/
|
370
|
+
getNextAvailableAccountName(keyringType = _keyringcontroller.KeyringTypes.hd) {
|
371
|
+
const keyringName = _chunkEIQ5DUI6js.keyringTypeToName.call(void 0, keyringType);
|
372
|
+
const keyringAccounts = _chunkUJIPPGP6js.__privateMethod.call(void 0, this, _getAccountsByKeyringType, getAccountsByKeyringType_fn).call(this, keyringType);
|
373
|
+
const lastDefaultIndexUsedForKeyringType = keyringAccounts.reduce(
|
374
|
+
(maxInternalAccountIndex, internalAccount) => {
|
375
|
+
const match = new RegExp(`${keyringName} ([0-9]+)$`, "u").exec(
|
376
|
+
internalAccount.metadata.name
|
377
|
+
);
|
378
|
+
if (match) {
|
379
|
+
const internalAccountIndex = parseInt(match[1], 10);
|
380
|
+
return Math.max(maxInternalAccountIndex, internalAccountIndex);
|
381
|
+
}
|
382
|
+
return maxInternalAccountIndex;
|
383
|
+
},
|
384
|
+
0
|
385
|
+
);
|
386
|
+
const index = Math.max(
|
387
|
+
keyringAccounts.length + 1,
|
388
|
+
lastDefaultIndexUsedForKeyringType + 1
|
389
|
+
);
|
390
|
+
return `${keyringName} ${index}`;
|
391
|
+
}
|
279
392
|
};
|
280
393
|
_generateInternalAccountForNonSnapAccount = new WeakSet();
|
281
394
|
generateInternalAccountForNonSnapAccount_fn = function(address, type) {
|
282
395
|
return {
|
283
|
-
id:
|
396
|
+
id: _chunkEIQ5DUI6js.getUUIDFromAddressOfNormalAccount.call(void 0, address),
|
284
397
|
address,
|
285
398
|
options: {},
|
286
399
|
methods: [
|
@@ -294,6 +407,7 @@ generateInternalAccountForNonSnapAccount_fn = function(address, type) {
|
|
294
407
|
type: _keyringapi.EthAccountType.Eoa,
|
295
408
|
metadata: {
|
296
409
|
name: "",
|
410
|
+
importTime: Date.now(),
|
297
411
|
keyring: {
|
298
412
|
type
|
299
413
|
}
|
@@ -323,8 +437,13 @@ listNormalAccounts_fn = async function() {
|
|
323
437
|
"KeyringController:getKeyringForAccount",
|
324
438
|
address
|
325
439
|
);
|
440
|
+
const keyringType = keyring.type;
|
441
|
+
if (!_chunkEIQ5DUI6js.isNormalKeyringType.call(void 0, keyringType)) {
|
442
|
+
continue;
|
443
|
+
}
|
444
|
+
const id = _chunkEIQ5DUI6js.getUUIDFromAddressOfNormalAccount.call(void 0, address);
|
326
445
|
internalAccounts.push({
|
327
|
-
id
|
446
|
+
id,
|
328
447
|
address,
|
329
448
|
options: {},
|
330
449
|
methods: [
|
@@ -337,16 +456,16 @@ listNormalAccounts_fn = async function() {
|
|
337
456
|
],
|
338
457
|
type: _keyringapi.EthAccountType.Eoa,
|
339
458
|
metadata: {
|
340
|
-
name: "",
|
459
|
+
name: _chunkUJIPPGP6js.__privateMethod.call(void 0, this, _populateExistingMetadata, populateExistingMetadata_fn).call(this, id, "name") ?? "",
|
460
|
+
importTime: _chunkUJIPPGP6js.__privateMethod.call(void 0, this, _populateExistingMetadata, populateExistingMetadata_fn).call(this, id, "importTime") ?? Date.now(),
|
461
|
+
lastSelected: _chunkUJIPPGP6js.__privateMethod.call(void 0, this, _populateExistingMetadata, populateExistingMetadata_fn).call(this, id, "lastSelected") ?? 0,
|
341
462
|
keyring: {
|
342
463
|
type: keyring.type
|
343
464
|
}
|
344
465
|
}
|
345
466
|
});
|
346
467
|
}
|
347
|
-
return internalAccounts
|
348
|
-
(account) => account.metadata.keyring.type !== _keyringcontroller.KeyringTypes.snap
|
349
|
-
);
|
468
|
+
return internalAccounts;
|
350
469
|
};
|
351
470
|
_handleOnKeyringStateChange = new WeakSet();
|
352
471
|
handleOnKeyringStateChange_fn = function(keyringState) {
|
@@ -391,7 +510,7 @@ handleOnKeyringStateChange_fn = function(keyringState) {
|
|
391
510
|
const addedAccounts = [];
|
392
511
|
const deletedAccounts = [];
|
393
512
|
for (const account of updatedNormalKeyringAddresses) {
|
394
|
-
if (!this.state.internalAccounts.accounts[
|
513
|
+
if (!this.state.internalAccounts.accounts[_chunkEIQ5DUI6js.getUUIDFromAddressOfNormalAccount.call(void 0, account.address)]) {
|
395
514
|
addedAccounts.push(account);
|
396
515
|
}
|
397
516
|
}
|
@@ -418,12 +537,12 @@ handleOnKeyringStateChange_fn = function(keyringState) {
|
|
418
537
|
}
|
419
538
|
if (deletedAccounts.length > 0) {
|
420
539
|
for (const account of deletedAccounts) {
|
421
|
-
|
540
|
+
_chunkUJIPPGP6js.__privateMethod.call(void 0, this, _handleAccountRemoved, handleAccountRemoved_fn).call(this, account.id);
|
422
541
|
}
|
423
542
|
}
|
424
543
|
if (addedAccounts.length > 0) {
|
425
544
|
for (const account of addedAccounts) {
|
426
|
-
|
545
|
+
_chunkUJIPPGP6js.__privateMethod.call(void 0, this, _handleNewAccountAdded, handleNewAccountAdded_fn).call(this, account);
|
427
546
|
}
|
428
547
|
}
|
429
548
|
if (!this.getAccount(this.state.internalAccounts.selectedAccount)) {
|
@@ -470,34 +589,30 @@ getAccountsByKeyringType_fn = function(keyringType) {
|
|
470
589
|
return internalAccount.metadata.keyring.type === keyringType;
|
471
590
|
});
|
472
591
|
};
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
keyringAccounts.length + 1,
|
492
|
-
lastDefaultIndexUsedForKeyringType + 1
|
493
|
-
);
|
494
|
-
return { accountPrefix: keyringName, indexToUse };
|
592
|
+
_getLastSelectedAccount = new WeakSet();
|
593
|
+
getLastSelectedAccount_fn = function(accounts) {
|
594
|
+
return accounts.reduce((prevAccount, currentAccount) => {
|
595
|
+
if (
|
596
|
+
// When the account is added, lastSelected will be set
|
597
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
598
|
+
currentAccount.metadata.lastSelected > // When the account is added, lastSelected will be set
|
599
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
600
|
+
prevAccount.metadata.lastSelected
|
601
|
+
) {
|
602
|
+
return currentAccount;
|
603
|
+
}
|
604
|
+
return prevAccount;
|
605
|
+
}, accounts[0]);
|
606
|
+
};
|
607
|
+
_isAccountCompatibleWithChain = new WeakSet();
|
608
|
+
isAccountCompatibleWithChain_fn = function(account, chainId) {
|
609
|
+
return account.type.startsWith(_utils.parseCaipChainId.call(void 0, chainId).namespace);
|
495
610
|
};
|
496
611
|
_handleNewAccountAdded = new WeakSet();
|
497
612
|
handleNewAccountAdded_fn = function(account) {
|
498
613
|
let newAccount;
|
499
614
|
if (account.type !== _keyringcontroller.KeyringTypes.snap) {
|
500
|
-
newAccount =
|
615
|
+
newAccount = _chunkUJIPPGP6js.__privateMethod.call(void 0, this, _generateInternalAccountForNonSnapAccount, generateInternalAccountForNonSnapAccount_fn).call(this, account.address, account.type);
|
501
616
|
} else {
|
502
617
|
const [snapKeyring] = this.messagingSystem.call(
|
503
618
|
"KeyringController:getKeyringsByType",
|
@@ -510,17 +625,21 @@ handleNewAccountAdded_fn = function(account) {
|
|
510
625
|
return;
|
511
626
|
}
|
512
627
|
}
|
513
|
-
const
|
514
|
-
|
628
|
+
const accountName = this.getNextAvailableAccountName(
|
629
|
+
newAccount.metadata.keyring.type
|
630
|
+
);
|
515
631
|
this.update((currentState) => {
|
516
|
-
|
632
|
+
const newState = _chunkEIQ5DUI6js.deepCloneDraft.call(void 0, currentState);
|
633
|
+
newState.internalAccounts.accounts[newAccount.id] = {
|
517
634
|
...newAccount,
|
518
635
|
metadata: {
|
519
636
|
...newAccount.metadata,
|
520
637
|
name: accountName,
|
638
|
+
importTime: Date.now(),
|
521
639
|
lastSelected: Date.now()
|
522
640
|
}
|
523
641
|
};
|
642
|
+
return newState;
|
524
643
|
});
|
525
644
|
this.setSelectedAccount(newAccount.id);
|
526
645
|
};
|
@@ -530,6 +649,11 @@ handleAccountRemoved_fn = function(accountId) {
|
|
530
649
|
delete currentState.internalAccounts.accounts[accountId];
|
531
650
|
});
|
532
651
|
};
|
652
|
+
_populateExistingMetadata = new WeakSet();
|
653
|
+
populateExistingMetadata_fn = function(accountId, metadataKey) {
|
654
|
+
const internalAccount = this.getAccount(accountId);
|
655
|
+
return internalAccount ? internalAccount.metadata[metadataKey] : void 0;
|
656
|
+
};
|
533
657
|
_registerMessageHandlers = new WeakSet();
|
534
658
|
registerMessageHandlers_fn = function() {
|
535
659
|
this.messagingSystem.registerActionHandler(
|
@@ -552,10 +676,18 @@ registerMessageHandlers_fn = function() {
|
|
552
676
|
`${controllerName}:getSelectedAccount`,
|
553
677
|
this.getSelectedAccount.bind(this)
|
554
678
|
);
|
679
|
+
this.messagingSystem.registerActionHandler(
|
680
|
+
`${controllerName}:getSelectedMultichainAccount`,
|
681
|
+
this.getSelectedMultichainAccount.bind(this)
|
682
|
+
);
|
555
683
|
this.messagingSystem.registerActionHandler(
|
556
684
|
`${controllerName}:getAccountByAddress`,
|
557
685
|
this.getAccountByAddress.bind(this)
|
558
686
|
);
|
687
|
+
this.messagingSystem.registerActionHandler(
|
688
|
+
`${controllerName}:getNextAvailableAccountName`,
|
689
|
+
this.getNextAvailableAccountName.bind(this)
|
690
|
+
);
|
559
691
|
this.messagingSystem.registerActionHandler(
|
560
692
|
`AccountsController:getAccount`,
|
561
693
|
this.getAccount.bind(this)
|
@@ -565,4 +697,4 @@ registerMessageHandlers_fn = function() {
|
|
565
697
|
|
566
698
|
|
567
699
|
exports.AccountsController = AccountsController;
|
568
|
-
//# sourceMappingURL=chunk-
|
700
|
+
//# sourceMappingURL=chunk-7CWWNB3P.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../src/AccountsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n RestrictedControllerMessenger,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport { SnapKeyring } from '@metamask/eth-snap-keyring';\nimport type { InternalAccount } from '@metamask/keyring-api';\nimport {\n EthAccountType,\n EthMethod,\n isEvmAccountType,\n} from '@metamask/keyring-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type {\n KeyringControllerState,\n KeyringControllerGetKeyringForAccountAction,\n KeyringControllerGetKeyringsByTypeAction,\n KeyringControllerGetAccountsAction,\n KeyringControllerStateChangeEvent,\n} from '@metamask/keyring-controller';\nimport type {\n SnapControllerState,\n SnapStateChange,\n} from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport type { Snap } from '@metamask/snaps-utils';\nimport type { CaipChainId } from '@metamask/utils';\nimport {\n type Keyring,\n type Json,\n isCaipChainId,\n parseCaipChainId,\n} from '@metamask/utils';\nimport type { Draft } from 'immer';\n\nimport {\n deepCloneDraft,\n getUUIDFromAddressOfNormalAccount,\n isNormalKeyringType,\n keyringTypeToName,\n} from './utils';\n\nconst controllerName = 'AccountsController';\n\nexport type AccountsControllerState = {\n internalAccounts: {\n accounts: Record<string, InternalAccount>;\n selectedAccount: string; // id of the selected account\n };\n};\n\nexport type AccountsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n AccountsControllerState\n>;\n\nexport type AccountsControllerSetSelectedAccountAction = {\n type: `${typeof controllerName}:setSelectedAccount`;\n handler: AccountsController['setSelectedAccount'];\n};\n\nexport type AccountsControllerSetAccountNameAction = {\n type: `${typeof controllerName}:setAccountName`;\n handler: AccountsController['setAccountName'];\n};\n\nexport type AccountsControllerListAccountsAction = {\n type: `${typeof controllerName}:listAccounts`;\n handler: AccountsController['listAccounts'];\n};\n\nexport type AccountsControllerUpdateAccountsAction = {\n type: `${typeof controllerName}:updateAccounts`;\n handler: AccountsController['updateAccounts'];\n};\n\nexport type AccountsControllerGetSelectedAccountAction = {\n type: `${typeof controllerName}:getSelectedAccount`;\n handler: AccountsController['getSelectedAccount'];\n};\n\nexport type AccountsControllerGetSelectedMultichainAccountAction = {\n type: `${typeof controllerName}:getSelectedMultichainAccount`;\n handler: AccountsController['getSelectedMultichainAccount'];\n};\n\nexport type AccountsControllerGetAccountByAddressAction = {\n type: `${typeof controllerName}:getAccountByAddress`;\n handler: AccountsController['getAccountByAddress'];\n};\n\nexport type AccountsControllerGetNextAvailableAccountNameAction = {\n type: `${typeof controllerName}:getNextAvailableAccountName`;\n handler: AccountsController['getNextAvailableAccountName'];\n};\n\nexport type AccountsControllerGetAccountAction = {\n type: `${typeof controllerName}:getAccount`;\n handler: AccountsController['getAccount'];\n};\n\nexport type AllowedActions =\n | KeyringControllerGetKeyringForAccountAction\n | KeyringControllerGetKeyringsByTypeAction\n | KeyringControllerGetAccountsAction;\n\nexport type AccountsControllerActions =\n | AccountsControllerGetStateAction\n | AccountsControllerSetSelectedAccountAction\n | AccountsControllerListAccountsAction\n | AccountsControllerSetAccountNameAction\n | AccountsControllerUpdateAccountsAction\n | AccountsControllerGetAccountByAddressAction\n | AccountsControllerGetSelectedAccountAction\n | AccountsControllerGetNextAvailableAccountNameAction\n | AccountsControllerGetAccountAction\n | AccountsControllerGetSelectedMultichainAccountAction;\n\nexport type AccountsControllerChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n AccountsControllerState\n>;\n\nexport type AccountsControllerSelectedAccountChangeEvent = {\n type: `${typeof controllerName}:selectedAccountChange`;\n payload: [InternalAccount];\n};\n\nexport type AccountsControllerSelectedEvmAccountChangeEvent = {\n type: `${typeof controllerName}:selectedEvmAccountChange`;\n payload: [InternalAccount];\n};\n\nexport type AllowedEvents = SnapStateChange | KeyringControllerStateChangeEvent;\n\nexport type AccountsControllerEvents =\n | AccountsControllerChangeEvent\n | AccountsControllerSelectedAccountChangeEvent\n | AccountsControllerSelectedEvmAccountChangeEvent;\n\nexport type AccountsControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n AccountsControllerActions | AllowedActions,\n AccountsControllerEvents | AllowedEvents,\n AllowedActions['type'],\n AllowedEvents['type']\n>;\n\ntype AddressAndKeyringTypeObject = {\n address: string;\n type: string;\n};\n\nconst accountsControllerMetadata = {\n internalAccounts: {\n persist: true,\n anonymous: false,\n },\n};\n\nconst defaultState: AccountsControllerState = {\n internalAccounts: {\n accounts: {},\n selectedAccount: '',\n },\n};\n\n/**\n * Controller that manages internal accounts.\n * The accounts controller is responsible for creating and managing internal accounts.\n * It also provides convenience methods for accessing and updating the internal accounts.\n * The accounts controller also listens for keyring state changes and updates the internal accounts accordingly.\n * The accounts controller also listens for snap state changes and updates the internal accounts accordingly.\n *\n */\nexport class AccountsController extends BaseController<\n typeof controllerName,\n AccountsControllerState,\n AccountsControllerMessenger\n> {\n /**\n * Constructor for AccountsController.\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: AccountsControllerMessenger;\n state: AccountsControllerState;\n }) {\n super({\n messenger,\n name: controllerName,\n metadata: accountsControllerMetadata,\n state: {\n ...defaultState,\n ...state,\n },\n });\n\n this.messagingSystem.subscribe(\n 'SnapController:stateChange',\n (snapStateState) => this.#handleOnSnapStateChange(snapStateState),\n );\n\n this.messagingSystem.subscribe(\n 'KeyringController:stateChange',\n (keyringState) => this.#handleOnKeyringStateChange(keyringState),\n );\n\n this.#registerMessageHandlers();\n }\n\n /**\n * Returns the internal account object for the given account ID, if it exists.\n *\n * @param accountId - The ID of the account to retrieve.\n * @returns The internal account object, or undefined if the account does not exist.\n */\n getAccount(accountId: string): InternalAccount | undefined {\n return this.state.internalAccounts.accounts[accountId];\n }\n\n /**\n * Returns an array of all evm internal accounts.\n *\n * @returns An array of InternalAccount objects.\n */\n listAccounts(): InternalAccount[] {\n const accounts = Object.values(this.state.internalAccounts.accounts);\n return accounts.filter((account) => isEvmAccountType(account.type));\n }\n\n /**\n * Returns an array of all internal accounts.\n *\n * @param chainId - The chain ID.\n * @returns An array of InternalAccount objects.\n */\n listMultichainAccounts(chainId?: CaipChainId): InternalAccount[] {\n const accounts = Object.values(this.state.internalAccounts.accounts);\n if (!chainId) {\n return accounts;\n }\n\n if (!isCaipChainId(chainId)) {\n throw new Error(`Invalid CAIP-2 chain ID: ${String(chainId)}`);\n }\n\n return accounts.filter((account) =>\n this.#isAccountCompatibleWithChain(account, chainId),\n );\n }\n\n /**\n * Returns the internal account object for the given account ID.\n *\n * @param accountId - The ID of the account to retrieve.\n * @returns The internal account object.\n * @throws An error if the account ID is not found.\n */\n getAccountExpect(accountId: string): InternalAccount {\n // Edge case where the extension is setup but the srp is not yet created\n // certain ui elements will query the selected address before any accounts are created.\n if (!accountId) {\n return {\n id: '',\n address: '',\n options: {},\n methods: [],\n type: EthAccountType.Eoa,\n metadata: {\n name: '',\n keyring: {\n type: '',\n },\n importTime: 0,\n },\n };\n }\n\n const account = this.getAccount(accountId);\n if (account === undefined) {\n throw new Error(`Account Id \"${accountId}\" not found`);\n }\n return account;\n }\n\n /**\n * Returns the last selected evm account.\n *\n * @returns The selected internal account.\n */\n getSelectedAccount(): InternalAccount {\n const selectedAccount = this.getAccountExpect(\n this.state.internalAccounts.selectedAccount,\n );\n if (isEvmAccountType(selectedAccount.type)) {\n return selectedAccount;\n }\n\n const accounts = this.listAccounts();\n\n if (!accounts.length) {\n // ! Should never reach this.\n throw new Error('No EVM accounts');\n }\n\n // This will never be undefined because we have already checked if accounts.length is > 0\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this.#getLastSelectedAccount(accounts)!;\n }\n\n /**\n * __WARNING The return value may be undefined if there isn't an account for that chain id.__\n *\n * Retrieves the last selected account by chain ID.\n *\n * @param chainId - The chain ID to filter the accounts.\n * @returns The last selected account compatible with the specified chain ID or undefined.\n */\n getSelectedMultichainAccount(\n chainId?: CaipChainId,\n ): InternalAccount | undefined {\n if (!chainId) {\n return this.getAccountExpect(this.state.internalAccounts.selectedAccount);\n }\n\n if (!isCaipChainId(chainId)) {\n throw new Error(`Invalid CAIP-2 chain ID: ${chainId as string}`);\n }\n\n const accounts = Object.values(this.state.internalAccounts.accounts).filter(\n (account) => this.#isAccountCompatibleWithChain(account, chainId),\n );\n\n return this.#getLastSelectedAccount(accounts);\n }\n\n /**\n * Returns the account with the specified address.\n * ! This method will only return the first account that matches the address\n * @param address - The address of the account to retrieve.\n * @returns The account with the specified address, or undefined if not found.\n */\n getAccountByAddress(address: string): InternalAccount | undefined {\n return this.listAccounts().find(\n (account) => account.address.toLowerCase() === address.toLowerCase(),\n );\n }\n\n /**\n * Sets the selected account by its ID.\n *\n * @param accountId - The ID of the account to be selected.\n */\n setSelectedAccount(accountId: string): void {\n const account = this.getAccountExpect(accountId);\n\n this.update((currentState: Draft<AccountsControllerState>) => {\n currentState.internalAccounts.accounts[account.id].metadata.lastSelected =\n Date.now();\n currentState.internalAccounts.selectedAccount = account.id;\n });\n\n if (isEvmAccountType(account.type)) {\n this.messagingSystem.publish(\n 'AccountsController:selectedEvmAccountChange',\n account,\n );\n }\n\n this.messagingSystem.publish(\n 'AccountsController:selectedAccountChange',\n account,\n );\n }\n\n /**\n * Sets the name of the account with the given ID.\n *\n * @param accountId - The ID of the account to set the name for.\n * @param accountName - The new name for the account.\n * @throws An error if an account with the same name already exists.\n */\n setAccountName(accountId: string, accountName: string): void {\n const account = this.getAccountExpect(accountId);\n\n if (\n this.listAccounts().find(\n (internalAccount) =>\n internalAccount.metadata.name === accountName &&\n internalAccount.id !== accountId,\n )\n ) {\n throw new Error('Account name already exists');\n }\n\n this.update((currentState: Draft<AccountsControllerState>) => {\n const internalAccount = {\n ...account,\n metadata: { ...account.metadata, name: accountName },\n };\n // FIXME: deep clone of old state to get around Type instantiation is excessively deep and possibly infinite.\n const newState = deepCloneDraft(currentState);\n\n newState.internalAccounts.accounts[accountId] = internalAccount;\n\n return newState;\n });\n }\n\n /**\n * Updates the internal accounts list by retrieving normal and snap accounts,\n * removing duplicates, and updating the metadata of each account.\n *\n * @returns A Promise that resolves when the accounts have been updated.\n */\n async updateAccounts(): Promise<void> {\n const snapAccounts = await this.#listSnapAccounts();\n const normalAccounts = await this.#listNormalAccounts();\n\n // keyring type map.\n const keyringTypes = new Map<string, number>();\n const previousAccounts = this.state.internalAccounts.accounts;\n\n const accounts: Record<string, InternalAccount> = [\n ...normalAccounts,\n ...snapAccounts,\n ].reduce((internalAccountMap, internalAccount) => {\n const keyringTypeName = keyringTypeToName(\n internalAccount.metadata.keyring.type,\n );\n const keyringAccountIndex = keyringTypes.get(keyringTypeName) ?? 0;\n if (keyringAccountIndex) {\n keyringTypes.set(keyringTypeName, keyringAccountIndex + 1);\n } else {\n keyringTypes.set(keyringTypeName, 1);\n }\n\n const existingAccount = previousAccounts[internalAccount.id];\n\n internalAccountMap[internalAccount.id] = {\n ...internalAccount,\n\n metadata: {\n ...internalAccount.metadata,\n name:\n this.#populateExistingMetadata(existingAccount?.id, 'name') ??\n `${keyringTypeName} ${keyringAccountIndex + 1}`,\n importTime:\n this.#populateExistingMetadata(existingAccount?.id, 'importTime') ??\n Date.now(),\n lastSelected:\n this.#populateExistingMetadata(\n existingAccount?.id,\n 'lastSelected',\n ) ?? 0,\n },\n };\n\n return internalAccountMap;\n }, {} as Record<string, InternalAccount>);\n\n this.update((currentState: Draft<AccountsControllerState>) => {\n // FIXME: deep clone of old state to get around Type instantiation is excessively deep and possibly infinite.\n const newState = deepCloneDraft(currentState);\n\n newState.internalAccounts.accounts = accounts;\n\n return newState;\n });\n }\n\n /**\n * Loads the backup state of the accounts controller.\n *\n * @param backup - The backup state to load.\n */\n loadBackup(backup: AccountsControllerState): void {\n if (backup.internalAccounts) {\n this.update((currentState: Draft<AccountsControllerState>) => {\n // FIXME: deep clone of old state to get around Type instantiation is excessively deep and possibly infinite.\n const newState = deepCloneDraft(currentState);\n\n newState.internalAccounts = backup.internalAccounts;\n\n return newState;\n });\n }\n }\n\n /**\n * Generates an internal account for a non-Snap account.\n * @param address - The address of the account.\n * @param type - The type of the account.\n * @returns The generated internal account.\n */\n #generateInternalAccountForNonSnapAccount(\n address: string,\n type: string,\n ): InternalAccount {\n return {\n id: getUUIDFromAddressOfNormalAccount(address),\n address,\n options: {},\n methods: [\n EthMethod.PersonalSign,\n EthMethod.Sign,\n EthMethod.SignTransaction,\n EthMethod.SignTypedDataV1,\n EthMethod.SignTypedDataV3,\n EthMethod.SignTypedDataV4,\n ],\n type: EthAccountType.Eoa,\n metadata: {\n name: '',\n importTime: Date.now(),\n keyring: {\n type,\n },\n },\n };\n }\n\n /**\n * Returns a list of internal accounts created using the SnapKeyring.\n *\n * @returns A promise that resolves to an array of InternalAccount objects.\n */\n async #listSnapAccounts(): Promise<InternalAccount[]> {\n const [snapKeyring] = this.messagingSystem.call(\n 'KeyringController:getKeyringsByType',\n SnapKeyring.type,\n );\n // snap keyring is not available until the first account is created in the keyring controller\n if (!snapKeyring) {\n return [];\n }\n\n const snapAccounts = (snapKeyring as SnapKeyring).listAccounts();\n\n return snapAccounts;\n }\n\n /**\n * Returns a list of normal accounts.\n * Note: listNormalAccounts is a temporary method until the keyrings all implement the InternalAccount interface.\n * Once all keyrings implement the InternalAccount interface, this method can be removed and getAccounts can be used instead.\n *\n * @returns A Promise that resolves to an array of InternalAccount objects.\n */\n async #listNormalAccounts(): Promise<InternalAccount[]> {\n const addresses = await this.messagingSystem.call(\n 'KeyringController:getAccounts',\n );\n const internalAccounts: InternalAccount[] = [];\n for (const address of addresses) {\n const keyring = await this.messagingSystem.call(\n 'KeyringController:getKeyringForAccount',\n address,\n );\n\n const keyringType = (keyring as Keyring<Json>).type;\n if (!isNormalKeyringType(keyringType as KeyringTypes)) {\n // We only consider \"normal accounts\" here, so keep looping\n continue;\n }\n\n const id = getUUIDFromAddressOfNormalAccount(address);\n\n internalAccounts.push({\n id,\n address,\n options: {},\n methods: [\n EthMethod.PersonalSign,\n EthMethod.Sign,\n EthMethod.SignTransaction,\n EthMethod.SignTypedDataV1,\n EthMethod.SignTypedDataV3,\n EthMethod.SignTypedDataV4,\n ],\n type: EthAccountType.Eoa,\n metadata: {\n name: this.#populateExistingMetadata(id, 'name') ?? '',\n importTime:\n this.#populateExistingMetadata(id, 'importTime') ?? Date.now(),\n lastSelected: this.#populateExistingMetadata(id, 'lastSelected') ?? 0,\n keyring: {\n type: (keyring as Keyring<Json>).type,\n },\n },\n });\n }\n\n return internalAccounts;\n }\n\n /**\n * Handles changes in the keyring state, specifically when new accounts are added or removed.\n *\n * @param keyringState - The new state of the keyring controller.\n */\n #handleOnKeyringStateChange(keyringState: KeyringControllerState): void {\n // check if there are any new accounts added\n // TODO: change when accountAdded event is added to the keyring controller\n\n // We check for keyrings length to be greater than 0 because the extension client may try execute\n // submit password twice and clear the keyring state.\n // https://github.com/MetaMask/KeyringController/blob/2d73a4deed8d013913f6ef0c9f5c0bb7c614f7d3/src/KeyringController.ts#L910\n if (keyringState.isUnlocked && keyringState.keyrings.length > 0) {\n const updatedNormalKeyringAddresses: AddressAndKeyringTypeObject[] = [];\n const updatedSnapKeyringAddresses: AddressAndKeyringTypeObject[] = [];\n\n for (const keyring of keyringState.keyrings) {\n if (keyring.type === KeyringTypes.snap) {\n updatedSnapKeyringAddresses.push(\n ...keyring.accounts.map((address) => {\n return {\n address,\n type: keyring.type,\n };\n }),\n );\n } else {\n updatedNormalKeyringAddresses.push(\n ...keyring.accounts.map((address) => {\n return {\n address,\n type: keyring.type,\n };\n }),\n );\n }\n }\n\n const { previousNormalInternalAccounts, previousSnapInternalAccounts } =\n this.listAccounts().reduce(\n (accumulator, account) => {\n if (account.metadata.keyring.type === KeyringTypes.snap) {\n accumulator.previousSnapInternalAccounts.push(account);\n } else {\n accumulator.previousNormalInternalAccounts.push(account);\n }\n return accumulator;\n },\n {\n previousNormalInternalAccounts: [] as InternalAccount[],\n previousSnapInternalAccounts: [] as InternalAccount[],\n },\n );\n\n const addedAccounts: AddressAndKeyringTypeObject[] = [];\n const deletedAccounts: InternalAccount[] = [];\n\n // snap account ids are random uuid while normal accounts\n // are determininistic based on the address\n\n // ^NOTE: This will be removed when normal accounts also implement internal accounts\n // finding all the normal accounts that were added\n for (const account of updatedNormalKeyringAddresses) {\n if (\n !this.state.internalAccounts.accounts[\n getUUIDFromAddressOfNormalAccount(account.address)\n ]\n ) {\n addedAccounts.push(account);\n }\n }\n\n // finding all the snap accounts that were added\n for (const account of updatedSnapKeyringAddresses) {\n if (\n !previousSnapInternalAccounts.find(\n (internalAccount: InternalAccount) =>\n internalAccount.address.toLowerCase() ===\n account.address.toLowerCase(),\n )\n ) {\n addedAccounts.push(account);\n }\n }\n\n // finding all the normal accounts that were deleted\n for (const account of previousNormalInternalAccounts) {\n if (\n !updatedNormalKeyringAddresses.find(\n ({ address }) =>\n address.toLowerCase() === account.address.toLowerCase(),\n )\n ) {\n deletedAccounts.push(account);\n }\n }\n\n // finding all the snap accounts that were deleted\n for (const account of previousSnapInternalAccounts) {\n if (\n !updatedSnapKeyringAddresses.find(\n ({ address }) =>\n address.toLowerCase() === account.address.toLowerCase(),\n )\n ) {\n deletedAccounts.push(account);\n }\n }\n\n if (deletedAccounts.length > 0) {\n for (const account of deletedAccounts) {\n this.#handleAccountRemoved(account.id);\n }\n }\n\n if (addedAccounts.length > 0) {\n for (const account of addedAccounts) {\n this.#handleNewAccountAdded(account);\n }\n }\n\n // handle if the selected account was deleted\n if (!this.getAccount(this.state.internalAccounts.selectedAccount)) {\n const [accountToSelect] = this.listAccounts().sort(\n (accountA, accountB) => {\n // sort by lastSelected descending\n return (\n (accountB.metadata.lastSelected ?? 0) -\n (accountA.metadata.lastSelected ?? 0)\n );\n },\n );\n\n // if the accountToSelect is undefined, then there are no accounts\n // it mean the keyring was reinitialized.\n if (!accountToSelect) {\n this.update((currentState: Draft<AccountsControllerState>) => {\n currentState.internalAccounts.selectedAccount = '';\n });\n return;\n }\n\n this.setSelectedAccount(accountToSelect.id);\n }\n }\n }\n\n /**\n * Handles the change in SnapControllerState by updating the metadata of accounts that have a snap enabled.\n *\n * @param snapState - The new SnapControllerState.\n */\n #handleOnSnapStateChange(snapState: SnapControllerState) {\n // only check if snaps changed in status\n const { snaps } = snapState;\n const accounts = this.listAccounts().filter(\n (account) => account.metadata.snap,\n );\n\n this.update((currentState: Draft<AccountsControllerState>) => {\n accounts.forEach((account) => {\n const currentAccount =\n currentState.internalAccounts.accounts[account.id];\n if (currentAccount.metadata.snap) {\n const snapId = currentAccount.metadata.snap.id;\n const storedSnap: Snap = snaps[snapId as SnapId];\n if (storedSnap) {\n currentAccount.metadata.snap.enabled =\n storedSnap.enabled && !storedSnap.blocked;\n }\n }\n });\n });\n }\n\n /**\n * Returns the list of accounts for a given keyring type.\n * @param keyringType - The type of keyring.\n * @returns The list of accounts associcated with this keyring type.\n */\n #getAccountsByKeyringType(keyringType: string) {\n return this.listAccounts().filter((internalAccount) => {\n // We do consider `hd` and `simple` keyrings to be of same type. So we check those 2 types\n // to group those accounts together!\n if (\n keyringType === KeyringTypes.hd ||\n keyringType === KeyringTypes.simple\n ) {\n return (\n internalAccount.metadata.keyring.type === KeyringTypes.hd ||\n internalAccount.metadata.keyring.type === KeyringTypes.simple\n );\n }\n\n return internalAccount.metadata.keyring.type === keyringType;\n });\n }\n\n /**\n * Returns the last selected account from the given array of accounts.\n *\n * @param accounts - An array of InternalAccount objects.\n * @returns The InternalAccount object that was last selected, or undefined if the array is empty.\n */\n #getLastSelectedAccount(\n accounts: InternalAccount[],\n ): InternalAccount | undefined {\n return accounts.reduce((prevAccount, currentAccount) => {\n if (\n // When the account is added, lastSelected will be set\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n currentAccount.metadata.lastSelected! >\n // When the account is added, lastSelected will be set\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n prevAccount.metadata.lastSelected!\n ) {\n return currentAccount;\n }\n return prevAccount;\n }, accounts[0]);\n }\n\n /**\n * Returns the next account number for a given keyring type.\n * @param keyringType - The type of keyring.\n * @returns An object containing the account prefix and index to use.\n */\n getNextAvailableAccountName(keyringType: string = KeyringTypes.hd): string {\n const keyringName = keyringTypeToName(keyringType);\n const keyringAccounts = this.#getAccountsByKeyringType(keyringType);\n const lastDefaultIndexUsedForKeyringType = keyringAccounts.reduce(\n (maxInternalAccountIndex, internalAccount) => {\n // We **DO NOT USE** `\\d+` here to only consider valid \"human\"\n // number (rounded decimal number)\n const match = new RegExp(`${keyringName} ([0-9]+)$`, 'u').exec(\n internalAccount.metadata.name,\n );\n\n if (match) {\n // Quoting `RegExp.exec` documentation:\n // > The returned array has the matched text as the first item, and then one item for\n // > each capturing group of the matched text.\n // So use `match[1]` to get the captured value\n const internalAccountIndex = parseInt(match[1], 10);\n return Math.max(maxInternalAccountIndex, internalAccountIndex);\n }\n\n return maxInternalAccountIndex;\n },\n 0,\n );\n\n const index = Math.max(\n keyringAccounts.length + 1,\n lastDefaultIndexUsedForKeyringType + 1,\n );\n\n return `${keyringName} ${index}`;\n }\n\n /**\n * Checks if an account is compatible with a given chain namespace.\n * @private\n * @param account - The account to check compatibility for.\n * @param chainId - The CAIP2 to check compatibility with.\n * @returns Returns true if the account is compatible with the chain namespace, otherwise false.\n */\n #isAccountCompatibleWithChain(\n account: InternalAccount,\n chainId: CaipChainId,\n ): boolean {\n // TODO: Change this logic to not use account's type\n // Because we currently only use type, we can only use namespace for now.\n return account.type.startsWith(parseCaipChainId(chainId).namespace);\n }\n\n /**\n * Handles the addition of a new account to the controller.\n * If the account is not a Snap Keyring account, generates an internal account for it and adds it to the controller.\n * If the account is a Snap Keyring account, retrieves the account from the keyring and adds it to the controller.\n * @param account - The address and keyring type object of the new account.\n */\n #handleNewAccountAdded(account: AddressAndKeyringTypeObject) {\n let newAccount: InternalAccount;\n if (account.type !== KeyringTypes.snap) {\n newAccount = this.#generateInternalAccountForNonSnapAccount(\n account.address,\n account.type,\n );\n } else {\n const [snapKeyring] = this.messagingSystem.call(\n 'KeyringController:getKeyringsByType',\n SnapKeyring.type,\n );\n\n newAccount = (snapKeyring as SnapKeyring).getAccountByAddress(\n account.address,\n ) as InternalAccount;\n\n // The snap deleted the account before the keyring controller could add it\n if (!newAccount) {\n return;\n }\n }\n\n // Get next account name available for this given keyring\n const accountName = this.getNextAvailableAccountName(\n newAccount.metadata.keyring.type,\n );\n\n this.update((currentState: Draft<AccountsControllerState>) => {\n // FIXME: deep clone of old state to get around Type instantiation is excessively deep and possibly infinite.\n const newState = deepCloneDraft(currentState);\n\n newState.internalAccounts.accounts[newAccount.id] = {\n ...newAccount,\n metadata: {\n ...newAccount.metadata,\n name: accountName,\n importTime: Date.now(),\n lastSelected: Date.now(),\n },\n };\n\n return newState;\n });\n\n this.setSelectedAccount(newAccount.id);\n }\n\n /**\n * Handles the removal of an account from the internal accounts list.\n * @param accountId - The ID of the account to be removed.\n */\n #handleAccountRemoved(accountId: string) {\n this.update((currentState: Draft<AccountsControllerState>) => {\n delete currentState.internalAccounts.accounts[accountId];\n });\n }\n\n /**\n * Retrieves the value of a specific metadata key for an existing account.\n * @param accountId - The ID of the account.\n * @param metadataKey - The key of the metadata to retrieve.\n * @returns The value of the specified metadata key, or undefined if the account or metadata key does not exist.\n */\n #populateExistingMetadata<T extends keyof InternalAccount['metadata']>(\n accountId: string,\n metadataKey: T,\n ): InternalAccount['metadata'][T] | undefined {\n const internalAccount = this.getAccount(accountId);\n return internalAccount ? internalAccount.metadata[metadataKey] : undefined;\n }\n\n /**\n * Registers message handlers for the AccountsController.\n * @private\n */\n #registerMessageHandlers() {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:setSelectedAccount`,\n this.setSelectedAccount.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:listAccounts`,\n this.listAccounts.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:setAccountName`,\n this.setAccountName.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateAccounts`,\n this.updateAccounts.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getSelectedAccount`,\n this.getSelectedAccount.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getSelectedMultichainAccount`,\n this.getSelectedMultichainAccount.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getAccountByAddress`,\n this.getAccountByAddress.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getNextAvailableAccountName`,\n this.getNextAvailableAccountName.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `AccountsController:getAccount`,\n this.getAccount.bind(this),\n );\n }\n}\n"]}
|