Skip to content

Commit

Permalink
[CFDS][WALL] shontzu/CFDS-3913/API-updates-for-maintenance-and-unavai…
Browse files Browse the repository at this point in the history
…lable-flag-for-TH-Cashier-Wallets (#16064)

* feat: created server maintenance modal and account unavailable modal

* feat: added server_maintenance and unavailable to status badge config

* refactor: make server-maintenance-modal generic

* chore: rename status from server_maintenance to under_maintenance following BE

* refactor: separate mt5_login_list status from trading_platform_status

* feat: incorporated response from trading_platform_status

* Apply suggestions from code review

chore: code review batch 1

Co-authored-by: Farrah Mae Ochoa <[email protected]>

* refactor: replace WS call with /hooks useTradingPlatformStatus

* feat: status badge and hint message in prod cashier

* refactor: unavailable status badge and hint message refac

* feat: server-maintenance and account-unavailable modals in wallets

* chore: useTradingPlatformStatus hook in api-v2 for wallets

* feat: status badge in MT5AccountsList

* refactor: moved status badge to correct place

* chore: TradingPlatformStatus type

* feat: hint message in wallets account-transfer

* fix: status badge text

* fix: accidentally removed smtg

* fix: api-types

* fix: remove usePhoneNumberVerificationSetTimer

* style: bold serverMaintenance time

* Apply suggestions from code review

Co-authored-by: Aizad Ridzo <[email protected]>

* chore: duplicated type in TSocketEndpoints and TPrivateSocketEndpoints

* chore: apply code review suggestions

* refactor: type in TPrivateSocketEndpoints instead of TSocketEndpoints

* refactor: replace switch case with object keys

* refactor: tradingPlatformStatusData type and hook docs

* style: css improvements

* chore: Missed the typing here

* refactor: remove hardcoding pt1

* chore: delete dead directory

* style: status badge icon height issue

* style: using WalletText component for status badge text

* chore: useTradingPlatformStatus.spec.tsx

* chore: empty commit

* fix: indentation in api types

* fix: mockUseQuery

* refactor: move handling logic to hook

* fix: fallback val

* fix: tests

* chore: capitalisation

* chore: disabling transfer button check

* chore: why is this not being committed

* fix: failing test

* chore: fix complains

* fix: useTransferMessages.ts should not return undefined

* chore: OCDing

* refactor: small nit

* refactor: type from trading_platform_accounts

* chore: update server maintenance modal content

* chore: update server maintenance modal content

* Apply suggestions from code review

Co-authored-by: thisyahlen  <[email protected]>

* Update packages/cashier/src/pages/account-transfer/account-transfer-form/account-transfer-form.tsx

Co-authored-by: thisyahlen  <[email protected]>

* chore: format formatt

* refactor: non-cfd platform not falling back to cfd active status

* chore: remove unused variable

* refactor: consolidated serverMaintenance and accountUnavailable modals

* refactor: remove redundant code

* refactor: status badge component

* chore: translations

* chore: empty commit

* fix: cashier bundle size

* fix: use WS from deriv/shared instead of useQuery from deriv/api

* fix: useTradingPlatformStatus proptypes

* chore: server maintenance modal content update

* fix: mock mockUseMT5SVGEligibleToMigrate

* fix: localize text

* fix: subtasks (balance field, text alignment, multiple status badges)

* fix: wallets multiple status showing multiple badges

* fix: test

* fix: broken server maintenance badge

* chore: wallets code review (translations and components from deriv-com/ui)

Co-authored-by: lubega-deriv <[email protected]>
Co-authored-by: aizad-deriv <[email protected]>

* fix: add under_maintenance check for isMaintenance flag

* fix: mobile view in wallets

---------

Co-authored-by: Farrah Mae Ochoa <[email protected]>
Co-authored-by: Aizad Ridzo <[email protected]>
Co-authored-by: thisyahlen <[email protected]>
Co-authored-by: lubega-deriv <[email protected]>
Co-authored-by: aizad-deriv <[email protected]>
  • Loading branch information
6 people authored Aug 23, 2024
1 parent d237e2e commit 2bd466f
Show file tree
Hide file tree
Showing 55 changed files with 1,545 additions and 635 deletions.
12 changes: 11 additions & 1 deletion packages/account/src/Configs/get-status-badge-config.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { Text } from '@deriv/components';
import { AUTH_STATUS_CODES, MT5_ACCOUNT_STATUS, routes } from '@deriv/shared';
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';
Expand Down Expand Up @@ -80,6 +80,16 @@ const getStatusBadgeConfig = (
text: <Localize i18n_default_text='<0>Account closed</0>' components={[BadgeTextComponent]} />,
icon: 'IcAlertWarning',
};
case MT5_ACCOUNT_STATUS.UNDER_MAINTENANCE:
return {
text: <Localize i18n_default_text='<0>Server maintenance</0>' components={[BadgeTextComponent]} />,
icon: 'IcAlertWarning',
};
case TRADING_PLATFORM_STATUS.UNAVAILABLE:
return {
text: <Localize i18n_default_text='<0>Unavailable</0>' components={[BadgeTextComponent]} />,
icon: 'IcAlertWarning',
};
default:
return {
text: '',
Expand Down
12 changes: 10 additions & 2 deletions packages/account/src/Types/common.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ import {
IdentityVerificationAddDocumentResponse,
ApiToken,
} from '@deriv/api-types';
import { AUTH_STATUS_CODES, CFD_PLATFORMS, MT5_ACCOUNT_STATUS, Platforms } from '@deriv/shared';
import {
AUTH_STATUS_CODES,
CFD_PLATFORMS,
MT5_ACCOUNT_STATUS,
Platforms,
TRADING_PLATFORM_STATUS,
} from '@deriv/shared';

export type TToken = NonNullable<ApiToken['tokens']>[0];

Expand Down Expand Up @@ -275,7 +281,9 @@ export type TFinancialInformationForm = Omit<SetFinancialAssessmentRequest, 'set

export type TAuthStatusCodes = typeof AUTH_STATUS_CODES[keyof typeof AUTH_STATUS_CODES];

export type TMT5AccountStatus = typeof MT5_ACCOUNT_STATUS[keyof typeof MT5_ACCOUNT_STATUS];
export type TMT5AccountStatus =
| typeof MT5_ACCOUNT_STATUS[keyof typeof MT5_ACCOUNT_STATUS]
| typeof TRADING_PLATFORM_STATUS[keyof typeof TRADING_PLATFORM_STATUS];

export type TFilesDescription = {
descriptions: { id: string; value: JSX.Element }[];
Expand Down
1 change: 1 addition & 0 deletions packages/api-v2/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,5 @@ export { default as useExchangeRates } from './useExchangeRates';
export { default as useIsDIELEnabled } from './useIsDIELEnabled';
export { default as useKycAuthStatus } from './useKycAuthStatus';
export { default as useClientCountry } from './useClientCountry';
export { default as useTradingPlatformStatus } from './useTradingPlatformStatus';
export { DocumentUploadStatus } from './useDocumentUpload';
43 changes: 43 additions & 0 deletions packages/api-v2/src/hooks/useTradingPlatformStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { CFD_PLATFORMS } from '@deriv/shared';
import useAuthorizedQuery from '../useAuthorizedQuery';
import useQuery from '../useQuery';

type TPlatformStatus = Exclude<
NonNullable<ReturnType<typeof useQuery<'trading_platform_status'>>['data']>['trading_platform_status'][0],
undefined
>;

/** A custom hook that gets the list of statuses of ctrader dxtrade mt5 platform. */
const useTradingPlatformStatus = () => {
const { data, ...rest } = useAuthorizedQuery(
'trading_platform_status',
{},
{
refetchInterval: 120000,
}
);

const tradingPlatformStatusData = data?.trading_platform_status;

/**
* Retrieves the status of a specified trading platform.
* @param platform The platform identifier (e.g., 'ctrader', 'dxtrade', 'mt5').
* @returns The status of the identified platform ('active', 'maintenance', 'unavailable').
*/
const getPlatformStatus = (platform: string) => {
const platformStatus =
platform === CFD_PLATFORMS.MT5 || platform === CFD_PLATFORMS.DXTRADE || platform === CFD_PLATFORMS.CTRADER
? tradingPlatformStatusData?.find((status: TPlatformStatus) => status.platform === platform)?.status
: undefined; // cashier may pass non-cfd platform (i.e. doughflow, p2p, paymentagent, etc) which doesn't have status property

return platformStatus;
};

return {
...rest,
data: tradingPlatformStatusData,
getPlatformStatus,
};
};

export default useTradingPlatformStatus;
20 changes: 20 additions & 0 deletions packages/api-v2/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2246,6 +2246,22 @@ type MT5AccountListResponse = {

type TAccountList = NonNullable<AccountListResponse['account_list']>[number] & { excluded_until: Date };

type TradingPlatformStatusRequest = {
trading_platform_status: 1;
};

type TradingPlatformStatusResponse = {
trading_platform_status: {
platform: Exclude<
NonNullable<
TSocketEndpoints['trading_platform_accounts']['response']['trading_platform_accounts']
>[0]['platform'],
undefined
>;
status: 'active' | 'maintenance' | 'unavailable';
}[];
};

interface IExtendedAccountListResponse extends AccountListResponse {
account_list?: TAccountList[];
}
Expand Down Expand Up @@ -2687,6 +2703,10 @@ type TSocketEndpoints = {
request: TradingPlatformPasswordResetRequest;
response: TradingPlatformPasswordResetResponse;
};
trading_platform_status: {
request: TradingPlatformStatusRequest;
response: TradingPlatformStatusResponse;
};
trading_servers: {
request: ServerListRequest;
response: ServerListResponse;
Expand Down
29 changes: 28 additions & 1 deletion packages/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2319,7 +2319,30 @@ type ChangeEmailResponse = {
msg_type: 'change_email';
req_id?: number;
};

/**
* Get list of platform and their server status
*/
type TradingPlatformStatusRequest = {
/**
* Must be 1
*/
trading_platform_status: 1;
};
/**
* response containing platform and their server status.
*/
type TradingPlatformStatusResponse = {
trading_platform_status: {
/**
* types of cfd platforms
*/
platform: 'mt5' | 'ctrader' | 'dxtrade';
/**
* possible server statuses
*/
status: 'active' | 'maintenance' | 'unavailable';
}[];
};
type TSocketEndpoints = {
active_symbols: {
request: ActiveSymbolsRequest;
Expand Down Expand Up @@ -2773,6 +2796,10 @@ type TSocketEndpoints = {
request: TradingPlatformPasswordResetRequest;
response: TradingPlatformPasswordResetResponse;
};
trading_platform_status: {
request: TradingPlatformStatusRequest;
response: TradingPlatformStatusResponse;
};
trading_servers: {
request: ServerListRequest;
response: ServerListResponse;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { StoreProvider, mockStore } from '@deriv/stores';
import { useMT5SVGEligibleToMigrate, useTradingPlatformStatus, useGrowthbookGetFeatureValue } from '@deriv/hooks';

import CFDsListing from '../index';

jest.mock('Components/containers/listing-container', () =>
Expand All @@ -13,7 +15,45 @@ jest.mock('@deriv-com/ui', () => ({
isTablet: false,
})),
}));
jest.mock('@deriv/hooks');
const mockUseGrowthbookGetFeatureValue = useGrowthbookGetFeatureValue as jest.MockedFunction<
typeof useGrowthbookGetFeatureValue
>;
const mockUseTradingPlatformStatus = useTradingPlatformStatus as jest.MockedFunction<typeof useTradingPlatformStatus>;
const mockUseMT5SVGEligibleToMigrate = useMT5SVGEligibleToMigrate as jest.MockedFunction<
typeof useMT5SVGEligibleToMigrate
>;

mockUseGrowthbookGetFeatureValue.mockReturnValue([true, true]);

mockUseMT5SVGEligibleToMigrate.mockReturnValue({
eligible_account_to_migrate_label: 'BVI',
eligible_svg_to_bvi_derived_accounts: true,
eligible_svg_to_bvi_financial_accounts: false,
eligible_svg_to_vanuatu_derived_accounts: false,
eligible_svg_to_vanuatu_financial_accounts: false,
getEligibleAccountToMigrate: jest.fn().mockReturnValue('BVI'),
has_derived_and_financial_mt5: false,
has_derived_mt5_to_migrate: true,
has_svg_accounts_to_migrate: true,
no_of_svg_accounts_to_migrate: 1,
svg_accounts_to_migrate: [
{
landing_company_short: 'svg',
eligible_to_migrate: { synthetic: 'BVI' },
},
],
});

mockUseTradingPlatformStatus.mockReturnValue({
data: [
{
platform: 'mt5',
status: 'active',
},
],
getPlatformStatus: jest.fn(),
});
describe('CFDsListing', () => {
const mock = mockStore({
traders_hub: {
Expand Down
73 changes: 61 additions & 12 deletions packages/appstore/src/components/cfds-listing/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import React, { Fragment, useEffect } from 'react';
import { observer, useStore } from '@deriv/stores';
import { Loading, Text, StaticUrl } from '@deriv/components';
import { Loading, Text } from '@deriv/components';
import {
CFD_PLATFORMS,
formatMoney,
getAuthenticationStatusInfo,
Jurisdiction,
MT5_ACCOUNT_STATUS,
TRADING_PLATFORM_STATUS,
makeLazyLoader,
moduleLoader,
setPerformanceValue,
} from '@deriv/shared';
import { useDevice } from '@deriv-com/ui';
import { localize, Localize } from '@deriv/translations';
import { localize } from '@deriv/translations';
import { Analytics } from '@deriv-com/analytics';
import ListingContainer from 'Components/containers/listing-container';
import AddOptionsAccount from 'Components/add-options-account';
Expand All @@ -20,7 +22,13 @@ import PlatformLoader from 'Components/pre-loader/platform-loader';
import CompareAccount from 'Components/compare-account';
import CFDsDescription from 'Components/elements/cfds-description';
import { getHasDivider } from 'Constants/utils';
import { useMT5SVGEligibleToMigrate, useGrowthbookGetFeatureValue } from '@deriv/hooks';
import {
useMT5SVGEligibleToMigrate,
useTradingPlatformStatus,
TradingPlatformStatus,
useGrowthbookGetFeatureValue,
} from '@deriv/hooks';

import './cfds-listing.scss';

const MigrationBanner = makeLazyLoader(
Expand Down Expand Up @@ -67,7 +75,14 @@ const CFDsListing = observer(() => {
financial_restricted_countries,
} = traders_hub;

const { setAccountType, toggleCTraderTransferModal, setProduct } = cfd;
const {
setAccountType,
toggleCTraderTransferModal,
setAccountUnavailableModal,
setServerMaintenanceModal,
setProduct,
} = cfd;

const {
account_status,
is_landing_company_loaded,
Expand Down Expand Up @@ -96,7 +111,39 @@ const CFDsListing = observer(() => {
const { has_svg_accounts_to_migrate } = useMT5SVGEligibleToMigrate();
const getAuthStatus = (status_list: boolean[]) => status_list.some(status => status);

const { getPlatformStatus } = useTradingPlatformStatus();

const getTradingPlatformStatus = (platform: TradingPlatformStatus['platform']) => {
const status = getPlatformStatus(platform);

switch (status) {
case TRADING_PLATFORM_STATUS.MAINTENANCE:
return setServerMaintenanceModal(true);
case TRADING_PLATFORM_STATUS.UNAVAILABLE:
return setAccountUnavailableModal(true);
case TRADING_PLATFORM_STATUS.ACTIVE:
return getAccount();
default:
break;
}
};

const hasUnavailableAccount = combined_cfd_mt5_accounts.some(
account => account.status === TRADING_PLATFORM_STATUS.UNAVAILABLE
);
const hasMaintenanceStatus =
combined_cfd_mt5_accounts.some(account => account.status === MT5_ACCOUNT_STATUS.UNDER_MAINTENANCE) ||
combined_cfd_mt5_accounts.some(
account => getPlatformStatus(account.platform ?? CFD_PLATFORMS.MT5) === TRADING_PLATFORM_STATUS.MAINTENANCE
);

const getMT5AccountAuthStatus = (current_acc_status?: string | null, jurisdiction?: string) => {
if (current_acc_status === 'under_maintenance') {
return MT5_ACCOUNT_STATUS.UNDER_MAINTENANCE;
} else if (current_acc_status === 'unavailable') {
return TRADING_PLATFORM_STATUS.UNAVAILABLE;
}

if (jurisdiction) {
switch (jurisdiction) {
case Jurisdiction.BVI: {
Expand Down Expand Up @@ -153,7 +200,7 @@ const CFDsListing = observer(() => {
return null;
}
}
return null;
return '';
};

const no_real_mf_account_eu_regulator = no_MF_account && is_eu_user && is_real;
Expand Down Expand Up @@ -187,7 +234,7 @@ const CFDsListing = observer(() => {
setPerformanceValue('switch_from_demo_to_real_time');
setPerformanceValue('switch_from_real_to_demo_time');
}
}, [is_populating_mt5_account_list]);
}, [is_landing_company_loaded, is_populating_mt5_account_list]);

return (
<ListingContainer
Expand Down Expand Up @@ -217,14 +264,14 @@ const CFDsListing = observer(() => {
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
existing_account?.status || is_idv_revoked || hasMaintenanceStatus
? getMT5AccountAuthStatus(
existing_account?.status,
existing_account?.landing_company_short
)
: null;
: '';

return (
<TradingAppCard
action_type={existing_account.action_type}
Expand All @@ -249,6 +296,8 @@ const CFDsListing = observer(() => {
account_name: track_account_subtitle,
});
}
if (hasUnavailableAccount || hasMaintenanceStatus)
return setServerMaintenanceModal(true);

if (real_account_creation_unlock_date && no_real_mf_account_eu_regulator) {
setShouldShowCooldownModal(true);
Expand All @@ -261,7 +310,7 @@ const CFDsListing = observer(() => {
});
setProduct(existing_account.product);
setAppstorePlatform(existing_account.platform);
getAccount();
getTradingPlatformStatus(existing_account.platform);
}
} else if (existing_account.action_type === 'multi-action') {
const button_name = e?.currentTarget?.name;
Expand Down Expand Up @@ -423,7 +472,7 @@ const CFDsListing = observer(() => {
type: account.market_type,
});
setAppstorePlatform(account.platform);
getAccount();
getTradingPlatformStatus(account.platform);
}
}}
key={`trading_app_card_${account.name}`}
Expand Down Expand Up @@ -536,7 +585,7 @@ const CFDsListing = observer(() => {
type: account.market_type,
});
setAppstorePlatform(account.platform);
getAccount();
getTradingPlatformStatus(account.platform);
}
}}
key={`trading_app_card_${account.name}`}
Expand Down
Loading

0 comments on commit 2bd466f

Please sign in to comment.