@metamask-previews/keyring-controller 19.0.5-preview-d21875e1 → 19.0.5-preview-37653b42

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.
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _KeyringController_instances, _KeyringController_controllerOperationMutex, _KeyringController_vaultOperationMutex, _KeyringController_keyringBuilders, _KeyringController_unsupportedKeyrings, _KeyringController_encryptor, _KeyringController_cacheEncryptionKey, _KeyringController_keyrings, _KeyringController_password, _KeyringController_qrKeyringStateListener, _KeyringController_registerMessageHandlers, _KeyringController_getKeyringBuilderForType, _KeyringController_addQRKeyring, _KeyringController_subscribeToQRKeyringEvents, _KeyringController_unsubscribeFromQRKeyringsEvents, _KeyringController_createNewVaultWithKeyring, _KeyringController_verifySeedPhrase, _KeyringController_getUpdatedKeyrings, _KeyringController_getSerializedKeyrings, _KeyringController_restoreSerializedKeyrings, _KeyringController_unlockKeyrings, _KeyringController_updateVault, _KeyringController_getAccountsFromKeyrings, _KeyringController_createKeyringWithFirstAccount, _KeyringController_newKeyring, _KeyringController_clearKeyrings, _KeyringController_restoreKeyring, _KeyringController_destroyKeyring, _KeyringController_removeEmptyKeyrings, _KeyringController_checkForDuplicate, _KeyringController_setUnlocked, _KeyringController_persistOrRollback, _KeyringController_withRollback, _KeyringController_assertControllerMutexIsLocked, _KeyringController_withControllerLock, _KeyringController_withVaultLock;
12
+ var _KeyringController_instances, _KeyringController_controllerOperationMutex, _KeyringController_vaultOperationMutex, _KeyringController_keyringBuilders, _KeyringController_keyrings, _KeyringController_unsupportedKeyrings, _KeyringController_password, _KeyringController_encryptor, _KeyringController_cacheEncryptionKey, _KeyringController_qrKeyringStateListener, _KeyringController_registerMessageHandlers, _KeyringController_getKeyringBuilderForType, _KeyringController_addQRKeyring, _KeyringController_subscribeToQRKeyringEvents, _KeyringController_unsubscribeFromQRKeyringsEvents, _KeyringController_createNewVaultWithKeyring, _KeyringController_verifySeedPhrase, _KeyringController_getUpdatedKeyrings, _KeyringController_getSerializedKeyrings, _KeyringController_restoreSerializedKeyrings, _KeyringController_unlockKeyrings, _KeyringController_updateVault, _KeyringController_getAccountsFromKeyrings, _KeyringController_createKeyringWithFirstAccount, _KeyringController_newKeyring, _KeyringController_clearKeyrings, _KeyringController_restoreKeyring, _KeyringController_destroyKeyring, _KeyringController_removeEmptyKeyrings, _KeyringController_checkForDuplicate, _KeyringController_setUnlocked, _KeyringController_persistOrRollback, _KeyringController_withRollback, _KeyringController_assertControllerMutexIsLocked, _KeyringController_withControllerLock, _KeyringController_withVaultLock;
13
13
  function $importDefault(module) {
14
14
  if (module?.__esModule) {
15
15
  return module.default;
@@ -19,8 +19,7 @@ function $importDefault(module) {
19
19
  import { isValidPrivate, toBuffer, getBinarySize } from "@ethereumjs/util";
20
20
  import { BaseController } from "@metamask/base-controller";
21
21
  import * as encryptorUtils from "@metamask/browser-passworder";
22
- import $HDKeyring from "@metamask/eth-hd-keyring";
23
- const HDKeyring = $importDefault($HDKeyring);
22
+ import HDKeyring from "@metamask/eth-hd-keyring";
24
23
  import { normalize as ethNormalize } from "@metamask/eth-sig-util";
25
24
  import $SimpleKeyring from "@metamask/eth-simple-keyring";
26
25
  const SimpleKeyring = $importDefault($SimpleKeyring);
@@ -36,18 +35,31 @@ const name = 'KeyringController';
36
35
  */
37
36
  export var KeyringTypes;
38
37
  (function (KeyringTypes) {
38
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
39
+ // eslint-disable-next-line @typescript-eslint/naming-convention
39
40
  KeyringTypes["simple"] = "Simple Key Pair";
41
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
42
+ // eslint-disable-next-line @typescript-eslint/naming-convention
40
43
  KeyringTypes["hd"] = "HD Key Tree";
44
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
45
+ // eslint-disable-next-line @typescript-eslint/naming-convention
41
46
  KeyringTypes["qr"] = "QR Hardware Wallet Device";
47
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
48
+ // eslint-disable-next-line @typescript-eslint/naming-convention
42
49
  KeyringTypes["trezor"] = "Trezor Hardware";
50
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
51
+ // eslint-disable-next-line @typescript-eslint/naming-convention
43
52
  KeyringTypes["ledger"] = "Ledger Hardware";
53
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
54
+ // eslint-disable-next-line @typescript-eslint/naming-convention
44
55
  KeyringTypes["lattice"] = "Lattice Hardware";
56
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
57
+ // eslint-disable-next-line @typescript-eslint/naming-convention
45
58
  KeyringTypes["snap"] = "Snap Keyring";
46
59
  })(KeyringTypes || (KeyringTypes = {}));
47
60
  /**
48
61
  * Custody keyring types are a special case, as they are not a single type
49
62
  * but they all start with the prefix "Custody".
50
- *
51
63
  * @param keyringType - The type of the keyring.
52
64
  * @returns Whether the keyring type is a custody keyring.
53
65
  */
@@ -59,7 +71,11 @@ export const isCustodyKeyring = (keyringType) => {
59
71
  */
60
72
  export var AccountImportStrategy;
61
73
  (function (AccountImportStrategy) {
74
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
75
+ // eslint-disable-next-line @typescript-eslint/naming-convention
62
76
  AccountImportStrategy["privateKey"] = "privateKey";
77
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
78
+ // eslint-disable-next-line @typescript-eslint/naming-convention
63
79
  AccountImportStrategy["json"] = "json";
64
80
  })(AccountImportStrategy || (AccountImportStrategy = {}));
65
81
  /**
@@ -158,15 +174,35 @@ function isSerializedKeyringsArray(array) {
158
174
  * @param keyring - The keyring to display.
159
175
  * @returns A keyring display object, with type and accounts properties.
160
176
  */
161
- async function displayForKeyring(keyring) {
177
+ export async function displayForKeyring(keyring) {
162
178
  const accounts = await keyring.getAccounts();
163
179
  return {
164
180
  type: keyring.type,
165
181
  // Cast to `string[]` here is safe here because `accounts` has no nullish
166
182
  // values, and `normalize` returns `string` unless given a nullish value
167
183
  accounts: accounts.map(normalize),
184
+ // @ts-expect-error TODO: update type in @metamask/utils
185
+ fingerprint: await keyring?.getFingerprint?.(),
168
186
  };
169
187
  }
188
+ /**
189
+ * Retrieves a keyring from an array of keyrings based on its fingerprint.
190
+ *
191
+ * @param keyrings - Array of keyrings to search through.
192
+ * @param fingerprint - The fingerprint to match against.
193
+ * @returns Promise resolving to the matching keyring, or undefined if not found.
194
+ */
195
+ export async function getKeyringByFingerprint(keyrings, fingerprint) {
196
+ // Do not attempt to return a keyring if the fingerprint is not provided
197
+ if (!fingerprint) {
198
+ return undefined;
199
+ }
200
+ const fingerprints = await Promise.all(
201
+ // @ts-expect-error TODO: update type in @metamask/utils
202
+ keyrings.map((kr) => kr?.getFingerprint?.()));
203
+ const index = fingerprints.indexOf(fingerprint);
204
+ return keyrings[index];
205
+ }
170
206
  /**
171
207
  * Check if address is an ethereum address
172
208
  *
@@ -237,11 +273,11 @@ export class KeyringController extends BaseController {
237
273
  _KeyringController_controllerOperationMutex.set(this, new Mutex());
238
274
  _KeyringController_vaultOperationMutex.set(this, new Mutex());
239
275
  _KeyringController_keyringBuilders.set(this, void 0);
276
+ _KeyringController_keyrings.set(this, void 0);
240
277
  _KeyringController_unsupportedKeyrings.set(this, void 0);
278
+ _KeyringController_password.set(this, void 0);
241
279
  _KeyringController_encryptor.set(this, void 0);
242
280
  _KeyringController_cacheEncryptionKey.set(this, void 0);
243
- _KeyringController_keyrings.set(this, void 0);
244
- _KeyringController_password.set(this, void 0);
245
281
  _KeyringController_qrKeyringStateListener.set(this, void 0);
246
282
  __classPrivateFieldSet(this, _KeyringController_keyringBuilders, keyringBuilders
247
283
  ? keyringBuilders.concat(defaultKeyringBuilders)
@@ -343,7 +379,6 @@ export class KeyringController extends BaseController {
343
379
  * If there is a pre-existing locked vault, it will be replaced.
344
380
  *
345
381
  * @param password - Password to unlock the new vault.
346
- * @returns Promise resolving when the operation ends successfully.
347
382
  */
348
383
  async createNewVaultAndKeychain(password) {
349
384
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
@@ -393,12 +428,27 @@ export class KeyringController extends BaseController {
393
428
  * Gets the seed phrase of the HD keyring.
394
429
  *
395
430
  * @param password - Password of the keyring.
431
+ * @param keyringId - The keyring identifier.
396
432
  * @returns Promise resolving to the seed phrase.
397
433
  */
398
- async exportSeedPhrase(password) {
434
+ async exportSeedPhrase(password, keyringId) {
399
435
  await this.verifyPassword(password);
400
- assertHasUint8ArrayMnemonic(__classPrivateFieldGet(this, _KeyringController_keyrings, "f")[0]);
401
- return __classPrivateFieldGet(this, _KeyringController_keyrings, "f")[0].mnemonic;
436
+ let keyring;
437
+ if (keyringId) {
438
+ keyring = await getKeyringByFingerprint(__classPrivateFieldGet(this, _KeyringController_keyrings, "f"), keyringId);
439
+ if (!keyring) {
440
+ throw new Error(KeyringControllerError.KeyringNotFound);
441
+ }
442
+ if (keyring.type !== KeyringTypes.hd) {
443
+ throw new Error(KeyringControllerError.UnsupportedExportSeedPhrase);
444
+ }
445
+ }
446
+ else {
447
+ // There will always be an HD keyring
448
+ keyring = this.getKeyringsByType(KeyringTypes.hd)[0];
449
+ }
450
+ assertHasUint8ArrayMnemonic(keyring);
451
+ return keyring.mnemonic;
402
452
  }
403
453
  /**
404
454
  * Gets the private key from the keyring controlling an address.
@@ -524,7 +574,7 @@ export class KeyringController extends BaseController {
524
574
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
525
575
  let privateKey;
526
576
  switch (strategy) {
527
- case AccountImportStrategy.privateKey:
577
+ case 'privateKey':
528
578
  const [importedKey] = args;
529
579
  if (!importedKey) {
530
580
  throw new Error('Cannot import an empty key.');
@@ -544,7 +594,7 @@ export class KeyringController extends BaseController {
544
594
  }
545
595
  privateKey = remove0x(prefixed);
546
596
  break;
547
- case AccountImportStrategy.json:
597
+ case 'json':
548
598
  let wallet;
549
599
  const [input, password] = args;
550
600
  try {
@@ -556,7 +606,7 @@ export class KeyringController extends BaseController {
556
606
  privateKey = bytesToHex(wallet.getPrivateKey());
557
607
  break;
558
608
  default:
559
- throw new Error(`Unexpected import strategy: '${String(strategy)}'`);
609
+ throw new Error(`Unexpected import strategy: '${strategy}'`);
560
610
  }
561
611
  const newKeyring = (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, KeyringTypes.simple, [
562
612
  privateKey,
@@ -581,6 +631,7 @@ export class KeyringController extends BaseController {
581
631
  }
582
632
  // The `removeAccount` method of snaps keyring is async. We have to update
583
633
  // the interface of the other keyrings to be async as well.
634
+ // eslint-disable-next-line @typescript-eslint/await-thenable
584
635
  // FIXME: We do cast to `Hex` to makes the type checker happy here, and
585
636
  // because `Keyring<State>.removeAccount` requires address to be `Hex`. Those
586
637
  // type would need to be updated for a full non-EVM support.
@@ -811,6 +862,9 @@ export class KeyringController extends BaseController {
811
862
  if ('address' in selector) {
812
863
  keyring = (await this.getKeyringForAccount(selector.address));
813
864
  }
865
+ else if ('fingerprint' in selector) {
866
+ keyring = (await getKeyringByFingerprint(__classPrivateFieldGet(this, _KeyringController_keyrings, "f"), selector.fingerprint));
867
+ }
814
868
  else {
815
869
  keyring = this.getKeyringsByType(selector.type)[selector.index || 0];
816
870
  if (!keyring && options.createIfMissing) {
@@ -1015,7 +1069,7 @@ export class KeyringController extends BaseController {
1015
1069
  });
1016
1070
  }
1017
1071
  }
1018
- _KeyringController_controllerOperationMutex = new WeakMap(), _KeyringController_vaultOperationMutex = new WeakMap(), _KeyringController_keyringBuilders = new WeakMap(), _KeyringController_unsupportedKeyrings = new WeakMap(), _KeyringController_encryptor = new WeakMap(), _KeyringController_cacheEncryptionKey = new WeakMap(), _KeyringController_keyrings = new WeakMap(), _KeyringController_password = new WeakMap(), _KeyringController_qrKeyringStateListener = new WeakMap(), _KeyringController_instances = new WeakSet(), _KeyringController_registerMessageHandlers = function _KeyringController_registerMessageHandlers() {
1072
+ _KeyringController_controllerOperationMutex = new WeakMap(), _KeyringController_vaultOperationMutex = new WeakMap(), _KeyringController_keyringBuilders = new WeakMap(), _KeyringController_keyrings = new WeakMap(), _KeyringController_unsupportedKeyrings = new WeakMap(), _KeyringController_password = new WeakMap(), _KeyringController_encryptor = new WeakMap(), _KeyringController_cacheEncryptionKey = new WeakMap(), _KeyringController_qrKeyringStateListener = new WeakMap(), _KeyringController_instances = new WeakSet(), _KeyringController_registerMessageHandlers = function _KeyringController_registerMessageHandlers() {
1019
1073
  this.messagingSystem.registerActionHandler(`${name}:signMessage`, this.signMessage.bind(this));
1020
1074
  this.messagingSystem.registerActionHandler(`${name}:signPersonalMessage`, this.signPersonalMessage.bind(this));
1021
1075
  this.messagingSystem.registerActionHandler(`${name}:signTypedMessage`, this.signTypedMessage.bind(this));
@@ -1350,6 +1404,9 @@ async function _KeyringController_newKeyring(type, data) {
1350
1404
  // NOTE: Not all keyrings implement this method in a asynchronous-way. Using `await` for
1351
1405
  // non-thenable will still be valid (despite not being really useful). It allows us to cover both
1352
1406
  // cases and allow retro-compatibility too.
1407
+ // FIXME: For some reason, it seems that eslint is complaining about this call being non-thenable
1408
+ // even though it is... For now, we just disable it:
1409
+ // eslint-disable-next-line @typescript-eslint/await-thenable
1353
1410
  await keyring.generateRandomMnemonic();
1354
1411
  await keyring.addAccounts(1);
1355
1412
  }
@@ -1464,12 +1521,14 @@ async function _KeyringController_checkForDuplicate(type, newAccountArray) {
1464
1521
  * and save the keyrings to state after it, or rollback to their
1465
1522
  * previous state in case of error.
1466
1523
  *
1467
- * @param callback - The function to execute.
1524
+ * @param fn - The function to execute.
1468
1525
  * @returns The result of the function.
1469
1526
  */
1470
- async function _KeyringController_persistOrRollback(callback) {
1527
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
1528
+ // eslint-disable-next-line @typescript-eslint/naming-convention
1529
+ async function _KeyringController_persistOrRollback(fn) {
1471
1530
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async ({ releaseLock }) => {
1472
- const callbackResult = await callback({ releaseLock });
1531
+ const callbackResult = await fn({ releaseLock });
1473
1532
  // State is committed only if the operation is successful
1474
1533
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
1475
1534
  return callbackResult;
@@ -1479,15 +1538,17 @@ async function _KeyringController_persistOrRollback(callback) {
1479
1538
  * Execute the given function after acquiring the controller lock
1480
1539
  * and rollback keyrings and password states in case of error.
1481
1540
  *
1482
- * @param callback - The function to execute atomically.
1541
+ * @param fn - The function to execute atomically.
1483
1542
  * @returns The result of the function.
1484
1543
  */
1485
- async function _KeyringController_withRollback(callback) {
1544
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
1545
+ // eslint-disable-next-line @typescript-eslint/naming-convention
1546
+ async function _KeyringController_withRollback(fn) {
1486
1547
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async ({ releaseLock }) => {
1487
1548
  const currentSerializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
1488
1549
  const currentPassword = __classPrivateFieldGet(this, _KeyringController_password, "f");
1489
1550
  try {
1490
- return await callback({ releaseLock });
1551
+ return await fn({ releaseLock });
1491
1552
  }
1492
1553
  catch (e) {
1493
1554
  // Keyrings and password are restored to their previous state
@@ -1510,11 +1571,13 @@ async function _KeyringController_withRollback(callback) {
1510
1571
  * controller and that changes its state is executed in a mutually exclusive way,
1511
1572
  * preventing unsafe concurrent access that could lead to unpredictable behavior.
1512
1573
  *
1513
- * @param callback - The function to execute while the controller mutex is locked.
1574
+ * @param fn - The function to execute while the controller mutex is locked.
1514
1575
  * @returns The result of the function.
1515
1576
  */
1516
- async function _KeyringController_withControllerLock(callback) {
1517
- return withLock(__classPrivateFieldGet(this, _KeyringController_controllerOperationMutex, "f"), callback);
1577
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
1578
+ // eslint-disable-next-line @typescript-eslint/naming-convention
1579
+ async function _KeyringController_withControllerLock(fn) {
1580
+ return withLock(__classPrivateFieldGet(this, _KeyringController_controllerOperationMutex, "f"), fn);
1518
1581
  }, _KeyringController_withVaultLock =
1519
1582
  /**
1520
1583
  * Lock the vault mutex before executing the given function,
@@ -1524,12 +1587,14 @@ async function _KeyringController_withControllerLock(callback) {
1524
1587
  * This ensures that each operation that interacts with the vault
1525
1588
  * is executed in a mutually exclusive way.
1526
1589
  *
1527
- * @param callback - The function to execute while the vault mutex is locked.
1590
+ * @param fn - The function to execute while the vault mutex is locked.
1528
1591
  * @returns The result of the function.
1529
1592
  */
1530
- async function _KeyringController_withVaultLock(callback) {
1593
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
1594
+ // eslint-disable-next-line @typescript-eslint/naming-convention
1595
+ async function _KeyringController_withVaultLock(fn) {
1531
1596
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1532
- return withLock(__classPrivateFieldGet(this, _KeyringController_vaultOperationMutex, "f"), callback);
1597
+ return withLock(__classPrivateFieldGet(this, _KeyringController_vaultOperationMutex, "f"), fn);
1533
1598
  };
1534
1599
  /**
1535
1600
  * Lock the given mutex before executing the given function,
@@ -1537,13 +1602,15 @@ async function _KeyringController_withVaultLock(callback) {
1537
1602
  * error is thrown.
1538
1603
  *
1539
1604
  * @param mutex - The mutex to lock.
1540
- * @param callback - The function to execute while the mutex is locked.
1605
+ * @param fn - The function to execute while the mutex is locked.
1541
1606
  * @returns The result of the function.
1542
1607
  */
1543
- async function withLock(mutex, callback) {
1608
+ // TODO: Either fix this lint violation or explain why it's necessary to ignore.
1609
+ // eslint-disable-next-line @typescript-eslint/naming-convention
1610
+ async function withLock(mutex, fn) {
1544
1611
  const releaseLock = await mutex.acquire();
1545
1612
  try {
1546
- return await callback({ releaseLock });
1613
+ return await fn({ releaseLock });
1547
1614
  }
1548
1615
  finally {
1549
1616
  releaseLock();