@metamask/accounts-controller 37.1.1 → 38.0.0

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
@@ -7,6 +7,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [38.0.0]
11
+
12
+ ### Added
13
+
14
+ - Add support for `SnapKeyring` v2 accounts ([#8513](https://github.com/MetaMask/core/pull/8513))
15
+
16
+ ### Changed
17
+
18
+ - Bump `@metamask/messenger` from `^1.0.0` to `^1.2.0` ([#8364](https://github.com/MetaMask/core/pull/8364), [#8373](https://github.com/MetaMask/core/pull/8373), [#8632](https://github.com/MetaMask/core/pull/8632))
19
+ - Bump `@metamask/base-controller` from `^9.0.1` to `^9.1.0` ([#8457](https://github.com/MetaMask/core/pull/8457))
20
+ - Bump `@metamask/eth-snap-keyring` from `^19.0.0` to `^22.0.1` ([#8464](https://github.com/MetaMask/core/pull/8464), [#8584](https://github.com/MetaMask/core/pull/8584), [#8647](https://github.com/MetaMask/core/pull/8647))
21
+ - Bump `@metamask/keyring-api` from `^21.6.0` to `^23.1.0` ([#8464](https://github.com/MetaMask/core/pull/8464), [#8647](https://github.com/MetaMask/core/pull/8647))
22
+ - Bump `@metamask/keyring-internal-api` from `^10.0.0` to `^11.0.1` ([#8464](https://github.com/MetaMask/core/pull/8464), [#8584](https://github.com/MetaMask/core/pull/8584), [#8647](https://github.com/MetaMask/core/pull/8647))
23
+ - Bump `@metamask/keyring-controller` from `^25.2.0` to `^25.4.0` ([#8634](https://github.com/MetaMask/core/pull/8634), [#8665](https://github.com/MetaMask/core/pull/8665))
24
+ - Bump `@metamask/network-controller` from `^30.0.1` to `^30.1.0` ([#8636](https://github.com/MetaMask/core/pull/8636))
25
+
26
+ ### Removed
27
+
28
+ - **BREAKING:** `InternalAccount.metadata.snap.{enabled,name}` properties have been removed ([#8584](https://github.com/MetaMask/core/pull/8584))
29
+ - You now need to use `metadata.snap.id` and the `SnapController:<actions>` to get those information.
30
+ - No longer depend on `SnapController:stateChange` event ([#8584](https://github.com/MetaMask/core/pull/8584))
31
+
32
+ ## [37.2.0]
33
+
34
+ ### Added
35
+
36
+ - Now supports `KeyringTypes.money` in `keyringTypeToName` ([#8362](https://github.com/MetaMask/core/pull/8362))
37
+ - Even though this controller does not support Money accounts, this helper might be used with this new keyring type (added for completeness).
38
+
39
+ ### Changed
40
+
41
+ - Filter out Money accounts when replicating `KeyringController` state ([#8362](https://github.com/MetaMask/core/pull/8362))
42
+ - Those accounts are treated differently with their own "account-like" controller.
43
+ - Bump `@metamask/keyring-controller` from `^25.1.1` to `^25.2.0` ([#8363](https://github.com/MetaMask/core/pull/8363))
44
+
10
45
  ## [37.1.1]
11
46
 
12
47
  ### Changed
@@ -748,7 +783,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
748
783
 
749
784
  - Initial release ([#1637](https://github.com/MetaMask/core/pull/1637))
750
785
 
751
- [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/accounts-controller@37.1.1...HEAD
786
+ [Unreleased]: https://github.com/MetaMask/core/compare/@metamask/accounts-controller@38.0.0...HEAD
787
+ [38.0.0]: https://github.com/MetaMask/core/compare/@metamask/accounts-controller@37.2.0...@metamask/accounts-controller@38.0.0
788
+ [37.2.0]: https://github.com/MetaMask/core/compare/@metamask/accounts-controller@37.1.1...@metamask/accounts-controller@37.2.0
752
789
  [37.1.1]: https://github.com/MetaMask/core/compare/@metamask/accounts-controller@37.1.0...@metamask/accounts-controller@37.1.1
753
790
  [37.1.0]: https://github.com/MetaMask/core/compare/@metamask/accounts-controller@37.0.0...@metamask/accounts-controller@37.1.0
754
791
  [37.0.0]: https://github.com/MetaMask/core/compare/@metamask/accounts-controller@36.0.1...@metamask/accounts-controller@37.0.0
@@ -4,12 +4,14 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
4
4
  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");
5
5
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
6
  };
7
- var _AccountsController_instances, _AccountsController_getAccountExpect, _AccountsController_assertAccountCanBeRenamed, _AccountsController_getInternalAccountForNonSnapAccount, _AccountsController_getSnapKeyring, _AccountsController_handleOnSnapKeyringAccountEvent, _AccountsController_handleOnKeyringStateChange, _AccountsController_update, _AccountsController_handleOnSnapStateChange, _AccountsController_getLastSelectedAccount, _AccountsController_getLastSelectedIndex, _AccountsController_getInternalAccountFromAddressAndType, _AccountsController_handleOnMultichainNetworkDidChange, _AccountsController_subscribeToMessageEvents;
7
+ var _AccountsController_instances, _AccountsController_getAccountExpect, _AccountsController_assertAccountCanBeRenamed, _AccountsController_getInternalAccountForNonSnapAccount, _AccountsController_getSnapKeyring, _AccountsController_getAccountFromSnapKeyringV1, _AccountsController_getAccountFromSnapKeyringV2, _AccountsController_handleOnSnapKeyringAccountEvent, _AccountsController_handleOnKeyringStateChange, _AccountsController_update, _AccountsController_getLastSelectedAccount, _AccountsController_getLastSelectedIndex, _AccountsController_getInternalAccountFromAddressAndType, _AccountsController_handleOnMultichainNetworkDidChange, _AccountsController_subscribeToMessageEvents;
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.AccountsController = exports.EMPTY_ACCOUNT = void 0;
10
10
  const base_controller_1 = require("@metamask/base-controller");
11
11
  const eth_snap_keyring_1 = require("@metamask/eth-snap-keyring");
12
+ const v2_1 = require("@metamask/eth-snap-keyring/v2");
12
13
  const keyring_api_1 = require("@metamask/keyring-api");
14
+ const v2_2 = require("@metamask/keyring-api/v2");
13
15
  const keyring_utils_1 = require("@metamask/keyring-utils");
14
16
  const utils_1 = require("@metamask/utils");
15
17
  const lodash_1 = require("lodash");
@@ -333,6 +335,11 @@ class AccountsController extends base_controller_1.BaseController {
333
335
  const internalAccounts = {};
334
336
  const { keyrings } = this.messenger.call('KeyringController:getState');
335
337
  for (const keyring of keyrings) {
338
+ // Money accounts are not treated as real accounts, they are owned by the `MoneyAccountController`, so
339
+ // we need to filter them out here.
340
+ if ((0, utils_2.isMoneyKeyringType)(keyring.type)) {
341
+ continue;
342
+ }
336
343
  const keyringTypeName = (0, utils_2.keyringTypeToName)(keyring.type);
337
344
  for (const address of keyring.accounts) {
338
345
  const internalAccount = __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_getInternalAccountFromAddressAndType).call(this, address, keyring);
@@ -470,6 +477,43 @@ _AccountsController_instances = new WeakSet(), _AccountsController_getAccountExp
470
477
  // Snap keyring is not available until the first account is created in the keyring
471
478
  // controller, so this might be undefined.
472
479
  return snapKeyring;
480
+ }, _AccountsController_getAccountFromSnapKeyringV1 = function _AccountsController_getAccountFromSnapKeyringV1(address) {
481
+ const snapKeyring = __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_getSnapKeyring).call(this);
482
+ // We need the Snap keyring to retrieve the account from its address.
483
+ if (!snapKeyring) {
484
+ return undefined;
485
+ }
486
+ // This might be undefined if the Snap deleted the account before
487
+ // reaching that point.
488
+ return snapKeyring.getAccountByAddress(address);
489
+ }, _AccountsController_getAccountFromSnapKeyringV2 = function _AccountsController_getAccountFromSnapKeyringV2(address) {
490
+ const keyrings = this.messenger.call('KeyringController:getKeyringsByType', v2_2.KeyringType.Snap);
491
+ // Snap keyring v2 are "per-Snaps", so we need to iterate over all of them to find the account.
492
+ for (const keyring of keyrings) {
493
+ if (keyring instanceof v2_1.SnapKeyring) {
494
+ // We use the synchronous method here since this method is used during `:stateChange` that are
495
+ // use synchronous handlers.
496
+ const account = keyring.lookupByAddress(address);
497
+ if (account) {
498
+ return {
499
+ ...account,
500
+ // We still have to use internal account for now, so we inject some metadata.
501
+ metadata: {
502
+ name: '',
503
+ importTime: Date.now(),
504
+ lastSelected: 0,
505
+ keyring: {
506
+ type: v2_2.KeyringType.Snap,
507
+ },
508
+ snap: {
509
+ id: keyring.snapId,
510
+ },
511
+ },
512
+ };
513
+ }
514
+ }
515
+ }
516
+ return undefined;
473
517
  }, _AccountsController_handleOnSnapKeyringAccountEvent = function _AccountsController_handleOnSnapKeyringAccountEvent(event, ...payload) {
474
518
  this.messenger.publish(event, ...payload);
475
519
  }, _AccountsController_handleOnKeyringStateChange = function _AccountsController_handleOnKeyringStateChange({ isUnlocked, keyrings, }) {
@@ -482,36 +526,25 @@ _AccountsController_instances = new WeakSet(), _AccountsController_getAccountExp
482
526
  }
483
527
  (0, logger_1.projectLogger)('Synchronizing accounts with keyrings (through :stateChange)...');
484
528
  // State patches.
485
- const generatePatch = () => {
486
- return {
487
- previous: {},
488
- added: [],
489
- updated: [],
490
- removed: [],
491
- };
492
- };
493
- const patches = {
494
- snap: generatePatch(),
495
- normal: generatePatch(),
496
- };
497
- // Gets the patch object based on the keyring type (since Snap accounts and other accounts
498
- // are handled differently).
499
- const patchOf = (type) => {
500
- if ((0, utils_2.isSnapKeyringType)(type)) {
501
- return patches.snap;
502
- }
503
- return patches.normal;
529
+ const patch = {
530
+ previous: {},
531
+ added: [],
532
+ updated: [],
533
+ removed: [],
504
534
  };
505
535
  // Create a map (with lower-cased addresses) of all existing accounts.
506
536
  for (const account of this.listMultichainAccounts()) {
507
537
  const address = account.address.toLowerCase();
508
- const patch = patchOf(account.metadata.keyring.type);
509
538
  patch.previous[address] = account;
510
539
  }
511
540
  // Go over all keyring changes and create patches out of it.
512
541
  const addresses = new Set();
513
542
  for (const keyring of keyrings) {
514
- const patch = patchOf(keyring.type);
543
+ // Money accounts are not treated as real accounts, they are owned by the `MoneyAccountController`, so
544
+ // we need to filter them out here.
545
+ if ((0, utils_2.isMoneyKeyringType)(keyring.type)) {
546
+ continue;
547
+ }
515
548
  for (const accountAddress of keyring.accounts) {
516
549
  // Lower-case address to use it in the `previous` map.
517
550
  const address = accountAddress.toLowerCase();
@@ -533,12 +566,10 @@ _AccountsController_instances = new WeakSet(), _AccountsController_getAccountExp
533
566
  }
534
567
  // We might have accounts associated with removed keyrings, so we iterate
535
568
  // over all previous known accounts and check against the keyring addresses.
536
- for (const patch of [patches.snap, patches.normal]) {
537
- for (const [address, account] of Object.entries(patch.previous)) {
538
- // If a previous address is not part of the new addesses, then it got removed.
539
- if (!addresses.has(address)) {
540
- patch.removed.push(account);
541
- }
569
+ for (const [address, account] of Object.entries(patch.previous)) {
570
+ // If a previous address is not part of the new addesses, then it got removed.
571
+ if (!addresses.has(address)) {
572
+ patch.removed.push(account);
542
573
  }
543
574
  }
544
575
  // Diff that we will use to publish events afterward.
@@ -548,29 +579,27 @@ _AccountsController_instances = new WeakSet(), _AccountsController_getAccountExp
548
579
  };
549
580
  __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_update).call(this, (state) => {
550
581
  const { internalAccounts, accountIdByAddress } = state;
551
- for (const patch of [patches.snap, patches.normal]) {
552
- for (const account of patch.removed) {
553
- delete internalAccounts.accounts[account.id];
554
- delete accountIdByAddress[account.address];
555
- diff.removed.push(account.id);
556
- }
557
- for (const added of patch.added) {
558
- const account = __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_getInternalAccountFromAddressAndType).call(this, added.address, added.keyring);
559
- if (account) {
560
- const accounts = Object.values(internalAccounts.accounts);
561
- // If it's the first account, we need to select it.
562
- const lastSelected = accounts.length === 0 ? __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_getLastSelectedIndex).call(this) : 0;
563
- internalAccounts.accounts[account.id] = {
564
- ...account,
565
- metadata: {
566
- ...account.metadata,
567
- importTime: Date.now(),
568
- lastSelected,
569
- },
570
- };
571
- accountIdByAddress[account.address] = account.id;
572
- diff.added.push(internalAccounts.accounts[account.id]);
573
- }
582
+ for (const account of patch.removed) {
583
+ delete internalAccounts.accounts[account.id];
584
+ delete accountIdByAddress[account.address];
585
+ diff.removed.push(account.id);
586
+ }
587
+ for (const added of patch.added) {
588
+ const account = __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_getInternalAccountFromAddressAndType).call(this, added.address, added.keyring);
589
+ if (account) {
590
+ const accounts = Object.values(internalAccounts.accounts);
591
+ // If it's the first account, we need to select it.
592
+ const lastSelected = accounts.length === 0 ? __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_getLastSelectedIndex).call(this) : 0;
593
+ internalAccounts.accounts[account.id] = {
594
+ ...account,
595
+ metadata: {
596
+ ...account.metadata,
597
+ importTime: Date.now(),
598
+ lastSelected,
599
+ },
600
+ };
601
+ accountIdByAddress[account.address] = account.id;
602
+ diff.added.push(internalAccounts.accounts[account.id]);
574
603
  }
575
604
  }
576
605
  },
@@ -631,36 +660,6 @@ _AccountsController_instances = new WeakSet(), _AccountsController_getAccountExp
631
660
  this.messenger.publish('AccountsController:selectedAccountChange', account);
632
661
  }
633
662
  }
634
- }, _AccountsController_handleOnSnapStateChange = function _AccountsController_handleOnSnapStateChange(snapState) {
635
- // Only check if Snaps changed in status.
636
- const { snaps } = snapState;
637
- const accounts = [];
638
- for (const account of this.listMultichainAccounts()) {
639
- if (account.metadata.snap) {
640
- const snap = snaps[account.metadata.snap.id];
641
- if (snap) {
642
- const enabled = snap.enabled && !snap.blocked;
643
- const metadata = account.metadata.snap;
644
- if (metadata.enabled !== enabled) {
645
- accounts.push({ id: account.id, enabled });
646
- }
647
- }
648
- else {
649
- // If Snap could not be found on the state, we consider it disabled.
650
- accounts.push({ id: account.id, enabled: false });
651
- }
652
- }
653
- }
654
- if (accounts.length > 0) {
655
- this.update((state) => {
656
- for (const { id, enabled } of accounts) {
657
- const account = state.internalAccounts.accounts[id];
658
- if (account.metadata.snap) {
659
- account.metadata.snap.enabled = enabled;
660
- }
661
- }
662
- });
663
- }
664
663
  }, _AccountsController_getLastSelectedAccount = function _AccountsController_getLastSelectedAccount(accounts) {
665
664
  const [accountToSelect] = accounts.sort((accountA, accountB) => {
666
665
  // sort by lastSelected descending
@@ -673,15 +672,16 @@ _AccountsController_instances = new WeakSet(), _AccountsController_getAccountExp
673
672
  // will always be higher than any already selected account index.
674
673
  return Date.now();
675
674
  }, _AccountsController_getInternalAccountFromAddressAndType = function _AccountsController_getInternalAccountFromAddressAndType(address, keyring) {
676
- if ((0, utils_2.isSnapKeyringType)(keyring.type)) {
677
- const snapKeyring = __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_getSnapKeyring).call(this);
678
- // We need the Snap keyring to retrieve the account from its address.
679
- if (!snapKeyring) {
680
- return undefined;
675
+ const isSnapKeyringV1 = (0, utils_2.isSnapKeyringType)(keyring.type);
676
+ const isSnapKeyringV2 = (0, utils_2.isSnapKeyringV2Type)(keyring.type);
677
+ if (isSnapKeyringV1 || isSnapKeyringV2) {
678
+ let account;
679
+ if (isSnapKeyringV1) {
680
+ account = __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_getAccountFromSnapKeyringV1).call(this, address);
681
+ }
682
+ else {
683
+ account = __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_getAccountFromSnapKeyringV2).call(this, address);
681
684
  }
682
- // This might be undefined if the Snap deleted the account before
683
- // reaching that point.
684
- let account = snapKeyring.getAccountByAddress(address);
685
685
  if (account) {
686
686
  // We force the copy here, to avoid mutating the reference returned by the Snap keyring.
687
687
  account = (0, lodash_1.cloneDeep)(account);
@@ -731,7 +731,6 @@ _AccountsController_instances = new WeakSet(), _AccountsController_getAccountExp
731
731
  });
732
732
  // DO NOT publish AccountsController:setSelectedAccount to prevent circular listener loops
733
733
  }, _AccountsController_subscribeToMessageEvents = function _AccountsController_subscribeToMessageEvents() {
734
- this.messenger.subscribe('SnapController:stateChange', (snapStateState) => __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_handleOnSnapStateChange).call(this, snapStateState));
735
734
  this.messenger.subscribe('KeyringController:stateChange', (keyringState) => __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_handleOnKeyringStateChange).call(this, keyringState));
736
735
  this.messenger.subscribe('SnapKeyring:accountAssetListUpdated', (snapAccountEvent) => __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_handleOnSnapKeyringAccountEvent).call(this, 'AccountsController:accountAssetListUpdated', snapAccountEvent));
737
736
  this.messenger.subscribe('SnapKeyring:accountBalancesUpdated', (snapAccountEvent) => __classPrivateFieldGet(this, _AccountsController_instances, "m", _AccountsController_handleOnSnapKeyringAccountEvent).call(this, 'AccountsController:accountBalancesUpdated', snapAccountEvent));