From 25a6496f5843fa139a0afc7924907d9de11dde16 Mon Sep 17 00:00:00 2001 From: Jongsun Suh Date: Wed, 27 Nov 2024 08:50:14 -0500 Subject: [PATCH] Merge `MetamaskState` defined in `metametrics-controller` into `initialMetamaskState` --- .../controllers/metametrics-controller.ts | 137 ++++++++---------- shared/constants/metametrics.ts | 4 +- ui/ducks/metamask/constants.ts | 27 +++- 3 files changed, 86 insertions(+), 82 deletions(-) diff --git a/app/scripts/controllers/metametrics-controller.ts b/app/scripts/controllers/metametrics-controller.ts index b2b78a4e6406..960773b81814 100644 --- a/app/scripts/controllers/metametrics-controller.ts +++ b/app/scripts/controllers/metametrics-controller.ts @@ -10,8 +10,7 @@ import { } from 'lodash'; import { bufferToHex, keccak } from 'ethereumjs-util'; import { v4 as uuidv4 } from 'uuid'; -import { NameControllerState, NameType } from '@metamask/name-controller'; -import { AccountsControllerState } from '@metamask/accounts-controller'; +import { NameType } from '@metamask/name-controller'; import { getErrorMessage, Hex, @@ -23,14 +22,9 @@ import { NetworkControllerGetNetworkClientByIdAction, NetworkControllerGetStateAction, NetworkControllerNetworkDidChangeEvent, - NetworkState, } from '@metamask/network-controller'; import { Browser } from 'webextension-polyfill'; -import { - Nft, - NftControllerState, - TokensControllerState, -} from '@metamask/assets-controllers'; +import { Nft } from '@metamask/assets-controllers'; import { captureException as sentryCaptureException } from '@sentry/browser'; import { BaseController, @@ -38,7 +32,7 @@ import { ControllerStateChangeEvent, RestrictedControllerMessenger, } from '@metamask/base-controller'; -import { AddressBookControllerState } from '@metamask/address-book-controller'; +import type { MemStoreControllersComposedState } from '../metamask-controller-stores'; import { ENVIRONMENT_TYPE_BACKGROUND } from '../../../shared/constants/app'; import { METAMETRICS_ANONYMOUS_ID, @@ -65,7 +59,6 @@ import { AnonymousTransactionMetaMetricsEvent, TransactionMetaMetricsEvent, } from '../../../shared/constants/transaction'; -import { LedgerTransportTypes } from '../../../shared/constants/hardware-wallets'; import Analytics from '../lib/segment/analytics'; ///: BEGIN:ONLY_INCLUDE_IF(build-main) @@ -144,39 +137,6 @@ const exceptionsToFilter: Record = { */ type SegmentEventType = 'identify' | 'track' | 'page'; -// TODO: Complete MetaMaskState by adding the full state definition and relocate it after the background is converted to TypeScript. -export type MetaMaskState = { - ledgerTransportType: LedgerTransportTypes; - networkConfigurationsByChainId: NetworkState['networkConfigurationsByChainId']; - internalAccounts: AccountsControllerState['internalAccounts']; - allNfts: NftControllerState['allNfts']; - allTokens: TokensControllerState['allTokens']; - theme: string; - participateInMetaMetrics: boolean; - dataCollectionForMarketing: boolean; - ShowNativeTokenAsMainBalance: boolean; - useNftDetection: PreferencesControllerState['useNftDetection']; - openSeaEnabled: PreferencesControllerState['openSeaEnabled']; - securityAlertsEnabled: PreferencesControllerState['securityAlertsEnabled']; - useTokenDetection: PreferencesControllerState['useTokenDetection']; - tokenSortConfig: PreferencesControllerState['preferences']['tokenSortConfig']; - names: NameControllerState['names']; - security_providers: string[]; - addressBook: AddressBookControllerState['addressBook']; - currentCurrency: string; - preferences: { - privacyMode: PreferencesControllerState['preferences']['privacyMode']; - tokenNetworkFilter: string[]; - }; - ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) - custodyAccountDetails: { - [address: string]: { - custodianName: string; - }; - }; - ///: END:ONLY_INCLUDE_IF -}; - /** * {@link MetaMetricsController}'s metadata. * @@ -1004,7 +964,7 @@ export default class MetaMetricsController extends BaseController< } } - handleMetaMaskStateUpdate(newState: MetaMaskState): void { + handleMetaMaskStateUpdate(newState: MemStoreControllersComposedState): void { const userTraits = this._buildUserTraitsObject(newState); if (userTraits) { this.identify(userTraits); @@ -1169,73 +1129,85 @@ export default class MetaMetricsController extends BaseController< * @returns traits that have changed since last update */ _buildUserTraitsObject( - metamaskState: MetaMaskState, + metamaskState: MemStoreControllersComposedState, ): Partial | null { ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) const mmiAccountAddress = - metamaskState.custodyAccountDetails && - Object.keys(metamaskState.custodyAccountDetails).length - ? Object.keys(metamaskState.custodyAccountDetails)[0] + metamaskState.CustodyController.custodyAccountDetails && + Object.keys(metamaskState.CustodyController.custodyAccountDetails).length + ? Object.keys(metamaskState.CustodyController.custodyAccountDetails)[0] : null; ///: END:ONLY_INCLUDE_IF const { traits, previousUserTraits } = this.state; const currentTraits = { [MetaMetricsUserTrait.AddressBookEntries]: sum( - Object.values(metamaskState.addressBook).map(size), + Object.values(metamaskState.AddressBookController.addressBook).map( + size, + ), ), [MetaMetricsUserTrait.InstallDateExt]: traits[MetaMetricsUserTrait.InstallDateExt] || '', [MetaMetricsUserTrait.LedgerConnectionType]: - metamaskState.ledgerTransportType, + metamaskState.PreferencesController.ledgerTransportType, [MetaMetricsUserTrait.NetworksAdded]: Object.values( - metamaskState.networkConfigurationsByChainId, + metamaskState.NetworkController.networkConfigurationsByChainId, ).map((networkConfiguration) => networkConfiguration.chainId), [MetaMetricsUserTrait.NetworksWithoutTicker]: Object.values( - metamaskState.networkConfigurationsByChainId, + metamaskState.NetworkController.networkConfigurationsByChainId, ) .filter(({ nativeCurrency }) => !nativeCurrency) .map(({ chainId }) => chainId), [MetaMetricsUserTrait.NftAutodetectionEnabled]: - metamaskState.useNftDetection, + metamaskState.PreferencesController.useNftDetection, [MetaMetricsUserTrait.NumberOfAccounts]: Object.values( - metamaskState.internalAccounts.accounts, + metamaskState.AccountsController.internalAccounts.accounts, ).length, [MetaMetricsUserTrait.NumberOfNftCollections]: - this.#getAllUniqueNFTAddressesLength(metamaskState.allNfts), + this.#getAllUniqueNFTAddressesLength( + metamaskState.NftController.allNfts, + ), [MetaMetricsUserTrait.NumberOfNfts]: this.#getAllNFTsFlattened( - metamaskState.allNfts, + metamaskState.NftController.allNfts, ).length, [MetaMetricsUserTrait.NumberOfTokens]: this.#getNumberOfTokens( - metamaskState.allTokens, + metamaskState.TokensController.allTokens, ), - [MetaMetricsUserTrait.OpenSeaApiEnabled]: metamaskState.openSeaEnabled, + [MetaMetricsUserTrait.OpenSeaApiEnabled]: + metamaskState.PreferencesController.openSeaEnabled, [MetaMetricsUserTrait.ThreeBoxEnabled]: false, // deprecated, hard-coded as false - [MetaMetricsUserTrait.Theme]: metamaskState.theme || 'default', + [MetaMetricsUserTrait.Theme]: + metamaskState.PreferencesController.theme || 'default', [MetaMetricsUserTrait.TokenDetectionEnabled]: - metamaskState.useTokenDetection, + metamaskState.PreferencesController.useTokenDetection, [MetaMetricsUserTrait.ShowNativeTokenAsMainBalance]: - metamaskState.ShowNativeTokenAsMainBalance, - [MetaMetricsUserTrait.CurrentCurrency]: metamaskState.currentCurrency, + metamaskState.PreferencesController.preferences + .showNativeTokenAsMainBalance, + [MetaMetricsUserTrait.CurrentCurrency]: + metamaskState.CurrencyController.currentCurrency, ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) [MetaMetricsUserTrait.MmiExtensionId]: this.#extension?.runtime?.id, [MetaMetricsUserTrait.MmiAccountAddress]: mmiAccountAddress ?? null, [MetaMetricsUserTrait.MmiIsCustodian]: Boolean(mmiAccountAddress), ///: END:ONLY_INCLUDE_IF - [MetaMetricsUserTrait.SecurityProviders]: - metamaskState.securityAlertsEnabled ? ['blockaid'] : [], + [MetaMetricsUserTrait.SecurityProviders]: metamaskState + .PreferencesController.securityAlertsEnabled + ? ['blockaid'] + : [], [MetaMetricsUserTrait.PetnameAddressCount]: this.#getPetnameAddressCount(metamaskState), [MetaMetricsUserTrait.IsMetricsOptedIn]: - metamaskState.participateInMetaMetrics, + metamaskState.MetaMetricsController.participateInMetaMetrics, [MetaMetricsUserTrait.HasMarketingConsent]: - metamaskState.dataCollectionForMarketing, + metamaskState.MetaMetricsController.dataCollectionForMarketing, [MetaMetricsUserTrait.TokenSortPreference]: - metamaskState.tokenSortConfig?.key || '', + metamaskState.PreferencesController.preferences.tokenSortConfig?.key || + '', [MetaMetricsUserTrait.PrivacyModeEnabled]: - metamaskState.preferences.privacyMode, + metamaskState.PreferencesController.preferences.privacyMode, [MetaMetricsUserTrait.NetworkFilterPreference]: Object.keys( - metamaskState.preferences.tokenNetworkFilter || {}, + metamaskState.PreferencesController.preferences.tokenNetworkFilter || + {}, ), }; @@ -1299,11 +1271,15 @@ export default class MetaMetricsController extends BaseController< * * @param allNfts */ - #getAllNFTsFlattened = memoize((allNfts: MetaMaskState['allNfts'] = {}) => { - return Object.values(allNfts).reduce((result: Nft[], chainNFTs) => { - return result.concat(...Object.values(chainNFTs)); - }, []); - }); + #getAllNFTsFlattened = memoize( + ( + allNfts: MemStoreControllersComposedState['NftController']['allNfts'] = {}, + ) => { + return Object.values(allNfts).reduce((result: Nft[], chainNFTs) => { + return result.concat(...Object.values(chainNFTs)); + }, []); + }, + ); /** * Returns the number of unique NFT addresses the user @@ -1312,7 +1288,7 @@ export default class MetaMetricsController extends BaseController< * @param allNfts */ #getAllUniqueNFTAddressesLength( - allNfts: MetaMaskState['allNfts'] = {}, + allNfts: MemStoreControllersComposedState['NftController']['allNfts'] = {}, ): number { const allNFTAddresses = this.#getAllNFTsFlattened(allNfts).map( (nft) => nft.address, @@ -1325,7 +1301,9 @@ export default class MetaMetricsController extends BaseController< * @param allTokens * @returns number of unique token addresses */ - #getNumberOfTokens(allTokens: MetaMaskState['allTokens']): number { + #getNumberOfTokens( + allTokens: MemStoreControllersComposedState['TokensController']['allTokens'], + ): number { return Object.values(allTokens).reduce((result, accountsByChain) => { return result + sum(Object.values(accountsByChain).map(size)); }, 0); @@ -1549,8 +1527,11 @@ export default class MetaMetricsController extends BaseController< * * @param metamaskState */ - #getPetnameAddressCount(metamaskState: MetaMaskState): number { - const addressNames = metamaskState.names?.[NameType.ETHEREUM_ADDRESS] ?? {}; + #getPetnameAddressCount( + metamaskState: MemStoreControllersComposedState, + ): number { + const addressNames = + metamaskState.NameController.names?.[NameType.ETHEREUM_ADDRESS] ?? {}; return Object.keys(addressNames).reduce((totalCount, address) => { const addressEntry = addressNames[address]; diff --git a/shared/constants/metametrics.ts b/shared/constants/metametrics.ts index c87af10544c3..22998d09bf1d 100644 --- a/shared/constants/metametrics.ts +++ b/shared/constants/metametrics.ts @@ -455,11 +455,11 @@ export type MetaMetricsUserTraits = { /** * Does the user opt in for metrics */ - is_metrics_opted_in?: boolean; + is_metrics_opted_in?: boolean | null; /** * Does the user accepted marketing consent */ - has_marketing_consent?: boolean; + has_marketing_consent?: boolean | null; /** * The date the extension was installed. */ diff --git a/ui/ducks/metamask/constants.ts b/ui/ducks/metamask/constants.ts index d7b4961cf040..bfbed2ccb654 100644 --- a/ui/ducks/metamask/constants.ts +++ b/ui/ducks/metamask/constants.ts @@ -1,6 +1,13 @@ -import { Preferences } from '../../../app/scripts/controllers/preferences-controller'; +import { NameControllerState } from '@metamask/name-controller'; +import { + getDefaultPreferencesControllerState, + Preferences, +} from '../../../app/scripts/controllers/preferences-controller'; import { MemStoreControllersComposedState } from '../../../app/scripts/metamask-controller-stores'; -import { DEFAULT_AUTO_LOCK_TIME_LIMIT } from '../../../shared/constants/preferences'; +import { + DEFAULT_AUTO_LOCK_TIME_LIMIT, + ThemeType, +} from '../../../shared/constants/preferences'; export const initialMetamaskState: Partial<{ [ControllerName in keyof MemStoreControllersComposedState]: Partial< @@ -26,6 +33,7 @@ export const initialMetamaskState: Partial<{ approvalFlows: [], }, CurrencyController: { + currentCurrency: 'usd', currencyRates: { ETH: { conversionRate: null, @@ -50,18 +58,29 @@ export const initialMetamaskState: Partial<{ participateInMetaMetrics: null, dataCollectionForMarketing: null, }, + NameController: { + names: {} as NameControllerState['names'], + }, NetworkController: { selectedNetworkClientId: '', networkConfigurationsByChainId: {}, networksMetadata: {}, }, + NftController: { + allNfts: {}, + }, OnboardingController: { firstTimeFlowType: null, completedOnboarding: false, }, PreferencesController: { + theme: ThemeType.os, useBlockie: false, use4ByteResolution: true, + useNftDetection: false, + useTokenDetection: true, + openSeaEnabled: false, + securityAlertsEnabled: false, featureFlags: {}, currentLocale: '', knownMethodData: {}, @@ -70,13 +89,17 @@ export const initialMetamaskState: Partial<{ autoLockTimeLimit: DEFAULT_AUTO_LOCK_TIME_LIMIT, showExtensionInFullSizeView: false, showFiatInTestnets: false, + showNativeTokenAsMainBalance: true, showTestNetworks: false, smartTransactionsOptInStatus: true, petnamesEnabled: true, featureNotificationsEnabled: false, privacyMode: false, showMultiRpcModal: false, + tokenSortConfig: {}, + tokenNetworkFilter: {}, } as Preferences, + ...getDefaultPreferencesControllerState(), }, SignatureController: { unapprovedPersonalMsgs: {},