@metamask-previews/keyring-controller 17.2.0-preview-cf09c0a → 17.2.0-preview-09a2ffd5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/KeyringController.js +22 -0
  2. package/dist/KeyringController.js.map +1 -0
  3. package/dist/KeyringController.mjs +20 -1585
  4. package/dist/KeyringController.mjs.map +1 -1
  5. package/dist/chunk-F64I344Z.mjs +68 -0
  6. package/dist/chunk-F64I344Z.mjs.map +1 -0
  7. package/dist/chunk-JQRVJ3XK.mjs +1595 -0
  8. package/dist/chunk-JQRVJ3XK.mjs.map +1 -0
  9. package/dist/chunk-NOCGQCUM.js +68 -0
  10. package/dist/chunk-NOCGQCUM.js.map +1 -0
  11. package/dist/chunk-YRSQWNOT.js +1595 -0
  12. package/dist/chunk-YRSQWNOT.js.map +1 -0
  13. package/dist/constants.js +7 -0
  14. package/dist/constants.js.map +1 -0
  15. package/dist/constants.mjs +6 -35
  16. package/dist/constants.mjs.map +1 -1
  17. package/dist/index.js +20 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/index.mjs +19 -1
  20. package/dist/index.mjs.map +1 -1
  21. package/dist/tsconfig.build.tsbuildinfo +1 -0
  22. package/dist/{KeyringController.d.mts → types/KeyringController.d.ts} +10 -10
  23. package/dist/types/KeyringController.d.ts.map +1 -0
  24. package/dist/{constants.d.cts → types/constants.d.ts} +1 -1
  25. package/dist/types/constants.d.ts.map +1 -0
  26. package/dist/types/index.d.ts +2 -0
  27. package/dist/types/index.d.ts.map +1 -0
  28. package/package.json +7 -12
  29. package/dist/KeyringController.cjs +0 -1608
  30. package/dist/KeyringController.cjs.map +0 -1
  31. package/dist/KeyringController.d.cts +0 -700
  32. package/dist/KeyringController.d.cts.map +0 -1
  33. package/dist/KeyringController.d.mts.map +0 -1
  34. package/dist/constants.cjs +0 -39
  35. package/dist/constants.cjs.map +0 -1
  36. package/dist/constants.d.cts.map +0 -1
  37. package/dist/constants.d.mts +0 -35
  38. package/dist/constants.d.mts.map +0 -1
  39. package/dist/index.cjs +0 -18
  40. package/dist/index.cjs.map +0 -1
  41. package/dist/index.d.cts +0 -2
  42. package/dist/index.d.cts.map +0 -1
  43. package/dist/index.d.mts +0 -2
  44. package/dist/index.d.mts.map +0 -1
@@ -1,1608 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
26
- if (kind === "m") throw new TypeError("Private method is not writable");
27
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
28
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
29
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
30
- };
31
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
32
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
33
- 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");
34
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
35
- };
36
- var __importDefault = (this && this.__importDefault) || function (mod) {
37
- return (mod && mod.__esModule) ? mod : { "default": mod };
38
- };
39
- var _KeyringController_instances, _KeyringController_controllerOperationMutex, _KeyringController_vaultOperationMutex, _KeyringController_keyringBuilders, _KeyringController_keyrings, _KeyringController_unsupportedKeyrings, _KeyringController_password, _KeyringController_encryptor, _KeyringController_cacheEncryptionKey, _KeyringController_qrKeyringStateListener, _KeyringController_registerMessageHandlers, _KeyringController_getKeyringBuilderForType, _KeyringController_addQRKeyring, _KeyringController_subscribeToQRKeyringEvents, _KeyringController_unsubscribeFromQRKeyringsEvents, _KeyringController_createNewVaultWithKeyring, _KeyringController_getUpdatedKeyrings, _KeyringController_getSerializedKeyrings, _KeyringController_restoreSerializedKeyrings, _KeyringController_unlockKeyrings, _KeyringController_updateVault, _KeyringController_getAccountsFromKeyrings, _KeyringController_createKeyringWithFirstAccount, _KeyringController_newKeyring, _KeyringController_clearKeyrings, _KeyringController_restoreKeyring, _KeyringController_destroyKeyring, _KeyringController_removeEmptyKeyrings, _KeyringController_checkForDuplicate, _KeyringController_setUnlocked, _KeyringController_persistOrRollback, _KeyringController_withRollback, _KeyringController_assertControllerMutexIsLocked, _KeyringController_withControllerLock, _KeyringController_withVaultLock;
40
- Object.defineProperty(exports, "__esModule", { value: true });
41
- exports.KeyringController = exports.getDefaultKeyringState = exports.keyringBuilderFactory = exports.SignTypedDataVersion = exports.AccountImportStrategy = exports.isCustodyKeyring = exports.KeyringTypes = void 0;
42
- const util_1 = require("@ethereumjs/util");
43
- const base_controller_1 = require("@metamask/base-controller");
44
- const encryptorUtils = __importStar(require("@metamask/browser-passworder"));
45
- const eth_hd_keyring_1 = __importDefault(require("@metamask/eth-hd-keyring"));
46
- const eth_sig_util_1 = require("@metamask/eth-sig-util");
47
- const eth_simple_keyring_1 = __importDefault(require("@metamask/eth-simple-keyring"));
48
- const utils_1 = require("@metamask/utils");
49
- const async_mutex_1 = require("async-mutex");
50
- const ethereumjs_wallet_1 = __importStar(require("ethereumjs-wallet"));
51
- const constants_1 = require("./constants.cjs");
52
- const name = 'KeyringController';
53
- /**
54
- * Available keyring types
55
- */
56
- var KeyringTypes;
57
- (function (KeyringTypes) {
58
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
59
- // eslint-disable-next-line @typescript-eslint/naming-convention
60
- KeyringTypes["simple"] = "Simple Key Pair";
61
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
62
- // eslint-disable-next-line @typescript-eslint/naming-convention
63
- KeyringTypes["hd"] = "HD Key Tree";
64
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
65
- // eslint-disable-next-line @typescript-eslint/naming-convention
66
- KeyringTypes["qr"] = "QR Hardware Wallet Device";
67
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
68
- // eslint-disable-next-line @typescript-eslint/naming-convention
69
- KeyringTypes["trezor"] = "Trezor Hardware";
70
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
71
- // eslint-disable-next-line @typescript-eslint/naming-convention
72
- KeyringTypes["ledger"] = "Ledger Hardware";
73
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
74
- // eslint-disable-next-line @typescript-eslint/naming-convention
75
- KeyringTypes["lattice"] = "Lattice Hardware";
76
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
77
- // eslint-disable-next-line @typescript-eslint/naming-convention
78
- KeyringTypes["snap"] = "Snap Keyring";
79
- })(KeyringTypes || (exports.KeyringTypes = KeyringTypes = {}));
80
- /**
81
- * Custody keyring types are a special case, as they are not a single type
82
- * but they all start with the prefix "Custody".
83
- * @param keyringType - The type of the keyring.
84
- * @returns Whether the keyring type is a custody keyring.
85
- */
86
- const isCustodyKeyring = (keyringType) => {
87
- return keyringType.startsWith('Custody');
88
- };
89
- exports.isCustodyKeyring = isCustodyKeyring;
90
- /**
91
- * A strategy for importing an account
92
- */
93
- var AccountImportStrategy;
94
- (function (AccountImportStrategy) {
95
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
96
- // eslint-disable-next-line @typescript-eslint/naming-convention
97
- AccountImportStrategy["privateKey"] = "privateKey";
98
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
99
- // eslint-disable-next-line @typescript-eslint/naming-convention
100
- AccountImportStrategy["json"] = "json";
101
- })(AccountImportStrategy || (exports.AccountImportStrategy = AccountImportStrategy = {}));
102
- /**
103
- * The `signTypedMessage` version
104
- *
105
- * @see https://docs.metamask.io/guide/signing-data.html
106
- */
107
- var SignTypedDataVersion;
108
- (function (SignTypedDataVersion) {
109
- SignTypedDataVersion["V1"] = "V1";
110
- SignTypedDataVersion["V3"] = "V3";
111
- SignTypedDataVersion["V4"] = "V4";
112
- })(SignTypedDataVersion || (exports.SignTypedDataVersion = SignTypedDataVersion = {}));
113
- /**
114
- * Get builder function for `Keyring`
115
- *
116
- * Returns a builder function for `Keyring` with a `type` property.
117
- *
118
- * @param KeyringConstructor - The Keyring class for the builder.
119
- * @returns A builder function for the given Keyring.
120
- */
121
- function keyringBuilderFactory(KeyringConstructor) {
122
- const builder = () => new KeyringConstructor();
123
- builder.type = KeyringConstructor.type;
124
- return builder;
125
- }
126
- exports.keyringBuilderFactory = keyringBuilderFactory;
127
- const defaultKeyringBuilders = [
128
- keyringBuilderFactory(eth_simple_keyring_1.default),
129
- keyringBuilderFactory(eth_hd_keyring_1.default),
130
- ];
131
- const getDefaultKeyringState = () => {
132
- return {
133
- isUnlocked: false,
134
- keyrings: [],
135
- };
136
- };
137
- exports.getDefaultKeyringState = getDefaultKeyringState;
138
- /**
139
- * Assert that the given keyring has an exportable
140
- * mnemonic.
141
- *
142
- * @param keyring - The keyring to check
143
- * @throws When the keyring does not have a mnemonic
144
- */
145
- function assertHasUint8ArrayMnemonic(keyring) {
146
- if (!((0, utils_1.hasProperty)(keyring, 'mnemonic') && keyring.mnemonic instanceof Uint8Array)) {
147
- throw new Error("Can't get mnemonic bytes from keyring");
148
- }
149
- }
150
- /**
151
- * Assert that the provided encryptor supports
152
- * encryption and encryption key export.
153
- *
154
- * @param encryptor - The encryptor to check.
155
- * @throws If the encryptor does not support key encryption.
156
- */
157
- function assertIsExportableKeyEncryptor(encryptor) {
158
- if (!('importKey' in encryptor &&
159
- typeof encryptor.importKey === 'function' &&
160
- 'decryptWithKey' in encryptor &&
161
- typeof encryptor.decryptWithKey === 'function' &&
162
- 'encryptWithKey' in encryptor &&
163
- typeof encryptor.encryptWithKey === 'function')) {
164
- throw new Error(constants_1.KeyringControllerError.UnsupportedEncryptionKeyExport);
165
- }
166
- }
167
- /**
168
- * Assert that the provided password is a valid non-empty string.
169
- *
170
- * @param password - The password to check.
171
- * @throws If the password is not a valid string.
172
- */
173
- function assertIsValidPassword(password) {
174
- if (typeof password !== 'string') {
175
- throw new Error(constants_1.KeyringControllerError.WrongPasswordType);
176
- }
177
- if (!password || !password.length) {
178
- throw new Error(constants_1.KeyringControllerError.InvalidEmptyPassword);
179
- }
180
- }
181
- /**
182
- * Checks if the provided value is a serialized keyrings array.
183
- *
184
- * @param array - The value to check.
185
- * @returns True if the value is a serialized keyrings array.
186
- */
187
- function isSerializedKeyringsArray(array) {
188
- return (typeof array === 'object' &&
189
- Array.isArray(array) &&
190
- array.every((value) => value.type && (0, utils_1.isValidJson)(value.data)));
191
- }
192
- /**
193
- * Display For Keyring
194
- *
195
- * Is used for adding the current keyrings to the state object.
196
- *
197
- * @param keyring - The keyring to display.
198
- * @returns A keyring display object, with type and accounts properties.
199
- */
200
- async function displayForKeyring(keyring) {
201
- const accounts = await keyring.getAccounts();
202
- return {
203
- type: keyring.type,
204
- // Cast to `string[]` here is safe here because `accounts` has no nullish
205
- // values, and `normalize` returns `string` unless given a nullish value
206
- accounts: accounts.map(normalize),
207
- };
208
- }
209
- /**
210
- * Check if address is an ethereum address
211
- *
212
- * @param address - An address.
213
- * @returns Returns true if the address is an ethereum one, false otherwise.
214
- */
215
- function isEthAddress(address) {
216
- // We first check if it's a matching `Hex` string, so that is narrows down
217
- // `address` as an `Hex` type, allowing us to use `isValidHexAddress`
218
- return (
219
- // NOTE: This function only checks for lowercased strings
220
- (0, utils_1.isStrictHexString)(address.toLowerCase()) &&
221
- // This checks for lowercased addresses and checksum addresses too
222
- (0, utils_1.isValidHexAddress)(address));
223
- }
224
- /**
225
- * Normalize ethereum or non-EVM address.
226
- *
227
- * @param address - Ethereum or non-EVM address.
228
- * @returns The normalized address.
229
- */
230
- function normalize(address) {
231
- // Since the `KeyringController` is only dealing with address, we have
232
- // no other way to get the associated account type with this address. So we
233
- // are down to check the actual address format for now
234
- // TODO: Find a better way to not have those runtime checks based on the
235
- // address value!
236
- return isEthAddress(address) ? (0, eth_sig_util_1.normalize)(address) : address;
237
- }
238
- /**
239
- * Controller responsible for establishing and managing user identity.
240
- *
241
- * This class is a wrapper around the `eth-keyring-controller` package. The
242
- * `eth-keyring-controller` manages the "vault", which is an encrypted store of private keys, and
243
- * it manages the wallet "lock" state. This wrapper class has convenience methods for interacting
244
- * with the internal keyring controller and handling certain complex operations that involve the
245
- * keyrings.
246
- */
247
- class KeyringController extends base_controller_1.BaseController {
248
- /**
249
- * Creates a KeyringController instance.
250
- *
251
- * @param options - Initial options used to configure this controller
252
- * @param options.encryptor - An optional object for defining encryption schemes.
253
- * @param options.keyringBuilders - Set a new name for account.
254
- * @param options.cacheEncryptionKey - Whether to cache or not encryption key.
255
- * @param options.messenger - A restricted controller messenger.
256
- * @param options.state - Initial state to set on this controller.
257
- */
258
- constructor(options) {
259
- const { encryptor = encryptorUtils, keyringBuilders, messenger, state, } = options;
260
- super({
261
- name,
262
- metadata: {
263
- vault: { persist: true, anonymous: false },
264
- isUnlocked: { persist: false, anonymous: true },
265
- keyrings: { persist: false, anonymous: false },
266
- encryptionKey: { persist: false, anonymous: false },
267
- encryptionSalt: { persist: false, anonymous: false },
268
- },
269
- messenger,
270
- state: {
271
- ...(0, exports.getDefaultKeyringState)(),
272
- ...state,
273
- },
274
- });
275
- _KeyringController_instances.add(this);
276
- _KeyringController_controllerOperationMutex.set(this, new async_mutex_1.Mutex());
277
- _KeyringController_vaultOperationMutex.set(this, new async_mutex_1.Mutex());
278
- _KeyringController_keyringBuilders.set(this, void 0);
279
- _KeyringController_keyrings.set(this, void 0);
280
- _KeyringController_unsupportedKeyrings.set(this, void 0);
281
- _KeyringController_password.set(this, void 0);
282
- _KeyringController_encryptor.set(this, void 0);
283
- _KeyringController_cacheEncryptionKey.set(this, void 0);
284
- _KeyringController_qrKeyringStateListener.set(this, void 0);
285
- __classPrivateFieldSet(this, _KeyringController_keyringBuilders, keyringBuilders
286
- ? keyringBuilders.concat(defaultKeyringBuilders)
287
- : defaultKeyringBuilders, "f");
288
- __classPrivateFieldSet(this, _KeyringController_encryptor, encryptor, "f");
289
- __classPrivateFieldSet(this, _KeyringController_keyrings, [], "f");
290
- __classPrivateFieldSet(this, _KeyringController_unsupportedKeyrings, [], "f");
291
- // This option allows the controller to cache an exported key
292
- // for use in decrypting and encrypting data without password
293
- __classPrivateFieldSet(this, _KeyringController_cacheEncryptionKey, Boolean(options.cacheEncryptionKey), "f");
294
- if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
295
- assertIsExportableKeyEncryptor(encryptor);
296
- }
297
- __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_registerMessageHandlers).call(this);
298
- }
299
- /**
300
- * Adds a new account to the default (first) HD seed phrase keyring.
301
- *
302
- * @param accountCount - Number of accounts before adding a new one, used to
303
- * make the method idempotent.
304
- * @returns Promise resolving to the added account address.
305
- */
306
- async addNewAccount(accountCount) {
307
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
308
- const primaryKeyring = this.getKeyringsByType('HD Key Tree')[0];
309
- if (!primaryKeyring) {
310
- throw new Error('No HD keyring found');
311
- }
312
- const oldAccounts = await primaryKeyring.getAccounts();
313
- if (accountCount && oldAccounts.length !== accountCount) {
314
- if (accountCount > oldAccounts.length) {
315
- throw new Error('Account out of sequence');
316
- }
317
- // we return the account already existing at index `accountCount`
318
- const existingAccount = oldAccounts[accountCount];
319
- if (!existingAccount) {
320
- throw new Error(`Can't find account at index ${accountCount}`);
321
- }
322
- return existingAccount;
323
- }
324
- const [addedAccountAddress] = await primaryKeyring.addAccounts(1);
325
- await this.verifySeedPhrase();
326
- return addedAccountAddress;
327
- });
328
- }
329
- /**
330
- * Adds a new account to the specified keyring.
331
- *
332
- * @param keyring - Keyring to add the account to.
333
- * @param accountCount - Number of accounts before adding a new one, used to make the method idempotent.
334
- * @returns Promise resolving to the added account address
335
- */
336
- async addNewAccountForKeyring(keyring, accountCount) {
337
- // READ THIS CAREFULLY:
338
- // We still uses `Hex` here, since we are not using this method when creating
339
- // and account using a "Snap Keyring". This function assume the `keyring` is
340
- // ethereum compatible, but "Snap Keyring" might not be.
341
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
342
- const oldAccounts = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getAccountsFromKeyrings).call(this);
343
- if (accountCount && oldAccounts.length !== accountCount) {
344
- if (accountCount > oldAccounts.length) {
345
- throw new Error('Account out of sequence');
346
- }
347
- const existingAccount = oldAccounts[accountCount];
348
- (0, utils_1.assertIsStrictHexString)(existingAccount);
349
- return existingAccount;
350
- }
351
- await keyring.addAccounts(1);
352
- const addedAccountAddress = (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getAccountsFromKeyrings).call(this)).find((selectedAddress) => !oldAccounts.includes(selectedAddress));
353
- (0, utils_1.assertIsStrictHexString)(addedAccountAddress);
354
- return addedAccountAddress;
355
- });
356
- }
357
- /**
358
- * Adds a new account to the default (first) HD seed phrase keyring without updating identities in preferences.
359
- *
360
- * @returns Promise resolving to the added account address.
361
- */
362
- async addNewAccountWithoutUpdate() {
363
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
364
- const primaryKeyring = this.getKeyringsByType('HD Key Tree')[0];
365
- if (!primaryKeyring) {
366
- throw new Error('No HD keyring found');
367
- }
368
- const [addedAccountAddress] = await primaryKeyring.addAccounts(1);
369
- await this.verifySeedPhrase();
370
- return addedAccountAddress;
371
- });
372
- }
373
- /**
374
- * Effectively the same as creating a new keychain then populating it
375
- * using the given seed phrase.
376
- *
377
- * @param password - Password to unlock keychain.
378
- * @param seed - A BIP39-compliant seed phrase as Uint8Array,
379
- * either as a string or an array of UTF-8 bytes that represent the string.
380
- * @returns Promise resolving when the operation ends successfully.
381
- */
382
- async createNewVaultAndRestore(password, seed) {
383
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
384
- assertIsValidPassword(password);
385
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createNewVaultWithKeyring).call(this, password, {
386
- type: KeyringTypes.hd,
387
- opts: {
388
- mnemonic: seed,
389
- numberOfAccounts: 1,
390
- },
391
- });
392
- });
393
- }
394
- /**
395
- * Create a new vault and primary keyring.
396
- *
397
- * This only works if keyrings are empty. If there is a pre-existing unlocked vault, calling this will have no effect.
398
- * If there is a pre-existing locked vault, it will be replaced.
399
- *
400
- * @param password - Password to unlock the new vault.
401
- */
402
- async createNewVaultAndKeychain(password) {
403
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
404
- const accounts = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getAccountsFromKeyrings).call(this);
405
- if (!accounts.length) {
406
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createNewVaultWithKeyring).call(this, password, {
407
- type: KeyringTypes.hd,
408
- });
409
- }
410
- });
411
- }
412
- /**
413
- * Adds a new keyring of the given `type`.
414
- *
415
- * @param type - Keyring type name.
416
- * @param opts - Keyring options.
417
- * @throws If a builder for the given `type` does not exist.
418
- * @returns Promise resolving to the added keyring.
419
- */
420
- async addNewKeyring(type, opts) {
421
- if (type === KeyringTypes.qr) {
422
- return this.getOrAddQRKeyring();
423
- }
424
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, opts));
425
- }
426
- /**
427
- * Method to verify a given password validity. Throws an
428
- * error if the password is invalid.
429
- *
430
- * @param password - Password of the keyring.
431
- */
432
- async verifyPassword(password) {
433
- if (!this.state.vault) {
434
- throw new Error(constants_1.KeyringControllerError.VaultError);
435
- }
436
- await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, this.state.vault);
437
- }
438
- /**
439
- * Returns the status of the vault.
440
- *
441
- * @returns Boolean returning true if the vault is unlocked.
442
- */
443
- isUnlocked() {
444
- return this.state.isUnlocked;
445
- }
446
- /**
447
- * Gets the seed phrase of the HD keyring.
448
- *
449
- * @param password - Password of the keyring.
450
- * @returns Promise resolving to the seed phrase.
451
- */
452
- async exportSeedPhrase(password) {
453
- await this.verifyPassword(password);
454
- assertHasUint8ArrayMnemonic(__classPrivateFieldGet(this, _KeyringController_keyrings, "f")[0]);
455
- return __classPrivateFieldGet(this, _KeyringController_keyrings, "f")[0].mnemonic;
456
- }
457
- /**
458
- * Gets the private key from the keyring controlling an address.
459
- *
460
- * @param password - Password of the keyring.
461
- * @param address - Address to export.
462
- * @returns Promise resolving to the private key for an address.
463
- */
464
- async exportAccount(password, address) {
465
- await this.verifyPassword(password);
466
- const keyring = (await this.getKeyringForAccount(address));
467
- if (!keyring.exportAccount) {
468
- throw new Error(constants_1.KeyringControllerError.UnsupportedExportAccount);
469
- }
470
- return await keyring.exportAccount(normalize(address));
471
- }
472
- /**
473
- * Returns the public addresses of all accounts from every keyring.
474
- *
475
- * @returns A promise resolving to an array of addresses.
476
- */
477
- async getAccounts() {
478
- return this.state.keyrings.reduce((accounts, keyring) => accounts.concat(keyring.accounts), []);
479
- }
480
- /**
481
- * Get encryption public key.
482
- *
483
- * @param account - An account address.
484
- * @param opts - Additional encryption options.
485
- * @throws If the `account` does not exist or does not support the `getEncryptionPublicKey` method
486
- * @returns Promise resolving to encyption public key of the `account` if one exists.
487
- */
488
- async getEncryptionPublicKey(account, opts) {
489
- const address = (0, eth_sig_util_1.normalize)(account);
490
- const keyring = (await this.getKeyringForAccount(account));
491
- if (!keyring.getEncryptionPublicKey) {
492
- throw new Error(constants_1.KeyringControllerError.UnsupportedGetEncryptionPublicKey);
493
- }
494
- return await keyring.getEncryptionPublicKey(address, opts);
495
- }
496
- /**
497
- * Attempts to decrypt the provided message parameters.
498
- *
499
- * @param messageParams - The decryption message parameters.
500
- * @param messageParams.from - The address of the account you want to use to decrypt the message.
501
- * @param messageParams.data - The encrypted data that you want to decrypt.
502
- * @returns The raw decryption result.
503
- */
504
- async decryptMessage(messageParams) {
505
- const address = (0, eth_sig_util_1.normalize)(messageParams.from);
506
- const keyring = (await this.getKeyringForAccount(address));
507
- if (!keyring.decryptMessage) {
508
- throw new Error(constants_1.KeyringControllerError.UnsupportedDecryptMessage);
509
- }
510
- return keyring.decryptMessage(address, messageParams.data);
511
- }
512
- /**
513
- * Returns the currently initialized keyring that manages
514
- * the specified `address` if one exists.
515
- *
516
- * @deprecated Use of this method is discouraged as actions executed directly on
517
- * keyrings are not being reflected in the KeyringController state and not
518
- * persisted in the vault. Use `withKeyring` instead.
519
- * @param account - An account address.
520
- * @returns Promise resolving to keyring of the `account` if one exists.
521
- */
522
- async getKeyringForAccount(account) {
523
- const address = normalize(account);
524
- const candidates = await Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(async (keyring) => {
525
- return Promise.all([keyring, keyring.getAccounts()]);
526
- }));
527
- const winners = candidates.filter((candidate) => {
528
- const accounts = candidate[1].map(normalize);
529
- return accounts.includes(address);
530
- });
531
- if (winners.length && winners[0]?.length) {
532
- return winners[0][0];
533
- }
534
- // Adding more info to the error
535
- let errorInfo = '';
536
- if (!candidates.length) {
537
- errorInfo = 'There are no keyrings';
538
- }
539
- else if (!winners.length) {
540
- errorInfo = 'There are keyrings, but none match the address';
541
- }
542
- throw new Error(`${constants_1.KeyringControllerError.NoKeyring}. Error info: ${errorInfo}`);
543
- }
544
- /**
545
- * Returns all keyrings of the given type.
546
- *
547
- * @deprecated Use of this method is discouraged as actions executed directly on
548
- * keyrings are not being reflected in the KeyringController state and not
549
- * persisted in the vault. Use `withKeyring` instead.
550
- * @param type - Keyring type name.
551
- * @returns An array of keyrings of the given type.
552
- */
553
- getKeyringsByType(type) {
554
- return __classPrivateFieldGet(this, _KeyringController_keyrings, "f").filter((keyring) => keyring.type === type);
555
- }
556
- /**
557
- * Persist all serialized keyrings in the vault.
558
- *
559
- * @deprecated This method is being phased out in favor of `withKeyring`.
560
- * @returns Promise resolving with `true` value when the
561
- * operation completes.
562
- */
563
- async persistAllKeyrings() {
564
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => true);
565
- }
566
- /**
567
- * Imports an account with the specified import strategy.
568
- *
569
- * @param strategy - Import strategy name.
570
- * @param args - Array of arguments to pass to the underlying stategy.
571
- * @throws Will throw when passed an unrecognized strategy.
572
- * @returns Promise resolving to the imported account address.
573
- */
574
- async importAccountWithStrategy(strategy,
575
- // TODO: Replace `any` with type
576
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
577
- args) {
578
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
579
- let privateKey;
580
- switch (strategy) {
581
- case 'privateKey':
582
- const [importedKey] = args;
583
- if (!importedKey) {
584
- throw new Error('Cannot import an empty key.');
585
- }
586
- const prefixed = (0, utils_1.add0x)(importedKey);
587
- let bufferedPrivateKey;
588
- try {
589
- bufferedPrivateKey = (0, util_1.toBuffer)(prefixed);
590
- }
591
- catch {
592
- throw new Error('Cannot import invalid private key.');
593
- }
594
- if (!(0, util_1.isValidPrivate)(bufferedPrivateKey) ||
595
- // ensures that the key is 64 bytes long
596
- (0, util_1.getBinarySize)(prefixed) !== 64 + '0x'.length) {
597
- throw new Error('Cannot import invalid private key.');
598
- }
599
- privateKey = (0, utils_1.remove0x)(prefixed);
600
- break;
601
- case 'json':
602
- let wallet;
603
- const [input, password] = args;
604
- try {
605
- wallet = ethereumjs_wallet_1.thirdparty.fromEtherWallet(input, password);
606
- }
607
- catch (e) {
608
- wallet = wallet || (await ethereumjs_wallet_1.default.fromV3(input, password, true));
609
- }
610
- privateKey = (0, utils_1.bytesToHex)(wallet.getPrivateKey());
611
- break;
612
- default:
613
- throw new Error(`Unexpected import strategy: '${strategy}'`);
614
- }
615
- const newKeyring = (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, KeyringTypes.simple, [
616
- privateKey,
617
- ]));
618
- const accounts = await newKeyring.getAccounts();
619
- return accounts[0];
620
- });
621
- }
622
- /**
623
- * Removes an account from keyring state.
624
- *
625
- * @param address - Address of the account to remove.
626
- * @fires KeyringController:accountRemoved
627
- * @returns Promise resolving when the account is removed.
628
- */
629
- async removeAccount(address) {
630
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
631
- const keyring = (await this.getKeyringForAccount(address));
632
- // Not all the keyrings support this, so we have to check
633
- if (!keyring.removeAccount) {
634
- throw new Error(constants_1.KeyringControllerError.UnsupportedRemoveAccount);
635
- }
636
- // The `removeAccount` method of snaps keyring is async. We have to update
637
- // the interface of the other keyrings to be async as well.
638
- // eslint-disable-next-line @typescript-eslint/await-thenable
639
- // FIXME: We do cast to `Hex` to makes the type checker happy here, and
640
- // because `Keyring<State>.removeAccount` requires address to be `Hex`. Those
641
- // type would need to be updated for a full non-EVM support.
642
- keyring.removeAccount(address);
643
- const accounts = await keyring.getAccounts();
644
- // Check if this was the last/only account
645
- if (accounts.length === 0) {
646
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_removeEmptyKeyrings).call(this);
647
- }
648
- });
649
- this.messagingSystem.publish(`${name}:accountRemoved`, address);
650
- }
651
- /**
652
- * Deallocates all secrets and locks the wallet.
653
- *
654
- * @returns Promise resolving when the operation completes.
655
- */
656
- async setLocked() {
657
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
658
- __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unsubscribeFromQRKeyringsEvents).call(this);
659
- __classPrivateFieldSet(this, _KeyringController_password, undefined, "f");
660
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
661
- this.update((state) => {
662
- state.isUnlocked = false;
663
- state.keyrings = [];
664
- delete state.encryptionKey;
665
- delete state.encryptionSalt;
666
- });
667
- this.messagingSystem.publish(`${name}:lock`);
668
- });
669
- }
670
- /**
671
- * Signs message by calling down into a specific keyring.
672
- *
673
- * @param messageParams - PersonalMessageParams object to sign.
674
- * @returns Promise resolving to a signed message string.
675
- */
676
- async signMessage(messageParams) {
677
- if (!messageParams.data) {
678
- throw new Error("Can't sign an empty message");
679
- }
680
- const address = (0, eth_sig_util_1.normalize)(messageParams.from);
681
- const keyring = (await this.getKeyringForAccount(address));
682
- if (!keyring.signMessage) {
683
- throw new Error(constants_1.KeyringControllerError.UnsupportedSignMessage);
684
- }
685
- return await keyring.signMessage(address, messageParams.data);
686
- }
687
- /**
688
- * Signs personal message by calling down into a specific keyring.
689
- *
690
- * @param messageParams - PersonalMessageParams object to sign.
691
- * @returns Promise resolving to a signed message string.
692
- */
693
- async signPersonalMessage(messageParams) {
694
- const address = (0, eth_sig_util_1.normalize)(messageParams.from);
695
- const keyring = (await this.getKeyringForAccount(address));
696
- if (!keyring.signPersonalMessage) {
697
- throw new Error(constants_1.KeyringControllerError.UnsupportedSignPersonalMessage);
698
- }
699
- const normalizedData = normalize(messageParams.data);
700
- return await keyring.signPersonalMessage(address, normalizedData);
701
- }
702
- /**
703
- * Signs typed message by calling down into a specific keyring.
704
- *
705
- * @param messageParams - TypedMessageParams object to sign.
706
- * @param version - Compatibility version EIP712.
707
- * @throws Will throw when passed an unrecognized version.
708
- * @returns Promise resolving to a signed message string or an error if any.
709
- */
710
- async signTypedMessage(messageParams, version) {
711
- try {
712
- if (![
713
- SignTypedDataVersion.V1,
714
- SignTypedDataVersion.V3,
715
- SignTypedDataVersion.V4,
716
- ].includes(version)) {
717
- throw new Error(`Unexpected signTypedMessage version: '${version}'`);
718
- }
719
- // Cast to `Hex` here is safe here because `messageParams.from` is not nullish.
720
- // `normalize` returns `Hex` unless given a nullish value.
721
- const address = (0, eth_sig_util_1.normalize)(messageParams.from);
722
- const keyring = (await this.getKeyringForAccount(address));
723
- if (!keyring.signTypedData) {
724
- throw new Error(constants_1.KeyringControllerError.UnsupportedSignTypedMessage);
725
- }
726
- return await keyring.signTypedData(address, version !== SignTypedDataVersion.V1 &&
727
- typeof messageParams.data === 'string'
728
- ? JSON.parse(messageParams.data)
729
- : messageParams.data, { version });
730
- }
731
- catch (error) {
732
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
733
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
734
- throw new Error(`Keyring Controller signTypedMessage: ${error}`);
735
- }
736
- }
737
- /**
738
- * Signs a transaction by calling down into a specific keyring.
739
- *
740
- * @param transaction - Transaction object to sign. Must be a `ethereumjs-tx` transaction instance.
741
- * @param from - Address to sign from, should be in keychain.
742
- * @param opts - An optional options object.
743
- * @returns Promise resolving to a signed transaction string.
744
- */
745
- async signTransaction(transaction, from, opts) {
746
- const address = (0, eth_sig_util_1.normalize)(from);
747
- const keyring = (await this.getKeyringForAccount(address));
748
- if (!keyring.signTransaction) {
749
- throw new Error(constants_1.KeyringControllerError.UnsupportedSignTransaction);
750
- }
751
- return await keyring.signTransaction(address, transaction, opts);
752
- }
753
- /**
754
- * Convert a base transaction to a base UserOperation.
755
- *
756
- * @param from - Address of the sender.
757
- * @param transactions - Base transactions to include in the UserOperation.
758
- * @param executionContext - The execution context to use for the UserOperation.
759
- * @returns A pseudo-UserOperation that can be used to construct a real.
760
- */
761
- async prepareUserOperation(from, transactions, executionContext) {
762
- const address = (0, eth_sig_util_1.normalize)(from);
763
- const keyring = (await this.getKeyringForAccount(address));
764
- if (!keyring.prepareUserOperation) {
765
- throw new Error(constants_1.KeyringControllerError.UnsupportedPrepareUserOperation);
766
- }
767
- return await keyring.prepareUserOperation(address, transactions, executionContext);
768
- }
769
- /**
770
- * Patches properties of a UserOperation. Currently, only the
771
- * `paymasterAndData` can be patched.
772
- *
773
- * @param from - Address of the sender.
774
- * @param userOp - UserOperation to patch.
775
- * @param executionContext - The execution context to use for the UserOperation.
776
- * @returns A patch to apply to the UserOperation.
777
- */
778
- async patchUserOperation(from, userOp, executionContext) {
779
- const address = (0, eth_sig_util_1.normalize)(from);
780
- const keyring = (await this.getKeyringForAccount(address));
781
- if (!keyring.patchUserOperation) {
782
- throw new Error(constants_1.KeyringControllerError.UnsupportedPatchUserOperation);
783
- }
784
- return await keyring.patchUserOperation(address, userOp, executionContext);
785
- }
786
- /**
787
- * Signs an UserOperation.
788
- *
789
- * @param from - Address of the sender.
790
- * @param userOp - UserOperation to sign.
791
- * @param executionContext - The execution context to use for the UserOperation.
792
- * @returns The signature of the UserOperation.
793
- */
794
- async signUserOperation(from, userOp, executionContext) {
795
- const address = (0, eth_sig_util_1.normalize)(from);
796
- const keyring = (await this.getKeyringForAccount(address));
797
- if (!keyring.signUserOperation) {
798
- throw new Error(constants_1.KeyringControllerError.UnsupportedSignUserOperation);
799
- }
800
- return await keyring.signUserOperation(address, userOp, executionContext);
801
- }
802
- /**
803
- * Changes the password used to encrypt the vault.
804
- *
805
- * @param password - The new password.
806
- * @returns Promise resolving when the operation completes.
807
- */
808
- changePassword(password) {
809
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
810
- if (!this.state.isUnlocked) {
811
- throw new Error(constants_1.KeyringControllerError.MissingCredentials);
812
- }
813
- assertIsValidPassword(password);
814
- __classPrivateFieldSet(this, _KeyringController_password, password, "f");
815
- // We need to clear encryption key and salt from state
816
- // to force the controller to re-encrypt the vault using
817
- // the new password.
818
- if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
819
- this.update((state) => {
820
- delete state.encryptionKey;
821
- delete state.encryptionSalt;
822
- });
823
- }
824
- });
825
- }
826
- /**
827
- * Attempts to decrypt the current vault and load its keyrings,
828
- * using the given encryption key and salt.
829
- *
830
- * @param encryptionKey - Key to unlock the keychain.
831
- * @param encryptionSalt - Salt to unlock the keychain.
832
- * @returns Promise resolving when the operation completes.
833
- */
834
- async submitEncryptionKey(encryptionKey, encryptionSalt) {
835
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
836
- __classPrivateFieldSet(this, _KeyringController_keyrings, await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, undefined, encryptionKey, encryptionSalt), "f");
837
- __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
838
- });
839
- }
840
- /**
841
- * Attempts to decrypt the current vault and load its keyrings,
842
- * using the given password.
843
- *
844
- * @param password - Password to unlock the keychain.
845
- * @returns Promise resolving when the operation completes.
846
- */
847
- async submitPassword(password) {
848
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
849
- __classPrivateFieldSet(this, _KeyringController_keyrings, await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, password), "f");
850
- __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
851
- });
852
- }
853
- /**
854
- * Verifies the that the seed phrase restores the current keychain's accounts.
855
- *
856
- * @returns Promise resolving to the seed phrase as Uint8Array.
857
- */
858
- async verifySeedPhrase() {
859
- const primaryKeyring = this.getKeyringsByType(KeyringTypes.hd)[0];
860
- if (!primaryKeyring) {
861
- throw new Error('No HD keyring found.');
862
- }
863
- assertHasUint8ArrayMnemonic(primaryKeyring);
864
- const seedWords = primaryKeyring.mnemonic;
865
- const accounts = await primaryKeyring.getAccounts();
866
- /* istanbul ignore if */
867
- if (accounts.length === 0) {
868
- throw new Error('Cannot verify an empty keyring.');
869
- }
870
- // The HD Keyring Builder is a default keyring builder
871
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
872
- const hdKeyringBuilder = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringBuilderForType).call(this, KeyringTypes.hd);
873
- const hdKeyring = hdKeyringBuilder();
874
- // @ts-expect-error @metamask/eth-hd-keyring correctly handles
875
- // Uint8Array seed phrases in the `deserialize` method.
876
- await hdKeyring.deserialize({
877
- mnemonic: seedWords,
878
- numberOfAccounts: accounts.length,
879
- });
880
- const testAccounts = await hdKeyring.getAccounts();
881
- /* istanbul ignore if */
882
- if (testAccounts.length !== accounts.length) {
883
- throw new Error('Seed phrase imported incorrect number of accounts.');
884
- }
885
- testAccounts.forEach((account, i) => {
886
- /* istanbul ignore if */
887
- if (account.toLowerCase() !== accounts[i].toLowerCase()) {
888
- throw new Error('Seed phrase imported different accounts.');
889
- }
890
- });
891
- return seedWords;
892
- }
893
- async withKeyring(selector, operation, options = {
894
- createIfMissing: false,
895
- }) {
896
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
897
- let keyring;
898
- if ('address' in selector) {
899
- keyring = (await this.getKeyringForAccount(selector.address));
900
- }
901
- else {
902
- keyring = this.getKeyringsByType(selector.type)[selector.index || 0];
903
- if (!keyring && options.createIfMissing) {
904
- keyring = (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, selector.type, options.createWithData));
905
- }
906
- }
907
- if (!keyring) {
908
- throw new Error(constants_1.KeyringControllerError.KeyringNotFound);
909
- }
910
- const result = await operation(keyring);
911
- if (Object.is(result, keyring)) {
912
- // Access to a keyring instance outside of controller safeguards
913
- // should be discouraged, as it can lead to unexpected behavior.
914
- // This error is thrown to prevent consumers using `withKeyring`
915
- // as a way to get a reference to a keyring instance.
916
- throw new Error(constants_1.KeyringControllerError.UnsafeDirectKeyringAccess);
917
- }
918
- return result;
919
- });
920
- }
921
- // QR Hardware related methods
922
- /**
923
- * Get QR Hardware keyring.
924
- *
925
- * @returns The QR Keyring if defined, otherwise undefined
926
- * @deprecated Use `withKeyring` instead.
927
- */
928
- getQRKeyring() {
929
- // QRKeyring is not yet compatible with Keyring type from @metamask/utils
930
- return this.getKeyringsByType(KeyringTypes.qr)[0];
931
- }
932
- /**
933
- * Get QR hardware keyring. If it doesn't exist, add it.
934
- *
935
- * @returns The added keyring
936
- * @deprecated Use `addNewKeyring` and `withKeyring` instead.
937
- */
938
- async getOrAddQRKeyring() {
939
- return (this.getQRKeyring() ||
940
- (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_addQRKeyring).call(this))));
941
- }
942
- /**
943
- * Restore QR keyring from serialized data.
944
- *
945
- * @param serialized - Serialized data to restore the keyring from.
946
- * @returns Promise resolving when the operation completes.
947
- * @deprecated Use `withKeyring` instead.
948
- */
949
- // TODO: Replace `any` with type
950
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
951
- async restoreQRKeyring(serialized) {
952
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
953
- const keyring = this.getQRKeyring() || (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_addQRKeyring).call(this));
954
- keyring.deserialize(serialized);
955
- });
956
- }
957
- /**
958
- * Reset QR keyring state.
959
- *
960
- * @returns Promise resolving when the operation completes.
961
- * @deprecated Use `withKeyring` instead.
962
- */
963
- async resetQRKeyringState() {
964
- (await this.getOrAddQRKeyring()).resetStore();
965
- }
966
- /**
967
- * Get QR keyring state.
968
- *
969
- * @returns Promise resolving to the keyring state.
970
- * @deprecated Use `withKeyring` or subscribe to `"KeyringController:qrKeyringStateChange"`
971
- * instead.
972
- */
973
- async getQRKeyringState() {
974
- return (await this.getOrAddQRKeyring()).getMemStore();
975
- }
976
- /**
977
- * Submit QR hardware wallet public HDKey.
978
- *
979
- * @param cryptoHDKey - The key to submit.
980
- * @returns Promise resolving when the operation completes.
981
- * @deprecated Use `withKeyring` instead.
982
- */
983
- async submitQRCryptoHDKey(cryptoHDKey) {
984
- (await this.getOrAddQRKeyring()).submitCryptoHDKey(cryptoHDKey);
985
- }
986
- /**
987
- * Submit QR hardware wallet account.
988
- *
989
- * @param cryptoAccount - The account to submit.
990
- * @returns Promise resolving when the operation completes.
991
- * @deprecated Use `withKeyring` instead.
992
- */
993
- async submitQRCryptoAccount(cryptoAccount) {
994
- (await this.getOrAddQRKeyring()).submitCryptoAccount(cryptoAccount);
995
- }
996
- /**
997
- * Submit QR hardware wallet signature.
998
- *
999
- * @param requestId - The request ID.
1000
- * @param ethSignature - The signature to submit.
1001
- * @returns Promise resolving when the operation completes.
1002
- * @deprecated Use `withKeyring` instead.
1003
- */
1004
- async submitQRSignature(requestId, ethSignature) {
1005
- (await this.getOrAddQRKeyring()).submitSignature(requestId, ethSignature);
1006
- }
1007
- /**
1008
- * Cancel QR sign request.
1009
- *
1010
- * @returns Promise resolving when the operation completes.
1011
- * @deprecated Use `withKeyring` instead.
1012
- */
1013
- async cancelQRSignRequest() {
1014
- (await this.getOrAddQRKeyring()).cancelSignRequest();
1015
- }
1016
- /**
1017
- * Cancels qr keyring sync.
1018
- *
1019
- * @returns Promise resolving when the operation completes.
1020
- * @deprecated Use `withKeyring` instead.
1021
- */
1022
- async cancelQRSynchronization() {
1023
- // eslint-disable-next-line n/no-sync
1024
- (await this.getOrAddQRKeyring()).cancelSync();
1025
- }
1026
- /**
1027
- * Connect to QR hardware wallet.
1028
- *
1029
- * @param page - The page to connect to.
1030
- * @returns Promise resolving to the connected accounts.
1031
- * @deprecated Use of this method is discouraged as it creates a dangling promise
1032
- * internal to the `QRKeyring`, which can lead to unpredictable deadlocks. Please use
1033
- * `withKeyring` instead.
1034
- */
1035
- async connectQRHardware(page) {
1036
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
1037
- try {
1038
- const keyring = this.getQRKeyring() || (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_addQRKeyring).call(this));
1039
- let accounts;
1040
- switch (page) {
1041
- case -1:
1042
- accounts = await keyring.getPreviousPage();
1043
- break;
1044
- case 1:
1045
- accounts = await keyring.getNextPage();
1046
- break;
1047
- default:
1048
- accounts = await keyring.getFirstPage();
1049
- }
1050
- // TODO: Replace `any` with type
1051
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1052
- return accounts.map((account) => {
1053
- return {
1054
- ...account,
1055
- balance: '0x0',
1056
- };
1057
- });
1058
- }
1059
- catch (e) {
1060
- // TODO: Add test case for when keyring throws
1061
- /* istanbul ignore next */
1062
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
1063
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
1064
- throw new Error(`Unspecified error when connect QR Hardware, ${e}`);
1065
- }
1066
- });
1067
- }
1068
- /**
1069
- * Unlock a QR hardware wallet account.
1070
- *
1071
- * @param index - The index of the account to unlock.
1072
- * @returns Promise resolving when the operation completes.
1073
- * @deprecated Use `withKeyring` instead.
1074
- */
1075
- async unlockQRHardwareWalletAccount(index) {
1076
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
1077
- const keyring = this.getQRKeyring() || (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_addQRKeyring).call(this));
1078
- keyring.setAccountToUnlock(index);
1079
- await keyring.addAccounts(1);
1080
- });
1081
- }
1082
- async getAccountKeyringType(account) {
1083
- const keyring = (await this.getKeyringForAccount(account));
1084
- return keyring.type;
1085
- }
1086
- /**
1087
- * Forget the QR hardware wallet.
1088
- *
1089
- * @returns Promise resolving to the removed accounts and the remaining accounts.
1090
- * @deprecated Use `withKeyring` instead.
1091
- */
1092
- async forgetQRDevice() {
1093
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
1094
- const keyring = this.getQRKeyring();
1095
- if (!keyring) {
1096
- return { removedAccounts: [], remainingAccounts: [] };
1097
- }
1098
- const allAccounts = (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getAccountsFromKeyrings).call(this));
1099
- keyring.forgetDevice();
1100
- const remainingAccounts = (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getAccountsFromKeyrings).call(this));
1101
- const removedAccounts = allAccounts.filter((address) => !remainingAccounts.includes(address));
1102
- return { removedAccounts, remainingAccounts };
1103
- });
1104
- }
1105
- }
1106
- exports.KeyringController = KeyringController;
1107
- _KeyringController_controllerOperationMutex = new WeakMap(), _KeyringController_vaultOperationMutex = new WeakMap(), _KeyringController_keyringBuilders = new WeakMap(), _KeyringController_keyrings = new WeakMap(), _KeyringController_unsupportedKeyrings = new WeakMap(), _KeyringController_password = new WeakMap(), _KeyringController_encryptor = new WeakMap(), _KeyringController_cacheEncryptionKey = new WeakMap(), _KeyringController_qrKeyringStateListener = new WeakMap(), _KeyringController_instances = new WeakSet(), _KeyringController_registerMessageHandlers = function _KeyringController_registerMessageHandlers() {
1108
- this.messagingSystem.registerActionHandler(`${name}:signMessage`, this.signMessage.bind(this));
1109
- this.messagingSystem.registerActionHandler(`${name}:signPersonalMessage`, this.signPersonalMessage.bind(this));
1110
- this.messagingSystem.registerActionHandler(`${name}:signTypedMessage`, this.signTypedMessage.bind(this));
1111
- this.messagingSystem.registerActionHandler(`${name}:decryptMessage`, this.decryptMessage.bind(this));
1112
- this.messagingSystem.registerActionHandler(`${name}:getEncryptionPublicKey`, this.getEncryptionPublicKey.bind(this));
1113
- this.messagingSystem.registerActionHandler(`${name}:getAccounts`, this.getAccounts.bind(this));
1114
- this.messagingSystem.registerActionHandler(`${name}:getKeyringsByType`, this.getKeyringsByType.bind(this));
1115
- this.messagingSystem.registerActionHandler(`${name}:getKeyringForAccount`, this.getKeyringForAccount.bind(this));
1116
- this.messagingSystem.registerActionHandler(`${name}:persistAllKeyrings`, this.persistAllKeyrings.bind(this));
1117
- this.messagingSystem.registerActionHandler(`${name}:prepareUserOperation`, this.prepareUserOperation.bind(this));
1118
- this.messagingSystem.registerActionHandler(`${name}:patchUserOperation`, this.patchUserOperation.bind(this));
1119
- this.messagingSystem.registerActionHandler(`${name}:signUserOperation`, this.signUserOperation.bind(this));
1120
- this.messagingSystem.registerActionHandler(`${name}:addNewAccount`, this.addNewAccount.bind(this));
1121
- }, _KeyringController_getKeyringBuilderForType = function _KeyringController_getKeyringBuilderForType(type) {
1122
- return __classPrivateFieldGet(this, _KeyringController_keyringBuilders, "f").find((keyringBuilder) => keyringBuilder.type === type);
1123
- }, _KeyringController_addQRKeyring =
1124
- /**
1125
- * Add qr hardware keyring.
1126
- *
1127
- * @returns The added keyring
1128
- * @throws If a QRKeyring builder is not provided
1129
- * when initializing the controller
1130
- */
1131
- async function _KeyringController_addQRKeyring() {
1132
- __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1133
- // QRKeyring is not yet compatible with Keyring type from @metamask/utils
1134
- return (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, KeyringTypes.qr));
1135
- }, _KeyringController_subscribeToQRKeyringEvents = function _KeyringController_subscribeToQRKeyringEvents(qrKeyring) {
1136
- __classPrivateFieldSet(this, _KeyringController_qrKeyringStateListener, (state) => {
1137
- this.messagingSystem.publish(`${name}:qrKeyringStateChange`, state);
1138
- }, "f");
1139
- qrKeyring.getMemStore().subscribe(__classPrivateFieldGet(this, _KeyringController_qrKeyringStateListener, "f"));
1140
- }, _KeyringController_unsubscribeFromQRKeyringsEvents = function _KeyringController_unsubscribeFromQRKeyringsEvents() {
1141
- const qrKeyrings = this.getKeyringsByType(KeyringTypes.qr);
1142
- qrKeyrings.forEach((qrKeyring) => {
1143
- if (__classPrivateFieldGet(this, _KeyringController_qrKeyringStateListener, "f")) {
1144
- qrKeyring.getMemStore().unsubscribe(__classPrivateFieldGet(this, _KeyringController_qrKeyringStateListener, "f"));
1145
- }
1146
- });
1147
- }, _KeyringController_createNewVaultWithKeyring =
1148
- /**
1149
- * Create new vault with an initial keyring
1150
- *
1151
- * Destroys any old encrypted storage,
1152
- * creates a new encrypted store with the given password,
1153
- * creates a new wallet with 1 account.
1154
- *
1155
- * @fires KeyringController:unlock
1156
- * @param password - The password to encrypt the vault with.
1157
- * @param keyring - A object containing the params to instantiate a new keyring.
1158
- * @param keyring.type - The keyring type.
1159
- * @param keyring.opts - Optional parameters required to instantiate the keyring.
1160
- * @returns A promise that resolves to the state.
1161
- */
1162
- async function _KeyringController_createNewVaultWithKeyring(password, keyring) {
1163
- __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1164
- if (typeof password !== 'string') {
1165
- throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
1166
- }
1167
- this.update((state) => {
1168
- delete state.encryptionKey;
1169
- delete state.encryptionSalt;
1170
- });
1171
- __classPrivateFieldSet(this, _KeyringController_password, password, "f");
1172
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
1173
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyringWithFirstAccount).call(this, keyring.type, keyring.opts);
1174
- __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
1175
- }, _KeyringController_getUpdatedKeyrings =
1176
- /**
1177
- * Get the updated array of each keyring's type and
1178
- * accounts list.
1179
- *
1180
- * @returns A promise resolving to the updated keyrings array.
1181
- */
1182
- async function _KeyringController_getUpdatedKeyrings() {
1183
- return Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(displayForKeyring));
1184
- }, _KeyringController_getSerializedKeyrings =
1185
- /**
1186
- * Serialize the current array of keyring instances,
1187
- * including unsupported keyrings by default.
1188
- *
1189
- * @param options - Method options.
1190
- * @param options.includeUnsupported - Whether to include unsupported keyrings.
1191
- * @returns The serialized keyrings.
1192
- */
1193
- async function _KeyringController_getSerializedKeyrings({ includeUnsupported } = {
1194
- includeUnsupported: true,
1195
- }) {
1196
- const serializedKeyrings = await Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(async (keyring) => {
1197
- const [type, data] = await Promise.all([
1198
- keyring.type,
1199
- keyring.serialize(),
1200
- ]);
1201
- return { type, data };
1202
- }));
1203
- if (includeUnsupported) {
1204
- serializedKeyrings.push(...__classPrivateFieldGet(this, _KeyringController_unsupportedKeyrings, "f"));
1205
- }
1206
- return serializedKeyrings;
1207
- }, _KeyringController_restoreSerializedKeyrings =
1208
- /**
1209
- * Restore a serialized keyrings array.
1210
- *
1211
- * @param serializedKeyrings - The serialized keyrings array.
1212
- */
1213
- async function _KeyringController_restoreSerializedKeyrings(serializedKeyrings) {
1214
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
1215
- for (const serializedKeyring of serializedKeyrings) {
1216
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreKeyring).call(this, serializedKeyring);
1217
- }
1218
- }, _KeyringController_unlockKeyrings =
1219
- /**
1220
- * Unlock Keyrings, decrypting the vault and deserializing all
1221
- * keyrings contained in it, using a password or an encryption key with salt.
1222
- *
1223
- * @param password - The keyring controller password.
1224
- * @param encryptionKey - An exported key string to unlock keyrings with.
1225
- * @param encryptionSalt - The salt used to encrypt the vault.
1226
- * @returns A promise resolving to the deserialized keyrings array.
1227
- */
1228
- async function _KeyringController_unlockKeyrings(password, encryptionKey, encryptionSalt) {
1229
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async ({ releaseLock }) => {
1230
- const encryptedVault = this.state.vault;
1231
- if (!encryptedVault) {
1232
- throw new Error(constants_1.KeyringControllerError.VaultError);
1233
- }
1234
- let vault;
1235
- const updatedState = {};
1236
- if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
1237
- assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
1238
- if (password) {
1239
- const result = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithDetail(password, encryptedVault);
1240
- vault = result.vault;
1241
- __classPrivateFieldSet(this, _KeyringController_password, password, "f");
1242
- updatedState.encryptionKey = result.exportedKeyString;
1243
- updatedState.encryptionSalt = result.salt;
1244
- }
1245
- else {
1246
- const parsedEncryptedVault = JSON.parse(encryptedVault);
1247
- if (encryptionSalt !== parsedEncryptedVault.salt) {
1248
- throw new Error(constants_1.KeyringControllerError.ExpiredCredentials);
1249
- }
1250
- if (typeof encryptionKey !== 'string') {
1251
- throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
1252
- }
1253
- const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
1254
- vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(key, parsedEncryptedVault);
1255
- // This call is required on the first call because encryptionKey
1256
- // is not yet inside the memStore
1257
- updatedState.encryptionKey = encryptionKey;
1258
- // we can safely assume that encryptionSalt is defined here
1259
- // because we compare it with the salt from the vault
1260
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1261
- updatedState.encryptionSalt = encryptionSalt;
1262
- }
1263
- }
1264
- else {
1265
- if (typeof password !== 'string') {
1266
- throw new TypeError(constants_1.KeyringControllerError.WrongPasswordType);
1267
- }
1268
- vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, encryptedVault);
1269
- __classPrivateFieldSet(this, _KeyringController_password, password, "f");
1270
- }
1271
- if (!isSerializedKeyringsArray(vault)) {
1272
- throw new Error(constants_1.KeyringControllerError.VaultDataError);
1273
- }
1274
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreSerializedKeyrings).call(this, vault);
1275
- const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
1276
- this.update((state) => {
1277
- state.keyrings = updatedKeyrings;
1278
- if (updatedState.encryptionKey || updatedState.encryptionSalt) {
1279
- state.encryptionKey = updatedState.encryptionKey;
1280
- state.encryptionSalt = updatedState.encryptionSalt;
1281
- }
1282
- });
1283
- if (__classPrivateFieldGet(this, _KeyringController_password, "f") &&
1284
- (!__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f") || !encryptionKey) &&
1285
- __classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated &&
1286
- !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated(encryptedVault)) {
1287
- // The lock needs to be released before persisting the keyrings
1288
- // to avoid deadlock
1289
- releaseLock();
1290
- // Re-encrypt the vault with safer method if one is available
1291
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
1292
- }
1293
- return __classPrivateFieldGet(this, _KeyringController_keyrings, "f");
1294
- });
1295
- }, _KeyringController_updateVault = function _KeyringController_updateVault() {
1296
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
1297
- const { encryptionKey, encryptionSalt } = this.state;
1298
- if (!__classPrivateFieldGet(this, _KeyringController_password, "f") && !encryptionKey) {
1299
- throw new Error(constants_1.KeyringControllerError.MissingCredentials);
1300
- }
1301
- const serializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
1302
- if (!serializedKeyrings.some((keyring) => keyring.type === KeyringTypes.hd)) {
1303
- throw new Error(constants_1.KeyringControllerError.NoHdKeyring);
1304
- }
1305
- const updatedState = {};
1306
- if (__classPrivateFieldGet(this, _KeyringController_cacheEncryptionKey, "f")) {
1307
- assertIsExportableKeyEncryptor(__classPrivateFieldGet(this, _KeyringController_encryptor, "f"));
1308
- if (encryptionKey) {
1309
- const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
1310
- const vaultJSON = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithKey(key, serializedKeyrings);
1311
- vaultJSON.salt = encryptionSalt;
1312
- updatedState.vault = JSON.stringify(vaultJSON);
1313
- }
1314
- else if (__classPrivateFieldGet(this, _KeyringController_password, "f")) {
1315
- const { vault: newVault, exportedKeyString } = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithDetail(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
1316
- updatedState.vault = newVault;
1317
- updatedState.encryptionKey = exportedKeyString;
1318
- }
1319
- }
1320
- else {
1321
- assertIsValidPassword(__classPrivateFieldGet(this, _KeyringController_password, "f"));
1322
- updatedState.vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encrypt(__classPrivateFieldGet(this, _KeyringController_password, "f"), serializedKeyrings);
1323
- }
1324
- if (!updatedState.vault) {
1325
- throw new Error(constants_1.KeyringControllerError.MissingVaultData);
1326
- }
1327
- const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
1328
- this.update((state) => {
1329
- state.vault = updatedState.vault;
1330
- state.keyrings = updatedKeyrings;
1331
- if (updatedState.encryptionKey) {
1332
- state.encryptionKey = updatedState.encryptionKey;
1333
- state.encryptionSalt = JSON.parse(updatedState.vault).salt;
1334
- }
1335
- });
1336
- return true;
1337
- });
1338
- }, _KeyringController_getAccountsFromKeyrings =
1339
- /**
1340
- * Retrieves all the accounts from keyrings instances
1341
- * that are currently in memory.
1342
- *
1343
- * @returns A promise resolving to an array of accounts.
1344
- */
1345
- async function _KeyringController_getAccountsFromKeyrings() {
1346
- const keyrings = __classPrivateFieldGet(this, _KeyringController_keyrings, "f");
1347
- const keyringArrays = await Promise.all(keyrings.map(async (keyring) => keyring.getAccounts()));
1348
- const addresses = keyringArrays.reduce((res, arr) => {
1349
- return res.concat(arr);
1350
- }, []);
1351
- // Cast to `string[]` here is safe here because `addresses` has no nullish
1352
- // values, and `normalize` returns `string` unless given a nullish value
1353
- return addresses.map(normalize);
1354
- }, _KeyringController_createKeyringWithFirstAccount =
1355
- /**
1356
- * Create a new keyring, ensuring that the first account is
1357
- * also created.
1358
- *
1359
- * @param type - Keyring type to instantiate.
1360
- * @param opts - Optional parameters required to instantiate the keyring.
1361
- * @returns A promise that resolves if the operation is successful.
1362
- */
1363
- async function _KeyringController_createKeyringWithFirstAccount(type, opts) {
1364
- __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1365
- const keyring = (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, opts));
1366
- const [firstAccount] = await keyring.getAccounts();
1367
- if (!firstAccount) {
1368
- throw new Error(constants_1.KeyringControllerError.NoFirstAccount);
1369
- }
1370
- }, _KeyringController_newKeyring =
1371
- /**
1372
- * Instantiate, initialize and return a new keyring of the given `type`,
1373
- * using the given `opts`. The keyring is built using the keyring builder
1374
- * registered for the given `type`.
1375
- *
1376
- *
1377
- * @param type - The type of keyring to add.
1378
- * @param data - The data to restore a previously serialized keyring.
1379
- * @returns The new keyring.
1380
- * @throws If the keyring includes duplicated accounts.
1381
- */
1382
- async function _KeyringController_newKeyring(type, data) {
1383
- __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1384
- const keyringBuilder = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringBuilderForType).call(this, type);
1385
- if (!keyringBuilder) {
1386
- throw new Error(`${constants_1.KeyringControllerError.NoKeyringBuilder}. Keyring type: ${type}`);
1387
- }
1388
- const keyring = keyringBuilder();
1389
- // @ts-expect-error Enforce data type after updating clients
1390
- await keyring.deserialize(data);
1391
- if (keyring.init) {
1392
- await keyring.init();
1393
- }
1394
- if (type === KeyringTypes.hd && (!(0, utils_1.isObject)(data) || !data.mnemonic)) {
1395
- if (!keyring.generateRandomMnemonic) {
1396
- throw new Error(constants_1.KeyringControllerError.UnsupportedGenerateRandomMnemonic);
1397
- }
1398
- keyring.generateRandomMnemonic();
1399
- await keyring.addAccounts(1);
1400
- }
1401
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_checkForDuplicate).call(this, type, await keyring.getAccounts());
1402
- if (type === KeyringTypes.qr) {
1403
- // In case of a QR keyring type, we need to subscribe
1404
- // to its events after creating it
1405
- __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_subscribeToQRKeyringEvents).call(this, keyring);
1406
- }
1407
- __classPrivateFieldGet(this, _KeyringController_keyrings, "f").push(keyring);
1408
- return keyring;
1409
- }, _KeyringController_clearKeyrings =
1410
- /**
1411
- * Remove all managed keyrings, destroying all their
1412
- * instances in memory.
1413
- */
1414
- async function _KeyringController_clearKeyrings() {
1415
- __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1416
- for (const keyring of __classPrivateFieldGet(this, _KeyringController_keyrings, "f")) {
1417
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_destroyKeyring).call(this, keyring);
1418
- }
1419
- __classPrivateFieldSet(this, _KeyringController_keyrings, [], "f");
1420
- }, _KeyringController_restoreKeyring =
1421
- /**
1422
- * Restore a Keyring from a provided serialized payload.
1423
- * On success, returns the resulting keyring instance.
1424
- *
1425
- * @param serialized - The serialized keyring.
1426
- * @returns The deserialized keyring or undefined if the keyring type is unsupported.
1427
- */
1428
- async function _KeyringController_restoreKeyring(serialized) {
1429
- __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1430
- try {
1431
- const { type, data } = serialized;
1432
- return await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, data);
1433
- }
1434
- catch (_) {
1435
- __classPrivateFieldGet(this, _KeyringController_unsupportedKeyrings, "f").push(serialized);
1436
- return undefined;
1437
- }
1438
- }, _KeyringController_destroyKeyring =
1439
- /**
1440
- * Destroy Keyring
1441
- *
1442
- * Some keyrings support a method called `destroy`, that destroys the
1443
- * keyring along with removing all its event listeners and, in some cases,
1444
- * clears the keyring bridge iframe from the DOM.
1445
- *
1446
- * @param keyring - The keyring to destroy.
1447
- */
1448
- async function _KeyringController_destroyKeyring(keyring) {
1449
- await keyring.destroy?.();
1450
- }, _KeyringController_removeEmptyKeyrings =
1451
- /**
1452
- * Remove empty keyrings.
1453
- *
1454
- * Loops through the keyrings and removes the ones with empty accounts
1455
- * (usually after removing the last / only account) from a keyring.
1456
- */
1457
- async function _KeyringController_removeEmptyKeyrings() {
1458
- __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1459
- const validKeyrings = [];
1460
- // Since getAccounts returns a Promise
1461
- // We need to wait to hear back form each keyring
1462
- // in order to decide which ones are now valid (accounts.length > 0)
1463
- await Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(async (keyring) => {
1464
- const accounts = await keyring.getAccounts();
1465
- if (accounts.length > 0) {
1466
- validKeyrings.push(keyring);
1467
- }
1468
- else {
1469
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_destroyKeyring).call(this, keyring);
1470
- }
1471
- }));
1472
- __classPrivateFieldSet(this, _KeyringController_keyrings, validKeyrings, "f");
1473
- }, _KeyringController_checkForDuplicate =
1474
- /**
1475
- * Checks for duplicate keypairs, using the the first account in the given
1476
- * array. Rejects if a duplicate is found.
1477
- *
1478
- * Only supports 'Simple Key Pair'.
1479
- *
1480
- * @param type - The key pair type to check for.
1481
- * @param newAccountArray - Array of new accounts.
1482
- * @returns The account, if no duplicate is found.
1483
- */
1484
- async function _KeyringController_checkForDuplicate(type, newAccountArray) {
1485
- const accounts = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getAccountsFromKeyrings).call(this);
1486
- switch (type) {
1487
- case KeyringTypes.simple: {
1488
- const isIncluded = Boolean(accounts.find((key) => newAccountArray[0] &&
1489
- (key === newAccountArray[0] ||
1490
- key === (0, utils_1.remove0x)(newAccountArray[0]))));
1491
- if (isIncluded) {
1492
- throw new Error(constants_1.KeyringControllerError.DuplicatedAccount);
1493
- }
1494
- return newAccountArray;
1495
- }
1496
- default: {
1497
- return newAccountArray;
1498
- }
1499
- }
1500
- }, _KeyringController_setUnlocked = function _KeyringController_setUnlocked() {
1501
- __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1502
- this.update((state) => {
1503
- state.isUnlocked = true;
1504
- });
1505
- this.messagingSystem.publish(`${name}:unlock`);
1506
- }, _KeyringController_persistOrRollback =
1507
- /**
1508
- * Execute the given function after acquiring the controller lock
1509
- * and save the keyrings to state after it, or rollback to their
1510
- * previous state in case of error.
1511
- *
1512
- * @param fn - The function to execute.
1513
- * @returns The result of the function.
1514
- */
1515
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
1516
- // eslint-disable-next-line @typescript-eslint/naming-convention
1517
- async function _KeyringController_persistOrRollback(fn) {
1518
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async ({ releaseLock }) => {
1519
- const callbackResult = await fn({ releaseLock });
1520
- // State is committed only if the operation is successful
1521
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
1522
- return callbackResult;
1523
- });
1524
- }, _KeyringController_withRollback =
1525
- /**
1526
- * Execute the given function after acquiring the controller lock
1527
- * and rollback keyrings and password states in case of error.
1528
- *
1529
- * @param fn - The function to execute atomically.
1530
- * @returns The result of the function.
1531
- */
1532
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
1533
- // eslint-disable-next-line @typescript-eslint/naming-convention
1534
- async function _KeyringController_withRollback(fn) {
1535
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async ({ releaseLock }) => {
1536
- const currentSerializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
1537
- const currentPassword = __classPrivateFieldGet(this, _KeyringController_password, "f");
1538
- try {
1539
- return await fn({ releaseLock });
1540
- }
1541
- catch (e) {
1542
- // Keyrings and password are restored to their previous state
1543
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreSerializedKeyrings).call(this, currentSerializedKeyrings);
1544
- __classPrivateFieldSet(this, _KeyringController_password, currentPassword, "f");
1545
- throw e;
1546
- }
1547
- });
1548
- }, _KeyringController_assertControllerMutexIsLocked = function _KeyringController_assertControllerMutexIsLocked() {
1549
- if (!__classPrivateFieldGet(this, _KeyringController_controllerOperationMutex, "f").isLocked()) {
1550
- throw new Error(constants_1.KeyringControllerError.ControllerLockRequired);
1551
- }
1552
- }, _KeyringController_withControllerLock =
1553
- /**
1554
- * Lock the controller mutex before executing the given function,
1555
- * and release it after the function is resolved or after an
1556
- * error is thrown.
1557
- *
1558
- * This wrapper ensures that each mutable operation that interacts with the
1559
- * controller and that changes its state is executed in a mutually exclusive way,
1560
- * preventing unsafe concurrent access that could lead to unpredictable behavior.
1561
- *
1562
- * @param fn - The function to execute while the controller mutex is locked.
1563
- * @returns The result of the function.
1564
- */
1565
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
1566
- // eslint-disable-next-line @typescript-eslint/naming-convention
1567
- async function _KeyringController_withControllerLock(fn) {
1568
- return withLock(__classPrivateFieldGet(this, _KeyringController_controllerOperationMutex, "f"), fn);
1569
- }, _KeyringController_withVaultLock =
1570
- /**
1571
- * Lock the vault mutex before executing the given function,
1572
- * and release it after the function is resolved or after an
1573
- * error is thrown.
1574
- *
1575
- * This ensures that each operation that interacts with the vault
1576
- * is executed in a mutually exclusive way.
1577
- *
1578
- * @param fn - The function to execute while the vault mutex is locked.
1579
- * @returns The result of the function.
1580
- */
1581
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
1582
- // eslint-disable-next-line @typescript-eslint/naming-convention
1583
- async function _KeyringController_withVaultLock(fn) {
1584
- __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1585
- return withLock(__classPrivateFieldGet(this, _KeyringController_vaultOperationMutex, "f"), fn);
1586
- };
1587
- /**
1588
- * Lock the given mutex before executing the given function,
1589
- * and release it after the function is resolved or after an
1590
- * error is thrown.
1591
- *
1592
- * @param mutex - The mutex to lock.
1593
- * @param fn - The function to execute while the mutex is locked.
1594
- * @returns The result of the function.
1595
- */
1596
- // TODO: Either fix this lint violation or explain why it's necessary to ignore.
1597
- // eslint-disable-next-line @typescript-eslint/naming-convention
1598
- async function withLock(mutex, fn) {
1599
- const releaseLock = await mutex.acquire();
1600
- try {
1601
- return await fn({ releaseLock });
1602
- }
1603
- finally {
1604
- releaseLock();
1605
- }
1606
- }
1607
- exports.default = KeyringController;
1608
- //# sourceMappingURL=KeyringController.cjs.map