Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WALL] Lubega / WALL-3517 / Withdrawal locked currency config load #13918

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions packages/api-v2/src/hooks/useCurrencyConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@ import useAuthorize from './useAuthorize';
/** A custom hook to get the currency config information from `website_status` endpoint and `crypto_config` endpoint. */
const useCurrencyConfig = () => {
const { isSuccess } = useAuthorize();
const { data: website_status_data, ...rest } = useQuery('website_status', {
const {
data: website_status_data,
isLoading: isWebsiteStatusLoading,
...rest
} = useQuery('website_status', {
options: {
enabled: isSuccess,
},
});
const { data: crypto_config_data } = useQuery('crypto_config', {
const { data: crypto_config_data, isLoading: isCryptConfigLoading } = useQuery('crypto_config', {
options: {
enabled: isSuccess,
},
Expand Down Expand Up @@ -103,6 +107,7 @@ const useCurrencyConfig = () => {
data: transformed_currencies_config,
/** Returns the currency config object for the given currency */
getConfig,
isLoading: isWebsiteStatusLoading || isCryptConfigLoading,
...rest,
};
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import {
useActiveWalletAccount,
useAuthentication,
useCashierValidation,
useCurrencyConfig,
} from '@deriv/api-v2';
import { WalletsActionScreen } from '../../../../components';
import getWithdrawalLockedDesc from './WithdrawalLockedContent';
import { Loader, WalletsActionScreen } from '../../../../components';
import getWithdrawalLockedDesc, { getWithdrawalLimitReachedDesc } from './WithdrawalLockedContent';
import './WithdrawalLocked.scss';

const WithdrawalLocked: React.FC<React.PropsWithChildren> = ({ children }) => {
Expand All @@ -17,6 +18,7 @@ const WithdrawalLocked: React.FC<React.PropsWithChildren> = ({ children }) => {
const { data: cashierValidation } = useCashierValidation();
const { data: accountLimits } = useAccountLimits();
const { data: status } = useAccountStatus();
const { isLoading: isCurrencyConfigLoading } = useCurrencyConfig();

const currency = activeWallet?.currency || 'USD';

Expand All @@ -35,29 +37,53 @@ const WithdrawalLocked: React.FC<React.PropsWithChildren> = ({ children }) => {
const isWithdrawalLocked = status?.is_withdrawal_locked;

const remainder = accountLimits?.remainder;
const minimumWithdrawal = activeWallet?.currency_config?.minimum_withdrawal;
const minimumWithdrawal = activeWallet?.currency_config?.is_crypto
? activeWallet?.currency_config?.minimum_withdrawal
: 0.01;
const withdrawalLimitReached = !!(
typeof remainder !== 'undefined' &&
typeof minimumWithdrawal !== 'undefined' &&
+remainder < minimumWithdrawal
);

if (isCurrencyConfigLoading) {
return <Loader />;
}

if (withdrawalLimitReached) {
return (
<div className='wallets-withdrawal-locked'>
<WalletsActionScreen
description={
getWithdrawalLimitReachedDesc({
askFinancialRiskApproval,
poaNeedsVerification,
poaStatus,
poiNeedsVerification,
poiStatus,
})?.description
}
title={
<Trans
defaults='Withdrawals from your {{currency}} Wallet are temporarily locked.'
values={{ currency }}
/>
}
/>
</div>
);
}

if (isWithdrawalLocked) {
return (
<div className='wallets-withdrawal-locked'>
<WalletsActionScreen
description={
getWithdrawalLockedDesc({
askAuthenticate,
askFinancialRiskApproval,
askFixDetails,
financialAssessmentRequired,
noWithdrawalOrTradingStatus,
poaNeedsVerification,
poaStatus,
poiNeedsVerification,
poiStatus,
withdrawalLimitReached,
withdrawalLockedStatus,
})?.description
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,30 @@ import React from 'react';
import { Trans } from 'react-i18next';
import { WalletLink, WalletText } from '../../../../components';

type TWithdrawalLockedDescProps = {
askAuthenticate?: boolean;
type TWithdrawalLimitReachedDescProps = {
askFinancialRiskApproval?: boolean;
askFixDetails?: boolean;
financialAssessmentRequired?: boolean;
noWithdrawalOrTradingStatus?: boolean;
poaNeedsVerification?: boolean;
poaStatus: string;
poiNeedsVerification?: boolean;
poiStatus: string;
withdrawalLimitReached: boolean;
};

type TWithdrawalLockedDescProps = {
askAuthenticate?: boolean;
askFixDetails?: boolean;
financialAssessmentRequired?: boolean;
noWithdrawalOrTradingStatus?: boolean;
withdrawalLockedStatus?: boolean;
};

const getWithdrawalLockedDesc = ({
askAuthenticate,
export const getWithdrawalLimitReachedDesc = ({
askFinancialRiskApproval,
askFixDetails,
financialAssessmentRequired,
noWithdrawalOrTradingStatus,
poaNeedsVerification,
poaStatus,
poiNeedsVerification,
poiStatus,
withdrawalLimitReached,
withdrawalLockedStatus,
}: TWithdrawalLockedDescProps) => {
if (withdrawalLimitReached && poiNeedsVerification && poiStatus === 'none')
}: TWithdrawalLimitReachedDescProps) => {
if (poiNeedsVerification && poiStatus === 'none')
return {
description: (
<WalletText align='center'>
Expand All @@ -41,7 +37,7 @@ const getWithdrawalLockedDesc = ({
),
};

if (withdrawalLimitReached && poiNeedsVerification && poiStatus !== 'verified' && poiStatus !== 'none')
if (poiNeedsVerification && poiStatus !== 'verified' && poiStatus !== 'none')
return {
description: (
<WalletText align='center'>
Expand All @@ -53,7 +49,7 @@ const getWithdrawalLockedDesc = ({
),
};

if (withdrawalLimitReached && poaNeedsVerification && poaStatus === 'none')
if (poaNeedsVerification && poaStatus === 'none')
return {
description: (
<WalletText align='center'>
Expand All @@ -65,7 +61,7 @@ const getWithdrawalLockedDesc = ({
),
};

if (withdrawalLimitReached && poaNeedsVerification && poaStatus !== 'verified' && poaStatus !== 'none')
if (poaNeedsVerification && poaStatus !== 'verified' && poaStatus !== 'none')
return {
description: (
<WalletText align='center'>
Expand All @@ -77,7 +73,7 @@ const getWithdrawalLockedDesc = ({
),
};

if (withdrawalLimitReached && askFinancialRiskApproval)
if (askFinancialRiskApproval)
return {
description: (
<WalletText align='center'>
Expand All @@ -88,7 +84,15 @@ const getWithdrawalLockedDesc = ({
</WalletText>
),
};
};

const getWithdrawalLockedDesc = ({
askAuthenticate,
askFixDetails,
financialAssessmentRequired,
noWithdrawalOrTradingStatus,
withdrawalLockedStatus,
}: TWithdrawalLockedDescProps) => {
if (financialAssessmentRequired)
return {
description: (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,32 @@ import {
useActiveWalletAccount,
useAuthentication,
useCashierValidation,
useCurrencyConfig,
} from '@deriv/api-v2';
import { render, screen } from '@testing-library/react';
import WithdrawalLocked from '../WithdrawalLocked';
import getWithdrawalLockedDesc from '../WithdrawalLockedContent';

jest.mock('@deriv/api-v2', () => ({
useAccountLimits: jest.fn(),
useAccountStatus: jest.fn(),
useActiveWalletAccount: jest.fn(),
useAuthentication: jest.fn(),
useCashierValidation: jest.fn(),
useCurrencyConfig: jest.fn(),
}));

jest.mock('../../../../../components', () => ({
...jest.requireActual('../../../../../components'),
Loader: jest.fn(() => <div>Loading...</div>),
}));

jest.mock('../WithdrawalLockedContent', () => ({
__esModule: true,
default: jest.fn(),
default: jest.fn(() => ({ description: <div>Locked Description</div> })),
getWithdrawalLimitReachedDesc: jest.fn(() => ({ description: <div>Locked Description</div> })),
}));

const mockActiveWalletData = { currency_config: { minimum_withdrawal: 10 } };
const mockAccountLimitsData = { remainder: 20 };
const mockActiveWalletData = { currency: 'USD', currency_config: { is_crypto: false, minimum_withdrawal: 10 } };
const mockAuthenticationData = {
is_poa_needed: false,
is_poi_needed: false,
Expand All @@ -37,24 +43,65 @@ const mockCashierValidationData = {
no_withdrawal_or_trading_status: false,
withdrawal_locked_status: false,
};
const mockStatusData = { is_withdrawal_locked: false };

describe('WithdrawalLocked', () => {
afterEach(() => {
beforeEach(() => {
jest.clearAllMocks();
});

it('should render locked screen when in a locked state', () => {
it('should render loader when in a loading state', () => {
const mockStatusData = { is_withdrawal_locked: false };
const mockAccountLimitsData = { remainder: 20 };

(useActiveWalletAccount as jest.Mock).mockReturnValueOnce({ data: mockActiveWalletData });
(useAccountLimits as jest.Mock).mockReturnValueOnce({ data: mockAccountLimitsData });
(useAuthentication as jest.Mock).mockReturnValueOnce({ data: mockAuthenticationData });
(useCashierValidation as jest.Mock).mockReturnValueOnce({ data: mockCashierValidationData });
(useAccountStatus as jest.Mock).mockReturnValueOnce({ data: mockStatusData });
(useCurrencyConfig as jest.Mock).mockReturnValueOnce({ isLoading: true });

render(
<WithdrawalLocked>
<div>Test Child Component</div>
</WithdrawalLocked>
);

expect(screen.queryByText('Test Child Component')).not.toBeInTheDocument();
expect(screen.getByText('Loading...')).toBeInTheDocument();
});

it('should render locked screen for withdrawal locked when in a locked state', () => {
const mockLockedStatusData = { is_withdrawal_locked: true };
const mockAccountLimitsData = { remainder: 20 };

(useActiveWalletAccount as jest.Mock).mockReturnValueOnce({ data: mockActiveWalletData });
(useAccountLimits as jest.Mock).mockReturnValueOnce({ data: mockAccountLimitsData });
(useAuthentication as jest.Mock).mockReturnValueOnce({ data: mockAuthenticationData });
(useCashierValidation as jest.Mock).mockReturnValueOnce({ data: mockCashierValidationData });
(useAccountStatus as jest.Mock).mockReturnValueOnce({ data: mockLockedStatusData });
(useCurrencyConfig as jest.Mock).mockReturnValueOnce({ isLoading: false });

const mockLockedState = { description: 'Locked Description' };
(getWithdrawalLockedDesc as jest.Mock).mockReturnValueOnce(mockLockedState);
render(
<WithdrawalLocked>
<div>Test Child Component</div>
</WithdrawalLocked>
);

expect(screen.queryByText('Test Child Component')).not.toBeInTheDocument();
expect(screen.getByText('Locked Description')).toBeInTheDocument();
expect(screen.getByText('Withdrawals from your USD Wallet are temporarily locked.')).toBeInTheDocument();
});

it('should render locked screen for withdrawal limit reached when in a locked state', () => {
const mockStatusData = { is_withdrawal_locked: false };
const mockLockedAccountLimitsData = { remainder: 0 };

(useActiveWalletAccount as jest.Mock).mockReturnValueOnce({ data: mockActiveWalletData });
(useAccountLimits as jest.Mock).mockReturnValueOnce({ data: mockLockedAccountLimitsData });
(useAuthentication as jest.Mock).mockReturnValueOnce({ data: mockAuthenticationData });
(useCashierValidation as jest.Mock).mockReturnValueOnce({ data: mockCashierValidationData });
(useAccountStatus as jest.Mock).mockReturnValueOnce({ data: mockStatusData });
(useCurrencyConfig as jest.Mock).mockReturnValueOnce({ isLoading: false });

render(
<WithdrawalLocked>
Expand All @@ -68,13 +115,15 @@ describe('WithdrawalLocked', () => {
});

it('should render children when not in a locked state', () => {
const mockStatusData = { is_withdrawal_locked: false };
const mockAccountLimitsData = { remainder: 20 };

(useActiveWalletAccount as jest.Mock).mockReturnValueOnce({ data: mockActiveWalletData });
(useAccountLimits as jest.Mock).mockReturnValueOnce({ data: mockAccountLimitsData });
(useAuthentication as jest.Mock).mockReturnValueOnce({ data: mockAuthenticationData });
(useCashierValidation as jest.Mock).mockReturnValueOnce({ data: mockCashierValidationData });
(useAccountStatus as jest.Mock).mockReturnValueOnce({ data: mockStatusData });

(getWithdrawalLockedDesc as jest.Mock).mockReturnValueOnce(null);
(useCurrencyConfig as jest.Mock).mockReturnValueOnce({ isLoading: false });

render(
<WithdrawalLocked>
Expand Down
Loading
Loading