@metamask-previews/keyring-controller 27.1.1-preview-4f4c98e → 27.1.1-preview-eb263b0ee

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 (64) hide show
  1. package/CHANGELOG.md +0 -4
  2. package/dist/KeyringController-method-action-types.cjs +7 -0
  3. package/dist/KeyringController-method-action-types.cjs.map +1 -0
  4. package/dist/{KeyringController-method-action-types.d.ts → KeyringController-method-action-types.d.cts} +2 -2
  5. package/dist/KeyringController-method-action-types.d.cts.map +1 -0
  6. package/dist/KeyringController-method-action-types.d.mts +491 -0
  7. package/dist/KeyringController-method-action-types.d.mts.map +1 -0
  8. package/dist/{KeyringController-method-action-types.js → KeyringController-method-action-types.mjs} +1 -1
  9. package/dist/KeyringController-method-action-types.mjs.map +1 -0
  10. package/dist/KeyringController.cjs +2018 -0
  11. package/dist/KeyringController.cjs.map +1 -0
  12. package/dist/{KeyringController.d.ts → KeyringController.d.cts} +13 -13
  13. package/dist/KeyringController.d.cts.map +1 -0
  14. package/dist/KeyringController.d.mts +825 -0
  15. package/dist/KeyringController.d.mts.map +1 -0
  16. package/dist/{KeyringController.js → KeyringController.mjs} +24 -31
  17. package/dist/KeyringController.mjs.map +1 -0
  18. package/dist/constants.cjs +48 -0
  19. package/dist/constants.cjs.map +1 -0
  20. package/dist/{constants.d.ts → constants.d.cts} +1 -1
  21. package/dist/constants.d.cts.map +1 -0
  22. package/dist/constants.d.mts +44 -0
  23. package/dist/constants.d.mts.map +1 -0
  24. package/dist/{constants.js → constants.mjs} +1 -1
  25. package/dist/constants.mjs.map +1 -0
  26. package/dist/errors.cjs +114 -0
  27. package/dist/errors.cjs.map +1 -0
  28. package/dist/{errors.d.ts → errors.d.cts} +1 -1
  29. package/dist/errors.d.cts.map +1 -0
  30. package/dist/errors.d.mts +91 -0
  31. package/dist/errors.d.mts.map +1 -0
  32. package/dist/{errors.js → errors.mjs} +2 -2
  33. package/dist/errors.mjs.map +1 -0
  34. package/dist/index.cjs +22 -0
  35. package/dist/index.cjs.map +1 -0
  36. package/dist/{index.d.ts → index.d.cts} +6 -6
  37. package/dist/index.d.cts.map +1 -0
  38. package/dist/index.d.mts +6 -0
  39. package/dist/index.d.mts.map +1 -0
  40. package/dist/index.mjs +4 -0
  41. package/dist/index.mjs.map +1 -0
  42. package/dist/types.cjs +3 -0
  43. package/dist/types.cjs.map +1 -0
  44. package/dist/{types.d.ts → types.d.cts} +2 -2
  45. package/dist/types.d.cts.map +1 -0
  46. package/dist/types.d.mts +80 -0
  47. package/dist/types.d.mts.map +1 -0
  48. package/dist/types.mjs +2 -0
  49. package/dist/types.mjs.map +1 -0
  50. package/package.json +18 -13
  51. package/dist/KeyringController-method-action-types.d.ts.map +0 -1
  52. package/dist/KeyringController-method-action-types.js.map +0 -1
  53. package/dist/KeyringController.d.ts.map +0 -1
  54. package/dist/KeyringController.js.map +0 -1
  55. package/dist/constants.d.ts.map +0 -1
  56. package/dist/constants.js.map +0 -1
  57. package/dist/errors.d.ts.map +0 -1
  58. package/dist/errors.js.map +0 -1
  59. package/dist/index.d.ts.map +0 -1
  60. package/dist/index.js +0 -4
  61. package/dist/index.js.map +0 -1
  62. package/dist/types.d.ts.map +0 -1
  63. package/dist/types.js +0 -2
  64. package/dist/types.js.map +0 -1
@@ -0,0 +1,2018 @@
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_keyringV2Builders, _KeyringController_encryptor, _KeyringController_keyrings, _KeyringController_unsupportedKeyrings, _KeyringController_encryptionKey, _KeyringController_verifyEncryptionKey, _KeyringController_verifyCredentials, _KeyringController_getKeyringForAccount, _KeyringController_getKeyringEntryForAccount, _KeyringController_findKeyringIndexForAccount, _KeyringController_getKeyringEntriesByType, _KeyringController_assertNoUnsafeDirectKeyringAccess, _KeyringController_registerMessageHandlers, _KeyringController_selectKeyringEntry, _KeyringController_getKeyringById, _KeyringController_getKeyringEntryById, _KeyringController_getKeyringByIdOrDefault, _KeyringController_getKeyringMetadata, _KeyringController_getKeyringBuilderForType, _KeyringController_getKeyringV2BuilderForType, _KeyringController_createNewVaultWithKeyring, _KeyringController_deriveAndSetEncryptionKey, _KeyringController_setEncryptionKey, _KeyringController_verifySeedPhrase, _KeyringController_getUpdatedKeyrings, _KeyringController_getSerializedKeyrings, _KeyringController_getSessionState, _KeyringController_restoreSerializedKeyrings, _KeyringController_unlockKeyrings, _KeyringController_updateVault, _KeyringController_isNewEncryptionAvailable, _KeyringController_getAccountsFromKeyrings, _KeyringController_createKeyringWithFirstAccount, _KeyringController_newKeyring, _KeyringController_createKeyring, _KeyringController_cleanUpEmptiedKeyringsAfter, _KeyringController_clearKeyrings, _KeyringController_restoreKeyring, _KeyringController_destroyKeyring, _KeyringController_assertNoDuplicateAccounts, _KeyringController_setUnlocked, _KeyringController_assertIsUnlocked, _KeyringController_persistOrRollback, _KeyringController_withRollback, _KeyringController_assertControllerMutexIsLocked, _KeyringController_isPrimaryKeyring, _KeyringController_assertNotRemovingPrimaryKeyring, _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 eth_hd_keyring_1 = require("@metamask/eth-hd-keyring");
45
+ const v2_1 = require("@metamask/eth-hd-keyring/v2");
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 v2_2 = require("@metamask/eth-simple-keyring/v2");
49
+ const utils_1 = require("@metamask/utils");
50
+ const async_mutex_1 = require("async-mutex");
51
+ const ethereumjs_wallet_1 = __importStar(require("ethereumjs-wallet"));
52
+ const lodash_1 = require("lodash");
53
+ // When generating a ULID within the same millisecond, monotonicFactory provides some guarantees regarding sort order.
54
+ const ulid_1 = require("ulid");
55
+ const constants_js_1 = require("./constants.cjs");
56
+ const errors_js_1 = require("./errors.cjs");
57
+ const name = 'KeyringController';
58
+ const MESSENGER_EXPOSED_METHODS = [
59
+ 'signMessage',
60
+ 'signEip7702Authorization',
61
+ 'signPersonalMessage',
62
+ 'signTransaction',
63
+ 'signTypedMessage',
64
+ 'decryptMessage',
65
+ 'getEncryptionPublicKey',
66
+ 'getAccounts',
67
+ 'getKeyringsByType',
68
+ 'getKeyringForAccount',
69
+ 'persistAllKeyrings',
70
+ 'prepareUserOperation',
71
+ 'patchUserOperation',
72
+ 'signUserOperation',
73
+ 'addNewAccount',
74
+ 'withController',
75
+ 'withKeyring',
76
+ 'withKeyringUnsafe',
77
+ 'withKeyringV2',
78
+ 'withKeyringV2Unsafe',
79
+ 'addNewKeyring',
80
+ 'createNewVaultAndKeychain',
81
+ 'createNewVaultAndRestore',
82
+ 'removeAccount',
83
+ 'isUnlocked',
84
+ 'exportSeedPhrase',
85
+ 'changePassword',
86
+ 'exportAccount',
87
+ 'exportEncryptionKey',
88
+ 'getAccountKeyringType',
89
+ 'importAccountWithStrategy',
90
+ 'setLocked',
91
+ 'submitEncryptionKey',
92
+ 'submitPassword',
93
+ 'verifyPassword',
94
+ ];
95
+ /**
96
+ * Available keyring types
97
+ *
98
+ * @deprecated Use `KeyringType` from `@metamask/keyring-api/v2` instead. This enum will be removed
99
+ * in a future release once V2 is fully adopted. Only use it if the keyring you are trying to access
100
+ * has no V2 builder available yet.
101
+ */
102
+ var KeyringTypes;
103
+ (function (KeyringTypes) {
104
+ // Changing this would be a breaking change, and not worth the effort at this
105
+ // time, so we disable the linting rule for this block.
106
+ /* eslint-disable @typescript-eslint/naming-convention */
107
+ KeyringTypes["simple"] = "Simple Key Pair";
108
+ KeyringTypes["hd"] = "HD Key Tree";
109
+ KeyringTypes["qr"] = "QR Hardware Wallet Device";
110
+ KeyringTypes["trezor"] = "Trezor Hardware";
111
+ KeyringTypes["oneKey"] = "OneKey Hardware";
112
+ KeyringTypes["ledger"] = "Ledger Hardware";
113
+ KeyringTypes["lattice"] = "Lattice Hardware";
114
+ KeyringTypes["snap"] = "Snap Keyring";
115
+ KeyringTypes["money"] = "Money Keyring";
116
+ /* eslint-enable @typescript-eslint/naming-convention */
117
+ })(KeyringTypes || (exports.KeyringTypes = KeyringTypes = {}));
118
+ /**
119
+ * Custody keyring types are a special case, as they are not a single type
120
+ * but they all start with the prefix "Custody".
121
+ *
122
+ * @param keyringType - The type of the keyring.
123
+ * @returns Whether the keyring type is a custody keyring.
124
+ */
125
+ const isCustodyKeyring = (keyringType) => {
126
+ return keyringType.startsWith('Custody');
127
+ };
128
+ exports.isCustodyKeyring = isCustodyKeyring;
129
+ /**
130
+ * A strategy for importing an account
131
+ */
132
+ var AccountImportStrategy;
133
+ (function (AccountImportStrategy) {
134
+ // Changing this would be a breaking change, and not worth the effort at this
135
+ // time, so we disable the linting rule for this block.
136
+ /* eslint-disable @typescript-eslint/naming-convention */
137
+ AccountImportStrategy["privateKey"] = "privateKey";
138
+ AccountImportStrategy["json"] = "json";
139
+ /* eslint-enable @typescript-eslint/naming-convention */
140
+ })(AccountImportStrategy || (exports.AccountImportStrategy = AccountImportStrategy = {}));
141
+ /**
142
+ * The `signTypedMessage` version
143
+ *
144
+ * @see https://docs.metamask.io/guide/signing-data.html
145
+ */
146
+ var SignTypedDataVersion;
147
+ (function (SignTypedDataVersion) {
148
+ SignTypedDataVersion["V1"] = "V1";
149
+ SignTypedDataVersion["V3"] = "V3";
150
+ SignTypedDataVersion["V4"] = "V4";
151
+ })(SignTypedDataVersion || (exports.SignTypedDataVersion = SignTypedDataVersion = {}));
152
+ /**
153
+ * Get builder function for `Keyring`
154
+ *
155
+ * Returns a builder function for `Keyring` with a `type` property.
156
+ *
157
+ * @param KeyringConstructor - The Keyring class for the builder.
158
+ * @returns A builder function for the given Keyring.
159
+ */
160
+ function keyringBuilderFactory(KeyringConstructor) {
161
+ const builder = () => new KeyringConstructor();
162
+ builder.type = KeyringConstructor.type;
163
+ return builder;
164
+ }
165
+ exports.keyringBuilderFactory = keyringBuilderFactory;
166
+ const defaultKeyringBuilders = [
167
+ // todo: keyring types are mismatched, this should be fixed in they keyrings themselves
168
+ // @ts-expect-error keyring types are mismatched
169
+ keyringBuilderFactory(eth_simple_keyring_1.default),
170
+ keyringBuilderFactory(eth_hd_keyring_1.HdKeyring),
171
+ ];
172
+ const hdKeyringV2Builder = Object.assign((keyring, metadata) => new v2_1.HdKeyring({
173
+ legacyKeyring: keyring,
174
+ entropySource: metadata.id,
175
+ }), { type: KeyringTypes.hd });
176
+ const simpleKeyringV2Builder = Object.assign((keyring) => new v2_2.SimpleKeyring({
177
+ legacyKeyring: keyring,
178
+ }), { type: KeyringTypes.simple });
179
+ const defaultKeyringV2Builders = [
180
+ simpleKeyringV2Builder,
181
+ hdKeyringV2Builder,
182
+ ];
183
+ const getDefaultKeyringState = () => {
184
+ return {
185
+ isUnlocked: false,
186
+ keyrings: [],
187
+ };
188
+ };
189
+ exports.getDefaultKeyringState = getDefaultKeyringState;
190
+ /**
191
+ * Assert that the given keyring has an exportable
192
+ * mnemonic.
193
+ *
194
+ * @param keyring - The keyring to check
195
+ * @throws When the keyring does not have a mnemonic
196
+ */
197
+ function assertHasUint8ArrayMnemonic(keyring) {
198
+ if (!((0, utils_1.hasProperty)(keyring, 'mnemonic') && keyring.mnemonic instanceof Uint8Array)) {
199
+ throw new errors_js_1.KeyringControllerError("Can't get mnemonic bytes from keyring");
200
+ }
201
+ }
202
+ /**
203
+ * Assert that the provided password is a valid non-empty string.
204
+ *
205
+ * @param password - The password to check.
206
+ * @throws If the password is not a valid string.
207
+ */
208
+ function assertIsValidPassword(password) {
209
+ if (typeof password !== 'string') {
210
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.WrongPasswordType);
211
+ }
212
+ if (!password?.length) {
213
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.InvalidEmptyPassword);
214
+ }
215
+ }
216
+ /**
217
+ * Assert that the provided encryption key is a valid non-empty string.
218
+ *
219
+ * @param encryptionKey - The encryption key to check.
220
+ * @throws If the encryption key is not a valid string.
221
+ */
222
+ function assertIsEncryptionKeySet(encryptionKey) {
223
+ if (!encryptionKey) {
224
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.EncryptionKeyNotSet);
225
+ }
226
+ }
227
+ /**
228
+ * Checks if the provided value is a serialized keyrings array.
229
+ *
230
+ * @param array - The value to check.
231
+ * @returns True if the value is a serialized keyrings array.
232
+ */
233
+ function isSerializedKeyringsArray(array) {
234
+ return (typeof array === 'object' &&
235
+ Array.isArray(array) &&
236
+ array.every((value) => value.type && (0, utils_1.isValidJson)(value.data)));
237
+ }
238
+ /**
239
+ * Display For Keyring
240
+ *
241
+ * Is used for adding the current keyrings to the state object.
242
+ *
243
+ * @param keyringWithMetadata - The keyring and its metadata.
244
+ * @param keyringWithMetadata.keyring - The keyring to display.
245
+ * @param keyringWithMetadata.metadata - The metadata of the keyring.
246
+ * @returns A keyring display object, with type and accounts properties.
247
+ */
248
+ async function displayForKeyring({ keyring, metadata, }) {
249
+ const accounts = await keyring.getAccounts();
250
+ return {
251
+ type: keyring.type,
252
+ // Cast to `string[]` here is safe here because `accounts` has no nullish
253
+ // values, and `normalize` returns `string` unless given a nullish value
254
+ accounts: accounts.map(normalize),
255
+ metadata,
256
+ };
257
+ }
258
+ /**
259
+ * Check if address is an ethereum address
260
+ *
261
+ * @param address - An address.
262
+ * @returns Returns true if the address is an ethereum one, false otherwise.
263
+ */
264
+ function isEthAddress(address) {
265
+ // We first check if it's a matching `Hex` string, so that is narrows down
266
+ // `address` as an `Hex` type, allowing us to use `isValidHexAddress`
267
+ return (
268
+ // NOTE: This function only checks for lowercased strings
269
+ (0, utils_1.isStrictHexString)(address.toLowerCase()) &&
270
+ // This checks for lowercased addresses and checksum addresses too
271
+ (0, utils_1.isValidHexAddress)(address));
272
+ }
273
+ /**
274
+ * Normalize ethereum or non-EVM address.
275
+ *
276
+ * @param address - Ethereum or non-EVM address.
277
+ * @returns The normalized address.
278
+ */
279
+ function normalize(address) {
280
+ // Since the `KeyringController` is only dealing with address, we have
281
+ // no other way to get the associated account type with this address. So we
282
+ // are down to check the actual address format for now
283
+ // TODO: Find a better way to not have those runtime checks based on the
284
+ // address value!
285
+ return isEthAddress(address) ? (0, eth_sig_util_1.normalize)(address) : address;
286
+ }
287
+ /**
288
+ * Controller responsible for establishing and managing user identity.
289
+ *
290
+ * This class is a wrapper around the `eth-keyring-controller` package. The
291
+ * `eth-keyring-controller` manages the "vault", which is an encrypted store of private keys, and
292
+ * it manages the wallet "lock" state. This wrapper class has convenience methods for interacting
293
+ * with the internal keyring controller and handling certain complex operations that involve the
294
+ * keyrings.
295
+ */
296
+ class KeyringController extends base_controller_1.BaseController {
297
+ /**
298
+ * Creates a KeyringController instance.
299
+ *
300
+ * @param options - Initial options used to configure this controller
301
+ * @param options.encryptor - An optional object for defining encryption schemes.
302
+ * @param options.keyringBuilders - Set a new name for account.
303
+ * @param options.cacheEncryptionKey - Whether to cache or not encryption key.
304
+ * @param options.messenger - A restricted messenger.
305
+ * @param options.state - Initial state to set on this controller.
306
+ */
307
+ constructor(options) {
308
+ const { encryptor, keyringBuilders, keyringV2Builders, messenger, state } = options;
309
+ super({
310
+ name,
311
+ metadata: {
312
+ vault: {
313
+ includeInStateLogs: false,
314
+ persist: true,
315
+ includeInDebugSnapshot: false,
316
+ usedInUi: false,
317
+ },
318
+ isUnlocked: {
319
+ includeInStateLogs: true,
320
+ persist: false,
321
+ includeInDebugSnapshot: true,
322
+ usedInUi: true,
323
+ },
324
+ keyrings: {
325
+ includeInStateLogs: true,
326
+ persist: false,
327
+ includeInDebugSnapshot: false,
328
+ usedInUi: true,
329
+ },
330
+ encryptionKey: {
331
+ includeInStateLogs: false,
332
+ persist: false,
333
+ includeInDebugSnapshot: false,
334
+ usedInUi: false,
335
+ },
336
+ encryptionSalt: {
337
+ includeInStateLogs: false,
338
+ persist: false,
339
+ includeInDebugSnapshot: false,
340
+ usedInUi: false,
341
+ },
342
+ },
343
+ messenger,
344
+ state: {
345
+ ...(0, exports.getDefaultKeyringState)(),
346
+ ...state,
347
+ },
348
+ });
349
+ _KeyringController_instances.add(this);
350
+ _KeyringController_controllerOperationMutex.set(this, new async_mutex_1.Mutex());
351
+ _KeyringController_vaultOperationMutex.set(this, new async_mutex_1.Mutex());
352
+ _KeyringController_keyringBuilders.set(this, void 0);
353
+ _KeyringController_keyringV2Builders.set(this, void 0);
354
+ _KeyringController_encryptor.set(this, void 0);
355
+ _KeyringController_keyrings.set(this, void 0);
356
+ _KeyringController_unsupportedKeyrings.set(this, void 0);
357
+ _KeyringController_encryptionKey.set(this, void 0);
358
+ __classPrivateFieldSet(this, _KeyringController_keyringBuilders, keyringBuilders
359
+ ? keyringBuilders.concat(defaultKeyringBuilders)
360
+ : defaultKeyringBuilders, "f");
361
+ __classPrivateFieldSet(this, _KeyringController_keyringV2Builders, keyringV2Builders
362
+ ? keyringV2Builders.concat(defaultKeyringV2Builders)
363
+ : defaultKeyringV2Builders, "f");
364
+ __classPrivateFieldSet(this, _KeyringController_encryptor, encryptor, "f");
365
+ __classPrivateFieldSet(this, _KeyringController_keyrings, [], "f");
366
+ __classPrivateFieldSet(this, _KeyringController_unsupportedKeyrings, [], "f");
367
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_registerMessageHandlers).call(this);
368
+ }
369
+ /**
370
+ * Adds a new account to the default (first) HD seed phrase keyring.
371
+ *
372
+ * @param accountCount - Number of accounts before adding a new one, used to
373
+ * make the method idempotent.
374
+ * @returns Promise resolving to the added account address.
375
+ */
376
+ async addNewAccount(accountCount) {
377
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
378
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
379
+ const primaryKeyring = this.getKeyringsByType('HD Key Tree')[0];
380
+ if (!primaryKeyring) {
381
+ throw new errors_js_1.KeyringControllerError('No HD keyring found');
382
+ }
383
+ const oldAccounts = await primaryKeyring.getAccounts();
384
+ if (accountCount && oldAccounts.length !== accountCount) {
385
+ if (accountCount > oldAccounts.length) {
386
+ throw new errors_js_1.KeyringControllerError('Account out of sequence');
387
+ }
388
+ // we return the account already existing at index `accountCount`
389
+ const existingAccount = oldAccounts[accountCount];
390
+ if (!existingAccount) {
391
+ throw new errors_js_1.KeyringControllerError(`Can't find account at index ${accountCount}`);
392
+ }
393
+ return existingAccount;
394
+ }
395
+ const [addedAccountAddress] = await primaryKeyring.addAccounts(1);
396
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_verifySeedPhrase).call(this);
397
+ return addedAccountAddress;
398
+ });
399
+ }
400
+ /**
401
+ * Adds a new account to the specified keyring.
402
+ *
403
+ * @param keyring - Keyring to add the account to.
404
+ * @param accountCount - Number of accounts before adding a new one, used to make the method idempotent.
405
+ * @returns Promise resolving to the added account address
406
+ */
407
+ async addNewAccountForKeyring(keyring, accountCount) {
408
+ // READ THIS CAREFULLY:
409
+ // We still uses `Hex` here, since we are not using this method when creating
410
+ // and account using a "Snap Keyring". This function assume the `keyring` is
411
+ // ethereum compatible, but "Snap Keyring" might not be.
412
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
413
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
414
+ const oldAccounts = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getAccountsFromKeyrings).call(this);
415
+ if (accountCount && oldAccounts.length !== accountCount) {
416
+ if (accountCount > oldAccounts.length) {
417
+ throw new errors_js_1.KeyringControllerError('Account out of sequence');
418
+ }
419
+ const existingAccount = oldAccounts[accountCount];
420
+ (0, utils_1.assertIsStrictHexString)(existingAccount);
421
+ return existingAccount;
422
+ }
423
+ await keyring.addAccounts(1);
424
+ const addedAccountAddress = (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getAccountsFromKeyrings).call(this)).find((selectedAddress) => !oldAccounts.includes(selectedAddress));
425
+ (0, utils_1.assertIsStrictHexString)(addedAccountAddress);
426
+ return addedAccountAddress;
427
+ });
428
+ }
429
+ /**
430
+ * Effectively the same as creating a new keychain then populating it
431
+ * using the given seed phrase.
432
+ *
433
+ * @param password - Password to unlock keychain.
434
+ * @param seed - A BIP39-compliant seed phrase as Uint8Array,
435
+ * either as a string or an array of UTF-8 bytes that represent the string.
436
+ * @returns Promise resolving when the operation ends successfully.
437
+ */
438
+ async createNewVaultAndRestore(password, seed) {
439
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
440
+ assertIsValidPassword(password);
441
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createNewVaultWithKeyring).call(this, password, {
442
+ type: KeyringTypes.hd,
443
+ opts: {
444
+ mnemonic: seed,
445
+ numberOfAccounts: 1,
446
+ },
447
+ });
448
+ });
449
+ }
450
+ /**
451
+ * Create a new vault and primary keyring.
452
+ *
453
+ * This only works if keyrings are empty. If there is a pre-existing unlocked vault, calling this will have no effect.
454
+ * If there is a pre-existing locked vault, it will be replaced.
455
+ *
456
+ * @param password - Password to unlock the new vault.
457
+ * @returns Promise resolving when the operation ends successfully.
458
+ */
459
+ async createNewVaultAndKeychain(password) {
460
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
461
+ const accounts = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getAccountsFromKeyrings).call(this);
462
+ if (!accounts.length) {
463
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createNewVaultWithKeyring).call(this, password, {
464
+ type: KeyringTypes.hd,
465
+ });
466
+ }
467
+ });
468
+ }
469
+ /**
470
+ * Adds a new keyring of the given `type`.
471
+ *
472
+ * @param type - Keyring type name.
473
+ * @param opts - Keyring options.
474
+ * @throws If a builder for the given `type` does not exist.
475
+ * @returns Promise resolving to the new keyring metadata.
476
+ */
477
+ async addNewKeyring(type, opts) {
478
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
479
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringMetadata).call(this, await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, opts)));
480
+ }
481
+ /**
482
+ * Method to verify a given password validity. Throws an
483
+ * error if the password is invalid.
484
+ *
485
+ * @param password - Password of the keyring.
486
+ */
487
+ async verifyPassword(password) {
488
+ if (!this.state.vault) {
489
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.VaultError);
490
+ }
491
+ await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decrypt(password, this.state.vault);
492
+ }
493
+ /**
494
+ * Returns the status of the vault.
495
+ *
496
+ * @returns Boolean returning true if the vault is unlocked.
497
+ */
498
+ isUnlocked() {
499
+ return this.state.isUnlocked;
500
+ }
501
+ /**
502
+ * Gets the seed phrase of the HD keyring.
503
+ *
504
+ * @param credentials - Object holding either the `password` or the vault
505
+ * `encryptionKey`.
506
+ * @param keyringId - The id of the keyring.
507
+ * @returns Promise resolving to the seed phrase.
508
+ */
509
+ async exportSeedPhrase(credentials, keyringId) {
510
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
511
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_verifyCredentials).call(this, credentials);
512
+ const selectedKeyring = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringByIdOrDefault).call(this, keyringId);
513
+ if (!selectedKeyring) {
514
+ throw new errors_js_1.KeyringControllerError('Keyring not found');
515
+ }
516
+ assertHasUint8ArrayMnemonic(selectedKeyring);
517
+ return selectedKeyring.mnemonic;
518
+ }
519
+ /**
520
+ * Gets the private key from the keyring controlling an address.
521
+ *
522
+ * @param credentials - Object holding either the `password` or the vault
523
+ * `encryptionKey`.
524
+ * @param address - Address to export.
525
+ * @returns Promise resolving to the private key for an address.
526
+ */
527
+ async exportAccount(credentials, address) {
528
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
529
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_verifyCredentials).call(this, credentials);
530
+ const keyring = (await this.getKeyringForAccount(address));
531
+ if (!keyring.exportAccount) {
532
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.UnsupportedExportAccount);
533
+ }
534
+ return await keyring.exportAccount(normalize(address));
535
+ }
536
+ /**
537
+ * Returns the public addresses of all accounts from every keyring.
538
+ *
539
+ * @returns A promise resolving to an array of addresses.
540
+ */
541
+ async getAccounts() {
542
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
543
+ return this.state.keyrings.reduce((accounts, keyring) => accounts.concat(keyring.accounts), []);
544
+ }
545
+ /**
546
+ * Get encryption public key.
547
+ *
548
+ * @param account - An account address.
549
+ * @param opts - Additional encryption options.
550
+ * @throws If the `account` does not exist or does not support the `getEncryptionPublicKey` method
551
+ * @returns Promise resolving to encyption public key of the `account` if one exists.
552
+ */
553
+ async getEncryptionPublicKey(account, opts) {
554
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
555
+ const address = (0, eth_sig_util_1.normalize)(account);
556
+ const keyring = (await this.getKeyringForAccount(account));
557
+ if (!keyring.getEncryptionPublicKey) {
558
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.UnsupportedGetEncryptionPublicKey);
559
+ }
560
+ return await keyring.getEncryptionPublicKey(address, opts);
561
+ }
562
+ /**
563
+ * Attempts to decrypt the provided message parameters.
564
+ *
565
+ * @param messageParams - The decryption message parameters.
566
+ * @param messageParams.from - The address of the account you want to use to decrypt the message.
567
+ * @param messageParams.data - The encrypted data that you want to decrypt.
568
+ * @returns The raw decryption result.
569
+ */
570
+ async decryptMessage(messageParams) {
571
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
572
+ const address = (0, eth_sig_util_1.normalize)(messageParams.from);
573
+ const keyring = (await this.getKeyringForAccount(address));
574
+ if (!keyring.decryptMessage) {
575
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.UnsupportedDecryptMessage);
576
+ }
577
+ return keyring.decryptMessage(address, messageParams.data);
578
+ }
579
+ /**
580
+ * Returns the currently initialized keyring that manages
581
+ * the specified `address` if one exists.
582
+ *
583
+ * @deprecated Use of this method is discouraged as actions executed directly on
584
+ * keyrings are not being reflected in the KeyringController state and not
585
+ * persisted in the vault. Use `withKeyring` instead.
586
+ * @param account - An account address.
587
+ * @returns Promise resolving to keyring of the `account` if one exists.
588
+ */
589
+ async getKeyringForAccount(account) {
590
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
591
+ const keyring = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringForAccount).call(this, account);
592
+ if (keyring) {
593
+ return keyring;
594
+ }
595
+ if (__classPrivateFieldGet(this, _KeyringController_keyrings, "f").length === 0) {
596
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.NoKeyring);
597
+ }
598
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.KeyringNotFound);
599
+ }
600
+ /**
601
+ * Returns all keyrings of the given type.
602
+ *
603
+ * @deprecated Use of this method is discouraged as actions executed directly on
604
+ * keyrings are not being reflected in the KeyringController state and not
605
+ * persisted in the vault. Use `withKeyring` instead.
606
+ * @param type - Keyring type name.
607
+ * @returns An array of keyrings of the given type.
608
+ */
609
+ getKeyringsByType(type) {
610
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
611
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringEntriesByType).call(this, { v2: false, type }).map(({ keyring }) => keyring);
612
+ }
613
+ /**
614
+ * Persist all serialized keyrings in the vault.
615
+ *
616
+ * @deprecated This method is being phased out in favor of `withKeyring`.
617
+ * @returns Promise resolving with `true` value when the
618
+ * operation completes.
619
+ */
620
+ async persistAllKeyrings() {
621
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
622
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
623
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
624
+ return true;
625
+ });
626
+ }
627
+ /**
628
+ * Imports an account with the specified import strategy.
629
+ *
630
+ * @param strategy - Import strategy name.
631
+ * @param args - Array of arguments to pass to the underlying stategy.
632
+ * @throws Will throw when passed an unrecognized strategy.
633
+ * @returns Promise resolving to the imported account address.
634
+ */
635
+ async importAccountWithStrategy(strategy,
636
+ // TODO: Replace `any` with type
637
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
638
+ args) {
639
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
640
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
641
+ let privateKey;
642
+ switch (strategy) {
643
+ case AccountImportStrategy.privateKey: {
644
+ const [importedKey] = args;
645
+ if (!importedKey) {
646
+ throw new errors_js_1.KeyringControllerError('Cannot import an empty key.');
647
+ }
648
+ const prefixed = (0, utils_1.add0x)(importedKey);
649
+ let bufferedPrivateKey;
650
+ try {
651
+ bufferedPrivateKey = (0, utils_1.hexToBytes)(prefixed);
652
+ }
653
+ catch {
654
+ throw new errors_js_1.KeyringControllerError('Cannot import invalid private key.');
655
+ }
656
+ if (!(0, util_1.isValidPrivate)(bufferedPrivateKey) ||
657
+ // ensures that the key is 64 bytes long
658
+ (0, util_1.getBinarySize)(prefixed) !== 64 + '0x'.length) {
659
+ throw new errors_js_1.KeyringControllerError('Cannot import invalid private key.');
660
+ }
661
+ privateKey = (0, utils_1.remove0x)(prefixed);
662
+ break;
663
+ }
664
+ case AccountImportStrategy.json: {
665
+ let wallet;
666
+ const [input, password] = args;
667
+ try {
668
+ wallet = ethereumjs_wallet_1.thirdparty.fromEtherWallet(input, password);
669
+ }
670
+ catch {
671
+ wallet = wallet ?? (await ethereumjs_wallet_1.default.fromV3(input, password, true));
672
+ }
673
+ privateKey = (0, utils_1.bytesToHex)(new Uint8Array(wallet.getPrivateKey()));
674
+ break;
675
+ }
676
+ default:
677
+ throw new errors_js_1.KeyringControllerError(`Unexpected import strategy: '${String(strategy)}'`);
678
+ }
679
+ const newKeyring = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, KeyringTypes.simple, [
680
+ privateKey,
681
+ ]);
682
+ const accounts = await newKeyring.getAccounts();
683
+ return accounts[0];
684
+ });
685
+ }
686
+ /**
687
+ * Removes an account from keyring state.
688
+ *
689
+ * @param address - Address of the account to remove.
690
+ * @fires KeyringController:accountRemoved
691
+ * @returns Promise resolving when the account is removed.
692
+ */
693
+ async removeAccount(address) {
694
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
695
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
696
+ const keyringIndex = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_findKeyringIndexForAccount).call(this, address);
697
+ if (keyringIndex === -1) {
698
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.NoKeyring);
699
+ }
700
+ const { keyring, keyringV2 } = __classPrivateFieldGet(this, _KeyringController_keyrings, "f")[keyringIndex];
701
+ const isPrimaryKeyring = keyringIndex === 0;
702
+ const shouldRemoveKeyring = (await keyring.getAccounts()).length === 1;
703
+ // Primary keyring should never be removed, so we need to keep at least one account in it
704
+ if (isPrimaryKeyring && shouldRemoveKeyring) {
705
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.LastAccountInPrimaryKeyring);
706
+ }
707
+ // Not all the keyrings support this, so we have to check
708
+ if (!keyring.removeAccount) {
709
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.UnsupportedRemoveAccount);
710
+ }
711
+ // FIXME #1: We do cast to `Hex` to make the type checker happy here, and
712
+ // because `Keyring<State>.removeAccount` requires address to be `Hex`.
713
+ // Those types would need to be updated for a full non-EVM support.
714
+ //
715
+ // FIXME #2: The `removeAccount` method of snaps keyring is async. We have
716
+ // to update the interface of the other keyrings to be async as well.
717
+ // eslint-disable-next-line @typescript-eslint/await-thenable
718
+ await keyring.removeAccount(address);
719
+ if (shouldRemoveKeyring) {
720
+ __classPrivateFieldGet(this, _KeyringController_keyrings, "f").splice(keyringIndex, 1);
721
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_destroyKeyring).call(this, keyring, keyringV2);
722
+ }
723
+ });
724
+ this.messenger.publish(`${name}:accountRemoved`, address);
725
+ }
726
+ /**
727
+ * Deallocates all secrets and locks the wallet.
728
+ *
729
+ * @returns Promise resolving when the operation completes.
730
+ */
731
+ async setLocked() {
732
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
733
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
734
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, undefined, "f");
735
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
736
+ this.update((state) => {
737
+ state.isUnlocked = false;
738
+ state.keyrings = [];
739
+ delete state.encryptionKey;
740
+ delete state.encryptionSalt;
741
+ });
742
+ this.messenger.publish(`${name}:lock`);
743
+ });
744
+ }
745
+ /**
746
+ * Signs message by calling down into a specific keyring.
747
+ *
748
+ * @param messageParams - PersonalMessageParams object to sign.
749
+ * @returns Promise resolving to a signed message string.
750
+ */
751
+ async signMessage(messageParams) {
752
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
753
+ if (!messageParams.data) {
754
+ throw new errors_js_1.KeyringControllerError("Can't sign an empty message");
755
+ }
756
+ const address = (0, eth_sig_util_1.normalize)(messageParams.from);
757
+ const keyring = (await this.getKeyringForAccount(address));
758
+ if (!keyring.signMessage) {
759
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.UnsupportedSignMessage);
760
+ }
761
+ return await keyring.signMessage(address, messageParams.data);
762
+ }
763
+ /**
764
+ * Signs EIP-7702 Authorization message by calling down into a specific keyring.
765
+ *
766
+ * @param params - EIP7702AuthorizationParams object to sign.
767
+ * @returns Promise resolving to an EIP-7702 Authorization signature.
768
+ * @throws Will throw UnsupportedSignEIP7702Authorization if the keyring does not support signing EIP-7702 Authorization messages.
769
+ */
770
+ async signEip7702Authorization(params) {
771
+ const from = (0, eth_sig_util_1.normalize)(params.from);
772
+ const keyring = (await this.getKeyringForAccount(from));
773
+ if (!keyring.signEip7702Authorization) {
774
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.UnsupportedSignEip7702Authorization);
775
+ }
776
+ const { chainId, nonce } = params;
777
+ const contractAddress = (0, eth_sig_util_1.normalize)(params.contractAddress);
778
+ if (contractAddress === undefined) {
779
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.MissingEip7702AuthorizationContractAddress);
780
+ }
781
+ return await keyring.signEip7702Authorization(from, [
782
+ chainId,
783
+ contractAddress,
784
+ nonce,
785
+ ]);
786
+ }
787
+ /**
788
+ * Signs personal message by calling down into a specific keyring.
789
+ *
790
+ * @param messageParams - PersonalMessageParams object to sign.
791
+ * @returns Promise resolving to a signed message string.
792
+ */
793
+ async signPersonalMessage(messageParams) {
794
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
795
+ const address = (0, eth_sig_util_1.normalize)(messageParams.from);
796
+ const keyring = (await this.getKeyringForAccount(address));
797
+ if (!keyring.signPersonalMessage) {
798
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.UnsupportedSignPersonalMessage);
799
+ }
800
+ const normalizedData = normalize(messageParams.data);
801
+ return await keyring.signPersonalMessage(address, normalizedData);
802
+ }
803
+ /**
804
+ * Signs typed message by calling down into a specific keyring.
805
+ *
806
+ * @param messageParams - TypedMessageParams object to sign.
807
+ * @param version - Compatibility version EIP712.
808
+ * @throws Will throw when passed an unrecognized version.
809
+ * @returns Promise resolving to a signed message string or an error if any.
810
+ */
811
+ async signTypedMessage(messageParams, version) {
812
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
813
+ try {
814
+ if (![
815
+ SignTypedDataVersion.V1,
816
+ SignTypedDataVersion.V3,
817
+ SignTypedDataVersion.V4,
818
+ ].includes(version)) {
819
+ throw new errors_js_1.KeyringControllerError(`Unexpected signTypedMessage version: '${version}'`);
820
+ }
821
+ // Cast to `Hex` here is safe here because `messageParams.from` is not nullish.
822
+ // `normalize` returns `Hex` unless given a nullish value.
823
+ const address = (0, eth_sig_util_1.normalize)(messageParams.from);
824
+ const keyring = (await this.getKeyringForAccount(address));
825
+ if (!keyring.signTypedData) {
826
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.UnsupportedSignTypedMessage);
827
+ }
828
+ return await keyring.signTypedData(address, version !== SignTypedDataVersion.V1 &&
829
+ typeof messageParams.data === 'string'
830
+ ? JSON.parse(messageParams.data)
831
+ : messageParams.data, { version });
832
+ }
833
+ catch (error) {
834
+ const errorMessage = error instanceof Error
835
+ ? `${error.name}: ${error.message}`
836
+ : String(error);
837
+ throw new errors_js_1.KeyringControllerError(`Keyring Controller signTypedMessage: ${errorMessage}`, error instanceof Error ? error : undefined);
838
+ }
839
+ }
840
+ /**
841
+ * Signs a transaction by calling down into a specific keyring.
842
+ *
843
+ * @param transaction - Transaction object to sign. Must be a `ethereumjs-tx` transaction instance.
844
+ * @param from - Address to sign from, should be in keychain.
845
+ * @param opts - An optional options object.
846
+ * @returns Promise resolving to a signed transaction string.
847
+ */
848
+ async signTransaction(transaction, from, opts) {
849
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
850
+ const address = (0, eth_sig_util_1.normalize)(from);
851
+ const keyring = (await this.getKeyringForAccount(address));
852
+ if (!keyring.signTransaction) {
853
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.UnsupportedSignTransaction);
854
+ }
855
+ return await keyring.signTransaction(address, transaction, opts);
856
+ }
857
+ /**
858
+ * Convert a base transaction to a base UserOperation.
859
+ *
860
+ * @param from - Address of the sender.
861
+ * @param transactions - Base transactions to include in the UserOperation.
862
+ * @param executionContext - The execution context to use for the UserOperation.
863
+ * @returns A pseudo-UserOperation that can be used to construct a real.
864
+ */
865
+ async prepareUserOperation(from, transactions, executionContext) {
866
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
867
+ const address = (0, eth_sig_util_1.normalize)(from);
868
+ const keyring = (await this.getKeyringForAccount(address));
869
+ if (!keyring.prepareUserOperation) {
870
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.UnsupportedPrepareUserOperation);
871
+ }
872
+ return await keyring.prepareUserOperation(address, transactions, executionContext);
873
+ }
874
+ /**
875
+ * Patches properties of a UserOperation. Currently, only the
876
+ * `paymasterAndData` can be patched.
877
+ *
878
+ * @param from - Address of the sender.
879
+ * @param userOp - UserOperation to patch.
880
+ * @param executionContext - The execution context to use for the UserOperation.
881
+ * @returns A patch to apply to the UserOperation.
882
+ */
883
+ async patchUserOperation(from, userOp, executionContext) {
884
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
885
+ const address = (0, eth_sig_util_1.normalize)(from);
886
+ const keyring = (await this.getKeyringForAccount(address));
887
+ if (!keyring.patchUserOperation) {
888
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.UnsupportedPatchUserOperation);
889
+ }
890
+ return await keyring.patchUserOperation(address, userOp, executionContext);
891
+ }
892
+ /**
893
+ * Signs an UserOperation.
894
+ *
895
+ * @param from - Address of the sender.
896
+ * @param userOp - UserOperation to sign.
897
+ * @param executionContext - The execution context to use for the UserOperation.
898
+ * @returns The signature of the UserOperation.
899
+ */
900
+ async signUserOperation(from, userOp, executionContext) {
901
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
902
+ const address = (0, eth_sig_util_1.normalize)(from);
903
+ const keyring = (await this.getKeyringForAccount(address));
904
+ if (!keyring.signUserOperation) {
905
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.UnsupportedSignUserOperation);
906
+ }
907
+ return await keyring.signUserOperation(address, userOp, executionContext);
908
+ }
909
+ /**
910
+ * Changes the password used to encrypt the vault.
911
+ *
912
+ * @param password - The new password.
913
+ * @returns Promise resolving when the operation completes.
914
+ */
915
+ changePassword(password) {
916
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
917
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
918
+ assertIsValidPassword(password);
919
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveAndSetEncryptionKey).call(this, password, {
920
+ ignoreExistingVault: true,
921
+ });
922
+ });
923
+ }
924
+ /**
925
+ * Attempts to decrypt the current vault and load its keyrings, using the
926
+ * given encryption key and salt. The optional salt can be used to check for
927
+ * consistency with the vault salt.
928
+ *
929
+ * @param encryptionKey - Key to unlock the keychain.
930
+ * @param encryptionSalt - Optional salt to unlock the keychain.
931
+ * @returns Promise resolving when the operation completes.
932
+ */
933
+ async submitEncryptionKey(encryptionKey, encryptionSalt) {
934
+ const { hasChanged } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
935
+ const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, {
936
+ encryptionKey,
937
+ encryptionSalt,
938
+ });
939
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
940
+ return result;
941
+ });
942
+ try {
943
+ // if new metadata has been generated during login, we
944
+ // can attempt to upgrade the vault.
945
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
946
+ if (hasChanged) {
947
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
948
+ }
949
+ });
950
+ }
951
+ catch (error) {
952
+ // We don't want to throw an error if the upgrade fails
953
+ // since the controller is already unlocked.
954
+ console.error('Failed to update vault during login:', error);
955
+ }
956
+ }
957
+ /**
958
+ * Exports the vault encryption key.
959
+ *
960
+ * @returns The vault encryption key.
961
+ */
962
+ async exportEncryptionKey() {
963
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
964
+ return await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async () => {
965
+ assertIsEncryptionKeySet(__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")?.serialized);
966
+ return __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").serialized;
967
+ });
968
+ }
969
+ /**
970
+ * Attempts to decrypt the current vault and load its keyrings,
971
+ * using the given password.
972
+ *
973
+ * @param password - Password to unlock the keychain.
974
+ * @returns Promise resolving when the operation completes.
975
+ */
976
+ async submitPassword(password) {
977
+ const { hasChanged } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
978
+ const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, { password });
979
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
980
+ return result;
981
+ });
982
+ try {
983
+ // If there are stronger encryption params available, or
984
+ // if the keyring state has changed during deserialization, we
985
+ // can attempt to upgrade the vault.
986
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
987
+ if (hasChanged || __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_isNewEncryptionAvailable).call(this)) {
988
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveAndSetEncryptionKey).call(this, password, {
989
+ // If the vault is being upgraded, we want to ignore the metadata
990
+ // that is already in the vault, so we can effectively
991
+ // re-encrypt the vault with the new encryption config.
992
+ ignoreExistingVault: true,
993
+ });
994
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
995
+ }
996
+ });
997
+ }
998
+ catch (error) {
999
+ // We don't want to throw an error if the upgrade fails
1000
+ // since the controller is already unlocked.
1001
+ console.error('Failed to update vault during login:', error);
1002
+ }
1003
+ }
1004
+ /**
1005
+ * Verifies the that the seed phrase restores the current keychain's accounts.
1006
+ *
1007
+ * @param keyringId - The id of the keyring to verify.
1008
+ * @returns Promise resolving to the seed phrase as Uint8Array.
1009
+ */
1010
+ async verifySeedPhrase(keyringId) {
1011
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
1012
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async () => __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_verifySeedPhrase).call(this, keyringId));
1013
+ }
1014
+ async withKeyring(selector, operation, options = {
1015
+ createIfMissing: false,
1016
+ }) {
1017
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
1018
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
1019
+ let entry = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_selectKeyringEntry).call(this, {
1020
+ v2: false,
1021
+ selector,
1022
+ });
1023
+ if (!entry && 'type' in selector && options.createIfMissing) {
1024
+ const newKeyring = (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, selector.type, options.createWithData));
1025
+ entry = __classPrivateFieldGet(this, _KeyringController_keyrings, "f").find(({ keyring }) => keyring === newKeyring);
1026
+ }
1027
+ if (!entry) {
1028
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.KeyringNotFound);
1029
+ }
1030
+ const { metadata } = entry;
1031
+ const keyring = entry.keyring;
1032
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoUnsafeDirectKeyringAccess).call(this, await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_cleanUpEmptiedKeyringsAfter).call(this, async () => operation({ keyring, metadata })), keyring);
1033
+ });
1034
+ }
1035
+ /**
1036
+ * Select a keyring and execute the given operation with the selected
1037
+ * keyring, **without** acquiring the controller's mutual exclusion lock.
1038
+ *
1039
+ * ## When to use this method
1040
+ *
1041
+ * This method is an escape hatch for read-only access to keyring data that
1042
+ * is immutable once the keyring is initialized. A typical safe use case is
1043
+ * reading the `mnemonic` from an `HdKeyring`: the mnemonic is set during
1044
+ * `deserialize()` and never mutated afterwards, so it can safely be read
1045
+ * without holding the lock.
1046
+ *
1047
+ * ## Why it is "unsafe"
1048
+ *
1049
+ * The "unsafe" designation mirrors the semantics of `unsafe { }` blocks in
1050
+ * Rust: the method itself does not enforce thread-safety guarantees. By
1051
+ * calling this method the **caller** explicitly takes responsibility for
1052
+ * ensuring that:
1053
+ *
1054
+ * - The operation is **read-only** — no state is mutated.
1055
+ * - The data being read is **immutable** after the keyring is initialized,
1056
+ * so concurrent locked operations cannot alter it while this callback
1057
+ * runs.
1058
+ *
1059
+ * Do **not** use this method to:
1060
+ * - Mutate keyring state (add accounts, sign, etc.) — use `withKeyring`.
1061
+ * - Read mutable fields that could change during concurrent operations.
1062
+ *
1063
+ * @param selector - Keyring selector object.
1064
+ * @param operation - Read-only function to execute with the selected keyring.
1065
+ * @returns Promise resolving to the result of the function execution.
1066
+ * @template SelectedKeyring - The type of the selected keyring.
1067
+ * @template CallbackResult - The type of the value resolved by the callback function.
1068
+ */
1069
+ async withKeyringUnsafe(selector, operation) {
1070
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
1071
+ const entry = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_selectKeyringEntry).call(this, { v2: false, selector });
1072
+ if (!entry) {
1073
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.KeyringNotFound);
1074
+ }
1075
+ const { metadata } = entry;
1076
+ const keyring = entry.keyring;
1077
+ // Even if this method is "unsafe", we still want to prevent returning
1078
+ // the keyring directly.
1079
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoUnsafeDirectKeyringAccess).call(this, await operation({ keyring, metadata }), keyring);
1080
+ }
1081
+ /**
1082
+ * Select a keyring using its `KeyringV2` adapter, and execute
1083
+ * the given operation with the wrapped keyring as a mutually
1084
+ * exclusive atomic operation.
1085
+ *
1086
+ * The cached `KeyringV2` adapter is retrieved from the keyring
1087
+ * entry.
1088
+ *
1089
+ * A `KeyringV2Builder` for the selected keyring's type must exist
1090
+ * (either as a default or registered via the `keyringV2Builders`
1091
+ * constructor option); otherwise an error is thrown.
1092
+ *
1093
+ * The method automatically persists changes at the end of the
1094
+ * function execution, or rolls back the changes if an error
1095
+ * is thrown.
1096
+ *
1097
+ * @param selector - Keyring selector object.
1098
+ * @param operation - Function to execute with the wrapped V2 keyring.
1099
+ * @returns Promise resolving to the result of the function execution.
1100
+ * @template CallbackResult - The type of the value resolved by the callback function.
1101
+ */
1102
+ async withKeyringV2(selector, operation) {
1103
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
1104
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
1105
+ const entry = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_selectKeyringEntry).call(this, {
1106
+ v2: true,
1107
+ selector,
1108
+ });
1109
+ if (!entry) {
1110
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.KeyringNotFound);
1111
+ }
1112
+ if (!entry.keyringV2) {
1113
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.KeyringV2NotSupported);
1114
+ }
1115
+ const { metadata } = entry;
1116
+ const keyring = entry.keyringV2;
1117
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoUnsafeDirectKeyringAccess).call(this, await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_cleanUpEmptiedKeyringsAfter).call(this, async () => operation({
1118
+ keyring,
1119
+ metadata,
1120
+ })), keyring);
1121
+ });
1122
+ }
1123
+ /**
1124
+ * Select a keyring, wrap it in a `KeyringV2` adapter, and execute
1125
+ * the given read-only operation **without** acquiring the controller's
1126
+ * mutual exclusion lock.
1127
+ *
1128
+ * ## When to use this method
1129
+ *
1130
+ * This method is an escape hatch for read-only access to keyring data that
1131
+ * is immutable once the keyring is initialized. A typical safe use case is
1132
+ * reading immutable fields from a `KeyringV2` adapter: data that is set
1133
+ * during initialization and never mutated afterwards.
1134
+ *
1135
+ * ## Why it is "unsafe"
1136
+ *
1137
+ * The "unsafe" designation mirrors the semantics of `unsafe { }` blocks in
1138
+ * Rust: the method itself does not enforce thread-safety guarantees. By
1139
+ * calling this method the **caller** explicitly takes responsibility for
1140
+ * ensuring that:
1141
+ *
1142
+ * - The operation is **read-only** — no state is mutated.
1143
+ * - The data being read is **immutable** after the keyring is initialized,
1144
+ * so concurrent locked operations cannot alter it while this callback
1145
+ * runs.
1146
+ *
1147
+ * Do **not** use this method to:
1148
+ * - Mutate keyring state (add accounts, sign, etc.) — use `withKeyringV2`.
1149
+ * - Read mutable fields that could change during concurrent operations.
1150
+ *
1151
+ * @param selector - Keyring selector object.
1152
+ * @param operation - Read-only function to execute with the wrapped V2 keyring.
1153
+ * @returns Promise resolving to the result of the function execution.
1154
+ * @template SelectedKeyring - The type of the selected V2 keyring.
1155
+ * @template CallbackResult - The type of the value resolved by the callback function.
1156
+ */
1157
+ async withKeyringV2Unsafe(selector, operation) {
1158
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
1159
+ const entry = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_selectKeyringEntry).call(this, {
1160
+ v2: true,
1161
+ selector,
1162
+ });
1163
+ if (!entry) {
1164
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.KeyringNotFound);
1165
+ }
1166
+ if (!entry.keyringV2) {
1167
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.KeyringV2NotSupported);
1168
+ }
1169
+ const { metadata } = entry;
1170
+ const keyring = entry.keyringV2;
1171
+ // Even if this method is "unsafe", we still want to prevent returning
1172
+ // the keyring directly.
1173
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoUnsafeDirectKeyringAccess).call(this, await operation({ keyring, metadata }), keyring);
1174
+ }
1175
+ /**
1176
+ * Execute an operation against all keyrings as a mutually exclusive atomic
1177
+ * operation. The operation receives a {@link RestrictedController} instance
1178
+ * that exposes a read-only live view of all keyrings as well as
1179
+ * `addNewKeyring` and `removeKeyring` methods to stage mutations.
1180
+ *
1181
+ * The method automatically persists changes at the end of the function
1182
+ * execution, or rolls back the changes if an error is thrown.
1183
+ *
1184
+ * @param operation - Function to execute with the restricted controller.
1185
+ * @returns Promise resolving to the result of the function execution.
1186
+ * @template CallbackResult - The type of the value resolved by the callback function.
1187
+ */
1188
+ async withController(operation) {
1189
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
1190
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
1191
+ // Track created and removed keyrings during the operation execution.
1192
+ const createdEntries = new Set();
1193
+ const removedEntries = new Set();
1194
+ // Copy of the current keyrings that is mutated during the operation execution.
1195
+ const restrictedEntries = [...__classPrivateFieldGet(this, _KeyringController_keyrings, "f")];
1196
+ // The restricted controller proxies the current keyrings and allows staging
1197
+ // mutations that are only applied to the real keyrings if the operation
1198
+ // completes successfully. This allows us to have a single source of truth
1199
+ // for the keyrings during the operation execution, and to automatically
1200
+ // roll back any changes if an error is thrown.
1201
+ const restrictedController = {
1202
+ // We freeze the array to prevent direct mutations, but the keyring instances
1203
+ // themselves are not frozen, allowing safe read-only access.
1204
+ get keyrings() {
1205
+ return Object.freeze([...restrictedEntries]);
1206
+ },
1207
+ // Method to create a new keyring and adds it to the restricted entries.
1208
+ addNewKeyring: async (type, opts) => {
1209
+ const entry = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyring).call(this, type, opts);
1210
+ restrictedEntries.push(entry);
1211
+ createdEntries.add(entry);
1212
+ return entry;
1213
+ },
1214
+ // Method to remove a keyring from the restricted entries.
1215
+ removeKeyring: async (id) => {
1216
+ const index = restrictedEntries.findIndex((entry) => entry.metadata.id === id);
1217
+ if (index === -1) {
1218
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.KeyringNotFound);
1219
+ }
1220
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNotRemovingPrimaryKeyring).call(this, restrictedEntries[index], restrictedEntries);
1221
+ const [removed] = restrictedEntries.splice(index, 1);
1222
+ removedEntries.add(removed);
1223
+ },
1224
+ };
1225
+ const destroyKeyrings = async (entries) => {
1226
+ await Promise.all([...entries].map(({ keyring, keyringV2 }) => __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_destroyKeyring).call(this, keyring, keyringV2)));
1227
+ };
1228
+ let result;
1229
+ try {
1230
+ result = await operation(restrictedController);
1231
+ }
1232
+ catch (error) {
1233
+ await destroyKeyrings(createdEntries);
1234
+ throw error;
1235
+ }
1236
+ await destroyKeyrings(removedEntries);
1237
+ // We update the real keyrings only after the operation completes successfully, so that
1238
+ // they will be persisted in the vault.
1239
+ __classPrivateFieldSet(this, _KeyringController_keyrings, restrictedEntries, "f");
1240
+ // As usual, we want to prevent returning direct references to keyring instances, so we check
1241
+ // the result for any unsafe direct access before returning.
1242
+ for (const { keyring, keyringV2 } of [
1243
+ ...__classPrivateFieldGet(this, _KeyringController_keyrings, "f"),
1244
+ // We also check for keyrings that got removed during the operation, since the result could
1245
+ // still have references to them.
1246
+ ...removedEntries,
1247
+ ]) {
1248
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoUnsafeDirectKeyringAccess).call(this, result, keyring);
1249
+ if (keyringV2) {
1250
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoUnsafeDirectKeyringAccess).call(this, result, keyringV2);
1251
+ }
1252
+ }
1253
+ return result;
1254
+ });
1255
+ }
1256
+ /**
1257
+ * Gets the type of the keyring that manages the specified account.
1258
+ *
1259
+ * @param account - The account address to look up.
1260
+ * @returns A promise that resolves to the type of the keyring managing the account.
1261
+ */
1262
+ async getAccountKeyringType(account) {
1263
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
1264
+ const keyring = (await this.getKeyringForAccount(account));
1265
+ return keyring.type;
1266
+ }
1267
+ }
1268
+ exports.KeyringController = KeyringController;
1269
+ _KeyringController_controllerOperationMutex = new WeakMap(), _KeyringController_vaultOperationMutex = new WeakMap(), _KeyringController_keyringBuilders = new WeakMap(), _KeyringController_keyringV2Builders = new WeakMap(), _KeyringController_encryptor = new WeakMap(), _KeyringController_keyrings = new WeakMap(), _KeyringController_unsupportedKeyrings = new WeakMap(), _KeyringController_encryptionKey = new WeakMap(), _KeyringController_instances = new WeakSet(), _KeyringController_verifyEncryptionKey =
1270
+ /**
1271
+ * Method to verify a given encryption key validity. Throws an error if the
1272
+ * encryption key is invalid, i.e. it cannot decrypt the vault.
1273
+ *
1274
+ * @param encryptionKey - Serialized vault encryption key.
1275
+ * @param encryptionSalt - Optional salt to verify against the vault. When
1276
+ * omitted, the salt serialized alongside the vault is used.
1277
+ */
1278
+ async function _KeyringController_verifyEncryptionKey(encryptionKey, encryptionSalt) {
1279
+ if (!this.state.vault) {
1280
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.VaultError);
1281
+ }
1282
+ const parsedEncryptedVault = JSON.parse(this.state.vault);
1283
+ const salt = encryptionSalt ?? parsedEncryptedVault.salt;
1284
+ if (parsedEncryptedVault.salt !== salt) {
1285
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.ExpiredCredentials);
1286
+ }
1287
+ const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
1288
+ await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(key, parsedEncryptedVault);
1289
+ }, _KeyringController_verifyCredentials =
1290
+ /**
1291
+ * Verifies export credentials by checking either the wallet password or the
1292
+ * vault encryption key.
1293
+ *
1294
+ * @param credentials - Object holding either the `password` or the vault
1295
+ * `encryptionKey`.
1296
+ */
1297
+ async function _KeyringController_verifyCredentials(credentials) {
1298
+ // eslint-disable-next-line no-restricted-syntax
1299
+ if ('password' in credentials) {
1300
+ await this.verifyPassword(credentials.password);
1301
+ }
1302
+ else {
1303
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_verifyEncryptionKey).call(this, credentials.encryptionKey, credentials.encryptionSalt);
1304
+ }
1305
+ }, _KeyringController_getKeyringForAccount = async function _KeyringController_getKeyringForAccount(account) {
1306
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
1307
+ const entry = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringEntryForAccount).call(this, account);
1308
+ return entry?.keyring;
1309
+ }, _KeyringController_getKeyringEntryForAccount = async function _KeyringController_getKeyringEntryForAccount(account) {
1310
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
1311
+ const keyringIndex = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_findKeyringIndexForAccount).call(this, account);
1312
+ if (keyringIndex > -1) {
1313
+ return __classPrivateFieldGet(this, _KeyringController_keyrings, "f")[keyringIndex];
1314
+ }
1315
+ return undefined;
1316
+ }, _KeyringController_findKeyringIndexForAccount = async function _KeyringController_findKeyringIndexForAccount(account) {
1317
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
1318
+ const address = account.toLowerCase();
1319
+ const accountsPerKeyring = await Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(({ keyring }) => keyring.getAccounts()));
1320
+ return accountsPerKeyring.findIndex((accounts) => accounts.map((a) => a.toLowerCase()).includes(address));
1321
+ }, _KeyringController_getKeyringEntriesByType = function _KeyringController_getKeyringEntriesByType({ v2, type, }) {
1322
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
1323
+ return __classPrivateFieldGet(this, _KeyringController_keyrings, "f").filter(({ keyring, keyringV2 }) => v2 ? keyringV2?.type === type : keyring.type === type);
1324
+ }, _KeyringController_assertNoUnsafeDirectKeyringAccess = function _KeyringController_assertNoUnsafeDirectKeyringAccess(value, keyring) {
1325
+ if (Object.is(value, keyring)) {
1326
+ // Access to a keyring instance outside of controller safeguards
1327
+ // should be discouraged, as it can lead to unexpected behavior.
1328
+ // This error is thrown to prevent consumers using `withKeyring`
1329
+ // as a way to get a reference to a keyring instance.
1330
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.UnsafeDirectKeyringAccess);
1331
+ }
1332
+ return value;
1333
+ }, _KeyringController_registerMessageHandlers = function _KeyringController_registerMessageHandlers() {
1334
+ this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
1335
+ }, _KeyringController_selectKeyringEntry =
1336
+ /**
1337
+ * Select a keyring entry using a selector without acquiring the controller lock.
1338
+ *
1339
+ * @param options - Selection options.
1340
+ * @param options.v2 - Tag to indicate whether the selector is for a V2 keyring.
1341
+ * @param options.selector - Keyring selector object.
1342
+ * @returns The selected keyring entry, or `undefined` if no match is found.
1343
+ * @template SelectedKeyring - The expected type of the selected keyring.
1344
+ * @template SelectedKeyringV2 - The expected type of the selected keyring (v2).
1345
+ */
1346
+ async function _KeyringController_selectKeyringEntry({ v2, selector, }) {
1347
+ let entry;
1348
+ if ('address' in selector) {
1349
+ entry = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringEntryForAccount).call(this, selector.address);
1350
+ }
1351
+ else if ('type' in selector) {
1352
+ const entries = v2
1353
+ ? __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringEntriesByType).call(this, { v2: true, type: selector.type })
1354
+ : __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringEntriesByType).call(this, { v2: false, type: selector.type });
1355
+ entry = entries[selector.index ?? 0];
1356
+ }
1357
+ else if ('id' in selector) {
1358
+ entry = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringEntryById).call(this, selector.id);
1359
+ }
1360
+ else if ('filter' in selector) {
1361
+ entry = __classPrivateFieldGet(this, _KeyringController_keyrings, "f").find(({ keyring, keyringV2, metadata }) => {
1362
+ // If v2, then we'll use the v2 selector which expects a `KeyringV2` instance.
1363
+ if (v2) {
1364
+ // However, some keyrings do not have a v2 wrapper, so we just skip them.
1365
+ if (!keyringV2) {
1366
+ return false;
1367
+ }
1368
+ return selector.filter(keyringV2, metadata);
1369
+ }
1370
+ return selector.filter(keyring, metadata);
1371
+ });
1372
+ }
1373
+ return entry;
1374
+ }, _KeyringController_getKeyringById = function _KeyringController_getKeyringById(keyringId) {
1375
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringEntryById).call(this, keyringId)?.keyring;
1376
+ }, _KeyringController_getKeyringEntryById = function _KeyringController_getKeyringEntryById(keyringId) {
1377
+ return __classPrivateFieldGet(this, _KeyringController_keyrings, "f").find(({ metadata }) => metadata.id === keyringId);
1378
+ }, _KeyringController_getKeyringByIdOrDefault = function _KeyringController_getKeyringByIdOrDefault(keyringId) {
1379
+ if (!keyringId) {
1380
+ return __classPrivateFieldGet(this, _KeyringController_keyrings, "f")[0]?.keyring;
1381
+ }
1382
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringById).call(this, keyringId);
1383
+ }, _KeyringController_getKeyringMetadata = function _KeyringController_getKeyringMetadata(keyring) {
1384
+ const keyringWithMetadata = __classPrivateFieldGet(this, _KeyringController_keyrings, "f").find((candidate) => candidate.keyring === keyring);
1385
+ if (!keyringWithMetadata) {
1386
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.KeyringNotFound);
1387
+ }
1388
+ return keyringWithMetadata.metadata;
1389
+ }, _KeyringController_getKeyringBuilderForType = function _KeyringController_getKeyringBuilderForType(type) {
1390
+ return __classPrivateFieldGet(this, _KeyringController_keyringBuilders, "f").find((keyringBuilder) => keyringBuilder.type === type);
1391
+ }, _KeyringController_getKeyringV2BuilderForType = function _KeyringController_getKeyringV2BuilderForType(type) {
1392
+ return __classPrivateFieldGet(this, _KeyringController_keyringV2Builders, "f").find((builder) => builder.type === type);
1393
+ }, _KeyringController_createNewVaultWithKeyring =
1394
+ /**
1395
+ * Create new vault with an initial keyring
1396
+ *
1397
+ * Destroys any old encrypted storage,
1398
+ * creates a new encrypted store with the given password,
1399
+ * creates a new wallet with 1 account.
1400
+ *
1401
+ * @fires KeyringController:unlock
1402
+ * @param password - The password to encrypt the vault with.
1403
+ * @param keyring - A object containing the params to instantiate a new keyring.
1404
+ * @param keyring.type - The keyring type.
1405
+ * @param keyring.opts - Optional parameters required to instantiate the keyring.
1406
+ * @returns A promise that resolves to the state.
1407
+ */
1408
+ async function _KeyringController_createNewVaultWithKeyring(password, keyring) {
1409
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1410
+ if (typeof password !== 'string') {
1411
+ throw new TypeError(constants_js_1.KeyringControllerErrorMessage.WrongPasswordType);
1412
+ }
1413
+ this.update((state) => {
1414
+ delete state.encryptionKey;
1415
+ delete state.encryptionSalt;
1416
+ });
1417
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveAndSetEncryptionKey).call(this, password, {
1418
+ ignoreExistingVault: true,
1419
+ });
1420
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
1421
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyringWithFirstAccount).call(this, keyring.type, keyring.opts);
1422
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
1423
+ }, _KeyringController_deriveAndSetEncryptionKey =
1424
+ /**
1425
+ * Derive the vault encryption key from the provided password, and
1426
+ * assign it to the instance variable for later use with cryptographic
1427
+ * functions.
1428
+ *
1429
+ * When the controller has a vault in its state, the key is derived
1430
+ * using the salt from the vault. If the vault is empty, a new salt
1431
+ * is generated and used to derive the key.
1432
+ *
1433
+ * If `options.ignoreExistingVault` is set to `true`, the existing
1434
+ * vault is completely ignored: the new key won't be able to decrypt
1435
+ * the existing vault, and should be used to re-encrypt it.
1436
+ *
1437
+ * @param password - The password to use for decryption or derivation.
1438
+ * @param options - Options for the key derivation.
1439
+ * @param options.ignoreExistingVault - Whether to ignore the existing vault salt and key metadata
1440
+ */
1441
+ async function _KeyringController_deriveAndSetEncryptionKey(password, options = {
1442
+ ignoreExistingVault: false,
1443
+ }) {
1444
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1445
+ const { vault } = this.state;
1446
+ if (typeof password !== 'string') {
1447
+ throw new TypeError(constants_js_1.KeyringControllerErrorMessage.WrongPasswordType);
1448
+ }
1449
+ let serializedEncryptionKey, salt;
1450
+ if (vault && !options.ignoreExistingVault) {
1451
+ // The `decryptWithDetail` method is being used here instead of
1452
+ // `keyFromPassword` + `exportKey` to let the encryptor handle
1453
+ // any legacy encryption formats and metadata that might be
1454
+ // present (or absent) in the vault.
1455
+ const { exportedKeyString, salt: existingSalt } = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithDetail(password, vault);
1456
+ serializedEncryptionKey = exportedKeyString;
1457
+ salt = existingSalt;
1458
+ }
1459
+ else {
1460
+ salt = __classPrivateFieldGet(this, _KeyringController_encryptor, "f").generateSalt();
1461
+ serializedEncryptionKey = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").exportKey(await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").keyFromPassword(password, salt, true));
1462
+ }
1463
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, {
1464
+ salt,
1465
+ serialized: serializedEncryptionKey,
1466
+ }, "f");
1467
+ }, _KeyringController_setEncryptionKey = function _KeyringController_setEncryptionKey(encryptionKey, keyDerivationSalt) {
1468
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1469
+ if (typeof encryptionKey !== 'string' ||
1470
+ typeof keyDerivationSalt !== 'string') {
1471
+ throw new TypeError(constants_js_1.KeyringControllerErrorMessage.WrongEncryptionKeyType);
1472
+ }
1473
+ const { vault } = this.state;
1474
+ if (vault && JSON.parse(vault).salt !== keyDerivationSalt) {
1475
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.ExpiredCredentials);
1476
+ }
1477
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, {
1478
+ salt: keyDerivationSalt,
1479
+ serialized: encryptionKey,
1480
+ }, "f");
1481
+ }, _KeyringController_verifySeedPhrase =
1482
+ /**
1483
+ * Internal non-exclusive method to verify the seed phrase.
1484
+ *
1485
+ * @param keyringId - The id of the keyring to verify the seed phrase for.
1486
+ * @returns A promise resolving to the seed phrase as Uint8Array.
1487
+ */
1488
+ async function _KeyringController_verifySeedPhrase(keyringId) {
1489
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1490
+ const keyring = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringByIdOrDefault).call(this, keyringId);
1491
+ if (!keyring) {
1492
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.KeyringNotFound);
1493
+ }
1494
+ if (keyring.type !== KeyringTypes.hd) {
1495
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.UnsupportedVerifySeedPhrase);
1496
+ }
1497
+ assertHasUint8ArrayMnemonic(keyring);
1498
+ const seedWords = keyring.mnemonic;
1499
+ const accounts = await keyring.getAccounts();
1500
+ /* istanbul ignore if */
1501
+ if (accounts.length === 0) {
1502
+ throw new errors_js_1.KeyringControllerError('Cannot verify an empty keyring.');
1503
+ }
1504
+ // The HD Keyring Builder is a default keyring builder
1505
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1506
+ const hdKeyringBuilder = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringBuilderForType).call(this, KeyringTypes.hd);
1507
+ const hdKeyring = hdKeyringBuilder();
1508
+ // @ts-expect-error @metamask/eth-hd-keyring correctly handles
1509
+ // Uint8Array seed phrases in the `deserialize` method.
1510
+ await hdKeyring.deserialize({
1511
+ mnemonic: seedWords,
1512
+ numberOfAccounts: accounts.length,
1513
+ });
1514
+ const testAccounts = await hdKeyring.getAccounts();
1515
+ /* istanbul ignore if */
1516
+ if (testAccounts.length !== accounts.length) {
1517
+ throw new errors_js_1.KeyringControllerError('Seed phrase imported incorrect number of accounts.');
1518
+ }
1519
+ testAccounts.forEach((account, i) => {
1520
+ /* istanbul ignore if */
1521
+ if (account.toLowerCase() !== accounts[i].toLowerCase()) {
1522
+ throw new errors_js_1.KeyringControllerError('Seed phrase imported different accounts.');
1523
+ }
1524
+ });
1525
+ return seedWords;
1526
+ }, _KeyringController_getUpdatedKeyrings =
1527
+ /**
1528
+ * Get the updated array of each keyring's type and
1529
+ * accounts list.
1530
+ *
1531
+ * @returns A promise resolving to the updated keyrings array.
1532
+ */
1533
+ async function _KeyringController_getUpdatedKeyrings() {
1534
+ return Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(displayForKeyring));
1535
+ }, _KeyringController_getSerializedKeyrings =
1536
+ /**
1537
+ * Serialize the current array of keyring instances,
1538
+ * including unsupported keyrings by default.
1539
+ *
1540
+ * @param options - Method options.
1541
+ * @param options.includeUnsupported - Whether to include unsupported keyrings.
1542
+ * @returns The serialized keyrings.
1543
+ */
1544
+ async function _KeyringController_getSerializedKeyrings({ includeUnsupported } = {
1545
+ includeUnsupported: true,
1546
+ }) {
1547
+ const serializedKeyrings = await Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(async ({ keyring, metadata }) => {
1548
+ return {
1549
+ type: keyring.type,
1550
+ data: await keyring.serialize(),
1551
+ metadata,
1552
+ };
1553
+ }));
1554
+ if (includeUnsupported) {
1555
+ serializedKeyrings.push(...__classPrivateFieldGet(this, _KeyringController_unsupportedKeyrings, "f"));
1556
+ }
1557
+ return serializedKeyrings;
1558
+ }, _KeyringController_getSessionState =
1559
+ /**
1560
+ * Get a snapshot of session data held by instance variables.
1561
+ *
1562
+ * @returns An object with serialized keyrings, keyrings metadata,
1563
+ * and the user password.
1564
+ */
1565
+ async function _KeyringController_getSessionState() {
1566
+ return {
1567
+ keyrings: await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this),
1568
+ encryptionKey: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f"),
1569
+ };
1570
+ }, _KeyringController_restoreSerializedKeyrings =
1571
+ /**
1572
+ * Restore a serialized keyrings array.
1573
+ *
1574
+ * @param serializedKeyrings - The serialized keyrings array.
1575
+ * @returns The restored keyrings.
1576
+ */
1577
+ async function _KeyringController_restoreSerializedKeyrings(serializedKeyrings) {
1578
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
1579
+ const keyrings = [];
1580
+ let hasChanged = false;
1581
+ for (const serializedKeyring of serializedKeyrings) {
1582
+ const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreKeyring).call(this, serializedKeyring);
1583
+ if (result) {
1584
+ const { keyring, metadata } = result;
1585
+ keyrings.push({ keyring, metadata });
1586
+ if (result.hasChanged) {
1587
+ hasChanged = true;
1588
+ }
1589
+ }
1590
+ }
1591
+ return { keyrings, hasChanged };
1592
+ }, _KeyringController_unlockKeyrings =
1593
+ /**
1594
+ * Unlock Keyrings, decrypting the vault and deserializing all
1595
+ * keyrings contained in it, using a password or an encryption key with salt.
1596
+ *
1597
+ * @param credentials - The credentials to unlock the keyrings.
1598
+ * @returns A promise resolving to the deserialized keyrings array.
1599
+ */
1600
+ async function _KeyringController_unlockKeyrings(credentials) {
1601
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
1602
+ if (!this.state.vault) {
1603
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.VaultError);
1604
+ }
1605
+ const parsedEncryptedVault = JSON.parse(this.state.vault);
1606
+ if ('password' in credentials) {
1607
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveAndSetEncryptionKey).call(this, credentials.password);
1608
+ }
1609
+ else {
1610
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setEncryptionKey).call(this, credentials.encryptionKey, credentials.encryptionSalt ?? parsedEncryptedVault.salt);
1611
+ }
1612
+ const encryptionKey = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")?.serialized;
1613
+ if (!encryptionKey) {
1614
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.MissingCredentials);
1615
+ }
1616
+ const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(encryptionKey);
1617
+ const vault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").decryptWithKey(key, parsedEncryptedVault);
1618
+ if (!isSerializedKeyringsArray(vault)) {
1619
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.VaultDataError);
1620
+ }
1621
+ const { keyrings, hasChanged } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreSerializedKeyrings).call(this, vault);
1622
+ const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
1623
+ this.update((state) => {
1624
+ state.keyrings = updatedKeyrings;
1625
+ state.encryptionKey = encryptionKey;
1626
+ state.encryptionSalt = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")?.salt;
1627
+ });
1628
+ return { keyrings, hasChanged };
1629
+ });
1630
+ }, _KeyringController_updateVault = function _KeyringController_updateVault() {
1631
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
1632
+ // Ensure no duplicate accounts are persisted.
1633
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoDuplicateAccounts).call(this);
1634
+ if (!__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")) {
1635
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.MissingCredentials);
1636
+ }
1637
+ const serializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
1638
+ if (!serializedKeyrings.some((keyring) => keyring.type === KeyringTypes.hd)) {
1639
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.NoHdKeyring);
1640
+ }
1641
+ const key = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").importKey(__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").serialized);
1642
+ const encryptedVault = await __classPrivateFieldGet(this, _KeyringController_encryptor, "f").encryptWithKey(key, serializedKeyrings);
1643
+ // We need to include the salt used to derive
1644
+ // the encryption key, to be able to derive it
1645
+ // from password again.
1646
+ encryptedVault.salt = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").salt;
1647
+ const updatedState = {
1648
+ vault: JSON.stringify(encryptedVault),
1649
+ encryptionKey: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").serialized,
1650
+ encryptionSalt: __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f").salt,
1651
+ };
1652
+ const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
1653
+ this.update((state) => {
1654
+ state.vault = updatedState.vault;
1655
+ state.keyrings = updatedKeyrings;
1656
+ state.encryptionKey = updatedState.encryptionKey;
1657
+ state.encryptionSalt = updatedState.encryptionSalt;
1658
+ });
1659
+ return true;
1660
+ });
1661
+ }, _KeyringController_isNewEncryptionAvailable = function _KeyringController_isNewEncryptionAvailable() {
1662
+ const { vault } = this.state;
1663
+ if (!vault || !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated) {
1664
+ return false;
1665
+ }
1666
+ return !__classPrivateFieldGet(this, _KeyringController_encryptor, "f").isVaultUpdated(vault);
1667
+ }, _KeyringController_getAccountsFromKeyrings =
1668
+ /**
1669
+ * Retrieves all the accounts from keyrings instances
1670
+ * that are currently in memory.
1671
+ *
1672
+ * @param additionalKeyrings - Additional keyrings to include in the search.
1673
+ * @returns A promise resolving to an array of accounts.
1674
+ */
1675
+ async function _KeyringController_getAccountsFromKeyrings(additionalKeyrings = []) {
1676
+ const keyrings = __classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(({ keyring }) => keyring);
1677
+ const keyringArrays = await Promise.all([...keyrings, ...additionalKeyrings].map(async (keyring) => keyring.getAccounts()));
1678
+ const addresses = keyringArrays.reduce((res, arr) => {
1679
+ return res.concat(arr);
1680
+ }, []);
1681
+ // Cast to `string[]` here is safe here because `addresses` has no nullish
1682
+ // values, and `normalize` returns `string` unless given a nullish value
1683
+ return addresses.map(normalize);
1684
+ }, _KeyringController_createKeyringWithFirstAccount =
1685
+ /**
1686
+ * Create a new keyring, ensuring that the first account is
1687
+ * also created.
1688
+ *
1689
+ * @param type - Keyring type to instantiate.
1690
+ * @param opts - Optional parameters required to instantiate the keyring.
1691
+ * @returns A promise that resolves if the operation is successful.
1692
+ */
1693
+ async function _KeyringController_createKeyringWithFirstAccount(type, opts) {
1694
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1695
+ const keyring = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, opts);
1696
+ const [firstAccount] = await keyring.getAccounts();
1697
+ if (!firstAccount) {
1698
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.NoFirstAccount);
1699
+ }
1700
+ return firstAccount;
1701
+ }, _KeyringController_newKeyring =
1702
+ /**
1703
+ * Instantiate, initialize and return a new keyring of the given `type`,
1704
+ * using the given `opts`. The keyring is built using the keyring builder
1705
+ * registered for the given `type`.
1706
+ *
1707
+ * The internal keyring and keyring metadata arrays are updated with the new
1708
+ * keyring as well.
1709
+ *
1710
+ * @param type - The type of keyring to add.
1711
+ * @param data - Keyring initialization options.
1712
+ * @returns The new keyring.
1713
+ * @throws If the keyring includes duplicated accounts.
1714
+ */
1715
+ async function _KeyringController_newKeyring(type, data) {
1716
+ const { keyring, keyringV2, metadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyring).call(this, type, data);
1717
+ __classPrivateFieldGet(this, _KeyringController_keyrings, "f").push({ keyring, keyringV2, metadata });
1718
+ return keyring;
1719
+ }, _KeyringController_createKeyring =
1720
+ /**
1721
+ * Instantiate, initialize and return a keyring of the given `type` using the
1722
+ * given `opts`. The keyring is built using the keyring builder registered
1723
+ * for the given `type`.
1724
+ *
1725
+ * The keyring might be new, or it might be restored from the vault. This
1726
+ * function should only be called from `#newKeyring` or `#restoreKeyring`,
1727
+ * for the "new" and "restore" cases respectively.
1728
+ *
1729
+ * The internal keyring and keyring metadata arrays are *not* updated, the
1730
+ * caller is expected to update them.
1731
+ *
1732
+ * @param type - The type of keyring to add.
1733
+ * @param data - Keyring initialization options.
1734
+ * @param metadata - Keyring metadata if available.
1735
+ * @returns The new keyring.
1736
+ * @throws If the keyring includes duplicated accounts.
1737
+ */
1738
+ async function _KeyringController_createKeyring(type, data, metadata) {
1739
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1740
+ const keyringMetadata = metadata ?? getDefaultKeyringMetadata();
1741
+ const keyringBuilder = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringBuilderForType).call(this, type);
1742
+ if (!keyringBuilder) {
1743
+ throw new errors_js_1.KeyringControllerError(`${constants_js_1.KeyringControllerErrorMessage.NoKeyringBuilder}. Keyring type: ${type}`);
1744
+ }
1745
+ const keyring = keyringBuilder();
1746
+ if (data) {
1747
+ // @ts-expect-error Enforce data type after updating clients
1748
+ await keyring.deserialize(data);
1749
+ }
1750
+ if (keyring.init) {
1751
+ await keyring.init();
1752
+ }
1753
+ if (type === KeyringTypes.hd &&
1754
+ (!(0, utils_1.isObject)(data) || !data.mnemonic)) {
1755
+ if (!keyring.generateRandomMnemonic) {
1756
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.UnsupportedGenerateRandomMnemonic);
1757
+ }
1758
+ // NOTE: Not all keyrings implement this method in a asynchronous-way. Using `await` for
1759
+ // non-thenable will still be valid (despite not being really useful). It allows us to cover both
1760
+ // cases and allow retro-compatibility too.
1761
+ await keyring.generateRandomMnemonic();
1762
+ await keyring.addAccounts(1);
1763
+ }
1764
+ // We now create the keyring V2 wrappers and store them in memory.
1765
+ const keyringBuilderV2 = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringV2BuilderForType).call(this, type);
1766
+ let keyringV2;
1767
+ if (keyringBuilderV2) {
1768
+ keyringV2 = keyringBuilderV2(keyring, keyringMetadata);
1769
+ }
1770
+ return { keyring, keyringV2, metadata: keyringMetadata };
1771
+ }, _KeyringController_cleanUpEmptiedKeyringsAfter =
1772
+ /**
1773
+ * Run the given operation and afterwards clean up any keyring whose
1774
+ * account list transitioned from non-empty to empty during the operation.
1775
+ *
1776
+ * This mirrors the cleanup behavior of {@link KeyringController.removeAccount}
1777
+ * for code paths where the consumer mutates a keyring directly via
1778
+ * {@link KeyringController.withKeyring} or
1779
+ * {@link KeyringController.withKeyringV2}: if the consumer drains the last
1780
+ * account from a keyring, the now-empty keyring is removed from
1781
+ * {@link KeyringController.#keyrings} and destroyed before persistence runs.
1782
+ *
1783
+ * Pre-existing empty keyrings (e.g. those created intentionally via
1784
+ * {@link KeyringController.addNewKeyring} without subsequent account
1785
+ * creation) are left alone, as are keyrings created within the operation
1786
+ * itself (they are not part of the pre-operation snapshot). The primary
1787
+ * keyring (see {@link KeyringController.#isPrimaryKeyring}) is also preserved
1788
+ * unconditionally to keep `removeAccount`'s primary-keyring invariant intact.
1789
+ *
1790
+ * @param operation - The operation to execute.
1791
+ * @returns The result of the operation.
1792
+ * @template Result - The type of the value resolved by the operation.
1793
+ */
1794
+ async function _KeyringController_cleanUpEmptiedKeyringsAfter(operation) {
1795
+ // Only the primary keyring exists, which is never auto-removed, so there
1796
+ // is nothing to clean up regardless of what the operation does.
1797
+ if (__classPrivateFieldGet(this, _KeyringController_keyrings, "f").length <= 1) {
1798
+ return operation();
1799
+ }
1800
+ const wasNonEmpty = new WeakSet();
1801
+ await Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(async ({ keyring }) => {
1802
+ if ((await keyring.getAccounts()).length > 0) {
1803
+ wasNonEmpty.add(keyring);
1804
+ }
1805
+ }));
1806
+ const result = await operation();
1807
+ const isNowEmpty = await Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(async ({ keyring }) => (await keyring.getAccounts()).length === 0));
1808
+ const emptied = __classPrivateFieldGet(this, _KeyringController_keyrings, "f").filter((entry, index) => !__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_isPrimaryKeyring).call(this, entry, __classPrivateFieldGet(this, _KeyringController_keyrings, "f")) &&
1809
+ wasNonEmpty.has(entry.keyring) &&
1810
+ isNowEmpty[index]);
1811
+ if (emptied.length > 0) {
1812
+ const removed = new Set(emptied);
1813
+ __classPrivateFieldSet(this, _KeyringController_keyrings, __classPrivateFieldGet(this, _KeyringController_keyrings, "f").filter((entry) => !removed.has(entry)), "f");
1814
+ await Promise.all(emptied.map(({ keyring, keyringV2 }) => __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_destroyKeyring).call(this, keyring, keyringV2)));
1815
+ }
1816
+ return result;
1817
+ }, _KeyringController_clearKeyrings =
1818
+ /**
1819
+ * Remove all managed keyrings, destroying all their
1820
+ * instances in memory.
1821
+ */
1822
+ async function _KeyringController_clearKeyrings() {
1823
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1824
+ for (const { keyring, keyringV2 } of __classPrivateFieldGet(this, _KeyringController_keyrings, "f")) {
1825
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_destroyKeyring).call(this, keyring, keyringV2);
1826
+ }
1827
+ __classPrivateFieldSet(this, _KeyringController_keyrings, [], "f");
1828
+ __classPrivateFieldSet(this, _KeyringController_unsupportedKeyrings, [], "f");
1829
+ }, _KeyringController_restoreKeyring =
1830
+ /**
1831
+ * Restore a Keyring from a provided serialized payload.
1832
+ * On success, returns the resulting keyring instance.
1833
+ *
1834
+ * @param serialized - The serialized keyring.
1835
+ * @returns The deserialized keyring or undefined if the keyring type is unsupported.
1836
+ */
1837
+ async function _KeyringController_restoreKeyring(serialized) {
1838
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1839
+ try {
1840
+ const { type, data, metadata: serializedMetadata } = serialized;
1841
+ // Track if we need to trigger a vault update.
1842
+ let hasChanged = false;
1843
+ // If metadata is missing, assume the data is from an installation before we had
1844
+ // keyring metadata.
1845
+ let metadata = serializedMetadata;
1846
+ if (!metadata) {
1847
+ hasChanged = true;
1848
+ metadata = getDefaultKeyringMetadata();
1849
+ }
1850
+ const oldState = JSON.stringify(data);
1851
+ const { keyring, keyringV2 } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyring).call(this, type, data, metadata);
1852
+ const newState = JSON.stringify(await keyring.serialize());
1853
+ hasChanged || (hasChanged = oldState !== newState);
1854
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoDuplicateAccounts).call(this, [keyring]);
1855
+ // The keyring is added to the keyrings array only if it's successfully restored
1856
+ // and the metadata is successfully added to the controller
1857
+ __classPrivateFieldGet(this, _KeyringController_keyrings, "f").push({
1858
+ keyring,
1859
+ keyringV2,
1860
+ metadata,
1861
+ });
1862
+ return { keyring, keyringV2, metadata, hasChanged };
1863
+ }
1864
+ catch (error) {
1865
+ console.error(error);
1866
+ __classPrivateFieldGet(this, _KeyringController_unsupportedKeyrings, "f").push(serialized);
1867
+ return undefined;
1868
+ }
1869
+ }, _KeyringController_destroyKeyring =
1870
+ /**
1871
+ * Destroy Keyring
1872
+ *
1873
+ * Some keyrings support a method called `destroy`, that destroys the
1874
+ * keyring along with removing all its event listeners and, in some cases,
1875
+ * clears the keyring bridge iframe from the DOM.
1876
+ *
1877
+ * @param keyring - The keyring to destroy.
1878
+ * @param keyringV2 - The keyring v2 to destroy (if any).
1879
+ */
1880
+ async function _KeyringController_destroyKeyring(keyring, keyringV2) {
1881
+ await keyring.destroy?.();
1882
+ if (keyringV2) {
1883
+ await keyringV2.destroy?.();
1884
+ }
1885
+ }, _KeyringController_assertNoDuplicateAccounts =
1886
+ /**
1887
+ * Assert that there are no duplicate accounts in the keyrings.
1888
+ *
1889
+ * @param additionalKeyrings - Additional keyrings to include in the check.
1890
+ * @throws If there are duplicate accounts.
1891
+ */
1892
+ async function _KeyringController_assertNoDuplicateAccounts(additionalKeyrings = []) {
1893
+ const accounts = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getAccountsFromKeyrings).call(this, additionalKeyrings);
1894
+ if (new Set(accounts).size !== accounts.length) {
1895
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.DuplicatedAccount);
1896
+ }
1897
+ }, _KeyringController_setUnlocked = function _KeyringController_setUnlocked() {
1898
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1899
+ this.update((state) => {
1900
+ state.isUnlocked = true;
1901
+ });
1902
+ this.messenger.publish(`${name}:unlock`);
1903
+ }, _KeyringController_assertIsUnlocked = function _KeyringController_assertIsUnlocked() {
1904
+ if (!this.state.isUnlocked) {
1905
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.ControllerLocked);
1906
+ }
1907
+ }, _KeyringController_persistOrRollback =
1908
+ /**
1909
+ * Execute the given function after acquiring the controller lock
1910
+ * and save the vault to state after it (only if needed), or rollback to their
1911
+ * previous state in case of error.
1912
+ *
1913
+ * @param callback - The function to execute.
1914
+ * @returns The result of the function.
1915
+ */
1916
+ async function _KeyringController_persistOrRollback(callback) {
1917
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async ({ releaseLock }) => {
1918
+ const oldState = JSON.stringify(await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSessionState).call(this));
1919
+ const callbackResult = await callback({ releaseLock });
1920
+ const newState = JSON.stringify(await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSessionState).call(this));
1921
+ // State is committed only if the operation is successful and need to trigger a vault update.
1922
+ if (oldState !== newState) {
1923
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
1924
+ }
1925
+ return callbackResult;
1926
+ });
1927
+ }, _KeyringController_withRollback =
1928
+ /**
1929
+ * Execute the given function after acquiring the controller lock
1930
+ * and rollback keyrings and password states in case of error.
1931
+ *
1932
+ * @param callback - The function to execute atomically.
1933
+ * @returns The result of the function.
1934
+ */
1935
+ async function _KeyringController_withRollback(callback) {
1936
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async ({ releaseLock }) => {
1937
+ const currentSerializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
1938
+ const currentEncryptionKey = (0, lodash_1.cloneDeep)(__classPrivateFieldGet(this, _KeyringController_encryptionKey, "f"));
1939
+ try {
1940
+ return await callback({ releaseLock });
1941
+ }
1942
+ catch (error) {
1943
+ // Keyrings and encryption credentials are restored to their previous state
1944
+ __classPrivateFieldSet(this, _KeyringController_encryptionKey, currentEncryptionKey, "f");
1945
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreSerializedKeyrings).call(this, currentSerializedKeyrings);
1946
+ throw error;
1947
+ }
1948
+ });
1949
+ }, _KeyringController_assertControllerMutexIsLocked = function _KeyringController_assertControllerMutexIsLocked() {
1950
+ if (!__classPrivateFieldGet(this, _KeyringController_controllerOperationMutex, "f").isLocked()) {
1951
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.ControllerLockRequired);
1952
+ }
1953
+ }, _KeyringController_isPrimaryKeyring = function _KeyringController_isPrimaryKeyring(entry, keyrings) {
1954
+ return (keyrings[0] === entry &&
1955
+ entry.keyring.type === KeyringTypes.hd);
1956
+ }, _KeyringController_assertNotRemovingPrimaryKeyring = function _KeyringController_assertNotRemovingPrimaryKeyring(entry, keyrings) {
1957
+ if (__classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_isPrimaryKeyring).call(this, entry, keyrings)) {
1958
+ throw new errors_js_1.KeyringControllerError(constants_js_1.KeyringControllerErrorMessage.CannotRemovePrimaryKeyring);
1959
+ }
1960
+ }, _KeyringController_withControllerLock =
1961
+ /**
1962
+ * Lock the controller mutex before executing the given function,
1963
+ * and release it after the function is resolved or after an
1964
+ * error is thrown.
1965
+ *
1966
+ * This wrapper ensures that each mutable operation that interacts with the
1967
+ * controller and that changes its state is executed in a mutually exclusive way,
1968
+ * preventing unsafe concurrent access that could lead to unpredictable behavior.
1969
+ *
1970
+ * @param callback - The function to execute while the controller mutex is locked.
1971
+ * @returns The result of the function.
1972
+ */
1973
+ async function _KeyringController_withControllerLock(callback) {
1974
+ return withLock(__classPrivateFieldGet(this, _KeyringController_controllerOperationMutex, "f"), callback);
1975
+ }, _KeyringController_withVaultLock =
1976
+ /**
1977
+ * Lock the vault mutex before executing the given function,
1978
+ * and release it after the function is resolved or after an
1979
+ * error is thrown.
1980
+ *
1981
+ * This ensures that each operation that interacts with the vault
1982
+ * is executed in a mutually exclusive way.
1983
+ *
1984
+ * @param callback - The function to execute while the vault mutex is locked.
1985
+ * @returns The result of the function.
1986
+ */
1987
+ async function _KeyringController_withVaultLock(callback) {
1988
+ __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1989
+ return withLock(__classPrivateFieldGet(this, _KeyringController_vaultOperationMutex, "f"), callback);
1990
+ };
1991
+ /**
1992
+ * Lock the given mutex before executing the given function,
1993
+ * and release it after the function is resolved or after an
1994
+ * error is thrown.
1995
+ *
1996
+ * @param mutex - The mutex to lock.
1997
+ * @param callback - The function to execute while the mutex is locked.
1998
+ * @returns The result of the function.
1999
+ */
2000
+ async function withLock(mutex, callback) {
2001
+ const releaseLock = await mutex.acquire();
2002
+ try {
2003
+ return await callback({ releaseLock });
2004
+ }
2005
+ finally {
2006
+ releaseLock();
2007
+ }
2008
+ }
2009
+ /**
2010
+ * Generate a new keyring metadata object.
2011
+ *
2012
+ * @returns Keyring metadata.
2013
+ */
2014
+ function getDefaultKeyringMetadata() {
2015
+ return { id: (0, ulid_1.ulid)(), name: '' };
2016
+ }
2017
+ exports.default = KeyringController;
2018
+ //# sourceMappingURL=KeyringController.cjs.map