diff --git a/packages/appstore/src/components/cfds-listing/__tests__/index.spec.tsx b/packages/appstore/src/components/cfds-listing/__tests__/index.spec.tsx index d95e9f924781..76714f55b0c8 100644 --- a/packages/appstore/src/components/cfds-listing/__tests__/index.spec.tsx +++ b/packages/appstore/src/components/cfds-listing/__tests__/index.spec.tsx @@ -55,33 +55,74 @@ mockUseTradingPlatformStatus.mockReturnValue({ getPlatformStatus: jest.fn(), }); describe('CFDsListing', () => { - const mock = mockStore({ - traders_hub: { - selected_region: 'Non-EU', - has_any_real_account: true, - is_real: true, - no_MF_account: true, - is_demo_low_risk: true, - }, - client: { - is_landing_company_loaded: true, - real_account_creation_unlock_date: '2022-02-02', - }, - modules: { - cfd: { - toggleCompareAccountsModal: jest.fn(), - setAccountType: jest.fn(), - current_list: {}, + it('should not render the component when cfd accounts are not supported', () => { + const mock = mockStore({ + traders_hub: { + selected_region: 'Non-EU', + has_any_real_account: true, + is_real: true, + no_MF_account: true, + is_demo_low_risk: true, + available_dxtrade_accounts: [], + available_ctrader_accounts: [], + combined_cfd_mt5_accounts: [], }, - }, + client: { + is_landing_company_loaded: true, + real_account_creation_unlock_date: '2022-02-02', + }, + modules: { + cfd: { + toggleCompareAccountsModal: jest.fn(), + setAccountType: jest.fn(), + current_list: {}, + }, + }, + }); + const wrapper = ({ children }: { children: JSX.Element }) => ( + {children} + ); + + render(, { wrapper }); + expect(screen.queryByTestId('listing-container')).not.toBeInTheDocument(); }); - it('should render the component', () => { + it('should render the component when cfd accounts are supported', () => { + const mock = mockStore({ + traders_hub: { + selected_region: 'Non-EU', + has_any_real_account: true, + is_real: true, + no_MF_account: true, + is_demo_low_risk: true, + available_dxtrade_accounts: [], + available_ctrader_accounts: [], + combined_cfd_mt5_accounts: [ + { + landing_company_short: 'svg', + product: 'financial', + status: 'proof_failed', + login: '123', + }, + ], + }, + client: { + is_landing_company_loaded: true, + real_account_creation_unlock_date: '2022-02-02', + }, + modules: { + cfd: { + toggleCompareAccountsModal: jest.fn(), + setAccountType: jest.fn(), + current_list: {}, + }, + }, + }); const wrapper = ({ children }: { children: JSX.Element }) => ( {children} ); render(, { wrapper }); - expect(screen.getByTestId('listing-container')).toBeInTheDocument(); + expect(screen.queryByTestId('listing-container')).toBeInTheDocument(); }); }); diff --git a/packages/appstore/src/components/cfds-listing/index.tsx b/packages/appstore/src/components/cfds-listing/index.tsx index 1c10911b9def..96c8563ffdd1 100644 --- a/packages/appstore/src/components/cfds-listing/index.tsx +++ b/packages/appstore/src/components/cfds-listing/index.tsx @@ -190,8 +190,12 @@ const CFDsListing = observer(() => { updateMT5AccountDetails(); }, [is_landing_company_loaded, is_populating_mt5_account_list]); + const is_cfd_accounts_supported = + combined_cfd_mt5_accounts.length || available_dxtrade_accounts.length || available_ctrader_accounts.length; + const is_mt5_list_loading = !is_landing_company_loaded || is_populating_mt5_account_list || is_switching; - return ( + + return is_cfd_accounts_supported ? ( { {has_svg_accounts_to_migrate && is_landing_company_loaded && } - {!is_mt5_list_loading ? ( + {!is_mt5_list_loading && combined_cfd_mt5_accounts.length ? ( {/* MT5 */} {combined_cfd_mt5_accounts.map((existing_account, index: number) => { @@ -553,7 +557,7 @@ const CFDsListing = observer(() => { )} - ); + ) : null; }); export default CFDsListing; diff --git a/packages/appstore/src/modules/traders-hub/index.tsx b/packages/appstore/src/modules/traders-hub/index.tsx index 372ca27a8891..da84cfc37332 100644 --- a/packages/appstore/src/modules/traders-hub/index.tsx +++ b/packages/appstore/src/modules/traders-hub/index.tsx @@ -57,7 +57,14 @@ const TradersHub = observer(() => { } = client; const { is_eu_demo, is_eu_real } = useContentFlag(); - const { selected_platform_type, setTogglePlatformType, is_eu_user } = traders_hub; + const { + selected_platform_type, + setTogglePlatformType, + is_eu_user, + combined_cfd_mt5_accounts, + available_ctrader_accounts, + available_dxtrade_accounts, + } = traders_hub; const traders_hub_ref = React.useRef(null); const can_show_notify = @@ -95,9 +102,12 @@ const TradersHub = observer(() => { setTogglePlatformType(event.target.value); }; if (!is_logged_in) return null; + const is_cfd_accounts_supported = + combined_cfd_mt5_accounts.length || available_dxtrade_accounts.length || available_ctrader_accounts.length; + const should_show_cfd_section = !!(is_mt5_allowed && is_cfd_accounts_supported); const getOrderedPlatformSections = () => { - if (is_mt5_allowed) { + if (should_show_cfd_section) { return ( { const desktopContent = !is_landing_company_loaded ? ( ) : ( - + ); const mobileTabletContent = ( {is_landing_company_loaded ? ( - is_mt5_allowed && ( + should_show_cfd_section && ( { ) : ( )} - {is_landing_company_loaded && !is_mt5_allowed && ( + {is_landing_company_loaded && !should_show_cfd_section && (
@@ -151,8 +161,8 @@ const TradersHub = observer(() => {
diff --git a/packages/cfd/src/Containers/cfd-password-modal-info.tsx b/packages/cfd/src/Containers/cfd-password-modal-info.tsx index 471556ea0cec..f0ec7c1de511 100644 --- a/packages/cfd/src/Containers/cfd-password-modal-info.tsx +++ b/packages/cfd/src/Containers/cfd-password-modal-info.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { Icon, Text } from '@deriv/components'; import { Localize } from '@deriv/translations'; -import { DBVI_COMPANY_NAMES } from '@deriv/shared'; import { useIsSelectedMT5AccountCreated } from '@deriv/hooks'; type CfdPasswordModalInfoProps = { diff --git a/packages/core/src/Stores/traders-hub-store.js b/packages/core/src/Stores/traders-hub-store.js index 3e6e8d04642d..a44d32ee64cc 100644 --- a/packages/core/src/Stores/traders-hub-store.js +++ b/packages/core/src/Stores/traders-hub-store.js @@ -467,9 +467,20 @@ export default class TradersHubStore extends BaseStore { ]; const groupedByProduct = trading_platform_available_accounts.reduce((acc, item) => { - const { product, is_default_jurisdiction } = item; - if ( - is_default_jurisdiction === 'true' || + const { product, is_default_jurisdiction, linkable_landing_companies } = item; + if (this.is_demo || (this.no_CR_account && !this.is_eu_user)) { + if ( + is_default_jurisdiction === 'true' || + (acc[product] && acc[product].some(i => i.is_default_jurisdiction === 'true')) + ) { + if (!acc[product]) { + acc[product] = []; + } + acc[product].push(item); + } + } else if ( + (linkable_landing_companies.includes(this.root_store.client.landing_company_shortcode) && + is_default_jurisdiction === 'true') || (acc[product] && acc[product].some(i => i.is_default_jurisdiction === 'true')) ) { if (!acc[product]) { @@ -477,16 +488,24 @@ export default class TradersHubStore extends BaseStore { } acc[product].push(item); } - return acc; }, {}); - const getFilteredAccounts = () => - this.root_store.client.is_logged_in - ? getMT5Accounts.filter(account => - Object.prototype.hasOwnProperty.call(groupedByProduct, account.product) - ) - : getMT5Accounts; + const getFilteredAccounts = () => { + if (this.is_low_risk_cr_eu_real) { + const existing_account = this.root_store.client.mt5_login_list.filter( + account => account.landing_company_short === this.root_store.client.landing_company_shortcode + ); + return existing_account.length + ? getMT5Accounts.filter(account => account.product === existing_account[0].product) + : []; + } else if (this.root_store.client.is_logged_in) { + return getMT5Accounts.filter(account => + Object.prototype.hasOwnProperty.call(groupedByProduct, account.product) + ); + } + return getMT5Accounts; + }; const all_available_accounts = [...getCFDAvailableAccount(), ...getFilteredAccounts()]; this.available_cfd_accounts = all_available_accounts.map(account => { @@ -534,6 +553,7 @@ export default class TradersHubStore extends BaseStore { ); return; } + if (this.financial_restricted_countries) { this.available_mt5_accounts = this.available_cfd_accounts.filter( account => account.market_type === 'financial' && account.platform === CFD_PLATFORMS.MT5 @@ -891,14 +911,20 @@ export default class TradersHubStore extends BaseStore { ); const { mt5_login_list } = await WS.authorized.mt5LoginList(); const current_account = mt5_login_list?.filter( - account => account.landing_company_short === jurisdiction_selected_shortcode && account.product === product + account => + account.landing_company_short === jurisdiction_selected_shortcode && + account.product === product && + account.account_type === this.selected_account_type ); if (current_account.length) { this.setSelectedJurisdictionKYCStatus(current_account[0]?.client_kyc_status ?? {}); } else { const selected_mt5_account = trading_platform_available_accounts?.filter( - account => account.shortcode === jurisdiction_selected_shortcode && account.product === product + account => + account.shortcode === jurisdiction_selected_shortcode && + account.product === product && + account.is_default_jurisdiction === 'true' ); if (selected_mt5_account.length) { this.setSelectedJurisdictionKYCStatus(selected_mt5_account[0]?.client_kyc_status ?? {}); diff --git a/packages/hooks/src/__tests__/useIsSelectedMT5AccountCreated.spec.tsx b/packages/hooks/src/__tests__/useIsSelectedMT5AccountCreated.spec.tsx index f7912df8c47f..c98a3b6a6695 100644 --- a/packages/hooks/src/__tests__/useIsSelectedMT5AccountCreated.spec.tsx +++ b/packages/hooks/src/__tests__/useIsSelectedMT5AccountCreated.spec.tsx @@ -13,12 +13,20 @@ describe('useIsSelectedMT5AccountCreated', () => { common: { platform: CFD_PLATFORMS.MT5 }, client: { mt5_login_list: [ - { landing_company_short: 'svg', product: 'financial', status: 'proof_failed', login: '123' }, + { + landing_company_short: 'svg', + product: 'financial', + status: 'proof_failed', + login: '123', + account_type: 'real', + }, ], updateMT5AccountDetails: jest.fn(), trading_platform_available_accounts: [{ shortcode: 'svg', product: 'financial' }], }, - + traders_hub: { + selected_account_type: 'real', + }, modules: { cfd: { jurisdiction_selected_shortcode: 'svg', product: 'financial' } }, }); @@ -33,6 +41,7 @@ describe('useIsSelectedMT5AccountCreated', () => { product: 'financial', status: 'proof_failed', login: '123', + account_type: 'real', }); expect(result.current.existing_account_status).toBe(MT5_ACCOUNT_STATUS.FAILED); expect(result.current.available_account_to_create).toBeNull(); @@ -42,14 +51,23 @@ describe('useIsSelectedMT5AccountCreated', () => { common: { platform: CFD_PLATFORMS.MT5 }, client: { mt5_login_list: [ - { landing_company_short: 'svg', product: 'financial', status: 'proof_failed', login: '123' }, + { + landing_company_short: 'svg', + product: 'financial', + status: 'proof_failed', + login: '123', + account_type: 'real', + }, ], updateMT5AccountDetails: jest.fn(), trading_platform_available_accounts: [ { shortcode: 'svg', product: 'financial' }, - { shortcode: 'bvi', product: 'zero_spread' }, + { shortcode: 'bvi', product: 'zero_spread', is_default_jurisdiction: 'true' }, ], }, + traders_hub: { + selected_account_type: 'real', + }, modules: { cfd: { jurisdiction_selected_shortcode: 'bvi', product: 'zero_spread' } }, }); @@ -65,13 +83,21 @@ describe('useIsSelectedMT5AccountCreated', () => { expect(result.current.available_account_to_create).toEqual({ shortcode: 'bvi', product: 'zero_spread', + is_default_jurisdiction: 'true', }); }); it('should return the correct status when account status "verification_pending"', () => { const mock = mockStore({ client: { - mt5_login_list: [{ landing_company_short: 'svg', product: 'standard', status: 'verification_pending' }], + mt5_login_list: [ + { + landing_company_short: 'svg', + product: 'standard', + status: 'verification_pending', + account_type: 'real', + }, + ], trading_platform_available_accounts: [{ shortcode: 'svg', product: 'standard' }], updateMT5AccountDetails: jest.fn(), }, @@ -81,6 +107,100 @@ describe('useIsSelectedMT5AccountCreated', () => { product: 'standard', }, }, + traders_hub: { + selected_account_type: 'real', + }, + }); + + const wrapper = ({ children }: { children: JSX.Element }) => ( + {children} + ); + const { result } = renderHook(() => useIsSelectedMT5AccountCreated(), { wrapper }); + + expect(result.current.existing_account_status).toBe(MT5_ACCOUNT_STATUS.PENDING); + }); + + it('should return available accounts based on real/demo account type', () => { + const mock = mockStore({ + client: { + mt5_login_list: [ + { + landing_company_short: 'svg', + product: 'standard', + status: 'verification_pending', + account_type: 'real', + }, + { + landing_company_short: 'svg', + product: 'financial', + status: 'proof_failed', + account_type: 'real', + }, + ], + trading_platform_available_accounts: [ + { shortcode: 'svg', product: 'standard', is_default_jurisdiction: 'true' }, + { shortcode: 'bvi', product: 'financial', is_default_jurisdiction: 'true' }, + ], + updateMT5AccountDetails: jest.fn(), + }, + modules: { + cfd: { + jurisdiction_selected_shortcode: 'svg', + product: 'standard', + }, + }, + traders_hub: { + selected_account_type: 'demo', + }, + }); + + const wrapper = ({ children }: { children: JSX.Element }) => ( + {children} + ); + const { result } = renderHook(() => useIsSelectedMT5AccountCreated(), { wrapper }); + + expect(result.current.is_selected_MT5_account_created).toBe(false); + expect(result.current.existing_account).toBeNull(); + expect(result.current.existing_account_status).toBeNull(); + expect(result.current.available_account_to_create).toEqual({ + shortcode: 'svg', + product: 'standard', + is_default_jurisdiction: 'true', + }); + }); + + it('should return available accounts based on real/demo account type', () => { + const mock = mockStore({ + client: { + mt5_login_list: [ + { + landing_company_short: 'svg', + product: 'standard', + status: 'verification_pending', + account_type: 'real', + }, + { + landing_company_short: 'svg', + product: 'financial', + status: 'proof_failed', + account_type: 'real', + }, + ], + trading_platform_available_accounts: [ + { shortcode: 'svg', product: 'standard', is_default_jurisdiction: 'true' }, + { shortcode: 'bvi', product: 'financial', is_default_jurisdiction: 'true' }, + ], + updateMT5AccountDetails: jest.fn(), + }, + modules: { + cfd: { + jurisdiction_selected_shortcode: 'svg', + product: 'standard', + }, + }, + traders_hub: { + selected_account_type: 'real', + }, }); const wrapper = ({ children }: { children: JSX.Element }) => ( @@ -88,7 +208,15 @@ describe('useIsSelectedMT5AccountCreated', () => { ); const { result } = renderHook(() => useIsSelectedMT5AccountCreated(), { wrapper }); + expect(result.current.is_selected_MT5_account_created).toBe(true); + expect(result.current.existing_account).toEqual({ + landing_company_short: 'svg', + product: 'standard', + status: 'verification_pending', + account_type: 'real', + }); expect(result.current.existing_account_status).toBe(MT5_ACCOUNT_STATUS.PENDING); + expect(result.current.available_account_to_create).toBeNull(); }); it('should handle cases where mt5_login_list and trading_platform_available_accounts are empty', () => { @@ -104,6 +232,9 @@ describe('useIsSelectedMT5AccountCreated', () => { product: 'standard', }, }, + traders_hub: { + selected_account_type: 'real', + }, }); const wrapper = ({ children }: { children: JSX.Element }) => ( diff --git a/packages/hooks/src/useIsSelectedMT5AccountCreated.ts b/packages/hooks/src/useIsSelectedMT5AccountCreated.ts index 7a37a63af76b..6a698981a7f2 100644 --- a/packages/hooks/src/useIsSelectedMT5AccountCreated.ts +++ b/packages/hooks/src/useIsSelectedMT5AccountCreated.ts @@ -27,6 +27,7 @@ const useIsSelectedMT5AccountCreated = () => { const { client, modules: { cfd }, + traders_hub: { selected_account_type }, } = useStore(); const { mt5_login_list, trading_platform_available_accounts, updateMT5AccountDetails } = client; @@ -39,17 +40,22 @@ const useIsSelectedMT5AccountCreated = () => { const { jurisdiction_selected_shortcode, product } = cfd; const created_account = mt5_login_list.filter( - account => account.landing_company_short === jurisdiction_selected_shortcode && account.product === product + account => + account.landing_company_short === jurisdiction_selected_shortcode && + account.product === product && + account.account_type === selected_account_type ); const selected_account = trading_platform_available_accounts.filter( - account => account.shortcode === jurisdiction_selected_shortcode && account.product === product + account => + account.shortcode === jurisdiction_selected_shortcode && + account.product === product && + account.is_default_jurisdiction === 'true' ); const is_selected_MT5_account_created = created_account && Object.keys(created_account).length > 0; const existing_account = is_selected_MT5_account_created ? created_account[0] : null; const existing_account_status = existing_account?.status ? getStatusBadge(existing_account?.status) : null; - const available_account_to_create = !is_selected_MT5_account_created ? selected_account[0] : null; return { is_selected_MT5_account_created,