From 5d6150f53da663443cb80493228a4ad2d4e07e72 Mon Sep 17 00:00:00 2001 From: Likhith Kolayari <98398322+likhith-deriv@users.noreply.github.com> Date: Wed, 26 Jul 2023 11:28:22 +0400 Subject: [PATCH] Likhith/87594/trigger onfido checks for high risk client (#7646) * feat: added onfido check for high risk client * feat: :zap: Incorporated POA for Labuan when status is idv_photoid * fix: failing testcase * feat: reverted the change * feat: added missing config * feat: added POA * feat: :sparkles: added POA trigger for IDV+photot status * fix: :recycle: incorporated review comments * chore: incorporated review comments * feat: :sparkles: incorporated IDV revoked status * refactor: :recycle: refactored code * refactor: :recycle: incorporated review comments * feat: :recycle: incorporated review comments * feat: resolved issue with POA * fix: :bug: Trigger POA only in user is idv+photo verified for labuan * fix: :sparkles: incorporated Resubmission triggers * feat: incorporated testcases * chore: trigger rebuild * fix: resolved issue with POA trigger for idv+photo clients * chore: :green_heart: trigger build * fix: :bug: resolved bugs regd high risk DBVI account * Likhith/incorporate deriv hooks (#42) * feat: :sparkles: installed deriv-hooks * feat: :sparkles: incorporated a new hook * fix: :white_check_mark: added testcase * feat: incorporated hook * fix: :art: reverted changes of hooks implementation * fix: :zap: added testcases --------- Co-authored-by: Matin shafiei --- packages/account/package.json | 1 + .../poa/status/status-codes/status-codes.ts | 4 +- .../account/src/Types/common-prop.type.ts | 4 + .../src/components/cfds-listing/index.tsx | 76 ++++++++++++++---- packages/cfd/package.json | 1 + packages/cfd/src/Components/cfd-poa.tsx | 36 ++++++--- ...-financial-stp-real-account-signup.spec.js | 79 +++++++++++++++---- .../src/Containers/cfd-dbvi-onboarding.tsx | 20 ++++- .../cfd-financial-stp-real-account-signup.tsx | 42 +++++++--- .../jurisdiction-modal-content-wrapper.tsx | 8 +- packages/cfd/types.ts | 3 + .../useIsAccountStatusPresent.spec.tsx | 42 ++++++++++ packages/hooks/src/index.ts | 1 + .../hooks/src/useIsAccountStatusPresent.ts | 59 ++++++++++++++ packages/shared/src/utils/cfd/cfd.ts | 25 ++++-- 15 files changed, 336 insertions(+), 65 deletions(-) create mode 100644 packages/hooks/src/__tests__/useIsAccountStatusPresent.spec.tsx create mode 100644 packages/hooks/src/useIsAccountStatusPresent.ts diff --git a/packages/account/package.json b/packages/account/package.json index 6feecfbc8024..bee6b47f0d0f 100644 --- a/packages/account/package.json +++ b/packages/account/package.json @@ -30,6 +30,7 @@ "@binary-com/binary-document-uploader": "^2.4.7", "@deriv/api-types": "^1.0.94", "@deriv/components": "^1.0.0", + "@deriv/hooks": "^1.0.0", "@deriv/shared": "^1.0.0", "@deriv/stores":"^1.0.0", "@deriv/translations": "^1.0.0", diff --git a/packages/account/src/Components/poa/status/status-codes/status-codes.ts b/packages/account/src/Components/poa/status/status-codes/status-codes.ts index 913d00353861..8a44a987f1a2 100644 --- a/packages/account/src/Components/poa/status/status-codes/status-codes.ts +++ b/packages/account/src/Components/poa/status/status-codes/status-codes.ts @@ -1,6 +1,6 @@ -type TPoaStatusCodes = Readonly>; +import { TVerificationStatus } from 'Types'; -export const poa_status_codes: TPoaStatusCodes = { +export const poa_status_codes: TVerificationStatus = { none: 'none', pending: 'pending', rejected: 'rejected', diff --git a/packages/account/src/Types/common-prop.type.ts b/packages/account/src/Types/common-prop.type.ts index b964c0e584f6..204e11a8985e 100644 --- a/packages/account/src/Types/common-prop.type.ts +++ b/packages/account/src/Types/common-prop.type.ts @@ -149,3 +149,7 @@ export type TPersonalDetailsForm = { } & FormikProps; export type TInputFieldValues = Record; + +export type TVerificationStatus = Readonly< + Record<'none' | 'pending' | 'rejected' | 'verified' | 'expired' | 'suspected', string> +>; diff --git a/packages/appstore/src/components/cfds-listing/index.tsx b/packages/appstore/src/components/cfds-listing/index.tsx index f70705787c46..2b2986b48f75 100644 --- a/packages/appstore/src/components/cfds-listing/index.tsx +++ b/packages/appstore/src/components/cfds-listing/index.tsx @@ -1,18 +1,18 @@ import React from 'react'; +import { observer } from 'mobx-react-lite'; import { Text, StaticUrl } from '@deriv/components'; +import { isMobile, formatMoney, getAuthenticationStatusInfo, Jurisdiction } from '@deriv/shared'; import { localize, Localize } from '@deriv/translations'; import ListingContainer from 'Components/containers/listing-container'; -import './cfds-listing.scss'; -import { useStores } from 'Stores/index'; -import { observer } from 'mobx-react-lite'; import AddOptionsAccount from 'Components/add-options-account'; -import { isMobile, formatMoney } from '@deriv/shared'; import TradingAppCard from 'Components/containers/trading-app-card'; -import { AvailableAccount, TDetailsOfEachMT5Loginid } from 'Types'; import PlatformLoader from 'Components/pre-loader/platform-loader'; import GetMoreAccounts from 'Components/get-more-accounts'; import { Actions } from 'Components/containers/trading-app-card-actions'; import { getHasDivider } from 'Constants/utils'; +import { useStores } from 'Stores/index'; +import { AvailableAccount, TDetailsOfEachMT5Loginid } from 'Types'; +import './cfds-listing.scss'; type TDetailedExistingAccount = AvailableAccount & TDetailsOfEachMT5Loginid & @@ -55,18 +55,57 @@ const CFDsListing = () => { } = traders_hub; const { toggleCompareAccountsModal, setAccountType } = cfd; - const { is_landing_company_loaded, real_account_creation_unlock_date } = client; + const { is_landing_company_loaded, real_account_creation_unlock_date, account_status } = client; const { setAppstorePlatform } = common; 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 getMT5AccountAuthStatus = (current_acc_status: string) => { - if (current_acc_status === 'proof_failed') { - return 'failed'; - } else if (current_acc_status === 'verification_pending') { - return 'pending'; + const { poi_pending_for_bvi_labuan, poi_resubmit_for_bvi_labuan, poa_resubmit_for_labuan, is_idv_revoked } = + getAuthenticationStatusInfo(account_status); + + const getAuthStatus = (status_list: boolean[]) => status_list.some(status => status); + + const getMT5AccountAuthStatus = (current_acc_status: string, jurisdiction?: string) => { + if (jurisdiction) { + switch (jurisdiction) { + case Jurisdiction.BVI: { + if ( + getAuthStatus([ + is_idv_revoked, + poi_resubmit_for_bvi_labuan, + current_acc_status === 'proof_failed', + ]) + ) { + return 'failed'; + } else if ( + getAuthStatus([poi_pending_for_bvi_labuan, current_acc_status === 'verification_pending']) + ) { + return 'pending'; + } + return null; + } + case Jurisdiction.LABUAN: { + if ( + getAuthStatus([ + poa_resubmit_for_labuan, + is_idv_revoked, + poi_resubmit_for_bvi_labuan, + current_acc_status === 'proof_failed', + ]) + ) { + return 'failed'; + } else if ( + getAuthStatus([poi_pending_for_bvi_labuan, current_acc_status === 'verification_pending']) + ) { + return 'pending'; + } + return null; + } + default: + return null; + } } return null; }; @@ -137,12 +176,17 @@ const CFDsListing = () => { {is_landing_company_loaded ? ( - <> + {combined_cfd_mt5_accounts.map((existing_account: TDetailedExistingAccount, index: number) => { const list_size = combined_cfd_mt5_accounts.length; - const has_mt5_account_status = existing_account.status - ? getMT5AccountAuthStatus(existing_account.status) - : null; + const has_mt5_account_status = + existing_account.status || is_idv_revoked + ? getMT5AccountAuthStatus( + existing_account.status, + existing_account?.short_code_and_region?.toLowerCase() + ) + : null; + return ( { description={localize('Get more Deriv MT5 account with different type and jurisdiction.')} /> )} - + ) : ( )} diff --git a/packages/cfd/package.json b/packages/cfd/package.json index 8846f3b980c5..25b62e5b2b99 100644 --- a/packages/cfd/package.json +++ b/packages/cfd/package.json @@ -86,6 +86,7 @@ "@deriv/api-types": "^1.0.94", "@deriv/components": "^1.0.0", "@deriv/deriv-api": "^1.0.11", + "@deriv/hooks": "^1.0.0", "@deriv/shared": "^1.0.0", "@deriv/stores": "^1.0.0", "@deriv/translations": "^1.0.0", diff --git a/packages/cfd/src/Components/cfd-poa.tsx b/packages/cfd/src/Components/cfd-poa.tsx index b1961950dfc6..6d8cf3f75657 100644 --- a/packages/cfd/src/Components/cfd-poa.tsx +++ b/packages/cfd/src/Components/cfd-poa.tsx @@ -1,24 +1,25 @@ -import { Field, Formik, FieldProps, FormikHelpers, FormikProps, FormikErrors } from 'formik'; import React from 'react'; +import { Field, FieldProps, Formik, FormikErrors, FormikHelpers, FormikProps } from 'formik'; +import { AccountStatusResponse, GetSettings, StatesList } from '@deriv/api-types'; import { AutoHeightWrapper, - FormSubmitButton, - ThemedScrollbars, + DesktopWrapper, + Div100vhContainer, Dropdown, + FormSubmitButton, Loading, - Div100vhContainer, + MobileWrapper, Modal, SelectNative, - DesktopWrapper, - MobileWrapper, - useStateCallback, Text, + ThemedScrollbars, + useStateCallback, } from '@deriv/components'; import { FileUploaderContainer, FormSubHeader, PoaStatusCodes } from '@deriv/account'; import { localize } from '@deriv/translations'; -import { isDesktop, isMobile, validAddress, validLength, validLetterSymbol, validPostCode, WS } from '@deriv/shared'; +import { WS, isDesktop, isMobile, validAddress, validLength, validLetterSymbol, validPostCode } from '@deriv/shared'; import { InputField } from './cfd-personal-details-form'; -import { GetSettings, StatesList, AccountStatusResponse } from '@deriv/api-types'; +import { TJurisdiction } from '../../types'; type TErrors = { code: string; @@ -79,11 +80,13 @@ export type TCFDPOAProps = { onSubmit: (index: number, value: TFormValues) => void; refreshNotifications: () => void; form_error: string; - get_settings: GetSettings; + account_settings: GetSettings; height: string; states_list: StatesList; storeProofOfAddress: TStoreProofOfAddress; value: TFormValue; + jurisdiction_selected_shortcode: TJurisdiction; + is_authenticated_with_idv_photoid: boolean; }; type TUpload = { upload: () => void; @@ -91,7 +94,15 @@ type TUpload = { let file_uploader_ref: React.RefObject; -const CFDPOA = ({ onSave, index, onSubmit, refreshNotifications, ...props }: TCFDPOAProps) => { +const CFDPOA = ({ + onSave, + index, + onSubmit, + refreshNotifications, + jurisdiction_selected_shortcode, + is_authenticated_with_idv_photoid, + ...props +}: TCFDPOAProps) => { const form = React.useRef | null>(null); const [is_loading, setIsLoading] = React.useState(true); @@ -259,7 +270,8 @@ const CFDPOA = ({ onSave, index, onSubmit, refreshNotifications, ...props }: TCF } = props; const { form_error, poa_status } = form_state; - const is_form_visible = !is_loading && poa_status !== PoaStatusCodes.verified; + const is_form_visible = + !is_loading && (poa_status !== PoaStatusCodes.verified || is_authenticated_with_idv_photoid); return ( ({ ...jest.requireActual('@deriv/account'), FormSubHeader: () =>
FormSubHeader
, })); -jest.mock('../../Components/cfd-poa', () => jest.fn(() =>
CFDPOA
)); +const MockComponent = ({ prevStep, nextStep }) => ( +
+ + +
+); + +jest.mock('../../Components/cfd-poa', () => + jest.fn(({ onCancel, onSubmit }) => ( +
+ CFDPOA + +
+ )) +); jest.mock('../../Components/cfd-poi', () => - jest.fn(({ onSubmit }) => ( -
onSubmit(0, {})}> + 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(); @@ -26,14 +47,6 @@ const getByTextFn = (text, should_be) => { } }; -const toHavaClassFn = (item, class_name, should_have) => { - if (should_have) { - expect(item).toHaveClass(class_name); - } else { - expect(item).not.toHaveClass(class_name); - } -}; - const testAllStepsFn = (steps, step_no) => { steps.map((step, index) => { if (index === step_no) { @@ -181,6 +194,7 @@ describe('', () => { }); it('should render properly for the first step content', () => { + getAuthenticationStatusInfo.mockReturnValueOnce({ need_poi_for_bvi_labuan: true }); render(, { wrapper: ({ children }) => {children}, }); @@ -189,14 +203,51 @@ describe('', () => { }); it('should render properly for the second step content', () => { + getAuthenticationStatusInfo.mockReturnValueOnce({ poa_resubmit_for_labuan: true }); const { getByTestId } = render(, { wrapper: ({ children }) => {children}, }); - const div = getByTestId('poa-form'); + testAllStepsFn(steps, 1); + }); - fireEvent.click(div); + 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_vanuatu_maltainvest: 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 new_mock_store = { + ...mockRootStore, + modules: { + ...mockRootStore.modules, + cfd: { + ...mockRootStore.modules.cfd, + jurisdiction_selected_shortcode: 'labuan', + }, + }, + }; + + getAuthenticationStatusInfo.mockReturnValueOnce({ need_poi_for_vanuatu_maltainvest: true }); + + render(, { + wrapper: ({ children }) => {children}, + }); testAllStepsFn(steps, 1); }); }); diff --git a/packages/cfd/src/Containers/cfd-dbvi-onboarding.tsx b/packages/cfd/src/Containers/cfd-dbvi-onboarding.tsx index 35899f963d04..75cbbd09df72 100644 --- a/packages/cfd/src/Containers/cfd-dbvi-onboarding.tsx +++ b/packages/cfd/src/Containers/cfd-dbvi-onboarding.tsx @@ -1,4 +1,6 @@ import React from 'react'; +import { PoiPoaDocsSubmitted } from '@deriv/account'; +import { AccountStatusResponse } from '@deriv/api-types'; import { Button, DesktopWrapper, @@ -11,9 +13,7 @@ import { UILoader, } from '@deriv/components'; import { localize } from '@deriv/translations'; -import { PoiPoaDocsSubmitted } from '@deriv/account'; import { getAuthenticationStatusInfo, isMobile, WS, Jurisdiction } from '@deriv/shared'; -import { AccountStatusResponse } from '@deriv/api-types'; import CFDFinancialStpRealAccountSignup from './cfd-financial-stp-real-account-signup'; import { observer, useStore } from '@deriv/stores'; import { useCfdStore } from '../Stores/Modules/CFD/Helpers/useCfdStores'; @@ -59,8 +59,14 @@ const CFDDbviOnboarding = observer(() => { const { get_account_status } = response; if (get_account_status?.authentication) { - const { poi_acknowledged_for_vanuatu_maltainvest, poi_acknowledged_for_bvi_labuan, poa_acknowledged } = - getAuthenticationStatusInfo(get_account_status); + const { + poi_acknowledged_for_vanuatu_maltainvest, + poi_acknowledged_for_bvi_labuan, + poa_acknowledged, + poa_resubmit_for_labuan, + need_poa_submission, + } = getAuthenticationStatusInfo(get_account_status); + if (jurisdiction_selected_shortcode === Jurisdiction.VANUATU) { setShowSubmittedModal( poi_acknowledged_for_vanuatu_maltainvest && @@ -69,6 +75,12 @@ const CFDDbviOnboarding = observer(() => { ); } else if (jurisdiction_selected_shortcode === Jurisdiction.MALTA_INVEST) { setShowSubmittedModal(poi_acknowledged_for_vanuatu_maltainvest && poa_acknowledged); + } else if (jurisdiction_selected_shortcode === Jurisdiction.LABUAN) { + /* When verified with IDV+ Photo ID, POA is auto verified */ + const is_poa_submitted = poa_resubmit_for_labuan ? false : !need_poa_submission; + setShowSubmittedModal( + poi_acknowledged_for_bvi_labuan && has_submitted_cfd_personal_details && is_poa_submitted + ); } else setShowSubmittedModal( poi_acknowledged_for_bvi_labuan && poa_acknowledged && has_submitted_cfd_personal_details 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 index 8f34449b3e2e..14dd74e08b47 100644 --- a/packages/cfd/src/Containers/cfd-financial-stp-real-account-signup.tsx +++ b/packages/cfd/src/Containers/cfd-financial-stp-real-account-signup.tsx @@ -1,5 +1,6 @@ import React from 'react'; import { Div100vhContainer } from '@deriv/components'; +import { useIsAccountStatusPresent } from '@deriv/hooks'; import { isDesktop, getAuthenticationStatusInfo, Jurisdiction } from '@deriv/shared'; import CFDPOA from '../Components/cfd-poa'; import CFDPOI from '../Components/cfd-poi'; @@ -87,6 +88,8 @@ const CFDFinancialStpRealAccountSignup = observer(({ onFinish }: TCFDFinancialSt const { need_poi_for_vanuatu_maltainvest, need_poi_for_bvi_labuan } = getAuthenticationStatusInfo(account_status); + const is_authenticated_with_idv_photoid = useIsAccountStatusPresent('authenticated_with_idv_photoid'); + const poi_config: TItemsState = { body: CFDPOI, form_value: { @@ -112,7 +115,13 @@ const CFDFinancialStpRealAccountSignup = observer(({ onFinish }: TCFDFinancialSt address_postcode: account_settings.address_postcode, upload_file: '', }, - forwarded_props: ['states_list', 'account_settings', 'storeProofOfAddress', 'refreshNotifications'], + forwarded_props: [ + 'states_list', + 'account_settings', + 'storeProofOfAddress', + 'refreshNotifications', + 'jurisdiction_selected_shortcode', + ], }; const personal_details_config: TItemsState = { @@ -133,14 +142,20 @@ const CFDFinancialStpRealAccountSignup = observer(({ onFinish }: TCFDFinancialSt } return need_poi_for_bvi_labuan; }; - const should_show_poa = !['pending', 'verified'].includes(authentication_status.document_status); + + const shouldShowPOA = () => { + if (Jurisdiction.LABUAN === jurisdiction_selected_shortcode && is_authenticated_with_idv_photoid) { + return true; + } + return !['pending', 'verified'].includes(authentication_status.document_status); + }; const should_show_personal_details = !has_submitted_cfd_personal_details && jurisdiction_selected_shortcode !== Jurisdiction.MALTA_INVEST; const verification_configs = [ ...(should_show_poi() ? [poi_config] : []), - ...(should_show_poa ? [poa_config] : []), + ...(shouldShowPOA() ? [poa_config] : []), ...(should_show_personal_details ? [personal_details_config] : []), ]; @@ -193,13 +208,20 @@ const CFDFinancialStpRealAccountSignup = observer(({ onFinish }: TCFDFinancialSt const form_value = getCurrent('form_value'); - const passthrough = ( - (getCurrent('forwarded_props') || []) as TItemsState['forwarded_props'] - ).reduce((forwarded_prop, item) => { - return Object.assign(forwarded_prop, { - [item]: passthroughProps[item], - }); - }, {}); + const passthrough: Partial & { + is_authenticated_with_idv_photoid?: boolean; + } = ((getCurrent('forwarded_props') || []) as TItemsState['forwarded_props']).reduce( + (forwarded_prop, item) => { + return Object.assign(forwarded_prop, { + [item]: passthroughProps[item], + }); + }, + {} + ); + + if (shouldShowPOA()) { + passthrough.is_authenticated_with_idv_photoid = is_authenticated_with_idv_photoid; + } return ( { @@ -166,7 +167,12 @@ const JurisdictionModalContentWrapper = observer(({ openPasswordModal }: TJurisd toggleCFDVerificationModal(); } } else if (is_labuan_selected) { - if (poi_acknowledged_for_bvi_labuan && poa_acknowledged && has_submitted_cfd_personal_details) { + if ( + poi_acknowledged_for_bvi_labuan && + poa_acknowledged && + has_submitted_cfd_personal_details && + !poa_resubmit_for_labuan + ) { openPasswordModal(type_of_account); } else { toggleCFDVerificationModal(); diff --git a/packages/cfd/types.ts b/packages/cfd/types.ts index 6389dd6f436a..9474ea0e54be 100644 --- a/packages/cfd/types.ts +++ b/packages/cfd/types.ts @@ -1,3 +1,6 @@ +import { Jurisdiction } from '@deriv/shared'; import type { TCoreStores } from '@deriv/stores/types'; export type TTradingPlatformAvailableAccount = TCoreStores['client']['trading_platform_available_accounts'][number]; + +export type TJurisdiction = typeof Jurisdiction[keyof typeof Jurisdiction]; diff --git a/packages/hooks/src/__tests__/useIsAccountStatusPresent.spec.tsx b/packages/hooks/src/__tests__/useIsAccountStatusPresent.spec.tsx new file mode 100644 index 000000000000..eeffe186e82a --- /dev/null +++ b/packages/hooks/src/__tests__/useIsAccountStatusPresent.spec.tsx @@ -0,0 +1,42 @@ +import * as React from 'react'; +import { mockStore, StoreProvider } from '@deriv/stores'; +import { renderHook } from '@testing-library/react-hooks'; +import { useIsAccountStatusPresent } from '../useIsAccountStatusPresent'; + +describe('useIsAccountStatusPresent', () => { + it('should return false when the status is not present', () => { + const mock = mockStore({ + client: { + account_status: { + status: [], + }, + }, + }); + + const wrapper = ({ children }: { children: JSX.Element }) => ( + {children} + ); + + const { result } = renderHook(() => useIsAccountStatusPresent('cashier_locked'), { wrapper }); + + expect(result.current).toBeFalsy(); + }); + + it('should return true when the status is present', () => { + const mock = mockStore({ + client: { + account_status: { + status: ['cashier_locked', 'unwelcome'], + }, + }, + }); + + const wrapper = ({ children }: { children: JSX.Element }) => ( + {children} + ); + + const { result } = renderHook(() => useIsAccountStatusPresent('cashier_locked'), { wrapper }); + + expect(result.current).toBeTruthy(); + }); +}); diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts index 4442969638f9..e0f6157a6d73 100644 --- a/packages/hooks/src/index.ts +++ b/packages/hooks/src/index.ts @@ -42,3 +42,4 @@ export { default as usePlatformRealAccounts } from './usePlatformRealAccounts'; export { default as useRealSTPAccount } from './useRealSTPAccount'; export { default as useTotalAccountBalance } from './useTotalAccountBalance'; export { default as useVerifyEmail } from './useVerifyEmail'; +export { useIsAccountStatusPresent } from './useIsAccountStatusPresent'; diff --git a/packages/hooks/src/useIsAccountStatusPresent.ts b/packages/hooks/src/useIsAccountStatusPresent.ts new file mode 100644 index 000000000000..f6b467cd0089 --- /dev/null +++ b/packages/hooks/src/useIsAccountStatusPresent.ts @@ -0,0 +1,59 @@ +import React from 'react'; +import { useStore } from '@deriv/stores'; + +const AccountStatusList = [ + 'address_verified', + 'age_verification', + 'allow_document_upload', + 'allow_poa_resubmission', + 'allow_poi_resubmission', + 'authenticated', + 'authenticated_with_idv_photoid', + 'cashier_locked', + 'crs_tin_information', + 'deposit_attempt', + 'deposit_locked', + 'df_deposit_requires_poi', + 'disabled', + 'document_expired', + 'document_expiring_soon', + 'document_under_review', + 'dxtrade_password_not_set', + 'financial_assessment_not_complete', + 'financial_information_not_complete', + 'financial_risk_approval', + 'idv_revoked', + 'max_turnover_limit_not_set', + 'mt5_password_not_set', + 'mt5_withdrawal_locked', + 'needs_affiliate_coc_approval', + 'no_trading', + 'no_withdrawal_or_trading', + 'p2p_blocked_for_pa', + 'pa_withdrawal_explicitly_allowed', + 'password_reset_required', + 'personal_details_locked', + 'poi_name_mismatch', + 'professional', + 'professional_requested', + 'professional_rejected', + 'shared_payment_method', + 'social_signup', + 'transfers_blocked', + 'trading_experience_not_complete', + 'ukgc_funds_protection', + 'unwelcome', + 'withdrawal_locked', +] as const; + +type TAccountStatus = typeof AccountStatusList[number]; + +export const useIsAccountStatusPresent = (status: TAccountStatus) => { + const { + client: { account_status }, + } = useStore(); + + const status_list = account_status?.status; + + return React.useMemo(() => status_list?.includes(status) ?? false, [status_list, status]); +}; diff --git a/packages/shared/src/utils/cfd/cfd.ts b/packages/shared/src/utils/cfd/cfd.ts index e1393316bec2..ed40356091ef 100644 --- a/packages/shared/src/utils/cfd/cfd.ts +++ b/packages/shared/src/utils/cfd/cfd.ts @@ -1,6 +1,6 @@ -import { CFD_PLATFORMS } from '../platform'; -import { LandingCompany, GetAccountStatus, DetailsOfEachMT5Loginid } from '@deriv/api-types'; +import { DetailsOfEachMT5Loginid, GetAccountStatus, LandingCompany } from '@deriv/api-types'; import { localize } from '@deriv/translations'; +import { CFD_PLATFORMS } from '../platform'; let CFD_text_translated: { [key: string]: () => void }; @@ -256,6 +256,8 @@ export const isLandingCompanyEnabled = ({ landing_companies, platform, type }: T }; export const getAuthenticationStatusInfo = (account_status: GetAccountStatus) => { + const risk_classification = account_status.risk_classification; + const poa_status = account_status?.authentication?.document?.status || ''; const poi_status = account_status?.authentication?.identity?.status || ''; @@ -263,6 +265,9 @@ export const getAuthenticationStatusInfo = (account_status: GetAccountStatus) => const onfido_status = account_status?.authentication?.identity?.services?.onfido?.status; const manual_status = account_status?.authentication?.identity?.services?.manual?.status; + const is_authenticated_with_idv_photoid = account_status?.status?.includes('authenticated_with_idv_photoid'); + const is_idv_revoked = account_status?.status?.includes('idv_revoked'); + const acknowledged_status = ['pending', 'verified']; const failed_cases = ['rejected', 'expired', 'suspected']; @@ -301,10 +306,15 @@ export const getAuthenticationStatusInfo = (account_status: GetAccountStatus) => const poi_poa_verified_for_vanuatu_maltainvest = poi_verified_for_vanuatu_maltainvest && poa_verified; //bvi-labuan - const poi_acknowledged_for_bvi_labuan = - (idv_status && acknowledged_status.includes(idv_status)) || - (onfido_status && acknowledged_status.includes(onfido_status)) || - (manual_status && acknowledged_status.includes(manual_status)); + let poi_acknowledged_for_bvi_labuan; + if (risk_classification === 'high') { + poi_acknowledged_for_bvi_labuan = onfido_status && acknowledged_status.includes(onfido_status); + } else { + poi_acknowledged_for_bvi_labuan = + (idv_status && acknowledged_status.includes(idv_status)) || + (onfido_status && acknowledged_status.includes(onfido_status)) || + (manual_status && acknowledged_status.includes(manual_status)); + } const need_poi_for_bvi_labuan = !poi_acknowledged_for_bvi_labuan; const poi_not_submitted_for_bvi_labuan = @@ -325,6 +335,7 @@ export const getAuthenticationStatusInfo = (account_status: GetAccountStatus) => const poi_resubmit_for_bvi_labuan = !poi_pending_for_bvi_labuan && !poi_not_submitted_for_bvi_labuan && !poi_verified_for_bvi_labuan; const poi_poa_verified_for_bvi_labuan = poi_verified_for_bvi_labuan && poa_verified; + const poa_resubmit_for_labuan = is_authenticated_with_idv_photoid; return { poa_status, @@ -355,5 +366,7 @@ export const getAuthenticationStatusInfo = (account_status: GetAccountStatus) => poi_resubmit_for_vanuatu_maltainvest, poi_resubmit_for_bvi_labuan, poa_pending, + poa_resubmit_for_labuan, + is_idv_revoked, }; };