Skip to content

Commit

Permalink
[WALL] Lubega / WALL-3317 & WALL-3318 / Wallets Withdrawal and Deposi…
Browse files Browse the repository at this point in the history
…t Locked scenarios (#13188)

* feat: withdrawal and deposit locked

* fix: improved sonarcloud analysis

* fix: applied comments

* fix: simplified logic

* fix: applied comments

* fix: applied css bem styling

* fix: updated and implemented wallet link component

* fix: removed classnames

* fix: applied comments
  • Loading branch information
lubega-deriv authored Jan 31, 2024
1 parent f717142 commit 88773e6
Show file tree
Hide file tree
Showing 19 changed files with 1,175 additions and 6 deletions.
1 change: 1 addition & 0 deletions packages/api/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export { default as useAccesiblePlatforms } from './useAccesiblePlatforms';
export { default as useAvailableMT5Accounts } from './useAvailableMT5Accounts';
export { default as useAvailableWallets } from './useAvailableWallets';
export { default as useBalance } from './useBalance';
export { default as useCashierValidation } from './useCashierValidation';
export { default as useCloseDerivAccount } from './useCloseDerivAccount';
export { default as useCFDAccountsList } from './useCFDAccountsList';
export { default as useCFDCompareAccounts } from './useCFDCompareAccounts';
Expand Down
44 changes: 44 additions & 0 deletions packages/api/src/hooks/useCashierValidation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { useMemo } from 'react';
import useGetAccountStatus from './useGetAccountStatus';

/** A custom hook to check the cashier validations for the cashier locked scenarios. */
const useCashierValidation = () => {
const { data: get_account_status_data, ...rest } = useGetAccountStatus();

const modified_cashier_validation = useMemo(() => {
if (!get_account_status_data?.cashier_validation) return;

const cashier_validation = new Set(get_account_status_data?.cashier_validation);

return {
transfer_blocked: cashier_validation.has('transfer_blocked'),
no_residence: cashier_validation.has('no_residence'),
unwelcome_status: cashier_validation.has('unwelcome_status'),
self_exclusion: cashier_validation.has('SelfExclusion'),
no_withdrawal_or_trading_status: cashier_validation.has('no_withdrawal_or_trading_status'),
only_pa_withdrawals_allowed_status: cashier_validation.has('only_pa_withdrawals_allowed_status'),
withdraw_service_unavailable_for_pa: cashier_validation.has('WithdrawServiceUnavailableForPA'),
withdrawal_locked_status: cashier_validation.has('withdrawal_locked_status'),
documents_expired: cashier_validation.has('documents_expired'),
cashier_locked_status: cashier_validation.has('cashier_locked_status'),
disabled_status: cashier_validation.has('disabled_status'),
financial_assessment_required: cashier_validation.has('FinancialAssessmentRequired'),
ask_currency: cashier_validation.has('ASK_CURRENCY'),
ask_authenticate: cashier_validation.has('ASK_AUTHENTICATE'),
ask_financial_risk_approval: cashier_validation.has('ASK_FINANCIAL_RISK_APPROVAL'),
ask_tin_information: cashier_validation.has('ASK_TIN_INFORMATION'),
ask_self_exclusion_max_turnover_set: cashier_validation.has('ASK_SELF_EXCLUSION_MAX_TURNOVER_SET'),
ask_fix_details: cashier_validation.has('ASK_FIX_DETAILS'),
ask_uk_funds_protection: cashier_validation.has('ASK_UK_FUNDS_PROTECTION'),
pa_commision_withdrawal_limit: cashier_validation.has('PACommisionWithdrawalLimit'),
};
}, [get_account_status_data?.cashier_validation]);

return {
/** The cashier validation response. */
data: modified_cashier_validation,
...rest,
};
};

export default useCashierValidation;
21 changes: 20 additions & 1 deletion packages/wallets/src/components/Base/WalletLink/WalletLink.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@
.wallets-link {
cursor: pointer;
color: var(--brand-coral, #ff444f);
text-decoration: underline;
border: none;
background: none;
font-size: inherit;
padding: 0;

&__variant {
&--normal {
text-decoration: underline;
}

&--bold {
font-weight: bold;
text-decoration: none;

&:hover {
text-decoration: underline;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ import React from 'react';
import { getStaticUrl } from '../../../helpers/urls';
import './WalletLink.scss';

type TVariant = 'bold' | 'normal';

interface LinkProps {
children?: React.ReactNode;
href?: React.AnchorHTMLAttributes<HTMLAnchorElement>['href'];
staticUrl?: React.AnchorHTMLAttributes<HTMLAnchorElement>['href'];
variant?: TVariant;
}

const WalletLink: React.FC<LinkProps> = ({ children, href, staticUrl }) => (
const WalletLink: React.FC<LinkProps> = ({ children, href, staticUrl, variant = 'normal' }) => (
<a
className='wallets-link'
className={`wallets-link wallets-link__variant--${variant}`}
href={href ?? (staticUrl ? getStaticUrl(staticUrl) : '#')}
rel='noopener noreferrer'
target='_blank'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type TProps = {
| ReactElement<ComponentProps<typeof WalletButton>>
| ReactElement<ComponentProps<typeof WalletButtonGroup>>
| null;
title?: string;
title?: ReactNode;
titleSize?: ComponentProps<typeof WalletText>['size'];
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { WalletResetBalance } from '../../flows/WalletResetBalance';
import { WalletTransactions } from '../../flows/WalletTransactions';
import { WalletTransfer } from '../../flows/WalletTransfer';
import { WalletWithdrawal } from '../../flows/WalletWithdrawal';
import { DepositLocked, WithdrawalLocked } from '../../screens';

const WalletCashierContent = () => {
const history = useHistory();
Expand All @@ -24,7 +25,12 @@ const WalletCashierContent = () => {
}
}, [isTransfer, isDeposit, isTransactions, isWithdraw, isResetBalance, isFiatOnRamp, history]);

if (isDeposit) return <WalletDeposit />;
if (isDeposit)
return (
<DepositLocked>
<WalletDeposit />
</DepositLocked>
);

if (isFiatOnRamp) return <WalletFiatOnRamp />;

Expand All @@ -35,7 +41,11 @@ const WalletCashierContent = () => {
if (isTransactions) return <WalletTransactions />;

if (isWithdraw) {
return <WalletWithdrawal />;
return (
<WithdrawalLocked>
<WalletWithdrawal />
</WithdrawalLocked>
);
}

return <></>;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.wallets-deposit-locked {
margin-top: 9.2rem; //140px - 48px from cashier content

@include mobile {
margin-top: 1.6rem; //40px - 16px from cashier content
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React from 'react';
import { Trans } from 'react-i18next';
import {
useAccountStatus,
useActiveWalletAccount,
useAuthentication,
useCashierValidation,
useQuery,
useSettings,
} from '@deriv/api';
import { WalletsActionScreen } from '../../../../components';
import getDepositLockedDesc from './DepositLockedContent';
import './DepositLocked.scss';

const DepositLocked: React.FC<React.PropsWithChildren> = ({ children }) => {
const { data: activeWallet } = useActiveWalletAccount();
const { data: settings } = useSettings();
const { data: websiteStatus } = useQuery('website_status');
const { data: authentication } = useAuthentication();
const { data: cashierValidation } = useCashierValidation();
const { data: status } = useAccountStatus();

const currency = activeWallet?.currency || 'USD';
const excludedUntil = activeWallet?.excluded_until;
const isMFAccount = activeWallet?.loginid?.startsWith('MF') || false;

const clientTncStatus = settings?.client_tnc_status;
const websiteTncVersion = websiteStatus?.website_status?.terms_conditions_version;

const poaNeedsVerification = authentication?.is_poa_needed;
const poiNeedsVerification = authentication?.is_poa_needed;
const poaStatus = authentication?.poa_status || 'none';
const poiStatus = authentication?.poi_status || 'none';

const askFixDetails = cashierValidation?.ask_fix_details;
const selfExclusion = cashierValidation?.self_exclusion;
const unwelcomeStatus = cashierValidation?.unwelcome_status;

const isDepositLocked = status?.is_deposit_locked;
const financialInformationNotComplete = status?.is_financial_information_not_complete;
const tradingExperienceNotComplete = status?.is_trading_experience_not_complete;

if (isDepositLocked) {
return (
<div className='wallets-deposit-locked'>
<WalletsActionScreen
description={
getDepositLockedDesc({
askFixDetails,
clientTncStatus,
excludedUntil,
financialInformationNotComplete,
isMFAccount,
poaNeedsVerification,
poaStatus,
poiNeedsVerification,
poiStatus,
selfExclusion,
tradingExperienceNotComplete,
unwelcomeStatus,
websiteTncVersion,
})?.description
}
title={
<Trans
defaults='Deposits into your {{currency}} Wallet are temporarily locked.'
values={{ currency }}
/>
}
/>
</div>
);
}

return <>{children}</>;
};

export default DepositLocked;
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import React from 'react';
import { Trans } from 'react-i18next';
import { WalletLink, WalletText } from '../../../../components';

type TDepositLockedDescProps = {
askFixDetails?: boolean;
clientTncStatus?: string | null;
excludedUntil?: Date;
financialInformationNotComplete?: boolean;
isMFAccount: boolean;
poaNeedsVerification?: boolean;
poaStatus: string;
poiNeedsVerification?: boolean;
poiStatus: string;
selfExclusion?: boolean;
tradingExperienceNotComplete?: boolean;
unwelcomeStatus?: boolean;
websiteTncVersion?: string;
};

const getDepositLockedDesc = ({
askFixDetails,
clientTncStatus,
excludedUntil,
financialInformationNotComplete,
isMFAccount,
poaNeedsVerification,
poaStatus,
poiNeedsVerification,
poiStatus,
selfExclusion,
tradingExperienceNotComplete,
unwelcomeStatus,
websiteTncVersion,
}: TDepositLockedDescProps) => {
if (poiNeedsVerification && poiStatus !== 'none')
return {
description: (
<WalletText align='center'>
<Trans
components={[<WalletLink href='/account/proof-of-identity' key={0} variant='bold' />]}
defaults='To enable deposits, you must check your <0>proof of identity document verification status</0>.'
/>
</WalletText>
),
};

if (poaNeedsVerification && poaStatus !== 'none')
return {
description: (
<WalletText align='center'>
<Trans
components={[<WalletLink href='/account/proof-of-address' key={0} variant='bold' />]}
defaults='To enable deposits, you must check your <0>proof of address document verification status</0>.'
/>
</WalletText>
),
};

if (clientTncStatus !== websiteTncVersion)
return {
description: (
<WalletText align='center'>
<Trans
components={[<WalletLink key={0} staticUrl='/terms-and-conditions/#clients' variant='bold' />]}
defaults='To enable deposits, you must accept our <0>updated terms and conditions</0>.'
/>
</WalletText>
),
};

if (isMFAccount && (financialInformationNotComplete || tradingExperienceNotComplete))
return {
description: (
<WalletText align='center'>
<Trans
components={[<WalletLink href='/account/financial-assessment' key={0} variant='bold' />]}
defaults='To enable deposits, you must complete the <0>financial assessment form</0>.'
/>
</WalletText>
),
};

if (askFixDetails)
return {
description: (
<WalletText align='center'>
<Trans
components={[<WalletLink href='/account/personal-details' key={0} variant='bold' />]}
defaults='Your <0>personal details</0> are incomplete. Please go to your account settings and complete your personal details to enable deposits.'
/>
</WalletText>
),
};

if (selfExclusion)
return {
description: (
<WalletText align='center'>
<Trans
components={[
<button
className='wallets-link wallets-link__variant--bold'
key={0}
onClick={() => window.LC_API.open_chat_window()}
/>,
]}
defaults='You have chosen to exclude yourself from trading on our website until {{excludedUntil}}. If you are unable to place a trade or deposit after your self-exclusion period, please contact us via <0>live chat</0>.'
values={{ excludedUntil }}
/>
</WalletText>
),
};

if (unwelcomeStatus)
return {
description: (
<WalletText align='center'>
<Trans
components={[
<button
className='wallets-link wallets-link__variant--bold'
key={0}
onClick={() => window.LC_API.open_chat_window()}
/>,
]}
defaults='Please contact us via <0>live chat</0>.'
/>
</WalletText>
),
};
};

export default getDepositLockedDesc;
Loading

0 comments on commit 88773e6

Please sign in to comment.