From f3990bb84e091ac45cfad5211b065e8b529da616 Mon Sep 17 00:00:00 2001 From: shontzu <108507236+shontzu-deriv@users.noreply.github.com> Date: Thu, 22 Jun 2023 18:29:32 +0800 Subject: [PATCH] shontzu/93860/add-derivez-to-tradershub (#8352) * feat: added derivez demo/real/static to tradershub/onboarding * fix: call success modal instead of logging out * fix: roundup patch #1 based on reviews * fix: move consts to Helpers/constants file * fix: roundup patch #2 based on reviews * Revert "fix: roundup patch #2 based on reviews" This reverts commit f0cf7f5bdc53717b0e65a59834644ee71fe17ddb. * fix: round up patch#2 based on review * fix: clean up * fix: outdated icons after merging * fix: fixed derivx testcase error * fix: update derivx icon * fix: fixed conflicts * fix: roundup patch #3 based on code reviews * fix: round up patch#3 based on code reviews * chore: unit test for derivez static * fix: asdf * feat: token implementation for derivez (todo: pandats error) * fix: qrcode, download links, and download options * fix: round-up-patch 1 * fix: round-up-patch 2 - Description Text below the Deriv EZ header on Onboarding page is different from Design - Text format is incorrect in DerivEZ Account creation success modal - Multiple discrepancies in Trade modal (fixed in round-up-patch 1) * fix: round-up-patch 3 - use instead ov <> - remove unintentional {' '} whitespaces * fix: code smells * fix: asdf * feat: disable derivez real flow * fix: added top up for DerivEz * fix: qr code for derivez and derivx * fix: hide qr box if isMobile * fix: derivez fund topup text * fix: derivx fund topup text * fix: onboarding demo title * fix: Deriv Ez -> Deriv EZ * fix: Go -> GO * fix: Description Text below the Deriv EZ header on Onboarding page * fix: revert changes on tradershub * fix: updated to latest description (derivez onboarding/tradershub) * fix: hide derivez and dxtrade in cfd_restricted countries (japan, norway) * fix: corrected the time in server maintenance notice on derivez trade modal * fix: Server maintenance notice time * fix: DerivEZ icon redirect to https://deriv.com/derivez/ * fix: derivez topupVirtual * revert: undo changes in cfd-dashboard.tsx (deprecated file) * remove unnecesary parameter * fix: fixed derivX top up and trade button in onboarding page * fix: disable button while getting account creating * fix: disable GET button while account is being created * fix: disable GET button while account is being created * fix: setIsAccountBeingCreated(false) after account creation to reenable get buttons * fix: remove redundant use of await * fix: server maintenance time TEXT (not time) for derivez * fix: reenable button when error is triggered too * fix: blur derivez icon on onboarding 5th page * fix: remove function call that trigger token error * Update cfd-store.js * fix: pull upstream * fix: hide derivez from oboarding page * fix: show derivez on onboarding and remove "Demo" from appname * fix: empty commit * fix: total asset included derivez balance * fix: updated mockstore * fix: separate dxtrade and derivez token loader into two reactions * fix: rerunning all of our tests * chore: empty commit * fix: capitalization on module import * chore: empty commit --------- Co-authored-by: hirad-deriv Co-authored-by: Ali(Ako) Hosseini --- .../ic-branding-derivez-dashboard.svg | 1 + ....svg => ic-branding-dxtrade-dashboard.svg} | 0 .../assets/svgs/trading-platform/index.tsx | 4 +- .../components/cfds-listing/cfds-listing.scss | 12 +- .../src/components/cfds-listing/index.tsx | 84 +++++- .../containers/trading-app-card-actions.tsx | 4 +- .../containers/trading-app-card.tsx | 9 +- .../src/components/modals/modal-manager.tsx | 2 + .../__tests__/static-dashboard.spec.tsx | 56 ++++ .../static-cfd-account-manager.tsx | 16 +- .../onboarding-new/static-dashboard.tsx | 64 +++-- packages/appstore/src/types/common.types.ts | 5 +- packages/cfd/build/webpack.config.js | 2 + .../trading-platform/ic-appstore-derivez.svg | 1 + .../Assets/svgs/trading-platform/index.tsx | 2 + .../cfd/src/Components/cfd-account-card.tsx | 26 +- packages/cfd/src/Components/passwordbox.tsx | 47 ++++ packages/cfd/src/Components/props.types.ts | 19 +- packages/cfd/src/Components/specbox.tsx | 19 ++ .../__tests__/cfd-password-modal.spec.js | 2 +- packages/cfd/src/Containers/cfd-dashboard.tsx | 7 + .../cfd/src/Containers/cfd-password-modal.tsx | 49 +++- .../src/Containers/cfd-top-up-demo-modal.tsx | 18 +- .../cfd/src/Containers/derivx-trade-modal.tsx | 2 +- .../cfd/src/Containers/dmt5-trade-modal.tsx | 1 + .../cfd/src/Containers/mt5-trade-modal.tsx | 14 +- packages/cfd/src/Containers/props.types.ts | 4 + packages/cfd/src/Containers/trade-modal.tsx | 240 ++++++++++++++++++ packages/cfd/src/Helpers/config.tsx | 89 +++++++ packages/cfd/src/Helpers/constants.ts | 81 +++++- .../Stores/Modules/CFD/Helpers/cfd-config.ts | 41 ++- .../cfd/src/Stores/Modules/CFD/cfd-store.js | 135 ++++++++-- packages/cfd/src/sass/cfd-dashboard.scss | 12 +- .../icon/brand/ic-brand-deriv-ez-wordmark.svg | 1 + .../icon/brand/ic-brand-deriv-ez.svg | 1 + .../icon/brand/ic-brand-dxtrade-wordmark.svg | 1 + .../components/src/components/icon/icons.js | 8 +- .../ic-rebranding-deriv-ez-wordmark.svg | 1 + .../rebranding/ic-rebranding-deriv-ez.svg | 1 + .../ic-rebranding-derivez-dashboard.svg | 1 + ...svg => ic-rebranding-dxtrade-wordmark.svg} | 0 packages/components/stories/icon/icons.js | 8 +- packages/core/src/Stores/client-store.js | 41 ++- packages/core/src/Stores/traders-hub-store.js | 47 +++- packages/core/src/_common/base/socket_base.js | 9 +- packages/hooks/src/useCFDAllAccounts.ts | 5 +- .../src/utils/cfd/available-cfd-accounts.ts | 8 + packages/shared/src/utils/cfd/cfd.ts | 7 +- .../src/utils/config/platform-config.ts | 2 +- packages/stores/src/mockStore.ts | 5 +- packages/stores/types.ts | 5 +- 51 files changed, 1111 insertions(+), 108 deletions(-) create mode 100644 packages/appstore/src/assets/svgs/trading-platform/branding/ic-branding-derivez-dashboard.svg rename packages/appstore/src/assets/svgs/trading-platform/branding/{ic-branding-derivx-dashboard.svg => ic-branding-dxtrade-dashboard.svg} (100%) create mode 100644 packages/appstore/src/components/onboarding-new/__tests__/static-dashboard.spec.tsx create mode 100644 packages/cfd/src/Assets/svgs/trading-platform/ic-appstore-derivez.svg create mode 100644 packages/cfd/src/Components/passwordbox.tsx create mode 100644 packages/cfd/src/Components/specbox.tsx create mode 100644 packages/cfd/src/Containers/trade-modal.tsx create mode 100644 packages/cfd/src/Helpers/config.tsx create mode 100644 packages/components/src/components/icon/brand/ic-brand-deriv-ez-wordmark.svg create mode 100644 packages/components/src/components/icon/brand/ic-brand-deriv-ez.svg create mode 100644 packages/components/src/components/icon/brand/ic-brand-dxtrade-wordmark.svg create mode 100644 packages/components/src/components/icon/rebranding/ic-rebranding-deriv-ez-wordmark.svg create mode 100644 packages/components/src/components/icon/rebranding/ic-rebranding-deriv-ez.svg create mode 100644 packages/components/src/components/icon/rebranding/ic-rebranding-derivez-dashboard.svg rename packages/components/src/components/icon/rebranding/{ic-rebranding-derivx-wordmark.svg => ic-rebranding-dxtrade-wordmark.svg} (100%) diff --git a/packages/appstore/src/assets/svgs/trading-platform/branding/ic-branding-derivez-dashboard.svg b/packages/appstore/src/assets/svgs/trading-platform/branding/ic-branding-derivez-dashboard.svg new file mode 100644 index 000000000000..6173fbf60c24 --- /dev/null +++ b/packages/appstore/src/assets/svgs/trading-platform/branding/ic-branding-derivez-dashboard.svg @@ -0,0 +1 @@ + diff --git a/packages/appstore/src/assets/svgs/trading-platform/branding/ic-branding-derivx-dashboard.svg b/packages/appstore/src/assets/svgs/trading-platform/branding/ic-branding-dxtrade-dashboard.svg similarity index 100% rename from packages/appstore/src/assets/svgs/trading-platform/branding/ic-branding-derivx-dashboard.svg rename to packages/appstore/src/assets/svgs/trading-platform/branding/ic-branding-dxtrade-dashboard.svg diff --git a/packages/appstore/src/assets/svgs/trading-platform/index.tsx b/packages/appstore/src/assets/svgs/trading-platform/index.tsx index 560dfa830f9d..6a4d77989224 100644 --- a/packages/appstore/src/assets/svgs/trading-platform/index.tsx +++ b/packages/appstore/src/assets/svgs/trading-platform/index.tsx @@ -5,11 +5,12 @@ import CFDs from 'Assets/svgs/trading-platform/branding/ic-branding-mt5-cfds.svg import DBot from 'Assets/svgs/trading-platform/branding/ic-branding-dbot-dashboard.svg'; import Demo from 'Assets/svgs/trading-platform/ic-brand-demo.svg'; import Derived from 'Assets/svgs/trading-platform/branding/ic-branding-mt5-derived-dashboard.svg'; +import DerivEz from 'Assets/svgs/trading-platform/branding/ic-branding-derivez-dashboard.svg'; import DerivGo from 'Assets/svgs/trading-platform/branding/ic-branding-derivgo-dashboard.svg'; import DerivGoBlack from 'Assets/svgs/trading-platform/ic-appstore-derivgo-black.svg'; import DerivLogo from 'Assets/svgs/trading-platform/branding/ic-branding-deriv-logo.svg'; import DerivTradingLogo from 'Assets/svgs/trading-platform/ic-appstore-deriv-trading-logo.svg'; -import DerivX from 'Assets/svgs/trading-platform/branding/ic-branding-derivx-dashboard.svg'; +import DerivX from 'Assets/svgs/trading-platform/branding/ic-branding-dxtrade-dashboard.svg'; import DropDown from 'Assets/svgs/trading-platform/drop-down.svg'; import DTrader from 'Assets/svgs/trading-platform/branding/ic-branding-dtrader-dashboard.svg'; import Financial from 'Assets/svgs/trading-platform/branding/ic-branding-mt5-financial-dashboard.svg'; @@ -26,6 +27,7 @@ export const PlatformIcons = { DBot, Demo, Derived, + DerivEz, DerivGo, DerivGoBlack, DerivLogo, diff --git a/packages/appstore/src/components/cfds-listing/cfds-listing.scss b/packages/appstore/src/components/cfds-listing/cfds-listing.scss index f8e0fb77bd50..b2335c6e8bdd 100644 --- a/packages/appstore/src/components/cfds-listing/cfds-listing.scss +++ b/packages/appstore/src/components/cfds-listing/cfds-listing.scss @@ -391,7 +391,6 @@ background: var(--brand-dark-grey); align-items: center; text-decoration: none; - padding: 0.2rem; border-radius: $BORDER_RADIUS; &-text { @@ -402,6 +401,9 @@ white-space: nowrap; } } + &-icon { + margin-left: 0.6rem; + } } &__specs { padding: 1.6rem; @@ -453,6 +455,12 @@ padding-top: 2rem; padding-bottom: 5.8rem; + &-description { + display: flex; + justify-content: center; + margin-top: 1.4rem; + } + &-app { display: flex; flex-direction: column; @@ -524,7 +532,7 @@ display: flex; flex-direction: column; width: 13.6rem; - height: 14rem; + height: auto; padding: 0.8rem; align-items: center; border: 1px solid var(--border-disabled); diff --git a/packages/appstore/src/components/cfds-listing/index.tsx b/packages/appstore/src/components/cfds-listing/index.tsx index ab42f5260e01..37265d011887 100644 --- a/packages/appstore/src/components/cfds-listing/index.tsx +++ b/packages/appstore/src/components/cfds-listing/index.tsx @@ -30,6 +30,7 @@ const CFDsListing = () => { } = useStores(); const { available_dxtrade_accounts, + available_derivez_accounts, combined_cfd_mt5_accounts, selected_region, has_any_real_account, @@ -206,16 +207,17 @@ const CFDsListing = () => { )} {!is_eu_user && !CFDs_restricted_countries && !financial_restricted_countries && ( -
-
-
- )} - {available_dxtrade_accounts?.length > 0 && ( -
- - {localize('Other CFD Platforms')} - -
+ +
+
+
+ +
+ + {localize('Other CFDs')} + +
+
)} {is_landing_company_loaded ? ( available_dxtrade_accounts?.map((account: AvailableAccount) => { @@ -279,6 +281,68 @@ const CFDsListing = () => { ) : ( )} + + {/* TODO: remove is_real flag to unblock the flow for derivez real account creation */} + {is_landing_company_loaded && !is_real + ? available_derivez_accounts?.map((account: AvailableAccount) => { + const existing_accounts = getExistingAccounts(account.platform, account.market_type); + const has_existing_accounts = existing_accounts.length > 0; + return has_existing_accounts ? ( + existing_accounts.map((existing_account: TDetailsOfEachMT5Loginid) => ( + ) => { + const button_name = e?.currentTarget?.name; + if (button_name === 'transfer-btn') { + toggleAccountTransferModal(); + setSelectedAccount(existing_account); + } else if (button_name === 'topup-btn') { + showTopUpModal(existing_account); + setAppstorePlatform(account.platform); + } else { + startTrade(account.platform, existing_account); + } + }} + /> + )) + ) : ( + { + if ((has_no_real_account || no_CR_account) && is_real) { + openDerivRealAccountNeededModal(); + } else { + setAccountType({ + category: selected_account_type, + type: account.market_type, + }); + setAppstorePlatform(account.platform); + getAccount(); + } + }} + key={`trading_app_card_${account.name}`} + /> + ); + }) + : !is_real && } ); }; diff --git a/packages/appstore/src/components/containers/trading-app-card-actions.tsx b/packages/appstore/src/components/containers/trading-app-card-actions.tsx index b82fc602f9b9..bb4899f1f5c7 100644 --- a/packages/appstore/src/components/containers/trading-app-card-actions.tsx +++ b/packages/appstore/src/components/containers/trading-app-card-actions.tsx @@ -14,6 +14,7 @@ export type Actions = { is_external?: boolean; new_tab?: boolean; is_buttons_disabled?: boolean; + is_account_being_created?: boolean; is_real?: boolean; }; @@ -23,13 +24,14 @@ const TradingAppCardActions = ({ onAction, is_external, new_tab, + is_account_being_created, is_buttons_disabled, is_real, }: Actions) => { switch (action_type) { case 'get': return ( - ); diff --git a/packages/appstore/src/components/containers/trading-app-card.tsx b/packages/appstore/src/components/containers/trading-app-card.tsx index 272e7027bbb7..46d2a31b29e3 100644 --- a/packages/appstore/src/components/containers/trading-app-card.tsx +++ b/packages/appstore/src/components/containers/trading-app-card.tsx @@ -29,9 +29,14 @@ const TradingAppCard = ({ selected_mt5_jurisdiction, openFailedVerificationModal, }: Actions & BrandConfig & AvailableAccount & TDetailsOfEachMT5Loginid) => { - const { common, traders_hub } = useStores(); + const { + common, + traders_hub, + modules: { cfd }, + } = useStores(); const { is_eu_user, is_demo_low_risk, content_flag, is_real } = traders_hub; const { current_language } = common; + const { is_account_being_created } = cfd; const low_risk_cr_non_eu = content_flag === ContentFlag.LOW_RISK_CR_NON_EU; @@ -54,6 +59,7 @@ const TradingAppCard = ({ window.open(getStaticUrl(`/dmt5`, {}, false, true)); else if (platform === CFD_PLATFORMS.MT5 && availability !== 'EU') window.open(getStaticUrl(`/dmt5`)); else if (platform === CFD_PLATFORMS.DXTRADE) window.open(getStaticUrl(`/derivx`)); + else if (platform === CFD_PLATFORMS.DERIVEZ) window.open(getStaticUrl(`/derivez`)); else if (icon === 'Options' && !is_eu_user) window.open(getStaticUrl(`/trade-types/options/`)); else; }; @@ -113,6 +119,7 @@ const TradingAppCard = ({ is_external={is_external} new_tab={new_tab} is_buttons_disabled={!!mt5_acc_auth_status} + is_account_being_created={!!is_account_being_created} is_real={is_real} /> diff --git a/packages/appstore/src/components/modals/modal-manager.tsx b/packages/appstore/src/components/modals/modal-manager.tsx index 92bdf0e00a6e..f630834a6127 100644 --- a/packages/appstore/src/components/modals/modal-manager.tsx +++ b/packages/appstore/src/components/modals/modal-manager.tsx @@ -49,6 +49,7 @@ const ModalManager = () => { getRealSwapfreeAccountsExistingData, current_account, dxtrade_companies, + derivez_companies, mt5_companies, topUpVirtual, } = modules.cfd; @@ -137,6 +138,7 @@ const ModalManager = () => { ', () => { + const is_blurry = { + icon: true, + item: false, + text: false, + get: false, + topup: false, + trade: false, + cfd_item: false, + cfd_text: false, + options_item: false, + options_text: false, + cfd_description: false, + options_description: false, + platformlauncher: false, + }; + + const is_onboarding_animated = { + text: false, + trade: false, + topup: false, + button: false, + get: false, + }; + + test('should render derivez in page if !CFDs_restricted_countries (non-eu countries)', () => { + const mock = mockStore({}); + + render( + + + + ); + expect(screen.queryByText('Deriv EZ')).toBeInTheDocument(); + }); + + test('should not render derivez if CFDs_restricted_countries: true (eu countries)', () => { + const mock = mockStore({ + traders_hub: { + CFDs_restricted_countries: true, + }, + }); + + render( + + + + ); + expect(screen.queryByText('Deriv Ez')).not.toBeInTheDocument(); + }); +}); diff --git a/packages/appstore/src/components/onboarding-new/static-cfd-account-manager.tsx b/packages/appstore/src/components/onboarding-new/static-cfd-account-manager.tsx index 4416ddf67fd9..773820c69506 100644 --- a/packages/appstore/src/components/onboarding-new/static-cfd-account-manager.tsx +++ b/packages/appstore/src/components/onboarding-new/static-cfd-account-manager.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { Button, Text } from '@deriv/components'; import { formatMoney, CFD_PLATFORMS } from '@deriv/shared'; +import { useStore } from '@deriv/stores'; import { Localize, localize } from '@deriv/translations'; import TradigPlatformIconProps from 'Assets/svgs/trading-platform'; import { TPlatform } from 'Types'; @@ -67,6 +68,8 @@ const StaticCFDAccountManager = ({ }: TStaticCFDAccountManager) => { const icon_size = 48; const platform_color = platform === 'options' ? 'prominent' : 'general'; + const { traders_hub } = useStore(); + const { is_demo } = traders_hub; return (
))} + {platform === CFD_PLATFORMS.DERIVEZ && ( + + )} + {platform === CFD_PLATFORMS.DXTRADE && (
- {has_account && platform !== CFD_PLATFORMS.DXTRADE ? ( + {has_account ? (
)} - {!is_eu_user && !CFDs_restricted_countries && !financial_restricted_countries && ( - + {!is_eu_user && !CFDs_restricted_countries && ( +
+ + +
)}
)} diff --git a/packages/appstore/src/types/common.types.ts b/packages/appstore/src/types/common.types.ts index 4b6eabb1d0ae..d0ed899ca233 100644 --- a/packages/appstore/src/types/common.types.ts +++ b/packages/appstore/src/types/common.types.ts @@ -12,7 +12,7 @@ export type RequiredAndNotNull = { export type TRegionAvailability = 'Non-EU' | 'EU' | 'All'; export type TAccountCategory = 'real' | 'demo'; -export type TPlatform = 'dxtrade' | 'mt5' | 'trader' | 'dbot' | 'smarttrader' | 'bbot' | 'go'; +export type TPlatform = 'dxtrade' | 'mt5' | 'trader' | 'dbot' | 'smarttrader' | 'bbot' | 'go' | 'derivez'; export type TBrandData = { name: string; icon?: string; @@ -119,7 +119,8 @@ export type TIconTypes = | 'Options' | 'SmartTrader' | 'SmartTraderBlue' - | 'CFDs'; + | 'CFDs' + | 'DerivEz'; export interface AvailableAccount { name: string; diff --git a/packages/cfd/build/webpack.config.js b/packages/cfd/build/webpack.config.js index 078493b40060..83625342aa01 100644 --- a/packages/cfd/build/webpack.config.js +++ b/packages/cfd/build/webpack.config.js @@ -18,9 +18,11 @@ module.exports = function (env) { CFDServerErrorDialog: 'Containers/cfd-server-error-dialog.tsx', CFDTopUpDemoModal: 'Containers/cfd-top-up-demo-modal.tsx', MT5TradeModal: 'Containers/mt5-trade-modal.tsx', + TradeModal: 'Containers/trade-modal.tsx', CFDPasswordManagerModal: 'Containers/cfd-password-manager-modal.tsx', CFDFinancialStpRealAccountSignup: 'Containers/cfd-financial-stp-real-account-signup.tsx', getDXTradeWebTerminalLink: 'Helpers/constants.ts', + getDerivEzWebTerminalLink: 'Helpers/constants.ts', }, mode: IS_RELEASE ? 'production' : 'development', module: { diff --git a/packages/cfd/src/Assets/svgs/trading-platform/ic-appstore-derivez.svg b/packages/cfd/src/Assets/svgs/trading-platform/ic-appstore-derivez.svg new file mode 100644 index 000000000000..aba5315db1a0 --- /dev/null +++ b/packages/cfd/src/Assets/svgs/trading-platform/ic-appstore-derivez.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/cfd/src/Assets/svgs/trading-platform/index.tsx b/packages/cfd/src/Assets/svgs/trading-platform/index.tsx index b589a9ebb1f9..3f6e42f96452 100644 --- a/packages/cfd/src/Assets/svgs/trading-platform/index.tsx +++ b/packages/cfd/src/Assets/svgs/trading-platform/index.tsx @@ -2,6 +2,7 @@ import React from 'react'; import Derived from './ic-appstore-derived.svg'; import Financial from './ic-appstore-financial.svg'; import CFDs from './ic-appstore-cfds.svg'; +import DerivEz from './ic-appstore-derivez.svg'; import SwapFree from './ic-appstore-swap-free.svg'; export interface IconProps { @@ -15,6 +16,7 @@ export const PlatformIcons = { Derived, Financial, CFDs, + DerivEz, SwapFree, }; diff --git a/packages/cfd/src/Components/cfd-account-card.tsx b/packages/cfd/src/Components/cfd-account-card.tsx index 2f405bd00c97..588d9761547b 100644 --- a/packages/cfd/src/Components/cfd-account-card.tsx +++ b/packages/cfd/src/Components/cfd-account-card.tsx @@ -7,7 +7,11 @@ import { localize, Localize } from '@deriv/translations'; import { connect } from '../Stores/connect'; import RootStore from '../Stores/index'; import { CFDAccountCopy } from './cfd-account-copy'; -import { getDXTradeWebTerminalLink, getPlatformDXTradeDownloadLink } from '../Helpers/constants'; +import { + getDXTradeWebTerminalLink, + getDerivEzWebTerminalLink, + getPlatformDXTradeDownloadLink, +} from '../Helpers/constants'; import { TAccountIconValues, TSpecBoxProps, @@ -174,6 +178,7 @@ const CFDAccountCardComponent = ({ commission_message, descriptor, dxtrade_tokens, + derivez_tokens, existing_accounts_data, has_banner, has_cfd_account_error, @@ -181,7 +186,6 @@ const CFDAccountCardComponent = ({ is_accounts_switcher_on, is_button_primary, is_disabled, - is_eu, is_logged_in, is_virtual, isEligibleForMoreDemoMt5Svg, @@ -715,6 +719,23 @@ const CFDAccountCardComponent = ({ )} + {existing_data && + is_logged_in && + !is_web_terminal_unsupported && + platform === CFD_PLATFORMS.DERIVEZ && ( + + + + )} {!existing_data && is_logged_in && ( ({ dxtrade_tokens: cfd.dxtrade_tokens, + derivez_tokens: cfd.derivez_tokens, isEligibleForMoreDemoMt5Svg: client.isEligibleForMoreDemoMt5Svg, isEligibleForMoreRealMt5: client.isEligibleForMoreRealMt5, setAccountType: cfd.setAccountType, diff --git a/packages/cfd/src/Components/passwordbox.tsx b/packages/cfd/src/Components/passwordbox.tsx new file mode 100644 index 000000000000..70e0e1023125 --- /dev/null +++ b/packages/cfd/src/Components/passwordbox.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { getCFDPlatformLabel } from '@deriv/shared'; +import { Text, Button, Icon, Popover } from '@deriv/components'; +import { TPasswordBoxProps } from './props.types'; +import { localize } from '@deriv/translations'; + +const PasswordBox = ({ platform, onClick }: TPasswordBoxProps) => ( +
+
+ + *************** + +
+ +
+); + +export default PasswordBox; diff --git a/packages/cfd/src/Components/props.types.ts b/packages/cfd/src/Components/props.types.ts index 311bab8d4f29..5592f22479fd 100644 --- a/packages/cfd/src/Components/props.types.ts +++ b/packages/cfd/src/Components/props.types.ts @@ -2,11 +2,18 @@ import { DetailsOfEachMT5Loginid } from '@deriv/api-types'; export type TCFDPlatform = 'dxtrade' | 'mt5'; +export type TCFDsPlatformType = 'dxtrade' | 'derivez' | 'ctrader'; + export type TCFDAccountCopy = { text: string | undefined; className: string; }; +export type TDxtradeDesktopDownloadProps = { + dxtrade_tokens: TCFDDashboardContainer['dxtrade_tokens']; + is_demo: string; +}; + export type TAccountIconValues = { [key: string]: string }; export type TSpecBoxProps = { @@ -33,6 +40,10 @@ export type TCFDDashboardContainer = { demo: string; real: string; }; + derivez_tokens: { + demo: string; + real: string; + }; }; export type TCFDAccountCardActionProps = { @@ -64,8 +75,10 @@ export type TTradingPlatformAvailableAccount = { }; signup: string[]; }; - shortcode: 'bvi' | 'labuan' | 'svg' | 'vanuatu' | 'maltainvest'; + shortcode: 'bvi' | 'labuan' | 'maltainvest' | 'svg' | 'vanuatu'; sub_account_type: string; + account_type?: 'real' | 'demo'; + landing_company_short?: 'bvi' | 'labuan' | 'svg' | 'vanuatu'; }; export type TCardFlipStatus = { @@ -148,6 +161,10 @@ export type TCFDAccountCard = { demo: string; real: string; }; + derivez_tokens: { + demo: string; + real: string; + }; is_hovered?: boolean; isEligibleForMoreDemoMt5Svg: ( market_type: TTradingPlatformAvailableAccount['market_type'] | 'synthetic' diff --git a/packages/cfd/src/Components/specbox.tsx b/packages/cfd/src/Components/specbox.tsx new file mode 100644 index 000000000000..249d47cd0ce2 --- /dev/null +++ b/packages/cfd/src/Components/specbox.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { Text } from '@deriv/components'; +import { CFDAccountCopy } from './cfd-account-copy'; + +export type TSpecBoxProps = { + value?: string; + is_bold?: boolean; +}; + +const SpecBox = ({ value, is_bold }: TSpecBoxProps) => ( +
+ + {value} + + +
+); + +export default SpecBox; 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 d4741dbd08fb..3d0dd9b41ca2 100644 --- a/packages/cfd/src/Containers/__tests__/cfd-password-modal.spec.js +++ b/packages/cfd/src/Containers/__tests__/cfd-password-modal.spec.js @@ -341,7 +341,7 @@ describe('', () => { ); - expect(await screen.findByText('IcRebrandingDerivx')).toBeInTheDocument(); + expect(await screen.findByText('IcRebrandingDxtradeDashboard')).toBeInTheDocument(); }); it('should display IcCfds icon in Success Dialog', async () => { diff --git a/packages/cfd/src/Containers/cfd-dashboard.tsx b/packages/cfd/src/Containers/cfd-dashboard.tsx index bc2e24421588..eacb9fe9dc93 100644 --- a/packages/cfd/src/Containers/cfd-dashboard.tsx +++ b/packages/cfd/src/Containers/cfd-dashboard.tsx @@ -137,6 +137,10 @@ export type TCFDDashboardProps = RouteComponentProps & { demo: string; real: string; }; + derivez_tokens: { + demo: string; + real: string; + }; has_real_account: boolean; NotificationMessages: ({ ...props }) => JSX.Element; platform: 'mt5' | 'dxtrade'; @@ -425,6 +429,7 @@ const CFDDashboard = (props: TCFDDashboardProps) => { createCFDAccount, current_list, dxtrade_tokens, + derivez_tokens, dxtrade_accounts_list_error, isAccountOfTypeDisabled, is_accounts_switcher_on, @@ -719,6 +724,7 @@ const CFDDashboard = (props: TCFDDashboardProps) => { active_index={active_index} is_dark_mode_on={is_dark_mode_on} dxtrade_tokens={dxtrade_tokens} + derivez_tokens={derivez_tokens} /> @@ -781,6 +787,7 @@ export default withRouter( createCFDAccount: modules.cfd.createCFDAccount, current_list: modules.cfd.current_list, dxtrade_tokens: modules.cfd.dxtrade_tokens, + derivez_tokens: modules.cfd.derivez_tokens, landing_companies: client.landing_companies, isAccountOfTypeDisabled: client.isAccountOfTypeDisabled, is_logged_in: client.is_logged_in, diff --git a/packages/cfd/src/Containers/cfd-password-modal.tsx b/packages/cfd/src/Containers/cfd-password-modal.tsx index 0e0429dc44c9..6fc19ab61316 100644 --- a/packages/cfd/src/Containers/cfd-password-modal.tsx +++ b/packages/cfd/src/Containers/cfd-password-modal.tsx @@ -222,7 +222,9 @@ const ReviewMessageForMT5 = ({ const IconType = React.memo(({ platform, type, show_eu_related_content }: TIconTypeProps) => { const traders_hub = window.location.pathname === routes.traders_hub; if (platform === CFD_PLATFORMS.DXTRADE) { - return ; + return ; + } else if (platform === CFD_PLATFORMS.DERIVEZ) { + return ; } else if (traders_hub) { switch (type) { case 'synthetic': @@ -556,7 +558,9 @@ const CFDPasswordForm = ({ i18n_default_text='Enter your {{platform}} password to add a {{platform_name}} {{account}} {{jurisdiction_shortcode}} account.' values={{ platform: getCFDPlatformLabel(platform), - platform_name: platform === CFD_PLATFORMS.MT5 ? 'MT5' : 'Deriv X', + // account: !show_eu_related_content ? account_title : '', + platform_name: + platform === CFD_PLATFORMS.MT5 ? 'MT5' : getCFDPlatformLabel(platform), account: !show_eu_related_content ? getAccountTitle(platform, account_type, account_title) : '', @@ -569,7 +573,9 @@ const CFDPasswordForm = ({ i18n_default_text='Enter your {{platform}} password to add a {{platform_name}} {{account}} account.' values={{ platform: getCFDPlatformLabel(platform), - platform_name: platform === CFD_PLATFORMS.MT5 ? 'MT5' : 'Deriv X', + // account: account_title, + platform_name: + platform === CFD_PLATFORMS.MT5 ? 'MT5' : getCFDPlatformLabel(platform), account: getAccountTitle(platform, account_type, account_title), }} /> @@ -844,26 +850,44 @@ const CFDPasswordModal = ({ const mt5_platform_label = jurisdiction_selected_shortcode !== Jurisdiction.MALTA_INVEST ? 'MT5' : ''; if (category === 'real') { + let platformName = ''; + switch (platform) { + case CFD_PLATFORMS.MT5: + platformName = mt5_platform_label; + break; + case CFD_PLATFORMS.DERIVEZ: + platformName = 'Deriv Ez'; + break; + default: + platformName = 'Deriv X'; + break; + } + return ( , ]} + components={[, ]} /> {platform === CFD_PLATFORMS.DXTRADE ? ( ) : ( )} @@ -876,11 +900,16 @@ const CFDPasswordModal = ({ i18n_default_text='Congratulations, you have successfully created your {{category}} {{deriv_keyword}} <0>{{platform}} <1>{{type}} account.' values={{ deriv_keyword: platform === CFD_PLATFORMS.MT5 ? 'Deriv' : '', - type: platform === CFD_PLATFORMS.DXTRADE ? deriv_x_type_label : type_label, + type: + platform === CFD_PLATFORMS.DERIVEZ + ? 'CFDs' + : platform === CFD_PLATFORMS.DXTRADE + ? deriv_x_type_label + : type_label, platform: platform === CFD_PLATFORMS.MT5 ? 'MT5' : getCFDPlatformLabel(platform), category: category_label, }} - components={[, ]} + components={[, ]} /> ); }; diff --git a/packages/cfd/src/Containers/cfd-top-up-demo-modal.tsx b/packages/cfd/src/Containers/cfd-top-up-demo-modal.tsx index 1bd8a101bd64..136efc99b972 100644 --- a/packages/cfd/src/Containers/cfd-top-up-demo-modal.tsx +++ b/packages/cfd/src/Containers/cfd-top-up-demo-modal.tsx @@ -6,7 +6,7 @@ import { localize, Localize } from '@deriv/translations'; import { DetailsOfEachMT5Loginid } from '@deriv/api-types'; import RootStore from '../Stores/index'; import { connect } from '../Stores/connect'; -import { TDxCompanies, TMtCompanies } from '../Stores/Modules/CFD/Helpers/cfd-config'; +import { TDxCompanies, TMtCompanies, TDerivezCompanies } from '../Stores/Modules/CFD/Helpers/cfd-config'; import { getTopUpConfig } from '../Helpers/constants'; type TExtendedCurrentAccount = DetailsOfEachMT5Loginid & { @@ -17,6 +17,7 @@ type TExtendedCurrentAccount = DetailsOfEachMT5Loginid & { type TCFDTopUpDemoModalProps = { dxtrade_companies: TDxCompanies; + derivez_companies: TDerivezCompanies; mt5_companies: TMtCompanies; current_account?: TExtendedCurrentAccount; closeSuccessTopUpModal: () => void; @@ -31,6 +32,7 @@ type TCFDTopUpDemoModalProps = { const CFDTopUpDemoModal = ({ dxtrade_companies, + derivez_companies, mt5_companies, current_account, closeSuccessTopUpModal, @@ -44,7 +46,7 @@ const CFDTopUpDemoModal = ({ }: TCFDTopUpDemoModalProps) => { const getAccountTitle = React.useCallback(() => { let title = ''; - if ((!mt5_companies && !dxtrade_companies) || !current_account) return ''; + if ((!mt5_companies && !dxtrade_companies && !derivez_companies) || !current_account) return ''; switch (platform) { case CFD_PLATFORMS.MT5: @@ -53,6 +55,12 @@ const CFDTopUpDemoModal = ({ current_account.type as keyof TMtCompanies['demo' | 'real'] ].title; break; + case CFD_PLATFORMS.DERIVEZ: + title = + derivez_companies[current_account.category as keyof TDerivezCompanies][ + current_account.type as keyof TDerivezCompanies['demo' | 'real'] + ].title; + break; case CFD_PLATFORMS.DXTRADE: title = dxtrade_companies[current_account.category as keyof TDxCompanies][ @@ -64,7 +72,7 @@ const CFDTopUpDemoModal = ({ } return title; - }, [mt5_companies, dxtrade_companies, current_account]); + }, [mt5_companies, dxtrade_companies, current_account, derivez_companies]); const onCloseSuccess = () => { closeSuccessTopUpModal(); @@ -72,8 +80,7 @@ const CFDTopUpDemoModal = ({ const platform_title = getCFDPlatformLabel(platform); - if ((!mt5_companies && !dxtrade_companies) || !current_account) return null; - + if ((!mt5_companies && !dxtrade_companies && !derivez_companies) || !current_account) return null; const { minimum_amount, additional_amount } = getTopUpConfig(); return ( @@ -210,5 +217,6 @@ export default connect(({ ui, modules }: RootStore) => ({ current_account: modules.cfd.current_account, dxtrade_companies: modules.cfd.dxtrade_companies, mt5_companies: modules.cfd.mt5_companies, + derivez_companies: modules.cfd.derivez_companies, topUpVirtual: modules.cfd.topUpVirtual, }))(CFDTopUpDemoModal); diff --git a/packages/cfd/src/Containers/derivx-trade-modal.tsx b/packages/cfd/src/Containers/derivx-trade-modal.tsx index 58e8d32e98db..cc8ff412423f 100644 --- a/packages/cfd/src/Containers/derivx-trade-modal.tsx +++ b/packages/cfd/src/Containers/derivx-trade-modal.tsx @@ -117,7 +117,7 @@ const DxtradeDesktopDownload = ({ dxtrade_tokens, is_demo }: TDxtradeDesktopDown > } diff --git a/packages/cfd/src/Containers/dmt5-trade-modal.tsx b/packages/cfd/src/Containers/dmt5-trade-modal.tsx index 6dc38fa4985d..b4e95931b8ee 100644 --- a/packages/cfd/src/Containers/dmt5-trade-modal.tsx +++ b/packages/cfd/src/Containers/dmt5-trade-modal.tsx @@ -28,6 +28,7 @@ type TMT5TradeModalProps = { ) => void; toggleModal: () => void; dxtrade_tokens: TCFDDashboardContainer['dxtrade_tokens']; + derivez_tokens: TCFDDashboardContainer['derivez_tokens']; }; export type TSpecBoxProps = { diff --git a/packages/cfd/src/Containers/mt5-trade-modal.tsx b/packages/cfd/src/Containers/mt5-trade-modal.tsx index 55378ff4e374..35cea86a5a05 100644 --- a/packages/cfd/src/Containers/mt5-trade-modal.tsx +++ b/packages/cfd/src/Containers/mt5-trade-modal.tsx @@ -6,8 +6,8 @@ import { localize } from '@deriv/translations'; import { DetailsOfEachMT5Loginid } from '@deriv/api-types'; import { TTradingPlatformAvailableAccount } from '../../types'; import { TCFDDashboardContainer } from '../Components/props.types'; +import TradeModal from './trade-modal'; import DMT5TradeModal from './dmt5-trade-modal'; -import DerivXTradeModal from './derivx-trade-modal'; type TMT5TradeModalProps = { mt5_trade_account: Required< @@ -23,12 +23,12 @@ type TMT5TradeModalProps = { arg5: string | undefined ) => void; toggleModal: () => void; - platform: 'mt5' | 'dxtrade'; + platform: 'mt5' | 'dxtrade' | 'derivez'; dxtrade_tokens: TCFDDashboardContainer['dxtrade_tokens']; + derivez_tokens: TCFDDashboardContainer['derivez_tokens']; is_demo: string; show_eu_related_content: boolean; }; - const MT5TradeModal = ({ mt5_trade_account, is_eu_user, @@ -36,6 +36,7 @@ const MT5TradeModal = ({ onPasswordManager, toggleModal, dxtrade_tokens, + derivez_tokens, platform, is_demo, show_eu_related_content, @@ -49,17 +50,20 @@ const MT5TradeModal = ({ onPasswordManager={onPasswordManager} toggleModal={toggleModal} dxtrade_tokens={dxtrade_tokens} + derivez_tokens={derivez_tokens} /> ); } return ( - ); }; @@ -94,9 +98,9 @@ const MT5TradeModal = ({ ); }; - export default connect(({ modules: { cfd }, modules, common, traders_hub }: RootStore) => ({ dxtrade_tokens: cfd.dxtrade_tokens, + derivez_tokens: cfd.derivez_tokens, platform: common.platform, mt5_trade_account: modules.cfd.mt5_trade_account, show_eu_related_content: traders_hub.show_eu_related_content, diff --git a/packages/cfd/src/Containers/props.types.ts b/packages/cfd/src/Containers/props.types.ts index dee5ea971e20..01840e99884b 100644 --- a/packages/cfd/src/Containers/props.types.ts +++ b/packages/cfd/src/Containers/props.types.ts @@ -49,6 +49,10 @@ export type TCFDDashboardContainer = { demo: string; real: string; }; + derivez_tokens: { + demo: string; + real: string; + }; }; export type TMT5AccountOpeningRealFinancialStpModal = { diff --git a/packages/cfd/src/Containers/trade-modal.tsx b/packages/cfd/src/Containers/trade-modal.tsx new file mode 100644 index 000000000000..cb4d419d3b3c --- /dev/null +++ b/packages/cfd/src/Containers/trade-modal.tsx @@ -0,0 +1,240 @@ +import React from 'react'; +import { Text, Icon, Money } from '@deriv/components'; +import { TTradingPlatformAccounts, TCFDDashboardContainer, TCFDsPlatformType } from 'Components/props.types'; +import { DetailsOfEachMT5Loginid } from '@deriv/api-types'; +import { CFD_PLATFORMS, getCFDAccountKey, isMobile } from '@deriv/shared'; +import { localize, Localize } from '@deriv/translations'; +import { getPlatformQRCode, PlatformsDesktopDownload } from '../Helpers/config'; +import { getTitle, platformsText, mobileDownloadLink } from '../Helpers/constants'; +import SpecBox from 'Components/specbox'; +import PasswordBox from 'Components/passwordbox'; + +type TTradeModalProps = { + mt5_trade_account: Required; + is_eu_user: boolean; + onPasswordManager: ( + arg1: string | undefined, + arg2: string, + arg3: string, + arg4: string, + arg5: string | undefined + ) => void; + toggleModal: () => void; + dxtrade_tokens: TCFDDashboardContainer['dxtrade_tokens']; + derivez_tokens: TCFDDashboardContainer['derivez_tokens']; + is_demo: string; + platform: TCFDsPlatformType; +}; + +const PlatformIconsAndDescriptions = (platform: TCFDsPlatformType, is_demo: string) => { + return ( + + +
+ + + +
+
+ ); +}; + +const TradeModal = ({ + mt5_trade_account, + is_eu_user, + onPasswordManager, + toggleModal, + dxtrade_tokens, + derivez_tokens, + is_demo, + platform, +}: TTradeModalProps) => { + const CTraderAndDerivEZDescription = () => { + const platform_name = platform === 'derivez' ? 'Deriv EZ' : 'cTrader'; + return ( +
+ + + +
+ ); + }; + const downloadCenterDescription = () => { + switch (platform) { + case 'dxtrade': + return ( + + {localize('Download Deriv X on your phone to trade with the Deriv X account')} + + ); + case 'derivez': + return ( + + {localize('Download Deriv GO on your phone to trade with the Deriv EZ account')} + + ); + case 'ctrader': + return ( + + {localize('Download Deriv cTrader on your phone to trade with the Deriv cTrader account')} + + ); + default: + return ''; + } + }; + + const downloadCenterAppOption = (platform_type: TCFDsPlatformType) => { + let appTitle = ''; + if (platform_type === 'dxtrade') { + appTitle = 'Run Deriv X on your browser'; + } else if (platform_type === 'derivez') { + appTitle = 'Run Deriv EZ on your browser'; + } else if (platform_type === 'ctrader') { + appTitle = 'Run Deriv cTrader on your browser'; + } else { + return null; + } + + return ( + +
+ + {localize(appTitle)} + + +
+
+ ); + }; + + return ( +
+
+ {PlatformIconsAndDescriptions(platform, is_demo)} + {mt5_trade_account?.display_balance && ( + + + + )} +
+
+ {platform !== 'dxtrade' && } + {platform === 'dxtrade' && ( + +
+ {localize('Username')} + +
+
+ {localize('Password')} +
+ { + const account_type = getCFDAccountKey({ + market_type: mt5_trade_account.market_type, + sub_account_type: mt5_trade_account.sub_account_type, + platform: CFD_PLATFORMS.DMT5, + shortcode: mt5_trade_account.landing_company_short, + }); + onPasswordManager( + mt5_trade_account?.login, + getTitle(mt5_trade_account.market_type, is_eu_user), + mt5_trade_account.account_type, + account_type, + (mt5_trade_account as DetailsOfEachMT5Loginid)?.server + ); + toggleModal(); + }} + /> +
+
+
+ )} + +
+ +
+ + {platform === CFD_PLATFORMS.DXTRADE && ( + + )} + {platform === CFD_PLATFORMS.MT5 && ( + + )} + {platform === CFD_PLATFORMS.DERIVEZ && ( + + )} + +
+
+
+
{downloadCenterAppOption(platform)}
+
{downloadCenterDescription()}
+
+
+
+ + + +
+ + + + + + +
+ {!isMobile() && ( +
+ {getPlatformQRCode(platform)} +
+ )} +
+
+ ); +}; + +export default TradeModal; diff --git a/packages/cfd/src/Helpers/config.tsx b/packages/cfd/src/Helpers/config.tsx new file mode 100644 index 000000000000..f955b624f06f --- /dev/null +++ b/packages/cfd/src/Helpers/config.tsx @@ -0,0 +1,89 @@ +import React from 'react'; +import { QRCode } from 'react-qrcode'; +import { TCFDsPlatformType } from 'Components/props.types'; +import { + getDXTradeWebTerminalLink, + getDerivEzWebTerminalLink, + platformsText, + platformsIcons, + mobileDownloadLink, +} from './constants'; +import { Text, Icon } from '@deriv/components'; +import { Localize } from '@deriv/translations'; +import { isMobile, OSDetect, isDesktopOs } from '@deriv/shared'; +import { TCFDDashboardContainer } from 'Containers/props.types'; + +export const getPlatformQRCode = (acc_type: TCFDsPlatformType) => { + const qr_code_width = isMobile() ? '100%' : '80%'; + const os = OSDetect(); + const checkForDesktop = isDesktopOs() ? (os === 'mac' ? 'ios' : 'android') : os; + + return ( + + + + + + + ); +}; + +type TPlatformsDesktopDownload = { + platform: TCFDsPlatformType; + dxtrade_tokens: TCFDDashboardContainer['dxtrade_tokens']; + derivez_tokens: TCFDDashboardContainer['derivez_tokens']; + is_demo: string; +}; + +export const PlatformsDesktopDownload = ({ + platform, + dxtrade_tokens, + derivez_tokens, + is_demo, +}: TPlatformsDesktopDownload) => { + const PlatformsDesktopDownloadLinks = () => { + switch (platform) { + case 'derivez': + return getDerivEzWebTerminalLink( + is_demo ? 'demo' : 'real', + derivez_tokens && derivez_tokens[is_demo ? 'demo' : 'real'] + ); + case 'dxtrade': + return getDXTradeWebTerminalLink( + is_demo ? 'demo' : 'real', + dxtrade_tokens && dxtrade_tokens[is_demo ? 'demo' : 'real'] + ); + default: + return ''; + } + }; + + return ( + + + +
+ + + +
+
+
+ ); +}; diff --git a/packages/cfd/src/Helpers/constants.ts b/packages/cfd/src/Helpers/constants.ts index 691457505789..fdad551a2643 100644 --- a/packages/cfd/src/Helpers/constants.ts +++ b/packages/cfd/src/Helpers/constants.ts @@ -1,8 +1,53 @@ import { OSDetect } from '@deriv/shared'; +import { localize } from '@deriv/translations'; +import { TCFDsPlatformType } from 'Components/props.types'; + +const platformsText = (platform: TCFDsPlatformType) => { + switch (platform) { + case 'derivez': + return 'EZ'; + case 'dxtrade': + return 'X'; + default: + return ''; + } +}; + +const platformsIcons = (platform: TCFDsPlatformType) => { + switch (platform) { + case 'derivez': + return 'DerivEz'; + case 'dxtrade': + return 'Dxtrade'; + default: + return ''; + } +}; + +const mobileDownloadLink = (platform: TCFDsPlatformType, type: 'ios' | 'android' | 'huawei') => { + switch (platform) { + case 'dxtrade': + return getPlatformDXTradeDownloadLink(type); + case 'derivez': + return getPlatformDerivEZDownloadLink(type); + default: + return ''; + } +}; + +const getTitle = (market_type: string, is_eu_user: boolean) => { + if (is_eu_user) localize('MT5 CFDs'); + return market_type; +}; const REAL_DXTRADE_URL = 'https://dx.deriv.com'; const DEMO_DXTRADE_URL = 'https://dx-demo.deriv.com'; +const DERIVEZ_URL = 'https://dqwsqxuu0r6t9.cloudfront.net/'; +const DERIVEZ_IOS_APP_URL = 'https://apps.apple.com/my/app/deriv-go/id1550561298'; +const DERIVEZ_ANDROID_APP_URL = 'https://play.google.com/store/apps/details?id=com.deriv.app&pli=1'; +const DERIVEZ_HUAWEI_APP_URL = 'https://appgallery.huawei.com/#/app/C103801913'; + const DXTRADE_IOS_APP_URL = 'https://apps.apple.com/us/app/deriv-x/id1563337503'; const DXTRADE_ANDROID_APP_URL = 'https://play.google.com/store/apps/details?id=com.deriv.dx'; const DXTRADE_HUAWEI_APP_URL = 'https://appgallery.huawei.com/app/C104633219'; @@ -16,14 +61,29 @@ const getTopUpConfig = () => { }; }; -const getPlatformDXTradeDownloadLink = (platform: 'ios' | 'android' | 'huawei') => { +const getPlatformDXTradeDownloadLink = (platform?: 'ios' | 'android' | 'huawei') => { switch (platform) { case 'ios': return DXTRADE_IOS_APP_URL; case 'huawei': return DXTRADE_HUAWEI_APP_URL; - default: + case 'android': return DXTRADE_ANDROID_APP_URL; + default: + return ''; + } +}; + +const getPlatformDerivEZDownloadLink = (platform: 'ios' | 'android' | 'huawei') => { + switch (platform) { + case 'ios': + return DERIVEZ_IOS_APP_URL; + case 'android': + return DERIVEZ_ANDROID_APP_URL; + case 'huawei': + return DERIVEZ_HUAWEI_APP_URL; + default: + return ''; } }; @@ -56,6 +116,16 @@ const getDXTradeWebTerminalLink = (category: string, token?: string) => { return url; }; +const getDerivEzWebTerminalLink = (category: string, token?: string) => { + let url = DERIVEZ_URL; + + if (token) { + url += `?token=${token}`; + } + + return url; +}; + const getMT5WebTerminalLink = ({ category, loginid, @@ -75,10 +145,17 @@ const getMT5WebTerminalLink = ({ export { REAL_DXTRADE_URL, DEMO_DXTRADE_URL, + DERIVEZ_URL, getBrokerName, + platformsText, + platformsIcons, + getTitle, + mobileDownloadLink, getPlatformDXTradeDownloadLink, + getPlatformDerivEZDownloadLink, getPlatformMt5DownloadLink, getDXTradeWebTerminalLink, + getDerivEzWebTerminalLink, getMT5WebTerminalLink, getTopUpConfig, }; diff --git a/packages/cfd/src/Stores/Modules/CFD/Helpers/cfd-config.ts b/packages/cfd/src/Stores/Modules/CFD/Helpers/cfd-config.ts index 0ba47eb40d3f..337c33a84e9e 100644 --- a/packages/cfd/src/Stores/Modules/CFD/Helpers/cfd-config.ts +++ b/packages/cfd/src/Stores/Modules/CFD/Helpers/cfd-config.ts @@ -3,6 +3,7 @@ import { Jurisdiction } from '@deriv/shared'; export type TDxCompanies = ReturnType; export type TMtCompanies = ReturnType; +export type TDerivezCompanies = ReturnType; export const getDxCompanies = () => { const all_config = { @@ -75,7 +76,7 @@ export const getMtCompanies = (is_eu: boolean) => { const all_config = { account_type: '', leverage: 100, - short_title: localize('Swap-Free'), + short_title: localize('Demo'), }; const synthetic_config = { account_type: '', @@ -107,6 +108,12 @@ export const getMtCompanies = (is_eu: boolean) => { title: localize('Demo Swap-Free SVG'), short_title: all_config.short_title, }, + derivez: { + mt5_account_type: all_config.account_type, + leverage: all_config.leverage, + title: localize('Demo'), + short_title: all_config.short_title, + }, synthetic: { mt5_account_type: synthetic_config.account_type, leverage: synthetic_config.leverage, @@ -158,6 +165,12 @@ export const getMtCompanies = (is_eu: boolean) => { title: localize('Real'), short_title: all_config.short_title, }, + derivez: { + mt5_account_type: all_config.account_type, + leverage: all_config.leverage, + title: localize('Real'), + short_title: all_config.short_title, + }, synthetic: { mt5_account_type: synthetic_config.account_type, leverage: synthetic_config.leverage, @@ -216,6 +229,32 @@ export const getMtCompanies = (is_eu: boolean) => { }; }; +export const getDerivezCompanies = () => { + const all_config = { + account_type: '', + leverage: 1000, + short_title: localize('CFDs'), + }; + return { + demo: { + all: { + derivez_account_type: all_config.account_type, + leverage: all_config.leverage, + title: localize('Demo'), + short_title: all_config.short_title, + }, + }, + real: { + all: { + derivez_account_type: all_config.account_type, + leverage: all_config.leverage, + title: localize('Real'), + short_title: all_config.short_title, + }, + }, + }; +}; + export const getFormattedJurisdictionCode = (jurisdiction_code: string) => { let formatted_label = ''; diff --git a/packages/cfd/src/Stores/Modules/CFD/cfd-store.js b/packages/cfd/src/Stores/Modules/CFD/cfd-store.js index ae9771796202..bd38722f3b7d 100644 --- a/packages/cfd/src/Stores/Modules/CFD/cfd-store.js +++ b/packages/cfd/src/Stores/Modules/CFD/cfd-store.js @@ -1,7 +1,7 @@ import { action, computed, observable, reaction, runInAction, makeObservable, override } from 'mobx'; import { getAccountListKey, getAccountTypeFields, CFD_PLATFORMS, WS, Jurisdiction } from '@deriv/shared'; import BaseStore from 'Stores/base-store'; -import { getDxCompanies, getMtCompanies } from './Helpers/cfd-config'; +import { getDxCompanies, getMtCompanies, getDerivezCompanies } from './Helpers/cfd-config'; export default class CFDStore extends BaseStore { is_compare_accounts_visible = false; @@ -21,6 +21,7 @@ export default class CFDStore extends BaseStore { has_cfd_error = false; error_message = ''; + is_account_being_created = false; is_cfd_success_dialog_enabled = false; is_mt5_financial_stp_modal_open = false; is_cfd_password_modal_enabled = false; @@ -34,6 +35,10 @@ export default class CFDStore extends BaseStore { demo: '', real: '', }; + derivez_tokens = { + demo: '', + real: '', + }; real_synthetic_accounts_existing_data = []; real_financial_accounts_existing_data = []; @@ -54,6 +59,7 @@ export default class CFDStore extends BaseStore { map_type: observable, has_cfd_error: observable, error_message: observable, + is_account_being_created: observable, is_cfd_success_dialog_enabled: observable, is_mt5_financial_stp_modal_open: observable, is_cfd_password_modal_enabled: observable, @@ -61,6 +67,7 @@ export default class CFDStore extends BaseStore { is_cfd_verification_modal_visible: observable, error_type: observable, dxtrade_tokens: observable, + derivez_tokens: observable, account_title: computed, current_list: computed, has_created_account_for_selected_jurisdiction: computed, @@ -83,6 +90,7 @@ export default class CFDStore extends BaseStore { setAccountType: action.bound, setCurrentAccount: action.bound, setMT5TradeAccount: action.bound, + setIsAccountBeingCreated: action.bound, setError: action.bound, setCFDNewAccount: action.bound, setCFDSuccessDialog: action.bound, @@ -104,7 +112,9 @@ export default class CFDStore extends BaseStore { setJurisdictionSelectedShortcode: action.bound, toggleCFDVerificationModal: action.bound, setDxtradeToken: action.bound, + setDerivezToken: action.bound, loadDxtradeTokens: action.bound, + loadDerivezTokens: action.bound, }); reaction( @@ -115,6 +125,16 @@ export default class CFDStore extends BaseStore { } } ); + + // todo: uncomment this once derivez tokens are ready + // reaction( + // () => [this.root_store.client.derivez_accounts_list], + // () => { + // if (this.root_store.client.derivez_accounts_list.length > 0) { + // this.loadDerivezTokens(); + // } + // } + // ); } get account_title() { @@ -154,6 +174,13 @@ export default class CFDStore extends BaseStore { }; }); + this.root_store.client.derivez_accounts_list.forEach(account => { + // e.g. derivez.real.financial_stp + list[getAccountListKey(account, CFD_PLATFORMS.DERIVEZ)] = { + ...account, + }; + }); + return list; } @@ -166,6 +193,12 @@ export default class CFDStore extends BaseStore { get dxtrade_companies() { return getDxCompanies(); } + + // eslint-disable-next-line class-methods-use-this + get derivez_companies() { + return getDerivezCompanies(); + } + get has_created_account_for_selected_jurisdiction() { switch (this.account_type.type) { case 'synthetic': @@ -205,6 +238,10 @@ export default class CFDStore extends BaseStore { } } + setIsAccountBeingCreated(is_account_being_created) { + this.is_account_being_created = is_account_being_created; + } + realAccountSignupEndListener() { const post_signup = JSON.parse(sessionStorage.getItem('post_real_account_signup')); if (post_signup && post_signup.category && post_signup.type) { @@ -225,8 +262,9 @@ export default class CFDStore extends BaseStore { this.is_cfd_password_modal_enabled = false; } - createCFDAccount({ category, platform, type, set_password }) { + async createCFDAccount({ category, platform, type, set_password }) { this.clearCFDError(); + this.setIsAccountBeingCreated(true); this.setAccountType({ category, type, @@ -246,6 +284,26 @@ export default class CFDStore extends BaseStore { } else this.setJurisdictionSelectedShortcode(Jurisdiction.SVG); this.demoCFDSignup(); } + } else if (platform === CFD_PLATFORMS.DERIVEZ) { + this.setJurisdictionSelectedShortcode('svg'); + const values = { + platform, + account_type: this.account_type.category, + market_type: this.account_type.type, + company: this.jurisdiction_selected_shortcode, + }; + const response = await this.openCFDAccount(values); + if (!response.error) { + this.enableCFDPasswordModal(); + this.setCFDSuccessDialog(true); + const trading_platform_accounts_list_response = await WS.tradingPlatformAccountsList(values.platform); + this.root_store.client.responseTradingPlatformAccountsList(trading_platform_accounts_list_response); + this.setCFDNewAccount(response.trading_platform_new_account); + this.setIsAccountBeingCreated(false); + } else { + this.setError(true, response.error); + this.setIsAccountBeingCreated(false); + } } } @@ -301,10 +359,14 @@ export default class CFDStore extends BaseStore { openCFDAccount(values) { return WS.tradingPlatformNewAccount({ - password: values.password, + password: CFD_PLATFORMS.DXTRADE ? values.password : '', platform: values.platform, account_type: this.account_type.category, - market_type: this.account_type.type === 'dxtrade' ? 'all' : this.account_type.type, + market_type: + this.account_type.type === 'dxtrade' || this.account_type.type === 'derivez' + ? 'all' + : this.account_type.type, + company: CFD_PLATFORMS.DERIVEZ ? this.jurisdiction_selected_shortcode : '', }); } @@ -475,31 +537,32 @@ export default class CFDStore extends BaseStore { } async submitCFDPassword(values, actions) { - if (this.root_store.client.is_dxtrade_password_not_set) { + if (CFD_PLATFORMS.DXTRADE && this.root_store.client.is_dxtrade_password_not_set) { const has_error = await this.createCFDPassword(values, actions); if (has_error) return; } const response = await this.openCFDAccount(values); - if (!response.error) { - actions.setStatus({ success: true }); - actions.setSubmitting(false); - this.setError(false); - this.setCFDSuccessDialog(true); - await this.getAccountStatus(CFD_PLATFORMS.DXTRADE); - - const trading_platform_accounts_list_response = await WS.tradingPlatformAccountsList(values.platform); - this.root_store.client.responseTradingPlatformAccountsList(trading_platform_accounts_list_response); - WS.transferBetweenAccounts(); // get the list of updated accounts for transfer in cashier - this.setCFDNewAccount(response.trading_platform_new_account); - } else { + if (response.error) { await this.getAccountStatus(CFD_PLATFORMS.DXTRADE); this.setError(true, response.error); actions.resetForm({}); actions.setSubmitting(false); actions.setStatus({ success: false }); } + + actions.setStatus({ success: true }); + actions.setSubmitting(false); + this.setError(false); + this.setCFDSuccessDialog(true); + await this.getAccountStatus(CFD_PLATFORMS.DXTRADE); + + const trading_platform_accounts_list_response = await WS.tradingPlatformAccountsList(values.platform); + this.root_store.client.responseTradingPlatformAccountsList(trading_platform_accounts_list_response); + + WS.transferBetweenAccounts(); // get the list of updated accounts for transfer in cashier + this.setCFDNewAccount(response.trading_platform_new_account); } toggleCompareAccountsModal() { @@ -549,6 +612,14 @@ export default class CFDStore extends BaseStore { }); break; } + case CFD_PLATFORMS.DERIVEZ: { + response = await WS.authorized.send({ + trading_platform_deposit: 1, + platform: CFD_PLATFORMS.DERIVEZ, + to_account: this.current_account.login, + }); + break; + } default: { response.error = 'Invalid platform'; break; @@ -575,6 +646,15 @@ export default class CFDStore extends BaseStore { )?.balance; break; } + case CFD_PLATFORMS.DERIVEZ: { + await WS.authorized + .tradingPlatformAccountsList(CFD_PLATFORMS.DERIVEZ) + .then(this.root_store.client.responseTradingPlatformAccountsList); + new_balance = this.root_store.client.derivez_accounts_list.find( + item => item.account_id === this.current_account.account_id + )?.balance; + break; + } default: { break; } @@ -621,6 +701,27 @@ export default class CFDStore extends BaseStore { }); } + setDerivezToken(response, server) { + if (!response.error) { + const { derivez } = response.service_token; + this.derivez_tokens[server] = derivez.token; + } + } + + loadDerivezTokens() { + ['demo', 'real'].forEach(account_type => { + const has_existing_account = this.root_store.client.derivez_accounts_list.some( + account => account.account_type === account_type + ); + + if (!this.derivez_tokens[account_type] && has_existing_account) { + WS.getServiceToken(CFD_PLATFORMS.DERIVEZ, account_type).then(response => + this.setDerivezToken(response, account_type) + ); + } + }); + } + static async changePassword({ login, old_password, new_password, password_type }) { let response; diff --git a/packages/cfd/src/sass/cfd-dashboard.scss b/packages/cfd/src/sass/cfd-dashboard.scss index 5665ff780c70..813626c1348e 100644 --- a/packages/cfd/src/sass/cfd-dashboard.scss +++ b/packages/cfd/src/sass/cfd-dashboard.scss @@ -236,7 +236,7 @@ } } - &-dxtrade-button { + &__dxtrade-button { background: $color-black-7; border-radius: $BORDER_RADIUS; text-decoration: none; @@ -255,7 +255,7 @@ padding: 0.4rem 0rem 0.4rem 0.2rem; } &-icon { - margin-left: 0.6rem; + padding-left: 0.6rem; } } @@ -1389,6 +1389,12 @@ padding-top: 2rem; padding-bottom: 5.8rem; + &-description { + display: flex; + justify-content: center; + margin-top: 1.4rem; + } + &-app { display: flex; flex-direction: column; @@ -1493,7 +1499,7 @@ display: flex; flex-direction: column; width: 13.6rem; - height: 14rem; + height: auto; padding: 0.8rem; align-items: center; justify-content: center; diff --git a/packages/components/src/components/icon/brand/ic-brand-deriv-ez-wordmark.svg b/packages/components/src/components/icon/brand/ic-brand-deriv-ez-wordmark.svg new file mode 100644 index 000000000000..6bd214a6945e --- /dev/null +++ b/packages/components/src/components/icon/brand/ic-brand-deriv-ez-wordmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/brand/ic-brand-deriv-ez.svg b/packages/components/src/components/icon/brand/ic-brand-deriv-ez.svg new file mode 100644 index 000000000000..aba5315db1a0 --- /dev/null +++ b/packages/components/src/components/icon/brand/ic-brand-deriv-ez.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/brand/ic-brand-dxtrade-wordmark.svg b/packages/components/src/components/icon/brand/ic-brand-dxtrade-wordmark.svg new file mode 100644 index 000000000000..891328871501 --- /dev/null +++ b/packages/components/src/components/icon/brand/ic-brand-dxtrade-wordmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/icons.js b/packages/components/src/components/icon/icons.js index 75787a4e3f2e..9269474c823a 100644 --- a/packages/components/src/components/icon/icons.js +++ b/packages/components/src/components/icon/icons.js @@ -52,11 +52,14 @@ import './appstore/ic-appstore-wallet-usd-light.svg'; import './appstore/ic-appstore-wallet-usdc-light.svg'; import './appstore/ic-appstore-wallet-usdt-light.svg'; import './appstore/ic-appstore-warning.svg'; +import './brand/ic-brand-deriv-ez-wordmark.svg'; +import './brand/ic-brand-deriv-ez.svg'; import './brand/ic-brand-deriv.svg'; import './brand/ic-brand-derivgo.svg'; import './brand/ic-brand-dmt5-financial-stp.svg'; import './brand/ic-brand-dmt5-financial.svg'; import './brand/ic-brand-dmt5-synthetics.svg'; +import './brand/ic-brand-dxtrade-wordmark.svg'; import './cashier/ic-cashier-add.svg'; import './cashier/ic-cashier-air-tm-dark.svg'; import './cashier/ic-cashier-air-tm-light.svg'; @@ -712,15 +715,18 @@ import './option/ic-option-up-down-asian.svg'; import './rebranding/ic-rebranding-binary-bot.svg'; import './rebranding/ic-rebranding-deriv-bot-dashboard.svg'; import './rebranding/ic-rebranding-deriv-bot.svg'; +import './rebranding/ic-rebranding-deriv-ez-wordmark.svg'; +import './rebranding/ic-rebranding-deriv-ez.svg'; import './rebranding/ic-rebranding-deriv-go-dashboard.svg'; import './rebranding/ic-rebranding-deriv-trader-dashboard.svg'; import './rebranding/ic-rebranding-deriv-trader.svg'; import './rebranding/ic-rebranding-deriv-x.svg'; -import './rebranding/ic-rebranding-derivx-wordmark.svg'; +import './rebranding/ic-rebranding-derivez-dashboard.svg'; import './rebranding/ic-rebranding-derivx.svg'; import './rebranding/ic-rebranding-dmt5-dashboard.svg'; import './rebranding/ic-rebranding-dmt5.svg'; import './rebranding/ic-rebranding-dxtrade-dashboard.svg'; +import './rebranding/ic-rebranding-dxtrade-wordmark.svg'; import './rebranding/ic-rebranding-dxtrade.svg'; import './rebranding/ic-rebranding-mt5-logo.svg'; import './rebranding/ic-rebranding-smarttrader-dashboard.svg'; diff --git a/packages/components/src/components/icon/rebranding/ic-rebranding-deriv-ez-wordmark.svg b/packages/components/src/components/icon/rebranding/ic-rebranding-deriv-ez-wordmark.svg new file mode 100644 index 000000000000..6bd214a6945e --- /dev/null +++ b/packages/components/src/components/icon/rebranding/ic-rebranding-deriv-ez-wordmark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/rebranding/ic-rebranding-deriv-ez.svg b/packages/components/src/components/icon/rebranding/ic-rebranding-deriv-ez.svg new file mode 100644 index 000000000000..aba5315db1a0 --- /dev/null +++ b/packages/components/src/components/icon/rebranding/ic-rebranding-deriv-ez.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/rebranding/ic-rebranding-derivez-dashboard.svg b/packages/components/src/components/icon/rebranding/ic-rebranding-derivez-dashboard.svg new file mode 100644 index 000000000000..aba5315db1a0 --- /dev/null +++ b/packages/components/src/components/icon/rebranding/ic-rebranding-derivez-dashboard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/components/src/components/icon/rebranding/ic-rebranding-derivx-wordmark.svg b/packages/components/src/components/icon/rebranding/ic-rebranding-dxtrade-wordmark.svg similarity index 100% rename from packages/components/src/components/icon/rebranding/ic-rebranding-derivx-wordmark.svg rename to packages/components/src/components/icon/rebranding/ic-rebranding-dxtrade-wordmark.svg diff --git a/packages/components/stories/icon/icons.js b/packages/components/stories/icon/icons.js index a0b968597776..4f05c5bf3aa7 100644 --- a/packages/components/stories/icon/icons.js +++ b/packages/components/stories/icon/icons.js @@ -57,11 +57,14 @@ export const icons = 'IcAppstoreWarning', ], 'brand': [ + 'IcBrandDerivEzWordmark', + 'IcBrandDerivEz', 'IcBrandDeriv', 'IcBrandDerivgo', 'IcBrandDmt5FinancialStp', 'IcBrandDmt5Financial', 'IcBrandDmt5Synthetics', + 'IcBrandDxtradeWordmark', ], 'cashier': [ 'IcCashierAdd', @@ -737,15 +740,18 @@ export const icons = 'IcRebrandingBinaryBot', 'IcRebrandingDerivBotDashboard', 'IcRebrandingDerivBot', + 'IcRebrandingDerivEzWordmark', + 'IcRebrandingDerivEz', 'IcRebrandingDerivGoDashboard', 'IcRebrandingDerivTraderDashboard', 'IcRebrandingDerivTrader', 'IcRebrandingDerivX', - 'IcRebrandingDerivxWordmark', + 'IcRebrandingDerivezDashboard', 'IcRebrandingDerivx', 'IcRebrandingDmt5Dashboard', 'IcRebrandingDmt5', 'IcRebrandingDxtradeDashboard', + 'IcRebrandingDxtradeWordmark', 'IcRebrandingDxtrade', 'IcRebrandingMt5Logo', 'IcRebrandingSmarttraderDashboard', diff --git a/packages/core/src/Stores/client-store.js b/packages/core/src/Stores/client-store.js index d52a1fd5a7a9..02e5deb1ccbd 100644 --- a/packages/core/src/Stores/client-store.js +++ b/packages/core/src/Stores/client-store.js @@ -52,6 +52,7 @@ export default class ClientStore extends BaseStore { email; accounts = {}; trading_platform_available_accounts = []; + derivez_available_accounts = []; pre_switch_broadcast = false; switched = ''; is_switching = false; @@ -102,6 +103,7 @@ export default class ClientStore extends BaseStore { mt5_login_list = []; mt5_login_list_error = null; dxtrade_accounts_list = []; + derivez_accounts_list = []; dxtrade_accounts_list_error = null; dxtrade_disabled_signup_types = { real: false, demo: false }; statement = []; @@ -167,6 +169,7 @@ export default class ClientStore extends BaseStore { email: observable, accounts: observable, trading_platform_available_accounts: observable, + derivez_available_accounts: observable, pre_switch_broadcast: observable, switched: observable, is_switching: observable, @@ -202,6 +205,7 @@ export default class ClientStore extends BaseStore { mt5_login_list: observable, mt5_login_list_error: observable, dxtrade_accounts_list: observable, + derivez_accounts_list: observable, dxtrade_accounts_list_error: observable, dxtrade_disabled_signup_types: observable, statement: observable, @@ -379,6 +383,7 @@ export default class ClientStore extends BaseStore { responseMt5LoginList: action.bound, responseDxtradeTradingServers: action.bound, responseTradingPlatformAvailableAccounts: action.bound, + responseDerivezAvailableAccounts: action.bound, responseTradingPlatformAccountsList: action.bound, responseStatement: action.bound, getChangeableFields: action.bound, @@ -621,10 +626,26 @@ export default class ClientStore extends BaseStore { return this.dxtrade_accounts_list.some(account => account.account_type === 'real'); } + get has_real_derivez_login() { + return this.derivez_accounts_list.some(account => account.account_type === 'real'); + } + hasAccountErrorInCFDList = (platform, account_type) => { if (!this.is_logged_in) return false; - - const list = platform === CFD_PLATFORMS.MT5 ? this.mt5_login_list : this.dxtrade_accounts_list; + let list; + switch (platform) { + case CFD_PLATFORMS.MT5: + list = this.mt5_login_list; + break; + case CFD_PLATFORMS.DXTRADE: + list = this.dxtrade_accounts_list; + break; + case CFD_PLATFORMS.DERIVEZ: + list = this.derivez_accounts_list; + break; + default: + return false; + } return list?.some(account => !!account.has_error && account.account_type === account_type); }; @@ -1299,7 +1320,6 @@ export default class ClientStore extends BaseStore { return new Promise(resolve => { let client_accounts; const has_client_accounts = !!LocalStore.get(storage_key); - const { oauth_token, client_id } = response.new_account_real ?? response.new_account_maltainvest; runInAction(() => { this.is_populating_account_list = true; @@ -1318,6 +1338,7 @@ export default class ClientStore extends BaseStore { console.error('JSON parse failed, invalid value (client.accounts): ', error); } + const { oauth_token, client_id } = response.new_account_real ?? response.new_account_maltainvest; BinarySocket.authorize(oauth_token) .then(authorize_response => { const new_data = {}; @@ -1673,6 +1694,8 @@ export default class ClientStore extends BaseStore { WS.tradingPlatformAvailableAccounts(CFD_PLATFORMS.MT5).then(this.responseTradingPlatformAvailableAccounts); WS.tradingPlatformAccountsList(CFD_PLATFORMS.DXTRADE).then(this.responseTradingPlatformAccountsList); WS.tradingServers(CFD_PLATFORMS.DXTRADE).then(this.responseDxtradeTradingServers); + WS.tradingPlatformAccountsList(CFD_PLATFORMS.DERIVEZ).then(this.responseTradingPlatformAccountsList); + WS.tradingPlatformAccountsList(CFD_PLATFORMS.DERIVEZ).then(this.responseDerivezAvailableAccounts); this.responseStatement( await BinarySocket.send({ @@ -2069,6 +2092,7 @@ export default class ClientStore extends BaseStore { this.accounts = {}; this.mt5_login_list = []; this.dxtrade_accounts_list = []; + this.derivez_accounts_list = []; this.landing_companies = {}; localStorage.removeItem('readScamMessage'); localStorage.removeItem('isNewAccount'); @@ -2456,6 +2480,11 @@ export default class ClientStore extends BaseStore { this.setMT5DisabledSignupTypes({ [account_type]: true, }); + if (platform === CFD_PLATFORMS.DERIVEZ) { + this.setCFDDisabledSignupTypes(platform, { + [account_type]: true, + }); + } return { account_type, display_login, @@ -2496,6 +2525,12 @@ export default class ClientStore extends BaseStore { } } + responseDerivezAvailableAccounts(response) { + if (!response.error) { + this.derivez_available_accounts = response.trading_platform_accounts; + } + } + responseTradingPlatformAccountsList(response) { const { platform } = response.echo_req || {}; diff --git a/packages/core/src/Stores/traders-hub-store.js b/packages/core/src/Stores/traders-hub-store.js index c6066f132b10..906d1a1c390f 100644 --- a/packages/core/src/Stores/traders-hub-store.js +++ b/packages/core/src/Stores/traders-hub-store.js @@ -10,6 +10,7 @@ export default class TradersHubStore extends BaseStore { available_cfd_accounts = []; available_mt5_accounts = []; available_dxtrade_accounts = []; + available_derivez_accounts = []; combined_cfd_mt5_accounts = []; selected_account_type; selected_region; @@ -20,7 +21,6 @@ export default class TradersHubStore extends BaseStore { is_account_type_modal_visible = false; account_type_card = ''; selected_platform_type = 'options'; - active_index = 0; open_failed_verification_for = ''; modal_data = { active_modal: '', @@ -36,6 +36,7 @@ export default class TradersHubStore extends BaseStore { account_type_card: observable, available_cfd_accounts: observable, available_dxtrade_accounts: observable, + available_derivez_accounts: observable, available_mt5_accounts: observable, available_platforms: observable, combined_cfd_mt5_accounts: observable, @@ -57,6 +58,7 @@ export default class TradersHubStore extends BaseStore { getAccount: action.bound, getAvailableCFDAccounts: action.bound, getAvailableDxtradeAccounts: action.bound, + getAvailableDerivEzAccounts: action.bound, getExistingAccounts: action.bound, handleTabItemClick: action.bound, has_any_real_account: computed, @@ -101,6 +103,7 @@ export default class TradersHubStore extends BaseStore { this.root_store.client.is_switching, this.root_store.client.mt5_login_list, this.root_store.client.dxtrade_accounts_list, + this.root_store.client.derivez_accounts_list, this.is_demo_low_risk, this.root_store.modules?.cfd?.current_list, this.root_store.client.landing_companies, @@ -383,6 +386,7 @@ export default class TradersHubStore extends BaseStore { }; }); this.getAvailableDxtradeAccounts(); + this.getAvailableDerivEzAccounts(); this.getAvailableMt5Accounts(); this.setCombinedCFDMT5Accounts(); } @@ -448,6 +452,26 @@ export default class TradersHubStore extends BaseStore { account => account.platform === CFD_PLATFORMS.DXTRADE ); } + + getAvailableDerivEzAccounts() { + if (this.CFDs_restricted_countries || this.financial_restricted_countries) { + this.available_derivez_accounts = []; + return; + } + + if (this.is_eu_user && !this.is_demo_low_risk) { + this.available_derivez_accounts = this.available_cfd_accounts.filter( + account => + ['EU', 'All'].some(region => region === account.availability) && + account.platform === CFD_PLATFORMS.DERIVEZ + ); + return; + } + this.available_derivez_accounts = this.available_cfd_accounts.filter( + account => account.platform === CFD_PLATFORMS.DERIVEZ + ); + } + hasCFDAccount(platform, category, type) { const current_list_keys = Object.keys(this.root_store.modules.cfd.current_list); return current_list_keys.some(key => key.startsWith(`${platform}.${category}.${type}`)); @@ -471,6 +495,9 @@ export default class TradersHubStore extends BaseStore { if (platform === CFD_PLATFORMS.DXTRADE && market_type === 'all') { return key.startsWith(`${platform}.${selected_account_type}.${platform}@${market_type}`); } + if (platform === CFD_PLATFORMS.DERIVEZ && market_type === 'all') { + return key.startsWith(`${platform}.${selected_account_type}.${platform}@${market_type}`); + } if ( platform === CFD_PLATFORMS.MT5 && (this.is_eu_user || isEuCountry(residence)) && @@ -527,29 +554,33 @@ export default class TradersHubStore extends BaseStore { } } - openDemoCFDAccount(account_type, platform) { + async openDemoCFDAccount(account_type, platform) { const { client, modules, ui } = this.root_store; const { standpoint, createCFDAccount, enableCFDPasswordModal, has_maltainvest_account } = modules.cfd; const { openAccountNeededModal } = ui; const { is_eu } = client; + if (is_eu && !has_maltainvest_account && standpoint?.iom) { openAccountNeededModal('maltainvest', localize('Deriv Multipliers'), localize('demo CFDs')); - return; + } else if (platform !== CFD_PLATFORMS.DERIVEZ) { + enableCFDPasswordModal(); + } else { + await createCFDAccount({ ...account_type, platform }); } - createCFDAccount({ ...account_type, platform }); - enableCFDPasswordModal(); } - openRealAccount(account_type, platform) { + async openRealAccount(account_type, platform) { const { client, modules } = this.root_store; const { has_active_real_account } = client; const { createCFDAccount, enableCFDPasswordModal, toggleJurisdictionModal } = modules.cfd; + if (has_active_real_account && platform === CFD_PLATFORMS.MT5) { toggleJurisdictionModal(); - } else { - createCFDAccount({ ...account_type, platform }); + } else if (platform !== CFD_PLATFORMS.DERIVEZ) { enableCFDPasswordModal(); + } else { + await createCFDAccount({ ...account_type, platform }); } } diff --git a/packages/core/src/_common/base/socket_base.js b/packages/core/src/_common/base/socket_base.js index fa77222da03b..3ddae7da8e7d 100644 --- a/packages/core/src/_common/base/socket_base.js +++ b/packages/core/src/_common/base/socket_base.js @@ -8,6 +8,7 @@ const { getLanguage } = require('@deriv/translations'); const website_name = require('@deriv/shared').website_name; const SocketCache = require('./socket_cache'); const APIMiddleware = require('./api_middleware'); +const { CFD_PLATFORMS } = require('@deriv/shared'); /* * An abstraction layer over native javascript WebSocket, @@ -379,12 +380,16 @@ const BinarySocketBase = (() => { name: 'test real labuan financial stp', }); - const getServiceToken = (platform, server) => + const getServiceToken = (platform, server) => { + let temp_service = platform; + if (platform === CFD_PLATFORMS.DERIVEZ) temp_service = 'pandats'; + deriv_api.send({ service_token: 1, - service: platform, + service: temp_service, server, }); + }; const changeEmail = api_request => deriv_api.send(api_request); diff --git a/packages/hooks/src/useCFDAllAccounts.ts b/packages/hooks/src/useCFDAllAccounts.ts index 0366ae893763..0c14923eb571 100644 --- a/packages/hooks/src/useCFDAllAccounts.ts +++ b/packages/hooks/src/useCFDAllAccounts.ts @@ -7,7 +7,7 @@ import { useStore } from '@deriv/stores'; */ const useCFDAllAccounts = () => { const { client } = useStore(); - const { dxtrade_accounts_list, mt5_login_list } = client; + const { dxtrade_accounts_list, mt5_login_list, derivez_accounts_list } = client; let cfd_accounts: typeof mt5_login_list = []; if (Array.isArray(mt5_login_list)) { @@ -16,6 +16,9 @@ const useCFDAllAccounts = () => { if (Array.isArray(dxtrade_accounts_list)) { cfd_accounts = [...cfd_accounts, ...dxtrade_accounts_list]; } + if (Array.isArray(derivez_accounts_list)) { + cfd_accounts = [...cfd_accounts, ...derivez_accounts_list]; + } return cfd_accounts; }; diff --git a/packages/shared/src/utils/cfd/available-cfd-accounts.ts b/packages/shared/src/utils/cfd/available-cfd-accounts.ts index ed42b829faaa..ff635cf58cb9 100644 --- a/packages/shared/src/utils/cfd/available-cfd-accounts.ts +++ b/packages/shared/src/utils/cfd/available-cfd-accounts.ts @@ -30,4 +30,12 @@ export const getCFDAvailableAccount = () => [ icon: 'DerivX', availability: 'Non-EU', }, + { + name: 'Deriv EZ', + description: localize('Trade CFDs on an easy-to-get-started platform with all your favourite assets.'), + platform: CFD_PLATFORMS.DERIVEZ, + market_type: 'all', + icon: 'DerivEz', + availability: 'Non-EU', + }, ]; diff --git a/packages/shared/src/utils/cfd/cfd.ts b/packages/shared/src/utils/cfd/cfd.ts index f18ac1be205d..e1393316bec2 100644 --- a/packages/shared/src/utils/cfd/cfd.ts +++ b/packages/shared/src/utils/cfd/cfd.ts @@ -9,6 +9,7 @@ export const CFD_text: { [key: string]: string } = { mt5: 'MT5', mt5_cfds: 'MT5 CFDs', cfd: 'CFDs', + derivez: 'DerivEz', synthetic: 'Derived', synthetic_demo: 'Derived Demo', synthetic_bvi: 'Derived BVI', @@ -217,7 +218,9 @@ export const getAccountListKey = (account: TAccount, platform: TPlatform, shortc sub_account_type: account.sub_account_type, platform, shortcode, - })}@${platform === CFD_PLATFORMS.DXTRADE ? account.market_type : account.server}`; + })}@${ + platform === CFD_PLATFORMS.DXTRADE || platform === CFD_PLATFORMS.DERIVEZ ? account.market_type : account.server + }`; }; export const getCFDPlatformLabel = (platform: TPlatform) => { @@ -226,6 +229,8 @@ export const getCFDPlatformLabel = (platform: TPlatform) => { return 'Deriv MT5'; case CFD_PLATFORMS.DXTRADE: return 'Deriv X'; + case CFD_PLATFORMS.DERIVEZ: + return 'Deriv EZ'; default: return ''; } diff --git a/packages/shared/src/utils/config/platform-config.ts b/packages/shared/src/utils/config/platform-config.ts index f683ebda478e..1590d048fa42 100644 --- a/packages/shared/src/utils/config/platform-config.ts +++ b/packages/shared/src/utils/config/platform-config.ts @@ -26,7 +26,7 @@ export const platforms: TPlatforms = { derivgo: { icon_text: undefined, is_hard_redirect: true, - platform_name: 'Deriv Go', + platform_name: 'Deriv GO', route_to_path: '', url: 'https://app.deriv.com/redirect/derivgo', }, diff --git a/packages/stores/src/mockStore.ts b/packages/stores/src/mockStore.ts index 4183faa31f9a..ce2e1965a666 100644 --- a/packages/stores/src/mockStore.ts +++ b/packages/stores/src/mockStore.ts @@ -204,6 +204,7 @@ const mock = (): TStores & { is_mock: boolean } => { is_deposit_lock: false, is_dxtrade_allowed: false, is_eu: false, + is_eu_country: false, is_uk: false, has_residence: false, is_fully_authenticated: false, @@ -276,6 +277,7 @@ const mock = (): TStores & { is_mock: boolean } => { switchEndSignal: jest.fn(), is_crypto: jest.fn(), dxtrade_accounts_list: [], + derivez_accounts_list: [], default_currency: 'USD', resetVirtualBalance: jest.fn(), has_enabled_two_fa: false, @@ -361,6 +363,7 @@ const mock = (): TStores & { is_mock: boolean } => { closeModal: jest.fn(), combined_cfd_mt5_accounts: [], content_flag: '', + CFDs_restricted_countries: false, openModal: jest.fn(), selected_account: { login: '', @@ -369,6 +372,7 @@ const mock = (): TStores & { is_mock: boolean } => { is_eu_user: false, is_real: false, selectRegion: jest.fn(), + setSelectedAccount: jest.fn(), is_low_risk_cr_eu_real: false, toggleRegulatorsCompareModal: jest.fn(), selected_region: '', @@ -380,7 +384,6 @@ const mock = (): TStores & { is_mock: boolean } => { multipliers_account_status: '', openFailedVerificationModal: jest.fn(), setTogglePlatformType: jest.fn(), - setSelectedAccount: jest.fn(), toggleAccountTransferModal: jest.fn(), selectAccountType: jest.fn(), }, diff --git a/packages/stores/types.ts b/packages/stores/types.ts index b79e405754ac..b95da3267e84 100644 --- a/packages/stores/types.ts +++ b/packages/stores/types.ts @@ -191,6 +191,7 @@ type TClientStore = { is_deposit_lock: boolean; is_dxtrade_allowed: boolean; is_eu: boolean; + is_eu_country: boolean; is_uk: boolean; is_social_signup: boolean; has_residence: boolean; @@ -266,6 +267,7 @@ type TClientStore = { should_allow_authentication: boolean; is_crypto: (currency?: string) => boolean; dxtrade_accounts_list: DetailsOfEachMT5Loginid[]; + derivez_accounts_list: DetailsOfEachMT5Loginid[]; default_currency: string; resetVirtualBalance: () => Promise; has_enabled_two_fa: boolean; @@ -414,9 +416,10 @@ type TTradersHubStore = { multipliers_account_status: string; financial_restricted_countries: boolean; selected_account_type: string; + setSelectedAccount: (account: { login?: string; account_id?: string }) => void; no_CR_account: boolean; no_MF_account: boolean; - setSelectedAccount: (account: { login?: string; account_id?: string }) => void; + CFDs_restricted_countries: boolean; toggleAccountTransferModal: () => void; is_demo: boolean; selectAccountType: (account_type: string) => void;