Skip to content

feat(suite): use message system context and features in trading #19089

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions packages/suite/src/hooks/suite/useMessageSystemTrading.ts
Original file line number Diff line number Diff line change
@@ -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,
};
};
4 changes: 4 additions & 0 deletions packages/suite/src/support/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
31 changes: 26 additions & 5 deletions packages/suite/src/views/wallet/trading/buy/TradingBuyForm.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,41 @@
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';
import { TradingContainer } from 'src/views/wallet/trading/common/TradingContainer';
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 (
<TradingFormContext.Provider value={tradingBuyContextValues}>
<TradingFormLayout />
</TradingFormContext.Provider>
);
};

const TradingBuyFormWrapper = ({ selectedAccount }: UseTradingProps) => {
const type: TradingType = 'buy';
const { isDisabled, content } = useMessageSystemTrading(type);

return (
<TradingLayout>
<TradingFormContext.Provider value={tradingBuyContextValues}>
<TradingFormLayout />
</TradingFormContext.Provider>
<ContextMessage context={Context.tradingBuy} />
{isDisabled ? (
<TradingDisabled type={type} content={content} />
) : (
<TradingBuyFormContent selectedAccount={selectedAccount} />
)}
</TradingLayout>
);
};

export const TradingBuyForm = () => <TradingContainer SectionComponent={TradingBuyComponent} />;
export const TradingBuyForm = () => <TradingContainer SectionComponent={TradingBuyFormWrapper} />;
34 changes: 34 additions & 0 deletions packages/suite/src/views/wallet/trading/common/TradingDisabled.tsx
Original file line number Diff line number Diff line change
@@ -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<TradingDisabledProps['type'], ExtendedMessageDescriptor['id']> = {
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 (
<Banner icon="warning" variant="warning">
{content ?? (
<Translation
id="TR_TRADING_DISABLED_DEFAULT"
values={{ type: translationString(typeLabels[type]) }}
/>
)}
</Banner>
);
};
Original file line number Diff line number Diff line change
@@ -1,22 +1,43 @@
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';
import { TradingContainer } from 'src/views/wallet/trading/common/TradingContainer';
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 (
<TradingFormContext.Provider value={tradingExchangeContextValue}>
<TradingFormLayout />
</TradingFormContext.Provider>
);
};

const TradingExchangeFormWrapper = ({ selectedAccount }: UseTradingProps) => {
const type: TradingType = 'exchange';
const { isDisabled, content } = useMessageSystemTrading(type);

return (
<TradingLayout>
<TradingFormContext.Provider value={tradingExchangeContextValue}>
<TradingFormLayout />
</TradingFormContext.Provider>
<ContextMessage context={Context.tradingExchange} />
{isDisabled ? (
<TradingDisabled type={type} content={content} />
) : (
<TradingExchangeFormContent selectedAccount={selectedAccount} />
)}
</TradingLayout>
);
};

export const TradingExchangeForm = () => (
<TradingContainer SectionComponent={TradingExchangeFormComponent} />
<TradingContainer SectionComponent={TradingExchangeFormWrapper} />
);
33 changes: 26 additions & 7 deletions packages/suite/src/views/wallet/trading/sell/TradingSellForm.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,41 @@
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';
import { TradingContainer } from 'src/views/wallet/trading/common/TradingContainer';
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 (
<TradingFormContext.Provider value={tradingSellContextValues}>
<TradingFormLayout />
</TradingFormContext.Provider>
);
};

const TradingSellFormWrapper = ({ selectedAccount }: UseTradingProps) => {
const type: TradingType = 'sell';
const { isDisabled, content } = useMessageSystemTrading(type);

return (
<TradingLayout>
<TradingFormContext.Provider value={tradingSellContextValues}>
<TradingFormLayout />
</TradingFormContext.Provider>
<ContextMessage context={Context.tradingSell} />
{isDisabled ? (
<TradingDisabled type={type} content={content} />
) : (
<TradingSellFormContent selectedAccount={selectedAccount} />
)}
</TradingLayout>
);
};

export const TradingSellForm = () => (
<TradingContainer SectionComponent={TradingSellFormComponent} />
);
export const TradingSellForm = () => <TradingContainer SectionComponent={TradingSellFormWrapper} />;
6 changes: 2 additions & 4 deletions suite-common/message-system/src/messageSystemTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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!!!).
Expand All @@ -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];
Expand Down
10 changes: 5 additions & 5 deletions suite-native/app/src/navigation/AppTabNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import {
TradingStackNavigator,
selectIsTradingBuyEnabled,
selectIsTradingEnabled,
selectIsTradingExchangeEnabled,
selectIsTradingSellEnabled,
selectIsTradingSwapEnabled,
} from '@suite-native/module-trading';
import { AppTabsParamList, AppTabsRoutes, TabBar } from '@suite-native/navigation';

Expand All @@ -22,13 +22,13 @@ const Tab = createBottomTabNavigator<AppTabsParamList>();

const getTradingAnalyticsType = (
isTradingBuyEnabled: boolean,
isTradingSwapEnabled: boolean,
isTradingExchangeEnabled: boolean,
isTradingSellEnabled: boolean,
) => {
if (isTradingBuyEnabled) {
return 'buy';
}
if (isTradingSwapEnabled) {
if (isTradingExchangeEnabled) {
return 'exchange';
}
if (isTradingSellEnabled) {
Expand All @@ -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 (
Expand All @@ -67,7 +67,7 @@ export const AppTabNavigator = () => {
tabPress: () => {
const tradingType = getTradingAnalyticsType(
isTradingBuyEnabled,
isTradingSwapEnabled,
isTradingExchangeEnabled,
isTradingSellEnabled,
);
if (!tradingType) return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('AppTabNavigator', () => {
featureFlags: {
...featureFlagsInitialState,
[FeatureFlag.IsTradingBuyEnabled]: false,
[FeatureFlag.IsTradingSwapEnabled]: false,
[FeatureFlag.IsTradingExchangeEnabled]: false,
[FeatureFlag.IsTradingSellEnabled]: false,
},
messageSystem: {
Expand All @@ -55,7 +55,7 @@ describe('AppTabNavigator', () => {
flag: false,
},
{
domain: 'trading.swap',
domain: 'trading.exchange',
flag: false,
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe('featureFlagsSlice', () => {
isDebugKeysAllowed: false,
isWalletConnectEnabled: false,
isTradingBuyEnabled: false,
isTradingSwapEnabled: false,
isTradingExchangeEnabled: false,
isTradingSellEnabled: false,
});
});
Expand All @@ -46,7 +46,7 @@ describe('featureFlagsSlice', () => {
isDebugKeysAllowed: false,
isWalletConnectEnabled: false,
isTradingBuyEnabled: false,
isTradingSwapEnabled: false,
isTradingExchangeEnabled: false,
isTradingSellEnabled: false,
});
});
Expand Down
6 changes: 3 additions & 3 deletions suite-native/feature-flags/src/featureFlagsSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const FeatureFlag = {
IsDebugKeysAllowed: 'isDebugKeysAllowed',
IsWalletConnectEnabled: 'isWalletConnectEnabled',
IsTradingBuyEnabled: 'isTradingBuyEnabled',
IsTradingSwapEnabled: 'isTradingSwapEnabled',
IsTradingExchangeEnabled: 'isTradingExchangeEnabled',
IsTradingSellEnabled: 'isTradingSellEnabled',
} as const;

Expand All @@ -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',
Expand All @@ -48,7 +48,7 @@ export const featureFlagsPersistedKeys: Array<keyof FeatureFlagsState> = [
FeatureFlag.IsConnectPopupEnabled,
FeatureFlag.IsWalletConnectEnabled,
FeatureFlag.IsTradingBuyEnabled,
FeatureFlag.IsTradingSwapEnabled,
FeatureFlag.IsTradingExchangeEnabled,
FeatureFlag.IsTradingSellEnabled,
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<FeatureFlagEnum, string>;

Expand Down
Loading
Loading