@metamask-previews/keyring-controller 19.1.0-preview-ea165590 → 19.1.0-preview-7a21cbc

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_assertIsUnlocked, _KeyringController_persistOrRollback, _KeyringController_withRollback, _KeyringController_assertControllerMutexIsLocked, _KeyringController_withControllerLock, _KeyringController_withVaultLock;
12
+ var _KeyringController_instances, _KeyringController_controllerOperationMutex, _KeyringController_vaultOperationMutex, _KeyringController_keyringBuilders, _KeyringController_unsupportedKeyrings, _KeyringController_encryptor, _KeyringController_cacheEncryptionKey, _KeyringController_keyrings, _KeyringController_keyringsMetadata, _KeyringController_password, _KeyringController_qrKeyringStateListener, _KeyringController_registerMessageHandlers, _KeyringController_getKeyringById, _KeyringController_getKeyringByIdOrDefault, _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_createKeyring, _KeyringController_clearKeyrings, _KeyringController_restoreKeyring, _KeyringController_destroyKeyring, _KeyringController_removeEmptyKeyrings, _KeyringController_checkForDuplicate, _KeyringController_setUnlocked, _KeyringController_assertIsUnlocked, _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,16 +19,16 @@ 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
- import $SimpleKeyring from "@metamask/eth-simple-keyring";
26
- const SimpleKeyring = $importDefault($SimpleKeyring);
24
+ import SimpleKeyring from "@metamask/eth-simple-keyring";
27
25
  import { add0x, assertIsStrictHexString, bytesToHex, hasProperty, isObject, isStrictHexString, isValidHexAddress, isValidJson, remove0x } from "@metamask/utils";
28
26
  import { Mutex } from "async-mutex";
29
27
  import $Wallet from "ethereumjs-wallet";
30
28
  const { thirdparty: importers } = $Wallet;
31
29
  const Wallet = $importDefault($Wallet);
30
+ // When generating a ULID within the same millisecond, monotonicFactory provides some guarantees regarding sort order.
31
+ import { ulid } from "ulid";
32
32
  import { KeyringControllerError } from "./constants.mjs";
33
33
  const name = 'KeyringController';
34
34
  /**
@@ -88,13 +88,17 @@ export function keyringBuilderFactory(KeyringConstructor) {
88
88
  return builder;
89
89
  }
90
90
  const defaultKeyringBuilders = [
91
+ // todo: keyring types are mismatched, this should be fixed in they keyrings themselves
92
+ // @ts-expect-error keyring types are mismatched
91
93
  keyringBuilderFactory(SimpleKeyring),
94
+ // @ts-expect-error keyring types are mismatched
92
95
  keyringBuilderFactory(HDKeyring),
93
96
  ];
94
97
  export const getDefaultKeyringState = () => {
95
98
  return {
96
99
  isUnlocked: false,
97
100
  keyrings: [],
101
+ keyringsMetadata: [],
98
102
  };
99
103
  };
100
104
  /**
@@ -225,6 +229,7 @@ export class KeyringController extends BaseController {
225
229
  vault: { persist: true, anonymous: false },
226
230
  isUnlocked: { persist: false, anonymous: true },
227
231
  keyrings: { persist: false, anonymous: false },
232
+ keyringsMetadata: { persist: true, anonymous: false },
228
233
  encryptionKey: { persist: false, anonymous: false },
229
234
  encryptionSalt: { persist: false, anonymous: false },
230
235
  },
@@ -242,6 +247,7 @@ export class KeyringController extends BaseController {
242
247
  _KeyringController_encryptor.set(this, void 0);
243
248
  _KeyringController_cacheEncryptionKey.set(this, void 0);
244
249
  _KeyringController_keyrings.set(this, void 0);
250
+ _KeyringController_keyringsMetadata.set(this, void 0);
245
251
  _KeyringController_password.set(this, void 0);
246
252
  _KeyringController_qrKeyringStateListener.set(this, void 0);
247
253
  __classPrivateFieldSet(this, _KeyringController_keyringBuilders, keyringBuilders
@@ -249,6 +255,7 @@ export class KeyringController extends BaseController {
249
255
  : defaultKeyringBuilders, "f");
250
256
  __classPrivateFieldSet(this, _KeyringController_encryptor, encryptor, "f");
251
257
  __classPrivateFieldSet(this, _KeyringController_keyrings, [], "f");
258
+ __classPrivateFieldSet(this, _KeyringController_keyringsMetadata, state?.keyringsMetadata ?? [], "f");
252
259
  __classPrivateFieldSet(this, _KeyringController_unsupportedKeyrings, [], "f");
253
260
  // This option allows the controller to cache an exported key
254
261
  // for use in decrypting and encrypting data without password
@@ -397,13 +404,18 @@ export class KeyringController extends BaseController {
397
404
  * Gets the seed phrase of the HD keyring.
398
405
  *
399
406
  * @param password - Password of the keyring.
407
+ * @param keyringId - The id of the keyring.
400
408
  * @returns Promise resolving to the seed phrase.
401
409
  */
402
- async exportSeedPhrase(password) {
410
+ async exportSeedPhrase(password, keyringId) {
403
411
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
404
412
  await this.verifyPassword(password);
405
- assertHasUint8ArrayMnemonic(__classPrivateFieldGet(this, _KeyringController_keyrings, "f")[0]);
406
- return __classPrivateFieldGet(this, _KeyringController_keyrings, "f")[0].mnemonic;
413
+ const selectedKeyring = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringByIdOrDefault).call(this, keyringId);
414
+ if (!selectedKeyring) {
415
+ throw new Error('Keyring not found');
416
+ }
417
+ assertHasUint8ArrayMnemonic(selectedKeyring);
418
+ return selectedKeyring.mnemonic;
407
419
  }
408
420
  /**
409
421
  * Gets the private key from the keyring controlling an address.
@@ -588,6 +600,13 @@ export class KeyringController extends BaseController {
588
600
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
589
601
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_persistOrRollback).call(this, async () => {
590
602
  const keyring = (await this.getKeyringForAccount(address));
603
+ const keyringIndex = this.state.keyrings.findIndex((kr) => kr.accounts.includes(address));
604
+ const isPrimaryKeyring = keyringIndex === 0;
605
+ const shouldRemoveKeyring = (await keyring.getAccounts()).length === 1;
606
+ // Primary keyring should never be removed, so we need to keep at least one account in it
607
+ if (isPrimaryKeyring && shouldRemoveKeyring) {
608
+ throw new Error(KeyringControllerError.LastAccountInPrimaryKeyring);
609
+ }
591
610
  // Not all the keyrings support this, so we have to check
592
611
  if (!keyring.removeAccount) {
593
612
  throw new Error(KeyringControllerError.UnsupportedRemoveAccount);
@@ -598,9 +617,7 @@ export class KeyringController extends BaseController {
598
617
  // because `Keyring<State>.removeAccount` requires address to be `Hex`. Those
599
618
  // type would need to be updated for a full non-EVM support.
600
619
  keyring.removeAccount(address);
601
- const accounts = await keyring.getAccounts();
602
- // Check if this was the last/only account
603
- if (accounts.length === 0) {
620
+ if (shouldRemoveKeyring) {
604
621
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_removeEmptyKeyrings).call(this);
605
622
  }
606
623
  });
@@ -644,6 +661,27 @@ export class KeyringController extends BaseController {
644
661
  }
645
662
  return await keyring.signMessage(address, messageParams.data);
646
663
  }
664
+ /**
665
+ * Signs EIP-7702 Authorization message by calling down into a specific keyring.
666
+ *
667
+ * @param params - EIP7702AuthorizationParams object to sign.
668
+ * @returns Promise resolving to an EIP-7702 Authorization signature.
669
+ * @throws Will throw UnsupportedSignEIP7702Authorization if the keyring does not support signing EIP-7702 Authorization messages.
670
+ */
671
+ async signEip7702Authorization(params) {
672
+ const from = ethNormalize(params.from);
673
+ const keyring = (await this.getKeyringForAccount(from));
674
+ if (!keyring.signEip7702Authorization) {
675
+ throw new Error(KeyringControllerError.UnsupportedSignEip7702Authorization);
676
+ }
677
+ const { chainId, nonce } = params;
678
+ const contractAddress = ethNormalize(params.contractAddress);
679
+ return await keyring.signEip7702Authorization(from, [
680
+ chainId,
681
+ contractAddress,
682
+ nonce,
683
+ ]);
684
+ }
647
685
  /**
648
686
  * Signs personal message by calling down into a specific keyring.
649
687
  *
@@ -817,11 +855,12 @@ export class KeyringController extends BaseController {
817
855
  /**
818
856
  * Verifies the that the seed phrase restores the current keychain's accounts.
819
857
  *
858
+ * @param keyringId - The id of the keyring to verify.
820
859
  * @returns Promise resolving to the seed phrase as Uint8Array.
821
860
  */
822
- async verifySeedPhrase() {
861
+ async verifySeedPhrase(keyringId) {
823
862
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertIsUnlocked).call(this);
824
- return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async () => __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_verifySeedPhrase).call(this));
863
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async () => __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_verifySeedPhrase).call(this, keyringId));
825
864
  }
826
865
  async withKeyring(selector, operation, options = {
827
866
  createIfMissing: false,
@@ -832,12 +871,15 @@ export class KeyringController extends BaseController {
832
871
  if ('address' in selector) {
833
872
  keyring = (await this.getKeyringForAccount(selector.address));
834
873
  }
835
- else {
874
+ else if ('type' in selector) {
836
875
  keyring = this.getKeyringsByType(selector.type)[selector.index || 0];
837
876
  if (!keyring && options.createIfMissing) {
838
877
  keyring = (await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, selector.type, options.createWithData));
839
878
  }
840
879
  }
880
+ else if ('id' in selector) {
881
+ keyring = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringById).call(this, selector.id);
882
+ }
841
883
  if (!keyring) {
842
884
  throw new Error(KeyringControllerError.KeyringNotFound);
843
885
  }
@@ -1050,8 +1092,9 @@ export class KeyringController extends BaseController {
1050
1092
  });
1051
1093
  }
1052
1094
  }
1053
- _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() {
1095
+ _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_keyringsMetadata = new WeakMap(), _KeyringController_password = new WeakMap(), _KeyringController_qrKeyringStateListener = new WeakMap(), _KeyringController_instances = new WeakSet(), _KeyringController_registerMessageHandlers = function _KeyringController_registerMessageHandlers() {
1054
1096
  this.messagingSystem.registerActionHandler(`${name}:signMessage`, this.signMessage.bind(this));
1097
+ this.messagingSystem.registerActionHandler(`${name}:signEip7702Authorization`, this.signEip7702Authorization.bind(this));
1055
1098
  this.messagingSystem.registerActionHandler(`${name}:signPersonalMessage`, this.signPersonalMessage.bind(this));
1056
1099
  this.messagingSystem.registerActionHandler(`${name}:signTypedMessage`, this.signTypedMessage.bind(this));
1057
1100
  this.messagingSystem.registerActionHandler(`${name}:decryptMessage`, this.decryptMessage.bind(this));
@@ -1065,6 +1108,14 @@ _KeyringController_controllerOperationMutex = new WeakMap(), _KeyringController_
1065
1108
  this.messagingSystem.registerActionHandler(`${name}:signUserOperation`, this.signUserOperation.bind(this));
1066
1109
  this.messagingSystem.registerActionHandler(`${name}:addNewAccount`, this.addNewAccount.bind(this));
1067
1110
  this.messagingSystem.registerActionHandler(`${name}:withKeyring`, this.withKeyring.bind(this));
1111
+ }, _KeyringController_getKeyringById = function _KeyringController_getKeyringById(keyringId) {
1112
+ const index = this.state.keyringsMetadata.findIndex((metadata) => metadata.id === keyringId);
1113
+ return __classPrivateFieldGet(this, _KeyringController_keyrings, "f")[index];
1114
+ }, _KeyringController_getKeyringByIdOrDefault = function _KeyringController_getKeyringByIdOrDefault(keyringId) {
1115
+ if (!keyringId) {
1116
+ return __classPrivateFieldGet(this, _KeyringController_keyrings, "f")[0];
1117
+ }
1118
+ return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringById).call(this, keyringId);
1068
1119
  }, _KeyringController_getKeyringBuilderForType = function _KeyringController_getKeyringBuilderForType(type) {
1069
1120
  return __classPrivateFieldGet(this, _KeyringController_keyringBuilders, "f").find((keyringBuilder) => keyringBuilder.type === type);
1070
1121
  }, _KeyringController_addQRKeyring =
@@ -1117,23 +1168,29 @@ async function _KeyringController_createNewVaultWithKeyring(password, keyring) {
1117
1168
  });
1118
1169
  __classPrivateFieldSet(this, _KeyringController_password, password, "f");
1119
1170
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
1171
+ __classPrivateFieldSet(this, _KeyringController_keyringsMetadata, [], "f");
1120
1172
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyringWithFirstAccount).call(this, keyring.type, keyring.opts);
1121
1173
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
1122
1174
  }, _KeyringController_verifySeedPhrase =
1123
1175
  /**
1124
1176
  * Internal non-exclusive method to verify the seed phrase.
1125
1177
  *
1178
+ * @param keyringId - The id of the keyring to verify the seed phrase for.
1126
1179
  * @returns A promise resolving to the seed phrase as Uint8Array.
1127
1180
  */
1128
- async function _KeyringController_verifySeedPhrase() {
1181
+ async function _KeyringController_verifySeedPhrase(keyringId) {
1129
1182
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1130
- const primaryKeyring = this.getKeyringsByType(KeyringTypes.hd)[0];
1131
- if (!primaryKeyring) {
1132
- throw new Error('No HD keyring found.');
1183
+ const keyring = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringByIdOrDefault).call(this, keyringId);
1184
+ if (!keyring) {
1185
+ throw new Error(KeyringControllerError.KeyringNotFound);
1133
1186
  }
1134
- assertHasUint8ArrayMnemonic(primaryKeyring);
1135
- const seedWords = primaryKeyring.mnemonic;
1136
- const accounts = await primaryKeyring.getAccounts();
1187
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison
1188
+ if (keyring.type !== KeyringTypes.hd) {
1189
+ throw new Error(KeyringControllerError.UnsupportedVerifySeedPhrase);
1190
+ }
1191
+ assertHasUint8ArrayMnemonic(keyring);
1192
+ const seedWords = keyring.mnemonic;
1193
+ const accounts = await keyring.getAccounts();
1137
1194
  /* istanbul ignore if */
1138
1195
  if (accounts.length === 0) {
1139
1196
  throw new Error('Cannot verify an empty keyring.');
@@ -1313,9 +1370,13 @@ async function _KeyringController_unlockKeyrings(password, encryptionKey, encryp
1313
1370
  throw new Error(KeyringControllerError.MissingVaultData);
1314
1371
  }
1315
1372
  const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
1373
+ if (updatedKeyrings.length !== __classPrivateFieldGet(this, _KeyringController_keyringsMetadata, "f").length) {
1374
+ throw new Error(KeyringControllerError.KeyringMetadataLengthMismatch);
1375
+ }
1316
1376
  this.update((state) => {
1317
1377
  state.vault = updatedState.vault;
1318
1378
  state.keyrings = updatedKeyrings;
1379
+ state.keyringsMetadata = __classPrivateFieldGet(this, _KeyringController_keyringsMetadata, "f").slice();
1319
1380
  if (updatedState.encryptionKey) {
1320
1381
  state.encryptionKey = updatedState.encryptionKey;
1321
1382
  state.encryptionSalt = JSON.parse(updatedState.vault).salt;
@@ -1355,19 +1416,48 @@ async function _KeyringController_createKeyringWithFirstAccount(type, opts) {
1355
1416
  if (!firstAccount) {
1356
1417
  throw new Error(KeyringControllerError.NoFirstAccount);
1357
1418
  }
1419
+ return firstAccount;
1358
1420
  }, _KeyringController_newKeyring =
1359
1421
  /**
1360
1422
  * Instantiate, initialize and return a new keyring of the given `type`,
1361
1423
  * using the given `opts`. The keyring is built using the keyring builder
1362
1424
  * registered for the given `type`.
1363
1425
  *
1426
+ * The internal keyring and keyring metadata arrays are updated with the new
1427
+ * keyring as well.
1364
1428
  *
1365
1429
  * @param type - The type of keyring to add.
1366
- * @param data - The data to restore a previously serialized keyring.
1430
+ * @param data - Keyring initialization options.
1367
1431
  * @returns The new keyring.
1368
1432
  * @throws If the keyring includes duplicated accounts.
1369
1433
  */
1370
1434
  async function _KeyringController_newKeyring(type, data) {
1435
+ const keyring = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyring).call(this, type, data);
1436
+ if (__classPrivateFieldGet(this, _KeyringController_keyrings, "f").length !== __classPrivateFieldGet(this, _KeyringController_keyringsMetadata, "f").length) {
1437
+ throw new Error('Keyring metadata missing');
1438
+ }
1439
+ __classPrivateFieldGet(this, _KeyringController_keyrings, "f").push(keyring);
1440
+ __classPrivateFieldGet(this, _KeyringController_keyringsMetadata, "f").push(getDefaultKeyringMetadata());
1441
+ return keyring;
1442
+ }, _KeyringController_createKeyring =
1443
+ /**
1444
+ * Instantiate, initialize and return a keyring of the given `type` using the
1445
+ * given `opts`. The keyring is built using the keyring builder registered
1446
+ * for the given `type`.
1447
+ *
1448
+ * The keyring might be new, or it might be restored from the vault. This
1449
+ * function should only be called from `#newKeyring` or `#restoreKeyring`,
1450
+ * for the "new" and "restore" cases respectively.
1451
+ *
1452
+ * The internal keyring and keyring metadata arrays are *not* updated, the
1453
+ * caller is expected to update them.
1454
+ *
1455
+ * @param type - The type of keyring to add.
1456
+ * @param data - Keyring initialization options.
1457
+ * @returns The new keyring.
1458
+ * @throws If the keyring includes duplicated accounts.
1459
+ */
1460
+ async function _KeyringController_createKeyring(type, data) {
1371
1461
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1372
1462
  const keyringBuilder = __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getKeyringBuilderForType).call(this, type);
1373
1463
  if (!keyringBuilder) {
@@ -1395,7 +1485,6 @@ async function _KeyringController_newKeyring(type, data) {
1395
1485
  // to its events after creating it
1396
1486
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_subscribeToQRKeyringEvents).call(this, keyring);
1397
1487
  }
1398
- __classPrivateFieldGet(this, _KeyringController_keyrings, "f").push(keyring);
1399
1488
  return keyring;
1400
1489
  }, _KeyringController_clearKeyrings =
1401
1490
  /**
@@ -1420,7 +1509,15 @@ async function _KeyringController_restoreKeyring(serialized) {
1420
1509
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1421
1510
  try {
1422
1511
  const { type, data } = serialized;
1423
- return await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_newKeyring).call(this, type, data);
1512
+ const keyring = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyring).call(this, type, data);
1513
+ __classPrivateFieldGet(this, _KeyringController_keyrings, "f").push(keyring);
1514
+ // If metadata is missing, assume the data is from an installation before
1515
+ // we had keyring metadata.
1516
+ if (__classPrivateFieldGet(this, _KeyringController_keyringsMetadata, "f").length < __classPrivateFieldGet(this, _KeyringController_keyrings, "f").length) {
1517
+ console.log(`Adding missing metadata for '${type}' keyring`);
1518
+ __classPrivateFieldGet(this, _KeyringController_keyringsMetadata, "f").push(getDefaultKeyringMetadata());
1519
+ }
1520
+ return keyring;
1424
1521
  }
1425
1522
  catch (_) {
1426
1523
  __classPrivateFieldGet(this, _KeyringController_unsupportedKeyrings, "f").push(serialized);
@@ -1448,19 +1545,22 @@ async function _KeyringController_destroyKeyring(keyring) {
1448
1545
  async function _KeyringController_removeEmptyKeyrings() {
1449
1546
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1450
1547
  const validKeyrings = [];
1548
+ const validKeyringMetadata = [];
1451
1549
  // Since getAccounts returns a Promise
1452
1550
  // We need to wait to hear back form each keyring
1453
1551
  // in order to decide which ones are now valid (accounts.length > 0)
1454
- await Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(async (keyring) => {
1552
+ await Promise.all(__classPrivateFieldGet(this, _KeyringController_keyrings, "f").map(async (keyring, index) => {
1455
1553
  const accounts = await keyring.getAccounts();
1456
1554
  if (accounts.length > 0) {
1457
1555
  validKeyrings.push(keyring);
1556
+ validKeyringMetadata.push(__classPrivateFieldGet(this, _KeyringController_keyringsMetadata, "f")[index]);
1458
1557
  }
1459
1558
  else {
1460
1559
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_destroyKeyring).call(this, keyring);
1461
1560
  }
1462
1561
  }));
1463
1562
  __classPrivateFieldSet(this, _KeyringController_keyrings, validKeyrings, "f");
1563
+ __classPrivateFieldSet(this, _KeyringController_keyringsMetadata, validKeyringMetadata, "f");
1464
1564
  }, _KeyringController_checkForDuplicate =
1465
1565
  /**
1466
1566
  * Checks for duplicate keypairs, using the the first account in the given
@@ -1526,6 +1626,7 @@ async function _KeyringController_withRollback(callback) {
1526
1626
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withControllerLock).call(this, async ({ releaseLock }) => {
1527
1627
  const currentSerializedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSerializedKeyrings).call(this);
1528
1628
  const currentPassword = __classPrivateFieldGet(this, _KeyringController_password, "f");
1629
+ const currentKeyringsMetadata = __classPrivateFieldGet(this, _KeyringController_keyringsMetadata, "f").slice();
1529
1630
  try {
1530
1631
  return await callback({ releaseLock });
1531
1632
  }
@@ -1533,6 +1634,7 @@ async function _KeyringController_withRollback(callback) {
1533
1634
  // Keyrings and password are restored to their previous state
1534
1635
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreSerializedKeyrings).call(this, currentSerializedKeyrings);
1535
1636
  __classPrivateFieldSet(this, _KeyringController_password, currentPassword, "f");
1637
+ __classPrivateFieldSet(this, _KeyringController_keyringsMetadata, currentKeyringsMetadata, "f");
1536
1638
  throw e;
1537
1639
  }
1538
1640
  });
@@ -1589,5 +1691,13 @@ async function withLock(mutex, callback) {
1589
1691
  releaseLock();
1590
1692
  }
1591
1693
  }
1694
+ /**
1695
+ * Generate a new keyring metadata object.
1696
+ *
1697
+ * @returns Keyring metadata.
1698
+ */
1699
+ function getDefaultKeyringMetadata() {
1700
+ return { id: ulid(), name: '' };
1701
+ }
1592
1702
  export default KeyringController;
1593
1703
  //# sourceMappingURL=KeyringController.mjs.map