diff --git a/app/scripts/controller-init/messengers/smart-transactions-controller-messenger.ts b/app/scripts/controller-init/messengers/smart-transactions-controller-messenger.ts index a90daae07c49..387eb15c0997 100644 --- a/app/scripts/controller-init/messengers/smart-transactions-controller-messenger.ts +++ b/app/scripts/controller-init/messengers/smart-transactions-controller-messenger.ts @@ -1,27 +1,34 @@ +import type { ErrorReportingServiceCaptureExceptionAction } from '@metamask/error-reporting-service'; import { Messenger } from '@metamask/messenger'; -import type { - TransactionControllerConfirmExternalTransactionAction, - TransactionControllerGetNonceLockAction, - TransactionControllerGetTransactionsAction, - TransactionControllerUpdateTransactionAction, -} from '@metamask/transaction-controller'; import { NetworkControllerGetNetworkClientByIdAction, NetworkControllerGetStateAction, NetworkControllerStateChangeEvent, } from '@metamask/network-controller'; +import type { + RemoteFeatureFlagControllerGetStateAction, + RemoteFeatureFlagControllerStateChangeEvent, +} from '@metamask/remote-feature-flag-controller'; +import type { + TransactionControllerGetNonceLockAction, + TransactionControllerGetTransactionsAction, + TransactionControllerUpdateTransactionAction, +} from '@metamask/transaction-controller'; import { MetaMetricsControllerTrackEventAction } from '../../controllers/metametrics-controller'; import { RootMessenger } from '../../lib/messenger'; type MessengerActions = + | ErrorReportingServiceCaptureExceptionAction | NetworkControllerGetNetworkClientByIdAction | NetworkControllerGetStateAction + | RemoteFeatureFlagControllerGetStateAction | TransactionControllerGetNonceLockAction | TransactionControllerGetTransactionsAction - | TransactionControllerUpdateTransactionAction - | TransactionControllerConfirmExternalTransactionAction; + | TransactionControllerUpdateTransactionAction; -type MessengerEvents = NetworkControllerStateChangeEvent; +type MessengerEvents = + | NetworkControllerStateChangeEvent + | RemoteFeatureFlagControllerStateChangeEvent; export type SmartTransactionsControllerMessenger = ReturnType< typeof getSmartTransactionsControllerMessenger @@ -42,14 +49,18 @@ export function getSmartTransactionsControllerMessenger( messenger.delegate({ messenger: controllerMessenger, actions: [ + 'ErrorReportingService:captureException', 'NetworkController:getNetworkClientById', 'NetworkController:getState', + 'RemoteFeatureFlagController:getState', 'TransactionController:getNonceLock', - 'TransactionController:confirmExternalTransaction', 'TransactionController:getTransactions', 'TransactionController:updateTransaction', ], - events: ['NetworkController:stateChange'], + events: [ + 'NetworkController:stateChange', + 'RemoteFeatureFlagController:stateChange', + ], }); return controllerMessenger; } diff --git a/app/scripts/controller-init/smart-transactions/smart-transactions-controller-init.ts b/app/scripts/controller-init/smart-transactions/smart-transactions-controller-init.ts index 5db68b53c8ea..a0ff6c3f34a9 100644 --- a/app/scripts/controller-init/smart-transactions/smart-transactions-controller-init.ts +++ b/app/scripts/controller-init/smart-transactions/smart-transactions-controller-init.ts @@ -5,10 +5,6 @@ import { import type { Hex } from '@metamask/utils'; import type { TraceCallback } from '@metamask/controller-utils'; import { getAllowedSmartTransactionsChainIds } from '../../../../shared/constants/smartTransactions'; -import { getFeatureFlagsByChainId } from '../../../../shared/modules/selectors'; -import { type ProviderConfigState } from '../../../../shared/modules/selectors/networks'; -import { type FeatureFlagsMetaMaskState } from '../../../../shared/modules/selectors/feature-flags'; -import type { FeatureFlags } from '../../lib/smart-transaction/smart-transactions'; import { ControllerInitFunction, ControllerInitRequest } from '../types'; import { SmartTransactionsControllerInitMessenger, @@ -57,12 +53,6 @@ export const SmartTransactionsControllerInit: ControllerInitFunction< >[0]['trackMetaMetricsEvent'], state: persistedState.SmartTransactionsController, messenger: controllerMessenger, - getFeatureFlags: () => { - const state = { metamask: getUIState() }; - return getFeatureFlagsByChainId( - state as unknown as ProviderConfigState & FeatureFlagsMetaMaskState, - ) as unknown as FeatureFlags; - }, getMetaMetricsProps: async () => { const metamask = getUIState(); const { internalAccounts } = metamask; diff --git a/app/scripts/lib/smart-transaction/smart-transactions.ts b/app/scripts/lib/smart-transaction/smart-transactions.ts index c6c57ac02780..64edb912a92d 100644 --- a/app/scripts/lib/smart-transaction/smart-transactions.ts +++ b/app/scripts/lib/smart-transaction/smart-transactions.ts @@ -12,6 +12,7 @@ import { type Fee, type Fees, type SmartTransaction, + type SmartTransactionsNetworkConfig, } from '@metamask/smart-transactions-controller'; import { TransactionController, @@ -30,10 +31,11 @@ import { import { CANCEL_GAS_LIMIT_DEC } from '../../../../shared/constants/smartTransactions'; import { decimalToHex } from '../../../../shared/modules/conversion.utils'; import { - getFeatureFlagsByChainId, getIsSmartTransaction, isHardwareWallet, + getSmartTransactionsFeatureFlagsForChain, } from '../../../../shared/modules/selectors'; +import { getCurrentChainId } from '../../../../shared/modules/selectors/networks'; import { isLegacyTransaction } from '../../../../shared/modules/transaction.utils'; import { ControllerFlatState } from '../../controller-init/controller-list'; @@ -53,17 +55,7 @@ export type SmartTransactionHookMessenger = Messenger< AllowedEvents >; -export type FeatureFlags = { - extensionActive: boolean; - mobileActive: boolean; - smartTransactions: { - expectedDeadline?: number; - maxDeadline?: number; - extensionReturnTxHashAsap?: boolean; - extensionReturnTxHashAsapBatch?: boolean; - extensionSkipSmartTransactionStatusPage?: boolean; - }; -}; +export type FeatureFlags = SmartTransactionsNetworkConfig; export type SubmitSmartTransactionRequest = { transactionMeta: TransactionMeta; @@ -88,17 +80,7 @@ class SmartTransactionHook { #controllerMessenger: SmartTransactionHookMessenger; - #featureFlags: { - extensionActive: boolean; - mobileActive: boolean; - smartTransactions: { - expectedDeadline?: number; - maxDeadline?: number; - extensionReturnTxHashAsap?: boolean; - extensionReturnTxHashAsapBatch?: boolean; - extensionSkipSmartTransactionStatusPage?: boolean; - }; - }; + #featureFlags: FeatureFlags; #isDapp: boolean; @@ -143,7 +125,7 @@ class SmartTransactionHook { this.#txParams = transactionMeta.txParams; this.#transactions = transactions; const extensionSkipSmartTransactionStatusPage = - featureFlags?.smartTransactions?.extensionSkipSmartTransactionStatusPage; + featureFlags?.extensionSkipSmartTransactionStatusPage; this.#shouldShowStatusPage = extensionSkipSmartTransactionStatusPage ? false @@ -218,7 +200,7 @@ class SmartTransactionHook { await this.#processApprovalIfNeeded(uuid); const extensionReturnTxHashAsap = - this.#featureFlags?.smartTransactions?.extensionReturnTxHashAsap; + this.#featureFlags?.extensionReturnTxHashAsap; let transactionHash: string | undefined | null; if (extensionReturnTxHashAsap && submitTransactionResponse?.txHash) { @@ -278,7 +260,7 @@ class SmartTransactionHook { } const extensionReturnTxHashAsapBatch = - this.#featureFlags?.smartTransactions?.extensionReturnTxHashAsapBatch; + this.#featureFlags?.extensionReturnTxHashAsapBatch; if ( extensionReturnTxHashAsapBatch && @@ -579,12 +561,14 @@ export function getSmartTransactionCommonParams( // UI state is required to support shared selectors to avoid duplicate logic in frontend and backend. // Ideally all backend logic would instead rely on messenger event / state subscriptions. const uiState = getUIState(flatState); - + const effectiveChainId = (chainId || getCurrentChainId(uiState)) as Hex; // @ts-expect-error Smart transaction selector types does not match controller state const isSmartTransaction = getIsSmartTransaction(uiState, chainId); - // @ts-expect-error Smart transaction selector types does not match controller state - const featureFlags = getFeatureFlagsByChainId(uiState, chainId); + const featureFlags = getSmartTransactionsFeatureFlagsForChain( + uiState, + effectiveChainId, + ); const isHardwareWalletAccount = isHardwareWallet(uiState); diff --git a/shared/modules/selectors/feature-flags.test.ts b/shared/modules/selectors/feature-flags.test.ts deleted file mode 100644 index 1838c82e3578..000000000000 --- a/shared/modules/selectors/feature-flags.test.ts +++ /dev/null @@ -1,295 +0,0 @@ -import { RpcEndpointType } from '@metamask/network-controller'; -import { Hex } from '@metamask/utils'; -import { CHAIN_IDS } from '../../constants/network'; -// Import the module to spy on -import * as featureFlags from '../feature-flags'; -import { - getFeatureFlagsByChainId, - type SwapsFeatureFlags, - type SmartTransactionsNetworks, - type FeatureFlagsMetaMaskState, -} from './feature-flags'; -import { ProviderConfigState } from './networks'; - -type MockState = ProviderConfigState & - FeatureFlagsMetaMaskState & { - metamask: { - networkConfigurationsByChainId: Record< - string, - { - chainId: string; - rpcEndpoints: { - networkClientId: string; - type: RpcEndpointType; - url: string; - }[]; - blockExplorerUrls: string[]; - defaultBlockExplorerUrlIndex: number; - name: string; - nativeCurrency: string; - defaultRpcEndpointIndex: number; - } - >; - selectedNetworkClientId: string; - networksMetadata: { - [clientId: string]: { status: string }; - }; - swapsState: { - swapsFeatureFlags: SwapsFeatureFlags; - }; - remoteFeatureFlags?: { - smartTransactionsNetworks?: SmartTransactionsNetworks; - }; - }; - }; - -describe('Feature Flags Selectors', () => { - const createMockState = ( - chainId: Hex = CHAIN_IDS.MAINNET, - remoteFeatureFlagsOverride?: { - smartTransactionsNetworks?: SmartTransactionsNetworks; - }, - ): MockState => { - const state: MockState = { - metamask: { - networkConfigurationsByChainId: { - [chainId]: { - chainId: chainId as Hex, - rpcEndpoints: [ - { - networkClientId: 'test-client-id', - type: RpcEndpointType.Custom, - url: 'https://example.com', - }, - ], - blockExplorerUrls: ['https://example.com'], - defaultBlockExplorerUrlIndex: 0, - name: 'Test Network', - nativeCurrency: 'ETH', - defaultRpcEndpointIndex: 0, - }, - }, - selectedNetworkClientId: 'test-client-id', - networksMetadata: { - 'test-client-id': { status: 'available' }, - }, - swapsState: { - swapsFeatureFlags: { - ethereum: { - extensionActive: true, - mobileActive: false, - smartTransactions: { - expectedDeadline: 45, - maxDeadline: 150, - }, - }, - bsc: { - extensionActive: true, - mobileActive: false, - smartTransactions: { - expectedDeadline: 60, - maxDeadline: 180, - }, - }, - smartTransactions: { - mobileActive: true, - extensionActive: true, - extensionReturnTxHashAsap: false, - }, - } as SwapsFeatureFlags, - }, - remoteFeatureFlags: remoteFeatureFlagsOverride - ? { - smartTransactionsNetworks: { - default: { - batchStatusPollingInterval: 1000, - extensionActive: true, - extensionReturnTxHashAsap: true, - extensionReturnTxHashAsapBatch: true, - extensionSkipSmartTransactionStatusPage: false, - }, - ...remoteFeatureFlagsOverride.smartTransactionsNetworks, - }, - } - : undefined, - }, - }; - return state; - }; - - describe('getFeatureFlagsByChainId', () => { - beforeEach(() => { - jest - .spyOn(featureFlags, 'getNetworkNameByChainId') - .mockImplementation((chainId: string) => { - switch (chainId) { - case CHAIN_IDS.MAINNET: - return 'ethereum'; - case CHAIN_IDS.BSC: - return 'bsc'; - case CHAIN_IDS.POLYGON: - return 'polygon'; - default: - return ''; - } - }); - }); - - afterEach(() => { - jest.restoreAllMocks(); - }); - - it('returns correct feature flags for current chain ID in state', () => { - const state = createMockState(CHAIN_IDS.MAINNET); - const result = getFeatureFlagsByChainId(state); - - expect(result).toStrictEqual({ - smartTransactions: { - mobileActive: true, - extensionActive: true, - expectedDeadline: 45, - maxDeadline: 150, - extensionReturnTxHashAsap: false, - extensionReturnTxHashAsapBatch: false, - extensionSkipSmartTransactionStatusPage: false, - }, - }); - }); - - it('returns null if chainId is not supported', () => { - // Instead of using SEPOLIA, create a state with a custom network - // and mock getNetworkNameByChainId to return empty string - const state = createMockState(CHAIN_IDS.MAINNET); - - // Mock the implementation for this specific test - jest - .spyOn(featureFlags, 'getNetworkNameByChainId') - .mockReturnValueOnce(''); - - const result = getFeatureFlagsByChainId(state); - expect(result).toBeNull(); - }); - - it('prioritizes provided chainId parameter over state chainId', () => { - // State has Ethereum network, but we're providing BSC chainId - const state = createMockState(CHAIN_IDS.MAINNET); - const result = getFeatureFlagsByChainId(state, CHAIN_IDS.BSC); - - expect(result).toStrictEqual({ - smartTransactions: { - extensionActive: true, - mobileActive: true, - expectedDeadline: 60, - maxDeadline: 180, - extensionReturnTxHashAsap: false, - extensionReturnTxHashAsapBatch: false, - extensionSkipSmartTransactionStatusPage: false, - }, - }); - }); - - it('falls back to state chainId if provided chainId is falsy', () => { - const state = createMockState(CHAIN_IDS.MAINNET); - const result = getFeatureFlagsByChainId(state, ''); - - expect(result).toStrictEqual({ - smartTransactions: { - extensionActive: true, - mobileActive: true, - expectedDeadline: 45, - maxDeadline: 150, - extensionReturnTxHashAsap: false, - extensionReturnTxHashAsapBatch: false, - extensionSkipSmartTransactionStatusPage: false, - }, - }); - }); - - describe('remote feature flags', () => { - it('uses extensionReturnTxHashAsap from remote flags when available', () => { - const state = createMockState(CHAIN_IDS.MAINNET, { - smartTransactionsNetworks: {}, - }); - const result = getFeatureFlagsByChainId(state); - - expect(result).toStrictEqual({ - smartTransactions: { - mobileActive: true, - extensionActive: true, - expectedDeadline: 45, - maxDeadline: 150, - extensionReturnTxHashAsap: true, - extensionReturnTxHashAsapBatch: true, - extensionSkipSmartTransactionStatusPage: false, - }, - }); - }); - - it('defaults to false when remote flags are not available', () => { - const state = createMockState(CHAIN_IDS.MAINNET); - const result = getFeatureFlagsByChainId(state); - - expect(result).toStrictEqual({ - smartTransactions: { - mobileActive: true, - extensionActive: true, - expectedDeadline: 45, - maxDeadline: 150, - extensionReturnTxHashAsap: false, - extensionReturnTxHashAsapBatch: false, - extensionSkipSmartTransactionStatusPage: false, - }, - }); - }); - - it('uses default remote flag value for all networks', () => { - const state = createMockState(CHAIN_IDS.BSC, { - smartTransactionsNetworks: {}, - }); - const result = getFeatureFlagsByChainId(state); - - expect(result).toStrictEqual({ - smartTransactions: { - extensionActive: true, - mobileActive: true, - expectedDeadline: 60, - maxDeadline: 180, - extensionReturnTxHashAsap: true, - extensionReturnTxHashAsapBatch: true, - extensionSkipSmartTransactionStatusPage: false, - }, - }); - }); - - it('uses extensionSkipSmartTransactionStatusPage from network specific remote flags and override default when available', () => { - const state = createMockState(CHAIN_IDS.BSC, { - smartTransactionsNetworks: { - [CHAIN_IDS.BSC]: { - extensionSkipSmartTransactionStatusPage: true, - }, - default: { - batchStatusPollingInterval: 1000, - extensionActive: true, - extensionReturnTxHashAsap: true, - extensionReturnTxHashAsapBatch: true, - extensionSkipSmartTransactionStatusPage: false, - }, - }, - }); - - const result = getFeatureFlagsByChainId(state); - expect(result).toStrictEqual({ - smartTransactions: { - extensionActive: true, - mobileActive: true, - expectedDeadline: 60, - maxDeadline: 180, - extensionReturnTxHashAsap: true, - extensionReturnTxHashAsapBatch: true, - extensionSkipSmartTransactionStatusPage: true, - }, - }); - }); - }); - }); -}); diff --git a/shared/modules/selectors/feature-flags.ts b/shared/modules/selectors/feature-flags.ts deleted file mode 100644 index 16c709fd1f64..000000000000 --- a/shared/modules/selectors/feature-flags.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { Hex } from '@metamask/utils'; -import { getNetworkNameByChainId } from '../feature-flags'; -import { ProviderConfigState, getCurrentChainId } from './networks'; - -type NetworkFeatureFlag = { - extensionActive: boolean; - mobileActive: boolean; - smartTransactions?: { - mobileActive?: boolean; - extensionActive?: boolean; - expectedDeadline?: number; - maxDeadline?: number; - extensionReturnTxHashAsap?: boolean; - }; -}; - -type SmartTransactionsFeatureFlag = { - mobileActive: boolean; - extensionActive: boolean; - extensionReturnTxHashAsap: boolean; -}; - -export type SwapsFeatureFlags = { - [networkName: string]: NetworkFeatureFlag; - smartTransactions: SmartTransactionsFeatureFlag; -}; - -export type SmartTransactionNetwork = { - extensionActive?: boolean; - sentinelUrl?: string; - extensionReturnTxHashAsap?: boolean; - extensionReturnTxHashAsapBatch?: boolean; - extensionSkipSmartTransactionStatusPage?: boolean; - batchStatusPollingInterval?: number; -}; - -export type SmartTransactionsNetworks = { - [chainId: Hex]: SmartTransactionNetwork | undefined; - default?: SmartTransactionNetwork; -}; - -export type FeatureFlagsMetaMaskState = { - metamask: { - swapsState: { - swapsFeatureFlags: SwapsFeatureFlags; - }; - remoteFeatureFlags?: { - smartTransactionsNetworks?: SmartTransactionsNetworks; - }; - }; -}; - -export function getFeatureFlagsByChainId( - state: ProviderConfigState & FeatureFlagsMetaMaskState, - chainId?: string, -) { - // TODO: Fix in https://github.com/MetaMask/metamask-extension/issues/31880 - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const effectiveChainId = chainId || getCurrentChainId(state); - const networkName = getNetworkNameByChainId(effectiveChainId); - const featureFlags = state.metamask.swapsState?.swapsFeatureFlags; - if (!featureFlags?.[networkName]) { - return null; - } - const smartTransactionsNetworks = - state.metamask.remoteFeatureFlags?.smartTransactionsNetworks; - const defaultConfig = smartTransactionsNetworks?.default ?? {}; - const chainSpecificConfig = - smartTransactionsNetworks?.[effectiveChainId as Hex] ?? {}; - - // Merge with fallback precedence: chainSpecific > default > hardcoded defaults (false) - // TODO: this is temporary until we deprecate this file and implement a better flag system. - const remoteFlags = { - extensionReturnTxHashAsap: - chainSpecificConfig.extensionReturnTxHashAsap ?? - defaultConfig.extensionReturnTxHashAsap ?? - false, - extensionReturnTxHashAsapBatch: - chainSpecificConfig.extensionReturnTxHashAsapBatch ?? - defaultConfig.extensionReturnTxHashAsapBatch ?? - false, - extensionSkipSmartTransactionStatusPage: - chainSpecificConfig.extensionSkipSmartTransactionStatusPage ?? - defaultConfig.extensionSkipSmartTransactionStatusPage ?? - false, - }; - - return { - smartTransactions: { - ...featureFlags.smartTransactions, - ...featureFlags[networkName].smartTransactions, - ...remoteFlags, - }, - }; -} diff --git a/shared/modules/selectors/index.ts b/shared/modules/selectors/index.ts index 9cd44470752b..6e983385b5cf 100644 --- a/shared/modules/selectors/index.ts +++ b/shared/modules/selectors/index.ts @@ -3,7 +3,6 @@ import { getHardwareWalletType } from '../../../ui/selectors/selectors'; export * from './smart-transactions'; -export * from './feature-flags'; export * from './account'; export { getHardwareWalletType }; diff --git a/shared/modules/selectors/smart-transactions.ts b/shared/modules/selectors/smart-transactions.ts index e13ed3911d1a..363e3a6ca06d 100644 --- a/shared/modules/selectors/smart-transactions.ts +++ b/shared/modules/selectors/smart-transactions.ts @@ -1,4 +1,7 @@ import { createSelector } from 'reselect'; +import type { SmartTransactionsNetworkConfig } from '@metamask/smart-transactions-controller'; +import { selectSmartTransactionsFeatureFlagsForChain } from '@metamask/smart-transactions-controller'; +import type { Hex, CaipChainId } from '@metamask/utils'; import { getAllowedSmartTransactionsChainIds, SKIP_STX_RPC_URL_CHECK_CHAIN_IDS, @@ -10,9 +13,14 @@ import { // TODO: Remove restricted import // eslint-disable-next-line import/no-restricted-paths } from '../../../ui/selectors/selectors'; // TODO: Migrate shared selectors to this file. +import { + getRemoteFeatureFlags, + type RemoteFeatureFlagsState, + // eslint-disable-next-line import/no-restricted-paths +} from '../../../ui/selectors/remote-feature-flags'; import { isProduction } from '../environment'; -import { getFeatureFlagsByChainId } from './feature-flags'; -import { getCurrentChainId, NetworkState } from './networks'; +import { getCurrentChainId, type NetworkState } from './networks'; +import { createDeepEqualSelector } from './util'; export type SmartTransactionsMetaMaskState = { metamask: { @@ -32,23 +40,6 @@ export type SmartTransactionsMetaMaskState = { }; }; }; - swapsState: { - swapsFeatureFlags: { - ethereum: { - extensionActive: boolean; - mobileActive: boolean; - smartTransactions: { - expectedDeadline?: number; - maxDeadline?: number; - extensionReturnTxHashAsap?: boolean; - }; - }; - smartTransactions: { - extensionActive: boolean; - mobileActive: boolean; - }; - }; - }; smartTransactionsState: { liveness: boolean; }; @@ -56,7 +47,27 @@ export type SmartTransactionsMetaMaskState = { }; export type SmartTransactionsState = SmartTransactionsMetaMaskState & - NetworkState; + NetworkState & + RemoteFeatureFlagsState; + +/** + * Selector to get the smart transactions feature flags for a specific chain. + * Uses the controller's selector which validates and merges default + chain-specific config. + * + * @param state - The Redux state + * @param chainId - The chain ID (hex or CAIP-2 format) + * @returns The merged feature flags for the specified chain + */ +export const getSmartTransactionsFeatureFlagsForChain = createDeepEqualSelector( + (state) => getRemoteFeatureFlags(state).smartTransactionsNetworks, + (_state, chainId: Hex | CaipChainId) => chainId, + (smartTransactionsNetworks, chainId): SmartTransactionsNetworkConfig => { + return selectSmartTransactionsFeatureFlagsForChain( + { remoteFeatureFlags: { smartTransactionsNetworks } }, + chainId, + ); + }, +); /** * Returns the user's explicit opt-in status for the smart transactions feature. @@ -176,12 +187,14 @@ export const getSmartTransactionsEnabled = ( state: SmartTransactionsState, chainId?: string, ): boolean => { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + const effectiveChainId = (chainId || getCurrentChainId(state)) as Hex; const supportedAccount = accountSupportsSmartTx(state); - // @ts-expect-error Smart transaction selector types does not match controller state - const featureFlagsByChainId = getFeatureFlagsByChainId(state, chainId); - // TODO: Create a new proxy service only for MM feature flags. - const smartTransactionsFeatureFlagEnabled = - featureFlagsByChainId?.smartTransactions?.extensionActive; + const featureFlags = getSmartTransactionsFeatureFlagsForChain( + state, + effectiveChainId, + ); + const smartTransactionsFeatureFlagEnabled = featureFlags?.extensionActive; const smartTransactionsLiveness = state.metamask.smartTransactionsState?.liveness; return Boolean( diff --git a/ui/ducks/swaps/swaps.js b/ui/ducks/swaps/swaps.js index 1b0a28ad98a0..24e94e793847 100644 --- a/ui/ducks/swaps/swaps.js +++ b/ui/ducks/swaps/swaps.js @@ -59,7 +59,6 @@ import { getCurrentChainId, getSelectedNetworkClientId, } from '../../../shared/modules/selectors/networks'; -import { getFeatureFlagsByChainId } from '../../../shared/modules/selectors/feature-flags'; import { getSelectedAccount, getTokenExchangeRates, @@ -74,6 +73,7 @@ import { } from '../../selectors'; import { getSmartTransactionsEnabled, + getSmartTransactionsFeatureFlagsForChain, getSmartTransactionsOptInStatusForMetrics, getSmartTransactionsPreferenceEnabled, } from '../../../shared/modules/selectors'; @@ -958,11 +958,15 @@ export const signAndSendSwapsSmartTransaction = ({ const { sourceTokenInfo = {}, destinationTokenInfo = {} } = metaData; const usedQuote = getUsedQuote(state); const selectedNetwork = getSelectedNetwork(state); - const swapsFeatureFlags = getFeatureFlagsByChainId(state); + const chainId = getCurrentChainId(state); + const featureFlags = getSmartTransactionsFeatureFlagsForChain( + state, + chainId, + ); dispatch( setSmartTransactionsRefreshInterval( - swapsFeatureFlags?.smartTransactions?.batchStatusPollingInterval, + featureFlags?.batchStatusPollingInterval, ), ); diff --git a/ui/pages/confirmations/hooks/useSmartTransactionFeatureFlags.ts b/ui/pages/confirmations/hooks/useSmartTransactionFeatureFlags.ts index 1104524013fa..fe716100d5f9 100644 --- a/ui/pages/confirmations/hooks/useSmartTransactionFeatureFlags.ts +++ b/ui/pages/confirmations/hooks/useSmartTransactionFeatureFlags.ts @@ -4,6 +4,7 @@ import { TransactionMeta } from '@metamask/transaction-controller'; import log from 'loglevel'; import { getChainSupportsSmartTransactions, + getSmartTransactionsFeatureFlagsForChain, getSmartTransactionsPreferenceEnabled, } from '../../../../shared/modules/selectors'; import { fetchSwapsFeatureFlags } from '../../swaps/swaps.util'; @@ -13,6 +14,7 @@ import { setSmartTransactionsRefreshInterval, } from '../../../store/actions'; import { useConfirmContext } from '../context/confirm'; +import { getCurrentChainId } from '../../../../shared/modules/selectors/networks'; export function useSmartTransactionFeatureFlags() { const dispatch = useDispatch(); @@ -28,10 +30,16 @@ export function useSmartTransactionFeatureFlags() { getSmartTransactionsPreferenceEnabled, ); + // TODO: this checks an hardcoded list in the client. const currentChainSupportsSmartTransactions = useSelector( getChainSupportsSmartTransactions, ); + const chainId = useSelector(getCurrentChainId); + const featureFlags = useSelector((state) => + getSmartTransactionsFeatureFlagsForChain(state, chainId), + ); + useEffect(() => { if ( !isTransaction || @@ -43,14 +51,16 @@ export function useSmartTransactionFeatureFlags() { } Promise.all([ + // TODO: check if this is still needed. fetchSwapsFeatureFlags(), fetchSmartTransactionsLiveness({ networkClientId })(), ]) .then(([swapsFeatureFlags]) => { + // TODO: check if this is still needed. dispatch(setSwapsFeatureFlags(swapsFeatureFlags)); dispatch( setSmartTransactionsRefreshInterval( - swapsFeatureFlags.smartTransactions?.batchStatusPollingInterval, + featureFlags?.batchStatusPollingInterval ?? 1000, ), ); })