@metamask-previews/keyring-controller 19.0.3-preview-5b0a5fea → 19.0.3-preview-83c8a21

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.
@@ -36,7 +36,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
36
36
  var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  return (mod && mod.__esModule) ? mod : { "default": mod };
38
38
  };
39
- var _KeyringController_instances, _KeyringController_controllerOperationMutex, _KeyringController_vaultOperationMutex, _KeyringController_keyringBuilders, _KeyringController_keyrings, _KeyringController_unsupportedKeyrings, _KeyringController_password, _KeyringController_encryptor, _KeyringController_cacheEncryptionKey, _KeyringController_qrKeyringStateListener, _KeyringController_registerMessageHandlers, _KeyringController_getKeyringBuilderForType, _KeyringController_addQRKeyring, _KeyringController_subscribeToQRKeyringEvents, _KeyringController_unsubscribeFromQRKeyringsEvents, _KeyringController_createNewVaultWithKeyring, _KeyringController_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;
39
+ var _KeyringController_instances, _KeyringController_controllerOperationMutex, _KeyringController_vaultOperationMutex, _KeyringController_keyringBuilders, _KeyringController_keyrings, _KeyringController_unsupportedKeyrings, _KeyringController_password, _KeyringController_encryptor, _KeyringController_cacheEncryptionKey, _KeyringController_qrKeyringStateListener, _KeyringController_registerMessageHandlers, _KeyringController_getKeyringById, _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;
40
40
  Object.defineProperty(exports, "__esModule", { value: true });
41
41
  exports.KeyringController = exports.getDefaultKeyringState = exports.keyringBuilderFactory = exports.SignTypedDataVersion = exports.AccountImportStrategy = exports.isCustodyKeyring = exports.KeyringTypes = void 0;
42
42
  const util_1 = require("@ethereumjs/util");
@@ -48,7 +48,10 @@ const eth_simple_keyring_1 = __importDefault(require("@metamask/eth-simple-keyri
48
48
  const utils_1 = require("@metamask/utils");
49
49
  const async_mutex_1 = require("async-mutex");
50
50
  const ethereumjs_wallet_1 = __importStar(require("ethereumjs-wallet"));
51
+ // When generating a ULID within the same millisecond, monotonicFactory provides some guarantees regarding sort order.
52
+ const ulid_1 = require("ulid");
51
53
  const constants_1 = require("./constants.cjs");
54
+ const ulid = (0, ulid_1.monotonicFactory)();
52
55
  const name = 'KeyringController';
53
56
  /**
54
57
  * Available keyring types
@@ -132,6 +135,7 @@ const getDefaultKeyringState = () => {
132
135
  return {
133
136
  isUnlocked: false,
134
137
  keyrings: [],
138
+ keyringsMetadata: [],
135
139
  };
136
140
  };
137
141
  exports.getDefaultKeyringState = getDefaultKeyringState;
@@ -263,6 +267,7 @@ class KeyringController extends base_controller_1.BaseController {
263
267
  vault: { persist: true, anonymous: false },
264
268
  isUnlocked: { persist: false, anonymous: true },
265
269
  keyrings: { persist: false, anonymous: false },
270
+ keyringsMetadata: { persist: true, anonymous: false },
266
271
  encryptionKey: { persist: false, anonymous: false },
267
272
  encryptionSalt: { persist: false, anonymous: false },
268
273
  },
@@ -300,16 +305,20 @@ class KeyringController extends base_controller_1.BaseController {
300
305
  * Adds a new account to the default (first) HD seed phrase keyring.
301
306
  *
302
307
  * @param accountCount - Number of accounts before adding a new one, used to
308
+ * @param keyringId - The id of the keyring to add the account to.
303
309
  * make the method idempotent.
304
310
  * @returns Promise resolving to the added account address.
305
311
  */
306
- async addNewAccount(accountCount) {
312
+ async addNewAccount(accountCount, keyringId) {
307
313
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
308
- const primaryKeyring = this.getKeyringsByType('HD Key Tree')[0];
309
- if (!primaryKeyring) {
314
+ let selectedKeyring = this.getKeyringsByType('HD Key Tree')[0];
315
+ if (keyringId) {
316
+ selectedKeyring = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringById).call(this, keyringId);
317
+ }
318
+ if (!selectedKeyring) {
310
319
  throw new Error('No HD keyring found');
311
320
  }
312
- const oldAccounts = await primaryKeyring.getAccounts();
321
+ const oldAccounts = await selectedKeyring.getAccounts();
313
322
  if (accountCount && oldAccounts.length !== accountCount) {
314
323
  if (accountCount > oldAccounts.length) {
315
324
  throw new Error('Account out of sequence');
@@ -321,8 +330,8 @@ class KeyringController extends base_controller_1.BaseController {
321
330
  }
322
331
  return existingAccount;
323
332
  }
324
- const [addedAccountAddress] = await primaryKeyring.addAccounts(1);
325
- await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_verifySeedPhrase).call(this);
333
+ const [addedAccountAddress] = await selectedKeyring.addAccounts(1);
334
+ await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_verifySeedPhrase).call(this, keyringId);
326
335
  return addedAccountAddress;
327
336
  });
328
337
  }
@@ -405,7 +414,7 @@ class KeyringController extends base_controller_1.BaseController {
405
414
  if (type === KeyringTypes.qr) {
406
415
  return this.getOrAddQRKeyring();
407
416
  }
408
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, opts));
417
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, opts, { id: ulid(), name: '' }));
409
418
  }
410
419
  /**
411
420
  * Method to verify a given password validity. Throws an
@@ -431,12 +440,21 @@ class KeyringController extends base_controller_1.BaseController {
431
440
  * Gets the seed phrase of the HD keyring.
432
441
  *
433
442
  * @param password - Password of the keyring.
443
+ * @param keyringId - The id of the keyring.
434
444
  * @returns Promise resolving to the seed phrase.
435
445
  */
436
- async exportSeedPhrase(password) {
446
+ async exportSeedPhrase(password, keyringId) {
437
447
  await this.verifyPassword(password);
438
- assertHasUint8ArrayMnemonic(__classPrivateFieldGet(this, _KeyringController_keyrings, "f")[0]);
439
- return __classPrivateFieldGet(this, _KeyringController_keyrings, "f")[0].mnemonic;
448
+ if (!keyringId) {
449
+ assertHasUint8ArrayMnemonic(__classPrivateFieldGet(this, _KeyringController_keyrings, "f")[0]);
450
+ return __classPrivateFieldGet(this, _KeyringController_keyrings, "f")[0].mnemonic;
451
+ }
452
+ const selectedKeyring = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringById).call(this, keyringId);
453
+ if (!selectedKeyring) {
454
+ throw new Error('Keyring not found');
455
+ }
456
+ assertHasUint8ArrayMnemonic(selectedKeyring);
457
+ return selectedKeyring.mnemonic;
440
458
  }
441
459
  /**
442
460
  * Gets the private key from the keyring controlling an address.
@@ -456,9 +474,18 @@ class KeyringController extends base_controller_1.BaseController {
456
474
  /**
457
475
  * Returns the public addresses of all accounts from every keyring.
458
476
  *
477
+ * @param keyringId - The id of the keyring to get the accounts from.
459
478
  * @returns A promise resolving to an array of addresses.
460
479
  */
461
- async getAccounts() {
480
+ async getAccounts(keyringId) {
481
+ if (keyringId) {
482
+ const keyringIndex = this.state.keyringsMetadata.findIndex((keyring) => keyring.id === keyringId);
483
+ const keyring = this.state.keyrings[keyringIndex];
484
+ if (!keyring) {
485
+ throw new Error('Keyring not found');
486
+ }
487
+ return keyring.accounts;
488
+ }
462
489
  return this.state.keyrings.reduce((accounts, keyring) => accounts.concat(keyring.accounts), []);
463
490
  }
464
491
  /**
@@ -598,7 +625,7 @@ class KeyringController extends base_controller_1.BaseController {
598
625
  }
599
626
  const newKeyring = (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, KeyringTypes.simple, [
600
627
  privateKey,
601
- ]));
628
+ ], { id: ulid(), name: '' }));
602
629
  const accounts = await newKeyring.getAccounts();
603
630
  return accounts[0];
604
631
  });
@@ -837,10 +864,11 @@ class KeyringController extends base_controller_1.BaseController {
837
864
  /**
838
865
  * Verifies the that the seed phrase restores the current keychain's accounts.
839
866
  *
867
+ * @param keyringId - The id of the keyring to verify.
840
868
  * @returns Promise resolving to the seed phrase as Uint8Array.
841
869
  */
842
- async verifySeedPhrase() {
843
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async () => __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_verifySeedPhrase).call(this));
870
+ async verifySeedPhrase(keyringId) {
871
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async () => __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_verifySeedPhrase).call(this, keyringId));
844
872
  }
845
873
  async withKeyring(selector, operation, options = {
846
874
  createIfMissing: false,
@@ -850,12 +878,16 @@ class KeyringController extends base_controller_1.BaseController {
850
878
  if ('address' in selector) {
851
879
  keyring = (await this.getKeyringForAccount(selector.address));
852
880
  }
853
- else {
881
+ else if ('type' in selector) {
854
882
  keyring = this.getKeyringsByType(selector.type)[selector.index || 0];
855
883
  if (!keyring && options.createIfMissing) {
856
- keyring = (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, selector.type, options.createWithData));
884
+ const newMetadata = { id: ulid(), name: '' };
885
+ keyring = (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, selector.type, options.createWithData, newMetadata));
857
886
  }
858
887
  }
888
+ else if ('id' in selector) {
889
+ keyring = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringById).call(this, selector.id);
890
+ }
859
891
  if (!keyring) {
860
892
  throw new Error(constants_1.KeyringControllerError.KeyringNotFound);
861
893
  }
@@ -1069,6 +1101,9 @@ _KeyringController_controllerOperationMutex = new WeakMap(), _KeyringController_
1069
1101
  this.messagingSystem.registerActionHandler(`${name}:patchUserOperation`, this.patchUserOperation.bind(this));
1070
1102
  this.messagingSystem.registerActionHandler(`${name}:signUserOperation`, this.signUserOperation.bind(this));
1071
1103
  this.messagingSystem.registerActionHandler(`${name}:addNewAccount`, this.addNewAccount.bind(this));
1104
+ }, _KeyringController_getKeyringById = function _KeyringController_getKeyringById(keyringId) {
1105
+ const index = this.state.keyringsMetadata.findIndex((metadata) => metadata.id === keyringId);
1106
+ return __classPrivateFieldGet(this, _KeyringController_keyrings, "f")[index];
1072
1107
  }, _KeyringController_getKeyringBuilderForType = function _KeyringController_getKeyringBuilderForType(type) {
1073
1108
  return __classPrivateFieldGet(this, _KeyringController_keyringBuilders, "f").find((keyringBuilder) => keyringBuilder.type === type);
1074
1109
  }, _KeyringController_addQRKeyring =
@@ -1082,7 +1117,10 @@ _KeyringController_controllerOperationMutex = new WeakMap(), _KeyringController_
1082
1117
  async function _KeyringController_addQRKeyring() {
1083
1118
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1084
1119
  // QRKeyring is not yet compatible with Keyring type from @metamask/utils
1085
- return (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, KeyringTypes.qr));
1120
+ return (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, KeyringTypes.qr, undefined, {
1121
+ id: ulid(),
1122
+ name: '',
1123
+ }));
1086
1124
  }, _KeyringController_subscribeToQRKeyringEvents = function _KeyringController_subscribeToQRKeyringEvents(qrKeyring) {
1087
1125
  __classPrivateFieldSet(this, _KeyringController_qrKeyringStateListener, (state) => {
1088
1126
  this.messagingSystem.publish(`${name}:qrKeyringStateChange`, state);
@@ -1127,17 +1165,20 @@ async function _KeyringController_createNewVaultWithKeyring(password, keyring) {
1127
1165
  /**
1128
1166
  * Internal non-exclusive method to verify the seed phrase.
1129
1167
  *
1168
+ * @param keyringId - The id of the keyring to verify the seed phrase for.
1130
1169
  * @returns A promise resolving to the seed phrase as Uint8Array.
1131
1170
  */
1132
- async function _KeyringController_verifySeedPhrase() {
1171
+ async function _KeyringController_verifySeedPhrase(keyringId) {
1133
1172
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1134
- const primaryKeyring = this.getKeyringsByType(KeyringTypes.hd)[0];
1135
- if (!primaryKeyring) {
1173
+ const keyring = keyringId
1174
+ ? __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringById).call(this, keyringId)
1175
+ : this.getKeyringsByType(KeyringTypes.hd)[0];
1176
+ if (!keyring) {
1136
1177
  throw new Error('No HD keyring found.');
1137
1178
  }
1138
- assertHasUint8ArrayMnemonic(primaryKeyring);
1139
- const seedWords = primaryKeyring.mnemonic;
1140
- const accounts = await primaryKeyring.getAccounts();
1179
+ assertHasUint8ArrayMnemonic(keyring);
1180
+ const seedWords = keyring.mnemonic;
1181
+ const accounts = await keyring.getAccounts();
1141
1182
  /* istanbul ignore if */
1142
1183
  if (accounts.length === 0) {
1143
1184
  throw new Error('Cannot verify an empty keyring.');
@@ -1185,7 +1226,7 @@ async function _KeyringController_getUpdatedKeyrings() {
1185
1226
  async function _KeyringController_getSerializedKeyrings({ includeUnsupported } = {
1186
1227
  includeUnsupported: true,
1187
1228
  }) {
1188
- const serializedKeyrings = await Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(async (keyring) => {
1229
+ const serializedKeyrings = await Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(async (keyring, index) => {
1189
1230
  const [type, data] = await Promise.all([
1190
1231
  keyring.type,
1191
1232
  keyring.serialize(),
@@ -1207,6 +1248,12 @@ async function _KeyringController_restoreSerializedKeyrings(serializedKeyrings)
1207
1248
  for (const serializedKeyring of serializedKeyrings) {
1208
1249
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreKeyring).call(this, serializedKeyring);
1209
1250
  }
1251
+ if (this.state.keyringsMetadata.length > __classPrivateFieldGet(this, _KeyringController_keyrings, "f").length) {
1252
+ this.update((state) => {
1253
+ // remove metadata from the end of the array to have the same length as the keyrings array
1254
+ state.keyringsMetadata = state.keyringsMetadata.slice(0, -1 * (state.keyringsMetadata.length - __classPrivateFieldGet(this, _KeyringController_keyrings, "f").length));
1255
+ });
1256
+ }
1210
1257
  }, _KeyringController_unlockKeyrings =
1211
1258
  /**
1212
1259
  * Unlock Keyrings, decrypting the vault and deserializing all
@@ -1324,6 +1371,9 @@ async function _KeyringController_unlockKeyrings(password, encryptionKey, encryp
1324
1371
  state.encryptionKey = updatedState.encryptionKey;
1325
1372
  state.encryptionSalt = JSON.parse(updatedState.vault).salt;
1326
1373
  }
1374
+ if (updatedKeyrings.length < state.keyringsMetadata.length) {
1375
+ state.keyringsMetadata = state.keyringsMetadata.slice(0, -1 * (state.keyringsMetadata.length - updatedKeyrings.length));
1376
+ }
1327
1377
  });
1328
1378
  return true;
1329
1379
  });
@@ -1354,11 +1404,15 @@ async function _KeyringController_getAccountsFromKeyrings() {
1354
1404
  */
1355
1405
  async function _KeyringController_createKeyringWithFirstAccount(type, opts) {
1356
1406
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1357
- const keyring = (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, opts));
1407
+ const keyring = (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, opts, {
1408
+ id: ulid(),
1409
+ name: '',
1410
+ }));
1358
1411
  const [firstAccount] = await keyring.getAccounts();
1359
1412
  if (!firstAccount) {
1360
1413
  throw new Error(constants_1.KeyringControllerError.NoFirstAccount);
1361
1414
  }
1415
+ return firstAccount;
1362
1416
  }, _KeyringController_newKeyring =
1363
1417
  /**
1364
1418
  * Instantiate, initialize and return a new keyring of the given `type`,
@@ -1368,10 +1422,11 @@ async function _KeyringController_createKeyringWithFirstAccount(type, opts) {
1368
1422
  *
1369
1423
  * @param type - The type of keyring to add.
1370
1424
  * @param data - The data to restore a previously serialized keyring.
1425
+ * @param metadata - The metadata to add to the keyring.
1371
1426
  * @returns The new keyring.
1372
1427
  * @throws If the keyring includes duplicated accounts.
1373
1428
  */
1374
- async function _KeyringController_newKeyring(type, data) {
1429
+ async function _KeyringController_newKeyring(type, data, metadata) {
1375
1430
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1376
1431
  const keyringBuilder = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringBuilderForType).call(this, type);
1377
1432
  if (!keyringBuilder) {
@@ -1403,6 +1458,11 @@ async function _KeyringController_newKeyring(type, data) {
1403
1458
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_subscribeToQRKeyringEvents).call(this, keyring);
1404
1459
  }
1405
1460
  __classPrivateFieldGet(this, _KeyringController_keyrings, "f").push(keyring);
1461
+ if (metadata && this.state.keyringsMetadata.length < __classPrivateFieldGet(this, _KeyringController_keyrings, "f").length) {
1462
+ this.update((state) => {
1463
+ state.keyringsMetadata = [...state.keyringsMetadata, metadata];
1464
+ });
1465
+ }
1406
1466
  return keyring;
1407
1467
  }, _KeyringController_clearKeyrings =
1408
1468
  /**
@@ -1458,7 +1518,7 @@ async function _KeyringController_removeEmptyKeyrings() {
1458
1518
  // Since getAccounts returns a Promise
1459
1519
  // We need to wait to hear back form each keyring
1460
1520
  // in order to decide which ones are now valid (accounts.length > 0)
1461
- await Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(async (keyring) => {
1521
+ await Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(async (keyring, index) => {
1462
1522
  const accounts = await keyring.getAccounts();
1463
1523
  if (accounts.length > 0) {
1464
1524
  validKeyrings.push(keyring);