@metamask/accounts-controller 3.0.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +7 -1
- package/dist/AccountsController.d.ts +20 -16
- package/dist/AccountsController.d.ts.map +1 -1
- package/dist/AccountsController.js +201 -126
- package/dist/AccountsController.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/utils.d.ts +14 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +57 -0
- package/dist/utils.js.map +1 -0
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
@@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [4.0.0]
|
10
|
+
### Changed
|
11
|
+
- **BREAKING** Update the `onKeyringStateChange` and `onSnapStateChange` methods, and remove the `keyringApiEnabled` from the AccountsController ([#1839](https://github.com/MetaMask/core/pull/1839))
|
12
|
+
- Add getSelectedAccount and getAccountByAddress actions to AccountsController ([#1858](https://github.com/MetaMask/core/pull/1858))
|
13
|
+
|
9
14
|
## [3.0.0]
|
10
15
|
### Changed
|
11
16
|
- **BREAKING:** Bump dependency on `@metamask/eth-snap-keyring` to ^1.0.0 ([#1735](https://github.com/MetaMask/core/pull/1735))
|
@@ -34,7 +39,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
34
39
|
### Added
|
35
40
|
- Initial release ([#1637](https://github.com/MetaMask/core/pull/1637))
|
36
41
|
|
37
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/accounts-controller@
|
42
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/accounts-controller@4.0.0...HEAD
|
43
|
+
[4.0.0]: https://github.com/MetaMask/core/compare/@metamask/accounts-controller@3.0.0...@metamask/accounts-controller@4.0.0
|
38
44
|
[3.0.0]: https://github.com/MetaMask/core/compare/@metamask/accounts-controller@2.0.2...@metamask/accounts-controller@3.0.0
|
39
45
|
[2.0.2]: https://github.com/MetaMask/core/compare/@metamask/accounts-controller@2.0.1...@metamask/accounts-controller@2.0.2
|
40
46
|
[2.0.1]: https://github.com/MetaMask/core/compare/@metamask/accounts-controller@2.0.0...@metamask/accounts-controller@2.0.1
|
@@ -15,23 +15,31 @@ export declare type AccountsControllerGetStateAction = {
|
|
15
15
|
type: `${typeof controllerName}:getState`;
|
16
16
|
handler: () => AccountsControllerState;
|
17
17
|
};
|
18
|
-
export declare type
|
18
|
+
export declare type AccountsControllerSetSelectedAccountAction = {
|
19
19
|
type: `${typeof controllerName}:setSelectedAccount`;
|
20
20
|
handler: AccountsController['setSelectedAccount'];
|
21
21
|
};
|
22
|
-
export declare type
|
22
|
+
export declare type AccountsControllerSetAccountNameAction = {
|
23
23
|
type: `${typeof controllerName}:setAccountName`;
|
24
24
|
handler: AccountsController['setAccountName'];
|
25
25
|
};
|
26
|
-
export declare type
|
26
|
+
export declare type AccountsControllerListAccountsAction = {
|
27
27
|
type: `${typeof controllerName}:listAccounts`;
|
28
28
|
handler: AccountsController['listAccounts'];
|
29
29
|
};
|
30
|
-
export declare type
|
30
|
+
export declare type AccountsControllerUpdateAccountsAction = {
|
31
31
|
type: `${typeof controllerName}:updateAccounts`;
|
32
32
|
handler: AccountsController['updateAccounts'];
|
33
33
|
};
|
34
|
-
export declare type
|
34
|
+
export declare type AccountsControllerGetSelectedAccountAction = {
|
35
|
+
type: `${typeof controllerName}:getSelectedAccount`;
|
36
|
+
handler: AccountsController['getSelectedAccount'];
|
37
|
+
};
|
38
|
+
export declare type AccountsControllerGetAccountByAddressAction = {
|
39
|
+
type: `${typeof controllerName}:getAccountByAddress`;
|
40
|
+
handler: AccountsController['getAccountByAddress'];
|
41
|
+
};
|
42
|
+
export declare type AccountsControllerActions = AccountsControllerGetStateAction | AccountsControllerSetSelectedAccountAction | AccountsControllerListAccountsAction | AccountsControllerSetAccountNameAction | AccountsControllerUpdateAccountsAction | AccountsControllerGetAccountByAddressAction | AccountsControllerGetSelectedAccountAction | KeyringControllerGetKeyringForAccountAction | KeyringControllerGetKeyringsByTypeAction | KeyringControllerGetAccountsAction;
|
35
43
|
export declare type AccountsControllerChangeEvent = {
|
36
44
|
type: `${typeof controllerName}:stateChange`;
|
37
45
|
payload: [AccountsControllerState, Patch[]];
|
@@ -52,19 +60,16 @@ export declare type AccountsControllerMessenger = RestrictedControllerMessenger<
|
|
52
60
|
*/
|
53
61
|
export declare class AccountsController extends BaseControllerV2<typeof controllerName, AccountsControllerState, AccountsControllerMessenger> {
|
54
62
|
#private;
|
55
|
-
keyringApiEnabled: boolean;
|
56
63
|
/**
|
57
64
|
* Constructor for AccountsController.
|
58
65
|
*
|
59
66
|
* @param options - The controller options.
|
60
67
|
* @param options.messenger - The messenger object.
|
61
68
|
* @param options.state - Initial state to set on this controller
|
62
|
-
* @param [options.keyringApiEnabled] - The keyring API enabled flag.
|
63
69
|
*/
|
64
|
-
constructor({ messenger, state,
|
70
|
+
constructor({ messenger, state, }: {
|
65
71
|
messenger: AccountsControllerMessenger;
|
66
72
|
state: AccountsControllerState;
|
67
|
-
keyringApiEnabled?: boolean;
|
68
73
|
});
|
69
74
|
/**
|
70
75
|
* Returns the internal account object for the given account ID, if it exists.
|
@@ -93,6 +98,12 @@ export declare class AccountsController extends BaseControllerV2<typeof controll
|
|
93
98
|
* @returns The selected internal account.
|
94
99
|
*/
|
95
100
|
getSelectedAccount(): InternalAccount;
|
101
|
+
/**
|
102
|
+
* Returns the account with the specified address.
|
103
|
+
* ! This method will only return the first account that matches the address
|
104
|
+
* @param address - The address of the account to retrieve.
|
105
|
+
* @returns The account with the specified address, or undefined if not found.
|
106
|
+
*/
|
96
107
|
getAccountByAddress(address: string): InternalAccount | undefined;
|
97
108
|
/**
|
98
109
|
* Sets the selected account by its ID.
|
@@ -122,12 +133,5 @@ export declare class AccountsController extends BaseControllerV2<typeof controll
|
|
122
133
|
*/
|
123
134
|
loadBackup(backup: AccountsControllerState): void;
|
124
135
|
}
|
125
|
-
/**
|
126
|
-
* Returns the name of the keyring type.
|
127
|
-
*
|
128
|
-
* @param keyringType - The type of the keyring.
|
129
|
-
* @returns The name of the keyring type.
|
130
|
-
*/
|
131
|
-
export declare function keyringTypeToName(keyringType: string): string;
|
132
136
|
export {};
|
133
137
|
//# sourceMappingURL=AccountsController.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"AccountsController.d.ts","sourceRoot":"","sources":["../src/AccountsController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;
|
1
|
+
{"version":3,"file":"AccountsController.d.ts","sourceRoot":"","sources":["../src/AccountsController.ts"],"names":[],"mappings":"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"}
|
@@ -13,14 +13,16 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
13
13
|
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");
|
14
14
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
15
15
|
};
|
16
|
-
var _AccountsController_instances, _AccountsController_listSnapAccounts, _AccountsController_listNormalAccounts,
|
16
|
+
var _AccountsController_instances, _AccountsController_generateInternalAccountForNonSnapAccount, _AccountsController_listSnapAccounts, _AccountsController_listNormalAccounts, _AccountsController_handleOnKeyringStateChange, _AccountsController_handleOnSnapStateChange, _AccountsController_getNextAccountNumber, _AccountsController_handleNewAccountAdded, _AccountsController_handleAccountRemoved, _AccountsController_registerMessageHandlers;
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
18
|
-
exports.
|
18
|
+
exports.AccountsController = void 0;
|
19
19
|
const base_controller_1 = require("@metamask/base-controller");
|
20
20
|
const eth_snap_keyring_1 = require("@metamask/eth-snap-keyring");
|
21
21
|
const keyring_api_1 = require("@metamask/keyring-api");
|
22
|
+
const keyring_controller_1 = require("@metamask/keyring-controller");
|
22
23
|
const ethereumjs_util_1 = require("ethereumjs-util");
|
23
24
|
const uuid_1 = require("uuid");
|
25
|
+
const utils_1 = require("./utils");
|
24
26
|
const controllerName = 'AccountsController';
|
25
27
|
const accountsControllerMetadata = {
|
26
28
|
internalAccounts: {
|
@@ -49,9 +51,8 @@ class AccountsController extends base_controller_1.BaseControllerV2 {
|
|
49
51
|
* @param options - The controller options.
|
50
52
|
* @param options.messenger - The messenger object.
|
51
53
|
* @param options.state - Initial state to set on this controller
|
52
|
-
* @param [options.keyringApiEnabled] - The keyring API enabled flag.
|
53
54
|
*/
|
54
|
-
constructor({ messenger, state,
|
55
|
+
constructor({ messenger, state, }) {
|
55
56
|
super({
|
56
57
|
messenger,
|
57
58
|
name: controllerName,
|
@@ -59,18 +60,9 @@ class AccountsController extends base_controller_1.BaseControllerV2 {
|
|
59
60
|
state: Object.assign(Object.assign({}, defaultState), state),
|
60
61
|
});
|
61
62
|
_AccountsController_instances.add(this);
|
62
|
-
this.
|
63
|
-
|
64
|
-
this.messagingSystem.subscribe('SnapController:stateChange', (snapStateState) => __awaiter(this, void 0, void 0, function* () { return yield __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_handleOnSnapStateChange).call(this, snapStateState); }));
|
65
|
-
}
|
66
|
-
this.messagingSystem.subscribe('KeyringController:stateChange', (keyringState) => __awaiter(this, void 0, void 0, function* () { return yield __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_handleOnKeyringStateChange).call(this, keyringState); }));
|
63
|
+
this.messagingSystem.subscribe('SnapController:stateChange', (snapStateState) => __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_handleOnSnapStateChange).call(this, snapStateState));
|
64
|
+
this.messagingSystem.subscribe('KeyringController:stateChange', (keyringState) => __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_handleOnKeyringStateChange).call(this, keyringState));
|
67
65
|
__classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_registerMessageHandlers).call(this);
|
68
|
-
// if somehow the selected account becomes lost then select the first account
|
69
|
-
if (this.state.internalAccounts.selectedAccount !== '' &&
|
70
|
-
!this.getAccount(this.state.internalAccounts.selectedAccount) &&
|
71
|
-
this.listAccounts().length > 0) {
|
72
|
-
this.setSelectedAccount(this.listAccounts()[0].id);
|
73
|
-
}
|
74
66
|
}
|
75
67
|
/**
|
76
68
|
* Returns the internal account object for the given account ID, if it exists.
|
@@ -128,6 +120,12 @@ class AccountsController extends base_controller_1.BaseControllerV2 {
|
|
128
120
|
getSelectedAccount() {
|
129
121
|
return this.getAccountExpect(this.state.internalAccounts.selectedAccount);
|
130
122
|
}
|
123
|
+
/**
|
124
|
+
* Returns the account with the specified address.
|
125
|
+
* ! This method will only return the first account that matches the address
|
126
|
+
* @param address - The address of the account to retrieve.
|
127
|
+
* @returns The account with the specified address, or undefined if not found.
|
128
|
+
*/
|
131
129
|
getAccountByAddress(address) {
|
132
130
|
return this.listAccounts().find((account) => account.address.toLowerCase() === address.toLowerCase());
|
133
131
|
}
|
@@ -137,15 +135,19 @@ class AccountsController extends base_controller_1.BaseControllerV2 {
|
|
137
135
|
* @param accountId - The ID of the account to be selected.
|
138
136
|
*/
|
139
137
|
setSelectedAccount(accountId) {
|
140
|
-
const account = this.
|
141
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
142
|
-
// @ts-ignore Type instantiation is excessively deep and possibly infinite.
|
138
|
+
const account = this.getAccount(accountId);
|
143
139
|
this.update((currentState) => {
|
144
|
-
|
145
|
-
Date.now();
|
146
|
-
|
140
|
+
if (account) {
|
141
|
+
currentState.internalAccounts.accounts[account.id].metadata.lastSelected = Date.now();
|
142
|
+
currentState.internalAccounts.selectedAccount = account.id;
|
143
|
+
}
|
144
|
+
else {
|
145
|
+
currentState.internalAccounts.selectedAccount = '';
|
146
|
+
}
|
147
147
|
});
|
148
|
-
|
148
|
+
if (account) {
|
149
|
+
this.messagingSystem.publish('AccountsController:selectedAccountChange', account);
|
150
|
+
}
|
149
151
|
}
|
150
152
|
/**
|
151
153
|
* Sets the name of the account with the given ID.
|
@@ -161,7 +163,10 @@ class AccountsController extends base_controller_1.BaseControllerV2 {
|
|
161
163
|
throw new Error('Account name already exists');
|
162
164
|
}
|
163
165
|
this.update((currentState) => {
|
164
|
-
|
166
|
+
const internalAccount = Object.assign(Object.assign({}, account), { metadata: Object.assign(Object.assign({}, account.metadata), { name: accountName }) });
|
167
|
+
currentState.internalAccounts.accounts[accountId] =
|
168
|
+
// @ts-expect-error Assigning a complex type `T` to `Draft<T>` causes an excessive type instantiation depth error.
|
169
|
+
internalAccount;
|
165
170
|
});
|
166
171
|
}
|
167
172
|
/**
|
@@ -172,13 +177,8 @@ class AccountsController extends base_controller_1.BaseControllerV2 {
|
|
172
177
|
*/
|
173
178
|
updateAccounts() {
|
174
179
|
return __awaiter(this, void 0, void 0, function* () {
|
175
|
-
|
176
|
-
|
177
|
-
if (this.keyringApiEnabled) {
|
178
|
-
snapAccounts = yield __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_listSnapAccounts).call(this);
|
179
|
-
// remove duplicate accounts that are retrieved from the snap keyring.
|
180
|
-
normalAccounts = normalAccounts.filter((account) => !snapAccounts.find((snapAccount) => snapAccount.address === account.address));
|
181
|
-
}
|
180
|
+
const snapAccounts = yield __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_listSnapAccounts).call(this);
|
181
|
+
const normalAccounts = (yield __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_listNormalAccounts).call(this)).filter((account) => !snapAccounts.find((snapAccount) => snapAccount.address === account.address));
|
182
182
|
// keyring type map.
|
183
183
|
const keyringTypes = new Map();
|
184
184
|
const previousAccounts = this.state.internalAccounts.accounts;
|
@@ -187,7 +187,7 @@ class AccountsController extends base_controller_1.BaseControllerV2 {
|
|
187
187
|
...snapAccounts,
|
188
188
|
].reduce((internalAccountMap, internalAccount) => {
|
189
189
|
var _a, _b;
|
190
|
-
const keyringTypeName = keyringTypeToName(internalAccount.metadata.keyring.type);
|
190
|
+
const keyringTypeName = (0, utils_1.keyringTypeToName)(internalAccount.metadata.keyring.type);
|
191
191
|
const keyringAccountIndex = (_a = keyringTypes.get(keyringTypeName)) !== null && _a !== void 0 ? _a : 0;
|
192
192
|
if (keyringAccountIndex) {
|
193
193
|
keyringTypes.set(keyringTypeName, keyringAccountIndex + 1);
|
@@ -201,10 +201,9 @@ class AccountsController extends base_controller_1.BaseControllerV2 {
|
|
201
201
|
: `${keyringTypeName} ${keyringAccountIndex + 1}`, lastSelected: (_b = existingAccount === null || existingAccount === void 0 ? void 0 : existingAccount.metadata) === null || _b === void 0 ? void 0 : _b.lastSelected }) });
|
202
202
|
return internalAccountMap;
|
203
203
|
}, {});
|
204
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
205
|
-
// @ts-ignore Type instantiation is excessively deep and possibly infinite.
|
206
204
|
this.update((currentState) => {
|
207
|
-
currentState.internalAccounts.accounts =
|
205
|
+
currentState.internalAccounts.accounts =
|
206
|
+
accounts;
|
208
207
|
});
|
209
208
|
});
|
210
209
|
}
|
@@ -216,20 +215,42 @@ class AccountsController extends base_controller_1.BaseControllerV2 {
|
|
216
215
|
loadBackup(backup) {
|
217
216
|
if (backup.internalAccounts) {
|
218
217
|
this.update((currentState) => {
|
219
|
-
currentState.internalAccounts =
|
218
|
+
currentState.internalAccounts =
|
219
|
+
backup.internalAccounts;
|
220
220
|
});
|
221
221
|
}
|
222
222
|
}
|
223
223
|
}
|
224
224
|
exports.AccountsController = AccountsController;
|
225
|
-
_AccountsController_instances = new WeakSet(),
|
225
|
+
_AccountsController_instances = new WeakSet(), _AccountsController_generateInternalAccountForNonSnapAccount = function _AccountsController_generateInternalAccountForNonSnapAccount(address, type) {
|
226
|
+
return {
|
227
|
+
id: (0, utils_1.getUUIDFromAddressOfNormalAccount)(address),
|
228
|
+
address,
|
229
|
+
options: {},
|
230
|
+
methods: [
|
231
|
+
'personal_sign',
|
232
|
+
'eth_sign',
|
233
|
+
'eth_signTransaction',
|
234
|
+
'eth_signTypedData_v1',
|
235
|
+
'eth_signTypedData_v3',
|
236
|
+
'eth_signTypedData_v4',
|
237
|
+
],
|
238
|
+
type: keyring_api_1.EthAccountType.Eoa,
|
239
|
+
metadata: {
|
240
|
+
name: '',
|
241
|
+
keyring: {
|
242
|
+
type,
|
243
|
+
},
|
244
|
+
},
|
245
|
+
};
|
246
|
+
}, _AccountsController_listSnapAccounts = function _AccountsController_listSnapAccounts() {
|
226
247
|
return __awaiter(this, void 0, void 0, function* () {
|
227
|
-
const [snapKeyring] =
|
248
|
+
const [snapKeyring] = this.messagingSystem.call('KeyringController:getKeyringsByType', eth_snap_keyring_1.SnapKeyring.type);
|
228
249
|
// snap keyring is not available until the first account is created in the keyring controller
|
229
250
|
if (!snapKeyring) {
|
230
251
|
return [];
|
231
252
|
}
|
232
|
-
const snapAccounts =
|
253
|
+
const snapAccounts = snapKeyring.listAccounts();
|
233
254
|
return snapAccounts;
|
234
255
|
});
|
235
256
|
}, _AccountsController_listNormalAccounts = function _AccountsController_listNormalAccounts() {
|
@@ -262,109 +283,163 @@ _AccountsController_instances = new WeakSet(), _AccountsController_listSnapAccou
|
|
262
283
|
},
|
263
284
|
});
|
264
285
|
}
|
265
|
-
return internalAccounts.filter((account) => account.metadata.keyring.type !==
|
286
|
+
return internalAccounts.filter((account) => account.metadata.keyring.type !== keyring_controller_1.KeyringTypes.snap);
|
266
287
|
});
|
267
|
-
}, _AccountsController_handleSelectedAccountRemoved = function _AccountsController_handleSelectedAccountRemoved() {
|
268
|
-
const previousAccount = this.listAccounts()
|
269
|
-
.filter((account) => account.id !== this.state.internalAccounts.selectedAccount)
|
270
|
-
.sort((accountA, accountB) => {
|
271
|
-
var _a, _b;
|
272
|
-
// sort by lastSelected descending
|
273
|
-
return (((_a = accountB.metadata.lastSelected) !== null && _a !== void 0 ? _a : 0) -
|
274
|
-
((_b = accountA.metadata.lastSelected) !== null && _b !== void 0 ? _b : 0));
|
275
|
-
})[0];
|
276
|
-
this.setSelectedAccount(previousAccount.id);
|
277
288
|
}, _AccountsController_handleOnKeyringStateChange = function _AccountsController_handleOnKeyringStateChange(keyringState) {
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
289
|
+
// check if there are any new accounts added
|
290
|
+
// TODO: change when accountAdded event is added to the keyring controller
|
291
|
+
if (keyringState.isUnlocked) {
|
292
|
+
const updatedNormalKeyringAddresses = [];
|
293
|
+
const updatedSnapKeyringAddresses = [];
|
294
|
+
for (const keyring of keyringState.keyrings) {
|
295
|
+
if (keyring.type === keyring_controller_1.KeyringTypes.snap) {
|
296
|
+
updatedSnapKeyringAddresses.push(...keyring.accounts.map((address) => {
|
297
|
+
return {
|
298
|
+
address,
|
299
|
+
type: keyring.type,
|
300
|
+
};
|
301
|
+
}));
|
291
302
|
}
|
292
|
-
else
|
293
|
-
|
294
|
-
|
303
|
+
else {
|
304
|
+
updatedNormalKeyringAddresses.push(...keyring.accounts.map((address) => {
|
305
|
+
return {
|
306
|
+
address,
|
307
|
+
type: keyring.type,
|
308
|
+
};
|
309
|
+
}));
|
310
|
+
}
|
311
|
+
}
|
312
|
+
const { previousNormalInternalAccounts, previousSnapInternalAccounts } = this.listAccounts().reduce((accumulator, account) => {
|
313
|
+
if (account.metadata.keyring.type === keyring_controller_1.KeyringTypes.snap) {
|
314
|
+
accumulator.previousSnapInternalAccounts.push(account);
|
295
315
|
}
|
296
|
-
else
|
297
|
-
|
298
|
-
|
299
|
-
|
316
|
+
else {
|
317
|
+
accumulator.previousNormalInternalAccounts.push(account);
|
318
|
+
}
|
319
|
+
return accumulator;
|
320
|
+
}, {
|
321
|
+
previousNormalInternalAccounts: [],
|
322
|
+
previousSnapInternalAccounts: [],
|
323
|
+
});
|
324
|
+
const addedAccounts = [];
|
325
|
+
const deletedAccounts = [];
|
326
|
+
// snap account ids are random uuid while normal accounts
|
327
|
+
// are determininistic based on the address
|
328
|
+
// ^NOTE: This will be removed when normal accounts also implement internal accounts
|
329
|
+
// finding all the normal accounts that were added
|
330
|
+
for (const account of updatedNormalKeyringAddresses) {
|
331
|
+
if (!this.state.internalAccounts.accounts[(0, utils_1.getUUIDFromAddressOfNormalAccount)(account.address)]) {
|
332
|
+
addedAccounts.push(account);
|
300
333
|
}
|
301
334
|
}
|
302
|
-
|
335
|
+
// finding all the snap accounts that were added
|
336
|
+
for (const account of updatedSnapKeyringAddresses) {
|
337
|
+
if (!previousSnapInternalAccounts.find((internalAccount) => internalAccount.address.toLowerCase() ===
|
338
|
+
account.address.toLowerCase())) {
|
339
|
+
addedAccounts.push(account);
|
340
|
+
}
|
341
|
+
}
|
342
|
+
// finding all the normal accounts that were deleted
|
343
|
+
for (const account of previousNormalInternalAccounts) {
|
344
|
+
if (!updatedNormalKeyringAddresses.find(({ address }) => address.toLowerCase() === account.address.toLowerCase())) {
|
345
|
+
deletedAccounts.push(account);
|
346
|
+
}
|
347
|
+
}
|
348
|
+
// finding all the snap accounts that were deleted
|
349
|
+
for (const account of previousSnapInternalAccounts) {
|
350
|
+
if (!updatedSnapKeyringAddresses.find(({ address }) => address.toLowerCase() === account.address.toLowerCase())) {
|
351
|
+
deletedAccounts.push(account);
|
352
|
+
}
|
353
|
+
}
|
354
|
+
if (deletedAccounts.length > 0) {
|
355
|
+
for (const account of deletedAccounts) {
|
356
|
+
__classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_handleAccountRemoved).call(this, account.id);
|
357
|
+
}
|
358
|
+
}
|
359
|
+
if (addedAccounts.length > 0) {
|
360
|
+
for (const account of addedAccounts) {
|
361
|
+
__classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_handleNewAccountAdded).call(this, account);
|
362
|
+
}
|
363
|
+
}
|
364
|
+
// handle if the selected account was deleted
|
365
|
+
if (!this.getAccount(this.state.internalAccounts.selectedAccount)) {
|
366
|
+
const [accountToSelect] = this.listAccounts().sort((accountA, accountB) => {
|
367
|
+
var _a, _b;
|
368
|
+
// sort by lastSelected descending
|
369
|
+
return (((_a = accountB.metadata.lastSelected) !== null && _a !== void 0 ? _a : 0) -
|
370
|
+
((_b = accountA.metadata.lastSelected) !== null && _b !== void 0 ? _b : 0));
|
371
|
+
});
|
372
|
+
// if the accountToSelect is undefined, then there are no accounts
|
373
|
+
// it mean the keyring was reinitialized.
|
374
|
+
this.setSelectedAccount(accountToSelect === null || accountToSelect === void 0 ? void 0 : accountToSelect.id);
|
375
|
+
}
|
376
|
+
}
|
303
377
|
}, _AccountsController_handleOnSnapStateChange = function _AccountsController_handleOnSnapStateChange(snapState) {
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
accounts.
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
storedSnap.enabled && !storedSnap.blocked;
|
317
|
-
}
|
378
|
+
// only check if snaps changed in status
|
379
|
+
const { snaps } = snapState;
|
380
|
+
const accounts = this.listAccounts().filter((account) => account.metadata.snap);
|
381
|
+
this.update((currentState) => {
|
382
|
+
accounts.forEach((account) => {
|
383
|
+
const currentAccount = currentState.internalAccounts.accounts[account.id];
|
384
|
+
if (currentAccount.metadata.snap) {
|
385
|
+
const snapId = currentAccount.metadata.snap.id;
|
386
|
+
const storedSnap = snaps[snapId];
|
387
|
+
if (storedSnap) {
|
388
|
+
currentAccount.metadata.snap.enabled =
|
389
|
+
storedSnap.enabled && !storedSnap.blocked;
|
318
390
|
}
|
319
|
-
}
|
391
|
+
}
|
320
392
|
});
|
321
393
|
});
|
322
|
-
},
|
323
|
-
const
|
324
|
-
const
|
394
|
+
}, _AccountsController_getNextAccountNumber = function _AccountsController_getNextAccountNumber(keyringType) {
|
395
|
+
const keyringName = (0, utils_1.keyringTypeToName)(keyringType);
|
396
|
+
const previousKeyringAccounts = this.listAccounts().filter((internalAccount) => {
|
397
|
+
if (keyringType === keyring_controller_1.KeyringTypes.hd ||
|
398
|
+
keyringType === keyring_controller_1.KeyringTypes.simple) {
|
399
|
+
return (internalAccount.metadata.keyring.type === keyring_controller_1.KeyringTypes.hd ||
|
400
|
+
internalAccount.metadata.keyring.type === keyring_controller_1.KeyringTypes.simple);
|
401
|
+
}
|
402
|
+
return internalAccount.metadata.keyring.type === keyringType;
|
403
|
+
});
|
404
|
+
const lastDefaultIndexUsedForKeyringType = previousKeyringAccounts
|
405
|
+
.filter((internalAccount) => new RegExp(`${keyringName} \\d+$`, 'u').test(internalAccount.metadata.name))
|
406
|
+
.map((internalAccount) => {
|
407
|
+
const nameToWords = internalAccount.metadata.name.split(' '); // get the index of a default account name
|
408
|
+
return parseInt(nameToWords[nameToWords.length], 10);
|
409
|
+
})
|
410
|
+
.sort((a, b) => b - a)[0] || 0;
|
411
|
+
const indexToUse = Math.max(previousKeyringAccounts.length + 1, lastDefaultIndexUsedForKeyringType + 1);
|
412
|
+
return { accountPrefix: keyringName, indexToUse };
|
413
|
+
}, _AccountsController_handleNewAccountAdded = function _AccountsController_handleNewAccountAdded(account) {
|
414
|
+
let newAccount;
|
415
|
+
if (account.type !== keyring_controller_1.KeyringTypes.snap) {
|
416
|
+
newAccount = __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_generateInternalAccountForNonSnapAccount).call(this, account.address, account.type);
|
417
|
+
}
|
418
|
+
else {
|
419
|
+
const [snapKeyring] = this.messagingSystem.call('KeyringController:getKeyringsByType', eth_snap_keyring_1.SnapKeyring.type);
|
420
|
+
newAccount = snapKeyring.getAccountByAddress(account.address);
|
421
|
+
// The snap deleted the account before the keyring controller could add it
|
422
|
+
if (!newAccount) {
|
423
|
+
return;
|
424
|
+
}
|
425
|
+
}
|
426
|
+
// get next index number for the keyring type
|
427
|
+
const { accountPrefix, indexToUse } = __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_getNextAccountNumber).call(this, newAccount.metadata.keyring.type);
|
428
|
+
const accountName = `${accountPrefix} ${indexToUse}`;
|
429
|
+
this.update((currentState) => {
|
430
|
+
currentState.internalAccounts.accounts[newAccount.id] = Object.assign(Object.assign({}, newAccount), { metadata: Object.assign(Object.assign({}, newAccount.metadata), { name: accountName, lastSelected: Date.now() }) });
|
431
|
+
});
|
325
432
|
this.setSelectedAccount(newAccount.id);
|
433
|
+
}, _AccountsController_handleAccountRemoved = function _AccountsController_handleAccountRemoved(accountId) {
|
434
|
+
this.update((currentState) => {
|
435
|
+
delete currentState.internalAccounts.accounts[accountId];
|
436
|
+
});
|
326
437
|
}, _AccountsController_registerMessageHandlers = function _AccountsController_registerMessageHandlers() {
|
327
438
|
this.messagingSystem.registerActionHandler(`${controllerName}:setSelectedAccount`, this.setSelectedAccount.bind(this));
|
328
439
|
this.messagingSystem.registerActionHandler(`${controllerName}:listAccounts`, this.listAccounts.bind(this));
|
329
440
|
this.messagingSystem.registerActionHandler(`${controllerName}:setAccountName`, this.setAccountName.bind(this));
|
330
441
|
this.messagingSystem.registerActionHandler(`${controllerName}:updateAccounts`, this.updateAccounts.bind(this));
|
442
|
+
this.messagingSystem.registerActionHandler(`${controllerName}:getSelectedAccount`, this.getSelectedAccount.bind(this));
|
443
|
+
this.messagingSystem.registerActionHandler(`${controllerName}:getAccountByAddress`, this.getAccountByAddress.bind(this));
|
331
444
|
};
|
332
|
-
/**
|
333
|
-
* Returns the name of the keyring type.
|
334
|
-
*
|
335
|
-
* @param keyringType - The type of the keyring.
|
336
|
-
* @returns The name of the keyring type.
|
337
|
-
*/
|
338
|
-
function keyringTypeToName(keyringType) {
|
339
|
-
switch (keyringType) {
|
340
|
-
case 'Simple Key Pair': {
|
341
|
-
return 'Account';
|
342
|
-
}
|
343
|
-
case 'HD Key Tree': {
|
344
|
-
return 'Account';
|
345
|
-
}
|
346
|
-
case 'Trezor Hardware': {
|
347
|
-
return 'Trezor';
|
348
|
-
}
|
349
|
-
case 'Ledger Hardware': {
|
350
|
-
return 'Ledger';
|
351
|
-
}
|
352
|
-
case 'Lattice Hardware': {
|
353
|
-
return 'Lattice';
|
354
|
-
}
|
355
|
-
case 'QR Hardware Wallet Device': {
|
356
|
-
return 'QR';
|
357
|
-
}
|
358
|
-
case 'Snap Keyring': {
|
359
|
-
return 'Snap Account';
|
360
|
-
}
|
361
|
-
case 'Custody': {
|
362
|
-
return 'Custody';
|
363
|
-
}
|
364
|
-
default: {
|
365
|
-
throw new Error(`Unknown keyring ${keyringType}`);
|
366
|
-
}
|
367
|
-
}
|
368
|
-
}
|
369
|
-
exports.keyringTypeToName = keyringTypeToName;
|
370
445
|
//# sourceMappingURL=AccountsController.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"AccountsController.js","sourceRoot":"","sources":["../src/AccountsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RestrictedControllerMessenger } from '@metamask/base-controller';\nimport { BaseControllerV2 } from '@metamask/base-controller';\nimport { SnapKeyring } from '@metamask/eth-snap-keyring';\nimport type { InternalAccount } from '@metamask/keyring-api';\nimport { EthAccountType } from '@metamask/keyring-api';\nimport type {\n KeyringControllerState,\n KeyringControllerEvents,\n KeyringControllerGetKeyringForAccountAction,\n KeyringControllerGetKeyringsByTypeAction,\n KeyringControllerGetAccountsAction,\n} from '@metamask/keyring-controller';\nimport type {\n SnapControllerEvents,\n SnapControllerState,\n} from '@metamask/snaps-controllers';\nimport type { Snap, ValidatedSnapId } from '@metamask/snaps-utils';\nimport type { Keyring, Json } from '@metamask/utils';\nimport { sha256FromString } from 'ethereumjs-util';\nimport type { Patch } from 'immer';\nimport { v4 as uuid } from 'uuid';\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 = {\n type: `${typeof controllerName}:getState`;\n handler: () => AccountsControllerState;\n};\n\nexport type AccountsControllerSetSelectedAccount = {\n type: `${typeof controllerName}:setSelectedAccount`;\n handler: AccountsController['setSelectedAccount'];\n};\n\nexport type AccountsControllerSetAccountName = {\n type: `${typeof controllerName}:setAccountName`;\n handler: AccountsController['setAccountName'];\n};\n\nexport type AccountsControllerListAccounts = {\n type: `${typeof controllerName}:listAccounts`;\n handler: AccountsController['listAccounts'];\n};\n\nexport type AccountsControllerUpdateAccounts = {\n type: `${typeof controllerName}:updateAccounts`;\n handler: AccountsController['updateAccounts'];\n};\n\nexport type AccountsControllerActions =\n | AccountsControllerGetStateAction\n | AccountsControllerSetSelectedAccount\n | AccountsControllerListAccounts\n | AccountsControllerSetAccountName\n | AccountsControllerUpdateAccounts\n | KeyringControllerGetKeyringForAccountAction\n | KeyringControllerGetKeyringsByTypeAction\n | KeyringControllerGetAccountsAction;\n\nexport type AccountsControllerChangeEvent = {\n type: `${typeof controllerName}:stateChange`;\n payload: [AccountsControllerState, Patch[]];\n};\n\nexport type AccountsControllerSelectedAccountChangeEvent = {\n type: `${typeof controllerName}:selectedAccountChange`;\n payload: [InternalAccount];\n};\n\nexport type AccountsControllerEvents =\n | AccountsControllerChangeEvent\n | AccountsControllerSelectedAccountChangeEvent\n | SnapControllerEvents\n | KeyringControllerEvents;\n\nexport type AccountsControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n AccountsControllerActions,\n AccountsControllerEvents,\n string,\n 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 BaseControllerV2<\n typeof controllerName,\n AccountsControllerState,\n AccountsControllerMessenger\n> {\n keyringApiEnabled: boolean;\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 * @param [options.keyringApiEnabled] - The keyring API enabled flag.\n */\n constructor({\n messenger,\n state,\n keyringApiEnabled,\n }: {\n messenger: AccountsControllerMessenger;\n state: AccountsControllerState;\n keyringApiEnabled?: boolean;\n }) {\n super({\n messenger,\n name: controllerName,\n metadata: accountsControllerMetadata,\n state: {\n ...defaultState,\n ...state,\n },\n });\n\n this.keyringApiEnabled = Boolean(keyringApiEnabled);\n\n if (this.keyringApiEnabled) {\n this.messagingSystem.subscribe(\n 'SnapController:stateChange',\n async (snapStateState) =>\n await this.#handleOnSnapStateChange(snapStateState),\n );\n }\n\n this.messagingSystem.subscribe(\n 'KeyringController:stateChange',\n async (keyringState) =>\n await this.#handleOnKeyringStateChange(keyringState),\n );\n\n this.#registerMessageHandlers();\n\n // if somehow the selected account becomes lost then select the first account\n if (\n this.state.internalAccounts.selectedAccount !== '' &&\n !this.getAccount(this.state.internalAccounts.selectedAccount) &&\n this.listAccounts().length > 0\n ) {\n this.setSelectedAccount(this.listAccounts()[0].id);\n }\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 internal accounts.\n *\n * @returns An array of InternalAccount objects.\n */\n listAccounts(): InternalAccount[] {\n return Object.values(this.state.internalAccounts.accounts);\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 },\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 selected internal account.\n *\n * @returns The selected internal account.\n */\n getSelectedAccount(): InternalAccount {\n return this.getAccountExpect(this.state.internalAccounts.selectedAccount);\n }\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 // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore Type instantiation is excessively deep and possibly infinite.\n this.update((currentState: AccountsControllerState) => {\n currentState.internalAccounts.accounts[account.id].metadata.lastSelected =\n Date.now();\n currentState.internalAccounts.selectedAccount = account.id;\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: AccountsControllerState) => {\n currentState.internalAccounts.accounts[accountId] = {\n ...account,\n metadata: {\n ...account.metadata,\n name: accountName,\n },\n };\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 let normalAccounts = await this.#listNormalAccounts();\n let snapAccounts: InternalAccount[] = [];\n if (this.keyringApiEnabled) {\n snapAccounts = await this.#listSnapAccounts();\n // remove duplicate accounts that are retrieved from the snap keyring.\n normalAccounts = normalAccounts.filter(\n (account) =>\n !snapAccounts.find(\n (snapAccount) => snapAccount.address === account.address,\n ),\n );\n }\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 existingAccount && existingAccount.metadata.name !== ''\n ? existingAccount.metadata.name\n : `${keyringTypeName} ${keyringAccountIndex + 1}`,\n lastSelected: existingAccount?.metadata?.lastSelected,\n },\n };\n\n return internalAccountMap;\n }, {} as Record<string, InternalAccount>);\n\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore Type instantiation is excessively deep and possibly infinite.\n this.update((currentState: AccountsControllerState) => {\n currentState.internalAccounts.accounts = accounts;\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: AccountsControllerState) => {\n currentState.internalAccounts = backup.internalAccounts;\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] = await 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 = await (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 const v4options = {\n random: sha256FromString(address).slice(0, 16),\n };\n\n internalAccounts.push({\n id: uuid(v4options),\n address,\n options: {},\n methods: [\n 'personal_sign',\n 'eth_sign',\n 'eth_signTransaction',\n 'eth_signTypedData_v1',\n 'eth_signTypedData_v3',\n 'eth_signTypedData_v4',\n ],\n type: EthAccountType.Eoa,\n metadata: {\n name: '',\n keyring: {\n type: (keyring as Keyring<Json>).type,\n },\n },\n });\n }\n\n return internalAccounts.filter(\n (account) => account.metadata.keyring.type !== 'Snap Keyring',\n );\n }\n\n /**\n * Handles the removal of the currently selected account by selecting the previous account in the list.\n */\n #handleSelectedAccountRemoved() {\n const previousAccount = this.listAccounts()\n .filter(\n (account) => account.id !== this.state.internalAccounts.selectedAccount,\n )\n .sort((accountA, accountB) => {\n // sort by lastSelected descending\n return (\n (accountB.metadata.lastSelected ?? 0) -\n (accountA.metadata.lastSelected ?? 0)\n );\n })[0];\n\n this.setSelectedAccount(previousAccount.id);\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 * @returns A Promise that resolves when the function has finished executing.\n */\n async #handleOnKeyringStateChange(\n keyringState: KeyringControllerState,\n ): Promise<void> {\n // check if there are any new accounts added\n // TODO: change when accountAdded event is added to the keyring controller\n\n if (keyringState.isUnlocked) {\n // TODO: ACCOUNTS_CONTROLLER keyring will return accounts instead of addresses, remove this flatMap after and just get the latest id\n const updatedKeyringAddresses = keyringState.keyrings.flatMap(\n (keyring) => keyring.accounts,\n );\n const previousAccounts = this.listAccounts();\n\n // if there are no overlaps between the addresses in the keyring and previous accounts,\n // it means the keyring is being reinitialized because the vault is being restored with the same SRP\n const overlaps = updatedKeyringAddresses.filter((address) =>\n previousAccounts.find(\n (account) => account.address.toLowerCase() === address.toLowerCase(),\n ),\n );\n\n await this.updateAccounts();\n\n if (updatedKeyringAddresses.length > previousAccounts.length) {\n this.#handleNewAccountAdded(updatedKeyringAddresses, previousAccounts);\n } else if (updatedKeyringAddresses.length > 0 && overlaps.length === 0) {\n // if the keyring is being reinitialized, the selected account will be reset to the first account\n this.setSelectedAccount(this.listAccounts()[0].id);\n } else if (\n updatedKeyringAddresses.length < previousAccounts.length &&\n overlaps.length > 0 &&\n !this.getAccount(this.state.internalAccounts.selectedAccount)\n ) {\n this.#handleSelectedAccountRemoved();\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 * @returns A Promise that resolves when the update is complete.\n */\n async #handleOnSnapStateChange(\n snapState: SnapControllerState,\n ): Promise<void> {\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: 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 ValidatedSnapId];\n if (storedSnap) {\n currentAccount.metadata.snap.enabled =\n storedSnap.enabled && !storedSnap.blocked;\n }\n }\n });\n });\n }\n\n /**\n * Handles the event when a new account is added to the keyring.\n *\n * @param updatedKeyringAddresses - An array of updated keyring addresses.\n * @param previousAccounts - An array of previous internal accounts.\n */\n #handleNewAccountAdded(\n updatedKeyringAddresses: string[],\n previousAccounts: InternalAccount[],\n ) {\n const [newAddress] = updatedKeyringAddresses.filter(\n (address) =>\n !previousAccounts.find(\n (account) => account.address.toLowerCase() === address.toLowerCase(),\n ),\n );\n\n const [newAccount] = this.listAccounts().filter(\n (account) => account.address.toLowerCase() === newAddress.toLowerCase(),\n );\n\n this.setSelectedAccount(newAccount.id);\n }\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}\n\n/**\n * Returns the name of the keyring type.\n *\n * @param keyringType - The type of the keyring.\n * @returns The name of the keyring type.\n */\nexport function keyringTypeToName(keyringType: string): string {\n switch (keyringType) {\n case 'Simple Key Pair': {\n return 'Account';\n }\n case 'HD Key Tree': {\n return 'Account';\n }\n case 'Trezor Hardware': {\n return 'Trezor';\n }\n case 'Ledger Hardware': {\n return 'Ledger';\n }\n case 'Lattice Hardware': {\n return 'Lattice';\n }\n case 'QR Hardware Wallet Device': {\n return 'QR';\n }\n case 'Snap Keyring': {\n return 'Snap Account';\n }\n case 'Custody': {\n return 'Custody';\n }\n default: {\n throw new Error(`Unknown keyring ${keyringType}`);\n }\n }\n}\n"]}
|
1
|
+
{"version":3,"file":"AccountsController.js","sourceRoot":"","sources":["../src/AccountsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RestrictedControllerMessenger } from '@metamask/base-controller';\nimport { BaseControllerV2 } from '@metamask/base-controller';\nimport { SnapKeyring } from '@metamask/eth-snap-keyring';\nimport type { InternalAccount } from '@metamask/keyring-api';\nimport { EthAccountType } from '@metamask/keyring-api';\nimport { KeyringTypes } from '@metamask/keyring-controller';\nimport type {\n KeyringControllerState,\n KeyringControllerEvents,\n KeyringControllerGetKeyringForAccountAction,\n KeyringControllerGetKeyringsByTypeAction,\n KeyringControllerGetAccountsAction,\n} from '@metamask/keyring-controller';\nimport type {\n SnapControllerEvents,\n SnapControllerState,\n} from '@metamask/snaps-controllers';\nimport type { Snap, ValidatedSnapId } from '@metamask/snaps-utils';\nimport type { Keyring, Json } from '@metamask/utils';\nimport { sha256FromString } from 'ethereumjs-util';\nimport type { Patch, Draft } from 'immer';\nimport { v4 as uuid } from 'uuid';\n\nimport { getUUIDFromAddressOfNormalAccount, keyringTypeToName } 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 = {\n type: `${typeof controllerName}:getState`;\n handler: () => 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 AccountsControllerGetAccountByAddressAction = {\n type: `${typeof controllerName}:getAccountByAddress`;\n handler: AccountsController['getAccountByAddress'];\n};\nexport type AccountsControllerActions =\n | AccountsControllerGetStateAction\n | AccountsControllerSetSelectedAccountAction\n | AccountsControllerListAccountsAction\n | AccountsControllerSetAccountNameAction\n | AccountsControllerUpdateAccountsAction\n | AccountsControllerGetAccountByAddressAction\n | AccountsControllerGetSelectedAccountAction\n | KeyringControllerGetKeyringForAccountAction\n | KeyringControllerGetKeyringsByTypeAction\n | KeyringControllerGetAccountsAction;\n\nexport type AccountsControllerChangeEvent = {\n type: `${typeof controllerName}:stateChange`;\n payload: [AccountsControllerState, Patch[]];\n};\n\nexport type AccountsControllerSelectedAccountChangeEvent = {\n type: `${typeof controllerName}:selectedAccountChange`;\n payload: [InternalAccount];\n};\n\nexport type AccountsControllerEvents =\n | AccountsControllerChangeEvent\n | AccountsControllerSelectedAccountChangeEvent\n | SnapControllerEvents\n | KeyringControllerEvents;\n\nexport type AccountsControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n AccountsControllerActions,\n AccountsControllerEvents,\n string,\n string\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 BaseControllerV2<\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 internal accounts.\n *\n * @returns An array of InternalAccount objects.\n */\n listAccounts(): InternalAccount[] {\n return Object.values(this.state.internalAccounts.accounts);\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 },\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 selected internal account.\n *\n * @returns The selected internal account.\n */\n getSelectedAccount(): InternalAccount {\n return this.getAccountExpect(this.state.internalAccounts.selectedAccount);\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.getAccount(accountId);\n\n this.update((currentState: Draft<AccountsControllerState>) => {\n if (account) {\n currentState.internalAccounts.accounts[\n account.id\n ].metadata.lastSelected = Date.now();\n currentState.internalAccounts.selectedAccount = account.id;\n } else {\n currentState.internalAccounts.selectedAccount = '';\n }\n });\n\n if (account) {\n this.messagingSystem.publish(\n 'AccountsController:selectedAccountChange',\n account,\n );\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 currentState.internalAccounts.accounts[accountId] =\n // @ts-expect-error Assigning a complex type `T` to `Draft<T>` causes an excessive type instantiation depth error.\n internalAccount as Draft<InternalAccount>;\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: InternalAccount[] = await this.#listSnapAccounts();\n const normalAccounts = (await this.#listNormalAccounts()).filter(\n (account) =>\n !snapAccounts.find(\n (snapAccount) => snapAccount.address === account.address,\n ),\n );\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 existingAccount && existingAccount.metadata.name !== ''\n ? existingAccount.metadata.name\n : `${keyringTypeName} ${keyringAccountIndex + 1}`,\n lastSelected: existingAccount?.metadata?.lastSelected,\n },\n };\n\n return internalAccountMap;\n }, {} as Record<string, InternalAccount>);\n\n this.update((currentState: Draft<AccountsControllerState>) => {\n (currentState as AccountsControllerState).internalAccounts.accounts =\n accounts;\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 (currentState as AccountsControllerState).internalAccounts =\n backup.internalAccounts;\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 'personal_sign',\n 'eth_sign',\n 'eth_signTransaction',\n 'eth_signTypedData_v1',\n 'eth_signTypedData_v3',\n 'eth_signTypedData_v4',\n ],\n type: EthAccountType.Eoa,\n metadata: {\n name: '',\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 const v4options = {\n random: sha256FromString(address).slice(0, 16),\n };\n\n internalAccounts.push({\n id: uuid(v4options),\n address,\n options: {},\n methods: [\n 'personal_sign',\n 'eth_sign',\n 'eth_signTransaction',\n 'eth_signTypedData_v1',\n 'eth_signTypedData_v3',\n 'eth_signTypedData_v4',\n ],\n type: EthAccountType.Eoa,\n metadata: {\n name: '',\n keyring: {\n type: (keyring as Keyring<Json>).type,\n },\n },\n });\n }\n\n return internalAccounts.filter(\n (account) => account.metadata.keyring.type !== KeyringTypes.snap,\n );\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 if (keyringState.isUnlocked) {\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) =>\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 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 ValidatedSnapId];\n if (storedSnap) {\n currentAccount.metadata.snap.enabled =\n storedSnap.enabled && !storedSnap.blocked;\n }\n }\n });\n });\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 #getNextAccountNumber(keyringType: string): {\n accountPrefix: string;\n indexToUse: number;\n } {\n const keyringName = keyringTypeToName(keyringType);\n const previousKeyringAccounts = this.listAccounts().filter(\n (internalAccount) => {\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 return internalAccount.metadata.keyring.type === keyringType;\n },\n );\n const lastDefaultIndexUsedForKeyringType =\n previousKeyringAccounts\n .filter((internalAccount) =>\n new RegExp(`${keyringName} \\\\d+$`, 'u').test(\n internalAccount.metadata.name,\n ),\n )\n .map((internalAccount) => {\n const nameToWords = internalAccount.metadata.name.split(' '); // get the index of a default account name\n return parseInt(nameToWords[nameToWords.length], 10);\n })\n .sort((a, b) => b - a)[0] || 0;\n\n const indexToUse = Math.max(\n previousKeyringAccounts.length + 1,\n lastDefaultIndexUsedForKeyringType + 1,\n );\n\n return { accountPrefix: keyringName, indexToUse };\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 index number for the keyring type\n const { accountPrefix, indexToUse } = this.#getNextAccountNumber(\n newAccount.metadata.keyring.type,\n );\n\n const accountName = `${accountPrefix} ${indexToUse}`;\n\n this.update((currentState: Draft<AccountsControllerState>) => {\n (currentState as AccountsControllerState).internalAccounts.accounts[\n newAccount.id\n ] = {\n ...newAccount,\n metadata: {\n ...newAccount.metadata,\n name: accountName,\n lastSelected: Date.now(),\n },\n };\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 * 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}:getAccountByAddress`,\n this.getAccountByAddress.bind(this),\n );\n }\n}\n"]}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC"}
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
@@ -15,4 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
15
15
|
};
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
17
17
|
__exportStar(require("./AccountsController"), exports);
|
18
|
+
__exportStar(require("./utils"), exports);
|
18
19
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uDAAqC","sourcesContent":["export * from './AccountsController';\n"]}
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uDAAqC;AACrC,0CAAwB","sourcesContent":["export * from './AccountsController';\nexport * from './utils';\n"]}
|
package/dist/utils.d.ts
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
/**
|
2
|
+
* Returns the name of the keyring type.
|
3
|
+
*
|
4
|
+
* @param keyringType - The type of the keyring.
|
5
|
+
* @returns The name of the keyring type.
|
6
|
+
*/
|
7
|
+
export declare function keyringTypeToName(keyringType: string): string;
|
8
|
+
/**
|
9
|
+
* Generates a UUID from a given Ethereum address.
|
10
|
+
* @param address - The Ethereum address to generate the UUID from.
|
11
|
+
* @returns The generated UUID.
|
12
|
+
*/
|
13
|
+
export declare function getUUIDFromAddressOfNormalAccount(address: string): string;
|
14
|
+
//# sourceMappingURL=utils.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CA8B7D;AAED;;;;GAIG;AACH,wBAAgB,iCAAiC,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMzE"}
|
package/dist/utils.js
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.getUUIDFromAddressOfNormalAccount = exports.keyringTypeToName = void 0;
|
4
|
+
const keyring_controller_1 = require("@metamask/keyring-controller");
|
5
|
+
const ethereumjs_util_1 = require("ethereumjs-util");
|
6
|
+
const uuid_1 = require("uuid");
|
7
|
+
/**
|
8
|
+
* Returns the name of the keyring type.
|
9
|
+
*
|
10
|
+
* @param keyringType - The type of the keyring.
|
11
|
+
* @returns The name of the keyring type.
|
12
|
+
*/
|
13
|
+
function keyringTypeToName(keyringType) {
|
14
|
+
switch (keyringType) {
|
15
|
+
case keyring_controller_1.KeyringTypes.simple: {
|
16
|
+
return 'Account';
|
17
|
+
}
|
18
|
+
case keyring_controller_1.KeyringTypes.hd: {
|
19
|
+
return 'Account';
|
20
|
+
}
|
21
|
+
case keyring_controller_1.KeyringTypes.trezor: {
|
22
|
+
return 'Trezor';
|
23
|
+
}
|
24
|
+
case keyring_controller_1.KeyringTypes.ledger: {
|
25
|
+
return 'Ledger';
|
26
|
+
}
|
27
|
+
case keyring_controller_1.KeyringTypes.lattice: {
|
28
|
+
return 'Lattice';
|
29
|
+
}
|
30
|
+
case keyring_controller_1.KeyringTypes.qr: {
|
31
|
+
return 'QR';
|
32
|
+
}
|
33
|
+
case keyring_controller_1.KeyringTypes.snap: {
|
34
|
+
return 'Snap Account';
|
35
|
+
}
|
36
|
+
case keyring_controller_1.KeyringTypes.custody: {
|
37
|
+
return 'Custody';
|
38
|
+
}
|
39
|
+
default: {
|
40
|
+
throw new Error(`Unknown keyring ${keyringType}`);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
}
|
44
|
+
exports.keyringTypeToName = keyringTypeToName;
|
45
|
+
/**
|
46
|
+
* Generates a UUID from a given Ethereum address.
|
47
|
+
* @param address - The Ethereum address to generate the UUID from.
|
48
|
+
* @returns The generated UUID.
|
49
|
+
*/
|
50
|
+
function getUUIDFromAddressOfNormalAccount(address) {
|
51
|
+
const v4options = {
|
52
|
+
random: (0, ethereumjs_util_1.sha256FromString)(address).slice(0, 16),
|
53
|
+
};
|
54
|
+
return (0, uuid_1.v4)(v4options);
|
55
|
+
}
|
56
|
+
exports.getUUIDFromAddressOfNormalAccount = getUUIDFromAddressOfNormalAccount;
|
57
|
+
//# sourceMappingURL=utils.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;AAAA,qEAA4D;AAC5D,qDAAmD;AACnD,+BAAkC;AAElC;;;;;GAKG;AACH,SAAgB,iBAAiB,CAAC,WAAmB;IACnD,QAAQ,WAAW,EAAE;QACnB,KAAK,iCAAY,CAAC,MAAM,CAAC,CAAC;YACxB,OAAO,SAAS,CAAC;SAClB;QACD,KAAK,iCAAY,CAAC,EAAE,CAAC,CAAC;YACpB,OAAO,SAAS,CAAC;SAClB;QACD,KAAK,iCAAY,CAAC,MAAM,CAAC,CAAC;YACxB,OAAO,QAAQ,CAAC;SACjB;QACD,KAAK,iCAAY,CAAC,MAAM,CAAC,CAAC;YACxB,OAAO,QAAQ,CAAC;SACjB;QACD,KAAK,iCAAY,CAAC,OAAO,CAAC,CAAC;YACzB,OAAO,SAAS,CAAC;SAClB;QACD,KAAK,iCAAY,CAAC,EAAE,CAAC,CAAC;YACpB,OAAO,IAAI,CAAC;SACb;QACD,KAAK,iCAAY,CAAC,IAAI,CAAC,CAAC;YACtB,OAAO,cAAc,CAAC;SACvB;QACD,KAAK,iCAAY,CAAC,OAAO,CAAC,CAAC;YACzB,OAAO,SAAS,CAAC;SAClB;QACD,OAAO,CAAC,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,mBAAmB,WAAW,EAAE,CAAC,CAAC;SACnD;KACF;AACH,CAAC;AA9BD,8CA8BC;AAED;;;;GAIG;AACH,SAAgB,iCAAiC,CAAC,OAAe;IAC/D,MAAM,SAAS,GAAG;QAChB,MAAM,EAAE,IAAA,kCAAgB,EAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;KAC/C,CAAC;IAEF,OAAO,IAAA,SAAI,EAAC,SAAS,CAAC,CAAC;AACzB,CAAC;AAND,8EAMC","sourcesContent":["import { KeyringTypes } from '@metamask/keyring-controller';\nimport { sha256FromString } from 'ethereumjs-util';\nimport { v4 as uuid } from 'uuid';\n\n/**\n * Returns the name of the keyring type.\n *\n * @param keyringType - The type of the keyring.\n * @returns The name of the keyring type.\n */\nexport function keyringTypeToName(keyringType: string): string {\n switch (keyringType) {\n case KeyringTypes.simple: {\n return 'Account';\n }\n case KeyringTypes.hd: {\n return 'Account';\n }\n case KeyringTypes.trezor: {\n return 'Trezor';\n }\n case KeyringTypes.ledger: {\n return 'Ledger';\n }\n case KeyringTypes.lattice: {\n return 'Lattice';\n }\n case KeyringTypes.qr: {\n return 'QR';\n }\n case KeyringTypes.snap: {\n return 'Snap Account';\n }\n case KeyringTypes.custody: {\n return 'Custody';\n }\n default: {\n throw new Error(`Unknown keyring ${keyringType}`);\n }\n }\n}\n\n/**\n * Generates a UUID from a given Ethereum address.\n * @param address - The Ethereum address to generate the UUID from.\n * @returns The generated UUID.\n */\nexport function getUUIDFromAddressOfNormalAccount(address: string): string {\n const v4options = {\n random: sha256FromString(address).slice(0, 16),\n };\n\n return uuid(v4options);\n}\n"]}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@metamask/accounts-controller",
|
3
|
-
"version": "
|
3
|
+
"version": "4.0.0",
|
4
4
|
"description": "Manages internal accounts",
|
5
5
|
"keywords": [
|
6
6
|
"MetaMask",
|
@@ -30,7 +30,7 @@
|
|
30
30
|
},
|
31
31
|
"dependencies": {
|
32
32
|
"@metamask/base-controller": "^3.2.3",
|
33
|
-
"@metamask/eth-snap-keyring": "^
|
33
|
+
"@metamask/eth-snap-keyring": "^2.0.0",
|
34
34
|
"@metamask/keyring-api": "^1.0.0",
|
35
35
|
"@metamask/snaps-utils": "^3.0.0",
|
36
36
|
"@metamask/utils": "^8.1.0",
|
@@ -40,8 +40,8 @@
|
|
40
40
|
"uuid": "^8.3.2"
|
41
41
|
},
|
42
42
|
"devDependencies": {
|
43
|
-
"@metamask/auto-changelog": "^3.
|
44
|
-
"@metamask/keyring-controller": "^8.0
|
43
|
+
"@metamask/auto-changelog": "^3.4.2",
|
44
|
+
"@metamask/keyring-controller": "^8.1.0",
|
45
45
|
"@metamask/snaps-controllers": "^3.0.0",
|
46
46
|
"@types/jest": "^27.4.1",
|
47
47
|
"@types/readable-stream": "^2.3.0",
|
@@ -52,7 +52,7 @@
|
|
52
52
|
"typescript": "~4.8.4"
|
53
53
|
},
|
54
54
|
"peerDependencies": {
|
55
|
-
"@metamask/keyring-controller": "^8.0
|
55
|
+
"@metamask/keyring-controller": "^8.1.0"
|
56
56
|
},
|
57
57
|
"engines": {
|
58
58
|
"node": ">=16.0.0"
|