diff --git a/.js.env.example b/.js.env.example index 4648ae1b482..a25bdac2698 100644 --- a/.js.env.example +++ b/.js.env.example @@ -45,7 +45,6 @@ export WALLET_CONNECT_PROJECT_ID="" # CDN for blockaid files export BLOCKAID_FILE_CDN="" export BLOCKAID_PUBLIC_KEY="" -export MM_BLOCKAID_UI_ENABLED="" # Default PORT for metro export WATCHER_PORT=8081 diff --git a/app/components/Nav/App/index.js b/app/components/Nav/App/index.js index 79af8053345..4b43ede6c99 100644 --- a/app/components/Nav/App/index.js +++ b/app/components/Nav/App/index.js @@ -44,7 +44,6 @@ import { } from '../../../actions/navigation'; import { findRouteNameFromNavigatorState } from '../../../util/general'; import { Authentication } from '../../../core/'; -import { isBlockaidFeatureEnabled } from '../../../util/blockaid'; import { useTheme } from '../../../util/theme'; import Device from '../../../util/device'; import SDKConnect from '../../../core/SDKConnect/SDKConnect'; @@ -783,7 +782,7 @@ const App = ({ userLoggedIn }) => { { ///: END:ONLY_INCLUDE_IF } - {isBlockaidFeatureEnabled() && } + - props.navigation.navigate(Routes.SETTINGS_VIEW, { - screen: Routes.SETTINGS.EXPERIMENTAL_SETTINGS, - }), - }, - ], - ] as WhatsNew['slides']) - : []), + ...([ + [ + { + type: 'title', + title: strings('whats_new.blockaid.title'), + }, + { + type: 'image', + image: require('../../../images/whats_new_blockaid.png'), + }, + { + type: 'description', + description: strings('whats_new.blockaid.description_1'), + }, + { + type: 'description', + description: strings('whats_new.blockaid.description_2'), + }, + { + type: 'description', + description: strings('whats_new.blockaid.description_3'), + }, + { + type: 'button', + buttonText: strings('whats_new.blockaid.got_it'), + buttonType: 'blue', + onPress: (props) => + props.navigation.navigate(Routes.SETTINGS_VIEW, { + screen: Routes.SETTINGS.EXPERIMENTAL_SETTINGS, + }), + }, + ], + ] as WhatsNew['slides']), [ { type: 'image', diff --git a/app/components/Views/Settings/SecuritySettings/SecuritySettings.tsx b/app/components/Views/Settings/SecuritySettings/SecuritySettings.tsx index e00bf5b6ea0..871437b5fab 100644 --- a/app/components/Views/Settings/SecuritySettings/SecuritySettings.tsx +++ b/app/components/Views/Settings/SecuritySettings/SecuritySettings.tsx @@ -116,7 +116,6 @@ import Button, { ButtonSize, ButtonWidthTypes, } from '../../../../component-library/components/Buttons/Button'; -import { isBlockaidFeatureEnabled } from '../../../../util/blockaid'; import trackErrorAsAnalytics from '../../../../util/metrics/TrackError/trackErrorAsAnalytics'; import BasicFunctionalityComponent from '../../../UI/BasicFunctionality/BasicFunctionality'; import Routes from '../../../../constants/navigation/Routes'; @@ -997,7 +996,7 @@ const Settings: React.FC = () => { - {isBlockaidFeatureEnabled() && } + {strings('app_settings.privacy_heading')} ({ }), updateSecurityAlertResponse: jest.fn(), }, + PreferencesController: { + state: { + securityAlertsEnabled: true, + }, + }, }, })); jest.mock('../../../../../util/custom-gas', () => ({ diff --git a/app/components/Views/confirmations/components/BlockaidBanner/BlockaidBanner.test.tsx b/app/components/Views/confirmations/components/BlockaidBanner/BlockaidBanner.test.tsx index 34b90c98aa6..a424d5a8528 100644 --- a/app/components/Views/confirmations/components/BlockaidBanner/BlockaidBanner.test.tsx +++ b/app/components/Views/confirmations/components/BlockaidBanner/BlockaidBanner.test.tsx @@ -12,7 +12,6 @@ import renderWithProvider from '../../../../../util/test/renderWithProvider'; jest.mock('../../../../../util/blockaid', () => ({ isBlockaidFeatureEnabled: jest.fn().mockReturnValue(true), - isBlockaidSupportedOnCurrentChain: jest.fn().mockReturnValue(true), })); jest.mock('react-native-gzip', () => ({ diff --git a/app/components/Views/confirmations/components/BlockaidBanner/BlockaidBanner.tsx b/app/components/Views/confirmations/components/BlockaidBanner/BlockaidBanner.tsx index 564f3d268a8..782270ca0ba 100644 --- a/app/components/Views/confirmations/components/BlockaidBanner/BlockaidBanner.tsx +++ b/app/components/Views/confirmations/components/BlockaidBanner/BlockaidBanner.tsx @@ -1,6 +1,5 @@ import React, { useEffect, useState } from 'react'; import { ActivityIndicator } from 'react-native'; -import { useSelector } from 'react-redux'; import { View } from 'react-native-animatable'; import { captureException } from '@sentry/react-native'; import { deflate } from 'react-native-gzip'; @@ -18,10 +17,7 @@ import { import Icon from '../../../../../component-library/components/Icons/Icon/Icon'; import Text from '../../../../../component-library/components/Texts/Text/Text'; import { useStyles } from '../../../../../component-library/hooks/useStyles'; -import { - isBlockaidFeatureEnabled, - isBlockaidSupportedOnCurrentChain, -} from '../../../../../util/blockaid'; +import { isBlockaidFeatureEnabled } from '../../../../../util/blockaid'; import { FALSE_POSITIVE_REPOST_LINE_TEST_ID, REASON_DESCRIPTION_I18N_KEY_MAP, @@ -39,7 +35,6 @@ import { UTM_SOURCE, } from '../../../../../constants/urls'; import { BLOCKAID_SUPPORTED_NETWORK_NAMES } from '../../../../../util/networks'; -import { selectIsSecurityAlertsEnabled } from '../../../../../selectors/preferencesController'; import BlockaidVersionInfo from '../../../../../lib/ppom/blockaid-version'; import ButtonIcon, { ButtonIconSizes, @@ -74,7 +69,6 @@ const BlockaidBanner = (bannerProps: BlockaidBannerProps) => { const { styles, theme } = useStyles(styleSheet, { style }); const [displayPositiveResponse, setDisplayPositiveResponse] = useState(false); const [reportUrl, setReportUrl] = useState(''); - const isSecurityAlertsEnabled = useSelector(selectIsSecurityAlertsEnabled); useEffect(() => { if (securityAlertResponse?.reason === Reason.requestInProgress) { @@ -115,12 +109,7 @@ const BlockaidBanner = (bannerProps: BlockaidBannerProps) => { })(); }, [securityAlertResponse]); - if ( - !securityAlertResponse || - !isBlockaidFeatureEnabled() || - !isBlockaidSupportedOnCurrentChain() || - !isSecurityAlertsEnabled - ) { + if (!securityAlertResponse || !isBlockaidFeatureEnabled()) { return null; } diff --git a/app/components/Views/confirmations/components/PersonalSign/index.test.tsx b/app/components/Views/confirmations/components/PersonalSign/index.test.tsx index bfd29a21347..6502a57e4eb 100644 --- a/app/components/Views/confirmations/components/PersonalSign/index.test.tsx +++ b/app/components/Views/confirmations/components/PersonalSign/index.test.tsx @@ -28,6 +28,11 @@ jest.mock('../../../../../core/Engine', () => ({ keyrings: [], }, }, + PreferencesController: { + state: { + securityAlertsEnabled: true, + }, + }, }, })); diff --git a/app/components/Views/confirmations/components/TransactionBlockaidBanner/TransactionBlockaidBanner.test.tsx b/app/components/Views/confirmations/components/TransactionBlockaidBanner/TransactionBlockaidBanner.test.tsx index b97644ac494..ab839a17d20 100644 --- a/app/components/Views/confirmations/components/TransactionBlockaidBanner/TransactionBlockaidBanner.test.tsx +++ b/app/components/Views/confirmations/components/TransactionBlockaidBanner/TransactionBlockaidBanner.test.tsx @@ -7,9 +7,14 @@ import { TESTID_ACCORDIONHEADER } from '../../../../../component-library/compone import { ResultType, Reason } from '../BlockaidBanner/BlockaidBanner.types'; import TransactionBlockaidBanner from './TransactionBlockaidBanner'; -jest.mock('../../../../../util/blockaid', () => ({ - isBlockaidFeatureEnabled: jest.fn().mockReturnValue(true), - isBlockaidSupportedOnCurrentChain: jest.fn().mockReturnValue(true), +jest.mock('../../../../../core/Engine', () => ({ + context: { + PreferencesController: { + state: { + securityAlertsEnabled: true, + }, + }, + }, })); jest.mock('react-native-gzip', () => ({ diff --git a/app/components/Views/confirmations/components/TransactionReview/index.test.tsx b/app/components/Views/confirmations/components/TransactionReview/index.test.tsx index 189fadd5897..a81e4505e7a 100644 --- a/app/components/Views/confirmations/components/TransactionReview/index.test.tsx +++ b/app/components/Views/confirmations/components/TransactionReview/index.test.tsx @@ -64,6 +64,11 @@ jest.mock('../../../../../core/Engine', () => ({ ], }, }, + PreferencesController: { + state: { + securityAlertsEnabled: true, + }, + }, }, })); diff --git a/app/components/Views/confirmations/components/TypedSign/index.test.tsx b/app/components/Views/confirmations/components/TypedSign/index.test.tsx index 49b0a84166a..dcf6497258d 100644 --- a/app/components/Views/confirmations/components/TypedSign/index.test.tsx +++ b/app/components/Views/confirmations/components/TypedSign/index.test.tsx @@ -41,6 +41,11 @@ jest.mock('../../../../../core/Engine', () => ({ removeListener: jest.fn(), }, }, + PreferencesController: { + state: { + securityAlertsEnabled: true, + }, + }, }, controllerMessenger: { subscribe: jest.fn(), diff --git a/app/core/Engine.ts b/app/core/Engine.ts index 3fc891c0e09..78802a482f4 100644 --- a/app/core/Engine.ts +++ b/app/core/Engine.ts @@ -164,7 +164,6 @@ import { } from './Snaps'; import { getRpcMethodMiddleware } from './RPCMethods/RPCMethodMiddleware'; ///: END:ONLY_INCLUDE_IF -import { isBlockaidFeatureEnabled } from '../util/blockaid'; import { getCaveatSpecifications, getPermissionSpecifications, @@ -1299,10 +1298,7 @@ class Engine { subjectMetadataController, ///: END:ONLY_INCLUDE_IF accountsController, - ]; - - if (isBlockaidFeatureEnabled()) { - const ppomController = new PPOMController({ + new PPOMController({ chainId: networkController.state.providerConfig.chainId, blockaidPublicKey: process.env.BLOCKAID_PUBLIC_KEY as string, cdnBaseUrl: process.env.BLOCKAID_FILE_CDN as string, @@ -1334,9 +1330,8 @@ class Engine { // TODO: Replace "any" with type // eslint-disable-next-line @typescript-eslint/no-explicit-any nativeCrypto: Crypto as any, - }); - controllers.push(ppomController); - } + }), + ]; // set initial state // TODO: Pass initial state into each controller constructor instead diff --git a/app/core/EngineService/EngineService.ts b/app/core/EngineService/EngineService.ts index ecec1d552cf..84d26c1324d 100644 --- a/app/core/EngineService/EngineService.ts +++ b/app/core/EngineService/EngineService.ts @@ -1,7 +1,6 @@ import UntypedEngine from '../Engine'; import AppConstants from '../AppConstants'; import { getVaultFromBackup } from '../BackupVault'; -import { isBlockaidFeatureEnabled } from '../../util/blockaid'; import { store as importedStore } from '../../store'; import Logger from '../../util/Logger'; import { @@ -115,14 +114,11 @@ class EngineService { name: 'AccountsController', key: `${engine.context.AccountsController.name}:stateChange`, }, - ]; - - if (isBlockaidFeatureEnabled()) { - controllers.push({ + { name: 'PPOMController', key: `${engine.context.PPOMController.name}:stateChange`, - }); - } + }, + ]; engine?.datamodel?.subscribe?.(() => { if (!engine.context.KeyringController.metadata.vault) { diff --git a/app/lib/ppom/ppom-util.test.ts b/app/lib/ppom/ppom-util.test.ts index b5f9faa220b..a78a01203af 100644 --- a/app/lib/ppom/ppom-util.test.ts +++ b/app/lib/ppom/ppom-util.test.ts @@ -1,6 +1,7 @@ import { normalizeTransactionParams } from '@metamask/transaction-controller'; import * as SignatureRequestActions from '../../actions/signatureRequest'; // eslint-disable-line import/no-namespace import * as TransactionActions from '../../actions/transaction'; // eslint-disable-line import/no-namespace +import * as NetworkControllerSelectors from '../../selectors/networkController'; // eslint-disable-line import/no-namespace import Engine from '../../core/Engine'; import PPOMUtil from './ppom-util'; import { @@ -34,6 +35,13 @@ jest.mock('../../core/Engine', () => ({ }, }, }, + backgroundState: { + NetworkController: { + providerConfig: { + chainId: 0x1, + }, + }, + }, })); const MockEngine = jest.mocked(Engine); @@ -115,8 +123,9 @@ describe('PPOM Utils', () => { TransactionActions, 'setTransactionSecurityAlertResponse', ); - MockEngine.context.NetworkController.state.providerConfig.chainId = - '0xfa'; + jest + .spyOn(NetworkControllerSelectors, 'selectChainId') + .mockReturnValue('0xfa'); await PPOMUtil.validateRequest(mockRequest, CHAIN_ID_MOCK); expect(MockEngine.context.PPOMController?.usePPOM).toBeCalledTimes(0); expect(spyTransactionAction).toBeCalledTimes(0); diff --git a/app/lib/ppom/ppom-util.ts b/app/lib/ppom/ppom-util.ts index fa02d01ce0b..1d615a4c8e1 100644 --- a/app/lib/ppom/ppom-util.ts +++ b/app/lib/ppom/ppom-util.ts @@ -1,6 +1,5 @@ import setSignatureRequestSecurityAlertResponse from '../../actions/signatureRequest'; import { setTransactionSecurityAlertResponse } from '../../actions/transaction'; -import { BLOCKAID_SUPPORTED_CHAIN_IDS } from '../../util/networks'; import { Reason, ResultType, @@ -57,26 +56,12 @@ const SECURITY_ALERT_RESPONSE_IN_PROGRESS = { }; async function validateRequest(req: PPOMRequest, transactionId?: string) { - const { - PPOMController: ppomController, - PreferencesController, - NetworkController, - } = Engine.context; + const { PPOMController: ppomController, NetworkController } = Engine.context; const chainId = NetworkController.state.providerConfig.chainId; const isConfirmationMethod = CONFIRMATION_METHODS.includes(req.method); - const isSupportedChain = BLOCKAID_SUPPORTED_CHAIN_IDS.includes(chainId); - - const isSecurityAlertsEnabled = - PreferencesController.state.securityAlertsEnabled; - - if ( - !ppomController || - !isBlockaidFeatureEnabled() || - !isSecurityAlertsEnabled || - !isConfirmationMethod || - !isSupportedChain - ) { + + if (!ppomController || !isBlockaidFeatureEnabled() || !isConfirmationMethod) { return; } diff --git a/app/util/blockaid/index.test.ts b/app/util/blockaid/index.test.ts index 0b456aba717..7047ea4fe45 100644 --- a/app/util/blockaid/index.test.ts +++ b/app/util/blockaid/index.test.ts @@ -7,13 +7,26 @@ import { // eslint-disable-next-line import/no-namespace import * as NetworkControllerMock from '../../selectors/networkController'; import { NETWORKS_CHAIN_ID } from '../../constants/network'; +import Engine from '../../core/Engine'; import { getBlockaidMetricsParams, isBlockaidSupportedOnCurrentChain, getBlockaidTransactionMetricsParams, + isBlockaidFeatureEnabled, } from '.'; +jest.mock('../../core/Engine', () => ({ + resetState: jest.fn(), + context: { + PreferencesController: { + state: { + securityAlertsEnabled: true, + }, + }, + }, +})); + describe('Blockaid util', () => { describe('getBlockaidTransactionMetricsParams', () => { beforeEach(() => { @@ -173,4 +186,33 @@ describe('Blockaid util', () => { expect(result).toEqual(false); }); }); + + describe('isBlockaidFeatureEnabled', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + it('return true if blockaid is supported on current network and its enabled by the user', () => { + jest + .spyOn(NetworkControllerMock, 'selectChainId') + .mockReturnValue(NETWORKS_CHAIN_ID.MAINNET); + const result = isBlockaidFeatureEnabled(); + expect(result).toEqual(true); + }); + + it('return false if blockaid is not supported on current network', () => { + jest.spyOn(NetworkControllerMock, 'selectChainId').mockReturnValue('0x9'); + const result = isBlockaidFeatureEnabled(); + expect(result).toEqual(false); + }); + + it('return false if blockaid is not enabled by the user', () => { + jest + .spyOn(NetworkControllerMock, 'selectChainId') + .mockReturnValue(NETWORKS_CHAIN_ID.MAINNET); + Engine.context.PreferencesController.state.securityAlertsEnabled = false; + const result = isBlockaidFeatureEnabled(); + expect(result).toEqual(false); + }); + }); }); diff --git a/app/util/blockaid/index.ts b/app/util/blockaid/index.ts index d9f8e62a99d..cb2205c6a59 100644 --- a/app/util/blockaid/index.ts +++ b/app/util/blockaid/index.ts @@ -1,3 +1,4 @@ +import Engine from '../../core/Engine'; import { ResultType, SecurityAlertResponse, @@ -34,15 +35,18 @@ export const isSupportedChainId = (chainId: string) => { return isSupported; }; -// eslint-disable-next-line import/prefer-default-export export const isBlockaidSupportedOnCurrentChain = () => { const chainId = selectChainId(store.getState()); return isSupportedChainId(chainId); }; -// eslint-disable-next-line import/prefer-default-export +export const isBlockaidPreferenceEnabled = () => { + const { PreferencesController } = Engine.context; + return PreferencesController.state.securityAlertsEnabled; +}; + export const isBlockaidFeatureEnabled = () => - process.env.MM_BLOCKAID_UI_ENABLED; + isBlockaidSupportedOnCurrentChain() && isBlockaidPreferenceEnabled(); export const getBlockaidMetricsParams = ( securityAlertResponse?: SecurityAlertResponse, @@ -51,11 +55,7 @@ export const getBlockaidMetricsParams = ( // eslint-disable-next-line @typescript-eslint/no-explicit-any const additionalParams: Record = {}; - if ( - securityAlertResponse && - isBlockaidFeatureEnabled() && - isBlockaidSupportedOnCurrentChain() - ) { + if (securityAlertResponse && isBlockaidFeatureEnabled()) { const { result_type, reason, providerRequestsCount, source } = securityAlertResponse; diff --git a/jest.config.js b/jest.config.js index 8f6df8f69fb..c1c9e97f957 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,4 @@ process.env.TZ = 'America/Toronto'; -process.env.MM_BLOCKAID_UI_ENABLED = 'true'; process.env.SEGMENT_DELETE_API_SOURCE_ID = 'testSourceId'; process.env.SEGMENT_REGULATIONS_ENDPOINT = 'TestRegulationsEndpoint';