@metamask-previews/keyring-controller 25.2.0-preview-866755774 → 25.2.0-preview-6b4f746

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.
package/CHANGELOG.md CHANGED
@@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
10
10
  ### Added
11
11
 
12
12
  - Expose `KeyringController:signTransaction` method through `KeyringController` messenger ([#8408](https://github.com/MetaMask/core/pull/8408))
13
+ - Persist vault when keyring state changes during unlock ([#8415](https://github.com/MetaMask/core/pull/8415))
14
+ - If a keyring's serialized state differs after deserialization (e.g. a migration ran, or metadata was missing), the vault is now re-persisted so the change is not lost on the next unlock.
13
15
  - Added `KeyringV2` support ([#8390](https://github.com/MetaMask/core/pull/8390))
14
16
  - The controller now maintains a list of `KeyringV2` instance in memory alongside previous `Keyring` instance.
15
17
  - This new keyring interface is more generic and will become the new standard to interact with keyring (creating accounts, executing logic that involves accounts like signing, etc...).
@@ -907,7 +907,7 @@ class KeyringController extends base_controller_1.BaseController {
907
907
  * @returns Promise resolving when the operation completes.
908
908
  */
909
909
  async submitEncryptionKey(encryptionKey, encryptionSalt) {
910
- const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
910
+ const { hasChanged } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
911
911
  const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, {
912
912
  encryptionKey,
913
913
  encryptionSalt,
@@ -919,7 +919,7 @@ class KeyringController extends base_controller_1.BaseController {
919
919
  // if new metadata has been generated during login, we
920
920
  // can attempt to upgrade the vault.
921
921
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
922
- if (newMetadata) {
922
+ if (hasChanged) {
923
923
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
924
924
  }
925
925
  });
@@ -950,17 +950,17 @@ class KeyringController extends base_controller_1.BaseController {
950
950
  * @returns Promise resolving when the operation completes.
951
951
  */
952
952
  async submitPassword(password) {
953
- const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
953
+ const { hasChanged } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
954
954
  const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, { password });
955
955
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
956
956
  return result;
957
957
  });
958
958
  try {
959
959
  // If there are stronger encryption params available, or
960
- // if new metadata has been generated during login, we
960
+ // if the keyring state has changed during deserialization, we
961
961
  // can attempt to upgrade the vault.
962
962
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
963
- if (newMetadata || __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_isNewEncryptionAvailable).call(this)) {
963
+ if (hasChanged || __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_isNewEncryptionAvailable).call(this)) {
964
964
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveAndSetEncryptionKey).call(this, password, {
965
965
  // If the vault is being upgraded, we want to ignore the metadata
966
966
  // that is already in the vault, so we can effectively
@@ -1448,18 +1448,18 @@ async function _KeyringController_getSessionState() {
1448
1448
  async function _KeyringController_restoreSerializedKeyrings(serializedKeyrings) {
1449
1449
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
1450
1450
  const keyrings = [];
1451
- let newMetadata = false;
1451
+ let hasChanged = false;
1452
1452
  for (const serializedKeyring of serializedKeyrings) {
1453
1453
  const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreKeyring).call(this, serializedKeyring);
1454
1454
  if (result) {
1455
1455
  const { keyring, metadata } = result;
1456
1456
  keyrings.push({ keyring, metadata });
1457
- if (result.newMetadata) {
1458
- newMetadata = true;
1457
+ if (result.hasChanged) {
1458
+ hasChanged = true;
1459
1459
  }
1460
1460
  }
1461
1461
  }
1462
- return { keyrings, newMetadata };
1462
+ return { keyrings, hasChanged };
1463
1463
  }, _KeyringController_unlockKeyrings =
1464
1464
  /**
1465
1465
  * Unlock Keyrings, decrypting the vault and deserializing all
@@ -1489,14 +1489,14 @@ async function _KeyringController_unlockKeyrings(credentials) {
1489
1489
  if (!isSerializedKeyringsArray(vault)) {
1490
1490
  throw new errors_1.KeyringControllerError(constants_1.KeyringControllerErrorMessage.VaultDataError);
1491
1491
  }
1492
- const { keyrings, newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreSerializedKeyrings).call(this, vault);
1492
+ const { keyrings, hasChanged } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreSerializedKeyrings).call(this, vault);
1493
1493
  const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
1494
1494
  this.update((state) => {
1495
1495
  state.keyrings = updatedKeyrings;
1496
1496
  state.encryptionKey = encryptionKey;
1497
1497
  state.encryptionSalt = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")?.salt;
1498
1498
  });
1499
- return { keyrings, newMetadata };
1499
+ return { keyrings, hasChanged };
1500
1500
  });
1501
1501
  }, _KeyringController_updateVault = function _KeyringController_updateVault() {
1502
1502
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
@@ -1663,15 +1663,19 @@ async function _KeyringController_restoreKeyring(serialized) {
1663
1663
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1664
1664
  try {
1665
1665
  const { type, data, metadata: serializedMetadata } = serialized;
1666
- let newMetadata = false;
1666
+ // Track if we need to trigger a vault update.
1667
+ let hasChanged = false;
1668
+ // If metadata is missing, assume the data is from an installation before we had
1669
+ // keyring metadata.
1667
1670
  let metadata = serializedMetadata;
1668
- // If metadata is missing, assume the data is from an installation before
1669
- // we had keyring metadata.
1670
1671
  if (!metadata) {
1671
- newMetadata = true;
1672
+ hasChanged = true;
1672
1673
  metadata = getDefaultKeyringMetadata();
1673
1674
  }
1675
+ const oldState = JSON.stringify(data);
1674
1676
  const { keyring, keyringV2 } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyring).call(this, type, data, metadata);
1677
+ const newState = JSON.stringify(await keyring.serialize());
1678
+ hasChanged || (hasChanged = oldState !== newState);
1675
1679
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoDuplicateAccounts).call(this, [keyring]);
1676
1680
  // The keyring is added to the keyrings array only if it's successfully restored
1677
1681
  // and the metadata is successfully added to the controller
@@ -1680,7 +1684,7 @@ async function _KeyringController_restoreKeyring(serialized) {
1680
1684
  keyringV2,
1681
1685
  metadata,
1682
1686
  });
1683
- return { keyring, keyringV2, metadata, newMetadata };
1687
+ return { keyring, keyringV2, metadata, hasChanged };
1684
1688
  }
1685
1689
  catch (error) {
1686
1690
  console.error(error);
@@ -1740,7 +1744,7 @@ async function _KeyringController_persistOrRollback(callback) {
1740
1744
  const callbackResult = await callback({ releaseLock });
1741
1745
  const newState = JSON.stringify(await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSessionState).call(this));
1742
1746
  // State is committed only if the operation is successful and need to trigger a vault update.
1743
- if (!(0, lodash_1.isEqual)(oldState, newState)) {
1747
+ if (oldState !== newState) {
1744
1748
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
1745
1749
  }
1746
1750
  return callbackResult;