diff --git a/packages/suite/src/hooks/suite/useMessageSystemTrading.ts b/packages/suite/src/hooks/suite/useMessageSystemTrading.ts new file mode 100644 index 000000000000..524c71901be7 --- /dev/null +++ b/packages/suite/src/hooks/suite/useMessageSystemTrading.ts @@ -0,0 +1,25 @@ +import { + Feature, + selectFeatureMessageContent, + selectIsFeatureDisabled, +} from '@suite-common/message-system'; +import { TradingType } from '@suite-common/trading'; + +import { selectLanguage } from 'src/reducers/suite/suiteReducer'; + +import { useSelector } from './useSelector'; + +export const useMessageSystemTrading = (type: TradingType) => { + const language = useSelector(selectLanguage); + + const isDisabled = useSelector(state => selectIsFeatureDisabled(state, Feature.trading[type])); + + const content = useSelector(state => + selectFeatureMessageContent(state, Feature.trading[type], language), + ); + + return { + isDisabled, + content, + }; +}; diff --git a/packages/suite/src/support/messages.ts b/packages/suite/src/support/messages.ts index 0180135dd1e0..ed679963b2fd 100644 --- a/packages/suite/src/support/messages.ts +++ b/packages/suite/src/support/messages.ts @@ -233,6 +233,10 @@ export default defineMessages({ defaultMessage: 'All fees included; the transaction fee is estimated at {feeAmount} ({feeAmountFiat}).', }, + TR_TRADING_DISABLED_DEFAULT: { + defaultMessage: '{type} is currently disabled.', + id: 'TR_TRADING_DISABLED_DEFAULT', + }, TR_TRADING_TERMS_DONT_SHOW_AGAIN: { defaultMessage: 'Don’t show me this again', id: 'TR_TRADING_TERMS_DONT_SHOW_AGAIN', diff --git a/packages/suite/src/views/wallet/trading/buy/TradingBuyForm.tsx b/packages/suite/src/views/wallet/trading/buy/TradingBuyForm.tsx index 1a02f26a76ca..d20575d644b9 100644 --- a/packages/suite/src/views/wallet/trading/buy/TradingBuyForm.tsx +++ b/packages/suite/src/views/wallet/trading/buy/TradingBuyForm.tsx @@ -1,3 +1,8 @@ +import { Context } from '@suite-common/message-system'; +import { TradingType } from '@suite-common/trading'; + +import { ContextMessage } from 'src/components/wallet/WalletLayout/AccountBanners/ContextMessage'; +import { useMessageSystemTrading } from 'src/hooks/suite/useMessageSystemTrading'; import { useTradingBuyForm } from 'src/hooks/wallet/trading/form/useTradingBuyForm'; import { TradingFormContext } from 'src/hooks/wallet/trading/form/useTradingCommonForm'; import { UseTradingProps } from 'src/types/trading/trading'; @@ -5,16 +10,32 @@ import { TradingContainer } from 'src/views/wallet/trading/common/TradingContain import { TradingFormLayout } from 'src/views/wallet/trading/common/TradingForm/TradingFormLayout'; import { TradingLayout } from 'src/views/wallet/trading/common/TradingLayout/TradingLayout'; -const TradingBuyComponent = ({ selectedAccount }: UseTradingProps) => { +import { TradingDisabled } from '../common/TradingDisabled'; + +const TradingBuyFormContent = ({ selectedAccount }: UseTradingProps) => { const tradingBuyContextValues = useTradingBuyForm({ selectedAccount }); + return ( + + + + ); +}; + +const TradingBuyFormWrapper = ({ selectedAccount }: UseTradingProps) => { + const type: TradingType = 'buy'; + const { isDisabled, content } = useMessageSystemTrading(type); + return ( - - - + + {isDisabled ? ( + + ) : ( + + )} ); }; -export const TradingBuyForm = () => ; +export const TradingBuyForm = () => ; diff --git a/packages/suite/src/views/wallet/trading/common/TradingDisabled.tsx b/packages/suite/src/views/wallet/trading/common/TradingDisabled.tsx new file mode 100644 index 000000000000..9be0e686b35d --- /dev/null +++ b/packages/suite/src/views/wallet/trading/common/TradingDisabled.tsx @@ -0,0 +1,34 @@ +import React from 'react'; + +import { ExtendedMessageDescriptor } from '@suite-common/intl-types'; +import { TradingType } from '@suite-common/trading'; +import { Banner } from '@trezor/components'; + +import { Translation } from 'src/components/suite'; +import { useTranslation } from 'src/hooks/suite'; + +const typeLabels: Record = { + buy: 'TR_BUY', + sell: 'TR_TRADING_SELL', + exchange: 'TR_TRADING_SWAP', +}; + +type TradingDisabledProps = { + type: TradingType; + content?: string; +}; + +export const TradingDisabled = ({ type, content }: TradingDisabledProps) => { + const { translationString } = useTranslation(); + + return ( + + {content ?? ( + + )} + + ); +}; diff --git a/packages/suite/src/views/wallet/trading/exchange/TradingExchangeForm.tsx b/packages/suite/src/views/wallet/trading/exchange/TradingExchangeForm.tsx index 88ca62726603..60d690d7ecd2 100644 --- a/packages/suite/src/views/wallet/trading/exchange/TradingExchangeForm.tsx +++ b/packages/suite/src/views/wallet/trading/exchange/TradingExchangeForm.tsx @@ -1,3 +1,8 @@ +import { Context } from '@suite-common/message-system'; +import { TradingType } from '@suite-common/trading'; + +import { ContextMessage } from 'src/components/wallet/WalletLayout/AccountBanners/ContextMessage'; +import { useMessageSystemTrading } from 'src/hooks/suite/useMessageSystemTrading'; import { TradingFormContext } from 'src/hooks/wallet/trading/form/useTradingCommonForm'; import { useTradingExchangeForm } from 'src/hooks/wallet/trading/form/useTradingExchangeForm'; import { UseTradingProps } from 'src/types/trading/trading'; @@ -5,18 +10,34 @@ import { TradingContainer } from 'src/views/wallet/trading/common/TradingContain import { TradingFormLayout } from 'src/views/wallet/trading/common/TradingForm/TradingFormLayout'; import { TradingLayout } from 'src/views/wallet/trading/common/TradingLayout/TradingLayout'; -const TradingExchangeFormComponent = ({ selectedAccount }: UseTradingProps) => { +import { TradingDisabled } from '../common/TradingDisabled'; + +const TradingExchangeFormContent = ({ selectedAccount }: UseTradingProps) => { const tradingExchangeContextValue = useTradingExchangeForm({ selectedAccount }); + return ( + + + + ); +}; + +const TradingExchangeFormWrapper = ({ selectedAccount }: UseTradingProps) => { + const type: TradingType = 'exchange'; + const { isDisabled, content } = useMessageSystemTrading(type); + return ( - - - + + {isDisabled ? ( + + ) : ( + + )} ); }; export const TradingExchangeForm = () => ( - + ); diff --git a/packages/suite/src/views/wallet/trading/sell/TradingSellForm.tsx b/packages/suite/src/views/wallet/trading/sell/TradingSellForm.tsx index 2919b5b8cb65..82315ab69ae3 100644 --- a/packages/suite/src/views/wallet/trading/sell/TradingSellForm.tsx +++ b/packages/suite/src/views/wallet/trading/sell/TradingSellForm.tsx @@ -1,3 +1,8 @@ +import { Context } from '@suite-common/message-system'; +import { TradingType } from '@suite-common/trading'; + +import { ContextMessage } from 'src/components/wallet/WalletLayout/AccountBanners/ContextMessage'; +import { useMessageSystemTrading } from 'src/hooks/suite/useMessageSystemTrading'; import { TradingFormContext } from 'src/hooks/wallet/trading/form/useTradingCommonForm'; import { useTradingSellForm } from 'src/hooks/wallet/trading/form/useTradingSellForm'; import { UseTradingProps } from 'src/types/trading/trading'; @@ -5,18 +10,32 @@ import { TradingContainer } from 'src/views/wallet/trading/common/TradingContain import { TradingFormLayout } from 'src/views/wallet/trading/common/TradingForm/TradingFormLayout'; import { TradingLayout } from 'src/views/wallet/trading/common/TradingLayout/TradingLayout'; -const TradingSellFormComponent = ({ selectedAccount }: UseTradingProps) => { +import { TradingDisabled } from '../common/TradingDisabled'; + +const TradingSellFormContent = ({ selectedAccount }: UseTradingProps) => { const tradingSellContextValues = useTradingSellForm({ selectedAccount }); + return ( + + + + ); +}; + +const TradingSellFormWrapper = ({ selectedAccount }: UseTradingProps) => { + const type: TradingType = 'sell'; + const { isDisabled, content } = useMessageSystemTrading(type); + return ( - - - + + {isDisabled ? ( + + ) : ( + + )} ); }; -export const TradingSellForm = () => ( - -); +export const TradingSellForm = () => ; diff --git a/suite-common/message-system/src/messageSystemTypes.ts b/suite-common/message-system/src/messageSystemTypes.ts index 4f7c5e1c5120..9da34dc3fc8f 100644 --- a/suite-common/message-system/src/messageSystemTypes.ts +++ b/suite-common/message-system/src/messageSystemTypes.ts @@ -42,11 +42,10 @@ export const Feature = { entropyCheckMobile: 'security.entropyCheck.mobile', // FW update feature flag implemented only for mobile app firmwareUpdate: 'device.firmware.update', - // trading feature flags implemented for mobile app trading: { buy: 'trading.buy', sell: 'trading.sell', - swap: 'trading.swap', + exchange: 'trading.exchange', }, // device onboarding (MOBILE ONLY!!!). @@ -67,10 +66,9 @@ export const Context = { coinjoin: 'accounts.coinjoin', ethStaking: 'accounts.eth.staking', solStaking: 'accounts.sol.staking', - // trading contexts are implemented for mobile app tradingBuy: 'trading.buy', tradingSell: 'trading.sell', - tradingSwap: 'trading.swap', + tradingExchange: 'trading.exchange', } as const; export type ContextDomain = (typeof Context)[keyof typeof Context]; diff --git a/suite-native/app/src/navigation/AppTabNavigator.tsx b/suite-native/app/src/navigation/AppTabNavigator.tsx index 1235e7c76efb..2b8da7eb4586 100644 --- a/suite-native/app/src/navigation/AppTabNavigator.tsx +++ b/suite-native/app/src/navigation/AppTabNavigator.tsx @@ -11,8 +11,8 @@ import { TradingStackNavigator, selectIsTradingBuyEnabled, selectIsTradingEnabled, + selectIsTradingExchangeEnabled, selectIsTradingSellEnabled, - selectIsTradingSwapEnabled, } from '@suite-native/module-trading'; import { AppTabsParamList, AppTabsRoutes, TabBar } from '@suite-native/navigation'; @@ -22,13 +22,13 @@ const Tab = createBottomTabNavigator(); const getTradingAnalyticsType = ( isTradingBuyEnabled: boolean, - isTradingSwapEnabled: boolean, + isTradingExchangeEnabled: boolean, isTradingSellEnabled: boolean, ) => { if (isTradingBuyEnabled) { return 'buy'; } - if (isTradingSwapEnabled) { + if (isTradingExchangeEnabled) { return 'exchange'; } if (isTradingSellEnabled) { @@ -43,7 +43,7 @@ export const AppTabNavigator = () => { const isTradingEnabled = useSelector(selectIsTradingEnabled); const isTradingBuyEnabled = useSelector(selectIsTradingBuyEnabled); - const isTradingSwapEnabled = useSelector(selectIsTradingSwapEnabled); + const isTradingExchangeEnabled = useSelector(selectIsTradingExchangeEnabled); const isTradingSellEnabled = useSelector(selectIsTradingSellEnabled); return ( @@ -67,7 +67,7 @@ export const AppTabNavigator = () => { tabPress: () => { const tradingType = getTradingAnalyticsType( isTradingBuyEnabled, - isTradingSwapEnabled, + isTradingExchangeEnabled, isTradingSellEnabled, ); if (!tradingType) return; diff --git a/suite-native/app/src/navigation/__tests__/AppTabNavigator.comp.test.tsx b/suite-native/app/src/navigation/__tests__/AppTabNavigator.comp.test.tsx index d44faa1fa83c..b469a3f71871 100644 --- a/suite-native/app/src/navigation/__tests__/AppTabNavigator.comp.test.tsx +++ b/suite-native/app/src/navigation/__tests__/AppTabNavigator.comp.test.tsx @@ -32,7 +32,7 @@ describe('AppTabNavigator', () => { featureFlags: { ...featureFlagsInitialState, [FeatureFlag.IsTradingBuyEnabled]: false, - [FeatureFlag.IsTradingSwapEnabled]: false, + [FeatureFlag.IsTradingExchangeEnabled]: false, [FeatureFlag.IsTradingSellEnabled]: false, }, messageSystem: { @@ -55,7 +55,7 @@ describe('AppTabNavigator', () => { flag: false, }, { - domain: 'trading.swap', + domain: 'trading.exchange', flag: false, }, { diff --git a/suite-native/feature-flags/src/__tests__/featureFlagsSlice.test.ts b/suite-native/feature-flags/src/__tests__/featureFlagsSlice.test.ts index d2e4eb086f70..d6c3b8568119 100644 --- a/suite-native/feature-flags/src/__tests__/featureFlagsSlice.test.ts +++ b/suite-native/feature-flags/src/__tests__/featureFlagsSlice.test.ts @@ -23,7 +23,7 @@ describe('featureFlagsSlice', () => { isDebugKeysAllowed: false, isWalletConnectEnabled: false, isTradingBuyEnabled: false, - isTradingSwapEnabled: false, + isTradingExchangeEnabled: false, isTradingSellEnabled: false, }); }); @@ -46,7 +46,7 @@ describe('featureFlagsSlice', () => { isDebugKeysAllowed: false, isWalletConnectEnabled: false, isTradingBuyEnabled: false, - isTradingSwapEnabled: false, + isTradingExchangeEnabled: false, isTradingSellEnabled: false, }); }); diff --git a/suite-native/feature-flags/src/featureFlagsSlice.ts b/suite-native/feature-flags/src/featureFlagsSlice.ts index 343bcc9b35b5..221df137932e 100644 --- a/suite-native/feature-flags/src/featureFlagsSlice.ts +++ b/suite-native/feature-flags/src/featureFlagsSlice.ts @@ -10,7 +10,7 @@ export const FeatureFlag = { IsDebugKeysAllowed: 'isDebugKeysAllowed', IsWalletConnectEnabled: 'isWalletConnectEnabled', IsTradingBuyEnabled: 'isTradingBuyEnabled', - IsTradingSwapEnabled: 'isTradingSwapEnabled', + IsTradingExchangeEnabled: 'isTradingExchangeEnabled', IsTradingSellEnabled: 'isTradingSellEnabled', } as const; @@ -35,7 +35,7 @@ export const featureFlagsInitialState: FeatureFlagsState = { [FeatureFlag.IsWalletConnectEnabled]: process.env.EXPO_PUBLIC_FF_IS_WALLET_CONNECT_ENABLED === 'true', [FeatureFlag.IsTradingBuyEnabled]: process.env.EXPO_PUBLIC_FF_IS_TRADING_BUY_ENABLED === 'true', - [FeatureFlag.IsTradingSwapEnabled]: + [FeatureFlag.IsTradingExchangeEnabled]: process.env.EXPO_PUBLIC_FF_IS_TRADING_SWAP_ENABLED === 'true', [FeatureFlag.IsTradingSellEnabled]: process.env.EXPO_PUBLIC_FF_IS_TRADING_SELL_ENABLED === 'true', @@ -48,7 +48,7 @@ export const featureFlagsPersistedKeys: Array = [ FeatureFlag.IsConnectPopupEnabled, FeatureFlag.IsWalletConnectEnabled, FeatureFlag.IsTradingBuyEnabled, - FeatureFlag.IsTradingSwapEnabled, + FeatureFlag.IsTradingExchangeEnabled, FeatureFlag.IsTradingSellEnabled, ]; diff --git a/suite-native/module-dev-utils/src/components/FeatureFlags.tsx b/suite-native/module-dev-utils/src/components/FeatureFlags.tsx index 0371c67ed89e..9fc10e02ed73 100644 --- a/suite-native/module-dev-utils/src/components/FeatureFlags.tsx +++ b/suite-native/module-dev-utils/src/components/FeatureFlags.tsx @@ -14,7 +14,7 @@ const featureFlagsTitleMap = { [FeatureFlagEnum.IsDebugKeysAllowed]: 'Device Auth Check Debug Keys', [FeatureFlagEnum.IsWalletConnectEnabled]: 'WalletConnect', [FeatureFlagEnum.IsTradingBuyEnabled]: 'πŸ’° Trading Buy', - [FeatureFlagEnum.IsTradingSwapEnabled]: 'πŸ’° Trading Swap', + [FeatureFlagEnum.IsTradingExchangeEnabled]: 'πŸ’° Trading Swap', [FeatureFlagEnum.IsTradingSellEnabled]: 'πŸ’° Trading Sell', } as const satisfies Record; diff --git a/suite-native/module-trading/src/selectors/__tests__/commonSelectors.test.ts b/suite-native/module-trading/src/selectors/__tests__/commonSelectors.test.ts index 65615eb0bfbf..bfd012d63a76 100644 --- a/suite-native/module-trading/src/selectors/__tests__/commonSelectors.test.ts +++ b/suite-native/module-trading/src/selectors/__tests__/commonSelectors.test.ts @@ -6,8 +6,8 @@ import { initialState } from '../../tradingSlice'; import { selectIsTradingBuyEnabled, selectIsTradingEnabled, + selectIsTradingExchangeEnabled, selectIsTradingSellEnabled, - selectIsTradingSwapEnabled, selectTradingEnvironment, } from '../commonSelectors'; @@ -17,11 +17,11 @@ const contentText = 'Content Text'; const getPreloadedState = ({ buy, sell, - swap, + exchange, }: { buy?: boolean; sell?: boolean; - swap?: boolean; + exchange?: boolean; }) => { const features: Feature[] = []; if (buy !== undefined) { @@ -36,10 +36,10 @@ const getPreloadedState = ({ flag: sell, }); } - if (swap !== undefined) { + if (exchange !== undefined) { features.push({ - domain: 'trading.swap', - flag: swap, + domain: 'trading.exchange', + flag: exchange, }); } @@ -119,13 +119,15 @@ describe('commonSelectors', () => { }); }); - describe('selectIsTradingSwapEnabled', () => { - it('should correctly select that swap is enabled if remote feature is enabled', () => { - expect(selectIsTradingSwapEnabled(getPreloadedState({ swap: true }))).toBe(true); + describe('selectIsTradingExchangeEnabled', () => { + it('should correctly select that exchange is enabled if remote feature is enabled', () => { + expect(selectIsTradingExchangeEnabled(getPreloadedState({ exchange: true }))).toBe( + true, + ); }); - it('should correctly select that swap is not enabled if remote feature is not enabled', () => { - expect(selectIsTradingSwapEnabled(getPreloadedState({}))).toBe(false); + it('should correctly select that exchange is not enabled if remote feature is not enabled', () => { + expect(selectIsTradingExchangeEnabled(getPreloadedState({}))).toBe(false); }); }); diff --git a/suite-native/module-trading/src/selectors/commonSelectors.ts b/suite-native/module-trading/src/selectors/commonSelectors.ts index f3d4e42d1c76..d6b0c75a592a 100644 --- a/suite-native/module-trading/src/selectors/commonSelectors.ts +++ b/suite-native/module-trading/src/selectors/commonSelectors.ts @@ -18,9 +18,11 @@ export const selectIsTradingBuyEnabled = (state: MessageSystemRootState & Featur selectIsFeatureFlagEnabled(state, FeatureFlag.IsTradingBuyEnabled) || selectIsFeatureEnabled(state, Feature.trading.buy, true); -export const selectIsTradingSwapEnabled = (state: MessageSystemRootState & FeatureFlagsRootState) => - selectIsFeatureFlagEnabled(state, FeatureFlag.IsTradingSwapEnabled) || - selectIsFeatureEnabled(state, Feature.trading.swap, false); +export const selectIsTradingExchangeEnabled = ( + state: MessageSystemRootState & FeatureFlagsRootState, +) => + selectIsFeatureFlagEnabled(state, FeatureFlag.IsTradingExchangeEnabled) || + selectIsFeatureEnabled(state, Feature.trading.exchange, false); export const selectIsTradingSellEnabled = (state: MessageSystemRootState & FeatureFlagsRootState) => selectIsFeatureFlagEnabled(state, FeatureFlag.IsTradingSellEnabled) || @@ -28,7 +30,7 @@ export const selectIsTradingSellEnabled = (state: MessageSystemRootState & Featu export const selectIsTradingEnabled = (state: MessageSystemRootState & FeatureFlagsRootState) => selectIsTradingBuyEnabled(state) || - selectIsTradingSwapEnabled(state) || + selectIsTradingExchangeEnabled(state) || selectIsTradingSellEnabled(state); // trade for opening in detail