>) => {
const text_size = is_hint ? 'xxxs' : 'xxs';
return (
{/* We only show "Withdrawal Limits" on account-wide settings pages. */}
- {!is_app_settings && (
-
- )}
+ {!is_app_settings && }
{should_show_article && isDesktop && }
diff --git a/packages/account/src/Components/account-limits/withdrawal-limits-table.tsx b/packages/account/src/Components/account-limits/withdrawal-limits-table.tsx
index d25ca4eb36da..7b8d5b0157a5 100644
--- a/packages/account/src/Components/account-limits/withdrawal-limits-table.tsx
+++ b/packages/account/src/Components/account-limits/withdrawal-limits-table.tsx
@@ -1,85 +1,60 @@
import { Fragment } from 'react';
-import { Text } from '@deriv/components';
import { FormatUtils, CurrencyConstants } from '@deriv-com/utils';
import { Localize } from '@deriv/translations';
import { observer, useStore } from '@deriv/stores';
import AccountLimitsTableCell from './account-limits-table-cell';
import AccountLimitsTableHeader from './account-limits-table-header';
+import AccountLimitsExtraInfo from './account-limits-extra-info';
+import { useGetWithdrawalLimitsDetails } from '@deriv/hooks';
-type TWithdrawalLimitsTable = {
- num_of_days_limit?: string | number;
- withdrawal_since_inception_monetary?: string | number;
- remainder?: string | number;
-};
+const WithdrawalLimitsTable = observer(() => {
+ const { client } = useStore();
+ const { withdrawal_limit_details } = useGetWithdrawalLimitsDetails();
+ const { currency } = client;
-const WithdrawalLimitsTable = observer(
- ({ num_of_days_limit, withdrawal_since_inception_monetary, remainder }: TWithdrawalLimitsTable) => {
- const { client } = useStore();
- const { currency, is_fully_authenticated } = client;
- return (
-
-
-
-
-
-
-
- {is_fully_authenticated && (
-
-
-
- )}
-
-
-
- {!is_fully_authenticated && (
-
-
-
-
-
-
- {FormatUtils.formatMoney((num_of_days_limit as number) ?? 0, {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {withdrawal_limit_details.map((withdrawal_limit_detail, index) => (
+
+ (
+
+ )}
+ >
+ {withdrawal_limit_detail.withdrawal_title}
+
+
+ {FormatUtils.formatMoney(
+ (withdrawal_limit_detail.withdrawal_amount as number) ?? 0,
+ {
currency: currency as CurrencyConstants.Currency,
- })}
-
-
-
-
-
-
-
- {FormatUtils.formatMoney((withdrawal_since_inception_monetary as number) ?? 0, {
- currency: currency as CurrencyConstants.Currency,
- })}
-
-
-
-
-
-
-
- {FormatUtils.formatMoney((remainder as number) ?? 0, {
- currency: currency as CurrencyConstants.Currency,
- })}
-
-
-
- )}
-
-
-
-
- {is_fully_authenticated ? (
-
- ) : (
-
- )}
-
-
-
- );
- }
-);
+ }
+ )}
+
+
+ ))}
+
+
+
+
+ );
+});
export default WithdrawalLimitsTable;
diff --git a/packages/account/src/Components/poa/status/needs-review/__tests__/needs-review-spec.tsx b/packages/account/src/Components/poa/status/needs-review/__tests__/needs-review-spec.tsx
deleted file mode 100644
index 83c9c33e28f7..000000000000
--- a/packages/account/src/Components/poa/status/needs-review/__tests__/needs-review-spec.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import { render, screen } from '@testing-library/react';
-
-import { BrowserRouter } from 'react-router-dom';
-import { Button } from '@deriv/components';
-import { NeedsReview } from '../needs-review';
-import React from 'react';
-
-jest.mock('Components/poa/continue-trading-button/continue-trading-button', () => ({
- ContinueTradingButton: jest.fn(() => ContinueTradingButton
),
-}));
-
-const mock_redirection_btn = Redirection button ;
-
-describe(' ', () => {
- it('should render NeedsReview component if it does not need poi', () => {
- render(
-
-
-
- );
-
- expect(screen.getByText('Your proof of address was submitted successfully')).toBeInTheDocument();
- expect(screen.getByText('Your document is being reviewed, please check back in 1-3 days.')).toBeInTheDocument();
- expect(screen.getByText('ContinueTradingButton')).toBeInTheDocument();
- });
-
- it('should render NeedsReview component if it does not need poi and is_description_enabled', () => {
- render(
-
-
-
- );
-
- expect(screen.getByText('Your proof of address was submitted successfully')).toBeInTheDocument();
- expect(screen.getByText('Your document is being reviewed, please check back in 1-3 days.')).toBeInTheDocument();
- expect(screen.queryByText('ContinueTradingButton')).not.toBeInTheDocument();
- expect(screen.getByRole('button')).toBeInTheDocument();
- });
-
- it('should render NeedsReview component if it needs poi', () => {
- render(
-
-
-
- );
-
- expect(screen.getByText('Your proof of address was submitted successfully')).toBeInTheDocument();
- expect(screen.getByText('Your document is being reviewed, please check back in 1-3 days.')).toBeInTheDocument();
- expect(screen.getByText('You must also submit a proof of identity.')).toBeInTheDocument();
- });
-});
diff --git a/packages/account/src/Components/poa/status/needs-review/index.ts b/packages/account/src/Components/poa/status/needs-review/index.ts
deleted file mode 100644
index d3c9442101b5..000000000000
--- a/packages/account/src/Components/poa/status/needs-review/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import { NeedsReview as PoaNeedsReview } from './needs-review';
-
-export default PoaNeedsReview;
diff --git a/packages/account/src/Components/poa/status/needs-review/needs-review.tsx b/packages/account/src/Components/poa/status/needs-review/needs-review.tsx
deleted file mode 100644
index c29d2d77019c..000000000000
--- a/packages/account/src/Components/poa/status/needs-review/needs-review.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-import React from 'react';
-import { Icon, Text } from '@deriv/components';
-import { isNavigationFromP2P, isNavigationFromDerivGO } from '@deriv/shared';
-import { localize } from '@deriv/translations';
-import ContinueTradingButton from '../../continue-trading-button';
-import IconMessageContent from '../../../icon-message-content';
-import PoiButton from '../../../poi/poi-button';
-import { TPoaStatusProps } from '../../../../Types';
-
-export const NeedsReview = ({ needs_poi, redirect_button }: TPoaStatusProps) => {
- const message = localize('Your proof of address was submitted successfully');
- const is_redirected_from_platform = isNavigationFromP2P() || isNavigationFromDerivGO();
- if (!needs_poi) {
- return (
- }
- >
- {redirect_button || (!is_redirected_from_platform && )}
-
- );
- }
- return (
- }>
-
-
- {localize('Your document is being reviewed, please check back in 1-3 days.')}
-
-
- {localize('You must also submit a proof of identity.')}
-
-
-
-
- );
-};
diff --git a/packages/account/src/Components/poa/status/submitted/__tests__/submitted.spec.tsx b/packages/account/src/Components/poa/status/submitted/__tests__/submitted.spec.tsx
index 193f59793311..be5fa726a9dd 100644
--- a/packages/account/src/Components/poa/status/submitted/__tests__/submitted.spec.tsx
+++ b/packages/account/src/Components/poa/status/submitted/__tests__/submitted.spec.tsx
@@ -14,23 +14,23 @@ describe(' ', () => {
it('should render the Submitted component', () => {
renderWithRouter( );
- expect(screen.getByText('Your documents were submitted successfully')).toBeInTheDocument();
+ expect(screen.getByText('Review in progress')).toBeInTheDocument();
});
it('should show submit_poi message if needs_poi is true', () => {
renderWithRouter( );
- expect(screen.getByText('You must also submit a proof of identity.')).toBeInTheDocument();
+ expect(screen.getByText('To start trading, you also need to verify your identity.')).toBeInTheDocument();
});
it('should show review message if needs_poi is true', () => {
renderWithRouter( );
expect(
- screen.getByText('We’ll review your documents and notify you of its status within 1 to 3 days.')
+ screen.getByText('Your proof of address is under review. We’ll get back to you in 1–3 working days.')
).toBeInTheDocument();
});
it('should show ContinueTradingButton if no props are passed', () => {
renderWithRouter( );
- expect(screen.getByTestId('continue-trading-button')).toBeInTheDocument();
+ expect(screen.getByText("Return to Trader's Hub")).toBeInTheDocument();
});
});
diff --git a/packages/account/src/Components/poa/status/submitted/submitted.tsx b/packages/account/src/Components/poa/status/submitted/submitted.tsx
index 24d3d187b0aa..0c7ffbf61825 100644
--- a/packages/account/src/Components/poa/status/submitted/submitted.tsx
+++ b/packages/account/src/Components/poa/status/submitted/submitted.tsx
@@ -1,14 +1,13 @@
import React from 'react';
import { Icon, Text } from '@deriv/components';
import { localize } from '@deriv/translations';
-import { isNavigationFromP2P, isNavigationFromDerivGO } from '@deriv/shared';
-import ContinueTradingButton from '../../continue-trading-button';
+import { isNavigationFromP2P, isNavigationFromDerivGO, routes } from '@deriv/shared';
import IconMessageContent from '../../../icon-message-content';
-import PoiButton from '../../../poi/poi-button';
+import RouteButton from '../../../route-button';
import { TPoaStatusProps } from '../../../../Types';
export const Submitted = ({ needs_poi, redirect_button }: TPoaStatusProps) => {
- const message = localize('Your documents were submitted successfully');
+ const message = localize('Review in progress');
const is_redirected_from_platform = isNavigationFromP2P() || isNavigationFromDerivGO();
if (needs_poi) {
return (
@@ -16,13 +15,15 @@ export const Submitted = ({ needs_poi, redirect_button }: TPoaStatusProps) => {
}>
- {localize('We’ll review your documents and notify you of its status within 1 to 3 days.')}
+ {localize(
+ 'Your proof of address is under review. We’ll get back to you in 1–3 working days.'
+ )}
- {localize('You must also submit a proof of identity.')}
+ {localize('To start trading, you also need to verify your identity.')}
-
+
);
@@ -31,10 +32,13 @@ export const Submitted = ({ needs_poi, redirect_button }: TPoaStatusProps) => {
}
>
- {redirect_button || (!is_redirected_from_platform && )}
+ {redirect_button ||
+ (!is_redirected_from_platform && (
+
+ ))}
);
diff --git a/packages/account/src/Components/poi-poa-docs-submitted/poi-poa-docs-submitted.tsx b/packages/account/src/Components/poi-poa-docs-submitted/poi-poa-docs-submitted.tsx
deleted file mode 100644
index 32dcdbf868b8..000000000000
--- a/packages/account/src/Components/poi-poa-docs-submitted/poi-poa-docs-submitted.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import React from 'react';
-import { Button, Icon, Loading } from '@deriv/components';
-import { localize } from '@deriv/translations';
-import { getAuthenticationStatusInfo, Jurisdiction } from '@deriv/shared';
-import IconMessageContent from 'Components/icon-message-content';
-import { GetAccountStatus } from '@deriv/api-types';
-
-type TPoiPoaDocsSubmitted = {
- account_status: GetAccountStatus;
- onClickOK: () => void;
- jurisdiction_selected_shortcode: string;
- has_created_account_for_selected_jurisdiction: boolean;
- openPasswordModal: () => void;
- updateAccountStatus: () => Promise;
-};
-
-const PoiPoaDocsSubmitted = ({
- account_status,
- jurisdiction_selected_shortcode,
- onClickOK,
- updateAccountStatus,
- has_created_account_for_selected_jurisdiction,
- openPasswordModal,
-}: TPoiPoaDocsSubmitted) => {
- const [is_loading, setIsLoading] = React.useState(false);
-
- React.useEffect(() => {
- const fetchAccountStatus = async () => {
- await updateAccountStatus();
- setIsLoading(false);
- };
- setIsLoading(true);
- fetchAccountStatus();
-
- return () => setIsLoading(false);
- }, [updateAccountStatus]);
-
- const onSubmit = () => {
- onClickOK();
- if (!has_created_account_for_selected_jurisdiction) {
- openPasswordModal();
- }
- };
-
- const getDescription = () => {
- const { manual_status, poi_verified_for_maltainvest, poi_verified_for_bvi_labuan_vanuatu, poa_pending } =
- getAuthenticationStatusInfo(account_status);
- const is_maltainvest_selected = jurisdiction_selected_shortcode === Jurisdiction.MALTA_INVEST;
- if (
- (is_maltainvest_selected && poi_verified_for_maltainvest && poa_pending) ||
- (!is_maltainvest_selected && poi_verified_for_bvi_labuan_vanuatu && poa_pending) ||
- manual_status === 'pending'
- ) {
- return localize('We’ll review your documents and notify you of its status within 1 - 3 working days.');
- }
- return localize('We’ll review your documents and notify you of its status within 5 minutes.');
- };
-
- return is_loading ? (
-
- ) : (
- }
- className='poi-poa-submitted'
- >
-
-
- );
-};
-
-export default PoiPoaDocsSubmitted;
diff --git a/packages/account/src/Components/poi/idv-status/idv-submit-complete/__tests__/idv-submit-complete.spec.tsx b/packages/account/src/Components/poi/idv-status/idv-submit-complete/__tests__/idv-submit-complete.spec.tsx
index d7a7b4f26636..7b7f9c3798e5 100644
--- a/packages/account/src/Components/poi/idv-status/idv-submit-complete/__tests__/idv-submit-complete.spec.tsx
+++ b/packages/account/src/Components/poi/idv-status/idv-submit-complete/__tests__/idv-submit-complete.spec.tsx
@@ -51,18 +51,12 @@ describe(' ', () => {
expect(screen.getByText('DerivLightWaitingPoiIcon')).toBeInTheDocument();
expect(screen.getByText('Mock Redirect Button')).toBeInTheDocument();
- expect(screen.getByText('Your documents were submitted successfully')).toBeInTheDocument();
- expect(
- screen.getByText('We’ll review your documents and notify you of its status within 5 minutes.')
- ).toBeInTheDocument();
expect(screen.queryByText('Your profile is updated')).not.toBeInTheDocument();
- expect(screen.queryByText('Your document has been submitted')).not.toBeInTheDocument();
+ expect(screen.queryByText('Review in progress')).toBeInTheDocument();
expect(
- screen.queryByText(
- "We'll review your proof of identity again and will give you an update as soon as possible."
- )
- ).not.toBeInTheDocument();
- expect(screen.queryByText("Next, we'll need your proof of address.")).not.toBeInTheDocument();
+ screen.queryByText('Your proof of identity is under review. We’ll get back to you within 5 minutes.')
+ ).toBeInTheDocument();
+ expect(screen.queryByText('To start trading, you also need to verify your address.')).not.toBeInTheDocument();
});
it('should render IdvSubmitComplete component needs_poa not external, without mismatch_status and redirect_button', () => {
@@ -74,16 +68,12 @@ describe(' ', () => {
renderComponent({ props: new_props });
expect(screen.getByText('DerivLightWaitingPoiIcon')).toBeInTheDocument();
- expect(screen.getByText('Your documents were submitted successfully')).toBeInTheDocument();
- expect(screen.getByText('Submit proof of address')).toBeInTheDocument();
- expect(screen.getByText("Next, we'll need your proof of address.")).toBeInTheDocument();
- expect(screen.queryByText('Your profile is updated')).not.toBeInTheDocument();
- expect(screen.queryByText('Your document has been submitted')).not.toBeInTheDocument();
+ expect(screen.queryByText('Review in progress')).toBeInTheDocument();
expect(
- screen.queryByText(
- "We'll review your proof of identity again and will give you an update as soon as possible."
- )
- ).not.toBeInTheDocument();
+ screen.queryByText('Your proof of identity is under review. We’ll get back to you within 5 minutes.')
+ ).toBeInTheDocument();
+ expect(screen.queryByText('To start trading, you also need to verify your address.')).toBeInTheDocument();
+ expect(screen.queryByText('Next')).toBeInTheDocument();
});
it('should render IdvSubmitComplete component with mismatch_status ', () => {
diff --git a/packages/account/src/Components/poi/idv-status/idv-submit-complete/idv-submit-complete.tsx b/packages/account/src/Components/poi/idv-status/idv-submit-complete/idv-submit-complete.tsx
index 5cc345bd25b0..27e0ae95fe0a 100644
--- a/packages/account/src/Components/poi/idv-status/idv-submit-complete/idv-submit-complete.tsx
+++ b/packages/account/src/Components/poi/idv-status/idv-submit-complete/idv-submit-complete.tsx
@@ -33,7 +33,7 @@ const IdvSubmitComplete = observer(
if (is_expired_or_failed_error)
return ;
}
- return ;
+ return ;
};
const getDescriptionText = () => {
@@ -42,13 +42,11 @@ const IdvSubmitComplete = observer(
);
return (
-
+
);
};
- const poa_button = !is_from_external && (
- } />
- );
+ const poa_button = !is_from_external && } />;
return (
@@ -62,7 +60,7 @@ const IdvSubmitComplete = observer(
{needs_poa ? (
-
+
{poa_button}
diff --git a/packages/account/src/Components/poi/status/unsupported/detail-component.tsx b/packages/account/src/Components/poi/status/unsupported/detail-component.tsx
index 4afada56eb79..69956726df81 100644
--- a/packages/account/src/Components/poi/status/unsupported/detail-component.tsx
+++ b/packages/account/src/Components/poi/status/unsupported/detail-component.tsx
@@ -31,6 +31,7 @@ type TDetailComponent = {
is_from_external?: boolean;
is_for_mt5?: boolean;
handlePOIforMT5Complete?: () => void;
+ needs_poa?: boolean;
};
const DetailComponent = ({
@@ -44,6 +45,7 @@ const DetailComponent = ({
is_from_external,
is_for_mt5,
handlePOIforMT5Complete,
+ needs_poa,
...props
}: TDetailComponent) => {
const [status, setStatus] = React.useState('');
@@ -121,7 +123,7 @@ const DetailComponent = ({
case STATUS.IS_UPLOADING:
return
;
case STATUS.IS_COMPLETED:
- return
;
+ return
;
case STATUS.IS_FAILED:
return
;
case STATUS.IS_DUPLICATE_UPLOAD:
diff --git a/packages/account/src/Components/poi/status/unsupported/unsupported.tsx b/packages/account/src/Components/poi/status/unsupported/unsupported.tsx
index e9cf976e8bf8..5a1bee49c3f2 100644
--- a/packages/account/src/Components/poi/status/unsupported/unsupported.tsx
+++ b/packages/account/src/Components/poi/status/unsupported/unsupported.tsx
@@ -93,6 +93,7 @@ const Unsupported = ({
handlePOIforMT5Complete={handlePOIforMT5Complete}
handleComplete={handleViewComplete}
is_for_mt5={is_for_mt5}
+ needs_poa={needs_poa}
{...props}
/>
);
diff --git a/packages/account/src/Components/poi/status/upload-complete/__tests__/upload-complete.spec.tsx b/packages/account/src/Components/poi/status/upload-complete/__tests__/upload-complete.spec.tsx
index 02a130dcf170..068437f73b3d 100644
--- a/packages/account/src/Components/poi/status/upload-complete/__tests__/upload-complete.spec.tsx
+++ b/packages/account/src/Components/poi/status/upload-complete/__tests__/upload-complete.spec.tsx
@@ -4,7 +4,7 @@ import { Button } from '@deriv/components';
import { UploadComplete } from '../upload-complete';
import { BrowserRouter } from 'react-router-dom';
-jest.mock('../../../../poa/poa-button', () => jest.fn(() =>
));
+jest.mock('../../../../poa/poa-button', () => jest.fn(() =>
Next
));
jest.mock('@deriv/components', () => {
const original_module = jest.requireActual('@deriv/components');
@@ -15,59 +15,57 @@ jest.mock('@deriv/components', () => {
});
describe('
', () => {
- const successful_upload_message = /your documents were submitted successfully/i;
- const poi_under_review_message = /We’ll review your documents and notify you of its status within 5 minutes./i;
+ const successful_upload_message = /Review in progress/i;
+ const poi_under_review_message =
+ /Your proof of identity is under review\. We’ll get back to you within 5 minutes./i;
const poi_under_review_message_for_manual =
- /We’ll review your documents and notify you of its status within 1 - 3 working days./i;
+ /Your proof of identity is under review\. We’ll get back to you within 1–3 working days\./i;
const redirect_button =
Lorem Ipsom ;
- const needs_poa_extra_submit_message = /you must also submit a proof of address./i;
+ const needs_poa_extra_submit_message = /To start trading, you also need to verify your address./i;
const renderWithRouter = (component: React.ReactElement) => render(
{component} );
it('should render
component for manual upload', () => {
renderWithRouter(
);
-
expect(screen.getByText(successful_upload_message)).toBeInTheDocument();
expect(screen.getByText(poi_under_review_message_for_manual)).toBeInTheDocument();
expect(screen.getByTestId(/dt_mocked_icon/i)).toBeInTheDocument();
expect(screen.queryByRole('button')).not.toBeInTheDocument();
});
- it('should render
component for manual upload', () => {
- renderWithRouter(
);
+ it('should render
component for idv and onfido upload', () => {
+ renderWithRouter(
);
expect(screen.getByText(successful_upload_message)).toBeInTheDocument();
- expect(screen.getByText(poi_under_review_message_for_manual)).toBeInTheDocument();
+ expect(screen.getByText(poi_under_review_message)).toBeInTheDocument();
expect(screen.getByTestId(/dt_mocked_icon/i)).toBeInTheDocument();
expect(screen.queryByRole('button')).not.toBeInTheDocument();
});
it('should not show redirect_button if it redirect_button passed and is_from_external is true, but needs_poa is false', () => {
renderWithRouter(
);
-
expect(screen.queryByRole('button')).not.toBeInTheDocument();
});
it('should show redirect button if needs_poa and is_from_external are false and have redirect button', () => {
renderWithRouter(
);
- expect(screen.getByRole('button')).toBeInTheDocument();
+ expect(screen.getByText(`Return to Trader's Hub`)).toBeInTheDocument();
});
it('should show needs_poa review message and extra submission message, and poa_buttons', () => {
renderWithRouter(
);
- expect(screen.getByTestId('dt_poa_button')).toBeInTheDocument();
expect(screen.getByText(poi_under_review_message)).toBeInTheDocument();
expect(screen.getByText(needs_poa_extra_submit_message)).toBeInTheDocument();
expect(screen.getByRole('button')).toBeInTheDocument();
+ expect(screen.getByRole('button')).toHaveTextContent('Lorem Ipsom');
});
it('should show needs_poa review message and extra submission message, and poa_buttons but redirect_button will not display', () => {
renderWithRouter(
);
- expect(screen.getByTestId('dt_poa_button')).toBeInTheDocument();
expect(screen.getByText(poi_under_review_message)).toBeInTheDocument();
expect(screen.getByText(needs_poa_extra_submit_message)).toBeInTheDocument();
- expect(screen.queryByRole('button')).not.toBeInTheDocument();
+ expect(screen.getByText('Next')).toBeInTheDocument();
});
});
diff --git a/packages/account/src/Components/poi/status/upload-complete/upload-complete.tsx b/packages/account/src/Components/poi/status/upload-complete/upload-complete.tsx
index e0ed002c5e78..d036e80cf890 100644
--- a/packages/account/src/Components/poi/status/upload-complete/upload-complete.tsx
+++ b/packages/account/src/Components/poi/status/upload-complete/upload-complete.tsx
@@ -1,9 +1,9 @@
import React from 'react';
import { Icon, Text } from '@deriv/components';
-import { isNavigationFromP2P, isNavigationFromDerivGO } from '@deriv/shared';
-import { localize } from '@deriv/translations';
+import { routes } from '@deriv/shared';
+import { useTranslations } from '@deriv-com/translations';
+import RouteButton from '../../../route-button';
import PoaButton from '../../../poa/poa-button';
-import { ContinueTradingButton } from '../../../poa/continue-trading-button/continue-trading-button';
import IconMessageContent from '../../../icon-message-content/icon-message-content';
import { TPOIStatus } from 'Types';
@@ -13,17 +13,18 @@ export const UploadComplete = ({
is_from_external,
is_manual_upload = false,
}: TPOIStatus) => {
- const message = localize('Your documents were submitted successfully');
+ const { localize } = useTranslations();
+ const message = localize('Review in progress');
const description = is_manual_upload
- ? localize('We’ll review your documents and notify you of its status within 1 - 3 working days.')
- : localize('We’ll review your documents and notify you of its status within 5 minutes.');
-
- const is_redirected_from_platform = isNavigationFromP2P() || isNavigationFromDerivGO();
+ ? localize('Your proof of identity is under review. We’ll get back to you within 1–3 working days.')
+ : localize('Your proof of identity is under review. We’ll get back to you within 5 minutes.');
if (!needs_poa) {
return (
}>
- {!is_from_external && (redirect_button || (!is_redirected_from_platform &&
))}
+ {!is_from_external && (
+
+ )}
);
}
@@ -35,10 +36,10 @@ export const UploadComplete = ({
{description}
- {localize('You must also submit a proof of address.')}
+ {localize('To start trading, you also need to verify your address.')}
-
+
{!is_from_external && redirect_button}
diff --git a/packages/account/src/Components/route-button/__tests__/route-button.spec.tsx b/packages/account/src/Components/route-button/__tests__/route-button.spec.tsx
new file mode 100644
index 000000000000..2327a4502171
--- /dev/null
+++ b/packages/account/src/Components/route-button/__tests__/route-button.spec.tsx
@@ -0,0 +1,31 @@
+import React from 'react';
+import { createBrowserHistory } from 'history';
+import { Router } from 'react-router';
+import { render, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import { routes } from '@deriv/shared';
+import { RouteButton } from '../route-button';
+
+describe(' ', () => {
+ const history = createBrowserHistory();
+ const renderWithRouter = (component: React.ReactElement) => {
+ return render({component} );
+ };
+
+ it('should render RouteButton component', () => {
+ renderWithRouter( );
+ screen.getByRole('link', {
+ name: 'Test Route Button',
+ });
+ expect(screen.getByText('Test Route Button')).toBeInTheDocument();
+ });
+
+ it('should navigate to route on clicking the text', () => {
+ renderWithRouter( );
+ const route_btn_text = screen.getByRole('link', {
+ name: 'Test Route Button',
+ });
+ userEvent.click(route_btn_text);
+ expect(history.location.pathname).toBe(routes.traders_hub);
+ });
+});
diff --git a/packages/account/src/Components/route-button/index.ts b/packages/account/src/Components/route-button/index.ts
new file mode 100644
index 000000000000..1e15db9c2c50
--- /dev/null
+++ b/packages/account/src/Components/route-button/index.ts
@@ -0,0 +1,3 @@
+import { RouteButton } from './route-button';
+
+export default RouteButton;
diff --git a/packages/account/src/Components/route-button/route-button.tsx b/packages/account/src/Components/route-button/route-button.tsx
new file mode 100644
index 000000000000..f71e808cd1ad
--- /dev/null
+++ b/packages/account/src/Components/route-button/route-button.tsx
@@ -0,0 +1,20 @@
+import clsx from 'clsx';
+import { ButtonLink, Text } from '@deriv/components';
+
+type TRouteButtonProps = { route: string; button_label: string; className?: string };
+
+/**
+ * Renders a button that redirects to the trading platform
+ * @name RouteButton
+ * @param route - Route to redirect to
+ * @param button_label - Text to be displayed on the button
+ * @param className - Styles to be applied to the button
+ * @returns React Element
+ */
+export const RouteButton = ({ button_label, className, route }: TRouteButtonProps) => (
+
+
+ {button_label}
+
+
+);
diff --git a/packages/account/src/Configs/__test__/get-status-badge-config.spec.tsx b/packages/account/src/Configs/__test__/get-status-badge-config.spec.tsx
index 64c6e7f6b770..6d857a07de92 100644
--- a/packages/account/src/Configs/__test__/get-status-badge-config.spec.tsx
+++ b/packages/account/src/Configs/__test__/get-status-badge-config.spec.tsx
@@ -1,31 +1,15 @@
import React from 'react';
import { BrowserRouter } from 'react-router-dom';
-import { fireEvent, render, screen } from '@testing-library/react';
+import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
-import getStatusBadgeConfig from 'Configs/get-status-badge-config';
-import { AUTH_STATUS_CODES, MT5_ACCOUNT_STATUS, routes } from '@deriv/shared';
-import { TMT5AccountStatus } from 'Types';
+import getStatusBadgeConfig from '../get-status-badge-config';
+import { ACCOUNT_BADGE_STATUS, TAccountBadgeStatus } from '@deriv/shared';
describe('getStatusBadgeConfig', () => {
- let account_status: TMT5AccountStatus;
- const openFailedVerificationModal = jest.fn();
- const setIsVerificationModalVisible = jest.fn();
- const selected_account_type = {};
+ let account_status: TAccountBadgeStatus;
- const renderCheck = (
- account_status: Parameters[0],
- openFailedVerificationModal: Parameters[1],
- selected_account_type: Parameters[2],
- setIsVerificationModalVisible?: Parameters[3],
- user_account_status?: Parameters[4]
- ) => {
- const badge = getStatusBadgeConfig(
- account_status,
- openFailedVerificationModal,
- selected_account_type,
- setIsVerificationModalVisible,
- user_account_status
- );
+ const renderCheck = (account_status: Parameters[0]) => {
+ const badge = getStatusBadgeConfig(account_status);
render(
{badge.text}
@@ -35,92 +19,35 @@ describe('getStatusBadgeConfig', () => {
};
it('should render pending status', () => {
- account_status = MT5_ACCOUNT_STATUS.PENDING;
-
- renderCheck(account_status, openFailedVerificationModal, selected_account_type);
-
- expect(screen.getByText('Pending verification')).toBeInTheDocument();
- expect(screen.getByText('IcAlertWarning')).toBeInTheDocument();
- });
-
- it('should render failed status and trigger "Why?"', () => {
- account_status = MT5_ACCOUNT_STATUS.FAILED;
-
- renderCheck(account_status, openFailedVerificationModal, selected_account_type);
-
- expect(screen.getByText('Verification failed.')).toBeInTheDocument();
- expect(screen.getByText('IcRedWarning')).toBeInTheDocument();
-
- fireEvent.click(screen.getByText('Why?'));
- expect(openFailedVerificationModal).toBeCalledWith(selected_account_type);
- });
-
- it('should render needs_verification status and redirect to identity by default', () => {
- account_status = MT5_ACCOUNT_STATUS.NEEDS_VERIFICATION;
+ account_status = ACCOUNT_BADGE_STATUS.PENDING;
- renderCheck(account_status, openFailedVerificationModal, selected_account_type, setIsVerificationModalVisible);
+ renderCheck(account_status);
- expect(screen.getByText(/Needs verification./));
- expect(screen.getByText('IcAlertInfo'));
-
- const btn = screen.getByText('Verify now');
- expect(btn).toBeInTheDocument();
- expect(btn.hasAttribute('href'));
- expect(btn.hasAttribute(routes.proof_of_identity));
- userEvent.click(btn);
- expect(setIsVerificationModalVisible).toBeCalled();
- });
-
- it('should render migrated_with_position status', () => {
- account_status = MT5_ACCOUNT_STATUS.MIGRATED_WITH_POSITION;
-
- renderCheck(account_status, openFailedVerificationModal, selected_account_type);
-
- expect(screen.getByText('No new positions')).toBeInTheDocument();
- expect(screen.getByText('IcAlertWarning')).toBeInTheDocument();
+ expect(screen.getByText('In review')).toBeInTheDocument();
+ expect(screen.getByText('IcMt5Pending')).toBeInTheDocument();
});
- it('should render migrated_without_position status', () => {
- account_status = MT5_ACCOUNT_STATUS.MIGRATED_WITHOUT_POSITION;
+ it('should render failed status', () => {
+ account_status = ACCOUNT_BADGE_STATUS.FAILED;
- renderCheck(account_status, openFailedVerificationModal, selected_account_type);
+ renderCheck(account_status);
+ const failed_text = screen.getByText('Failed');
- expect(screen.getByText('Account closed')).toBeInTheDocument();
- expect(screen.getByText('IcAlertWarning')).toBeInTheDocument();
- });
-
- it('should render need_verification status and redirect to POA when POI is verified', () => {
- account_status = MT5_ACCOUNT_STATUS.NEEDS_VERIFICATION;
-
- renderCheck(account_status, openFailedVerificationModal, selected_account_type, undefined, {
- poi_status: AUTH_STATUS_CODES.VERIFIED,
- poa_status: AUTH_STATUS_CODES.NONE,
- });
+ expect(failed_text).toBeInTheDocument();
+ expect(screen.getByText('IcMt5Failed')).toBeInTheDocument();
- expect(screen.getByText('Needs verification.'));
- expect(screen.getByText('IcAlertInfo'));
-
- const btn = screen.getByRole('link', { name: 'Verify now' });
- expect(btn).toBeInTheDocument();
- expect(btn.hasAttribute('href'));
- expect(btn.hasAttribute(routes.proof_of_address));
+ userEvent.click(failed_text);
});
- it('should render need_verification status and redirect to POI when POI status is not verified and POA status is not verified', () => {
- account_status = MT5_ACCOUNT_STATUS.NEEDS_VERIFICATION;
-
- renderCheck(account_status, openFailedVerificationModal, selected_account_type, undefined, {
- poi_status: AUTH_STATUS_CODES.NONE,
- poa_status: AUTH_STATUS_CODES.NONE,
- });
+ it('should render needs_verification status', () => {
+ account_status = ACCOUNT_BADGE_STATUS.NEEDS_VERIFICATION;
- expect(screen.getByText('Needs verification.'));
- expect(screen.getByText('IcAlertInfo'));
+ renderCheck(account_status);
+ const needs_verification_text = screen.getByText('Needs Verification');
- const btn = screen.getByRole('link', { name: 'Verify now' });
+ expect(needs_verification_text).toBeInTheDocument();
+ expect(screen.getByText('IcMt5Verification'));
- expect(btn).toBeInTheDocument();
- expect(btn.hasAttribute('href'));
- expect(btn.hasAttribute(routes.proof_of_identity));
+ userEvent.click(needs_verification_text);
});
});
diff --git a/packages/account/src/Configs/get-mt5-status-badge-config.tsx b/packages/account/src/Configs/get-mt5-status-badge-config.tsx
new file mode 100644
index 000000000000..78f4a90fac79
--- /dev/null
+++ b/packages/account/src/Configs/get-mt5-status-badge-config.tsx
@@ -0,0 +1,57 @@
+import React from 'react';
+import { Text } from '@deriv/components';
+import { MT5_ACCOUNT_STATUS, TRADING_PLATFORM_STATUS } from '@deriv/shared';
+import { Localize } from '@deriv-com/translations';
+import { TMT5AccountStatus } from '../Types/common.type';
+
+const getMT5StatusBadgeConfig = (mt5_account_status: TMT5AccountStatus) => {
+ const BadgeTextComponent = ;
+
+ switch (mt5_account_status) {
+ case MT5_ACCOUNT_STATUS.PENDING:
+ return {
+ text: ,
+ icon: 'IcMt5Pending',
+ };
+ case MT5_ACCOUNT_STATUS.FAILED:
+ return {
+ text: ,
+ icon: 'IcMt5Failed',
+ icon_size: '18',
+ };
+ case MT5_ACCOUNT_STATUS.NEEDS_VERIFICATION: {
+ return {
+ text: ,
+ icon: 'IcMt5Verification',
+ icon_size: '18',
+ };
+ }
+ case MT5_ACCOUNT_STATUS.MIGRATED_WITH_POSITION:
+ return {
+ text: ,
+ icon: 'IcAlertWarning',
+ };
+ case MT5_ACCOUNT_STATUS.MIGRATED_WITHOUT_POSITION:
+ return {
+ text: ,
+ icon: 'IcAlertWarning',
+ };
+ case MT5_ACCOUNT_STATUS.UNDER_MAINTENANCE:
+ return {
+ text: ,
+ icon: 'IcAlertWarning',
+ };
+ case TRADING_PLATFORM_STATUS.UNAVAILABLE:
+ return {
+ text: ,
+ icon: 'IcAlertWarning',
+ };
+ default:
+ return {
+ text: '',
+ icon: '',
+ };
+ }
+};
+
+export default getMT5StatusBadgeConfig;
diff --git a/packages/account/src/Configs/get-status-badge-config.tsx b/packages/account/src/Configs/get-status-badge-config.tsx
index 2f31d48d6269..cce0f1fcb352 100644
--- a/packages/account/src/Configs/get-status-badge-config.tsx
+++ b/packages/account/src/Configs/get-status-badge-config.tsx
@@ -1,102 +1,27 @@
import React from 'react';
-import { Text } from '@deriv/components';
-import { AUTH_STATUS_CODES, MT5_ACCOUNT_STATUS, TRADING_PLATFORM_STATUS, routes } from '@deriv/shared';
-import { Localize } from '@deriv/translations';
-import { TAuthStatusCodes, TMT5AccountStatus } from '../Types/common.type';
-import { Link } from 'react-router-dom';
+import { ACCOUNT_BADGE_STATUS, TAccountBadgeStatus } from '@deriv/shared';
+import { Localize } from '@deriv-com/translations';
-const getStatusBadgeConfig = (
- mt5_account_status: TMT5AccountStatus,
- openFailedVerificationModal?: (selected_account_type: Record) => void,
- selected_account_type?: Record,
- setIsVerificationModalVisible?: (value: boolean) => void,
- user_account_status?: { poi_status: TAuthStatusCodes; poa_status: TAuthStatusCodes }
-) => {
- const BadgeTextComponent = ;
-
- switch (mt5_account_status) {
- case MT5_ACCOUNT_STATUS.PENDING:
+const getStatusBadgeConfig = (account_status: TAccountBadgeStatus) => {
+ switch (account_status) {
+ case ACCOUNT_BADGE_STATUS.PENDING:
return {
- text: (
- ]}
- />
- ),
- icon: 'IcAlertWarning',
+ text: ,
+ icon: 'IcMt5Pending',
};
- case MT5_ACCOUNT_STATUS.FAILED:
+ case ACCOUNT_BADGE_STATUS.FAILED:
return {
- text: (
- ,
- {
- if (selected_account_type) {
- selected_account_type.client_kyc_status = {
- poi_status: user_account_status?.poi_status,
- poa_status: user_account_status?.poa_status,
- };
- selected_account_type;
- openFailedVerificationModal?.(selected_account_type ?? '');
- }
- }}
- />,
- ]}
- />
- ),
- icon: 'IcRedWarning',
+ text: ,
+ icon: 'IcMt5Failed',
+ icon_size: '18',
};
- case MT5_ACCOUNT_STATUS.NEEDS_VERIFICATION: {
- const redirect_url =
- user_account_status?.poi_status === AUTH_STATUS_CODES.NONE
- ? routes.proof_of_identity
- : routes.proof_of_address;
+ case ACCOUNT_BADGE_STATUS.NEEDS_VERIFICATION: {
return {
- text: (
- ,
- setIsVerificationModalVisible ? (
- setIsVerificationModalVisible?.(true)}
- />
- ) : (
-
- ),
- ]}
- />
- ),
- icon: 'IcAlertInfo',
+ text: ,
+ icon: 'IcMt5Verification',
+ icon_size: '18',
};
}
- case MT5_ACCOUNT_STATUS.MIGRATED_WITH_POSITION:
- return {
- text: ,
- icon: 'IcAlertWarning',
- };
- case MT5_ACCOUNT_STATUS.MIGRATED_WITHOUT_POSITION:
- return {
- text: ,
- icon: 'IcAlertWarning',
- };
- case MT5_ACCOUNT_STATUS.UNDER_MAINTENANCE:
- return {
- text: ,
- icon: 'IcAlertWarning',
- };
- case TRADING_PLATFORM_STATUS.UNAVAILABLE:
- return {
- text: ,
- icon: 'IcAlertWarning',
- };
default:
return {
text: '',
diff --git a/packages/account/src/Sections/Verification/Helpers/verification.js b/packages/account/src/Sections/Verification/Helpers/verification.js
index 624e7ecde65b..ac904c1a36a0 100644
--- a/packages/account/src/Sections/Verification/Helpers/verification.js
+++ b/packages/account/src/Sections/Verification/Helpers/verification.js
@@ -21,13 +21,16 @@ export const populateVerificationStatus = account_status => {
status => status === 'poa_authenticated_with_idv_photo'
);
const poa_expiring_soon = account_status.status.some(status => status === 'poa_expiring_soon');
-
+ const poi_acknowledged = ['pending', 'verified'].includes(identity_status);
const has_poa = !(document && document.status === 'none');
const has_poi = !(identity && identity.status === 'none');
const has_poinc = !(income && income.status === 'none');
const has_submitted_poa = document_status === 'pending' && !allow_poa_resubmission;
- const needs_poa = Boolean(needs_verification.length) && needs_verification.includes('document');
- const needs_poi = Boolean(needs_verification.length) && needs_verification.includes('identity');
+ const needs_poa =
+ !(has_submitted_poa || document_status === 'verified') ||
+ (needs_verification.length && needs_verification.includes('document'));
+ const needs_poi =
+ !poi_acknowledged || (Boolean(needs_verification.length) && needs_verification.includes('identity'));
const needs_poinc = needs_verification.length && needs_verification.includes('income');
const { idv, onfido, manual } = identity.services;
diff --git a/packages/account/src/Sections/Verification/ProofOfAddress/proof-of-address-container.tsx b/packages/account/src/Sections/Verification/ProofOfAddress/proof-of-address-container.tsx
index ba307e6b35df..566c1538a213 100644
--- a/packages/account/src/Sections/Verification/ProofOfAddress/proof-of-address-container.tsx
+++ b/packages/account/src/Sections/Verification/ProofOfAddress/proof-of-address-container.tsx
@@ -5,7 +5,6 @@ import { WS, getPlatformRedirect, platforms, routes, AUTH_STATUS_CODES } from '@
import { observer, useStore } from '@deriv/stores';
import { Localize } from '@deriv/translations';
import Expired from '../../../Components/poa/status/expired';
-import NeedsReview from '../../../Components/poa/status/needs-review';
import NotRequired from '../../../Components/poa/status/not-required';
import ProofOfAddressForm from './proof-of-address-form';
import Submitted from '../../../Components/poa/status/submitted';
@@ -60,6 +59,7 @@ const ProofOfAddressContainer = observer(({ onSubmit }: TProofOfAddressContainer
const { has_restricted_mt5_account, is_switching } = client;
const { is_verification_modal_visible } = ui;
const { refreshNotifications } = notifications;
+ const mt5_poa_status = localStorage.getItem('mt5_poa_status');
React.useEffect(() => {
if (!is_switching) {
@@ -100,6 +100,11 @@ const ProofOfAddressContainer = observer(({ onSubmit }: TProofOfAddressContainer
});
}
}, [is_switching, refreshNotifications]);
+ React.useEffect(() => {
+ return () => {
+ localStorage.removeItem('mt5_poa_status');
+ };
+ }, []);
const handleResubmit = () => {
setAuthenticationStatus(authentication_status => ({
@@ -193,22 +198,28 @@ const ProofOfAddressContainer = observer(({ onSubmit }: TProofOfAddressContainer
if (should_allow_resubmit) {
return ;
}
-
- switch (document_status) {
- case AUTH_STATUS_CODES.NONE:
- return ;
- case AUTH_STATUS_CODES.PENDING:
- return ;
- case AUTH_STATUS_CODES.VERIFIED:
- return ;
- case AUTH_STATUS_CODES.EXPIRED:
- return ;
- case AUTH_STATUS_CODES.REJECTED:
- case AUTH_STATUS_CODES.SUSPECTED:
- return ;
- default:
- return null;
- }
+ const getDocumentStatus = (
+ document_status: DeepRequired['authentication']['document']['status'] | string
+ ) => {
+ switch (document_status) {
+ case AUTH_STATUS_CODES.NONE:
+ return ;
+ case AUTH_STATUS_CODES.PENDING:
+ return ;
+ case AUTH_STATUS_CODES.VERIFIED:
+ return ;
+ case AUTH_STATUS_CODES.EXPIRED:
+ return ;
+ case AUTH_STATUS_CODES.REJECTED:
+ case AUTH_STATUS_CODES.SUSPECTED:
+ return ;
+ default:
+ return null;
+ }
+ };
+ if (mt5_poa_status) return getDocumentStatus(mt5_poa_status);
+ else if (document_status) return getDocumentStatus(document_status);
+ return null;
});
export default ProofOfAddressContainer;
diff --git a/packages/account/src/Sections/Verification/ProofOfIdentity/proof-of-identity-container-for-mt5.jsx b/packages/account/src/Sections/Verification/ProofOfIdentity/proof-of-identity-container-for-mt5.jsx
deleted file mode 100644
index d4178c30f96d..000000000000
--- a/packages/account/src/Sections/Verification/ProofOfIdentity/proof-of-identity-container-for-mt5.jsx
+++ /dev/null
@@ -1,78 +0,0 @@
-import React from 'react';
-import { Loading } from '@deriv/components';
-import { WS } from '@deriv/shared';
-import { localize } from '@deriv/translations';
-import { useStore, observer } from '@deriv/stores';
-import ErrorMessage from '../../../Components/error-component';
-import IconWithMessage from '../../../Components/icon-with-message';
-import POISubmissionForMT5 from './proof-of-identity-submission-for-mt5.jsx';
-import { service_code } from './proof-of-identity-utils';
-import { populateVerificationStatus } from '../Helpers/verification';
-
-const ProofOfIdentityContainerForMt5 = observer(({ onStateChange, citizen_data }) => {
- const [api_error, setAPIError] = React.useState();
- const [residence_list, setResidenceList] = React.useState();
- const [is_status_loading, setStatusLoading] = React.useState(true);
-
- const { client } = useStore();
- const { account_status, fetchResidenceList, is_switching, is_virtual } = client;
-
- React.useEffect(() => {
- // only re-mount logic when switching is done
- if (!is_switching) {
- WS.authorized.getAccountStatus().then(response_account_status => {
- if (response_account_status.error) {
- setAPIError(response_account_status.error);
- setStatusLoading(false);
- return;
- }
- fetchResidenceList().then(response_residence_list => {
- if (response_residence_list.error) {
- setAPIError(response_residence_list.error);
- } else {
- setResidenceList(response_residence_list.residence_list);
- }
- setStatusLoading(false);
- });
- });
- }
- }, [fetchResidenceList, is_switching]);
-
- if (is_status_loading || is_switching) {
- return ;
- } else if (is_virtual) {
- return (
-
- );
- } else if (api_error) {
- return ;
- }
-
- const verification_status = populateVerificationStatus(account_status);
- const { idv, identity_last_attempt, is_idv_disallowed, onfido } = verification_status;
-
- const poi_resubmission_cases = ['rejected', 'suspected', 'expired'];
-
- const has_idv_error =
- identity_last_attempt?.service && service_code.idv && poi_resubmission_cases.includes(idv.status);
-
- return (
-
- );
-});
-
-export default ProofOfIdentityContainerForMt5;
diff --git a/packages/account/src/Sections/Verification/ProofOfIdentity/proof-of-identity-submission-for-mt5.jsx b/packages/account/src/Sections/Verification/ProofOfIdentity/proof-of-identity-submission-for-mt5.jsx
deleted file mode 100644
index 2d5756e1e23d..000000000000
--- a/packages/account/src/Sections/Verification/ProofOfIdentity/proof-of-identity-submission-for-mt5.jsx
+++ /dev/null
@@ -1,193 +0,0 @@
-import React from 'react';
-import { AutoHeightWrapper } from '@deriv/components';
-import { useDevice } from '@deriv-com/ui';
-import {
- WS,
- isVerificationServiceSupported,
- formatIDVFormValues,
- formatIDVError,
- isIDVReportNotAvailable,
- getIDVNotApplicableOption,
-} from '@deriv/shared';
-import { useStore, observer } from '@deriv/stores';
-import Unsupported from '../../../Components/poi/status/unsupported';
-import OnfidoUpload from './onfido-sdk-view-container';
-import { identity_status_codes, submission_status_code, service_code } from './proof-of-identity-utils';
-import IdvFailed from '../../../Components/poi/idv-status/idv-failed';
-import { IdvDocSubmitOnSignup } from '../../../Components/poi/poi-form-on-signup/idv-doc-submit-on-signup/idv-doc-submit-on-signup';
-import { makeSettingsRequest } from '../../../Helpers/utils';
-
-const POISubmissionForMT5 = observer(
- ({
- idv,
- is_idv_disallowed,
- onfido,
- onStateChange,
- citizen_data,
- is_from_external,
- residence_list,
- identity_last_attempt,
- }) => {
- const { isDesktop } = useDevice();
- const [submission_status, setSubmissionStatus] = React.useState(); // submitting
- const [submission_service, setSubmissionService] = React.useState();
- const [idv_mismatch_status, setIdvMismatchStatus] = React.useState(null);
-
- const { client, notifications, traders_hub } = useStore();
- const { account_settings, getChangeableFields, account_status } = client;
- const { refreshNotifications } = notifications;
- const { is_eu_user } = traders_hub;
- const is_report_not_available = isIDVReportNotAvailable(idv);
- const IDV_NOT_APPLICABLE_OPTION = React.useMemo(() => getIDVNotApplicableOption(), []);
- const shouldSkipIdv = document_id => document_id === IDV_NOT_APPLICABLE_OPTION.id;
-
- const attempts = account_status?.authentication?.attempts;
-
- const { service } = attempts?.latest ?? {};
- const { submissions_left: idv_submissions_left, last_rejected, status } = idv;
- const { submissions_left: onfido_submissions_left } = onfido;
-
- const is_idv_supported =
- service === service_code.idv || isVerificationServiceSupported(residence_list, account_settings, 'idv');
- const is_onfido_supported =
- service === service_code.onfido ||
- (account_settings?.citizen !== 'ng' &&
- isVerificationServiceSupported(residence_list, account_settings, 'onfido'));
-
- React.useEffect(() => {
- if (citizen_data) {
- if (is_idv_supported && Number(idv_submissions_left) > 0 && !is_idv_disallowed && !is_eu_user) {
- setSubmissionService(service_code.idv);
- if (
- [
- identity_status_codes.rejected,
- identity_status_codes.suspected,
- identity_status_codes.expired,
- ].includes(status)
- ) {
- setIdvMismatchStatus(formatIDVError(last_rejected, status, undefined, is_report_not_available));
- }
- } else if (onfido_submissions_left && is_onfido_supported) {
- setSubmissionService(service_code.onfido);
- } else {
- setSubmissionService(service_code.manual);
- }
- setSubmissionStatus(submission_status_code.submitting);
- }
- }, [citizen_data]);
-
- const handleSelectionNext = () => {
- setSubmissionService(service_code.manual);
- };
-
- const handlePOIComplete = () => {
- if (onStateChange && typeof onStateChange === 'function') {
- onStateChange(identity_status_codes.pending);
- }
- WS.authorized.getAccountStatus().then(() => {
- refreshNotifications();
- });
- };
-
- const handleIdvSubmit = async (values, { setSubmitting, setErrors }) => {
- if (shouldSkipIdv(values?.document_type?.id)) {
- handleSelectionNext?.(true);
- return;
- }
- setSubmitting(true);
-
- const request = makeSettingsRequest(values, [...getChangeableFields()]);
-
- const data = await WS.setSettings(request);
-
- if (data.error) {
- setErrors({ error_message: data.error.message });
- setSubmitting(false);
- return;
- }
- const get_settings = WS.authorized.storage.getSettings();
-
- if (get_settings.error) {
- setErrors({ error_message: get_settings.error.message });
- setSubmitting(false);
- return;
- }
-
- const submit_data = {
- identity_verification_document_add: 1,
- ...formatIDVFormValues(values, citizen_data.value),
- };
-
- WS.send(submit_data).then(response => {
- setSubmitting(false);
- if (response.error) {
- setErrors({ error_message: response.error.message });
- return;
- }
- handlePOIComplete();
- });
- };
-
- if (submission_status === submission_status_code.submitting) {
- switch (submission_service) {
- case service_code.idv:
- return idv_mismatch_status ? (
-
- ) : (
-
- );
- case service_code.onfido: {
- const country_code = citizen_data.value;
- const doc_obj = citizen_data.identity.services.onfido.documents_supported;
- const documents_supported = Object.keys(doc_obj).map(d => doc_obj[d].display_name);
-
- return (
-
- {({ setRef, height }) => (
-
-
-
- )}
-
- );
- }
- case service_code.manual:
- return (
-
- );
- default:
- return null;
- }
- } else {
- return null;
- }
- }
-);
-
-export default POISubmissionForMT5;
diff --git a/packages/account/src/Styles/account.scss b/packages/account/src/Styles/account.scss
index 96717d7db005..d045ff565293 100644
--- a/packages/account/src/Styles/account.scss
+++ b/packages/account/src/Styles/account.scss
@@ -325,11 +325,6 @@ $MIN_HEIGHT_FLOATING: calc(
max-width: 100%;
width: 100%;
}
- .cfd-personal-details-modal__form & {
- margin: unset;
- max-width: unset;
- }
-
&--phone-verification-livechat-link {
color: var(--text-general);
}
diff --git a/packages/api-v2/package.json b/packages/api-v2/package.json
index a060ad184e88..ed5cfc4f46a8 100644
--- a/packages/api-v2/package.json
+++ b/packages/api-v2/package.json
@@ -16,7 +16,7 @@
"uuid": "^9.0.1"
},
"devDependencies": {
- "@deriv-com/analytics": "1.14.0",
+ "@deriv-com/analytics": "1.25.1",
"@deriv/api-types": "1.0.172",
"@testing-library/react": "^12.0.0",
"@testing-library/react-hooks": "^7.0.2",
diff --git a/packages/api-v2/src/hooks/__tests__/useSortedMT5Accounts.spec.ts b/packages/api-v2/src/hooks/__tests__/useSortedMT5Accounts.spec.ts
new file mode 100644
index 000000000000..9916fc1d8c78
--- /dev/null
+++ b/packages/api-v2/src/hooks/__tests__/useSortedMT5Accounts.spec.ts
@@ -0,0 +1,302 @@
+import { renderHook } from '@testing-library/react-hooks';
+import useActiveAccount from '../useActiveAccount';
+import useAvailableMT5Accounts from '../useAvailableMT5Accounts';
+import useIsEuRegion from '../useIsEuRegion';
+import useMT5AccountsList from '../useMT5AccountsList';
+import useSortedMT5Accounts from '../useSortedMT5Accounts';
+import { cleanup } from '@testing-library/react';
+
+jest.mock('../useActiveAccount', () => jest.fn());
+jest.mock('../useAvailableMT5Accounts', () => jest.fn());
+jest.mock('../useIsEuRegion', () => jest.fn());
+jest.mock('../useMT5AccountsList', () => jest.fn());
+
+const mockMT5NonEUAvailableAccounts = [
+ {
+ is_default_jurisdiction: 'false',
+ product: 'standard',
+ shortcode: 'svg',
+ },
+ {
+ is_default_jurisdiction: 'false',
+ product: 'financial',
+ shortcode: 'svg',
+ },
+ {
+ is_default_jurisdiction: 'true',
+ product: 'financial',
+ shortcode: 'vanuatu',
+ },
+ {
+ is_default_jurisdiction: 'true',
+ product: 'stp',
+ shortcode: 'vanuatu',
+ },
+ {
+ is_default_jurisdiction: 'true',
+ product: 'standard',
+ shortcode: 'vanuatu',
+ },
+ {
+ is_default_jurisdiction: 'true',
+ product: 'zero_spread',
+ shortcode: 'bvi',
+ },
+ {
+ is_default_jurisdiction: 'true',
+ product: 'swap_free',
+ shortcode: 'svg',
+ },
+];
+
+const mockMT5NonEUAddedAccounts = [
+ {
+ is_virtual: false,
+ landing_company_short: 'vanuatu',
+ product: 'standard',
+ },
+ {
+ is_virtual: false,
+ landing_company_short: 'vanuatu',
+ product: 'financial',
+ },
+ {
+ is_virtual: false,
+ landing_company_short: 'bvi',
+ product: 'zero_spread',
+ },
+];
+
+const mockMT5EUAvailableAccounts = [
+ {
+ is_default_jurisdiction: 'true',
+ product: 'financial',
+ shortcode: 'maltainvest',
+ },
+];
+
+const mockMT5EUAddedAccounts = [
+ {
+ is_virtual: false,
+ landing_company_short: 'maltainvest',
+ product: 'financial',
+ },
+];
+
+describe('useSortedMT5Accounts', () => {
+ beforeEach(() => {
+ (useActiveAccount as jest.Mock).mockReturnValue({
+ data: { is_virtual: false },
+ });
+ (useIsEuRegion as jest.Mock).mockReturnValue({
+ isEUCountry: false,
+ });
+ });
+ afterEach(cleanup);
+
+ it('returns non-eu available accounts with default jurisdiction', () => {
+ (useAvailableMT5Accounts as jest.Mock).mockReturnValue({
+ data: mockMT5NonEUAvailableAccounts,
+ });
+ (useMT5AccountsList as jest.Mock).mockReturnValue({
+ data: [],
+ });
+
+ const { result } = renderHook(() => useSortedMT5Accounts());
+
+ expect(result.current.data).toEqual([
+ {
+ is_added: false,
+ is_default_jurisdiction: 'true',
+ product: 'standard',
+ shortcode: 'vanuatu',
+ },
+ {
+ is_added: false,
+ is_default_jurisdiction: 'true',
+ product: 'financial',
+ shortcode: 'vanuatu',
+ },
+ {
+ is_added: false,
+ is_default_jurisdiction: 'true',
+ product: 'stp',
+ shortcode: 'vanuatu',
+ },
+ {
+ is_added: false,
+ is_default_jurisdiction: 'true',
+ product: 'swap_free',
+ shortcode: 'svg',
+ },
+ {
+ is_added: false,
+ is_default_jurisdiction: 'true',
+ product: 'zero_spread',
+ shortcode: 'bvi',
+ },
+ ]);
+ });
+
+ it('returns eu available accounts with default jurisdiction', () => {
+ (useAvailableMT5Accounts as jest.Mock).mockReturnValue({
+ data: mockMT5EUAvailableAccounts,
+ });
+ (useMT5AccountsList as jest.Mock).mockReturnValue({
+ data: [],
+ });
+
+ const { result } = renderHook(() => useSortedMT5Accounts());
+
+ expect(result.current.data).toEqual([
+ {
+ is_added: false,
+ is_default_jurisdiction: 'true',
+ product: 'financial',
+ shortcode: 'maltainvest',
+ },
+ ]);
+ });
+
+ it('returns list of non-eu added and available accounts after some accounts are created', () => {
+ (useAvailableMT5Accounts as jest.Mock).mockReturnValue({
+ data: mockMT5NonEUAvailableAccounts,
+ });
+ (useMT5AccountsList as jest.Mock).mockReturnValue({
+ data: mockMT5NonEUAddedAccounts,
+ });
+
+ const { result } = renderHook(() => useSortedMT5Accounts());
+
+ expect(result.current.data).toEqual([
+ {
+ is_added: true,
+ is_virtual: false,
+ landing_company_short: 'vanuatu',
+ product: 'standard',
+ },
+ {
+ is_added: true,
+ is_virtual: false,
+ landing_company_short: 'vanuatu',
+ product: 'financial',
+ },
+ {
+ is_added: false,
+ is_default_jurisdiction: 'true',
+ product: 'stp',
+ shortcode: 'vanuatu',
+ },
+ {
+ is_added: false,
+ is_default_jurisdiction: 'true',
+ product: 'swap_free',
+ shortcode: 'svg',
+ },
+ {
+ is_added: true,
+ is_virtual: false,
+ landing_company_short: 'bvi',
+ product: 'zero_spread',
+ },
+ ]);
+ });
+
+ it('returns list of eu added and available accounts after some accounts are created', () => {
+ (useAvailableMT5Accounts as jest.Mock).mockReturnValue({
+ data: mockMT5EUAvailableAccounts,
+ });
+ (useMT5AccountsList as jest.Mock).mockReturnValue({
+ data: mockMT5EUAddedAccounts,
+ });
+ (useIsEuRegion as jest.Mock).mockReturnValue({
+ isEUCountry: true,
+ });
+
+ const { result } = renderHook(() => useSortedMT5Accounts());
+
+ expect(result.current.data).toEqual([
+ {
+ is_added: true,
+ is_virtual: false,
+ landing_company_short: 'maltainvest',
+ product: 'financial',
+ },
+ ]);
+ });
+
+ it('returns sorted non-eu accounts list in the correct order', () => {
+ (useAvailableMT5Accounts as jest.Mock).mockReturnValue({
+ data: mockMT5NonEUAvailableAccounts,
+ });
+ (useMT5AccountsList as jest.Mock).mockReturnValue({
+ data: [],
+ });
+
+ const { result } = renderHook(() => useSortedMT5Accounts());
+
+ expect(result.current.data?.map(account => account.product)).toStrictEqual([
+ 'standard',
+ 'financial',
+ 'stp',
+ 'swap_free',
+ 'zero_spread',
+ ]);
+ });
+
+ it('all available MT5 accounts are created', () => {
+ (useAvailableMT5Accounts as jest.Mock).mockReturnValue({
+ data: mockMT5NonEUAvailableAccounts,
+ });
+ (useMT5AccountsList as jest.Mock).mockReturnValue({
+ data: [
+ ...mockMT5NonEUAddedAccounts,
+ {
+ is_virtual: false,
+ landing_company_short: 'svg',
+ product: 'swap_free',
+ },
+ {
+ is_virtual: false,
+ landing_company_short: 'vanuatu',
+ product: 'stp',
+ },
+ ],
+ });
+
+ const { result } = renderHook(() => useSortedMT5Accounts());
+
+ expect(result.current.data).toEqual([
+ {
+ is_added: true,
+ is_virtual: false,
+ landing_company_short: 'vanuatu',
+ product: 'standard',
+ },
+ {
+ is_added: true,
+ is_virtual: false,
+ landing_company_short: 'vanuatu',
+ product: 'financial',
+ },
+ {
+ is_added: true,
+ is_virtual: false,
+ landing_company_short: 'vanuatu',
+ product: 'stp',
+ },
+ {
+ is_added: true,
+ is_virtual: false,
+ landing_company_short: 'svg',
+ product: 'swap_free',
+ },
+ {
+ is_added: true,
+ is_virtual: false,
+ landing_company_short: 'bvi',
+ product: 'zero_spread',
+ },
+ ]);
+ });
+});
diff --git a/packages/api-v2/src/hooks/useSortedMT5Accounts.ts b/packages/api-v2/src/hooks/useSortedMT5Accounts.ts
index 7db93f7d010f..4634c5674865 100644
--- a/packages/api-v2/src/hooks/useSortedMT5Accounts.ts
+++ b/packages/api-v2/src/hooks/useSortedMT5Accounts.ts
@@ -28,79 +28,39 @@ const useSortedMT5Accounts = (regulation?: string) => {
: account.landing_company_short !== 'maltainvest')
);
- return filtered_available_accounts?.map(available_account => {
- const created_account = filtered_mt5_accounts?.find(account => {
+ const available_accounts = filtered_available_accounts
+ .filter(available => {
return (
- available_account.market_type === account.market_type &&
- available_account.shortcode === account.landing_company_short
+ !filtered_mt5_accounts.find(added => added.product === available.product) &&
+ // @ts-expect-error type for is_default_jurisdiction is unavailable in mt5_login_list and trading_platform_available_accounts
+ available.is_default_jurisdiction === 'true'
);
- });
-
- if (created_account)
- return {
- ...created_account,
- /** Determine if the account is added or not */
- is_added: true,
- } as const;
-
- return {
- ...available_account,
- /** Determine if the account is added or not */
- is_added: false,
- } as const;
- });
+ })
+ //@ts-expect-error needs backend type
+ .filter(account => !activeAccount?.is_virtual || account.product !== 'stp');
+
+ const combined_accounts = [
+ ...available_accounts.map(account => ({ ...account, is_added: false })),
+ ...filtered_mt5_accounts.map(account => ({ ...account, is_added: true })),
+ ];
+ return combined_accounts;
}, [activeAccount?.is_virtual, all_available_mt5_accounts, isEU, mt5_accounts]);
- // // Reduce out the added and non added accounts to make sure only one of each market_type is shown for not added
- const filtered_data = useMemo(() => {
- if (!modified_data) return;
-
- const added_accounts = modified_data.filter(account => account.is_added);
- const non_added_accounts = modified_data.filter(account => !account.is_added);
-
- const filtered_non_added_accounts = non_added_accounts.reduce((acc, account) => {
- const { market_type, product } = account;
- const key = product === 'zero_spread' ? `${market_type}_${product}` : market_type;
-
- const existing_account = acc.find(acc_account =>
- acc_account.product === 'zero_spread'
- ? `${acc_account.market_type}_${acc_account.product}` === key
- : acc_account.market_type === key
- );
- const added_account = added_accounts.find(acc_account =>
- acc_account.product === 'zero_spread'
- ? `${acc_account.market_type}_${acc_account.product}` === key
- : acc_account.market_type === key
- );
- if (existing_account || added_account) return acc;
-
- return [...acc, account];
- }, [] as typeof non_added_accounts);
-
- return [...added_accounts, ...filtered_non_added_accounts];
- }, [modified_data]);
-
- // Sort the data by market_type and product to make sure the order is 'synthetic', 'financial', 'swap_free' and 'zero_spread'
const sorted_data = useMemo(() => {
- const sorting_order = ['synthetic', 'financial', 'swap_free', 'zero_spread'];
+ const sorting_order = ['standard', 'financial', 'stp', 'swap_free', 'zero_spread'];
- if (!filtered_data) return;
+ if (!modified_data) return;
const sorted_data = sorting_order.reduce((acc, sort_order) => {
- const accounts = filtered_data.filter(account => {
- if (account.market_type === 'all') {
- return account.product === sort_order;
- }
- return account.market_type === sort_order;
- });
+ const accounts = modified_data.filter(account => account.product === sort_order);
if (!accounts.length) return acc;
return [...acc, ...accounts];
- }, [] as typeof filtered_data);
+ }, [] as typeof modified_data);
return sorted_data;
- }, [filtered_data]);
+ }, [modified_data]);
- const areAllAccountsCreated = sorted_data?.length === all_available_mt5_accounts?.length;
+ const areAllAccountsCreated = modified_data?.length === all_available_mt5_accounts?.length;
return {
data: sorted_data,
diff --git a/packages/appstore/package.json b/packages/appstore/package.json
index abb688f4fcc3..e9bd4b5b8349 100644
--- a/packages/appstore/package.json
+++ b/packages/appstore/package.json
@@ -26,7 +26,7 @@
"author": "Deriv",
"license": "Apache-2.0",
"dependencies": {
- "@deriv-com/analytics": "1.14.0",
+ "@deriv-com/analytics": "1.25.1",
"@deriv-com/translations": "1.3.9",
"@deriv-com/ui": "1.36.4",
"@deriv/account": "^1.0.0",
@@ -37,6 +37,7 @@
"@deriv/stores": "^1.0.0",
"@deriv/translations": "^1.0.0",
"@deriv/hooks": "^1.0.0",
+ "@deriv/quill-icons": "1.23.3",
"@deriv/wallets": "^1.0.0",
"classnames": "^2.2.6",
"mobx": "^6.6.1",
@@ -89,4 +90,4 @@
"webpack-bundle-analyzer": "^4.3.0",
"webpack-cli": "^4.7.2"
}
-}
\ No newline at end of file
+}
diff --git a/packages/appstore/src/components/banners/business-closure-banner/business-closure-banner.tsx b/packages/appstore/src/components/banners/business-closure-banner/business-closure-banner.tsx
index 178dd2b55e12..ba36e873738e 100644
--- a/packages/appstore/src/components/banners/business-closure-banner/business-closure-banner.tsx
+++ b/packages/appstore/src/components/banners/business-closure-banner/business-closure-banner.tsx
@@ -15,7 +15,7 @@ const BusinessClosureBanner = observer(() => {
{
no_MF_account,
toggleAccountTransferModal,
is_demo,
- openFailedVerificationModal,
showTopUpModal,
no_CR_account,
setSelectedAccount,
CFDs_restricted_countries,
financial_restricted_countries,
+ getDefaultJurisdiction,
} = traders_hub;
-
const {
setAccountType,
toggleCTraderTransferModal,
setAccountUnavailableModal,
setServerMaintenanceModal,
setProduct,
+ setJurisdictionSelectedShortcode,
} = cfd;
const {
- account_status,
is_landing_company_loaded,
is_populating_mt5_account_list,
real_account_creation_unlock_date,
ctrader_total_balance,
+ updateMT5AccountDetails,
+ is_switching,
} = client;
const { setAppstorePlatform } = common;
- const { openDerivRealAccountNeededModal, setShouldShowCooldownModal, setIsMT5VerificationFailedModal } = ui;
+ const { openDerivRealAccountNeededModal, setShouldShowCooldownModal } = ui;
const has_no_real_account = !has_any_real_account;
const accounts_sub_text =
!is_eu_user || is_demo_low_risk ? localize('Compare accounts') : localize('Account Information');
- const {
- poi_pending_for_bvi_labuan_vanuatu,
- poi_resubmit_for_bvi_labuan_vanuatu,
- poa_resubmit_for_labuan,
- is_idv_revoked,
- } = getAuthenticationStatusInfo(account_status);
-
const [is_traders_dashboard_tracking_enabled] = useGrowthbookGetFeatureValue({
featureFlag: 'ce_tradershub_dashboard_tracking',
defaultValue: false,
});
const { has_svg_accounts_to_migrate } = useMT5SVGEligibleToMigrate();
- const getAuthStatus = (status_list: boolean[]) => status_list.some(status => status);
const { getPlatformStatus } = useTradingPlatformStatus();
@@ -142,61 +133,23 @@ const CFDsListing = observer(() => {
return MT5_ACCOUNT_STATUS.UNDER_MAINTENANCE;
} else if (current_acc_status === 'unavailable') {
return TRADING_PLATFORM_STATUS.UNAVAILABLE;
- }
-
- if (jurisdiction) {
- switch (jurisdiction) {
- case Jurisdiction.BVI: {
- if (
- getAuthStatus([
- is_idv_revoked,
- poi_resubmit_for_bvi_labuan_vanuatu,
- current_acc_status === 'proof_failed',
- ])
- ) {
- return MT5_ACCOUNT_STATUS.FAILED;
- } else if (
- getAuthStatus([
- poi_pending_for_bvi_labuan_vanuatu,
- current_acc_status === 'verification_pending',
- ])
- ) {
- return MT5_ACCOUNT_STATUS.PENDING;
- }
- return null;
- }
- case Jurisdiction.LABUAN: {
- if (
- getAuthStatus([
- poa_resubmit_for_labuan,
- is_idv_revoked,
- poi_resubmit_for_bvi_labuan_vanuatu,
- current_acc_status === 'proof_failed',
- ])
- ) {
- return MT5_ACCOUNT_STATUS.FAILED;
- } else if (
- getAuthStatus([
- poi_pending_for_bvi_labuan_vanuatu,
- current_acc_status === 'verification_pending',
- ])
- ) {
- return MT5_ACCOUNT_STATUS.PENDING;
- }
- return null;
- }
+ } else if (jurisdiction) {
+ switch (current_acc_status) {
+ case 'proof_failed':
+ case 'poa_failed':
+ case 'poa_outdated':
+ return MT5_ACCOUNT_STATUS.FAILED;
+ case 'verification_pending':
+ case 'poa_pending':
+ return MT5_ACCOUNT_STATUS.PENDING;
+ case 'needs_verification':
+ case 'poa_required':
+ return MT5_ACCOUNT_STATUS.NEEDS_VERIFICATION;
+ case 'migrated_with_position':
+ return MT5_ACCOUNT_STATUS.MIGRATED_WITH_POSITION;
+ case 'migrated_without_position':
+ return MT5_ACCOUNT_STATUS.MIGRATED_WITHOUT_POSITION;
default:
- if (current_acc_status === 'proof_failed') {
- return MT5_ACCOUNT_STATUS.FAILED;
- } else if (current_acc_status === 'verification_pending') {
- return MT5_ACCOUNT_STATUS.PENDING;
- } else if (current_acc_status === 'needs_verification') {
- return MT5_ACCOUNT_STATUS.NEEDS_VERIFICATION;
- } else if (current_acc_status === 'migrated_with_position') {
- return MT5_ACCOUNT_STATUS.MIGRATED_WITH_POSITION;
- } else if (current_acc_status === 'migrated_without_position') {
- return MT5_ACCOUNT_STATUS.MIGRATED_WITHOUT_POSITION;
- }
return null;
}
}
@@ -234,8 +187,10 @@ const CFDsListing = observer(() => {
setPerformanceValue('switch_from_demo_to_real_time');
setPerformanceValue('switch_from_real_to_demo_time');
}
+ updateMT5AccountDetails();
}, [is_landing_company_loaded, is_populating_mt5_account_list]);
+ const is_mt5_list_loading = (is_landing_company_loaded && is_populating_mt5_account_list) || is_switching;
return (
{
{has_svg_accounts_to_migrate && is_landing_company_loaded && }
- {is_landing_company_loaded && !is_populating_mt5_account_list ? (
+ {!is_mt5_list_loading ? (
+ {/* MT5 */}
{combined_cfd_mt5_accounts.map((existing_account, index: number) => {
const list_size = combined_cfd_mt5_accounts.length;
const track_account_subtitle = existing_account.tracking_name ?? '';
const has_mt5_account_status =
- existing_account?.status || is_idv_revoked || hasMaintenanceStatus
+ existing_account?.status || hasMaintenanceStatus
? getMT5AccountAuthStatus(
existing_account?.status,
existing_account?.landing_company_short
)
: '';
-
return (
{
});
setProduct(existing_account.product);
setAppstorePlatform(existing_account.platform);
+ setJurisdictionSelectedShortcode(getDefaultJurisdiction());
getTradingPlatformStatus(existing_account.platform);
}
} else if (existing_account.action_type === 'multi-action') {
@@ -351,12 +307,6 @@ const CFDsListing = observer(() => {
});
}
- if (has_mt5_account_status === MT5_ACCOUNT_STATUS.FAILED && is_eu_user) {
- setIsMT5VerificationFailedModal(true);
- openFailedVerificationModal(existing_account);
- return;
- }
-
startTrade(existing_account.platform, existing_account);
}
}
@@ -367,8 +317,8 @@ const CFDsListing = observer(() => {
category: selected_account_type,
type: existing_account.market_type,
jurisdiction: existing_account.landing_company_short,
+ product: existing_account.product,
}}
- openFailedVerificationModal={openFailedVerificationModal}
market_type={existing_account?.market_type}
/>
);
@@ -377,6 +327,8 @@ const CFDsListing = observer(() => {
) : (
)}
+
+ {/* cTrader */}
{!is_eu_user && !CFDs_restricted_countries && !financial_restricted_countries && (
@@ -496,6 +448,7 @@ const CFDsListing = observer(() => {
+ {/* dxtrade */}
{is_landing_company_loaded ? (
available_dxtrade_accounts?.map(account => {
const existing_accounts = getExistingAccounts(account.platform, account.market_type);
diff --git a/packages/appstore/src/components/containers/__tests__/trading-app-card.spec.tsx b/packages/appstore/src/components/containers/__tests__/trading-app-card.spec.tsx
index dacafe3bec8a..3db1b1fe0c2b 100644
--- a/packages/appstore/src/components/containers/__tests__/trading-app-card.spec.tsx
+++ b/packages/appstore/src/components/containers/__tests__/trading-app-card.spec.tsx
@@ -36,7 +36,7 @@ describe(' ', () => {
type: 'synthetic',
jurisdiction: 'svg',
},
- openFailedVerificationModal: jest.fn(),
+ openVerificationDocsListModal: jest.fn(),
market_type: 'synthetic',
};
@@ -124,7 +124,7 @@ describe(' ', () => {
};
renderComponent({ props: new_mock_props });
- expect(screen.queryByText(/Pending verification/)).not.toBeInTheDocument();
+ expect(screen.queryByText(/In review/)).not.toBeInTheDocument();
expect(screen.queryByText(/No new positions/)).not.toBeInTheDocument();
expect(screen.queryByText(/Account closed/)).not.toBeInTheDocument();
});
diff --git a/packages/appstore/src/components/containers/trading-app-card.tsx b/packages/appstore/src/components/containers/trading-app-card.tsx
index 189a98833340..adda3fd929ad 100644
--- a/packages/appstore/src/components/containers/trading-app-card.tsx
+++ b/packages/appstore/src/components/containers/trading-app-card.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import classNames from 'classnames';
-import getStatusBadgeConfig from '@deriv/account/src/Configs/get-status-badge-config';
+import getMT5StatusBadgeConfig from '@deriv/account/src/Configs/get-mt5-status-badge-config';
import { Text, StatusBadge } from '@deriv/components';
import { Localize } from '@deriv/translations';
import { Analytics } from '@deriv-com/analytics';
@@ -43,22 +43,32 @@ const TradingAppCard = ({
short_code_and_region,
mt5_acc_auth_status,
selected_mt5_jurisdiction,
- openFailedVerificationModal,
market_type,
is_new = false,
}: Actions & BrandConfig & AvailableAccount & TDetailsOfEachMT5Loginid) => {
const {
common,
traders_hub,
- ui,
modules: { cfd },
- client,
} = useStore();
- const { setIsVerificationModalVisible } = ui;
- const { is_eu_user, is_demo_low_risk, content_flag, is_real, selected_account_type } = traders_hub;
+
+ const {
+ is_eu_user,
+ is_demo_low_risk,
+ content_flag,
+ is_real,
+ selected_account_type,
+ setVerificationModalOpen,
+ getMT5AccountKYCStatus,
+ } = traders_hub;
const { current_language, setAppstorePlatform } = common;
- const { is_account_being_created, setAccountUnavailableModal, setServerMaintenanceModal } = cfd;
- const { account_status: { authentication } = {} } = client;
+ const {
+ is_account_being_created,
+ setAccountUnavailableModal,
+ setServerMaintenanceModal,
+ setJurisdictionSelectedShortcode,
+ setProduct,
+ } = cfd;
const [is_traders_dashboard_tracking_enabled] = useGrowthbookGetFeatureValue({
featureFlag: 'ce_tradershub_dashboard_tracking',
@@ -77,6 +87,8 @@ const TradingAppCard = ({
link_to: '',
};
+ const { text: badge_text, icon: badge_icon, icon_size: badge_size } = getMT5StatusBadgeConfig(mt5_acc_auth_status);
+
const getAppDescription = () => {
if (is_existing_real_ctrader_account) return '';
if (platform === CFD_PLATFORMS.DXTRADE) {
@@ -90,17 +102,6 @@ const TradingAppCard = ({
return app_desc;
};
- const { text: badge_text, icon: badge_icon } = getStatusBadgeConfig(
- mt5_acc_auth_status,
- openFailedVerificationModal,
- selected_mt5_jurisdiction,
- setIsVerificationModalVisible,
- {
- poi_status: client_kyc_status?.poi_status ?? authentication?.identity?.status,
- poa_status: client_kyc_status?.poa_status ?? authentication?.document?.status,
- }
- );
-
const handleStatusBadgeClick = (mt5_acc_auth_status: string) => {
switch (mt5_acc_auth_status) {
case MT5_ACCOUNT_STATUS.MIGRATED_WITH_POSITION:
@@ -110,6 +111,15 @@ const TradingAppCard = ({
return setServerMaintenanceModal(true);
case TRADING_PLATFORM_STATUS.UNAVAILABLE:
return setAccountUnavailableModal(true);
+ case MT5_ACCOUNT_STATUS.PENDING:
+ case MT5_ACCOUNT_STATUS.FAILED:
+ case MT5_ACCOUNT_STATUS.NEEDS_VERIFICATION: {
+ setJurisdictionSelectedShortcode(selected_mt5_jurisdiction?.jurisdiction ?? '');
+ setProduct(selected_mt5_jurisdiction?.product ?? '');
+ getMT5AccountKYCStatus();
+ return setVerificationModalOpen(true);
+ }
+
default:
}
};
@@ -150,11 +160,11 @@ const TradingAppCard = ({
window.open(getStaticUrl(`trade-types/options/digital-options/up-and-down/`));
else;
};
+ const is_mt5_maintainance_status = [
+ TRADING_PLATFORM_STATUS.UNAVAILABLE,
+ MT5_ACCOUNT_STATUS.UNDER_MAINTENANCE,
+ ].includes(mt5_acc_auth_status);
- const migration_status =
- mt5_acc_auth_status === MT5_ACCOUNT_STATUS.MIGRATED_WITH_POSITION ||
- mt5_acc_auth_status === MT5_ACCOUNT_STATUS.MIGRATED_WITHOUT_POSITION;
- const is_disabled = !!(mt5_acc_auth_status && !migration_status) && !is_eu_user;
const platform_name = is_account_being_created ? name : sub_title ?? name;
const is_existing_real_ctrader_account =
@@ -229,6 +239,7 @@ const TradingAppCard = ({
account_status={mt5_acc_auth_status}
icon={badge_icon}
text={badge_text}
+ icon_size={badge_size}
onClick={() => {
setAppstorePlatform(platform);
handleStatusBadgeClick(mt5_acc_auth_status);
@@ -249,10 +260,7 @@ const TradingAppCard = ({
onAction={onAction}
is_external={is_external}
new_tab={new_tab}
- is_buttons_disabled={
- //For MF, we enable the button even if account is not authenticated. Rest of jurisdictions, disable the button for pending, failed and needs verification
- is_disabled
- }
+ is_buttons_disabled={is_mt5_maintainance_status}
is_account_being_created={!!is_account_being_created}
is_real={is_real}
/>
diff --git a/packages/appstore/src/components/currency-switcher-card/real/__tests__/real-account-switcher.spec.tsx b/packages/appstore/src/components/currency-switcher-card/real/__tests__/real-account-switcher.spec.tsx
index fc01a34382dc..d016b9f2f7ed 100644
--- a/packages/appstore/src/components/currency-switcher-card/real/__tests__/real-account-switcher.spec.tsx
+++ b/packages/appstore/src/components/currency-switcher-card/real/__tests__/real-account-switcher.spec.tsx
@@ -18,7 +18,7 @@ jest.mock('../real-account-card', () => ({
jest.mock('@deriv/account', () => ({
__esModule: true,
getStatusBadgeConfig: () => ({
- text: 'Pending verification',
+ text: 'In review',
icon: 'pending',
}),
}));
@@ -61,8 +61,8 @@ describe('RealAccountSwitcher', () => {
const { container } = render( , { wrapper });
expect(container).toBeInTheDocument();
- expect(screen.getByText('Pending verification')).toBeInTheDocument();
- expect(screen.getByText('Pending verification')).toHaveClass(
+ expect(screen.getByText('In review')).toBeInTheDocument();
+ expect(screen.getByText('In review')).toHaveClass(
'switcher-status-badge__container switcher-status-badge__container--pending'
);
});
diff --git a/packages/appstore/src/components/currency-switcher-card/real/real-account-switcher.tsx b/packages/appstore/src/components/currency-switcher-card/real/real-account-switcher.tsx
index d88817f35b29..8300758aa0a1 100644
--- a/packages/appstore/src/components/currency-switcher-card/real/real-account-switcher.tsx
+++ b/packages/appstore/src/components/currency-switcher-card/real/real-account-switcher.tsx
@@ -11,22 +11,24 @@ import { useMFAccountStatus } from '@deriv/hooks';
const AccountNeedsVerification = observer(() => {
const mf_account_status = useMFAccountStatus();
- const { client, traders_hub } = useStore();
- const { account_list, loginid, account_status } = client;
- const { openModal, openFailedVerificationModal } = traders_hub;
+ const { client, traders_hub, common } = useStore();
+ const { account_list, loginid } = client;
+ const { openModal, setVerificationModalOpen } = traders_hub;
+ const { setAppstorePlatform } = common;
const account = account_list?.find((acc: { loginid?: string }) => loginid === acc?.loginid);
const icon_title = account?.title;
- const { authentication } = account_status || {};
+ const onClickBanner = () => {
+ setAppstorePlatform('');
+ setVerificationModalOpen(true);
+ };
- const { text: badge_text, icon: badge_icon } = getStatusBadgeConfig(
- mf_account_status,
- openFailedVerificationModal,
- 'multipliers',
- undefined,
- { poi_status: authentication?.identity?.status, poa_status: authentication?.document?.status }
- );
+ const {
+ text: badge_text,
+ icon: badge_icon,
+ icon_size: badge_icon_size,
+ } = getStatusBadgeConfig(mf_account_status, onClickBanner);
return (
{
return openModal('currency_selection');
}}
>
-
+
);
});
diff --git a/packages/appstore/src/components/modals/failed-veriification-modal/failed-verification-modal.scss b/packages/appstore/src/components/modals/failed-veriification-modal/failed-verification-modal.scss
deleted file mode 100644
index 7debd13c6be5..000000000000
--- a/packages/appstore/src/components/modals/failed-veriification-modal/failed-verification-modal.scss
+++ /dev/null
@@ -1,39 +0,0 @@
-.failed-verification-modal {
- @include mobile {
- .dc-dialog__dialog {
- max-width: 32rem;
- }
- .dc-dialog__footer {
- .dc-btn {
- flex: 1;
- margin-bottom: 0;
- }
-
- .dc-dialog__button {
- max-width: fit-content;
- .dc-text.dc-btn__text {
- font-size: 1.2rem;
- }
- }
- }
- }
- &__failed_list {
- padding: 1.2rem 2.4rem;
- &-item {
- display: list-item;
- list-style-type: disc;
- &:first-child {
- margin-bottom: 0.8rem;
- }
- }
- }
-}
-
-.dc-modal__container_failed-verification-modal {
- .dc-modal-body {
- padding: 0 2.4rem;
- }
- .dc-modal-footer {
- padding: 2.4rem;
- }
-}
diff --git a/packages/appstore/src/components/modals/failed-veriification-modal/failed-verification-modal.tsx b/packages/appstore/src/components/modals/failed-veriification-modal/failed-verification-modal.tsx
deleted file mode 100644
index 05a44c99586d..000000000000
--- a/packages/appstore/src/components/modals/failed-veriification-modal/failed-verification-modal.tsx
+++ /dev/null
@@ -1,150 +0,0 @@
-import React from 'react';
-import { observer } from 'mobx-react-lite';
-import { useStores } from 'Stores';
-import { useHistory } from 'react-router-dom';
-import { localize, Localize } from '@deriv/translations';
-import { Text, Dialog } from '@deriv/components';
-import { isMobile, getAuthenticationStatusInfo, routes, Jurisdiction } from '@deriv/shared';
-import './failed-verification-modal.scss';
-
-type TFailedVerificationModal = {
- should_resubmit_poi: boolean;
- should_resubmit_poa: boolean;
- from_account: string;
- is_from_multipliers: boolean;
- has_mf_mt5_account: boolean;
-};
-
-const FailedVerificationModalContent = ({
- should_resubmit_poi,
- should_resubmit_poa,
- from_account,
- is_from_multipliers,
- has_mf_mt5_account,
-}: TFailedVerificationModal) => {
- return (
-
-
-
-
-
- {should_resubmit_poi && (
-
-
-
- )}
- {should_resubmit_poa && (
-
-
-
- )}
-
- {!is_from_multipliers && has_mf_mt5_account ? (
-
-
-
- ) : (
-
-
-
- )}
-
- );
-};
-
-const FailedVerificationModal = () => {
- const {
- traders_hub,
- ui,
- modules: { cfd },
- client,
- } = useStores();
- const {
- is_failed_verification_modal_visible,
- mt5_existing_account,
- toggleFailedVerificationModalVisibility,
- open_failed_verification_for,
- startTrade,
- } = traders_hub;
- const { account_status, client_kyc_status } = client;
- const { toggleCFDVerificationModal, current_list } = cfd;
- const { disableApp, enableApp, is_mt5_verification_failed_modal, setIsMT5VerificationFailedModal } = ui;
- const is_from_multipliers = open_failed_verification_for === 'multipliers';
- const has_mf_mt5_account = Object.keys(current_list)
- .map(key => current_list[key])
- .some(account => account.landing_company_short === Jurisdiction.MALTA_INVEST);
-
- const { poi_resubmit_for_maltainvest } = getAuthenticationStatusInfo(account_status);
- const history = useHistory();
-
- const closeModal = () => {
- setIsMT5VerificationFailedModal(false);
- if (is_mt5_verification_failed_modal) {
- toggleFailedVerificationModalVisibility();
- startTrade(mt5_existing_account.platform, mt5_existing_account);
- return;
- }
- toggleFailedVerificationModalVisibility();
- };
-
- const onConfirmModal = () => {
- setIsMT5VerificationFailedModal(false);
- toggleFailedVerificationModalVisibility();
- if (is_from_multipliers) {
- if (should_resubmit_poi()) {
- history.push(routes.proof_of_identity);
- } else {
- history.push(routes.proof_of_address);
- }
- } else {
- toggleCFDVerificationModal();
- }
- };
-
- const should_resubmit_poi = () => {
- if (is_from_multipliers || open_failed_verification_for === 'maltainvest') {
- return poi_resubmit_for_maltainvest;
- }
- return ['rejected', 'expired', 'suspected'].includes(client_kyc_status?.poi_status);
- };
-
- const should_resubmit_poa = ['rejected', 'expired', 'suspected'].includes(client_kyc_status?.poa_status);
- const from_account_label = is_from_multipliers ? localize('Multipliers') : localize('MT5');
-
- return (
-
-
-
- );
-};
-
-export default observer(FailedVerificationModal);
diff --git a/packages/appstore/src/components/modals/failed-veriification-modal/index.ts b/packages/appstore/src/components/modals/failed-veriification-modal/index.ts
deleted file mode 100644
index 073d4fdd1689..000000000000
--- a/packages/appstore/src/components/modals/failed-veriification-modal/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-import FailedVerificationModal from './failed-verification-modal';
-
-export default FailedVerificationModal;
diff --git a/packages/appstore/src/components/modals/modal-manager.tsx b/packages/appstore/src/components/modals/modal-manager.tsx
index e3234b47759e..1e5b1177cbe8 100644
--- a/packages/appstore/src/components/modals/modal-manager.tsx
+++ b/packages/appstore/src/components/modals/modal-manager.tsx
@@ -1,19 +1,17 @@
import React from 'react';
-import { useLocation } from 'react-router-dom';
import { observer } from 'mobx-react-lite';
import { useWalletMigration } from '@deriv/hooks';
import { makeLazyLoader, moduleLoader } from '@deriv/shared';
import { Loading } from '@deriv/components';
import { TTradingPlatformAvailableAccount } from './account-type-modal/types';
import { useStores } from 'Stores';
-import { TOpenAccountTransferMeta } from 'Types';
import { DetailsOfEachMT5Loginid } from '@deriv/api-types';
import CFDResetPasswordModal from '@deriv/cfd/src/Containers/cfd-reset-password-modal';
-const FailedVerificationModal = makeLazyLoader(
+const VerificationDocsListModal = makeLazyLoader(
() =>
moduleLoader(
- () => import(/* webpackChunkName: "modal_failed-veriification-modal" */ './failed-veriification-modal')
+ () => import(/* webpackChunkName: "modal_verification-docs-list-modal" */ './verification-docs-list-modal')
),
() =>
)();
@@ -61,17 +59,6 @@ const CFDServerErrorDialog = makeLazyLoader(
() =>
)();
-const JurisdictionModal = makeLazyLoader(
- () =>
- moduleLoader(
- () =>
- import(
- /* webpackChunkName: "modal_cfd_jurisdiction-modal" */ '@deriv/cfd/src/Containers/jurisdiction-modal/jurisdiction-modal'
- )
- ),
- () =>
-)();
-
const CFDPasswordModal = makeLazyLoader(
() =>
moduleLoader(
@@ -105,17 +92,6 @@ const MT5AccountUnavailableModal = makeLazyLoader(
() =>
)();
-const CFDDbviOnBoarding = makeLazyLoader(
- () =>
- moduleLoader(
- () =>
- import(
- /* webpackChunkName: "modal_cfd_cfd-dbvi-onboarding" */ '@deriv/cfd/src/Containers/cfd-dbvi-onboarding'
- )
- ),
- () =>
-)();
-
const CFDTopUpDemoModal = makeLazyLoader(
() =>
moduleLoader(
@@ -203,16 +179,12 @@ const ModalManager = () => {
const { platform } = common;
const {
current_list,
- enableCFDPasswordModal,
is_mt5_trade_modal_visible,
- setAccountType,
toggleMT5TradeModal,
getRealSyntheticAccountsExistingData,
getRealFinancialAccountsExistingData,
getRealSwapfreeAccountsExistingData,
has_cfd_error,
- is_jurisdiction_modal_visible,
- is_cfd_verification_modal_visible,
mt5_migration_error,
is_mt5_password_invalid_format_modal_visible,
is_cfd_password_modal_enabled,
@@ -237,7 +209,7 @@ const ModalManager = () => {
is_account_transfer_modal_open,
toggleAccountTransferModal,
is_real_wallets_upgrade_on,
- is_failed_verification_modal_visible,
+ is_verification_docs_list_modal_visible,
is_regulators_compare_modal_visible,
is_wallet_migration_failed,
is_setup_real_account_or_go_to_demo_modal_visible,
@@ -276,11 +248,6 @@ const ModalManager = () => {
}));
};
- const openRealPasswordModal = (account_type: TOpenAccountTransferMeta) => {
- setAccountType(account_type);
- enableCFDPasswordModal();
- };
-
const existing_accounts_data = (acc_type: TTradingPlatformAvailableAccount['market_type'] | 'synthetic') => {
const current_list_keys = Object.keys(current_list);
const should_be_enabled = (list_item: TCurrentList) =>
@@ -314,10 +281,8 @@ const ModalManager = () => {
{is_server_maintenance_modal_visible && }
{is_account_unavailable_modal_visible && }
- {is_jurisdiction_modal_visible && }
{should_show_cfd_password_modal && }
- {is_cfd_verification_modal_visible && }
-
+ {/* a new condition for this hotfix needs to be found */}
{is_ctrader_transfer_modal_visible && }
{has_cfd_error && }
{(is_top_up_virtual_open || is_top_up_virtual_success) && }
@@ -363,7 +328,7 @@ const ModalManager = () => {
toggleModal={toggleAccountTransferModal}
/>
)}
- {is_failed_verification_modal_visible && }
+ {is_verification_docs_list_modal_visible && }
{is_wallet_migration_failed && }
{(is_eligible || is_real_wallets_upgrade_on || is_in_progress) && }
diff --git a/packages/appstore/src/components/modals/verification-docs-list-modal/ListItem.tsx b/packages/appstore/src/components/modals/verification-docs-list-modal/ListItem.tsx
new file mode 100644
index 000000000000..a41b7ad63c80
--- /dev/null
+++ b/packages/appstore/src/components/modals/verification-docs-list-modal/ListItem.tsx
@@ -0,0 +1,103 @@
+import React from 'react';
+import { observer, useStore } from '@deriv/stores';
+import { LabelPairedChevronRightMdRegularIcon } from '@deriv/quill-icons';
+import { useHistory } from 'react-router-dom';
+import { Localize } from '@deriv/translations';
+import { Text, StatusBadge } from '@deriv/components';
+import { AUTH_STATUS_CODES } from '@deriv/shared';
+import './verification-docs-list-modal.scss';
+import { useDevice } from '@deriv-com/ui';
+import classNames from 'classnames';
+
+type TListItemProps = {
+ id: string;
+ text: string;
+ status?: string | number;
+ route: string;
+};
+
+type TAuthStatusCodes = typeof AUTH_STATUS_CODES[keyof typeof AUTH_STATUS_CODES];
+
+const getBadgeStatus = (status: TAuthStatusCodes) => {
+ switch (status) {
+ case AUTH_STATUS_CODES.VERIFIED:
+ return {
+ text: ,
+ icon: 'IcMt5Success',
+ icon_size: '18',
+ };
+ case AUTH_STATUS_CODES.PENDING:
+ return {
+ text: ,
+ icon: 'IcMt5Pending',
+ icon_size: '12',
+ };
+ case AUTH_STATUS_CODES.REJECTED:
+ case AUTH_STATUS_CODES.SUSPECTED:
+ return {
+ text: ,
+ icon: 'IcMt5Failed',
+ icon_size: '18',
+ };
+ default:
+ return {
+ text: '',
+ icon: '',
+ };
+ }
+};
+
+const ListItem = observer(({ id, text, status, route }: TListItemProps) => {
+ const { text: badge_text, icon: badge_icon, icon_size: badge_size } = getBadgeStatus(status);
+ const { traders_hub, ui } = useStore();
+ const { isMobile } = useDevice();
+ const { setVerificationModalOpen } = traders_hub;
+ const history = useHistory();
+ const is_document_verified = status === AUTH_STATUS_CODES.VERIFIED;
+
+ const onClickItem = () => {
+ if (is_document_verified) {
+ return;
+ }
+ if (id === 'tax') {
+ ui.setFieldRefToFocus('employment-tax-section');
+ }
+ if (id === 'address' && status) {
+ localStorage.setItem('mt5_poa_status', String(status));
+ }
+ history.push(route);
+ setVerificationModalOpen(false);
+ };
+
+ return (
+
+
+
+
+ {status === AUTH_STATUS_CODES.NONE || (id === 'tax' && status === 0) ? (
+
+ ) : (
+
+
+
+
+ )}
+
+ );
+});
+
+export default ListItem;
diff --git a/packages/appstore/src/components/modals/verification-docs-list-modal/__tests__/Listitem.spec.tsx b/packages/appstore/src/components/modals/verification-docs-list-modal/__tests__/Listitem.spec.tsx
new file mode 100644
index 000000000000..322b561415f3
--- /dev/null
+++ b/packages/appstore/src/components/modals/verification-docs-list-modal/__tests__/Listitem.spec.tsx
@@ -0,0 +1,117 @@
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import ListItem from '../ListItem';
+import { StoreProvider, mockStore } from '@deriv/stores';
+import { useDevice } from '@deriv-com/ui';
+import { useGetStatus, useIsSelectedMT5AccountCreated } from '@deriv/hooks';
+import { AUTH_STATUS_CODES } from '@deriv/shared';
+
+jest.mock('@deriv-com/ui', () => ({
+ ...jest.requireActual('@deriv-com/ui'),
+ useDevice: jest.fn(),
+}));
+
+jest.mock('@deriv/hooks', () => ({
+ ...jest.requireActual('@deriv/hooks'),
+ useGetStatus: jest.fn(),
+ useIsSelectedMT5AccountCreated: jest.fn(),
+}));
+
+jest.mock('@deriv/quill-icons', () => ({
+ ...jest.requireActual('@deriv/quill-icons'),
+ DerivLightUploadPoiIcon: () => DerivLightUploadPoiIcon
,
+ LabelPairedChevronRightMdRegularIcon: () => LabelPairedChevronRightMdRegularIcon
,
+ DerivLightWaitingPoaIcon: () => DerivLightWaitingPoaIcon
,
+}));
+
+jest.mock('@deriv/components', () => ({
+ ...jest.requireActual('@deriv/components'),
+ StatusBadge: () => StatusBadge
,
+}));
+
+jest.mock('@deriv/shared', () => ({
+ ...jest.requireActual('@deriv/shared'),
+ AUTH_STATUS_CODES: {
+ VERIFIED: 'verified',
+ PENDING: 'pending',
+ REJECTED: 'rejected',
+ },
+}));
+
+jest.mock('react-router-dom', () => ({
+ ...jest.requireActual('react-router-dom'),
+ useHistory: () => ({
+ push: jest.fn(),
+ location: { search: 'test' },
+ }),
+}));
+
+describe(' ', () => {
+ const defaultStore = mockStore({
+ traders_hub: {
+ setVerificationModalOpen: jest.fn(),
+ },
+ common: {
+ platform: 'mt5',
+ },
+ });
+
+ const renderComponent = (props: { id: string; text: string; status: string; route: string }) => {
+ render(
+
+
+
+ );
+ };
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ (useDevice as jest.Mock).mockReturnValue({ isMobile: false });
+ (useGetStatus as jest.Mock).mockReturnValue({
+ client_kyc_status: { poi_status: 'verified', poa_status: 'verified', valid_tin: 'verified' },
+ });
+ (useIsSelectedMT5AccountCreated as jest.Mock).mockReturnValue({ is_selected_MT5_account_created: true });
+ });
+
+ it('should render verified status', () => {
+ const props = {
+ id: 'identity',
+ text: 'Verified',
+ status: AUTH_STATUS_CODES.VERIFIED,
+ route: '/proof_of_identity',
+ };
+ renderComponent(props);
+
+ expect(screen.getByText('Verified')).toBeInTheDocument();
+ expect(screen.getByText('StatusBadge')).toBeInTheDocument();
+ expect(screen.getByText('LabelPairedChevronRightMdRegularIcon')).toBeInTheDocument();
+ });
+
+ it('should render pending status', () => {
+ const props = {
+ id: 'identity',
+ text: 'In review',
+ status: AUTH_STATUS_CODES.PENDING,
+ route: '/proof_of_identity',
+ };
+ renderComponent(props);
+
+ expect(screen.getByText('In review')).toBeInTheDocument();
+ expect(screen.getByText('StatusBadge')).toBeInTheDocument();
+ expect(screen.getByText('LabelPairedChevronRightMdRegularIcon')).toBeInTheDocument();
+ });
+
+ it('should render with Failed status', () => {
+ const props = {
+ id: 'identity',
+ text: 'Failed',
+ status: AUTH_STATUS_CODES.REJECTED,
+ route: '/proof_of_identity',
+ };
+ renderComponent(props);
+
+ expect(screen.getByText('Failed')).toBeInTheDocument();
+ expect(screen.getByText('StatusBadge')).toBeInTheDocument();
+ expect(screen.getByText('LabelPairedChevronRightMdRegularIcon')).toBeInTheDocument();
+ });
+});
diff --git a/packages/appstore/src/components/modals/verification-docs-list-modal/__tests__/verification-docs-list-modal.spec.tsx b/packages/appstore/src/components/modals/verification-docs-list-modal/__tests__/verification-docs-list-modal.spec.tsx
new file mode 100644
index 000000000000..db0e2f30bc6d
--- /dev/null
+++ b/packages/appstore/src/components/modals/verification-docs-list-modal/__tests__/verification-docs-list-modal.spec.tsx
@@ -0,0 +1,193 @@
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import { mockStore, StoreProvider } from '@deriv/stores';
+import { useDevice } from '@deriv-com/ui';
+import { useGetStatus, useIsSelectedMT5AccountCreated } from '@deriv/hooks';
+import VerificationDocsListModal from '../verification-docs-list-modal';
+
+jest.mock('@deriv-com/ui', () => ({
+ ...jest.requireActual('@deriv-com/ui'),
+ useDevice: jest.fn(() => ({ isMobile: false })),
+}));
+
+jest.mock('@deriv/hooks', () => ({
+ ...jest.requireActual('@deriv/hooks'),
+ useGetStatus: jest.fn(() => ({
+ client_kyc_status: { poi_status: 'rejected', poa_status: 'verified', valid_tin: 1 },
+ })),
+ useIsSelectedMT5AccountCreated: jest.fn(() => ({ is_selected_MT5_account_created: false })),
+}));
+
+jest.mock('@deriv/quill-icons', () => ({
+ ...jest.requireActual('@deriv/quill-icons'),
+ LabelPairedChevronRightCaptionBoldIcon: () => LabelPairedChevronRightCaptionBoldIcon
,
+}));
+
+jest.mock('@deriv/components', () => ({
+ ...jest.requireActual('@deriv/components'),
+ StatusBadge: () => StatusBadge
,
+ Icon: jest.fn(() => 'mockedIcon'),
+}));
+
+jest.mock('@deriv/shared', () => ({
+ ...jest.requireActual('@deriv/shared'),
+ CFD_PLATFORMS: { MT5: 'mt5' },
+}));
+
+describe(' ', () => {
+ const defaultstore = mockStore({
+ traders_hub: {
+ is_verification_docs_list_modal_visible: true,
+ setVerificationModalOpen: jest.fn(),
+ },
+ common: {
+ platform: 'mt5',
+ },
+ });
+ const renderComponent = ({ store = defaultstore }) => {
+ render(
+
+
+
+ );
+ };
+ let modal_root_el: HTMLDivElement;
+
+ beforeAll(() => {
+ modal_root_el = document.createElement('div');
+ modal_root_el.setAttribute('id', 'modal_root');
+ document.body.appendChild(modal_root_el);
+ });
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ afterAll(() => {
+ document.body.removeChild(modal_root_el);
+ });
+
+ it('should render the modal with details when mt5 account is created', () => {
+ (useIsSelectedMT5AccountCreated as jest.Mock).mockReturnValue({ is_selected_MT5_account_created: true });
+ (useDevice as jest.Mock).mockReturnValueOnce({ isMobile: false });
+ (useGetStatus as jest.Mock).mockReturnValueOnce({
+ client_kyc_status: {
+ poi_status: 'none',
+ poa_status: 'verified',
+ valid_tin: 1,
+ required_tin: 1,
+ },
+ });
+ renderComponent({});
+ expect(screen.getByText('Verification required')).toBeInTheDocument();
+ expect(screen.getByText('Your account needs verification.')).toBeInTheDocument();
+ expect(screen.getByText('Proof of identity')).toBeInTheDocument();
+ expect(screen.getByText('Proof of address')).toBeInTheDocument();
+ expect(screen.queryByText('Additional information')).not.toBeInTheDocument();
+ });
+
+ it('should render the modal with details when mt5 account is not created', () => {
+ (useIsSelectedMT5AccountCreated as jest.Mock).mockReturnValue({ is_selected_MT5_account_created: false });
+ (useGetStatus as jest.Mock).mockReturnValueOnce({
+ client_kyc_status: {
+ poi_status: 'pending',
+ poa_status: 'none',
+ valid_tin: 0,
+ required_tin: 1,
+ },
+ });
+ renderComponent({});
+ expect(screen.getByText('mockedIcon')).toBeInTheDocument();
+ expect(screen.getByText('Complete your profile')).toBeInTheDocument();
+ expect(
+ screen.getByText('Confirm your details to open the account. After verification, you can begin trading.')
+ ).toBeInTheDocument();
+ expect(screen.getByText('Proof of identity')).toBeInTheDocument();
+ expect(screen.getByText('Proof of address')).toBeInTheDocument();
+ expect(screen.queryByText('Additional information')).toBeInTheDocument();
+ });
+ it('should render the modal with details when platform is not mt5', () => {
+ (useIsSelectedMT5AccountCreated as jest.Mock).mockReturnValue({ is_selected_MT5_account_created: false });
+ (useGetStatus as jest.Mock).mockReturnValueOnce({
+ client_kyc_status: {
+ poi_status: 'pending',
+ poa_status: 'none',
+ },
+ });
+ const mock_store = mockStore({
+ traders_hub: {
+ is_verification_docs_list_modal_visible: true,
+ setVerificationModalOpen: jest.fn(),
+ },
+ common: {
+ platform: '',
+ },
+ });
+ renderComponent({ store: mock_store });
+ expect(screen.getByText('mockedIcon')).toBeInTheDocument();
+ expect(screen.getByText('Verification required')).toBeInTheDocument();
+ expect(screen.getByText('Your account needs verification.')).toBeInTheDocument();
+ expect(screen.getByText('Proof of identity')).toBeInTheDocument();
+ expect(screen.getByText('Proof of address')).toBeInTheDocument();
+ expect(screen.queryByText('Additional information ')).not.toBeInTheDocument();
+ });
+ it('should render the modal with tax details when mt5 account requires tin and tin is invalid', () => {
+ (useIsSelectedMT5AccountCreated as jest.Mock).mockReturnValue({ is_selected_MT5_account_created: false });
+ (useGetStatus as jest.Mock).mockReturnValueOnce({
+ client_kyc_status: {
+ poi_status: 'pending',
+ poa_status: 'none',
+ valid_tin: 0,
+ required_tin: 1,
+ },
+ });
+ renderComponent({});
+ expect(screen.getByText('mockedIcon')).toBeInTheDocument();
+ expect(screen.getByText('Complete your profile')).toBeInTheDocument();
+ expect(
+ screen.getByText('Confirm your details to open the account. After verification, you can begin trading.')
+ ).toBeInTheDocument();
+ expect(screen.getByText('Proof of identity')).toBeInTheDocument();
+ expect(screen.getByText('Proof of address')).toBeInTheDocument();
+ expect(screen.queryByText('Additional information')).toBeInTheDocument();
+ });
+ it('should render the modal without tax details when mt5 account doesnt require tin', () => {
+ (useIsSelectedMT5AccountCreated as jest.Mock).mockReturnValue({ is_selected_MT5_account_created: false });
+ (useGetStatus as jest.Mock).mockReturnValueOnce({
+ client_kyc_status: {
+ poi_status: 'pending',
+ poa_status: 'none',
+ valid_tin: 0,
+ required_tin: 0,
+ },
+ });
+ renderComponent({});
+ expect(screen.getByText('mockedIcon')).toBeInTheDocument();
+ expect(screen.getByText('Complete your profile')).toBeInTheDocument();
+ expect(
+ screen.getByText('Confirm your details to open the account. After verification, you can begin trading.')
+ ).toBeInTheDocument();
+
+ expect(screen.queryByText('Additional information')).not.toBeInTheDocument();
+ });
+
+ it('should render the modal without tax details when mt5 account require tin and valid tin is present', () => {
+ (useIsSelectedMT5AccountCreated as jest.Mock).mockReturnValue({ is_selected_MT5_account_created: false });
+ (useGetStatus as jest.Mock).mockReturnValueOnce({
+ client_kyc_status: {
+ poi_status: 'pending',
+ poa_status: 'none',
+ valid_tin: 1,
+ required_tin: 1,
+ },
+ });
+ renderComponent({});
+ expect(screen.getByText('mockedIcon')).toBeInTheDocument();
+ expect(screen.getByText('Complete your profile')).toBeInTheDocument();
+ expect(
+ screen.getByText('Confirm your details to open the account. After verification, you can begin trading.')
+ ).toBeInTheDocument();
+
+ expect(screen.queryByText('Additional information')).not.toBeInTheDocument();
+ });
+});
diff --git a/packages/appstore/src/components/modals/verification-docs-list-modal/index.ts b/packages/appstore/src/components/modals/verification-docs-list-modal/index.ts
new file mode 100644
index 000000000000..d508b6390de5
--- /dev/null
+++ b/packages/appstore/src/components/modals/verification-docs-list-modal/index.ts
@@ -0,0 +1,3 @@
+import VerificationDocsListModal from './verification-docs-list-modal';
+
+export default VerificationDocsListModal;
diff --git a/packages/appstore/src/components/modals/verification-docs-list-modal/verification-docs-list-modal.scss b/packages/appstore/src/components/modals/verification-docs-list-modal/verification-docs-list-modal.scss
new file mode 100644
index 000000000000..458fbf1a79e5
--- /dev/null
+++ b/packages/appstore/src/components/modals/verification-docs-list-modal/verification-docs-list-modal.scss
@@ -0,0 +1,55 @@
+.verification-docs-list-modal {
+ &__content {
+ display: flex;
+ flex-direction: column;
+ padding: 2.4rem;
+ justify-content: center;
+ align-items: center;
+ &-list {
+ width: 100%;
+ &-item {
+ cursor: pointer;
+ display: flex;
+ min-height: 5.6rem;
+ align-items: center;
+ border-radius: 2 * $BORDER_RADIUS;
+ background: var(--icon-grey-background);
+ padding: 0.8rem 1.6rem;
+ justify-content: space-between;
+ margin: 1.6rem auto;
+
+ &:hover {
+ background: var(--state-normal);
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
+ transition-delay: 0.1s;
+ }
+
+ &--disabled {
+ cursor: not-allowed;
+ pointer-events: none;
+ }
+ }
+ }
+ }
+ &__card {
+ display: flex;
+ gap: 0.8rem;
+ align-items: center;
+ &--icon {
+ width: 2.4rem;
+ height: 2.4rem;
+ }
+ }
+ &__status-badge {
+ text-decoration: none;
+ }
+}
+
+.dc-modal__container_verification-docs-list-modal {
+ .dc-modal-body {
+ padding: 0 2.4rem;
+ }
+ .dc-modal-footer {
+ padding: 2.4rem;
+ }
+}
diff --git a/packages/appstore/src/components/modals/verification-docs-list-modal/verification-docs-list-modal.tsx b/packages/appstore/src/components/modals/verification-docs-list-modal/verification-docs-list-modal.tsx
new file mode 100644
index 000000000000..46a6a6e78bac
--- /dev/null
+++ b/packages/appstore/src/components/modals/verification-docs-list-modal/verification-docs-list-modal.tsx
@@ -0,0 +1,108 @@
+import React, { Suspense } from 'react';
+import { useDevice } from '@deriv-com/ui';
+import { observer, useStore } from '@deriv/stores';
+import { Localize } from '@deriv/translations';
+import { Text, Modal, UILoader, MobileDialog, Icon } from '@deriv/components';
+import { routes, CFD_PLATFORMS } from '@deriv/shared';
+import { useGetStatus, useIsSelectedMT5AccountCreated } from '@deriv/hooks';
+import ListItem from './ListItem';
+import './verification-docs-list-modal.scss';
+
+type TItems = {
+ id: string;
+ text: string;
+ status: string | number;
+ route: string;
+};
+
+const VerificationDocsListModalContent = observer(() => {
+ const {
+ common: { platform },
+ } = useStore();
+ const { isMobile } = useDevice();
+ const { client_kyc_status } = useGetStatus();
+ const { is_selected_MT5_account_created } = useIsSelectedMT5AccountCreated();
+ if (!client_kyc_status) return null;
+ const { poi_status, poa_status, valid_tin, required_tin } = client_kyc_status;
+ const is_tin_required = required_tin === 1 && valid_tin === 0;
+
+ const items: TItems[] = [
+ poi_status && {
+ id: 'identity',
+ text: 'Proof of identity',
+ status: poi_status,
+ route: routes.proof_of_identity,
+ },
+ poa_status && {
+ id: 'address',
+ text: 'Proof of address',
+ status: poa_status,
+ route: routes.proof_of_address,
+ },
+ is_tin_required && {
+ id: 'tax',
+ text: 'Additional information',
+ status: valid_tin,
+ route: routes.personal_details,
+ },
+ ].filter(Boolean) as TItems[];
+
+ return (
+
+
+
+ {platform === CFD_PLATFORMS.MT5 && !is_selected_MT5_account_created ? (
+
+ ) : (
+
+ )}
+
+
+ {items.map(item => (
+
+ ))}
+
+
+ );
+});
+
+const VerificationDocsListModal = observer(() => {
+ const { traders_hub, common } = useStore();
+ const { is_verification_docs_list_modal_visible, setVerificationModalOpen } = traders_hub;
+ const { platform } = common;
+ const { is_selected_MT5_account_created } = useIsSelectedMT5AccountCreated();
+ const { isMobile } = useDevice();
+ const getTitle = () =>
+ platform === CFD_PLATFORMS.MT5 && !is_selected_MT5_account_created ? (
+
+ ) : (
+
+ );
+ return (
+ }>
+ {!isMobile ? (
+ setVerificationModalOpen(false)}
+ title={getTitle()}
+ width='44rem'
+ should_header_stick_body={false}
+ has_close_icon
+ >
+
+
+ ) : (
+ setVerificationModalOpen(false)}
+ >
+
+
+ )}
+
+ );
+});
+
+export default VerificationDocsListModal;
diff --git a/packages/appstore/src/types/common.types.ts b/packages/appstore/src/types/common.types.ts
index 4813d0bb1cd4..40d00326a0b5 100644
--- a/packages/appstore/src/types/common.types.ts
+++ b/packages/appstore/src/types/common.types.ts
@@ -60,10 +60,10 @@ export type TDetailsOfEachMT5Loginid = DetailsOfEachMT5Loginid & {
selected_mt5_jurisdiction?: TOpenAccountTransferMeta &
TJurisdictionData & {
platform?: string;
+ product?: string;
};
platform?: TPlatform;
product?: 'swap_free' | 'zero_spread' | 'derivx' | 'ctrader';
- openFailedVerificationModal?: (from_account: string) => void;
market_type: NonNullable | TMarketType;
client_kyc_status?: {
poa_status: string;
diff --git a/packages/cashier/package.json b/packages/cashier/package.json
index f88fab5013bd..6ff76ebfc804 100644
--- a/packages/cashier/package.json
+++ b/packages/cashier/package.json
@@ -37,7 +37,7 @@
"url": "https://github.com/deriv-com/deriv-app/issues"
},
"dependencies": {
- "@deriv-com/analytics": "1.14.0",
+ "@deriv-com/analytics": "1.25.1",
"@deriv-com/ui": "1.36.4",
"@deriv/api": "^1.0.0",
"@deriv/api-types": "1.0.172",
diff --git a/packages/cashier/src/components/cashier-locked/cashier-locked-provider.tsx b/packages/cashier/src/components/cashier-locked/cashier-locked-provider.tsx
index e0824673dc59..e5b3dbdc0938 100644
--- a/packages/cashier/src/components/cashier-locked/cashier-locked-provider.tsx
+++ b/packages/cashier/src/components/cashier-locked/cashier-locked-provider.tsx
@@ -64,7 +64,7 @@ const getMessage = ({
title: localize('Deposits disabled'),
description: (
{
const {
@@ -48,7 +48,7 @@ const CashierLocked = observer(() => {
is_deposit_locked,
is_withdrawal_locked,
is_identity_verification_needed,
- is_pending_verification: mf_account_status === MT5_ACCOUNT_STATUS.PENDING,
+ is_pending_verification: mf_account_status === ACCOUNT_BADGE_STATUS.PENDING,
is_duplicate_dob_phone,
is_account_to_be_closed_by_residence,
account_time_of_closure,
diff --git a/packages/cashier/src/pages/account-transfer/account-transfer-form/account-transfer-form.tsx b/packages/cashier/src/pages/account-transfer/account-transfer-form/account-transfer-form.tsx
index 998d5f64a415..cd11bfbd12be 100644
--- a/packages/cashier/src/pages/account-transfer/account-transfer-form/account-transfer-form.tsx
+++ b/packages/cashier/src/pages/account-transfer/account-transfer-form/account-transfer-form.tsx
@@ -58,7 +58,7 @@ const AccountOption = ({
if (is_pending_verification) {
return (
-
+
);
} else if (is_verification_needed) {
@@ -70,7 +70,7 @@ const AccountOption = ({
} else if (is_verification_failed) {
return (
-
+
);
} else if (is_server_maintenance) {
diff --git a/packages/cashier/src/stores/account-transfer-store.ts b/packages/cashier/src/stores/account-transfer-store.ts
index 071a2b74d9a5..946c78b42a29 100644
--- a/packages/cashier/src/stores/account-transfer-store.ts
+++ b/packages/cashier/src/stores/account-transfer-store.ts
@@ -393,6 +393,7 @@ export default class AccountTransferStore {
platform: account.account_type,
is_eu: this.root_store.client.is_eu,
product: account.product,
+ shortcode: account.landing_company_short,
})} ${this.root_store.client.is_eu ? '' : non_eu_accounts}`
: `${cfd_text_display} ${
getCFDAccountDisplay({
diff --git a/packages/cfd/build/webpack.config.js b/packages/cfd/build/webpack.config.js
index bb568b4fcb1a..8bd4952fe5ab 100644
--- a/packages/cfd/build/webpack.config.js
+++ b/packages/cfd/build/webpack.config.js
@@ -10,9 +10,7 @@ module.exports = function (env) {
entry: {
cfd: path.resolve(__dirname, '../src', 'index.tsx'),
CFDStore: 'Stores/Modules/CFD/cfd-store',
- JurisdictionModal: 'Containers/jurisdiction-modal/jurisdiction-modal.tsx',
CFDPasswordModal: 'Containers/cfd-password-modal.tsx',
- CFDDbviOnBoarding: 'Containers/cfd-dbvi-onboarding.tsx',
CFDResetPasswordModal: 'Containers/cfd-reset-password-modal.tsx',
CFDServerErrorDialog: 'Containers/cfd-server-error-dialog.tsx',
CFDTopUpDemoModal: 'Containers/cfd-top-up-demo-modal.tsx',
diff --git a/packages/cfd/package.json b/packages/cfd/package.json
index 62914b9d0d87..089a173dedb3 100644
--- a/packages/cfd/package.json
+++ b/packages/cfd/package.json
@@ -86,7 +86,7 @@
},
"dependencies": {
"@deriv-com/ui": "1.36.4",
- "@deriv-com/analytics": "1.14.0",
+ "@deriv-com/analytics": "1.25.1",
"@deriv-com/translations": "1.3.9",
"@deriv-com/utils": "^0.0.36",
"@deriv/account": "^1.0.0",
diff --git a/packages/cfd/src/Components/__tests__/cfd-poa.spec.tsx b/packages/cfd/src/Components/__tests__/cfd-poa.spec.tsx
deleted file mode 100644
index 76ca9e8038ad..000000000000
--- a/packages/cfd/src/Components/__tests__/cfd-poa.spec.tsx
+++ /dev/null
@@ -1,151 +0,0 @@
-import React from 'react';
-import { BrowserRouter } from 'react-router-dom';
-import { fireEvent, render, screen, waitFor } from '@testing-library/react';
-import userEvent from '@testing-library/user-event';
-import { mockStore } from '@deriv/stores';
-import CFDPOA from '../cfd-poa';
-import CFDProviders from '../../cfd-providers';
-
-const mock_kyc_auth_status_response = {
- kyc_auth_status: {
- address: {
- supported_documents: ['utility_bill', 'affidavit', 'poa_others'],
- },
- },
- isLoading: false,
- isSuccess: false,
-};
-
-jest.mock('@deriv/account/src/Components/forms/personal-details-form.jsx', () =>
- jest.fn(() => PersonalDetailsForm
)
-);
-jest.mock('@deriv/account/src/Components/poa/common-mistakes/common-mistake-examples', () =>
- jest.fn(() => CommonMistakeExamples
)
-);
-
-jest.mock('@deriv/account/src/hooks', () => ({
- useKycAuthStatus: jest.fn(() => mock_kyc_auth_status_response),
-}));
-
-jest.mock('@deriv/account/src/Components/leave-confirm', () => jest.fn(() => LeaveConfirm
));
-jest.mock('@deriv/shared', () => ({
- ...jest.requireActual('@deriv/shared'),
- validPostCode: jest.fn(() => true),
- validLength: jest.fn(() => true),
- validLetterSymbol: jest.fn(() => true),
- validAddress: jest.fn(() => ({
- is_ok: true,
- })),
- WS: {
- authorized: {
- storage: {
- getSettings: jest.fn().mockResolvedValue({
- get_settings: {
- address_line_1: 'test address_line_1',
- address_line_2: 'test address_line_2',
- address_city: 'test address_city',
- address_state: 'test address_state',
- address_postcode: 'test address_postcode',
- },
- }),
- getAccountStatus: jest.fn().mockResolvedValue({
- get_account_status: {
- authentication: {
- document: {
- status: 'none',
- },
- identity: {
- status: 'none',
- },
- },
- },
- }),
- },
- },
- setSettings: jest.fn(() => Promise.resolve({ error: '' })),
- wait: jest.fn(() => Promise.resolve([])),
- getSocket: jest.fn().mockReturnValue({}),
- },
-}));
-
-jest.mock('@deriv/hooks', () => ({
- ...jest.requireActual('@deriv/hooks'),
- useFileUploader: jest.fn(() => ({
- upload: jest.fn(),
- })),
-}));
-
-describe(' ', () => {
- const mock_props: React.ComponentProps = {
- index: 0,
- onSave: jest.fn(),
- onSubmit: jest.fn(),
- };
- const mock_store = mockStore({
- client: {
- account_settings: {
- address_line_1: 'test address_line_1',
- address_line_2: 'test address_line_2',
- address_city: 'test address_city',
- address_state: 'test address_state',
- address_postcode: 'test address_postcode',
- country_code: 'in',
- },
- fetchResidenceList: jest.fn(() => Promise.resolve('')),
- getChangeableFields: jest.fn(() => []),
- },
- });
-
- it('should render CFDPOA and trigger buttons', async () => {
- render(
-
-
-
-
-
- );
-
- expect(await screen.findByText('PersonalDetailsForm')).toBeInTheDocument();
-
- const button = screen.getByRole('button');
- expect(button).toHaveTextContent('Continue');
- expect(button).toBeDisabled();
-
- const uploader = screen.getByTestId('dt_file_upload_input');
- const file = new File(['test file'], 'test_file.png', { type: 'image/png' });
- const dt_document_type = screen.getByRole('textbox', { name: /Type of document/ });
- fireEvent.change(dt_document_type, { target: { value: 'utility_bill' } });
- await waitFor(() => {
- userEvent.upload(uploader, file);
- });
-
- expect(button).toBeEnabled();
-
- userEvent.click(button);
-
- await waitFor(() => {
- expect(mock_props.onSave).toHaveBeenCalled();
- expect(mock_props.onSubmit).toHaveBeenCalled();
- });
- });
-
- it('should render duplicate document error message if has_submitted_duplicate_poa is true ', async () => {
- const setHasSubmittedDuplicatePOA = jest.fn();
- jest.spyOn(React, 'useState').mockImplementationOnce(() => [true, setHasSubmittedDuplicatePOA]);
-
- render(
-
-
-
-
-
- );
- expect(screen.getByText(/we could not verify your proof of address/i)).toBeInTheDocument();
- expect(screen.getByText(/proof of address documents upload failed/i)).toBeInTheDocument();
- expect(screen.getByText(/try again/i)).toBeInTheDocument();
- const submit_btn = screen.getByRole('button', { name: 'Try again' });
-
- userEvent.click(submit_btn);
- expect(setHasSubmittedDuplicatePOA).toHaveBeenCalledWith(false);
- });
-});
diff --git a/packages/cfd/src/Components/__tests__/cfd-poi.spec.js b/packages/cfd/src/Components/__tests__/cfd-poi.spec.js
deleted file mode 100644
index cb081f2cb04a..000000000000
--- a/packages/cfd/src/Components/__tests__/cfd-poi.spec.js
+++ /dev/null
@@ -1,106 +0,0 @@
-import { render, screen } from '@testing-library/react';
-import React from 'react';
-import CFDPOI from '../cfd-poi';
-import CFDProviders from '../../cfd-providers';
-import { mockStore } from '@deriv/stores';
-
-jest.mock('@deriv/account/src/Sections/Verification/ProofOfIdentity/proof-of-identity-container-for-mt5.jsx', () =>
- jest.fn(() => ProofOfIdentityContainerForMt5
)
-);
-
-describe(' ', () => {
- let props;
- let mockRootStore;
-
- beforeEach(() => {
- mockRootStore = {
- client: {
- account_status: {
- authentication: {
- attempts: { count: 0, history: {}, latest: null },
- identity: {
- services: { idv: {}, manual: {}, onfido: {} },
- status: 'none',
- },
- document: {
- status: 'none',
- },
- needs_verification: [],
- ownership: { requests: [], status: 'none' },
- },
- currency_config: {
- USD: {
- is_deposit_suspended: 0,
- is_withdrawal_suspended: 0,
- },
- },
- prompt_client_to_authenticate: 0,
- risk_classification: 'low',
- status: [
- 'allow_document_upload',
- 'crs_tin_information',
- 'deposit_attempt',
- 'financial_information_not_complete',
- 'trading_experience_not_complete',
- ],
- },
- is_switching: false,
- is_virtual: false,
- should_allow_authentication: true,
- fetchResidenceList: jest.fn(),
- },
- common: {
- routeBackInApp: jest.fn(),
- app_routing_history: [
- {
- action: 'POP',
- hash: '#real',
- pathname: '/mt5',
- search: '',
- state: undefined,
- },
- {
- action: 'PUSH',
- hash: '',
- pathname: '/',
- search: '',
- state: undefined,
- },
- ],
- },
- notifications: {
- refreshNotifications: jest.fn(),
- },
- };
-
- props = {
- addNotificationByKey: jest.fn(),
- authentication_status: {
- document_status: '',
- identity_status: '',
- },
- form_error: undefined,
- height: 'auto',
- index: 1,
- is_loading: false,
- is_switching: false,
- is_virtual: false,
- is_eu_user: false,
- onCancel: jest.fn(),
- onSave: jest.fn(),
- onSubmit: jest.fn(),
- removeNotificationByKey: jest.fn(),
- removeNotificationMessage: jest.fn(),
- value: {
- poi_state: 'unknown',
- },
- };
- });
-
- it('should render ProofOfIdentityContainerForMt5', () => {
- render( , {
- wrapper: ({ children }) => {children} ,
- });
- expect(screen.getByText('ProofOfIdentityContainerForMt5')).toBeInTheDocument();
- });
-});
diff --git a/packages/cfd/src/Components/cfd-account-card.tsx b/packages/cfd/src/Components/cfd-account-card.tsx
index d4a669254c27..0aa68ef8bb61 100644
--- a/packages/cfd/src/Components/cfd-account-card.tsx
+++ b/packages/cfd/src/Components/cfd-account-card.tsx
@@ -21,7 +21,7 @@ import {
TCFDAccountCard,
TCFDAccountCardActionProps,
TTradingPlatformAccounts,
- TTradingPlatformAvailableAccount,
+ TModifiedTradingPlatformAvailableAccount,
} from './props.types';
import { CFD_PLATFORMS, CATEGORY, MARKET_TYPE } from '../Helpers/cfd-config';
import { TMarketTypeSynthetic, TAccountCategory } from '../types/market-type.types';
@@ -177,7 +177,6 @@ const CFDAccountCardComponent = observer(
setAccountType,
setJurisdictionSelectedShortcode,
setMT5TradeAccount,
- toggleCFDVerificationModal,
toggleMT5TradeModal,
} = useCfdStore();
@@ -189,10 +188,10 @@ const CFDAccountCardComponent = observer(
platform === CFD_PLATFORMS.MT5 &&
(type.category === CATEGORY.DEMO
? isEligibleForMoreDemoMt5Svg(
- type.type as TTradingPlatformAvailableAccount['market_type'] | TMarketTypeSynthetic
+ type.type as TModifiedTradingPlatformAvailableAccount['market_type'] | TMarketTypeSynthetic
) && !!existing_data
: isEligibleForMoreRealMt5(
- type.type as TTradingPlatformAvailableAccount['market_type'] | TMarketTypeSynthetic
+ type.type as TModifiedTradingPlatformAvailableAccount['market_type'] | TMarketTypeSynthetic
) && !!existing_data);
const platform_icon = show_eu_related_content && platform === CFD_PLATFORMS.MT5 ? CFD_PLATFORMS.CFD : type.type;
@@ -272,7 +271,6 @@ const CFDAccountCardComponent = observer(
});
setJurisdictionSelectedShortcode(landing_company_short);
updateAccountStatus();
- toggleCFDVerificationModal();
}}
primary
large
diff --git a/packages/cfd/src/Components/cfd-poa.tsx b/packages/cfd/src/Components/cfd-poa.tsx
deleted file mode 100644
index 30e9a0de87f2..000000000000
--- a/packages/cfd/src/Components/cfd-poa.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-import React from 'react';
-import { FormikValues } from 'formik/dist/types';
-import ProofOfAddressForm from '@deriv/account/src/Sections/Verification/ProofOfAddress/proof-of-address-form';
-import IconMessageContent from '@deriv/account/src/Components/icon-message-content';
-import { Localize } from '@deriv/translations';
-import { Button, Text, Icon } from '@deriv/components';
-
-type TCFDPOA = {
- index: number;
- onSave: (index: number, values: FormikValues) => void;
- onSubmit: (index: number, values: FormikValues) => void;
-};
-
-const CFDPOA = ({ index, onSave, onSubmit }: TCFDPOA) => {
- const [has_submitted_duplicate_poa, setHasSubmittedDuplicatePOA] = React.useState(false);
- const onSubmitForCFDModal = (values: FormikValues, has_submitted_duplicate_poa = false) => {
- if (has_submitted_duplicate_poa) {
- setHasSubmittedDuplicatePOA(has_submitted_duplicate_poa);
- } else {
- onSave(index, values);
- onSubmit(index, values);
- }
- };
-
- return (
-
- {has_submitted_duplicate_poa ? (
- }
- text={ }
- icon={ }
- >
- setHasSubmittedDuplicatePOA(false)}
- has_effect
- primary
- large
- className='upload_error_btn'
- >
-
-
-
-
-
- ) : (
-
- )}
-
- );
-};
-
-export default CFDPOA;
diff --git a/packages/cfd/src/Components/cfd-poi.tsx b/packages/cfd/src/Components/cfd-poi.tsx
deleted file mode 100644
index 67ced113919b..000000000000
--- a/packages/cfd/src/Components/cfd-poi.tsx
+++ /dev/null
@@ -1,49 +0,0 @@
-// @ts-expect-error remove this line when ProofOfIdentityContainerForMt5 is converted to TS
-import ProofOfIdentityContainerForMt5 from '@deriv/account/src/Sections/Verification/ProofOfIdentity/proof-of-identity-container-for-mt5.jsx';
-import React from 'react';
-import { useStore, observer } from '@deriv/stores';
-import type { TCoreStores } from '@deriv/stores/types';
-
-type TCFDValue = {
- poi_state: string;
-};
-
-type TFormValues = {
- poi_state?: string;
-};
-
-export type TCFDPOIProps = {
- index: number;
- onSubmit: (index: number, value: TCFDValue) => void;
- value: TCFDValue;
- addNotificationMessageByKey: TCoreStores['notifications']['addNotificationMessageByKey'];
- height: string;
- onSave: (index: number, values: TFormValues) => void;
- removeNotificationByKey: TCoreStores['notifications']['removeNotificationByKey'];
- removeNotificationMessage: TCoreStores['notifications']['removeNotificationMessage'];
- jurisdiction_selected_shortcode: string;
-};
-
-const CFDPOI = observer(({ index, onSave, onSubmit, ...props }: TCFDPOIProps) => {
- const { client } = useStore();
- const { account_settings, residence_list } = client;
-
- const [poi_state, setPOIState] = React.useState('none');
- const citizen = account_settings?.citizen || account_settings?.country_code;
- const citizen_data = residence_list?.find(item => item.value === citizen);
-
- const onStateChange = (status: string) => {
- setPOIState(status);
- onSave(index, { poi_state: status });
- onSubmit(index, { poi_state });
- };
- return (
- onStateChange(status)}
- citizen_data={citizen_data}
- />
- );
-});
-
-export default CFDPOI;
diff --git a/packages/cfd/src/Components/props.types.ts b/packages/cfd/src/Components/props.types.ts
index e35eb267cf47..0f354d3c513b 100644
--- a/packages/cfd/src/Components/props.types.ts
+++ b/packages/cfd/src/Components/props.types.ts
@@ -1,4 +1,5 @@
import { DetailsOfEachMT5Loginid } from '@deriv/api-types';
+import { TAdditionalDetailsOfEachMT5Loginid, TTradingPlatformAvailableAccount } from '@deriv/stores/types';
import { TCFDPasswordReset } from '../Containers/props.types';
@@ -8,7 +9,7 @@ export type TCFDPlatform = 'dxtrade' | 'mt5' | 'ctrader';
export type TCFDsPlatformType = 'dxtrade' | 'mt5' | 'ctrader' | '';
-export type TProducts = 'swap_free' | 'zero_spread' | 'ctrader' | 'derivx';
+export type TProducts = 'swap_free' | 'zero_spread' | 'ctrader' | 'derivx' | 'financial' | 'standard' | 'stp';
export type TShortcode = DetailsOfEachMT5Loginid['landing_company_short'];
@@ -75,31 +76,11 @@ export type TCFDAccountCardActionProps = {
setShouldShowCooldownModal: (value: boolean) => void;
};
-export 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?: TShortcode;
- sub_account_type: string;
- account_type?: 'real' | 'demo';
- landing_company_short?: TShortcode;
- max_count?: number;
- available_count?: number;
-};
-
export type TModifiedTradingPlatformAvailableAccount = Omit & {
platform?: 'mt5' | 'dxtrade' | 'ctrader';
market_type: TTradingPlatformAvailableAccount['market_type'] | 'synthetic';
- product?: TProducts;
+ account_type?: 'real' | 'demo';
+ landing_company_short?: TShortcode;
};
export type TCardFlipStatus = {
@@ -264,7 +245,8 @@ export type TInstrumentsIcon = {
| 'Cryptocurrencies'
| 'ETF';
text: string;
- highlighted: boolean;
+ id?: string;
+ highlighted?: boolean;
className?: string;
is_asterisk?: boolean;
};
@@ -279,7 +261,7 @@ export type TJurisdictionData = {
jurisdiction?: 'bvi' | 'labuan' | 'svg' | 'vanuatu' | 'maltainvest' | 'malta';
};
-export type TDetailsOfEachMT5Loginid = DetailsOfEachMT5Loginid & {
+export type TDetailsOfEachMT5Loginid = TAdditionalDetailsOfEachMT5Loginid & {
display_login?: string;
white_label_links?: {
webtrader_url: string;
@@ -293,7 +275,6 @@ export type TDetailsOfEachMT5Loginid = DetailsOfEachMT5Loginid & {
selected_mt5_jurisdiction?: TOpenAccountTransferMeta &
TJurisdictionData & {
platform?: string;
+ product?: string;
};
-
- openFailedVerificationModal?: (from_account: string) => void;
};
diff --git a/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-bvi-contents.ts b/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-bvi-contents.ts
deleted file mode 100644
index 323315b0bec4..000000000000
--- a/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-bvi-contents.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-import { localize } from '@deriv/translations';
-import { TJurisdictionCardItems, TJurisdictionCardParams } from 'Components/props.types';
-
-export const getJurisdictionBviContents = ({
- toggleDynamicLeverage,
-}: TJurisdictionCardParams): TJurisdictionCardItems => ({
- is_over_header_available: false,
- header: localize('British Virgin Islands'),
- synthetic_contents: [
- {
- key: 'assets',
- title: localize('Assets'),
- description: localize(
- 'Forex (standard), stock indices, commodities, cryptocurrencies, stocks, ETFs, synthetic indices, basket indices and derived FX'
- ),
- title_indicators: {
- type: 'displayText',
- display_text: localize('210+'),
- display_text_skin_color: 'red-darker',
- },
- },
- {
- key: 'leverage',
- title: localize('Leverage'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('1:1000'),
- display_text_skin_color: 'yellow-light',
- },
- },
- {
- key: 'verifications',
- title: localize('Verifications'),
- title_indicators: { type: 'displayIcons' },
- clickable_description: [
- { type: 'link', text: localize('Learn more') },
- { type: 'text', text: localize('about required verifications.') },
- ],
- },
- {
- key: 'regulator',
- title: localize('Regulator/EDR'),
- description: localize('British Virgin Islands Financial Services Commission (License no. SIBA/L/18/1114)'),
- },
- ],
- financial_contents: [
- {
- key: 'assets',
- title: localize('Assets'),
- description: localize(
- 'Forex (standard/micro), stocks, stock indices, commodities, cryptocurrencies and ETFs'
- ),
- title_indicators: {
- type: 'displayText',
- display_text: localize('170+'),
- display_text_skin_color: 'red-light',
- },
- },
- {
- key: 'leverage',
- title: localize('Leverage'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('1:1000'),
- display_text_skin_color: 'yellow-light',
- },
- clickable_description: [
- {
- type: 'link',
- text: localize('Dynamic Leverage'),
- onClick: toggleDynamicLeverage,
- },
- ],
- },
- {
- key: 'spreadsFrom',
- title: localize('Spreads from'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('0.2 pips'),
- display_text_skin_color: 'violet-dark',
- },
- },
- {
- key: 'verifications',
- title: localize('Verifications'),
- title_indicators: { type: 'displayIcons' },
- clickable_description: [
- { type: 'link', text: localize('Learn more') },
- { type: 'text', text: localize('about required verifications.') },
- ],
- },
- {
- key: 'regulator',
- title: localize('Regulator/EDR'),
- description: localize('British Virgin Islands Financial Services Commission (License no. SIBA/L/18/1114)'),
- },
- ],
- synthetic_verification_docs: ['document_number', 'name_and_address'],
- financial_verification_docs: ['document_number', 'name_and_address'],
-});
diff --git a/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-contents.ts b/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-contents.ts
deleted file mode 100644
index 8f4e92bb6c48..000000000000
--- a/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-contents.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { TJurisdictionCardItems, TJurisdictionCardParams } from 'Components/props.types';
-import { getJurisdictionBviContents } from './jurisdiction-bvi-contents';
-import { getJurisdictionLabuanContents } from './jurisdiction-labuan-contents';
-import { getJurisdictionSvgContents } from './jurisdiction-svg-contents';
-import { getJurisdictionVanuatuContents } from './jurisdiction-vanuatu-contents';
-import { getJurisdictionMaltainvestContents } from './jurisdiction_maltainvest_contents';
-
-type TJurisdictionContent = {
- svg: TJurisdictionCardItems;
- vanuatu: TJurisdictionCardItems;
- labuan: TJurisdictionCardItems;
- maltainvest: TJurisdictionCardItems;
- bvi: TJurisdictionCardItems;
-};
-
-export const getJurisdictionContents = (params: TJurisdictionCardParams): TJurisdictionContent => ({
- svg: getJurisdictionSvgContents(params),
- bvi: getJurisdictionBviContents(params),
- vanuatu: getJurisdictionVanuatuContents(params),
- labuan: getJurisdictionLabuanContents(),
- maltainvest: getJurisdictionMaltainvestContents(),
-});
diff --git a/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-labuan-contents.ts b/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-labuan-contents.ts
deleted file mode 100644
index 8ba60e64f76a..000000000000
--- a/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-labuan-contents.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-import { localize } from '@deriv/translations';
-import { TJurisdictionCardItems } from 'Components/props.types';
-
-export const getJurisdictionLabuanContents = (): TJurisdictionCardItems => ({
- over_header: localize('Straight-through processing'),
- is_over_header_available: true,
- header: localize('Labuan'),
- synthetic_contents: [
- { key: 'assets', title: localize('Assets'), description: localize('Forex and Cryptocurrencies') },
- { key: 'leverage', title: localize('Leverage') },
- {
- key: 'spreadsFrom',
- title: localize('Spreads from'),
- },
- {
- key: 'verifications',
- title: localize('Verifications'),
- title_indicators: { type: 'displayIcons' },
- clickable_description: [
- { type: 'link', text: localize('Learn more') },
- { type: 'text', text: localize('about required verifications.') },
- ],
- },
- {
- key: 'regulator',
- title: localize('Regulator/EDR'),
- description: localize('Labuan Financial Services Authority (licence no. MB/18/0024)'),
- },
- ],
- financial_contents: [
- {
- key: 'assets',
- title: localize('Assets'),
- description: localize('Forex (standard/exotic) and cryptocurrencies'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('80+'),
- display_text_skin_color: 'red-dark',
- },
- },
- {
- key: 'leverage',
- title: localize('Leverage'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('1:100'),
- display_text_skin_color: 'yellow-dark',
- },
- },
- {
- key: 'spreadsFrom',
- title: localize('Spreads from'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('0.6 pips'),
- display_text_skin_color: 'violet-dark',
- },
- },
- {
- key: 'verifications',
- title: localize('Verifications'),
- title_indicators: { type: 'displayIcons' },
- clickable_description: [
- { type: 'link', text: localize('Learn more') },
- { type: 'text', text: localize('about required verifications.') },
- ],
- },
- {
- key: 'regulator',
- title: localize('Regulator/EDR'),
- description: localize('Labuan Financial Services Authority (licence no. MB/18/0024)'),
- },
- ],
- synthetic_verification_docs: ['document_number', 'name_and_address'],
- financial_verification_docs: ['document_number', 'name_and_address'],
-});
diff --git a/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-svg-contents.ts b/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-svg-contents.ts
deleted file mode 100644
index 4fc1d769b1b4..000000000000
--- a/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-svg-contents.ts
+++ /dev/null
@@ -1,135 +0,0 @@
-import { localize } from '@deriv/translations';
-import { TJurisdictionCardItems, TJurisdictionCardParams } from 'Components/props.types';
-
-export const getJurisdictionSvgContents = ({
- toggleDynamicLeverage,
-}: TJurisdictionCardParams): TJurisdictionCardItems => ({
- is_over_header_available: false,
- header: localize('St. Vincent & Grenadines'),
- synthetic_contents: [
- {
- key: 'assets',
- title: localize('Assets'),
- description: localize(
- 'Forex (standard), stock indices, commodities, cryptocurrencies, stocks, ETFs, synthetic indices, basket indices and derived FX'
- ),
- title_indicators: {
- type: 'displayText',
- display_text: localize('210+'),
- display_text_skin_color: 'red-darker',
- },
- },
- {
- key: 'leverage',
- title: localize('Leverage'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('1:1000'),
- display_text_skin_color: 'yellow-light',
- },
- },
- {
- key: 'verifications',
- title: localize('Verifications'),
- title_indicators: { type: 'displayIcons' },
- description: localize(
- 'You will need to submit proof of identity and address once you reach certain thresholds.'
- ),
- },
- {
- key: 'regulator',
- title: localize('Regulator/EDR'),
- description: localize('Deriv (SVG) LLC (company no. 273 LLC 2020)'),
- },
- ],
- financial_contents: [
- {
- key: 'assets',
- title: localize('Assets'),
- description: localize(
- 'Forex (standard/micro), stocks, stock indices, commodities, cryptocurrencies and ETFs'
- ),
- title_indicators: {
- type: 'displayText',
- display_text: localize('170+'),
- display_text_skin_color: 'red-light',
- },
- },
- {
- key: 'leverage',
- title: localize('Leverage'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('1:1000'),
- display_text_skin_color: 'yellow-light',
- },
- clickable_description: [
- {
- type: 'link',
- text: localize('Dynamic Leverage'),
- onClick: toggleDynamicLeverage,
- },
- ],
- },
- {
- key: 'spreadsFrom',
- title: localize('Spreads from'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('0.2 pips'),
- display_text_skin_color: 'violet-dark',
- },
- },
- {
- key: 'verifications',
- title: localize('Verifications'),
- title_indicators: { type: 'displayIcons' },
- description: localize(
- 'You will need to submit proof of identity and address once you reach certain thresholds.'
- ),
- },
- {
- key: 'regulator',
- title: localize('Regulator/EDR'),
- description: localize('Deriv (SVG) LLC (company no. 273 LLC 2020)'),
- },
- ],
- swapfree_contents: [
- {
- key: 'assets',
- title: localize('Assets'),
- description: localize(
- 'Forex, stocks, stock indices, commodities, cryptocurrencies, ETFs and synthetic indices'
- ),
- title_indicators: {
- type: 'displayText',
- display_text: localize('40+'),
- display_text_skin_color: 'red-darker',
- },
- },
- {
- key: 'leverage',
- title: localize('Leverage'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('1:1000'),
- display_text_skin_color: 'yellow-light',
- },
- },
- {
- key: 'verifications',
- title: localize('Verifications'),
- title_indicators: { type: 'displayIcons' },
- description: localize(
- 'You will need to submit proof of identity and address once you reach certain thresholds.'
- ),
- },
- {
- key: 'regulator',
- title: localize('Regulator/EDR'),
- description: localize('Deriv (SVG) LLC (company no. 273 LLC 2020)'),
- },
- ],
- synthetic_verification_docs: [],
- financial_verification_docs: [],
-});
diff --git a/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-vanuatu-contents.ts b/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-vanuatu-contents.ts
deleted file mode 100644
index ff107e5edd2b..000000000000
--- a/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-vanuatu-contents.ts
+++ /dev/null
@@ -1,101 +0,0 @@
-import { localize } from '@deriv/translations';
-import { TJurisdictionCardItems, TJurisdictionCardParams } from 'Components/props.types';
-
-export const getJurisdictionVanuatuContents = ({
- toggleDynamicLeverage,
-}: TJurisdictionCardParams): TJurisdictionCardItems => ({
- is_over_header_available: false,
- header: localize('Vanuatu'),
- synthetic_contents: [
- {
- key: 'assets',
- title: localize('Assets'),
- description: localize(
- 'Forex (standard), stock indices, commodities, cryptocurrencies, stocks, ETFs, synthetic indices, basket indices and derived FX'
- ),
- title_indicators: {
- type: 'displayText',
- display_text: localize('210+'),
- display_text_skin_color: 'red-darker',
- },
- },
- {
- key: 'leverage',
- title: localize('Leverage'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('1:1000'),
- display_text_skin_color: 'yellow-light',
- },
- },
- {
- key: 'verifications',
- title: localize('Verifications'),
- title_indicators: { type: 'displayIcons' },
- clickable_description: [
- { type: 'link', text: localize('Learn more') },
- { type: 'text', text: localize('about required verifications.') },
- ],
- },
- {
- key: 'regulator',
- title: localize('Regulator/EDR'),
- description: localize('Vanuatu Financial Services Commission'),
- },
- ],
- financial_contents: [
- {
- key: 'assets',
- title: localize('Assets'),
- description: localize(
- 'Forex (standard/micro), stocks, stock indices, commodities, cryptocurrencies and ETFs'
- ),
- title_indicators: {
- type: 'displayText',
- display_text: localize('170+'),
- display_text_skin_color: 'red-light',
- },
- },
- {
- key: 'leverage',
- title: localize('Leverage'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('1:1000'),
- display_text_skin_color: 'yellow-light',
- },
- clickable_description: [
- {
- type: 'link',
- text: localize('Dynamic Leverage'),
- onClick: toggleDynamicLeverage,
- },
- ],
- },
- {
- key: 'spreadsFrom',
- title: localize('Spreads from'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('0.2 pips'),
- display_text_skin_color: 'violet-dark',
- },
- },
- {
- key: 'verifications',
- title: localize('Verifications'),
- title_indicators: { type: 'displayIcons' },
- clickable_description: [
- { type: 'link', text: localize('Learn more') },
- { type: 'text', text: localize('about required verifications.') },
- ],
- },
- {
- key: 'regulator',
- title: localize('Regulator/EDR'),
- description: localize('Vanuatu Financial Services Commission'),
- },
- ],
- synthetic_verification_docs: ['document_number', 'name_and_address'],
- financial_verification_docs: ['document_number', 'name_and_address'],
-});
diff --git a/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-verification-contents.ts b/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-verification-contents.ts
deleted file mode 100644
index 3bad30e99bc6..000000000000
--- a/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction-verification-contents.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import { localize } from '@deriv/translations';
-import { TJurisdictionVerificationItems, TJurisdictionVerificationStatus } from 'Components/props.types';
-
-type TJurisdictionVerificationContents = {
- short_description: string;
- required_verification_docs: TJurisdictionVerificationItems;
- status_references: Array;
-};
-
-export const jurisdictionVerificationContents = (): TJurisdictionVerificationContents => ({
- short_description: localize('We need you to submit these in order to get this account:'),
- required_verification_docs: {
- document_number: {
- icon: 'IcDocumentNumberVerification',
- text: localize("Document number (e.g. identity card, passport, driver's license)"),
- },
- selfie: {
- icon: 'IcSelfieVerification',
- text: localize('A selfie of yourself.'),
- },
- identity_document: {
- icon: 'IcIdentityDocumentVerification',
- text: localize("A copy of your identity document (e.g. identity card, passport, driver's license)"),
- },
- name_and_address: {
- icon: 'IcNameAndAddressVerification',
- text: localize(
- 'A recent utility bill (e.g. electricity, water or gas) or recent bank statement or government-issued letter with your name and address.'
- ),
- },
- },
- status_references: [
- {
- icon: 'IcVerificationStatusYellow',
- text: localize('Verification in review.'),
- color: 'yellow',
- },
- {
- icon: 'IcVerificationStatusRed',
- text: localize('Verification failed. Resubmit your details.'),
- color: 'red',
- },
- { icon: 'IcVerificationStatusGreen', text: localize('Verification successful.'), color: 'green' },
- ],
-});
diff --git a/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction_maltainvest_contents.ts b/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction_maltainvest_contents.ts
deleted file mode 100644
index 38c0e38e6810..000000000000
--- a/packages/cfd/src/Constants/jurisdiction-contents/jurisdiction_maltainvest_contents.ts
+++ /dev/null
@@ -1,96 +0,0 @@
-import { localize } from '@deriv/translations';
-import { TJurisdictionCardItems } from 'Components/props.types';
-
-export const getJurisdictionMaltainvestContents = (): TJurisdictionCardItems => ({
- is_over_header_available: false,
- header: localize('Malta'),
- synthetic_contents: [
- {
- key: 'assets',
- title: localize('Assets'),
- description: localize('Synthetics, Forex, Stocks, Stock indices, Commodities, and Cryptocurrencies'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('140+'),
- display_text_skin_color: 'red-light',
- },
- },
- {
- key: 'leverage',
- title: localize('Leverage'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('1:30'),
- display_text_skin_color: 'brown-dark',
- },
- },
- {
- key: 'spreadsFrom',
- title: localize('Spreads from'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('0.5 pips'),
- display_text_skin_color: 'violet-dark',
- },
- },
- {
- key: 'verifications',
- title: localize('Verifications'),
- clickable_description: [
- { type: 'link', text: localize('Learn more') },
- { type: 'text', text: localize('about required verifications.') },
- ],
- },
- {
- key: 'regulator',
- title: localize('Regulator/EDR'),
- description: localize('Malta Financial Services Authority (MFSA) (licence no. IS/70156)'),
- },
- ],
- financial_contents: [
- {
- key: 'assets',
- title: localize('Assets'),
- description: localize('Forex, stocks, stock indices, commodities, cryptocurrencies and synthetic indices.'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('140+'),
- display_text_skin_color: 'red-light',
- },
- },
- {
- key: 'leverage',
- title: localize('Leverage'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('1:30'),
- display_text_skin_color: 'brown-dark',
- },
- },
- {
- key: 'spreadsFrom',
- title: localize('Spreads from'),
- title_indicators: {
- type: 'displayText',
- display_text: localize('0.5 pips'),
- display_text_skin_color: 'violet-dark',
- },
- },
- {
- key: 'verifications',
- title: localize('Verifications'),
- title_indicators: { type: 'displayIcons' },
- clickable_description: [
- { type: 'link', text: localize('Learn more') },
- { type: 'text', text: localize('about required verifications.') },
- ],
- },
- {
- key: 'regulator',
- title: localize('Regulator/EDR'),
- description: localize('Malta Financial Services Authority (MFSA) (licence no. IS/70156)'),
- },
- ],
- synthetic_verification_docs: ['selfie', 'identity_document', 'name_and_address'],
- financial_verification_docs: ['selfie', 'identity_document', 'name_and_address'],
-});
diff --git a/packages/cfd/src/Containers/__tests__/cfd-financial-stp-real-account-signup.spec.js b/packages/cfd/src/Containers/__tests__/cfd-financial-stp-real-account-signup.spec.js
deleted file mode 100644
index d98092f8f6e8..000000000000
--- a/packages/cfd/src/Containers/__tests__/cfd-financial-stp-real-account-signup.spec.js
+++ /dev/null
@@ -1,301 +0,0 @@
-import React from 'react';
-import { render, screen } from '@testing-library/react';
-import CFDFinancialStpRealAccountSignup from '../cfd-financial-stp-real-account-signup';
-import CFDProviders from '../../cfd-providers';
-import { mockStore } from '@deriv/stores';
-import { getAuthenticationStatusInfo } from '@deriv/shared';
-
-jest.mock('@deriv/account', () => ({
- ...jest.requireActual('@deriv/account'),
- FormSubHeader: () => FormSubHeader
,
-}));
-
-const MockComponent = ({ prevStep, nextStep }) => (
-
- Prev Step
- nextStep(0, {})}>Next Step
-
-);
-
-jest.mock('../../Components/cfd-poa', () =>
- jest.fn(({ onCancel, onSubmit }) => (
-
- CFDPOA
-
-
- ))
-);
-
-jest.mock('../../Components/cfd-poi', () =>
- jest.fn(({ onCancel, onSubmit }) => (
-
- CFDPOI
-
-
- ))
-);
-
-jest.mock('@deriv/shared', () => ({
- ...jest.requireActual('@deriv/shared'),
- getAuthenticationStatusInfo: jest.fn().mockReturnValue({}),
-}));
-
-const getByTextFn = (text, should_be) => {
- if (should_be) {
- expect(screen.getByText(text)).toBeInTheDocument();
- } else {
- expect(screen.queryByText(text)).not.toBeInTheDocument();
- }
-};
-
-const testAllStepsFn = (steps, step_no) => {
- steps.map((step, index) => {
- if (index === step_no) {
- getByTextFn(step.body, true);
- } else {
- getByTextFn(step.body, false);
- }
- });
-};
-
-const steps = [
- {
- body: 'CFDPOI',
- },
- {
- body: 'CFDPOA',
- },
-];
-
-describe(' ', () => {
- let modal_root_el;
-
- beforeAll(() => {
- modal_root_el = document.createElement('div');
- modal_root_el.setAttribute('id', 'modal_root');
- document.body.appendChild(modal_root_el);
- });
-
- afterAll(() => {
- document.body.removeChild(modal_root_el);
- });
-
- afterEach(() => {
- jest.clearAllMocks();
- });
-
- const verified_jurisdiction = {
- bvi: 1,
- labuan: 1,
- maltainvest: 0,
- svg: 1,
- vanuatu: 0,
- virtual: 0,
- };
-
- let mockRootStore = {
- notifications: {
- addNotificationByKey: jest.fn(),
- refreshNotifications: jest.fn(),
- removeNotificationByKey: jest.fn(),
- removeNotificationMessage: jest.fn(),
- },
- client: {
- account_settings: {
- account_opening_reason: '',
- address_city: 'MUDGEERABA',
- address_line_1: "29 Ross Street, .'",
- address_line_2: ".'",
- address_postcode: '111',
- address_state: '',
- allow_copiers: 0,
- citizen: '',
- client_tnc_status: 'Version 4.2.0 2020-08-07',
- country: 'Singapore',
- country_code: 'sg',
- date_of_birth: 984960000,
- email: 'mock@gmail.com',
- email_consent: 1,
- feature_flag: {
- wallet: 0,
- },
- first_name: 'mahdiyeh',
- has_secret_answer: 1,
- immutable_fields: ['residence'],
- is_authenticated_payment_agent: 0,
- last_name: 'am',
- non_pep_declaration: 1,
- phone: '+651213456',
- place_of_birth: null,
- preferred_language: 'EN',
- request_professional_status: 0,
- residence: 'Singapore',
- salutation: '',
- tax_identification_number: null,
- tax_residence: null,
- user_hash: '823341c18bfccb391b6bb5d77ab7e6a83991f82669c1ba4e5b01dbd2fd71c7fe',
- },
- account_status: {
- authentication: {
- document: {
- verified_jurisdiction,
- status: 'none',
- },
- attempts: {
- latest: {
- service: 'idv',
- },
- },
- },
- },
- authentication_status: {
- document_status: 'none',
- identity_status: 'none',
- },
- email: 'mock@gmail.com',
- is_fully_authenticated: true,
- landing_company: {
- config: {
- tax_details_required: 1,
- tin_format: ['^\\d{15}$'],
- tin_format_description: '999999999999999',
- },
- dxtrade_financial_company: {},
- dxtrade_gaming_company: {},
- financial_company: {},
- gaming_company: {},
- id: 'id',
- minimum_age: 18,
- mt_financial_company: {},
- mt_gaming_company: {},
- name: 'Indonesia',
- virtual_company: 'virtual',
- },
- residence_list: [
- {
- identity: {
- services: {
- idv: {
- documents_supported: {},
- has_visual_sample: 0,
- is_country_supported: 0,
- },
- onfido: {
- documents_supported: {
- passport: {
- display_name: 'Passport',
- },
- },
- is_country_supported: 0,
- },
- },
- },
- phone_idd: '93',
- text: 'Afghanistan',
- value: 'af',
- },
- ],
- fetchStatesList: jest.fn(),
- states_list: {
- text: 'Central Singapore',
- value: '01',
- },
- },
- modules: {
- cfd: {
- storeProofOfAddress: jest.fn(),
- },
- },
- jurisdiction_selected_shortcode: 'svg',
- };
-
- it('should render CFDFinancialStpRealAccountSignup component', () => {
- render( , {
- wrapper: ({ children }) => {children} ,
- });
-
- expect(screen.getByTestId('dt_cfd_financial_stp_modal_body')).toBeInTheDocument();
- });
-
- it('should render properly for the first step content', () => {
- getAuthenticationStatusInfo.mockReturnValueOnce({ need_poi_for_bvi_labuan_vanuatu: true });
- render( , {
- wrapper: ({ children }) => {children} ,
- });
-
- testAllStepsFn(steps, 0);
- });
-
- it('should render properly for the second step content', () => {
- getAuthenticationStatusInfo.mockReturnValueOnce({ poa_resubmit_for_labuan: true });
- const { getByTestId } = render( , {
- wrapper: ({ children }) => {children} ,
- });
-
- testAllStepsFn(steps, 1);
- });
-
- it('should check for POI status when Jurisdiction is Vanuatu or maltainvest', () => {
- const new_mock_store = {
- ...mockRootStore,
- modules: {
- ...mockRootStore.modules,
- cfd: {
- ...mockRootStore.modules.cfd,
- jurisdiction_selected_shortcode: 'vanuatu',
- },
- },
- };
-
- getAuthenticationStatusInfo.mockReturnValueOnce({ need_poi_for_bvi_labuan_vanuatu: true });
-
- render( , {
- wrapper: ({ children }) => {children} ,
- });
- testAllStepsFn(steps, 0);
- });
-
- it('should check for POA status when Jurisdiction is Labuan and resubmit status is set to true', () => {
- const verified_jurisdiction = {
- bvi: 1,
- labuan: 0,
- maltainvest: 0,
- svg: 1,
- vanuatu: 0,
- virtual: 0,
- };
- const new_mock_store = {
- ...mockRootStore,
- client: {
- ...mockRootStore.client,
- account_status: {
- authentication: {
- document: {
- verified_jurisdiction,
- status: 'none',
- },
- attempts: {
- latest: {
- service: 'idv',
- },
- },
- },
- },
- },
- modules: {
- ...mockRootStore.modules,
- cfd: {
- ...mockRootStore.modules.cfd,
- jurisdiction_selected_shortcode: 'labuan',
- },
- },
- };
-
- getAuthenticationStatusInfo.mockReturnValueOnce({ need_poi_for_maltainvest: true });
-
- render( , {
- wrapper: ({ children }) => {children} ,
- });
- testAllStepsFn(steps, 1);
- });
-});
diff --git a/packages/cfd/src/Containers/__tests__/cfd-password-modal.spec.js b/packages/cfd/src/Containers/__tests__/cfd-password-modal.spec.js
index 622f292a67c5..2b7b4ddf1262 100644
--- a/packages/cfd/src/Containers/__tests__/cfd-password-modal.spec.js
+++ b/packages/cfd/src/Containers/__tests__/cfd-password-modal.spec.js
@@ -114,14 +114,18 @@ describe(' ', () => {
jest.clearAllMocks();
});
- it('should render create Password modal when valid conditions are met', async () => {
+ it('should render create Password modal when valid conditions are met for dxtrade account', async () => {
const store = mockStore(mockRootStore);
+ const props = {
+ ...mock_props,
+ platform: 'dxtrade',
+ };
store.client.account_status = { status: ['mt5_password_not_set', 'dxtrade_password_not_set'] };
render(
-
+
,
{
wrapper: ({ children }) => {children} ,
@@ -321,7 +325,7 @@ describe(' ', () => {
}
);
- fireEvent.click(await screen.findByRole('button', { name: /ok/i }));
+ fireEvent.click(await screen.findByRole('button', { name: /Transfer now/i }));
await waitFor(() => {
expect(mockSetCFDSuccessDialog).toHaveBeenCalledWith(false);
@@ -494,7 +498,7 @@ describe(' ', () => {
}
);
fireEvent.change(await screen.findByTestId('dt_mt5_password'), { target: { value: user_input } });
- fireEvent.click(await screen.findByRole('button', { name: 'Create Deriv MT5 password' }));
+ fireEvent.click(await screen.findByRole('button', { name: 'Create account' }));
await waitFor(() => {
expect(mockSubmitMt5Password).toHaveBeenCalled();
diff --git a/packages/cfd/src/Containers/__tests__/dmt5-trade-modal.spec.tsx b/packages/cfd/src/Containers/__tests__/dmt5-trade-modal.spec.tsx
index db81757422ea..01bb3c903c35 100644
--- a/packages/cfd/src/Containers/__tests__/dmt5-trade-modal.spec.tsx
+++ b/packages/cfd/src/Containers/__tests__/dmt5-trade-modal.spec.tsx
@@ -120,7 +120,7 @@ describe(' ', () => {
};
renderComponent({ props: new_mock_props });
- expect(screen.queryByText(/Pending verification/)).not.toBeInTheDocument();
+ expect(screen.queryByText(/In review/)).not.toBeInTheDocument();
expect(screen.queryByText(/No new positions/)).not.toBeInTheDocument();
expect(screen.queryByText(/Account closed/)).not.toBeInTheDocument();
});
@@ -134,7 +134,7 @@ describe(' ', () => {
};
renderComponent({ props: new_mock_props });
- expect(screen.queryByText(/Pending verification/)).not.toBeInTheDocument();
+ expect(screen.queryByText(/In review/)).not.toBeInTheDocument();
expect(screen.queryByText(/No new positions/)).not.toBeInTheDocument();
expect(screen.queryByText(/Account closed/)).not.toBeInTheDocument();
});
diff --git a/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts-card.spec.tsx b/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts-card.spec.tsx
index ae757c4bd6bb..3394176bf0ea 100644
--- a/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts-card.spec.tsx
+++ b/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts-card.spec.tsx
@@ -25,7 +25,6 @@ describe(' ', () => {
setAccountType: jest.fn(),
setJurisdictionSelectedShortcode: jest.fn(),
enableCFDPasswordModal: jest.fn(),
- toggleCFDVerificationModal: jest.fn(),
},
},
});
@@ -50,20 +49,6 @@ describe(' ', () => {
expect(screen.queryByText(/New!/i)).not.toBeInTheDocument();
});
- it('should render the "Boom 300 and Crash 300 Index" for EU user', () => {
- mocked_props.is_eu_user = true;
- mocked_props.is_demo = false;
-
- const wrapper = ({ children }: { children: JSX.Element }) => (
- {children}
- );
-
- render( , { wrapper });
-
- expect(screen.queryByText(/New!/i)).not.toBeInTheDocument();
- expect(screen.getByText(/Boom 300 and Crash 300 Index/i)).toBeInTheDocument();
- });
-
it('should renders the component and not render the "New!" banner for MT5 demo', () => {
mocked_props.is_eu_user = false;
mocked_props.is_demo = true;
diff --git a/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts-description.spec.tsx b/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts-description.spec.tsx
index 383633b84489..17bb86935567 100644
--- a/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts-description.spec.tsx
+++ b/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts-description.spec.tsx
@@ -9,127 +9,114 @@ describe(' ', () => {
selected_region: 'Non-EU',
},
});
- const mocked_props = {
- trading_platforms: {
- market_type: 'gaming',
- shortcode: 'svg',
- },
- is_demo: false,
- };
- const assertContent = (
- leverageDescription: string,
- spread: string,
- spreadDescription: string,
- counterpartyCompanyDescription: string,
- jurisdictionDescription: string
- ) => {
- expect(screen.getByText(leverageDescription)).toBeInTheDocument();
- expect(screen.getByText(spread)).toBeInTheDocument();
- expect(screen.getByText(spreadDescription)).toBeInTheDocument();
- expect(screen.getByText(counterpartyCompanyDescription)).toBeInTheDocument();
- expect(screen.getByText(jurisdictionDescription)).toBeInTheDocument();
- };
const wrapper = ({ children }: { children: JSX.Element }) => {children} ;
- it('should render CFDCompareAccountsDescription component on default props', () => {
- render( , { wrapper });
- });
-
- it('should render content for gaming market type with market type svg', () => {
+ it('should render content for standard svg', () => {
+ const mocked_props = {
+ trading_platforms: {
+ market_type: 'gaming',
+ shortcode: 'svg',
+ instruments: ['Forex', 'Synthetic Indices', 'Stocks', 'Commodities', 'Cryptocurrencies'],
+ product_details: { max_leverage: '1:1000', min_spread: '0' },
+ platform: 'mt5',
+ product: 'standard',
+ },
+ is_demo: false,
+ };
render( , { wrapper });
- assertContent('Maximum leverage', '0.1 pips', 'Spreads from', 'Counterparty company', 'Jurisdiction');
expect(screen.getByText('Up to 1:1000')).toBeInTheDocument();
- expect(screen.getByText('Deriv (SVG) LLC')).toBeInTheDocument();
- expect(screen.getByText('St. Vincent & Grenadines')).toBeInTheDocument();
+ expect(screen.getByText('0 pips')).toBeInTheDocument();
});
- it('should render content for gaming market type with vanuatu shortcode', () => {
- mocked_props.trading_platforms.shortcode = 'vanuatu';
+ it('should render content for swapfree', () => {
+ const mocked_props = {
+ trading_platforms: {
+ market_type: 'all',
+ shortcode: 'svg',
+ instruments: ['Forex', 'Synthetic Indices', 'Stocks', 'Commodities', 'Cryptocurrencies'],
+ product_details: { max_leverage: '1:1111000', min_spread: '0.44' },
+ platform: 'mt5',
+ product: 'swap_free',
+ },
+ is_demo: false,
+ };
render( , { wrapper });
- assertContent('Maximum leverage', '0.1 pips', 'Spreads from', 'Counterparty company', 'Jurisdiction');
- expect(screen.getByText('Up to 1:1000')).toBeInTheDocument();
- expect(screen.getByText('Deriv (V) Ltd')).toBeInTheDocument();
- expect(screen.getByText('Vanuatu')).toBeInTheDocument();
+ expect(screen.getByText('Up to 1:1111000')).toBeInTheDocument();
+ expect(screen.getByText('0.44 pips')).toBeInTheDocument();
});
- it('should render content for all market type with svg shortcode', () => {
- mocked_props.trading_platforms.market_type = 'all';
+ it('should render content for financial', () => {
+ const mocked_props = {
+ trading_platforms: {
+ market_type: 'financial',
+ shortcode: 'labuan',
+ instruments: ['Forex', 'Cryptocurrencies'],
+ product_details: { max_leverage: '1:1000', min_spread: '0.2' },
+ platform: 'mt5',
+ product: 'standard',
+ },
+ is_demo: false,
+ };
render( , { wrapper });
- assertContent('Maximum leverage', '0.5 pips', 'Spreads from', 'Counterparty company', 'Jurisdiction');
- expect(screen.getByText('Up to 1:1000')).toBeInTheDocument();
- expect(screen.getByText('Deriv (SVG) LLC')).toBeInTheDocument();
- expect(screen.getByText('St. Vincent & Grenadines')).toBeInTheDocument();
- expect(screen.getByText('Financial Commission')).toBeInTheDocument();
- expect(screen.getByText('Regulator/External dispute resolution')).toBeInTheDocument();
- });
-
- it('should render content for financial market type with svg shortcode', () => {
- mocked_props.trading_platforms.market_type = 'financial';
- mocked_props.trading_platforms.shortcode = 'svg';
-
- render( , { wrapper });
- assertContent('Maximum leverage', '0.2 pips', 'Spreads from', 'Counterparty company', 'Jurisdiction');
- expect(screen.getByText('Up to 1:1000')).toBeInTheDocument();
- expect(screen.getByText('Deriv (SVG) LLC')).toBeInTheDocument();
- expect(screen.getByText('St. Vincent & Grenadines')).toBeInTheDocument();
- expect(screen.getByText('Financial Commission')).toBeInTheDocument();
- expect(screen.getByText('Regulator/External dispute resolution')).toBeInTheDocument();
- });
-
- it('should render content for financial market type with vanuatu shortcode', () => {
- mocked_props.trading_platforms.market_type = 'financial';
- mocked_props.trading_platforms.shortcode = 'vanuatu';
- render( , { wrapper });
- assertContent('Maximum leverage', '0.2 pips', 'Spreads from', 'Counterparty company', 'Jurisdiction');
expect(screen.getByText('Up to 1:1000')).toBeInTheDocument();
- expect(screen.getByText('Deriv (V) Ltd')).toBeInTheDocument();
- expect(screen.getByText('Vanuatu')).toBeInTheDocument();
- expect(screen.getByText('Vanuatu Financial Services Commission')).toBeInTheDocument();
- expect(screen.getByText('Regulator/External dispute resolution')).toBeInTheDocument();
- });
-
- it('should render content for financial market type with labuan shortcode', () => {
- mocked_props.trading_platforms.market_type = 'financial';
- mocked_props.trading_platforms.shortcode = 'labuan';
-
- render( , { wrapper });
- assertContent('Maximum leverage', '0.6 pips', 'Spreads from', 'Counterparty company', 'Jurisdiction');
- expect(screen.getByText('Up to 1:100')).toBeInTheDocument();
- expect(screen.getByText('Deriv (FX) Ltd')).toBeInTheDocument();
- expect(screen.getByText('Labuan')).toBeInTheDocument();
- expect(screen.getByText('Labuan Financial Services Authority')).toBeInTheDocument();
- expect(screen.getByText('(licence no. MB/18/0024)')).toBeInTheDocument();
- expect(screen.getByText('Regulator/External dispute resolution')).toBeInTheDocument();
+ expect(screen.getByText('0.2 pips')).toBeInTheDocument();
});
it('should render content for financial market type with maltainvest shortcode ', () => {
- mocked_props.trading_platforms.market_type = 'financial';
- mocked_props.trading_platforms.shortcode = 'maltainvest';
-
- render( , { wrapper });
- assertContent('Maximum leverage', '0.5 pips', 'Spreads from', 'Counterparty company', 'Jurisdiction');
+ const mock_store = mockStore({
+ traders_hub: {
+ selected_region: 'EU',
+ },
+ });
+
+ const mocked_props = {
+ trading_platforms: {
+ market_type: 'financial',
+ shortcode: 'maltainvest',
+ instruments: ['Forex', 'Cryptocurrencies'],
+ product_details: { max_leverage: '1:30', min_spread: '0.5' },
+ platform: 'mt5',
+ product: 'financial',
+ },
+ is_demo: false,
+ };
+
+ render(
+
+
+
+ );
expect(screen.getByText('Up to 1:30')).toBeInTheDocument();
- expect(screen.getByText('Deriv Investments (Europe) Limited')).toBeInTheDocument();
- expect(screen.getByText('Malta')).toBeInTheDocument();
- expect(screen.getByText('Financial Commission')).toBeInTheDocument();
- expect(
- screen.getByText('Regulated by the Malta Financial Services Authority (MFSA) (licence no. IS/70156)')
- ).toBeInTheDocument();
+ expect(screen.getByText('Leverage')).toBeInTheDocument();
});
- it('should render demo content for gaming market type with market type svg', () => {
- mocked_props.trading_platforms.market_type = 'financial';
- mocked_props.trading_platforms.shortcode = 'svg';
- mocked_props.is_demo = true;
-
- render( , { wrapper });
- expect(screen.getByText('Up to 1:1000')).toBeInTheDocument();
- expect(screen.getByText('Maximum leverage')).toBeInTheDocument();
- expect(screen.getByText('0.2 pips')).toBeInTheDocument();
- expect(screen.getByText('Spreads from')).toBeInTheDocument();
+ it('should render content for ctrader ', () => {
+ const mock_store = mockStore({
+ traders_hub: {
+ selected_region: 'NON-EU',
+ },
+ });
+
+ const mocked_props = {
+ trading_platforms: {
+ market_type: 'financial',
+ shortcode: 'maltainvest',
+ instruments: ['Forex', 'Cryptocurrencies'],
+ product_details: { max_leverage: '1:30', min_spread: '0.5' },
+ platform: 'ctrader',
+ },
+ is_demo: false,
+ };
+ render(
+
+
+
+ );
+ expect(screen.getByText('Up to 1:30')).toBeInTheDocument();
+ expect(screen.getByText('Leverage')).toBeInTheDocument();
});
});
diff --git a/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts-platform-label.spec.tsx b/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts-platform-label.spec.tsx
index ec754603f315..b808ad63682e 100644
--- a/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts-platform-label.spec.tsx
+++ b/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts-platform-label.spec.tsx
@@ -17,6 +17,11 @@ describe(' ', () => {
it('should renders Deriv X platform label', () => {
mocked_props.trading_platforms.platform = 'dxtrade';
render( );
- expect(screen.getByText(platformsHeaderLabel.other_cfds)).toBeInTheDocument();
+ expect(screen.getByText(platformsHeaderLabel.derivx)).toBeInTheDocument();
+ });
+ it('should renders ctrader platform label', () => {
+ mocked_props.trading_platforms.platform = 'ctrader';
+ render( );
+ expect(screen.getByText(platformsHeaderLabel.ctrader)).toBeInTheDocument();
});
});
diff --git a/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts-title-icon.spec.tsx b/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts-title-icon.spec.tsx
index 61e40e7fb639..be78c5baf695 100644
--- a/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts-title-icon.spec.tsx
+++ b/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts-title-icon.spec.tsx
@@ -5,139 +5,152 @@ import CFDCompareAccountsTitleIcon from '../cfd-compare-accounts-title-icon';
jest.mock('../../../Assets/svgs/trading-platform', () => jest.fn(() => Mocked Icon
));
const mocked_props = {
- trading_platforms: {
- platform: 'mt5',
- market_type: 'gaming',
- shortcode: 'svg',
- product: '',
- },
+ trading_platforms: {},
is_eu_user: false,
is_demo: false,
};
describe(' ', () => {
- test('should render correct title for synthetic_svg market type and shortcode', () => {
+ test('should render correct title for Standard product type', () => {
+ mocked_props.trading_platforms = {
+ platform: 'mt5',
+ market_type: 'gaming',
+ shortcode: 'svg',
+ product: 'standard',
+ };
+ render( );
+ expect(screen.getByText('Standard')).toBeInTheDocument();
+ });
+
+ test('should render correct title for financial_stp product type', () => {
+ mocked_props.trading_platforms = {
+ platform: 'mt5',
+ market_type: 'financial',
+ shortcode: 'labuan',
+ product: 'stp',
+ };
+ mocked_props.is_eu_user = false;
render( );
- expect(screen.getByText('Standard - SVG')).toBeInTheDocument();
+ expect(screen.getByText('Financial - STP')).toBeInTheDocument();
});
- test('should render correct title for synthetic_bvi market type and shortcode', () => {
- mocked_props.trading_platforms.shortcode = 'bvi';
+ test('should render correct title for financial product type', () => {
+ mocked_props.trading_platforms = {
+ platform: 'mt5',
+ market_type: 'financial',
+ shortcode: 'vanuatu',
+ product: 'financial',
+ };
render( );
- expect(screen.getByText('Standard - BVI')).toBeInTheDocument();
+ expect(screen.getByText('Financial')).toBeInTheDocument();
});
- test('should render correct title for synthetic_vanuatu market type and shortcode', () => {
- mocked_props.trading_platforms.shortcode = 'vanuatu';
+ test('should render correct title for Swap-Free product type', () => {
+ mocked_props.trading_platforms = {
+ platform: 'mt5',
+ market_type: 'all',
+ shortcode: 'svg',
+ product: 'swap_free',
+ };
render( );
- expect(screen.getByText('Standard - Vanuatu')).toBeInTheDocument();
+ expect(screen.getByText('Swap-Free')).toBeInTheDocument();
});
- test('should render correct title for financial_labuan market type and shortcode', () => {
- mocked_props.trading_platforms.platform = 'mt5';
- mocked_props.trading_platforms.market_type = 'financial';
- mocked_props.trading_platforms.shortcode = 'labuan';
- render( );
- expect(screen.getByText('Financial - Labuan')).toBeInTheDocument();
- });
-
- test('should render correct title for financial_vanuatu market type and shortcode', () => {
- mocked_props.trading_platforms.platform = 'mt5';
- mocked_props.trading_platforms.market_type = 'financial';
- mocked_props.trading_platforms.shortcode = 'vanuatu';
- render( );
- expect(screen.getByText('Financial - Vanuatu')).toBeInTheDocument();
- });
+ test('should render correct title for Zero Spread product type', () => {
+ mocked_props.trading_platforms = {
+ platform: 'mt5',
+ market_type: 'all',
+ shortcode: 'bvi',
+ product: 'zero_spread',
+ };
- test('should render correct title for financial_bvi market type and shortcode', () => {
- mocked_props.trading_platforms.platform = 'mt5';
- mocked_props.trading_platforms.market_type = 'financial';
- mocked_props.trading_platforms.shortcode = 'bvi';
render( );
- expect(screen.getByText('Financial - BVI')).toBeInTheDocument();
+ expect(screen.getByText('Zero Spread')).toBeInTheDocument();
});
- test('should render correct title for Swap-Free market type and shortcode', () => {
- mocked_props.trading_platforms.platform = 'mt5';
- mocked_props.trading_platforms.market_type = 'all';
- mocked_props.trading_platforms.shortcode = 'svg';
- mocked_props.trading_platforms.product = 'swap_free';
- render( );
- expect(screen.getByText('Swap-Free - SVG')).toBeInTheDocument();
- });
+ test('should render correct title for Deriv X product type', () => {
+ mocked_props.trading_platforms = {
+ platform: 'dxtrade',
+ market_type: 'all',
+ shortcode: 'svg',
+ };
- test('should render correct title for Zero Spread market type and shortcode', () => {
- mocked_props.trading_platforms.platform = 'mt5';
- mocked_props.trading_platforms.market_type = 'all';
- mocked_props.trading_platforms.shortcode = 'bvi';
- mocked_props.trading_platforms.product = 'zero_spread';
- render( );
- expect(screen.getByText('Zero Spread - BVI')).toBeInTheDocument();
- });
-
- test('should render correct title for Deriv X market type and shortcode', () => {
- mocked_props.trading_platforms.platform = 'dxtrade';
- mocked_props.trading_platforms.market_type = 'all';
- mocked_props.trading_platforms.shortcode = 'svg';
render( );
expect(screen.getByText('Deriv X')).toBeInTheDocument();
});
test('should render correct title for EU Clients', () => {
- mocked_props.trading_platforms.platform = 'mt5';
- mocked_props.trading_platforms.market_type = 'financial';
- mocked_props.trading_platforms.shortcode = 'svg';
+ mocked_props.trading_platforms = {
+ platform: 'mt5',
+ market_type: 'financial',
+ shortcode: 'maltainvest',
+ product: 'financial',
+ };
mocked_props.is_eu_user = true;
render( );
expect(screen.getByText('CFDs')).toBeInTheDocument();
});
- test('should render correct title for gaming market type and shortcode demo account', () => {
- mocked_props.trading_platforms.platform = 'mt5';
- mocked_props.trading_platforms.market_type = 'gaming';
- mocked_props.trading_platforms.shortcode = 'svg';
+ test('should render correct title for standard product type in demo account', () => {
+ mocked_props.trading_platforms = {
+ platform: 'mt5',
+ market_type: 'gaming',
+ shortcode: 'svg',
+ product: 'standard',
+ };
mocked_props.is_demo = true;
mocked_props.is_eu_user = false;
render( );
expect(screen.getByText('Standard Demo')).toBeInTheDocument();
});
- test('should render correct title for financial market type and shortcode demo account', () => {
- mocked_props.trading_platforms.platform = 'mt5';
- mocked_props.trading_platforms.market_type = 'financial';
- mocked_props.trading_platforms.shortcode = 'svg';
+ test('should render correct title for financial product in demo account', () => {
+ mocked_props.trading_platforms = {
+ platform: 'mt5',
+ market_type: 'financial',
+ shortcode: 'svg',
+ product: 'financial',
+ };
+
mocked_props.is_demo = true;
mocked_props.is_eu_user = false;
render( );
expect(screen.getByText('Financial Demo')).toBeInTheDocument();
});
- test('should render correct title for Swap-Free with correct market type and shortcode demo account', () => {
- mocked_props.trading_platforms.platform = 'mt5';
- mocked_props.trading_platforms.market_type = 'all';
- mocked_props.trading_platforms.shortcode = 'svg';
- mocked_props.trading_platforms.product = 'swap_free';
+ test('should render correct title for Swap-Free with correct product type demo account', () => {
+ mocked_props.trading_platforms = {
+ platform: 'mt5',
+ market_type: 'all',
+ shortcode: 'svg',
+ product: 'swap_free',
+ };
mocked_props.is_demo = true;
mocked_props.is_eu_user = false;
render( );
expect(screen.getByText('Swap-Free Demo')).toBeInTheDocument();
});
- test('should render correct title for Zero Spread with correct market type and shortcode demo account', () => {
- mocked_props.trading_platforms.platform = 'mt5';
- mocked_props.trading_platforms.market_type = 'all';
- mocked_props.trading_platforms.shortcode = 'bvi';
- mocked_props.trading_platforms.product = 'zero_spread';
+ test('should render correct title for Zero Spread with correct product type demo account', () => {
+ mocked_props.trading_platforms = {
+ platform: 'mt5',
+ market_type: 'all',
+ shortcode: 'bvi',
+ product: 'zero_spread',
+ };
+
mocked_props.is_demo = true;
mocked_props.is_eu_user = false;
render( );
expect(screen.getByText('Zero Spread Demo')).toBeInTheDocument();
});
- test('should render correct title for DerivX with correct market type and shortcode demo account', () => {
- mocked_props.trading_platforms.platform = 'dxtrade';
- mocked_props.trading_platforms.market_type = 'all';
- mocked_props.trading_platforms.shortcode = 'svg';
+ test('should render correct title for DerivX with correct product type demo account', () => {
+ mocked_props.trading_platforms = {
+ platform: 'dxtrade',
+ market_type: 'all',
+ shortcode: 'svg',
+ };
mocked_props.is_demo = true;
mocked_props.is_eu_user = false;
render( );
diff --git a/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts.spec.tsx b/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts.spec.tsx
index 3cee459e05bc..563844a791a5 100644
--- a/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts.spec.tsx
+++ b/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-compare-accounts.spec.tsx
@@ -59,7 +59,6 @@ describe(' ', () => {
setAccountType: jest.fn(),
setJurisdictionSelectedShortcode: jest.fn(),
enableCFDPasswordModal: jest.fn(),
- toggleCFDVerificationModal: jest.fn(),
},
},
});
diff --git a/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-instruments-label-highlighted.spec.tsx b/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-instruments-label-highlighted.spec.tsx
index 6bc3834871af..f496590f33dc 100644
--- a/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-instruments-label-highlighted.spec.tsx
+++ b/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/cfd-instruments-label-highlighted.spec.tsx
@@ -9,18 +9,21 @@ describe(' ', () => {
const mock = mockStore({
traders_hub: {
selected_region: 'Non-EU',
+ is_eu_user: false,
},
});
const mocked_props = {
trading_platforms: {
- platform: 'mt5',
- market_type: 'gaming',
- shortcode: 'svg',
+ market_type: 'financial',
+ shortcode: 'maltainvest',
+ instruments: ['Forex', 'Cryptocurrencies'],
+ product_details: { max_leverage: '1:30', min_spread: '0.5' },
+ platform: 'ctrader',
},
};
- it('should renders icons for market type gaming/synthetic', () => {
+ it('should renders icons for product type standard', () => {
const wrapper = ({ children }: { children: JSX.Element }) => (
{children}
);
@@ -52,4 +55,20 @@ describe(' ', () => {
expect(containerElement).toBeInTheDocument();
expect(containerElement).toHaveClass('compare-cfd-account-outline');
});
+
+ it('should render the "Boom 300 and Crash 300 Index" for EU user', () => {
+ const mockStoreEU = mockStore({
+ traders_hub: {
+ selected_region: 'EU',
+ is_eu_user: true,
+ },
+ });
+
+ const wrapper = ({ children }: { children: JSX.Element }) => (
+ {children}
+ );
+
+ render( , { wrapper });
+ expect(screen.getByText(/Boom 300 and Crash 300 Index/i)).toBeInTheDocument();
+ });
});
diff --git a/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/instruments-icon-with-label.spec.tsx b/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/instruments-icon-with-label.spec.tsx
index a4ccf243cf19..1011c78845b5 100644
--- a/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/instruments-icon-with-label.spec.tsx
+++ b/packages/cfd/src/Containers/cfd-compare-accounts/__tests__/instruments-icon-with-label.spec.tsx
@@ -22,7 +22,6 @@ describe(' ', () => {
expect(iconElement).toHaveClass('trading-instruments__icon');
expect(textElement).toBeInTheDocument();
expect(asteriskElement).toBeInTheDocument();
- expect(asteriskElement).toHaveClass('trading-instruments__span');
});
it('should not apply opacity if "highlighted" prop is true', () => {
diff --git a/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts-card.tsx b/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts-card.tsx
index e5bb1e3d79ab..1900c679cd1c 100644
--- a/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts-card.tsx
+++ b/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts-card.tsx
@@ -30,13 +30,6 @@ const CFDCompareAccountsCard = ({ trading_platforms, is_eu_user, is_demo }: TCom
/>
- {is_eu_user && (
-
-
-
-
-
- )}
);
diff --git a/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts-description.tsx b/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts-description.tsx
index 0e008aa66602..5dab0c3206a8 100644
--- a/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts-description.tsx
+++ b/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts-description.tsx
@@ -8,14 +8,26 @@ import { getJuridisctionDescription, getMarketType } from '../../Helpers/compare
import { REGION, CFD_PLATFORMS, MARKET_TYPE_SHORTCODE } from '../../Helpers/cfd-config';
const CFDCompareAccountsDescription = ({ trading_platforms, is_demo }: TCompareAccountsCard) => {
- const market_type = getMarketType(trading_platforms);
- const market_type_shortcode =
- trading_platforms.platform === CFD_PLATFORMS.MT5 && market_type === 'all'
- ? `${market_type}_${trading_platforms.product}_${trading_platforms.shortcode}`
- : market_type.concat('_', trading_platforms.shortcode ?? '');
- const juridisction_data = getJuridisctionDescription(market_type_shortcode);
const { traders_hub } = useStore();
const { selected_region } = traders_hub;
+
+ const getMarketTypeShortcode = () => {
+ if (
+ trading_platforms.platform === CFD_PLATFORMS.DXTRADE ||
+ trading_platforms.platform === CFD_PLATFORMS.CTRADER
+ ) {
+ return market_type.concat('_', trading_platforms.shortcode ?? '');
+ } else if (trading_platforms.platform === CFD_PLATFORMS.MT5 && market_type === 'all') {
+ return `${market_type}_${trading_platforms.product}_${trading_platforms.shortcode}`;
+ }
+ return market_type;
+ };
+
+ const market_type = getMarketType(trading_platforms);
+ const market_type_shortcode = getMarketTypeShortcode();
+
+ const juridisction_data = getJuridisctionDescription(market_type_shortcode, trading_platforms);
+
const zero_spread_spread_message = localize('Commissions apply');
return (
@@ -26,7 +38,7 @@ const CFDCompareAccountsDescription = ({ trading_platforms, is_demo }: TCompareA
>
- {localize('Up to')} {juridisction_data.leverage}
+ {localize('Up to')} {juridisction_data.leverage ?? ''}
{selected_region === REGION.NON_EU ? juridisction_data.leverage_description : localize('Leverage')}
@@ -56,39 +68,6 @@ const CFDCompareAccountsDescription = ({ trading_platforms, is_demo }: TCompareA
)}
- {!is_demo && (
-
-
-
- {juridisction_data.counterparty_company}
-
-
- {juridisction_data.counterparty_company_description}
-
-
-
-
- {juridisction_data.jurisdiction}
-
-
- {juridisction_data.jurisdiction_description}
-
-
-
-
- {juridisction_data.regulator}
-
- {juridisction_data.regulator_license && (
-
- {juridisction_data.regulator_license}
-
- )}
-
- {juridisction_data.regulator_description}
-
-
-
- )}
);
};
diff --git a/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts-platform-label.tsx b/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts-platform-label.tsx
index 358dd45b4cf3..34a2cf2e8171 100644
--- a/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts-platform-label.tsx
+++ b/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts-platform-label.tsx
@@ -14,6 +14,8 @@ const CFDCompareAccountsPlatformLabel = ({ trading_platforms }: TCompareAccounts
'compare-cfd-account-platform-label--other-cfds':
platform_label === platformsHeaderLabel.other_cfds ||
platform_label === platformsHeaderLabel.ctrader,
+ 'compare-cfd-account-platform-label--derivx': platform_label === platformsHeaderLabel.derivx,
+ 'compare-cfd-account-platform-label--ctrader': platform_label === platformsHeaderLabel.ctrader,
})}
>
diff --git a/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts-title-icon.tsx b/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts-title-icon.tsx
index da89afd19d30..9b7e97cc87d9 100644
--- a/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts-title-icon.tsx
+++ b/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts-title-icon.tsx
@@ -1,17 +1,22 @@
import React from 'react';
import { Text, Popover } from '@deriv/components';
+import { useDevice } from '@deriv-com/ui';
import { localize } from '@deriv/translations';
import TradigPlatformIconProps from '../../Assets/svgs/trading-platform';
import { TCompareAccountsCard } from 'Components/props.types';
import { getAccountCardTitle, getMarketType, getAccountIcon } from '../../Helpers/compare-accounts-config';
import { CFD_PLATFORMS, MARKET_TYPE, MARKET_TYPE_SHORTCODE } from '../../Helpers/cfd-config';
+import { PRODUCT } from '@deriv/shared';
const CFDCompareAccountsTitleIcon = ({ trading_platforms, is_eu_user, is_demo }: TCompareAccountsCard) => {
+ const { isDesktop } = useDevice();
const market_type = !is_eu_user ? getMarketType(trading_platforms) : 'CFDs';
+
const market_type_shortcode =
- trading_platforms.platform === CFD_PLATFORMS.MT5 && market_type === MARKET_TYPE.ALL
+ trading_platforms.platform === CFD_PLATFORMS.MT5 &&
+ (market_type === MARKET_TYPE.ALL || trading_platforms.product === PRODUCT.STP)
? `${market_type}_${trading_platforms.product}_${trading_platforms.shortcode}`
- : market_type.concat('_', trading_platforms.shortcode ?? '');
+ : market_type ?? '';
const jurisdiction_card_icon =
trading_platforms.platform === CFD_PLATFORMS.DXTRADE || trading_platforms.platform === CFD_PLATFORMS.CTRADER
? getAccountIcon(trading_platforms.platform)
@@ -20,8 +25,10 @@ const CFDCompareAccountsTitleIcon = ({ trading_platforms, is_eu_user, is_demo }:
trading_platforms.platform === CFD_PLATFORMS.DXTRADE || trading_platforms.platform === CFD_PLATFORMS.CTRADER
? getAccountCardTitle(trading_platforms.platform, is_demo)
: getAccountCardTitle(market_type_shortcode, is_demo);
- const labuan_jurisdiction_message = localize(
- 'Choosing this jurisdiction will give you a Financial STP account. Your trades will go directly to the market and have tighter spreads.'
+ const labuan_jurisdiction_message = (
+
+ {localize('This account gives you direct market price access and tighter spreads.')}
+
);
return (
@@ -46,7 +53,7 @@ const CFDCompareAccountsTitleIcon = ({ trading_platforms, is_eu_user, is_demo }:
)}
-
+
);
};
diff --git a/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts.scss b/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts.scss
index fbfdb6d319d7..684bf67c6a1e 100644
--- a/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts.scss
+++ b/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts.scss
@@ -53,17 +53,15 @@
width: 27rem;
border: 1px solid var(--general-hover);
border-radius: 2.4rem;
- padding-bottom: 1.6rem;
&:hover {
box-shadow: 0 2px 8px 0 var(--shadow-menu);
}
@include mobile-or-tablet-screen {
- width: 18rem;
+ width: 20rem;
}
&__eu-clients {
position: relative;
top: 0.5rem;
- text-align: center;
}
&__banner {
position: absolute;
@@ -85,17 +83,13 @@
&-outline {
display: flex;
flex-direction: column;
- padding: 4rem 2.4rem 0;
+ padding: 1.6rem 2.4rem 2.4rem;
border-radius: 2.4rem;
- @include mobile-or-tablet-screen {
- padding: 7rem 1.5rem 1.5rem;
- }
}
&-text-container {
max-height: 25.5rem;
@include mobile {
- min-height: 32rem;
height: fit-content;
}
@@ -137,9 +131,9 @@
position: relative;
width: 62%;
@include mobile-or-tablet-screen {
- display: block;
+ display: flex;
position: fixed;
- width: 15.2rem;
+ width: 13.4rem;
right: 0;
}
}
@@ -167,10 +161,21 @@
&--other-cfds {
background-color: var(--header-background-others);
}
+ &--derivx {
+ background-color: var(--header-background-others);
+ }
+ &--ctrader {
+ background-color: #{$color-yellow-6};
+ }
}
&-underline {
- border-top: 0.5rem solid var(--less-prominent);
- width: 21.3rem;
+ height: 1px;
+ width: 75%;
+ background-color: var(--general-hover);
+ position: absolute;
+ left: 50%;
+ transform: translateX(-50%);
+ margin-top: 0.4rem;
}
&__button {
width: calc(100% - 4rem);
diff --git a/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts.tsx b/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts.tsx
index 57ad68ada583..b6f97a23ece3 100644
--- a/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts.tsx
+++ b/packages/cfd/src/Containers/cfd-compare-accounts/cfd-compare-accounts.tsx
@@ -64,19 +64,20 @@ const CompareCFDs = observer(() => {
? all_cfd_available_accounts.length + 1
: all_cfd_available_accounts.length;
- const CompareAccountsHeader = (
-
- );
+ const getCompareAccountsHeader = () =>
+ selected_region === REGION.EU ? (
+
+ ) : (
+
+ );
const DesktopHeader = (
@@ -93,7 +94,7 @@ const CompareCFDs = observer(() => {
- {CompareAccountsHeader}
+ {getCompareAccountsHeader()}
@@ -142,7 +143,7 @@ const CompareCFDs = observer(() => {
return (
history.push(routes.traders_hub)}
diff --git a/packages/cfd/src/Containers/cfd-compare-accounts/cfd-instruments-label-highlighted.tsx b/packages/cfd/src/Containers/cfd-compare-accounts/cfd-instruments-label-highlighted.tsx
index 438628b03420..5d542839c2ab 100644
--- a/packages/cfd/src/Containers/cfd-compare-accounts/cfd-instruments-label-highlighted.tsx
+++ b/packages/cfd/src/Containers/cfd-compare-accounts/cfd-instruments-label-highlighted.tsx
@@ -1,4 +1,6 @@
import React from 'react';
+import { Text } from '@deriv/components';
+import { Localize } from '@deriv/translations';
import InstrumentsIconWithLabel from './instruments-icon-with-label';
import { TInstrumentsIcon, TCompareAccountsCard } from 'Components/props.types';
import { getHighlightedIconLabel } from '../../Helpers/compare-accounts-config';
@@ -6,15 +8,38 @@ import { useStore } from '@deriv/stores';
const CFDInstrumentsLabelHighlighted = ({ trading_platforms }: TCompareAccountsCard) => {
const { traders_hub } = useStore();
- const selected_region = traders_hub.selected_region;
+ const { selected_region, is_eu_user } = traders_hub;
const iconData: TInstrumentsIcon[] = [...getHighlightedIconLabel(trading_platforms, selected_region)];
return (
- {iconData.map(item => (
-
- ))}
+ {is_eu_user ? (
+
+ {iconData
+ .filter(item => item.highlighted)
+ .map(item => (
+
+ ))}
+
+
+
+
+
+
+ ) : (
+ iconData.map(item => (
+
+ ))
+ )}
);
};
diff --git a/packages/cfd/src/Containers/cfd-compare-accounts/instruments-icon-with-label.tsx b/packages/cfd/src/Containers/cfd-compare-accounts/instruments-icon-with-label.tsx
index ae0624646d83..2ff4404647bd 100644
--- a/packages/cfd/src/Containers/cfd-compare-accounts/instruments-icon-with-label.tsx
+++ b/packages/cfd/src/Containers/cfd-compare-accounts/instruments-icon-with-label.tsx
@@ -1,9 +1,11 @@
import React from 'react';
+import { useDevice } from '@deriv-com/ui';
import { Text } from '@deriv/components';
import { TInstrumentsIcon } from 'Components/props.types';
import TradingInstrumentsIcon from '../../Assets/svgs/trading-instruments';
const InstrumentsIconWithLabel = ({ icon, text, highlighted, className, is_asterisk }: TInstrumentsIcon) => {
+ const { isMobile } = useDevice();
return (
-
+
{text}
+ {is_asterisk && (
+
+ *
+
+ )}
- {is_asterisk && (
-
- *
-
- )}
);
};
diff --git a/packages/cfd/src/Containers/cfd-dbvi-onboarding.tsx b/packages/cfd/src/Containers/cfd-dbvi-onboarding.tsx
deleted file mode 100644
index 02073b333de5..000000000000
--- a/packages/cfd/src/Containers/cfd-dbvi-onboarding.tsx
+++ /dev/null
@@ -1,165 +0,0 @@
-import React from 'react';
-import { useDevice } from '@deriv-com/ui';
-import { PoiPoaDocsSubmitted } from '@deriv/account';
-import { AccountStatusResponse } from '@deriv/api-types';
-import { Button, Icon, Loading, MobileDialog, Modal, Text, UILoader } from '@deriv/components';
-import { localize } from '@deriv/translations';
-import { getAuthenticationStatusInfo, isMobile, WS, isPOARequiredForMT5 } from '@deriv/shared';
-import CFDFinancialStpRealAccountSignup from './cfd-financial-stp-real-account-signup';
-import { observer, useStore } from '@deriv/stores';
-import { useCfdStore } from '../Stores/Modules/CFD/Helpers/useCfdStores';
-import { JURISDICTION } from '../Helpers/cfd-config';
-
-const SwitchToRealAccountMessage = ({ onClickOk }: { onClickOk: () => void }) => (
-
-
-
- {localize('Switch to your real account to submit your documents')}
-
- {
- onClickOk();
- }}
- className='da-icon-with-message__button'
- primary
- />
-
-);
-
-const CFDDbviOnboarding = observer(() => {
- const { isDesktop } = useDevice();
- const {
- client,
- ui,
- modules: { cfd },
- } = useStore();
-
- const { account_status, fetchAccountSettings, is_virtual, updateAccountStatus, updateMT5Status } = client;
- const { disableApp, enableApp } = ui;
- const { setProduct } = cfd;
-
- const {
- has_created_account_for_selected_jurisdiction,
- has_submitted_cfd_personal_details,
- is_cfd_verification_modal_visible,
- jurisdiction_selected_shortcode,
- enableCFDPasswordModal,
- toggleCFDVerificationModal,
- } = useCfdStore();
-
- const [showSubmittedModal, setShowSubmittedModal] = React.useState(true);
- const [is_loading, setIsLoading] = React.useState(false);
-
- const getAccountStatusFromAPI = () => {
- WS.authorized.getAccountStatus().then((response: AccountStatusResponse) => {
- const { get_account_status } = response;
- if (get_account_status?.authentication) {
- const { poi_acknowledged_for_maltainvest, poi_acknowledged_for_bvi_labuan_vanuatu, poa_acknowledged } =
- getAuthenticationStatusInfo(get_account_status);
- if (jurisdiction_selected_shortcode === JURISDICTION.MALTA_INVEST) {
- setShowSubmittedModal(poi_acknowledged_for_maltainvest && poa_acknowledged);
- } else {
- /**
- * Need to retrigger POA when user has not explicitly submitted Address proof docs
- */
- const is_poa_required_for_mt5 = isPOARequiredForMT5(
- account_status,
- jurisdiction_selected_shortcode
- );
- setShowSubmittedModal(
- poi_acknowledged_for_bvi_labuan_vanuatu &&
- has_submitted_cfd_personal_details &&
- !is_poa_required_for_mt5
- );
- }
- }
-
- setIsLoading(false);
- });
- setIsLoading(false);
- };
-
- const clickOncloseButton = () => {
- toggleCFDVerificationModal();
- setProduct();
- };
-
- React.useEffect(() => {
- if (is_cfd_verification_modal_visible) {
- setIsLoading(true);
- getAccountStatusFromAPI();
- fetchAccountSettings();
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [is_cfd_verification_modal_visible]);
-
- const getModalContent = () => {
- if (is_loading) {
- return ;
- } else if (is_virtual) {
- return ;
- }
- return showSubmittedModal ? (
-
- ) : (
- {
- updateMT5Status();
- if (has_created_account_for_selected_jurisdiction) {
- setShowSubmittedModal(true);
- } else {
- toggleCFDVerificationModal();
- enableCFDPasswordModal();
- }
- }}
- />
- );
- };
-
- const getModalTitle = () =>
- has_created_account_for_selected_jurisdiction
- ? localize('Submit your proof of identity and address')
- : localize('Add a real MT5 account');
-
- return (
- }>
- {isDesktop ? (
- getAccountStatusFromAPI()}
- exit_classname='cfd-modal--custom-exit'
- >
- {getModalContent()}
-
- ) : (
-
- {getModalContent()}
-
- )}
-
- );
-});
-
-export default CFDDbviOnboarding;
diff --git a/packages/cfd/src/Containers/cfd-enter-password-modal-title.tsx b/packages/cfd/src/Containers/cfd-enter-password-modal-title.tsx
new file mode 100644
index 000000000000..bdc995dc8694
--- /dev/null
+++ b/packages/cfd/src/Containers/cfd-enter-password-modal-title.tsx
@@ -0,0 +1,49 @@
+import React from 'react';
+import { Text } from '@deriv/components';
+import { getCFDPlatformLabel, getCFDPlatformNames } from '@deriv/shared';
+import { observer, useStore } from '@deriv/stores';
+import { Localize } from '@deriv/translations';
+import { CATEGORY, CFD_PLATFORMS } from '../Helpers/cfd-config';
+
+type TCFDEnterPasswordModalTitleProps = { platform: typeof CFD_PLATFORMS[keyof typeof CFD_PLATFORMS] };
+
+const CFDEnterPasswordModalTitle = observer(({ platform }: TCFDEnterPasswordModalTitleProps) => {
+ const {
+ modules: { cfd },
+ } = useStore();
+ const { account_title, account_type } = cfd;
+
+ const getAccountCardTitle = () => {
+ switch (platform) {
+ case CFD_PLATFORMS.CTRADER:
+ case CFD_PLATFORMS.DXTRADE:
+ return account_type.category === CATEGORY.REAL ? 'Real' : '';
+ default:
+ return account_title;
+ }
+ };
+
+ return (
+
+ {platform === CFD_PLATFORMS.MT5 ? (
+
+ ) : (
+
+ )}
+
+ );
+});
+
+export default CFDEnterPasswordModalTitle;
diff --git a/packages/cfd/src/Containers/cfd-financial-stp-real-account-signup.tsx b/packages/cfd/src/Containers/cfd-financial-stp-real-account-signup.tsx
deleted file mode 100644
index 777a17646914..000000000000
--- a/packages/cfd/src/Containers/cfd-financial-stp-real-account-signup.tsx
+++ /dev/null
@@ -1,229 +0,0 @@
-import React from 'react';
-import { useDevice } from '@deriv-com/ui';
-import { Div100vhContainer } from '@deriv/components';
-import { getAuthenticationStatusInfo, isPOARequiredForMT5 } from '@deriv/shared';
-import { observer, useStore } from '@deriv/stores';
-import type { TCoreStores } from '@deriv/stores/types';
-import CFDPOA from '../Components/cfd-poa';
-import CFDPOI from '../Components/cfd-poi';
-import CFDPersonalDetailsContainer from './cfd-personal-details-container';
-import { useCfdStore } from '../Stores/Modules/CFD/Helpers/useCfdStores';
-import { JURISDICTION } from '../Helpers/cfd-config';
-
-type TCFDFinancialStpRealAccountSignupProps = {
- onFinish: () => void;
-};
-
-type TNextStep = (index: number, value: { [key: string]: string | undefined }) => void;
-
-type TItem = {
- refreshNotifications: TCoreStores['notifications']['refreshNotifications'];
- removeNotificationMessage: TCoreStores['notifications']['removeNotificationMessage'];
- removeNotificationByKey: TCoreStores['notifications']['removeNotificationByKey'];
- addNotificationMessageByKey: TCoreStores['notifications']['addNotificationMessageByKey'];
- authentication_status: TCoreStores['client']['authentication_status'];
- account_settings: TCoreStores['client']['account_settings'];
- email: TCoreStores['client']['email'];
- is_fully_authenticated: TCoreStores['client']['is_fully_authenticated'];
- landing_company: TCoreStores['client']['landing_company'];
- residence_list: TCoreStores['client']['residence_list'];
- states_list: TCoreStores['client']['states_list'];
- fetchStatesList: TCoreStores['client']['fetchStatesList'];
- account_status: TCoreStores['client']['account_status'];
- jurisdiction_selected_shortcode: TCoreStores['modules']['cfd']['jurisdiction_selected_shortcode'];
- has_submitted_cfd_personal_details: TCoreStores['modules']['cfd']['has_submitted_cfd_personal_details'];
- onFinish: TCFDFinancialStpRealAccountSignupProps['onFinish'];
-};
-
-type TItemsState = {
- body: typeof CFDPOI | typeof CFDPOA | typeof CFDPersonalDetailsContainer;
- form_value: { [key: string]: string | undefined };
- forwarded_props: Array>;
-};
-
-const CFDFinancialStpRealAccountSignup = observer(({ onFinish }: TCFDFinancialStpRealAccountSignupProps) => {
- const { isDesktop } = useDevice();
- const { notifications, client } = useStore();
-
- const { refreshNotifications, removeNotificationMessage, removeNotificationByKey, addNotificationMessageByKey } =
- notifications;
-
- const {
- authentication_status,
- account_settings,
- email,
- is_fully_authenticated,
- landing_company,
- residence_list,
- states_list,
- fetchStatesList,
- account_status,
- } = client;
-
- const { jurisdiction_selected_shortcode, has_submitted_cfd_personal_details } = useCfdStore();
-
- const passthroughProps = {
- refreshNotifications,
- removeNotificationMessage,
- removeNotificationByKey,
- addNotificationMessageByKey,
- authentication_status,
- account_settings,
- email,
- is_fully_authenticated,
- landing_company,
- residence_list,
- states_list,
- fetchStatesList,
- account_status,
- jurisdiction_selected_shortcode,
- has_submitted_cfd_personal_details,
- onFinish,
- } as const;
-
- const [step, setStep] = React.useState(0);
- const [form_error, setFormError] = React.useState('');
- const state_index = step;
- let is_mounted = React.useRef(true).current;
-
- const { need_poi_for_maltainvest, need_poi_for_bvi_labuan_vanuatu } = getAuthenticationStatusInfo(account_status);
-
- const poi_config: TItemsState = {
- body: CFDPOI,
- form_value: {
- poi_state: 'unknown',
- },
- forwarded_props: [
- 'addNotificationMessageByKey',
- 'authentication_status',
- 'refreshNotifications',
- 'removeNotificationMessage',
- 'removeNotificationByKey',
- 'jurisdiction_selected_shortcode',
- ],
- };
-
- const poa_config: TItemsState = {
- body: CFDPOA,
- form_value: {},
- forwarded_props: [],
- };
-
- const personal_details_config: TItemsState = {
- body: CFDPersonalDetailsContainer,
- form_value: {
- citizen: '',
- place_of_birth: '',
- tax_residence: '',
- tax_identification_number: '',
- account_opening_reason: '',
- },
- forwarded_props: ['residence_list', 'landing_company'],
- };
-
- const should_show_poi = () => {
- if (jurisdiction_selected_shortcode === JURISDICTION.MALTA_INVEST) {
- return need_poi_for_maltainvest;
- }
- return need_poi_for_bvi_labuan_vanuatu;
- };
-
- const shouldShowPOA = () => {
- return isPOARequiredForMT5(account_status, jurisdiction_selected_shortcode);
- };
-
- const should_show_personal_details =
- !has_submitted_cfd_personal_details && jurisdiction_selected_shortcode !== JURISDICTION.MALTA_INVEST;
-
- const verification_configs = [
- ...(should_show_poi() ? [poi_config] : []),
- ...(shouldShowPOA() ? [poa_config] : []),
- ...(should_show_personal_details ? [personal_details_config] : []),
- ];
-
- const [items, setItems] = React.useState[]>(verification_configs);
-
- const clearError = () => {
- setFormError('');
- };
-
- React.useEffect(() => {
- refreshNotifications();
- }, [items, refreshNotifications]);
-
- React.useEffect(() => {
- fetchStatesList();
- }, [fetchStatesList]);
-
- const unmount = () => {
- is_mounted = false;
- onFinish();
- };
-
- const saveFormData = (index: number, value: { [key: string]: string | undefined }) => {
- if (!is_mounted) return; // avoiding state update on unmounted component
- const cloned_items: TItemsState[] = [...items];
- cloned_items[index].form_value = value;
- setItems(cloned_items);
- };
-
- const nextStep: TNextStep = (index, value) => {
- clearError();
- if (step + 1 < items.length) {
- saveFormData(index, value);
- setStep(step + 1);
- } else unmount();
- };
-
- const prevStep = () => {
- if (step - 1 >= 0) {
- setStep(step - 1);
- setFormError('');
- } else unmount();
- };
-
- const getCurrent = (key?: keyof TItemsState) => {
- return key ? items[state_index][key] : items[state_index];
- };
-
- const BodyComponent = getCurrent('body') as typeof CFDPOI & typeof CFDPOA & typeof CFDPersonalDetailsContainer;
-
- const form_value = getCurrent('form_value');
-
- const passthrough: Partial = (
- (getCurrent('forwarded_props') || []) as TItemsState['forwarded_props']
- ).reduce((forwarded_prop, item) => {
- return Object.assign(forwarded_prop, {
- [item]: passthroughProps[item],
- });
- }, {});
-
- return (
-
-
-
-
-
- );
-});
-
-export default CFDFinancialStpRealAccountSignup;
diff --git a/packages/cfd/src/Containers/cfd-password-change.tsx b/packages/cfd/src/Containers/cfd-password-change.tsx
index 0dd66adc8e7c..2d5e6d948d51 100644
--- a/packages/cfd/src/Containers/cfd-password-change.tsx
+++ b/packages/cfd/src/Containers/cfd-password-change.tsx
@@ -26,6 +26,7 @@ type TCFDPasswordChangeProps = TCFDPasswordFormReusedProps & {
onForgotPassword: () => void;
setNewPasswordValue?: React.Dispatch>;
should_set_trading_password: boolean;
+ need_tnc: boolean;
};
type TOnSubmitPasswordChange = (
@@ -42,6 +43,7 @@ const CFDPasswordChange = observer(
setNewPasswordValue,
should_set_trading_password,
platform,
+ need_tnc,
}: TCFDPasswordChangeProps) => {
const { isMobile } = useDevice();
const { ui, modules } = useStore();
@@ -199,6 +201,7 @@ const CFDPasswordChange = observer(
platform={platform}
checked={checked}
onCheck={() => setChecked(prev => !prev)}
+ need_tnc={need_tnc}
/>
)}
diff --git a/packages/cfd/src/Containers/cfd-password-modal-info.tsx b/packages/cfd/src/Containers/cfd-password-modal-info.tsx
index 7337a7719f91..471556ea0cec 100644
--- a/packages/cfd/src/Containers/cfd-password-modal-info.tsx
+++ b/packages/cfd/src/Containers/cfd-password-modal-info.tsx
@@ -2,28 +2,49 @@ 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 = {
jurisdiction_selected_shortcode: string;
platform: string;
product: string;
+ need_tnc: boolean;
};
-const CfdPasswordModalInfo = ({ jurisdiction_selected_shortcode, platform, product }: CfdPasswordModalInfoProps) => {
+const CfdPasswordModalInfo = ({ platform, product, need_tnc }: CfdPasswordModalInfoProps) => {
+ const { available_account_to_create } = useIsSelectedMT5AccountCreated();
return (
-
+
-
+ {need_tnc ? (
+ ,
+ ]}
+ />
+ ) : (
+
+ )}
);
diff --git a/packages/cfd/src/Containers/cfd-password-modal-title.tsx b/packages/cfd/src/Containers/cfd-password-modal-title.tsx
deleted file mode 100644
index b4a523cf2a3b..000000000000
--- a/packages/cfd/src/Containers/cfd-password-modal-title.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-import React from 'react';
-import { Text } from '@deriv/components';
-import { getCFDPlatformNames, getCFDPlatformLabel, getFormattedJurisdictionCode } from '@deriv/shared';
-import { observer, useStore } from '@deriv/stores';
-import { Localize } from '@deriv/translations';
-import { CATEGORY, CFD_PLATFORMS } from '../Helpers/cfd-config';
-import { useCfdStore } from '../Stores/Modules/CFD/Helpers/useCfdStores';
-
-type TCFDPasswordModalTitleProps = { platform: typeof CFD_PLATFORMS[keyof typeof CFD_PLATFORMS] };
-
-const CFDPasswordModalTitle = observer(({ platform }: TCFDPasswordModalTitleProps) => {
- const { traders_hub } = useStore();
- const { show_eu_related_content } = traders_hub;
- const { account_title, account_type, jurisdiction_selected_shortcode } = useCfdStore();
-
- const accountTitle = (category: typeof CATEGORY[keyof typeof CATEGORY]) => {
- switch (platform) {
- case CFD_PLATFORMS.CTRADER:
- case CFD_PLATFORMS.DXTRADE:
- return category === CATEGORY.REAL ? 'Real' : '';
- default:
- return account_title;
- }
- };
-
- const showJurisdiction = () => {
- if (platform === CFD_PLATFORMS.DXTRADE) {
- return '';
- } else if (!show_eu_related_content) {
- return getFormattedJurisdictionCode(jurisdiction_selected_shortcode);
- }
- return 'CFDs';
- };
-
- return (
-
- {account_type.category === CATEGORY.REAL && (
-
- )}
- {account_type.category === CATEGORY.DEMO && (
-
- )}
-
- );
-});
-
-export default CFDPasswordModalTitle;
diff --git a/packages/cfd/src/Containers/cfd-password-modal-tnc.tsx b/packages/cfd/src/Containers/cfd-password-modal-tnc.tsx
index 9bb595222285..544e79ebe26f 100644
--- a/packages/cfd/src/Containers/cfd-password-modal-tnc.tsx
+++ b/packages/cfd/src/Containers/cfd-password-modal-tnc.tsx
@@ -1,40 +1,41 @@
import React from 'react';
import { getCFDPlatformLabel, CFD_PRODUCTS_TITLE, CFD_PLATFORMS } from '@deriv/shared';
-import { observer, useStore } from '@deriv/stores';
+import { observer } from '@deriv/stores';
import CfdPasswordModalInfo from './cfd-password-modal-info';
-import JurisdictionCheckBox from './jurisdiction-modal/jurisdiction-modal-checkbox';
+import JurisdictionCheckBox from './jurisdiction-checkbox';
import { useCfdStore } from '../Stores/Modules/CFD/Helpers/useCfdStores';
import classNames from 'classnames';
type CfdPasswordModalTncProps = {
platform: typeof CFD_PLATFORMS[keyof typeof CFD_PLATFORMS];
checked: boolean;
+ need_tnc: boolean;
onCheck: () => void;
className?: string;
};
-const CfdPasswordModalTnc = observer(({ platform, checked, onCheck, className }: CfdPasswordModalTncProps) => {
- const { client } = useStore();
- const { should_restrict_vanuatu_account_creation, should_restrict_bvi_account_creation } = client;
- const { jurisdiction_selected_shortcode } = useCfdStore();
-
- return (
-
-
-
-
- );
-});
+const CfdPasswordModalTnc = observer(
+ ({ platform, checked, onCheck, className, need_tnc }: CfdPasswordModalTncProps) => {
+ const { jurisdiction_selected_shortcode, account_title } = useCfdStore();
+ return (
+
+
+ {need_tnc && (
+
+ )}
+
+ );
+ }
+);
export default CfdPasswordModalTnc;
diff --git a/packages/cfd/src/Containers/cfd-password-modal.tsx b/packages/cfd/src/Containers/cfd-password-modal.tsx
index 3bd3a1f3f0d5..500167672766 100644
--- a/packages/cfd/src/Containers/cfd-password-modal.tsx
+++ b/packages/cfd/src/Containers/cfd-password-modal.tsx
@@ -2,8 +2,8 @@ import React from 'react';
import { useHistory } from 'react-router';
import { Formik, FormikErrors, FormikHelpers } from 'formik';
import { useDevice } from '@deriv-com/ui';
-
import { SentEmailModal } from '@deriv/account';
+import '../sass/cfd.scss';
import {
FormSubmitButton,
Icon,
@@ -15,10 +15,9 @@ import {
Text,
} from '@deriv/components';
import {
- getAuthenticationStatusInfo,
getCFDPlatformLabel,
+ getCFDPlatformNames,
getErrorMessages,
- getLegalEntityName,
routes,
validLength,
validPassword,
@@ -29,25 +28,34 @@ import {
} from '@deriv/shared';
import { observer, useStore } from '@deriv/stores';
import { Localize, localize } from '@deriv/translations';
-
-import { TProducts } from '../Components/props.types';
+import CFDEnterPasswordModalTitle from './cfd-enter-password-modal-title';
import SuccessDialog from '../Components/success-dialog/success-dialog';
-import CFDPasswordModalTitle from './cfd-password-modal-title';
-import TradingPlatformIcon from '../Assets/svgs/trading-platform';
import MigrationSuccessModal from '../Components/migration-success-modal';
import { useCfdStore } from '../Stores/Modules/CFD/Helpers/useCfdStores';
-import { CFD_PLATFORMS, JURISDICTION, CATEGORY, PRODUCT } from '../Helpers/cfd-config';
+import { CFD_PLATFORMS, CATEGORY } from '../Helpers/cfd-config';
+import classNames from 'classnames';
import { getDxCompanies, getMtCompanies, TDxCompanies, TMtCompanies } from '../Stores/Modules/CFD/Helpers/cfd-config';
-import '../sass/cfd.scss';
-import CfdPasswordModalTnc from './cfd-password-modal-tnc';
-import classNames from 'classnames';
+const MT5CreatePassword = makeLazyLoader(
+ () => moduleLoader(() => import('./mt5-create-password/mt5-create-password')),
+ () =>
+)();
+
+const CfdPasswordModalTnc = makeLazyLoader(
+ () => moduleLoader(() => import('./cfd-password-modal-tnc')),
+ () =>
+)();
const CFDPasswordChange = makeLazyLoader(
() => moduleLoader(() => import('./cfd-password-change')),
() =>
)();
+const CFDPasswordSuccessIcon = makeLazyLoader(
+ () => moduleLoader(() => import('./cfd-password-success-icon')),
+ () =>
+)();
+
const CFDPasswordChangeContent = makeLazyLoader(
() => moduleLoader(() => import('./cfd-password-change-content')),
() =>
@@ -69,13 +77,6 @@ type TPasswordModalHeaderProps = {
has_mt5_account?: boolean;
};
-type TIconTypeProps = {
- platform: string;
- type?: string;
- show_eu_related_content: boolean;
- product?: TProducts;
-};
-
type TCFDPasswordFormReusedProps = {
platform: typeof CFD_PLATFORMS[keyof typeof CFD_PLATFORMS];
error_message: string;
@@ -85,37 +86,34 @@ type TCFDPasswordFormReusedProps = {
type TCFDCreatePasswordProps = TCFDPasswordFormReusedProps & {
password: string;
onSubmit: TOnSubmitPassword;
- is_real_financial_stp: boolean;
+ need_tnc: boolean;
};
type TCFDCreatePasswordFormProps = TCFDPasswordFormReusedProps & {
has_mt5_account: boolean;
submitPassword: TOnSubmitPassword;
- is_real_financial_stp: boolean;
+ need_tnc: boolean;
};
type TMultiStepRefProps = {
goNextStep: () => void;
goPrevStep: () => void;
};
-type TReviewMsgForMT5 = {
- is_selected_mt5_verified: boolean;
- jurisdiction_selected_shortcode: string;
- manual_status: string;
-};
type TCFDPasswordFormProps = TCFDPasswordFormReusedProps & {
closeModal: () => void;
error_type?: string;
form_error?: string;
has_mt5_account: boolean;
- is_bvi: boolean;
is_dxtrade_allowed: boolean;
- is_real_financial_stp: boolean;
onCancel: () => void;
onForgotPassword: () => void;
should_set_trading_password: boolean;
submitPassword: TOnSubmitPassword;
+ account_type: {
+ type: string;
+ category: string;
+ };
};
type TCFDPasswordModalProps = {
@@ -130,21 +128,41 @@ const PasswordModalHeader = ({
platform,
}: TPasswordModalHeaderProps) => {
const { isDesktop } = useDevice();
+ const is_mt5 = platform === CFD_PLATFORMS.MT5;
const element = !isDesktop ? 'p' : 'span';
- const alignment = 'center';
- const font_size = 's';
+
+ const style = !isDesktop
+ ? {
+ padding: '2rem',
+ }
+ : {};
+
+ if (is_mt5 && !is_password_reset_error) {
+ const platform_name = getCFDPlatformNames(platform);
+ return (
+
+ {should_set_trading_password ? (
+
+ ) : (
+
+ )}
+
+ );
+ }
return (
-
- {should_set_trading_password && !is_password_reset_error && platform === CFD_PLATFORMS.MT5 && (
-
- )}
+
{!should_set_trading_password && !is_password_reset_error && (
);
};
-const ReviewMessageForMT5 = ({
- is_selected_mt5_verified,
- jurisdiction_selected_shortcode,
- manual_status,
-}: TReviewMsgForMT5) => {
- if (is_selected_mt5_verified) {
- return ;
- } else if (
- jurisdiction_selected_shortcode === JURISDICTION.BVI ||
- jurisdiction_selected_shortcode === JURISDICTION.VANUATU
- ) {
- if (manual_status === 'pending') {
- return ;
- }
- return ;
- } else if (jurisdiction_selected_shortcode === JURISDICTION.LABUAN) {
- return ;
- } else if (jurisdiction_selected_shortcode === JURISDICTION.MALTA_INVEST) {
- return (
-
- );
- }
- return null;
-};
-
-const IconType = React.memo(({ platform, type, show_eu_related_content, product }: TIconTypeProps) => {
- const traders_hub = window.location.pathname === routes.traders_hub;
- if (platform === CFD_PLATFORMS.DXTRADE) {
- return ;
- } else if (traders_hub) {
- if (platform === CFD_PLATFORMS.CTRADER) {
- return ;
- }
- switch (type) {
- case 'synthetic':
- return ;
- case 'all':
- if (product === PRODUCT.ZEROSPREAD) {
- return ;
- }
- return ;
- case 'financial':
- if (show_eu_related_content) {
- return ;
- }
- return ;
- default:
- return ;
- }
- } else {
- switch (type) {
- case 'synthetic':
- return ;
- case 'all':
- if (product === PRODUCT.ZEROSPREAD) {
- return ;
- }
- return ;
- case 'financial':
- if (show_eu_related_content) {
- return ;
- }
- return ;
- default:
- return ;
- }
- }
-});
-IconType.displayName = 'IconType';
const getCancelButtonLabel = ({
should_set_trading_password,
@@ -251,19 +200,7 @@ const handlePasswordInputChange = (
});
};
-const CreatePassword = ({
- password,
- platform,
- validatePassword,
- onSubmit,
- error_message,
- is_real_financial_stp,
-}: TCFDCreatePasswordProps) => {
- const { product, account_type } = useCfdStore();
- const [checked, setChecked] = React.useState(
- !(product === PRODUCT.ZEROSPREAD && account_type.category === CATEGORY.REAL)
- );
-
+const CreatePassword = ({ password, platform, validatePassword, onSubmit, error_message }: TCFDCreatePasswordProps) => {
return (
-
- {platform === CFD_PLATFORMS.MT5 ? (
- <>
-
-
-
-
- >
- ) : (
- <>
-
-
-
-
-
-
-
- >
- )}
-
-
- {() => (
- ) => {
- handlePasswordInputChange(
- e,
- handleChange,
- validateForm,
- setFieldTouched
- );
- }}
- data_testId={`dt_${platform}_password`}
- />
- )}
-
-
- {is_real_financial_stp && (
-
-
-
- )}
- {product === PRODUCT.ZEROSPREAD && account_type.category === CATEGORY.REAL && (
-
setChecked(prev => !prev)}
- />
- )}
+
+
+
+
+
+
+
+
+
+ {() => (
+ ) => {
+ handlePasswordInputChange(e, handleChange, validateForm, setFieldTouched);
+ }}
+ data_testId={`dt_${platform}_password`}
+ />
+ )}
+
0}
+ is_disabled={!values.password || Object.keys(errors).length > 0}
is_loading={isSubmitting}
label={localize('Create {{platform}} password', {
platform: getCFDPlatformLabel(platform),
@@ -398,7 +296,7 @@ const CFDCreatePasswordForm = ({
error_message,
validatePassword,
submitPassword,
- is_real_financial_stp,
+ need_tnc,
}: TCFDCreatePasswordFormProps) => {
const multi_step_ref = React.useRef();
const [password, setPassword] = React.useState('');
@@ -414,16 +312,26 @@ const CFDCreatePasswordForm = ({
const steps = [
{
- component: (
-
- ),
+ component:
+ platform === CFD_PLATFORMS.MT5 ? (
+
+ ) : (
+
+ ),
},
{
component: (
@@ -449,19 +357,18 @@ const CFDPasswordForm = observer(
error_type,
form_error,
has_mt5_account,
- is_real_financial_stp,
onCancel,
onForgotPassword,
platform,
should_set_trading_password,
submitPassword,
validatePassword,
+ account_type,
}: TCFDPasswordFormProps) => {
const { isDesktop } = useDevice();
- const { product, account_type } = useCfdStore();
- const [checked, setChecked] = React.useState(
- !(product === PRODUCT.ZEROSPREAD && account_type.category === CATEGORY.REAL)
- );
+ const { jurisdiction_selected_shortcode } = useCfdStore();
+ const [checked, setChecked] = React.useState(false);
+ const need_tnc = jurisdiction_selected_shortcode !== 'svg' && account_type.category === CATEGORY.REAL;
const button_label = React.useMemo(() => {
if (error_type === 'PasswordReset') {
@@ -520,10 +427,11 @@ const CFDPasswordForm = observer(
validatePassword={validatePassword}
submitPassword={submitPassword}
has_mt5_account={has_mt5_account}
- is_real_financial_stp={is_real_financial_stp}
+ need_tnc={need_tnc}
/>
);
}
+ // enter password modal
return (
(