@metamask-previews/keyring-controller 25.2.0-preview-dff83af4c → 25.2.0-preview-aa31fa3

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
 
14
16
  ### Changed
15
17
 
@@ -895,7 +895,7 @@ class KeyringController extends base_controller_1.BaseController {
895
895
  * @returns Promise resolving when the operation completes.
896
896
  */
897
897
  async submitEncryptionKey(encryptionKey, encryptionSalt) {
898
- const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
898
+ const { hasChanged } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
899
899
  const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, {
900
900
  encryptionKey,
901
901
  encryptionSalt,
@@ -907,7 +907,7 @@ class KeyringController extends base_controller_1.BaseController {
907
907
  // if new metadata has been generated during login, we
908
908
  // can attempt to upgrade the vault.
909
909
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
910
- if (newMetadata) {
910
+ if (hasChanged) {
911
911
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
912
912
  }
913
913
  });
@@ -938,17 +938,17 @@ class KeyringController extends base_controller_1.BaseController {
938
938
  * @returns Promise resolving when the operation completes.
939
939
  */
940
940
  async submitPassword(password) {
941
- const { newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
941
+ const { hasChanged } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
942
942
  const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_unlockKeyrings).call(this, { password });
943
943
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_setUnlocked).call(this);
944
944
  return result;
945
945
  });
946
946
  try {
947
947
  // If there are stronger encryption params available, or
948
- // if new metadata has been generated during login, we
948
+ // if the keyring state has changed during deserialization, we
949
949
  // can attempt to upgrade the vault.
950
950
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withRollback).call(this, async () => {
951
- if (newMetadata || __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_isNewEncryptionAvailable).call(this)) {
951
+ if (hasChanged || __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_isNewEncryptionAvailable).call(this)) {
952
952
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_deriveAndSetEncryptionKey).call(this, password, {
953
953
  // If the vault is being upgraded, we want to ignore the metadata
954
954
  // that is already in the vault, so we can effectively
@@ -1296,18 +1296,18 @@ async function _KeyringController_getSessionState() {
1296
1296
  async function _KeyringController_restoreSerializedKeyrings(serializedKeyrings) {
1297
1297
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_clearKeyrings).call(this);
1298
1298
  const keyrings = [];
1299
- let newMetadata = false;
1299
+ let hasChanged = false;
1300
1300
  for (const serializedKeyring of serializedKeyrings) {
1301
1301
  const result = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreKeyring).call(this, serializedKeyring);
1302
1302
  if (result) {
1303
1303
  const { keyring, metadata } = result;
1304
1304
  keyrings.push({ keyring, metadata });
1305
- if (result.newMetadata) {
1306
- newMetadata = true;
1305
+ if (result.hasChanged) {
1306
+ hasChanged = true;
1307
1307
  }
1308
1308
  }
1309
1309
  }
1310
- return { keyrings, newMetadata };
1310
+ return { keyrings, hasChanged };
1311
1311
  }, _KeyringController_unlockKeyrings =
1312
1312
  /**
1313
1313
  * Unlock Keyrings, decrypting the vault and deserializing all
@@ -1337,14 +1337,14 @@ async function _KeyringController_unlockKeyrings(credentials) {
1337
1337
  if (!isSerializedKeyringsArray(vault)) {
1338
1338
  throw new errors_1.KeyringControllerError(constants_1.KeyringControllerErrorMessage.VaultDataError);
1339
1339
  }
1340
- const { keyrings, newMetadata } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreSerializedKeyrings).call(this, vault);
1340
+ const { keyrings, hasChanged } = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_restoreSerializedKeyrings).call(this, vault);
1341
1341
  const updatedKeyrings = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getUpdatedKeyrings).call(this);
1342
1342
  this.update((state) => {
1343
1343
  state.keyrings = updatedKeyrings;
1344
1344
  state.encryptionKey = encryptionKey;
1345
1345
  state.encryptionSalt = __classPrivateFieldGet(this, _KeyringController_encryptionKey, "f")?.salt;
1346
1346
  });
1347
- return { keyrings, newMetadata };
1347
+ return { keyrings, hasChanged };
1348
1348
  });
1349
1349
  }, _KeyringController_updateVault = function _KeyringController_updateVault() {
1350
1350
  return __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_withVaultLock).call(this, async () => {
@@ -1503,14 +1503,16 @@ async function _KeyringController_restoreKeyring(serialized) {
1503
1503
  __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertControllerMutexIsLocked).call(this);
1504
1504
  try {
1505
1505
  const { type, data, metadata: serializedMetadata } = serialized;
1506
- let newMetadata = false;
1507
- let metadata = serializedMetadata;
1506
+ const oldState = JSON.stringify(data);
1508
1507
  const keyring = await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_createKeyring).call(this, type, data);
1508
+ const newState = JSON.stringify(await keyring.serialize());
1509
+ let hasChanged = oldState !== newState;
1509
1510
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_assertNoDuplicateAccounts).call(this, [keyring]);
1510
- // If metadata is missing, assume the data is from an installation before
1511
- // we had keyring metadata.
1511
+ // If metadata is missing, assume the data is from an installation before we had
1512
+ // keyring metadata.
1513
+ let metadata = serializedMetadata;
1512
1514
  if (!metadata) {
1513
- newMetadata = true;
1515
+ hasChanged = true;
1514
1516
  metadata = getDefaultKeyringMetadata();
1515
1517
  }
1516
1518
  // The keyring is added to the keyrings array only if it's successfully restored
@@ -1519,7 +1521,7 @@ async function _KeyringController_restoreKeyring(serialized) {
1519
1521
  keyring,
1520
1522
  metadata,
1521
1523
  });
1522
- return { keyring, metadata, newMetadata };
1524
+ return { keyring, metadata, hasChanged };
1523
1525
  }
1524
1526
  catch (error) {
1525
1527
  console.error(error);
@@ -1575,7 +1577,7 @@ async function _KeyringController_persistOrRollback(callback) {
1575
1577
  const callbackResult = await callback({ releaseLock });
1576
1578
  const newState = JSON.stringify(await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_getSessionState).call(this));
1577
1579
  // State is committed only if the operation is successful and need to trigger a vault update.
1578
- if (!(0, lodash_1.isEqual)(oldState, newState)) {
1580
+ if (oldState !== newState) {
1579
1581
  await __classPrivateFieldGet(this, _KeyringController_instances, "m", _KeyringController_updateVault).call(this);
1580
1582
  }
1581
1583
  return callbackResult;