From 320415ca9dfc9e5c6016817abd7cb08e3470f3cc Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 4 Jan 2024 12:21:20 -0330 Subject: [PATCH] chore(preferences-controller): Clean up types The `PreferencesController` types are now declared as types rather than interfaces, in accordance with our conventions, and they are now fully documented. The state properties have also been alphabetized so that they are easier to maintain. Additionally, the old "ContactEntry" type has been renamed to "Identity", which is a more accurate name for what it is being used for here. --- .../src/AccountTrackerController.test.ts | 30 ++-- .../src/PreferencesController.ts | 139 ++++++++++++------ 2 files changed, 109 insertions(+), 60 deletions(-) diff --git a/packages/assets-controllers/src/AccountTrackerController.test.ts b/packages/assets-controllers/src/AccountTrackerController.test.ts index 6a4ef05d74c..e9cf3aed6d2 100644 --- a/packages/assets-controllers/src/AccountTrackerController.test.ts +++ b/packages/assets-controllers/src/AccountTrackerController.test.ts @@ -1,6 +1,6 @@ import { query } from '@metamask/controller-utils'; import HttpProvider from '@metamask/ethjs-provider-http'; -import type { ContactEntry } from '@metamask/preferences-controller'; +import type { Identity } from '@metamask/preferences-controller'; import { PreferencesController } from '@metamask/preferences-controller'; import * as sinon from 'sinon'; @@ -105,8 +105,8 @@ describe('AccountTrackerController', () => { onPreferencesStateChange: sinon.stub(), getIdentities: () => { return { - bar: {} as ContactEntry, - baz: {} as ContactEntry, + bar: {} as Identity, + baz: {} as Identity, }; }, getSelectedAddress: () => '0x0', @@ -158,7 +158,7 @@ describe('AccountTrackerController', () => { { onPreferencesStateChange: sinon.stub(), getIdentities: () => { - return { [ADDRESS_1]: {} as ContactEntry }; + return { [ADDRESS_1]: {} as Identity }; }, getSelectedAddress: () => ADDRESS_1, getMultiAccountBalancesEnabled: () => true, @@ -196,8 +196,8 @@ describe('AccountTrackerController', () => { onPreferencesStateChange: sinon.stub(), getIdentities: () => { return { - [ADDRESS_1]: {} as ContactEntry, - [ADDRESS_2]: {} as ContactEntry, + [ADDRESS_1]: {} as Identity, + [ADDRESS_2]: {} as Identity, }; }, getSelectedAddress: () => ADDRESS_1, @@ -234,8 +234,8 @@ describe('AccountTrackerController', () => { onPreferencesStateChange: sinon.stub(), getIdentities: () => { return { - [ADDRESS_1]: {} as ContactEntry, - [ADDRESS_2]: {} as ContactEntry, + [ADDRESS_1]: {} as Identity, + [ADDRESS_2]: {} as Identity, }; }, getSelectedAddress: () => ADDRESS_1, @@ -270,8 +270,8 @@ describe('AccountTrackerController', () => { onPreferencesStateChange: sinon.stub(), getIdentities: () => { return { - bar: {} as ContactEntry, - baz: {} as ContactEntry, + bar: {} as Identity, + baz: {} as Identity, }; }, getSelectedAddress: () => '0x0', @@ -331,7 +331,7 @@ describe('AccountTrackerController', () => { const controller = new AccountTrackerController({ onPreferencesStateChange: sinon.stub(), getIdentities: () => { - return { [ADDRESS_1]: {} as ContactEntry }; + return { [ADDRESS_1]: {} as Identity }; }, getSelectedAddress: () => ADDRESS_1, getMultiAccountBalancesEnabled: () => true, @@ -376,8 +376,8 @@ describe('AccountTrackerController', () => { onPreferencesStateChange: sinon.stub(), getIdentities: () => { return { - [ADDRESS_1]: {} as ContactEntry, - [ADDRESS_2]: {} as ContactEntry, + [ADDRESS_1]: {} as Identity, + [ADDRESS_2]: {} as Identity, }; }, getSelectedAddress: () => ADDRESS_1, @@ -420,8 +420,8 @@ describe('AccountTrackerController', () => { onPreferencesStateChange: sinon.stub(), getIdentities: () => { return { - [ADDRESS_1]: {} as ContactEntry, - [ADDRESS_2]: {} as ContactEntry, + [ADDRESS_1]: {} as Identity, + [ADDRESS_2]: {} as Identity, }; }, getSelectedAddress: () => ADDRESS_1, diff --git a/packages/preferences-controller/src/PreferencesController.ts b/packages/preferences-controller/src/PreferencesController.ts index e04f41bdafd..01b3ecb08c3 100644 --- a/packages/preferences-controller/src/PreferencesController.ts +++ b/packages/preferences-controller/src/PreferencesController.ts @@ -1,63 +1,112 @@ -import type { BaseConfig, BaseState } from '@metamask/base-controller'; +import type { BaseConfig } from '@metamask/base-controller'; import { BaseControllerV1 } from '@metamask/base-controller'; import { toChecksumHexAddress } from '@metamask/controller-utils'; import { ETHERSCAN_SUPPORTED_CHAIN_IDS } from './constants'; /** - * ContactEntry representation. - * - * @property address - Hex address of a recipient account - * @property name - Nickname associated with this address - * @property importTime - Data time when an account as created/imported + * A representation of a MetaMask identity */ -// This interface was created before this ESLint rule was added. -// Convert to a `type` in a future major version. -// eslint-disable-next-line @typescript-eslint/consistent-type-definitions -export interface ContactEntry { +export type Identity = { + /** + * The address of the identity + */ address: string; - name: string; + /** + * The timestamp for when this identity was first added + */ importTime?: number; -} + /** + * The name of the identity + */ + name: string; +}; +/** + * A type union of the name for each chain that is supported by Etherscan or + * an Etherscan-compatible service. + */ export type EtherscanSupportedChains = keyof typeof ETHERSCAN_SUPPORTED_CHAIN_IDS; +/** + * A type union of the chain ID for each chain that is supported by Etherscan + * or an Etherscan-compatible service. + */ export type EtherscanSupportedHexChainId = (typeof ETHERSCAN_SUPPORTED_CHAIN_IDS)[EtherscanSupportedChains]; /** - * @type PreferencesState - * * Preferences controller state - * @property featureFlags - Map of specific features to enable or disable - * @property identities - Map of addresses to ContactEntry objects - * @property lostIdentities - Map of lost addresses to ContactEntry objects - * @property selectedAddress - Current coinbase account */ -// This interface was created before this ESLint rule was added. -// Convert to a `type` in a future major version. -// eslint-disable-next-line @typescript-eslint/consistent-type-definitions -export interface PreferencesState extends BaseState { - featureFlags: { [feature: string]: boolean }; - ipfsGateway: string; - identities: { [address: string]: ContactEntry }; - lostIdentities: { [address: string]: ContactEntry }; - selectedAddress: string; - useTokenDetection: boolean; - useNftDetection: boolean; - openSeaEnabled: boolean; - securityAlertsEnabled: boolean; - isMultiAccountBalancesEnabled: boolean; +export type PreferencesState = { + /** + * A map of RPC method names to enabled state (true is enabled, false is disabled) + */ disabledRpcMethodPreferences: { [methodName: string]: boolean; }; - showTestNetworks: boolean; + /** + * Map of specific features to enable or disable + */ + featureFlags: { [feature: string]: boolean }; + /** + * Map of addresses to Identity objects + */ + identities: { [address: string]: Identity }; + /** + * The configured IPFS gateway + */ + ipfsGateway: string; + /** + * Controls whether IPFS is enabled or not + */ isIpfsGatewayEnabled: boolean; + /** + * Controls whether multi-account balances are enabled or not + */ + isMultiAccountBalancesEnabled: boolean; + /** + * Map of lost addresses to Identity objects + */ + lostIdentities: { [address: string]: Identity }; + /** + * The name of the controller + * + * @deprecated This property is never set, and will be removed in a future release + */ + name?: string; + /** + * Controls whether the OpenSea API is used + */ + openSeaEnabled: boolean; + /** + * Controls whether "security alerts" are enabled + */ + securityAlertsEnabled: boolean; + /** + * The current selected address + */ + selectedAddress: string; + /** + * Controls whether incoming transactions are enabled, per-chain (for Etherscan-supported chains) + */ showIncomingTransactions: { [chainId in EtherscanSupportedHexChainId]: boolean; }; -} + /** + * Controls whether test networks are shown in the wallet + */ + showTestNetworks: boolean; + /** + * Controls whether NFT detection is enabled + */ + useNftDetection: boolean; + /** + * Controls whether token detection is enabled + */ + useTokenDetection: boolean; +}; /** * Controller that stores shared settings and exposes convenience methods @@ -80,21 +129,18 @@ export class PreferencesController extends BaseControllerV1< constructor(config?: Partial, state?: Partial) { super(config, state); this.defaultState = { + disabledRpcMethodPreferences: { + eth_sign: false, + }, featureFlags: {}, identities: {}, ipfsGateway: 'https://ipfs.io/ipfs/', + isIpfsGatewayEnabled: true, + isMultiAccountBalancesEnabled: true, lostIdentities: {}, - selectedAddress: '', - useTokenDetection: true, - useNftDetection: false, openSeaEnabled: false, securityAlertsEnabled: false, - isMultiAccountBalancesEnabled: true, - disabledRpcMethodPreferences: { - eth_sign: false, - }, - showTestNetworks: false, - isIpfsGatewayEnabled: true, + selectedAddress: '', showIncomingTransactions: { [ETHERSCAN_SUPPORTED_CHAIN_IDS.MAINNET]: true, [ETHERSCAN_SUPPORTED_CHAIN_IDS.GOERLI]: true, @@ -116,6 +162,9 @@ export class PreferencesController extends BaseControllerV1< [ETHERSCAN_SUPPORTED_CHAIN_IDS.MOONRIVER]: true, [ETHERSCAN_SUPPORTED_CHAIN_IDS.GNOSIS]: true, }, + showTestNetworks: false, + useNftDetection: false, + useTokenDetection: true, }; this.initialize(); } @@ -198,7 +247,7 @@ export class PreferencesController extends BaseControllerV1< toChecksumHexAddress(address), ); const { identities, lostIdentities } = this.state; - const newlyLost: { [address: string]: ContactEntry } = {}; + const newlyLost: { [address: string]: Identity } = {}; for (const [address, identity] of Object.entries(identities)) { if (!addresses.includes(address)) { @@ -237,7 +286,7 @@ export class PreferencesController extends BaseControllerV1< ); const oldIdentities = this.state.identities; const identities = addresses.reduce( - (ids: { [address: string]: ContactEntry }, address, index) => { + (ids: { [address: string]: Identity }, address, index) => { ids[address] = oldIdentities[address] || { address, name: `Account ${index + 1}`,