diff --git a/packages/appstore/package.json b/packages/appstore/package.json
index 04fe6dee5fd3..77cd8a233135 100644
--- a/packages/appstore/package.json
+++ b/packages/appstore/package.json
@@ -29,6 +29,7 @@
"@deriv/cashier": "^1.0.0",
"@deriv/components": "^1.0.0",
"@deriv/cfd": "^1.0.0",
+ "@deriv/hooks": "^1.0.0",
"@deriv/shared": "^1.0.0",
"@deriv/stores": "^1.0.0",
"@deriv/trader": "^3.8.0",
diff --git a/packages/appstore/src/assets/svgs/trading-platform/ic-appstore-swap-free.svg b/packages/appstore/src/assets/svgs/trading-platform/ic-appstore-swap-free.svg
new file mode 100644
index 000000000000..7b464b0951e6
--- /dev/null
+++ b/packages/appstore/src/assets/svgs/trading-platform/ic-appstore-swap-free.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/appstore/src/assets/svgs/trading-platform/index.tsx b/packages/appstore/src/assets/svgs/trading-platform/index.tsx
index 10ab73c97b71..560dfa830f9d 100644
--- a/packages/appstore/src/assets/svgs/trading-platform/index.tsx
+++ b/packages/appstore/src/assets/svgs/trading-platform/index.tsx
@@ -16,6 +16,7 @@ import Financial from 'Assets/svgs/trading-platform/branding/ic-branding-mt5-fin
import Options from 'Assets/svgs/trading-platform/ic-appstore-options.svg';
import SmartTrader from 'Assets/svgs/trading-platform/branding/ic-branding-smarttrader-dashboard.svg';
import SmartTraderBlue from 'Assets/svgs/trading-platform/ic-appstore-smarttrader-blue.svg';
+import SwapFree from 'Assets/svgs/trading-platform/ic-appstore-swap-free.svg';
import { IconProps } from '../icon-types';
export const PlatformIcons = {
@@ -33,6 +34,7 @@ export const PlatformIcons = {
DropDown,
DTrader,
Financial,
+ SwapFree,
Options,
SmartTrader,
SmartTraderBlue,
diff --git a/packages/appstore/src/components/cfds-listing/cfds-listing.scss b/packages/appstore/src/components/cfds-listing/cfds-listing.scss
index 44d35d7421ed..654d41675cab 100644
--- a/packages/appstore/src/components/cfds-listing/cfds-listing.scss
+++ b/packages/appstore/src/components/cfds-listing/cfds-listing.scss
@@ -1,5 +1,6 @@
.cfd-jurisdiction-card--synthetic,
-.cfd-jurisdiction-card--financial {
+.cfd-jurisdiction-card--financial,
+.cfd-jurisdiction-card--all {
border: solid 1px var(--border-normal);
border-radius: 0.8rem;
display: flex;
diff --git a/packages/appstore/src/components/modals/account-type-modal/account-type-modal.tsx b/packages/appstore/src/components/modals/account-type-modal/account-type-modal.tsx
index 54afec4e0cef..cf3a99bfc425 100644
--- a/packages/appstore/src/components/modals/account-type-modal/account-type-modal.tsx
+++ b/packages/appstore/src/components/modals/account-type-modal/account-type-modal.tsx
@@ -5,21 +5,11 @@ import { observer } from 'mobx-react-lite';
import classNames from 'classnames';
import { useStores } from 'Stores/index';
import TradigPlatformIconProps from 'Assets/svgs/trading-platform';
-import { TModalContent, TAccountType, TAccountCard, TTradingPlatformAvailableAccount } from './types';
+import { TModalContent, TAccountCard, TTradingPlatformAvailableAccount } from './types';
import { TIconTypes } from 'Types';
import { CFD_PLATFORMS } from '@deriv/shared';
-
-const getDerivedAccount = (): TAccountType => ({
- title_and_type: localize('Derived'),
- icon: 'Derived',
- description: localize('Trade CFDs on MT5 with Derived indices that simulate real-world market movements.'),
-});
-
-const getFinancialAccount = (): TAccountType => ({
- title_and_type: localize('Financial'),
- icon: 'Financial',
- description: localize('Trade CFDs on MT5 with forex, stock indices, commodities, and cryptocurrencies.'),
-});
+import { getDerivedAccount, getFinancialAccount, getSwapFreeAccount } from '../../../helpers/account-helper';
+import { useHasSwapFreeAccount } from '@deriv/hooks';
const AccountCard = ({ selectAccountTypeCard, account_type_card, title_and_type, description, icon }: TAccountCard) => {
const cardSelection = (cardType: string) => {
@@ -54,6 +44,7 @@ const ModalContent = ({
selectAccountTypeCard,
is_financial_available,
is_synthetic_available,
+ is_swapfree_available,
}: TModalContent) => {
return (
@@ -75,6 +66,15 @@ const ModalContent = ({
icon={getFinancialAccount().icon}
/>
)}
+ {is_swapfree_available && (
+
selectAccountTypeCard(`${getSwapFreeAccount().title_and_type}`)}
+ description={getSwapFreeAccount().description}
+ title_and_type={getSwapFreeAccount().title_and_type}
+ icon={getSwapFreeAccount().icon}
+ />
+ )}
);
};
@@ -92,6 +92,13 @@ const MT5AccountTypeModal = () => {
const { trading_platform_available_accounts } = client;
const { enableApp, disableApp } = ui;
const { setAppstorePlatform } = common;
+
+ React.useEffect(() => {
+ if (!is_account_type_modal_visible) {
+ selectAccountTypeCard('');
+ }
+ }, [is_account_type_modal_visible, selectAccountTypeCard]);
+
const is_financial_available = trading_platform_available_accounts.some(
(available_account: TTradingPlatformAvailableAccount) => available_account.market_type === 'financial'
);
@@ -99,12 +106,22 @@ const MT5AccountTypeModal = () => {
const is_synthetic_available = trading_platform_available_accounts.some(
(available_account: TTradingPlatformAvailableAccount) => available_account.market_type === 'gaming'
);
+ const is_swapfree_available = useHasSwapFreeAccount();
- const set_account_type = () =>
- account_type_card === localize('Derived')
- ? setAccountType({ category: 'real', type: 'synthetic' })
- : setAccountType({ category: 'real', type: 'financial' });
-
+ const set_account_type = () => {
+ switch (account_type_card) {
+ case 'Derived':
+ setAccountType({ category: 'real', type: 'synthetic' });
+ break;
+ case 'Swap-Free':
+ setAccountType({ category: 'real', type: 'all' });
+ break;
+ case 'Financial':
+ default:
+ setAccountType({ category: 'real', type: 'financial' });
+ break;
+ }
+ };
return (
}>
@@ -126,6 +143,7 @@ const MT5AccountTypeModal = () => {
selectAccountTypeCard={selectAccountTypeCard}
is_financial_available={is_financial_available}
is_synthetic_available={is_synthetic_available}
+ is_swapfree_available={is_swapfree_available}
/>
)}
diff --git a/packages/cfd/src/Components/props.types.ts b/packages/cfd/src/Components/props.types.ts
index 3dae634df84c..03d0147dbb6f 100644
--- a/packages/cfd/src/Components/props.types.ts
+++ b/packages/cfd/src/Components/props.types.ts
@@ -52,7 +52,7 @@ export type TCFDAccountCardActionProps = {
};
export type TTradingPlatformAvailableAccount = {
- market_type: 'financial' | 'gaming';
+ market_type: 'financial' | 'gaming' | 'all';
name: string;
requirements: {
after_first_deposit: {
@@ -79,8 +79,10 @@ export type TCFDAccountCard = {
real: string;
};
is_hovered?: boolean;
- isEligibleForMoreDemoMt5Svg: (market_type: 'synthetic' | 'financial') => boolean;
- isEligibleForMoreRealMt5: (market_type: 'synthetic' | 'financial') => boolean;
+ isEligibleForMoreDemoMt5Svg: (
+ market_type: TTradingPlatformAvailableAccount['market_type'] | 'synthetic'
+ ) => boolean;
+ isEligibleForMoreRealMt5: (market_type: TTradingPlatformAvailableAccount['market_type'] | 'synthetic') => boolean;
existing_accounts_data?: TExistingData;
trading_platform_available_accounts: TTradingPlatformAvailableAccount[];
has_banner?: boolean;
@@ -158,9 +160,9 @@ export type TTradingPlatformAccounts = {
/**
* Market type
*/
- market_type?: 'financial' | 'synthetic';
+ market_type?: 'financial' | 'synthetic' | 'all';
/**
* Name of trading platform.
*/
- platform?: 'dxtrade';
+ platform?: 'dxtrade' | string;
};
diff --git a/packages/cfd/src/Constants/cfd-specifications.ts b/packages/cfd/src/Constants/cfd-specifications.ts
index edc80044e78a..5b38704f14dd 100644
--- a/packages/cfd/src/Constants/cfd-specifications.ts
+++ b/packages/cfd/src/Constants/cfd-specifications.ts
@@ -38,6 +38,12 @@ const mt5 = {
'stop-out-level': { key: () => localize('Stop out level'), value: () => localize('50%') },
'number-of-assets': { key: () => localize('Number of assets'), value: () => localize('150+') },
},
+ real_all_specs: {
+ leverage: { key: () => localize('Leverage'), value: () => localize('Up to 1:1000') },
+ 'margin-call': { key: () => localize('Margin call'), value: () => localize('100%') },
+ 'stop-out-level': { key: () => localize('Stop out level'), value: () => localize('50%') },
+ 'number-of-assets': { key: () => localize('Number of assets'), value: () => localize('40+') },
+ },
eu_real_financial_specs: {
leverage: { key: () => localize('Leverage'), value: () => localize('Up to 1:30') },
'margin-call': { key: () => localize('Margin call'), value: () => localize('100%') },
diff --git a/packages/cfd/src/Constants/jurisdiction-contents.ts b/packages/cfd/src/Constants/jurisdiction-contents.ts
index e47a5e95d456..b83e28e125ea 100644
--- a/packages/cfd/src/Constants/jurisdiction-contents.ts
+++ b/packages/cfd/src/Constants/jurisdiction-contents.ts
@@ -5,6 +5,7 @@ type TJurisdictionCardItems = {
over_header?: string;
synthetic_contents: Array;
financial_contents: Array;
+ swapfree_contents?: Array;
is_over_header_available: boolean;
};
type TJurisdictionContent = {
@@ -32,6 +33,13 @@ export const getJurisdictionContents = (): TJurisdictionContent => ({
)}`,
`${localize('Leverage up to 1:1000')}`,
],
+ swapfree_contents: [
+ `${localize('Selecting this will onboard you through Deriv (SVG) LLC (company no. 273 LLC 2020)')}`,
+ `${localize(
+ '40+ assets: forex, synthetics, stocks, stock indices, cryptocurrencies, and ETFs swap-free.'
+ )}`,
+ `${localize('Leverage up to 1:1000')}`,
+ ],
},
vanuatu: {
is_over_header_available: false,
diff --git a/packages/cfd/src/Containers/cfd-dashboard.tsx b/packages/cfd/src/Containers/cfd-dashboard.tsx
index f61777085162..bc2e24421588 100644
--- a/packages/cfd/src/Containers/cfd-dashboard.tsx
+++ b/packages/cfd/src/Containers/cfd-dashboard.tsx
@@ -30,11 +30,12 @@ import { general_messages } from '../Constants/cfd-shared-strings';
import SwitchToRealAccountModal from './switch-to-real-account';
import 'Sass/cfd-dashboard.scss';
import RootStore from '../Stores/index';
-import { DetailsOfEachMT5Loginid, LandingCompany, ResidenceList } from '@deriv/api-types';
+import { LandingCompany, ResidenceList, DetailsOfEachMT5Loginid } from '@deriv/api-types';
// TODO: Change these imports after real released
import CFDDxtradeDemoAccountDisplay from '../Components/cfd-dxtrade-demo-account-display';
import CFDMT5DemoAccountDisplay from '../Components/cfd-mt5-demo-account-display';
import { CFDRealAccountDisplay } from '../Components/cfd-real-account-display';
+import { TTradingPlatformAccounts } from 'Components/props.types';
declare module 'react' {
interface HTMLAttributes extends React.AriaAttributes, React.DOMAttributes {
@@ -310,18 +311,20 @@ const CFDDashboard = (props: TCFDDashboardProps) => {
};
const openAccountTransfer = (
- data: DetailsOfEachMT5Loginid & { account_id?: string; platform?: string },
- meta: { category: string; type?: string }
+ data: DetailsOfEachMT5Loginid | TTradingPlatformAccounts,
+ meta: TOpenAccountTransferMeta
) => {
if (meta.category === 'real') {
- if (data.platform === CFD_PLATFORMS.DXTRADE)
- sessionStorage.setItem('cfd_transfer_to_login_id', data.account_id as string);
- else sessionStorage.setItem('cfd_transfer_to_login_id', data.login as string);
-
- props.disableCFDPasswordModal();
- props.history.push(routes.cashier_acc_transfer);
+ if (data) {
+ if ('platform' in data && data.platform === CFD_PLATFORMS.DXTRADE)
+ sessionStorage.setItem('cfd_transfer_to_login_id', data.account_id || '');
+ else sessionStorage.setItem('cfd_transfer_to_login_id', data.login || '');
+
+ props.disableCFDPasswordModal();
+ props.history.push(routes.cashier_acc_transfer);
+ }
} else {
- props.setCurrentAccount(data, meta);
+ if ('sub_account_type' in data) props.setCurrentAccount(data, meta);
props.openTopUpModal();
}
};
@@ -402,6 +405,19 @@ const CFDDashboard = (props: TCFDDashboardProps) => {
);
};
+ const isSwapFreeCardVisible = () => {
+ const { platform, landing_companies, is_logged_in } = props;
+
+ return (
+ !is_logged_in ||
+ isLandingCompanyEnabled({
+ landing_companies,
+ platform,
+ type: 'all',
+ })
+ );
+ };
+
const {
account_status,
beginRealSignupForMt5,
@@ -646,6 +662,7 @@ const CFDDashboard = (props: TCFDDashboardProps) => {
is_loading={is_loading}
isSyntheticCardVisible={isSyntheticCardVisible}
isFinancialCardVisible={isFinancialCardVisible}
+ isSwapFreeCardVisible={isSwapFreeCardVisible}
current_list={current_list}
onSelectAccount={createCFDAccount}
landing_companies={landing_companies}
diff --git a/packages/cfd/src/Containers/cfd-password-modal.tsx b/packages/cfd/src/Containers/cfd-password-modal.tsx
index f019569dd3e4..6cf7acd3416e 100644
--- a/packages/cfd/src/Containers/cfd-password-modal.tsx
+++ b/packages/cfd/src/Containers/cfd-password-modal.tsx
@@ -4,7 +4,13 @@ import { RouteComponentProps, withRouter } from 'react-router';
import { SentEmailModal } from '@deriv/account';
import { DetailsOfEachMT5Loginid, GetAccountStatus, LandingCompany, Mt5NewAccount } from '@deriv/api-types';
import RootStore from '../Stores/index';
-import { getMtCompanies, getFormattedJurisdictionCode, TMtCompanies } from '../Stores/Modules/CFD/Helpers/cfd-config';
+import {
+ getDxCompanies,
+ getMtCompanies,
+ getFormattedJurisdictionCode,
+ TMtCompanies,
+ TDxCompanies,
+} from '../Stores/Modules/CFD/Helpers/cfd-config';
import {
FormSubmitButton,
Icon,
@@ -38,7 +44,7 @@ import TradingPlatformIcon from '../Assets/svgs/trading-platform';
export type TCFDPasswordFormValues = { password: string };
type TExtendedDetailsOfEachMT5Loginid = Omit & {
- market_type?: 'synthetic' | 'financial' | 'gaming';
+ market_type?: 'synthetic' | 'financial' | 'gaming' | 'all';
};
type TOnSubmitPassword = (values: TCFDPasswordFormValues, actions: FormikHelpers) => void;
@@ -147,6 +153,23 @@ type TCFDPasswordModalProps = RouteComponentProps & {
updateAccountStatus: () => void;
};
+const getAccountTitle = (
+ platform: string,
+ account_type: {
+ category?: string;
+ type?: string;
+ },
+ account_title: string
+) => {
+ if (platform === CFD_PLATFORMS.DXTRADE) {
+ return getDxCompanies()[account_type.category as keyof TDxCompanies][
+ account_type.type as keyof TDxCompanies['demo' | 'real']
+ ].short_title;
+ }
+
+ return account_title;
+};
+
const PasswordModalHeader = ({
should_set_trading_password,
is_password_reset_error,
@@ -203,6 +226,8 @@ const IconType = React.memo(({ platform, type, show_eu_related_content }: TIconT
switch (type) {
case 'synthetic':
return ;
+ case 'all':
+ return ;
case 'financial':
if (show_eu_related_content) {
return ;
@@ -215,6 +240,8 @@ const IconType = React.memo(({ platform, type, show_eu_related_content }: TIconT
switch (type) {
case 'synthetic':
return ;
+ case 'all':
+ return ;
case 'financial':
if (show_eu_related_content) {
return ;
@@ -529,7 +556,9 @@ const CFDPasswordForm = ({
values={{
platform: getCFDPlatformLabel(platform),
platform_name: platform === CFD_PLATFORMS.MT5 ? 'MT5' : 'Deriv X',
- account: !show_eu_related_content ? account_title : '',
+ account: !show_eu_related_content
+ ? getAccountTitle(platform, account_type, account_title)
+ : '',
jurisdiction_shortcode: showJuristiction(),
}}
/>
@@ -540,7 +569,7 @@ const CFDPasswordForm = ({
values={{
platform: getCFDPlatformLabel(platform),
platform_name: platform === CFD_PLATFORMS.MT5 ? 'MT5' : 'Deriv X',
- account: account_title,
+ account: getAccountTitle(platform, account_type, account_title),
}}
/>
)}
@@ -800,6 +829,8 @@ const CFDPasswordModal = ({
getMtCompanies(show_eu_related_content)[category as keyof TMtCompanies][
type as keyof TMtCompanies['demo' | 'real']
].short_title;
+ const deriv_x_type_label =
+ getDxCompanies()[category as keyof TDxCompanies][type as keyof TDxCompanies['demo' | 'real']].short_title;
const jurisdiction_label =
jurisdiction_selected_shortcode && getFormattedJurisdictionCode(jurisdiction_selected_shortcode);
const mt5_platform_label = jurisdiction_selected_shortcode !== 'maltainvest' ? 'MT5' : '';
@@ -811,7 +842,7 @@ const CFDPasswordModal = ({
i18n_default_text='Congratulations, you have successfully created your {{category}} <0>{{platform}}0> <1>{{type}} {{jurisdiction_selected_shortcode}}1> account. '
values={{
// TODO: remove below condition once deriv x changes are completed
- type: platform === 'dxtrade' && type_label === 'Derived' ? 'Synthetic' : type_label,
+ type: platform === CFD_PLATFORMS.DXTRADE ? deriv_x_type_label : type_label,
platform: platform === CFD_PLATFORMS.MT5 ? mt5_platform_label : 'Deriv X',
category: category_label,
jurisdiction_selected_shortcode:
@@ -834,9 +865,10 @@ const CFDPasswordModal = ({
return (
- {getHeadingTitle()}
+ {trade_modal_title}
{(mt5_trade_account as TTradingPlatformAccounts)?.display_login && (
diff --git a/packages/cfd/src/Containers/dmt5-trade-modal.tsx b/packages/cfd/src/Containers/dmt5-trade-modal.tsx
index 7f5c47e83920..6dc38fa4985d 100644
--- a/packages/cfd/src/Containers/dmt5-trade-modal.tsx
+++ b/packages/cfd/src/Containers/dmt5-trade-modal.tsx
@@ -17,7 +17,7 @@ import { getPlatformMt5DownloadLink, getMT5WebTerminalLink } from '../Helpers/co
import TradingPlatformIcon from '../Assets/svgs/trading-platform';
type TMT5TradeModalProps = {
- mt5_trade_account: Required;
+ mt5_trade_account: DetailsOfEachMT5Loginid;
show_eu_related_content: boolean;
onPasswordManager: (
arg1: string | undefined,
@@ -119,6 +119,7 @@ const DMT5TradeModal = ({
const getAccountTitle = () => {
if (show_eu_related_content) return 'CFDs';
else if (mt5_trade_account.market_type === 'synthetic') return 'Derived';
+ else if (mt5_trade_account.market_type === 'all') return 'SwapFree';
return 'Financial';
};
return (
@@ -173,8 +174,8 @@ const DMT5TradeModal = ({
});
onPasswordManager(
mt5_trade_account?.login,
- getTitle(mt5_trade_account.market_type, show_eu_related_content),
- mt5_trade_account.account_type,
+ getTitle(mt5_trade_account.market_type || '', show_eu_related_content),
+ mt5_trade_account.account_type || '',
account_type,
(mt5_trade_account as DetailsOfEachMT5Loginid)?.server
);
diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card-banner.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card-banner.tsx
index 0ddd4b06fc90..d604d63fe7eb 100644
--- a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card-banner.tsx
+++ b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card-banner.tsx
@@ -18,6 +18,7 @@ const VerificationStatusBanner = ({
should_restrict_vanuatu_account_creation,
real_synthetic_accounts_existing_data,
real_financial_accounts_existing_data,
+ real_swapfree_accounts_existing_data,
}: TVerificationStatusBannerProps) => {
const {
poi_not_submitted_for_vanuatu_maltainvest,
@@ -62,10 +63,22 @@ const VerificationStatusBanner = ({
}
};
- const isAccountCreated = () =>
- account_type === 'synthetic'
- ? real_synthetic_accounts_existing_data?.some(account => account.landing_company_short === type_of_card)
- : real_financial_accounts_existing_data?.some(account => account.landing_company_short === type_of_card);
+ const isAccountCreated = () => {
+ switch (account_type) {
+ case 'synthetic':
+ return real_synthetic_accounts_existing_data?.some(
+ account => account.landing_company_short === type_of_card
+ );
+ case 'all':
+ return real_swapfree_accounts_existing_data?.some(
+ account => account.landing_company_short === type_of_card
+ );
+ default:
+ return real_financial_accounts_existing_data?.some(
+ account => account.landing_company_short === type_of_card
+ );
+ }
+ };
if (disabled && isAccountCreated()) {
// account added
@@ -195,4 +208,5 @@ export default connect(({ modules: { cfd }, client }: RootStore) => ({
should_restrict_vanuatu_account_creation: client.should_restrict_vanuatu_account_creation,
real_financial_accounts_existing_data: cfd.real_financial_accounts_existing_data,
real_synthetic_accounts_existing_data: cfd.real_synthetic_accounts_existing_data,
+ real_swapfree_accounts_existing_data: cfd.real_swapfree_accounts_existing_data,
}))(JurisdictionCardBanner);
diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card.tsx
index bee3284893ce..955c0aaa1936 100644
--- a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card.tsx
+++ b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-card.tsx
@@ -14,20 +14,27 @@ const JurisdictionCard = ({
financial_available_accounts,
setJurisdictionSelectedShortcode,
synthetic_available_accounts,
+ swapfree_available_accounts,
type_of_card,
}: TJurisdictionCardProps) => {
const card_classname = `cfd-jurisdiction-card--${account_type}`;
const number_of_synthetic_accounts_to_be_shown = synthetic_available_accounts?.length;
const number_of_financial_accounts_to_be_shown = financial_available_accounts?.length;
+ const number_of_swapfree_accounts_to_be_shown = swapfree_available_accounts?.length;
const is_synthetic = account_type === 'synthetic';
+ const is_swapfree = account_type === 'all';
+ const non_synthetic_accounts = is_swapfree
+ ? number_of_swapfree_accounts_to_be_shown
+ : number_of_financial_accounts_to_be_shown;
const [number_of_cards] = React.useState(
- is_synthetic ? number_of_synthetic_accounts_to_be_shown : number_of_financial_accounts_to_be_shown
+ is_synthetic ? number_of_synthetic_accounts_to_be_shown : non_synthetic_accounts
);
const card_values = getJurisdictionContents()[type_of_card as TJurisdictionCardType];
- const card_data = is_synthetic ? card_values.synthetic_contents : card_values.financial_contents;
+ const non_synthetic_card_data = is_swapfree ? card_values.swapfree_contents : card_values.financial_contents;
+ const card_data = is_synthetic ? card_values.synthetic_contents : non_synthetic_card_data;
const cardSelection = (cardType: string) => {
setJurisdictionSelectedShortcode(jurisdiction_selected_shortcode === cardType ? '' : cardType);
@@ -57,7 +64,7 @@ const JurisdictionCard = ({
- {card_data.map((item, index) => (
+ {card_data?.map((item, index) => (
diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-content.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-content.tsx
index 800cfc63a5e9..d5b65a585d25 100644
--- a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-content.tsx
+++ b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-content.tsx
@@ -9,24 +9,42 @@ const JurisdictionModalContent = ({
setJurisdictionSelectedShortcode,
synthetic_available_accounts,
financial_available_accounts,
+ swapfree_available_accounts,
context,
real_synthetic_accounts_existing_data,
real_financial_accounts_existing_data,
+ real_swapfree_accounts_existing_data,
}: TJurisdictionModalContentProps) => {
const card_classname = `cfd-jurisdiction-card--${account_type}`;
- const cardsToBeShown = (type_of_card: string) =>
- account_type === 'synthetic'
- ? synthetic_available_accounts?.some(account => account.shortcode === type_of_card)
- : financial_available_accounts?.some(account => account.shortcode === type_of_card);
-
+ const cardsToBeShown = (type_of_card: string) => {
+ switch (account_type) {
+ case 'synthetic':
+ return synthetic_available_accounts?.some(account => account.shortcode === type_of_card);
+ case 'all':
+ return swapfree_available_accounts?.some(account => account.shortcode === type_of_card);
+ default:
+ return financial_available_accounts?.some(account => account.shortcode === type_of_card);
+ }
+ };
const disableCard = (type_of_card: string) => {
if (is_virtual && type_of_card !== 'svg') {
return true;
}
- return account_type === 'synthetic'
- ? real_synthetic_accounts_existing_data?.some(account => account.landing_company_short === type_of_card)
- : real_financial_accounts_existing_data?.some(account => account.landing_company_short === type_of_card);
+ switch (account_type) {
+ case 'synthetic':
+ return real_synthetic_accounts_existing_data?.some(
+ account => account.landing_company_short === type_of_card
+ );
+ case 'all':
+ return real_swapfree_accounts_existing_data?.some(
+ account => account.landing_company_short === type_of_card
+ );
+ default:
+ return real_financial_accounts_existing_data?.some(
+ account => account.landing_company_short === type_of_card
+ );
+ }
};
const jurisdiction_cards_array = ['svg', 'bvi', 'vanuatu', 'labuan', 'maltainvest'];
return (
@@ -43,6 +61,7 @@ const JurisdictionModalContent = ({
jurisdiction_selected_shortcode={jurisdiction_selected_shortcode}
synthetic_available_accounts={synthetic_available_accounts}
financial_available_accounts={financial_available_accounts}
+ swapfree_available_accounts={swapfree_available_accounts}
account_type={account_type}
setJurisdictionSelectedShortcode={setJurisdictionSelectedShortcode}
/>
diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-foot-note.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-foot-note.tsx
index a9f4ddec1090..ed67f6ba1f5e 100644
--- a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-foot-note.tsx
+++ b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal-foot-note.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { Text } from '@deriv/components';
import { Localize } from '@deriv/translations';
-import { getAuthenticationStatusInfo, isMobile } from '@deriv/shared';
+import { getAuthenticationStatusInfo, isMobile, getMT5Title } from '@deriv/shared';
import { TJurisdictionModalFootNoteProps } from '../props.types';
const FooterNote = ({
@@ -13,7 +13,7 @@ const FooterNote = ({
should_restrict_bvi_account_creation,
should_restrict_vanuatu_account_creation,
}: TJurisdictionModalFootNoteProps) => {
- const account_type_name = account_type === 'synthetic' ? 'Derived' : 'Financial';
+ const account_type_name = getMT5Title(account_type);
const { poa_pending } = getAuthenticationStatusInfo(account_status);
diff --git a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal.tsx b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal.tsx
index 60bf787fcf05..d290dfc2c4a9 100644
--- a/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal.tsx
+++ b/packages/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal.tsx
@@ -4,7 +4,7 @@ import { localize } from '@deriv/translations';
import { connect } from '../../Stores/connect';
import RootStore from '../../Stores/index';
import JurisdictionModalContent from './jurisdiction-modal-content';
-import { getAuthenticationStatusInfo, isMobile } from '@deriv/shared';
+import { getAuthenticationStatusInfo, isMobile, getMT5Title } from '@deriv/shared';
import { TJurisdictionModalProps } from '../props.types';
import JurisdictionCheckBox from './jurisdiction-modal-checkbox';
import JurisdictionModalFootNote from './jurisdiction-modal-foot-note';
@@ -21,6 +21,7 @@ const JurisdictionModal = ({
openPasswordModal,
real_synthetic_accounts_existing_data,
real_financial_accounts_existing_data,
+ real_swapfree_accounts_existing_data,
trading_platform_available_accounts,
toggleJurisdictionModal,
setJurisdictionSelectedShortcode,
@@ -76,10 +77,18 @@ const JurisdictionModal = ({
: available_account.shortcode !== 'maltainvest')
);
+ const swapfree_available_accounts = trading_platform_available_accounts.filter(
+ available_account =>
+ available_account.market_type === 'all' &&
+ (show_eu_related_content
+ ? available_account.shortcode === 'maltainvest'
+ : available_account.shortcode !== 'maltainvest')
+ );
+
const modal_title = show_eu_related_content
? localize('Jurisdiction for your Deriv MT5 CFDs account')
- : localize('Choose a jurisdiction for your MT5 {{account_type}} account', {
- account_type: account_type.type === 'synthetic' ? 'Derived' : 'Financial',
+ : localize('Choose a jurisdiction for your Deriv MT5 {{account_type}} account', {
+ account_type: getMT5Title(account_type.type),
});
const is_svg_selected = jurisdiction_selected_shortcode === 'svg';
@@ -90,14 +99,21 @@ const JurisdictionModal = ({
const isNextButtonDisabled = () => {
if (jurisdiction_selected_shortcode) {
- const is_account_created =
- account_type.type === 'synthetic'
- ? real_synthetic_accounts_existing_data?.some(
- account => account.landing_company_short === jurisdiction_selected_shortcode
- )
- : real_financial_accounts_existing_data?.some(
- account => account.landing_company_short === jurisdiction_selected_shortcode
- );
+ let is_account_created;
+
+ if (account_type.type === 'synthetic') {
+ is_account_created = real_synthetic_accounts_existing_data?.some(
+ account => account.landing_company_short === jurisdiction_selected_shortcode
+ );
+ } else if (account_type.type === 'all') {
+ is_account_created = real_swapfree_accounts_existing_data?.some(
+ account => account.landing_company_short === jurisdiction_selected_shortcode
+ );
+ } else {
+ is_account_created = real_financial_accounts_existing_data?.some(
+ account => account.landing_company_short === jurisdiction_selected_shortcode
+ );
+ }
if (!is_account_created) {
if (
@@ -168,10 +184,12 @@ const JurisdictionModal = ({
is_virtual={is_virtual}
real_financial_accounts_existing_data={real_financial_accounts_existing_data}
real_synthetic_accounts_existing_data={real_synthetic_accounts_existing_data}
+ real_swapfree_accounts_existing_data={real_swapfree_accounts_existing_data}
jurisdiction_selected_shortcode={jurisdiction_selected_shortcode}
context={context}
setJurisdictionSelectedShortcode={setJurisdictionSelectedShortcode}
synthetic_available_accounts={synthetic_available_accounts}
+ swapfree_available_accounts={swapfree_available_accounts}
/>
;
+ mt5_trade_account: Required<
+ DetailsOfEachMT5Loginid & { market_type?: TTradingPlatformAvailableAccount['market_type'] | 'synthetic' }
+ >;
is_eu_user: boolean;
is_open: boolean;
onPasswordManager: (
diff --git a/packages/cfd/src/Containers/props.types.ts b/packages/cfd/src/Containers/props.types.ts
index 37856780cca8..fc9de6cdb716 100644
--- a/packages/cfd/src/Containers/props.types.ts
+++ b/packages/cfd/src/Containers/props.types.ts
@@ -166,6 +166,7 @@ export type TJurisdictionCardProps = {
context: RootStore;
synthetic_available_accounts: TTradingPlatformAvailableAccount[];
financial_available_accounts: TTradingPlatformAvailableAccount[];
+ swapfree_available_accounts: TTradingPlatformAvailableAccount[];
setJurisdictionSelectedShortcode: (card_type: string) => void;
account_type: string;
type_of_card: string;
@@ -184,6 +185,7 @@ export type TVerificationStatusBannerProps = {
type_of_card: string;
real_synthetic_accounts_existing_data: TExistingData;
real_financial_accounts_existing_data: TExistingData;
+ real_swapfree_accounts_existing_data: TExistingData;
should_restrict_bvi_account_creation: boolean;
should_restrict_vanuatu_account_creation: boolean;
};
@@ -225,6 +227,7 @@ export type TJurisdictionModalProps = {
toggleCFDVerificationModal: () => void;
real_synthetic_accounts_existing_data: TExistingData;
real_financial_accounts_existing_data: TExistingData;
+ real_swapfree_accounts_existing_data: TExistingData;
updateMT5Status: () => void;
has_submitted_cfd_personal_details: boolean;
};
@@ -236,8 +239,10 @@ export type TJurisdictionModalContentProps = {
setJurisdictionSelectedShortcode: (card_type: string) => void;
synthetic_available_accounts: TTradingPlatformAvailableAccount[];
financial_available_accounts: TTradingPlatformAvailableAccount[];
+ swapfree_available_accounts: TTradingPlatformAvailableAccount[];
real_synthetic_accounts_existing_data: TExistingData;
real_financial_accounts_existing_data: TExistingData;
+ real_swapfree_accounts_existing_data: TExistingData;
is_virtual: boolean;
};
diff --git a/packages/cfd/src/Stores/Modules/CFD/Helpers/cfd-config.ts b/packages/cfd/src/Stores/Modules/CFD/Helpers/cfd-config.ts
index 0de741e45e0f..6498e216b23a 100644
--- a/packages/cfd/src/Stores/Modules/CFD/Helpers/cfd-config.ts
+++ b/packages/cfd/src/Stores/Modules/CFD/Helpers/cfd-config.ts
@@ -4,6 +4,11 @@ export type TDxCompanies = ReturnType;
export type TMtCompanies = ReturnType;
export const getDxCompanies = () => {
+ const all_config = {
+ account_type: '',
+ leverage: 500,
+ short_title: localize('CFDs'),
+ };
const synthetic_config = {
account_type: '',
leverage: 500,
@@ -16,6 +21,12 @@ export const getDxCompanies = () => {
};
return {
demo: {
+ all: {
+ dxtrade_account_type: all_config.account_type,
+ leverage: all_config.leverage,
+ title: localize('Demo'),
+ short_title: all_config.short_title,
+ },
synthetic: {
dxtrade_account_type: synthetic_config.account_type,
leverage: synthetic_config.leverage,
@@ -30,6 +41,18 @@ export const getDxCompanies = () => {
},
},
real: {
+ all: {
+ dxtrade_account_type: all_config.account_type,
+ leverage: all_config.leverage,
+ title: localize('Real'),
+ short_title: all_config.short_title,
+ },
+ dxtrade: {
+ mt5_account_type: all_config.account_type,
+ leverage: all_config.leverage,
+ title: localize('Real'),
+ short_title: all_config.short_title,
+ },
synthetic: {
dxtrade_account_type: synthetic_config.account_type,
leverage: synthetic_config.leverage,
@@ -50,8 +73,8 @@ export const getMtCompanies = (is_eu: boolean) => {
// TODO: Move this to the getDxCompanies for real release and when separating MT5 and DerivX components.
const all_config = {
account_type: '',
- leverage: 500,
- short_title: localize('CFDs'),
+ leverage: 100,
+ short_title: localize('Swap-Free'),
};
const synthetic_config = {
account_type: '',
@@ -74,7 +97,13 @@ export const getMtCompanies = (is_eu: boolean) => {
all: {
mt5_account_type: all_config.account_type,
leverage: all_config.leverage,
- title: localize('Demo'),
+ title: localize('Demo Swap-Free'),
+ short_title: all_config.short_title,
+ },
+ all_svg: {
+ mt5_account_type: all_config.account_type,
+ leverage: all_config.leverage,
+ title: localize('Demo Swap-Free SVG'),
short_title: all_config.short_title,
},
synthetic: {
@@ -113,7 +142,13 @@ export const getMtCompanies = (is_eu: boolean) => {
all: {
mt5_account_type: all_config.account_type,
leverage: all_config.leverage,
- title: localize('Real'),
+ title: localize('Swap-Free'),
+ short_title: all_config.short_title,
+ },
+ all_svg: {
+ mt5_account_type: all_config.account_type,
+ leverage: all_config.leverage,
+ title: localize('Swap-Free SVG'),
short_title: all_config.short_title,
},
dxtrade: {
diff --git a/packages/cfd/src/Stores/Modules/CFD/cfd-store.js b/packages/cfd/src/Stores/Modules/CFD/cfd-store.js
index 3a7e6e007c41..305500419575 100644
--- a/packages/cfd/src/Stores/Modules/CFD/cfd-store.js
+++ b/packages/cfd/src/Stores/Modules/CFD/cfd-store.js
@@ -37,6 +37,7 @@ export default class CFDStore extends BaseStore {
real_synthetic_accounts_existing_data = [];
real_financial_accounts_existing_data = [];
+ real_swapfree_accounts_existing_data = [];
constructor({ root_store }) {
super({ root_store });
@@ -94,6 +95,7 @@ export default class CFDStore extends BaseStore {
toggleCompareAccountsModal: action.bound,
getRealSyntheticAccountsExistingData: action.bound,
getRealFinancialAccountsExistingData: action.bound,
+ getRealSwapfreeAccountsExistingData: action.bound,
toggleJurisdictionModal: action.bound,
toggleMT5TradeModal: action.bound,
disableMt5FinancialStpModal: action.bound,
@@ -165,13 +167,20 @@ export default class CFDStore extends BaseStore {
return getDxCompanies();
}
get has_created_account_for_selected_jurisdiction() {
- return this.account_type.type === 'synthetic'
- ? this.real_synthetic_accounts_existing_data?.some(
- account => account.landing_company_short === this.jurisdiction_selected_shortcode
- )
- : this.real_financial_accounts_existing_data?.some(
- account => account.landing_company_short === this.jurisdiction_selected_shortcode
- );
+ switch (this.account_type.type) {
+ case 'synthetic':
+ return this.real_synthetic_accounts_existing_data?.some(
+ account => account.landing_company_short === this.jurisdiction_selected_shortcode
+ );
+ case 'all':
+ return this.real_swapfree_accounts_existing_data?.some(
+ account => account.landing_company_short === this.jurisdiction_selected_shortcode
+ );
+ default:
+ return this.real_financial_accounts_existing_data?.some(
+ account => account.landing_company_short === this.jurisdiction_selected_shortcode
+ );
+ }
}
onMount() {
@@ -278,6 +287,7 @@ export default class CFDStore extends BaseStore {
phone,
state: address_state,
zipCode: address_postcode,
+ ...(this.account_type.type === 'all' ? { sub_account_category: 'swap_free' } : {}),
...(values.server ? { server: values.server } : {}),
...(this.jurisdiction_selected_shortcode ? { company: this.jurisdiction_selected_shortcode } : {}),
...(this.jurisdiction_selected_shortcode !== 'labuan'
@@ -504,6 +514,10 @@ export default class CFDStore extends BaseStore {
this.real_financial_accounts_existing_data = real_financial_accounts_existing_data;
}
+ getRealSwapfreeAccountsExistingData(real_swapfree_accounts_existing_data) {
+ this.real_swapfree_accounts_existing_data = real_swapfree_accounts_existing_data;
+ }
+
toggleJurisdictionModal() {
this.is_jurisdiction_modal_visible = !this.is_jurisdiction_modal_visible;
}
diff --git a/packages/cfd/src/sass/cfd-dashboard.scss b/packages/cfd/src/sass/cfd-dashboard.scss
index 937250771fd5..e4f84d45e409 100644
--- a/packages/cfd/src/sass/cfd-dashboard.scss
+++ b/packages/cfd/src/sass/cfd-dashboard.scss
@@ -488,7 +488,8 @@
}
.cfd-jurisdiction-card--synthetic,
-.cfd-jurisdiction-card--financial {
+.cfd-jurisdiction-card--financial,
+.cfd-jurisdiction-card--all {
border: solid 1px var(--border-normal);
border-radius: 0.8rem;
display: flex;
diff --git a/packages/cfd/types.ts b/packages/cfd/types.ts
new file mode 100644
index 000000000000..6389dd6f436a
--- /dev/null
+++ b/packages/cfd/types.ts
@@ -0,0 +1,3 @@
+import type { TCoreStores } from '@deriv/stores/types';
+
+export type TTradingPlatformAvailableAccount = TCoreStores['client']['trading_platform_available_accounts'][number];
diff --git a/packages/components/src/components/icon/icons.js b/packages/components/src/components/icon/icons.js
index c51f50ca4e17..1869d85d25bd 100644
--- a/packages/components/src/components/icon/icons.js
+++ b/packages/components/src/components/icon/icons.js
@@ -645,6 +645,7 @@ import './mt5/ic-mt5-open-markets.svg';
import './mt5/ic-mt5-password-updated.svg';
import './mt5/ic-mt5-responsive.svg';
import './mt5/ic-mt5-support.svg';
+import './mt5/ic-mt5-swap-free-platform.svg';
import './mt5/ic-mt5-synthetic-dashboard.svg';
import './mt5/ic-mt5-synthetic-indices.svg';
import './mt5/ic-mt5-synthetic-platform.svg';
diff --git a/packages/components/src/components/icon/mt5/ic-mt5-swap-free-platform.svg b/packages/components/src/components/icon/mt5/ic-mt5-swap-free-platform.svg
new file mode 100644
index 000000000000..7b464b0951e6
--- /dev/null
+++ b/packages/components/src/components/icon/mt5/ic-mt5-swap-free-platform.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/packages/components/stories/icon/icons.js b/packages/components/stories/icon/icons.js
index 0424319c40e1..a809e59bc3a9 100644
--- a/packages/components/stories/icon/icons.js
+++ b/packages/components/stories/icon/icons.js
@@ -665,6 +665,7 @@ export const icons =
'IcMt5PasswordUpdated',
'IcMt5Responsive',
'IcMt5Support',
+ 'IcMt5SwapFreePlatform',
'IcMt5SyntheticDashboard',
'IcMt5SyntheticIndices',
'IcMt5SyntheticPlatform',
diff --git a/packages/core/src/Constants/cfd-text.js b/packages/core/src/Constants/cfd-text.js
index 361ae8c8d724..264d84db7f70 100644
--- a/packages/core/src/Constants/cfd-text.js
+++ b/packages/core/src/Constants/cfd-text.js
@@ -6,13 +6,18 @@ export const CFD_TEXT = {
mt5_cfds: () => localize('MT5 CFDs'),
cfd: () => localize('CFDs'),
synthetic: () => localize('Derived'),
+ synthetic_demo: () => localize('Derived Demo'),
synthetic_bvi: () => localize('Derived BVI'),
synthetic_svg: () => localize('Derived SVG'),
synthetic_v: () => localize('Derived Vanuatu'),
financial: () => localize('Financial'),
+ financial_demo: () => localize('Financial Demo'),
financial_bvi: () => localize('Financial BVI'),
financial_fx: () => localize('Financial Labuan'),
financial_v: () => localize('Financial Vanuatu'),
financial_svg: () => localize('Financial SVG'),
derivez: () => localize('Deriv EZ'),
+ all: () => localize('Swap-Free'),
+ all_demo: () => localize('Swap-Free Demo'),
+ all_svg: () => localize('Swap-Free SVG'),
};
diff --git a/packages/core/src/Stores/Helpers/client.js b/packages/core/src/Stores/Helpers/client.js
index 6bf8bfd76ab2..534d7a76c75c 100644
--- a/packages/core/src/Stores/Helpers/client.js
+++ b/packages/core/src/Stores/Helpers/client.js
@@ -34,6 +34,13 @@ export const getAccountTitle = loginid => {
return types_map[getClientAccountType(loginid)] || types_map.default;
};
+export const getAvailableAccount = market_type => {
+ if (market_type === 'all') {
+ return 'all';
+ }
+ return 'financial';
+};
+
export const getLandingCompanyValue = ({ loginid, landing_company, isAccountOfType }) => {
const key = 'changeable_fields';
let landing_company_object;
diff --git a/packages/core/src/Stores/client-store.js b/packages/core/src/Stores/client-store.js
index 8d5c69e4dd4b..79a8e18fb7fd 100644
--- a/packages/core/src/Stores/client-store.js
+++ b/packages/core/src/Stores/client-store.js
@@ -26,7 +26,7 @@ import {
} from '@deriv/shared';
import { WS, requestLogout } from 'Services';
import { action, computed, makeObservable, observable, reaction, runInAction, toJS, when } from 'mobx';
-import { getAccountTitle, getClientAccountType } from './Helpers/client';
+import { getAccountTitle, getClientAccountType, getAvailableAccount } from './Helpers/client';
import { getLanguage, localize } from '@deriv/translations';
import { getRegion, isEuCountry, isMultipliersOnly, isOptionsBlocked } from '_common/utility';
@@ -989,39 +989,50 @@ export default class ClientStore extends BaseStore {
}
};
- getIsMarketTypeMatching = (account, market_type) =>
- market_type === 'synthetic'
- ? account.market_type === market_type || account.market_type === 'gaming'
- : account.market_type === 'financial';
+ getIsMarketTypeMatching = (account, market_type) => {
+ if (market_type === 'synthetic') {
+ return account.market_type === market_type || account.market_type === 'gaming';
+ } else if (market_type === 'all') {
+ return account.market_type === 'all';
+ }
+ return account.market_type === 'financial';
+ };
isEligibleForMoreDemoMt5Svg(market_type) {
+ const is_synthetic = market_type === 'synthetic';
+ const available_account = getAvailableAccount(market_type);
const existing_demo_accounts = this.mt5_login_list.filter(
account => account.account_type === 'demo' && this.getIsMarketTypeMatching(account, market_type)
);
- return (
- this.trading_platform_available_accounts.some(
- account =>
- (market_type === 'synthetic' ? 'gaming' : 'financial') === account.market_type &&
- account.shortcode === 'svg'
- ) && existing_demo_accounts.every(account => !(account.landing_company_short === 'svg'))
- );
+ const has_matching_account = this.trading_platform_available_accounts.some(account => {
+ return (is_synthetic ? 'gaming' : available_account) === account.market_type && account.shortcode === 'svg';
+ });
+ const has_no_svg_account = existing_demo_accounts.every(account => {
+ return !(account.landing_company_short === 'svg');
+ });
+
+ return has_matching_account && has_no_svg_account;
}
isEligibleForMoreRealMt5(market_type) {
+ const is_synthetic = market_type === 'synthetic';
+ const available_account = getAvailableAccount(market_type);
const existing_real_accounts = this.mt5_login_list.filter(
account => account.account_type === 'real' && this.getIsMarketTypeMatching(account, market_type)
);
const available_real_accounts_shortcodes = this.trading_platform_available_accounts
.filter(
account =>
- (market_type === 'synthetic' ? 'gaming' : 'financial') === account.market_type &&
+ (is_synthetic ? 'gaming' : available_account) === account.market_type &&
account.shortcode !== 'maltainvest'
)
.map(account => account.shortcode);
- return !!available_real_accounts_shortcodes.filter(shortcode =>
- existing_real_accounts.every(account => account.landing_company_short !== shortcode)
- ).length;
+ const has_no_matching_accounts = available_real_accounts_shortcodes.every(shortcode =>
+ existing_real_accounts.some(account => account.landing_company_short !== shortcode)
+ );
+
+ return !has_no_matching_accounts;
}
isMT5Allowed = landing_companies => {
diff --git a/packages/core/src/Stores/traders-hub-store.js b/packages/core/src/Stores/traders-hub-store.js
index 463498940f38..e3afa1aad9c0 100644
--- a/packages/core/src/Stores/traders-hub-store.js
+++ b/packages/core/src/Stores/traders-hub-store.js
@@ -341,23 +341,37 @@ export default class TradersHubStore extends BaseStore {
}
getAvailableCFDAccounts() {
- const account_desc =
- !this.is_eu_user || this.is_demo_low_risk
+ const getAccountDesc = () => {
+ return !this.is_eu_user || this.is_demo_low_risk
? localize('Trade CFDs on MT5 with forex, stock indices, commodities, and cryptocurrencies.')
: localize(
'Trade CFDs on MT5 with forex, stocks, stock indices, synthetics, cryptocurrencies, and commodities.'
);
+ };
+ const getSwapFreeAccountDesc = () => {
+ return localize(
+ 'Trade swap-free CFDs on MT5 with synthetics, forex, stocks, stock indices, cryptocurrencies and ETFs.'
+ );
+ };
const all_available_accounts = [
...getCFDAvailableAccount(),
{
name: !this.is_eu_user || this.is_demo_low_risk ? localize('Financial') : localize('CFDs'),
- description: account_desc,
+ description: getAccountDesc(),
platform: CFD_PLATFORMS.MT5,
market_type: 'financial',
icon: !this.is_eu_user || this.is_demo_low_risk ? 'Financial' : 'CFDs',
availability: 'All',
},
+ {
+ name: !this.is_eu_user ? localize('Swap-Free') : '',
+ description: getSwapFreeAccountDesc(),
+ platform: CFD_PLATFORMS.MT5,
+ market_type: 'all',
+ icon: 'SwapFree',
+ availability: 'Non-EU',
+ },
];
this.available_cfd_accounts = all_available_accounts.map(account => {
return {
@@ -399,7 +413,10 @@ export default class TradersHubStore extends BaseStore {
if (this.CFDs_restricted_countries) {
this.available_mt5_accounts = this.available_cfd_accounts.filter(
- account => account.market_type !== 'financial' && account.platform === CFD_PLATFORMS.MT5
+ account =>
+ account.market_type !== 'financial' &&
+ account.market_type !== 'all' &&
+ account.platform === CFD_PLATFORMS.MT5
);
return;
}
@@ -445,6 +462,9 @@ export default class TradersHubStore extends BaseStore {
if (platform === CFD_PLATFORMS.MT5 && !this.is_eu_user && !maltainvest_account) {
return key.startsWith(`${platform}.${selected_account_type}.${market_type}`);
}
+ if (platform === CFD_PLATFORMS.MT5 && market_type === 'all') {
+ return key.startsWith(`${platform}.${selected_account_type}.${platform}@${market_type}`);
+ }
if (platform === CFD_PLATFORMS.DXTRADE && market_type === 'all') {
return key.startsWith(`${platform}.${selected_account_type}.${platform}@${market_type}`);
}
@@ -572,8 +592,11 @@ export default class TradersHubStore extends BaseStore {
this.is_real &&
!this.is_eu_user &&
(this.hasCFDAccount(CFD_PLATFORMS.MT5, 'real', 'synthetic') ||
- this.hasCFDAccount(CFD_PLATFORMS.MT5, 'real', 'financial')) &&
- (isEligibleForMoreRealMt5('synthetic') || isEligibleForMoreRealMt5('financial')) &&
+ this.hasCFDAccount(CFD_PLATFORMS.MT5, 'real', 'financial') ||
+ this.hasCFDAccount(CFD_PLATFORMS.MT5, 'real', 'all')) &&
+ (isEligibleForMoreRealMt5('synthetic') ||
+ isEligibleForMoreRealMt5('financial') ||
+ isEligibleForMoreRealMt5('all')) &&
!is_high_risk_client_for_mt5
);
}
diff --git a/packages/hooks/src/__tests__/useHasSwapFreeAccount.spec.tsx b/packages/hooks/src/__tests__/useHasSwapFreeAccount.spec.tsx
new file mode 100644
index 000000000000..f071c8f9d6b5
--- /dev/null
+++ b/packages/hooks/src/__tests__/useHasSwapFreeAccount.spec.tsx
@@ -0,0 +1,50 @@
+import * as React from 'react';
+import { StoreProvider, mockStore } from '@deriv/stores';
+import { renderHook } from '@testing-library/react-hooks';
+import useHasSwapFreeAccount from '../useHasSwapFreeAccount';
+
+describe('useHasSwapFreeAccount', () => {
+ test('should be true if it has a market type of all', async () => {
+ const mock = mockStore({
+ client: {
+ trading_platform_available_accounts: [{ market_type: 'all' }],
+ },
+ });
+
+ const wrapper = ({ children }: { children: JSX.Element }) => (
+ {children}
+ );
+ const { result } = renderHook(() => useHasSwapFreeAccount(), { wrapper });
+
+ expect(result.current).toBe(true);
+ });
+
+ test('should be false if it has a market type of financial', async () => {
+ const mock = mockStore({
+ client: {
+ trading_platform_available_accounts: [{ market_type: 'financial' }],
+ },
+ });
+
+ const wrapper = ({ children }: { children: JSX.Element }) => (
+ {children}
+ );
+ const { result } = renderHook(() => useHasSwapFreeAccount(), { wrapper });
+
+ expect(result.current).toBe(false);
+ });
+ test('should be false if has a market type of gaming ', async () => {
+ const mock = mockStore({
+ client: {
+ trading_platform_available_accounts: [{ market_type: 'gaming' }],
+ },
+ });
+
+ const wrapper = ({ children }: { children: JSX.Element }) => (
+ {children}
+ );
+ const { result } = renderHook(() => useHasSwapFreeAccount(), { wrapper });
+
+ expect(result.current).toBe(false);
+ });
+});
diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts
index 1a88d45c814a..ca9e6182e64d 100644
--- a/packages/hooks/src/index.ts
+++ b/packages/hooks/src/index.ts
@@ -12,6 +12,7 @@ export { default as useHasActiveRealAccount } from './useHasActiveRealAccount';
export { default as useHasFiatCurrency } from './useHasFiatCurrency';
export { default as useHasMaltaInvestAccount } from './useHasMaltaInvestAccount';
export { default as useHasSetCurrency } from './useHasSetCurrency';
+export { default as useHasSwapFreeAccount } from './useHasSwapFreeAccount';
export { default as useHasSvgAccount } from './useHasSvgAccount';
export { default as useHasUSDCurrency } from './useHasUSDCurrency';
export { default as useIsP2PEnabled } from './useIsP2PEnabled';
diff --git a/packages/hooks/src/useHasSwapFreeAccount.ts b/packages/hooks/src/useHasSwapFreeAccount.ts
new file mode 100644
index 000000000000..642bdd30e24d
--- /dev/null
+++ b/packages/hooks/src/useHasSwapFreeAccount.ts
@@ -0,0 +1,17 @@
+import { useStore } from '@deriv/stores';
+
+/**
+ * This hook is used to check if the client has a Swap-Free account.
+ * It checks for availability of market_type 'all' in trading_platform_available_accounts API response
+ */
+const useHasSwapFreeAccount = () => {
+ const { client } = useStore();
+ const { trading_platform_available_accounts } = client;
+ const has_swap_free_account = trading_platform_available_accounts.some(
+ available_account => available_account.market_type === 'all'
+ );
+
+ return has_swap_free_account;
+};
+
+export default useHasSwapFreeAccount;
diff --git a/packages/shared/src/utils/cfd/cfd.ts b/packages/shared/src/utils/cfd/cfd.ts
index 212943728176..f18ac1be205d 100644
--- a/packages/shared/src/utils/cfd/cfd.ts
+++ b/packages/shared/src/utils/cfd/cfd.ts
@@ -4,23 +4,37 @@ import { localize } from '@deriv/translations';
let CFD_text_translated: { [key: string]: () => void };
-// TODO: add swap_free to this file when ready
-const CFD_text: { [key: string]: string } = {
+export const CFD_text: { [key: string]: string } = {
dxtrade: 'Deriv X',
mt5: 'MT5',
mt5_cfds: 'MT5 CFDs',
cfd: 'CFDs',
synthetic: 'Derived',
+ synthetic_demo: 'Derived Demo',
synthetic_bvi: 'Derived BVI',
synthetic_svg: 'Derived SVG',
synthetic_v: 'Derived Vanuatu',
financial: 'Financial',
+ financial_demo: 'Financial Demo',
financial_bvi: 'Financial BVI',
financial_fx: 'Financial Labuan',
financial_v: 'Financial Vanuatu',
financial_svg: 'Financial SVG',
+ all: 'Swap-Free',
+ all_demo: 'Swap-Free Demo',
+ all_svg: 'Swap-Free SVG',
} as const;
+export const getMT5Title = (account_type: string) => {
+ if (account_type === 'synthetic') {
+ return CFD_text.synthetic;
+ }
+ if (account_type === 'all') {
+ return CFD_text.all;
+ }
+ return CFD_text.financial;
+};
+
type TPlatform = 'dxtrade' | 'mt5' | 'derivez';
type TMarketType = 'financial' | 'synthetic' | 'gaming' | 'all' | undefined;
type TShortcode = 'svg' | 'bvi' | 'labuan' | 'vanuatu';
@@ -38,9 +52,20 @@ type TGetCFDAccountKey = TGetAccount & {
// sub_account_type: "financial" | "financial_stp" | "swap_free"
// *
// sub_account_type financial_stp only happens in "financial" market_type
+// dxrade and swap_free both have market_type "all" so check for platform is neccessary
export const getCFDAccountKey = ({ market_type, sub_account_type, platform, shortcode }: TGetCFDAccountKey) => {
if (market_type === 'all') {
- return platform === CFD_PLATFORMS.DERIVEZ ? 'derivez' : 'dxtrade';
+ if (platform === CFD_PLATFORMS.MT5) {
+ // currently we are only supporting SVG for SwapFree
+ switch (shortcode) {
+ case 'svg':
+ return 'all_svg';
+ default:
+ return 'all_demo';
+ }
+ } else {
+ return platform === CFD_PLATFORMS.DERIVEZ ? 'derivez' : 'dxtrade';
+ }
}
if (market_type === 'gaming' || market_type === 'synthetic') {
@@ -53,7 +78,7 @@ export const getCFDAccountKey = ({ market_type, sub_account_type, platform, shor
case 'vanuatu':
return 'synthetic_v';
default:
- return 'synthetic';
+ return 'synthetic_demo';
}
}
}
@@ -73,7 +98,7 @@ export const getCFDAccountKey = ({ market_type, sub_account_type, platform, shor
case 'vanuatu':
return 'financial_v';
default:
- return 'financial';
+ return 'financial_demo';
}
}
}
@@ -90,7 +115,7 @@ export const getCFDAccountKey = ({ market_type, sub_account_type, platform, shor
type TGetAccountTypeFields = {
category: 'real' | 'demo';
- type: 'financial' | 'synthetic';
+ type: 'financial' | 'synthetic' | 'all';
};
type TAccountType = {
@@ -112,6 +137,9 @@ export const getAccountTypeFields = ({ category, type }: TGetAccountTypeFields)
account_type: 'financial',
mt5_account_type: 'financial',
},
+ all: {
+ account_type: 'all',
+ },
},
demo: {
synthetic: {
@@ -121,6 +149,9 @@ export const getAccountTypeFields = ({ category, type }: TGetAccountTypeFields)
account_type: 'demo',
mt5_account_type: 'financial',
},
+ all: {
+ account_type: 'demo',
+ },
},
};
diff --git a/packages/stores/src/mockStore.ts b/packages/stores/src/mockStore.ts
index 51bbf865470c..4e6d494e11a8 100644
--- a/packages/stores/src/mockStore.ts
+++ b/packages/stores/src/mockStore.ts
@@ -8,6 +8,7 @@ const mock = (): TStores & { is_mock: boolean } => {
account_settings: {},
accounts: {},
active_account_landing_company: '',
+ trading_platform_available_accounts: [],
account_limits: {
daily_transfers: {
dxtrade: {
diff --git a/packages/stores/types.ts b/packages/stores/types.ts
index 8a6536f136a3..be904a96ea23 100644
--- a/packages/stores/types.ts
+++ b/packages/stores/types.ts
@@ -51,6 +51,23 @@ type TActiveAccount = TAccount & {
is_virtual: number;
};
+type TTradingPlatformAvailableAccount = {
+ market_type: 'financial' | 'gaming' | 'all';
+ name: string;
+ requirements: {
+ after_first_deposit: {
+ financial_assessment: string[];
+ };
+ compliance: {
+ mt5: string[];
+ tax_information: string[];
+ };
+ signup: string[];
+ };
+ shortcode: 'bvi' | 'labuan' | 'svg' | 'vanuatu';
+ sub_account_type: string;
+};
+
type TAuthenticationStatus = { document_status: string; identity_status: string };
type TMenuItem = {
@@ -108,6 +125,7 @@ type TClientStore = {
accounts: { [k: string]: TActiveAccount };
active_accounts: TActiveAccount[];
active_account_landing_company: string;
+ trading_platform_available_accounts: TTradingPlatformAvailableAccount[];
account_limits: Partial & {
is_loading?: boolean;
api_initial_load_error?: string;