diff --git a/eslint-suppressions.json b/eslint-suppressions.json index 5ba155be96..77068ed231 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -83,11 +83,6 @@ "count": 1 } }, - "packages/account-tree-controller/src/rules/keyring.ts": { - "@typescript-eslint/explicit-function-return-type": { - "count": 2 - } - }, "packages/account-tree-controller/src/type-utils.ts": { "@typescript-eslint/naming-convention": { "count": 1 diff --git a/packages/account-tree-controller/CHANGELOG.md b/packages/account-tree-controller/CHANGELOG.md index e306123252..ee22ddd629 100644 --- a/packages/account-tree-controller/CHANGELOG.md +++ b/packages/account-tree-controller/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add group naming support for `KeyringType` (v2) ([#8885](https://github.com/MetaMask/core/pull/8885)) +- Add `KeyringType` (v2) in Snap matching rule ([#8885](https://github.com/MetaMask/core/pull/8885)) + ## [7.4.0] ### Added diff --git a/packages/account-tree-controller/src/rules/keyring.test.ts b/packages/account-tree-controller/src/rules/keyring.test.ts index 50c3cebe86..02f5bd947d 100644 --- a/packages/account-tree-controller/src/rules/keyring.test.ts +++ b/packages/account-tree-controller/src/rules/keyring.test.ts @@ -5,6 +5,7 @@ import { AccountWalletType, } from '@metamask/account-api'; import { EthAccountType, EthMethod, EthScope } from '@metamask/keyring-api'; +import { KeyringType } from '@metamask/keyring-api/v2'; import { KeyringTypes } from '@metamask/keyring-controller'; import type { InternalAccount } from '@metamask/keyring-internal-api'; @@ -21,10 +22,12 @@ import { KeyringRule, getAccountWalletNameFromKeyringType } from './keyring'; describe('keyring', () => { describe('getAccountWalletNameFromKeyringType', () => { - it.each(Object.values(KeyringTypes))( + it.each([...Object.values(KeyringTypes), ...Object.values(KeyringType)])( 'computes wallet name from: %s', (type) => { - const name = getAccountWalletNameFromKeyringType(type as KeyringTypes); + const name = getAccountWalletNameFromKeyringType( + type as KeyringTypes | KeyringType, + ); expect(name).toBeDefined(); expect(name.length).toBeGreaterThan(0); @@ -134,6 +137,14 @@ describe('keyring', () => { [KeyringTypes.qr, 'QR Account'], [KeyringTypes.trezor, 'Trezor Account'], [KeyringTypes.simple, 'Imported Account'], + [KeyringType.Lattice, 'Lattice Account'], + [KeyringType.Ledger, 'Ledger Account'], + [KeyringType.OneKey, 'OneKey Account'], + [KeyringType.Qr, 'QR Account'], + [KeyringType.Trezor, 'Trezor Account'], + [KeyringType.PrivateKey, 'Imported Account'], + [KeyringType.Hd, 'Account'], + [KeyringType.Snap, 'Snap Account'], ['unknown', 'Unknown Account'], ])( 'returns default name prefix for "$0" to be "$1"', diff --git a/packages/account-tree-controller/src/rules/keyring.ts b/packages/account-tree-controller/src/rules/keyring.ts index 13bb287266..9873988c95 100644 --- a/packages/account-tree-controller/src/rules/keyring.ts +++ b/packages/account-tree-controller/src/rules/keyring.ts @@ -1,6 +1,7 @@ import { AccountGroupType } from '@metamask/account-api'; import { AccountWalletType } from '@metamask/account-api'; import { toAccountGroupId, toAccountWalletId } from '@metamask/account-api'; +import { KeyringType } from '@metamask/keyring-api/v2'; import { KeyringTypes } from '@metamask/keyring-controller'; import type { InternalAccount } from '@metamask/keyring-internal-api'; @@ -15,31 +16,41 @@ import type { AccountWalletObjectOf } from '../wallet'; * @param type - Keyring's type. * @returns Wallet name. */ -export function getAccountWalletNameFromKeyringType(type: KeyringTypes) { +export function getAccountWalletNameFromKeyringType( + type: KeyringTypes | KeyringType, +): string { switch (type) { + case KeyringType.PrivateKey: case KeyringTypes.simple: { return 'Imported accounts'; } + case KeyringType.Trezor: case KeyringTypes.trezor: { return 'Trezor'; } + case KeyringType.OneKey: case KeyringTypes.oneKey: { return 'OneKey'; } + case KeyringType.Ledger: case KeyringTypes.ledger: { return 'Ledger'; } + case KeyringType.Lattice: case KeyringTypes.lattice: { return 'Lattice'; } + case KeyringType.Qr: case KeyringTypes.qr: { return 'QR'; } // Those keyrings should never really be used in such context since they // should be used by other grouping rules. + case KeyringType.Hd: case KeyringTypes.hd: { return 'HD Wallet'; } + case KeyringType.Snap: case KeyringTypes.snap: { return 'Snap Wallet'; } @@ -56,31 +67,41 @@ export function getAccountWalletNameFromKeyringType(type: KeyringTypes) { * @param type - Keyring's type. * @returns Wallet name. */ -export function getAccountGroupPrefixFromKeyringType(type: KeyringTypes) { +export function getAccountGroupPrefixFromKeyringType( + type: KeyringTypes | KeyringType, +): string { switch (type) { + case KeyringType.PrivateKey: case KeyringTypes.simple: { return 'Imported Account'; } + case KeyringType.Trezor: case KeyringTypes.trezor: { return 'Trezor Account'; } + case KeyringType.OneKey: case KeyringTypes.oneKey: { return 'OneKey Account'; } + case KeyringType.Ledger: case KeyringTypes.ledger: { return 'Ledger Account'; } + case KeyringType.Lattice: case KeyringTypes.lattice: { return 'Lattice Account'; } + case KeyringType.Qr: case KeyringTypes.qr: { return 'QR Account'; } // Those keyrings should never really be used in such context since they // should be used by other grouping rules. + case KeyringType.Hd: case KeyringTypes.hd: { return 'Account'; } + case KeyringType.Snap: case KeyringTypes.snap: { return 'Snap Account'; } diff --git a/packages/account-tree-controller/src/rules/snap.test.ts b/packages/account-tree-controller/src/rules/snap.test.ts index d0bb89cbdc..1309b23ef7 100644 --- a/packages/account-tree-controller/src/rules/snap.test.ts +++ b/packages/account-tree-controller/src/rules/snap.test.ts @@ -5,6 +5,7 @@ import { AccountWalletType, } from '@metamask/account-api'; import { EthAccountType, EthMethod, EthScope } from '@metamask/keyring-api'; +import { KeyringType } from '@metamask/keyring-api/v2'; import { KeyringTypes } from '@metamask/keyring-controller'; import type { InternalAccount } from '@metamask/keyring-internal-api'; import type { SnapId } from '@metamask/snaps-sdk'; @@ -54,6 +55,22 @@ const MOCK_SNAP_ACCOUNT_1: InternalAccount = { }, }; +const MOCK_SNAP_ACCOUNT_V2: InternalAccount = { + id: 'mock-snap-account-id-v2', + address: '0xDEF', + options: {}, + methods: [...ETH_EOA_METHODS], + type: EthAccountType.Eoa, + scopes: [EthScope.Eoa], + metadata: { + name: 'Snap Account V2', + keyring: { type: KeyringType.Snap }, + snap: { id: MOCK_SNAP_1.id }, + importTime: 0, + lastSelected: 0, + }, +}; + describe('SnapRule', () => { describe('match', () => { it('returns undefined for a snap that is enabled but blocked', () => { @@ -99,6 +116,57 @@ describe('SnapRule', () => { expect(rule.match(MOCK_SNAP_ACCOUNT_1)).toBeDefined(); }); + + it('returns a result for a v2 snap keyring type account', () => { + const messenger = getRootMessenger(); + const accountTreeControllerMessenger = + getAccountTreeControllerMessenger(messenger); + const rule = new SnapRule(accountTreeControllerMessenger); + + messenger.registerActionHandler( + 'SnapController:getSnap', + () => MOCK_SNAP_1 as unknown as Snap, + ); + + expect(rule.match(MOCK_SNAP_ACCOUNT_V2)).toBeDefined(); + }); + + it('returns undefined for a v2 snap keyring type account when snap is blocked', () => { + const messenger = getRootMessenger(); + const accountTreeControllerMessenger = + getAccountTreeControllerMessenger(messenger); + const rule = new SnapRule(accountTreeControllerMessenger); + + const blockedSnap = { ...MOCK_SNAP_1, enabled: true, blocked: true }; + messenger.registerActionHandler( + 'SnapController:getSnap', + () => blockedSnap as unknown as Snap, + ); + + expect(rule.match(MOCK_SNAP_ACCOUNT_V2)).toBeUndefined(); + }); + + it('returns undefined for account with unknown keyring type', () => { + const messenger = getRootMessenger(); + const accountTreeControllerMessenger = + getAccountTreeControllerMessenger(messenger); + const rule = new SnapRule(accountTreeControllerMessenger); + + messenger.registerActionHandler( + 'SnapController:getSnap', + () => MOCK_SNAP_1 as unknown as Snap, + ); + + const accountWithUnknownKeyring: InternalAccount = { + ...MOCK_SNAP_ACCOUNT_1, + metadata: { + ...MOCK_SNAP_ACCOUNT_1.metadata, + keyring: { type: 'unknown-keyring-type' }, + }, + }; + + expect(rule.match(accountWithUnknownKeyring)).toBeUndefined(); + }); }); describe('getComputedAccountGroupName', () => { diff --git a/packages/account-tree-controller/src/rules/snap.ts b/packages/account-tree-controller/src/rules/snap.ts index 97fc3c6b4c..085242db78 100644 --- a/packages/account-tree-controller/src/rules/snap.ts +++ b/packages/account-tree-controller/src/rules/snap.ts @@ -1,5 +1,6 @@ import { AccountGroupType, AccountWalletType } from '@metamask/account-api'; import { toAccountWalletId, toAccountGroupId } from '@metamask/account-api'; +import { KeyringType } from '@metamask/keyring-api/v2'; import { KeyringTypes } from '@metamask/keyring-controller'; import type { InternalAccount } from '@metamask/keyring-internal-api'; import type { SnapId } from '@metamask/snaps-sdk'; @@ -105,10 +106,10 @@ export class SnapRule return false; } - return ( - account.metadata.keyring.type === (KeyringTypes.snap as string) && - snap.enabled && - !snap.blocked - ); + const keyringType = account.metadata.keyring.type; + const hasSnapKeyringType = + keyringType === KeyringTypes.snap || keyringType === KeyringType.Snap; + + return hasSnapKeyringType && snap.enabled && !snap.blocked; } }