From 09ea59e535e2afbb9e8d503f98512e42b7bb42a2 Mon Sep 17 00:00:00 2001 From: ahmadtaimoor-deriv <129935294+ahmadtaimoor-deriv@users.noreply.github.com> Date: Wed, 9 Oct 2024 14:19:01 +0800 Subject: [PATCH 01/10] fix: add condition --- .../shared/src/utils/contract/trade-url-params-config.ts | 5 ++++- packages/trader/src/Stores/Modules/Trading/trade-store.ts | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/shared/src/utils/contract/trade-url-params-config.ts b/packages/shared/src/utils/contract/trade-url-params-config.ts index d7cb1a7ced03..6d6a5ad2f7e6 100644 --- a/packages/shared/src/utils/contract/trade-url-params-config.ts +++ b/packages/shared/src/utils/contract/trade-url-params-config.ts @@ -68,7 +68,10 @@ export const getTradeURLParams = ({ active_symbols = [], contract_types_list = { contract_types_list[key]?.categories || []; return [...acc, ...categories.map(contract => (contract as TTextValueStrings).value)]; }, []); - const isTradeTypeValid = contractList.includes(trade_type ?? ''); + + const isTradeTypeValid = + (contractList.length === 0 && trade_type !== '') || + (contractList.length > 0 && contractList.includes(trade_type ?? '')); if (validInterval) result.granularity = Number(validInterval.value); if (validChartType) result.chartType = chartTypeParam; diff --git a/packages/trader/src/Stores/Modules/Trading/trade-store.ts b/packages/trader/src/Stores/Modules/Trading/trade-store.ts index 50b492321f4f..12d0fa23c3b6 100644 --- a/packages/trader/src/Stores/Modules/Trading/trade-store.ts +++ b/packages/trader/src/Stores/Modules/Trading/trade-store.ts @@ -1801,7 +1801,7 @@ export default class TradeStore extends BaseStore { } setChartModeFromURL() { - const { chartType: chartTypeParam, granularity: granularityParam } = getTradeURLParams(); + const { chartType: chartTypeParam, granularity: granularityParam, contractType } = getTradeURLParams(); const { chart_type, granularity, updateChartType, updateGranularity } = this.root_store.contract_trade; if (!isNaN(Number(granularityParam)) && granularityParam !== granularity) { updateGranularity(Number(granularityParam)); @@ -1809,9 +1809,13 @@ export default class TradeStore extends BaseStore { if (chartTypeParam && chartTypeParam !== chart_type) { updateChartType(chartTypeParam); } + + this.contract_type = contractType ?? ''; + setTradeURLParams({ chartType: chartTypeParam ?? chart_type, granularity: granularityParam ?? Number(granularity), + contractType: contractType ?? '', }); } From b99fed3539940b4b96145b5506116316aa219f5f Mon Sep 17 00:00:00 2001 From: Likhith Kolayari <98398322+likhith-deriv@users.noreply.github.com> Date: Thu, 17 Oct 2024 09:50:13 +0400 Subject: [PATCH 02/10] fix: eslint errors occured during merge (#17227) --- packages/account/build/constants.js | 1 - packages/account/build/webpack.config.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/account/build/constants.js b/packages/account/build/constants.js index c0a569d80482..13739e5c4c1e 100644 --- a/packages/account/build/constants.js +++ b/packages/account/build/constants.js @@ -30,7 +30,6 @@ const ALIASES = { Stores: path.resolve(__dirname, '../src/Stores'), Styles: path.resolve(__dirname, '../src/Styles'), Types: path.resolve(__dirname, '../src/Types'), - 'react/jsx-runtime': 'react/jsx-runtime.js', }; const rules = (is_test_env = false) => [ diff --git a/packages/account/build/webpack.config.js b/packages/account/build/webpack.config.js index 03e1de3f9d5f..3089aefb44f4 100644 --- a/packages/account/build/webpack.config.js +++ b/packages/account/build/webpack.config.js @@ -22,7 +22,7 @@ module.exports = function (env) { 'terms-of-use-config': 'Configs/terms-of-use-config', 'trading-assessment-config': 'Configs/trading-assessment-config', 'test-warning-modal': 'Components/trading-assessment/test-warning-modal', - 'employment-tax-info-config':'Configs/employment-tax-info-config', + 'employment-tax-info-config': 'Configs/employment-tax-info-config', }, mode: IS_RELEASE ? 'production' : 'development', module: { From 007374e87730a4b7ecab254e08c13602004e6b0c Mon Sep 17 00:00:00 2001 From: prince-deriv <82309725+prince-deriv@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:32:01 +0400 Subject: [PATCH 03/10] fix: destroy instead of minimize (#17229) --- .../core/src/App/Components/Elements/LiveChat/live-chat.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/App/Components/Elements/LiveChat/live-chat.tsx b/packages/core/src/App/Components/Elements/LiveChat/live-chat.tsx index 71ec82da410d..742f88d1639a 100644 --- a/packages/core/src/App/Components/Elements/LiveChat/live-chat.tsx +++ b/packages/core/src/App/Components/Elements/LiveChat/live-chat.tsx @@ -28,7 +28,7 @@ const LiveChat = observer(({ showPopover }: { showPopover?: boolean }) => { // We will add a refactor after this setInterval(() => { if (enable_freshworks_live_chat) { - window.LiveChatWidget?.call('minimize'); + window.LiveChatWidget?.call('destroy'); } }, 10); From ea4efbb17f6b169f853a796f28c077f01e47c139 Mon Sep 17 00:00:00 2001 From: nada-deriv <122768621+nada-deriv@users.noreply.github.com> Date: Thu, 17 Oct 2024 13:28:10 +0400 Subject: [PATCH 04/10] fix: redirection fro staging to p2p staging (#17231) --- packages/p2p/src/pages/app.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/p2p/src/pages/app.jsx b/packages/p2p/src/pages/app.jsx index bb67167937c4..a679f5cc6008 100644 --- a/packages/p2p/src/pages/app.jsx +++ b/packages/p2p/src/pages/app.jsx @@ -19,7 +19,7 @@ import Routes from 'Components/routes'; import './app.scss'; const App = () => { - const is_production = process.env.NODE_ENV === 'production'; + const is_production = window.location.origin === URLConstants.derivAppProduction; const [is_p2p_standalone_enabled, isGBLoaded] = useGrowthbookGetFeatureValue({ featureFlag: 'p2p_standalone_enabled', defaultValue: false, From 9ed88b1e74f396a278156a802643a45b2a6f47b1 Mon Sep 17 00:00:00 2001 From: Likhith Kolayari <98398322+likhith-deriv@users.noreply.github.com> Date: Thu, 17 Oct 2024 19:12:15 +0400 Subject: [PATCH 05/10] fix: idv update in real account creation (#17235) --- packages/account/src/Configs/kyc-validation-config.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/account/src/Configs/kyc-validation-config.ts b/packages/account/src/Configs/kyc-validation-config.ts index dd190a2b7b22..3175bf4e6468 100644 --- a/packages/account/src/Configs/kyc-validation-config.ts +++ b/packages/account/src/Configs/kyc-validation-config.ts @@ -29,7 +29,10 @@ export const getIDVFormValidationSchema = () => { .test({ name: 'testAdditionalDocumentNumber', test: (value, context) => { - if (context.parent.document_type.id === IDV_NOT_APPLICABLE_OPTION.id) { + if ( + context.parent.document_type.id === IDV_NOT_APPLICABLE_OPTION.id || + !context.parent.document_type?.additional + ) { return true; } return validateAdditionalDocumentNumber(value as string, context); From 819bf072f2dbc3a16fd265ca739dd6311e954e49 Mon Sep 17 00:00:00 2001 From: Likhith Kolayari <98398322+likhith-deriv@users.noreply.github.com> Date: Fri, 18 Oct 2024 10:43:49 +0400 Subject: [PATCH 06/10] fix: misaligned employment-status field (#17242) --- .../src/Components/forms/form-fields/employment-status.tsx | 2 +- packages/account/src/Styles/account.scss | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/account/src/Components/forms/form-fields/employment-status.tsx b/packages/account/src/Components/forms/form-fields/employment-status.tsx index 319089e852fb..bcec4f8cc013 100644 --- a/packages/account/src/Components/forms/form-fields/employment-status.tsx +++ b/packages/account/src/Components/forms/form-fields/employment-status.tsx @@ -19,7 +19,7 @@ const EmploymentStatusField = ({ required, is_disabled, fieldFocused }: TEmploym return ( {({ field, form: { setFieldValue, setFieldTouched, handleBlur, handleChange }, meta }: FieldProps) => ( -
+
{isDesktop ? ( Date: Sat, 19 Oct 2024 12:14:17 +0400 Subject: [PATCH 07/10] CSIT-1558/Prince/Livechat icon on testlinks (#17251) * fix: livechat icon on testlinks * fix: country data for growthbook --- .../Elements/LiveChat/live-chat.tsx | 7 ++++++- .../Components/Layout/Header/login-button.jsx | 2 +- packages/core/src/Utils/Analytics/index.ts | 20 +++++++++++++++++-- .../hooks/src/useGrowthbookGetFeatureValue.ts | 5 +++++ types/global.d.ts | 1 + 5 files changed, 31 insertions(+), 4 deletions(-) diff --git a/packages/core/src/App/Components/Elements/LiveChat/live-chat.tsx b/packages/core/src/App/Components/Elements/LiveChat/live-chat.tsx index 742f88d1639a..751c26d364b5 100644 --- a/packages/core/src/App/Components/Elements/LiveChat/live-chat.tsx +++ b/packages/core/src/App/Components/Elements/LiveChat/live-chat.tsx @@ -22,7 +22,12 @@ const LiveChat = observer(({ showPopover }: { showPopover?: boolean }) => { const chat = enable_freshworks_live_chat ? freshChat : null; - if ((enable_freshworks_live_chat && !chat?.isReady) || !is_livechat_available) return null; + const isFreshchatEnabledButNotReady = enable_freshworks_live_chat && !chat?.isReady; + const isNeitherChatNorLiveChatAvailable = !is_livechat_available && !enable_freshworks_live_chat; + + if (isFreshchatEnabledButNotReady || isNeitherChatNorLiveChatAvailable) { + return null; + } // Quick fix for making sure livechat won't popup if feature flag is late to enable. // We will add a refactor after this diff --git a/packages/core/src/App/Components/Layout/Header/login-button.jsx b/packages/core/src/App/Components/Layout/Header/login-button.jsx index aafb78497d9a..d3af832d6893 100644 --- a/packages/core/src/App/Components/Layout/Header/login-button.jsx +++ b/packages/core/src/App/Components/Layout/Header/login-button.jsx @@ -11,7 +11,7 @@ const LoginButton = ({ className }) => ( has_effect text={localize('Log in')} onClick={() => { - window.LiveChatWidget.call('hide'); + window.LiveChatWidget?.call('hide'); redirectToLogin(false, getLanguage()); }} tertiary diff --git a/packages/core/src/Utils/Analytics/index.ts b/packages/core/src/Utils/Analytics/index.ts index 9ccd4516e696..d50d46786673 100644 --- a/packages/core/src/Utils/Analytics/index.ts +++ b/packages/core/src/Utils/Analytics/index.ts @@ -23,6 +23,23 @@ export const AnalyticsInitializer = async () => { utm_content: 'no content', } : Cookies.getJSON('utm_data'); + + /* + Temp solution to fetch country and handle experiments without causing inconsistencies to the users. + */ + + const getCountry = async () => { + try { + const response = await fetch('https://www.cloudflare.com/cdn-cgi/trace').catch(() => null); + const text = response ? await response.text().catch(() => '') : ''; + const entries = text ? text.split('\n').map(v => v.split('=', 2)) : []; + const data = entries.length ? Object.fromEntries(entries) : {}; + return data?.loc?.toLowerCase() ?? ''; + } catch { + return ''; + } + }; + const config = { growthbookKey: flags.marketing_growthbook ? process.env.GROWTHBOOK_CLIENT_KEY : undefined, growthbookDecryptionKey: flags.marketing_growthbook ? process.env.GROWTHBOOK_DECRYPTION_KEY : undefined, @@ -34,8 +51,7 @@ export const AnalyticsInitializer = async () => { device_type: window.innerWidth <= MAX_MOBILE_WIDTH ? 'mobile' : 'desktop', device_language: navigator?.language || 'en-EN', user_language: getLanguage().toLowerCase(), - country: - Cookies.getJSON('clients_country') || Cookies?.getJSON('website_status')?.clients_country, + country: await getCountry(), utm_source: ppc_campaign_cookies?.utm_source, utm_medium: ppc_campaign_cookies?.utm_medium, utm_campaign: ppc_campaign_cookies?.utm_campaign, diff --git a/packages/hooks/src/useGrowthbookGetFeatureValue.ts b/packages/hooks/src/useGrowthbookGetFeatureValue.ts index 13ee9958adca..433b58c87949 100644 --- a/packages/hooks/src/useGrowthbookGetFeatureValue.ts +++ b/packages/hooks/src/useGrowthbookGetFeatureValue.ts @@ -19,6 +19,11 @@ const useGrowthbookGetFeatureValue = ({ const isGBLoaded = useIsGrowthbookIsLoaded(); const isMounted = useIsMounted(); + // Required for debugging Growthbook, this will be removed after Freshchat launch + if (typeof window !== 'undefined') { + window.Analytics = Analytics; + } + useEffect(() => { if (isGBLoaded) { if (Analytics?.getInstances()?.ab) { diff --git a/types/global.d.ts b/types/global.d.ts index efe426c37130..7c91a75e41ff 100644 --- a/types/global.d.ts +++ b/types/global.d.ts @@ -34,6 +34,7 @@ declare global { FreshChat: { initialize: (config: FreshChatConfig) => void; }; + Analytics: any; } interface FreshChatConfig { token: string | null; From ec7280480a96350d1366f37dd94f3a94145d42f8 Mon Sep 17 00:00:00 2001 From: prince-deriv <82309725+prince-deriv@users.noreply.github.com> Date: Mon, 21 Oct 2024 10:40:48 +0400 Subject: [PATCH 08/10] CSIT-1559/Prince/add livechat widget call check (#17257) * fix: add livechat widget call check * fix: whatsapp issue on freshchats * chore: pass country to growthbook on login using cloudflare check * fix: import issue * chore: added test case for getCountry * fix: test error --- .../Components/poi/status/limited/limited.tsx | 2 +- .../account/src/Configs/poi-error-config.tsx | 2 +- .../wallets-migration-failed.tsx | 2 +- .../cashier-locked-provider.tsx | 16 ++++---- .../side-note-faq/side-note-faq.tsx | 2 +- .../cashier-onboarding-side-note-fiat.tsx | 2 +- .../src/modules/deposit-fiat/deposit-fiat.tsx | 2 +- .../open-livechat-link/open-livechat-link.tsx | 2 +- .../Components/Elements/WhatsApp/whatsapp.tsx | 8 +++- .../one-time-deposit-modal-content.tsx | 2 +- .../change-account-currency.jsx | 2 +- .../signup-error-content.jsx | 7 +++- .../src/App/Containers/Redirect/redirect.jsx | 2 +- packages/core/src/Stores/client-store.js | 5 ++- .../core/src/Stores/notification-store.js | 14 +++---- packages/core/src/Utils/Analytics/index.ts | 17 +-------- .../hooks/src/useIsLiveChatWidgetAvailable.ts | 2 +- packages/hooks/src/useLiveChat.ts | 2 +- .../dp2p-blocked/dp2p-blocked-description.tsx | 2 +- .../ad-visibility-error-modal.tsx | 2 +- .../constants/phone-number-verification.tsx | 2 +- .../utils/src/__tests__/getCountry.spec.ts | 37 +++++++++++++++++++ packages/utils/src/getCountry.ts | 17 +++++++++ packages/utils/src/index.ts | 1 + .../NeedHelpMessage/NeedHelpMessage.tsx | 2 +- .../DepositLocked/DepositLockedContent.tsx | 4 +- .../WithdrawalLockedContent.tsx | 2 +- 27 files changed, 104 insertions(+), 56 deletions(-) create mode 100644 packages/utils/src/__tests__/getCountry.spec.ts create mode 100644 packages/utils/src/getCountry.ts diff --git a/packages/account/src/Components/poi/status/limited/limited.tsx b/packages/account/src/Components/poi/status/limited/limited.tsx index 2ecc3383d653..8a00dbaa05ba 100644 --- a/packages/account/src/Components/poi/status/limited/limited.tsx +++ b/packages/account/src/Components/poi/status/limited/limited.tsx @@ -13,7 +13,7 @@ export const POILimited = () => ( window.LiveChatWidget.call('maximize')} + onClick={() => window.LiveChatWidget?.call('maximize')} />, ]} /> diff --git a/packages/account/src/Configs/poi-error-config.tsx b/packages/account/src/Configs/poi-error-config.tsx index 7857c92c1c6f..5de8fdf86989 100644 --- a/packages/account/src/Configs/poi-error-config.tsx +++ b/packages/account/src/Configs/poi-error-config.tsx @@ -5,7 +5,7 @@ import { Localize } from '@deriv/translations'; import { DerivLightNameDobPoiIcon, DerivLightDobPoiIcon, DerivLightNamePoiIcon } from '@deriv/quill-icons'; import { getIDVDocumentType } from '../Helpers/utils'; -const handleOnClick = () => window.LiveChatWidget.call('maximize'); +const handleOnClick = () => window.LiveChatWidget?.call('maximize'); export const GENERIC_ERROR_MESSAGE = ( diff --git a/packages/appstore/src/components/modals/wallets-migration-failed/wallets-migration-failed.tsx b/packages/appstore/src/components/modals/wallets-migration-failed/wallets-migration-failed.tsx index 264c6166284a..3128265a566a 100644 --- a/packages/appstore/src/components/modals/wallets-migration-failed/wallets-migration-failed.tsx +++ b/packages/appstore/src/components/modals/wallets-migration-failed/wallets-migration-failed.tsx @@ -16,7 +16,7 @@ const WalletsMigrationFailed = observer(() => { }; const handleLivechatButtonClick = () => { - window.LiveChatWidget.call('maximize'); + window.LiveChatWidget?.call('maximize'); setWalletsMigrationFailedPopup(false); }; diff --git a/packages/cashier/src/components/cashier-locked/cashier-locked-provider.tsx b/packages/cashier/src/components/cashier-locked/cashier-locked-provider.tsx index 53afe1f1405b..e0824673dc59 100644 --- a/packages/cashier/src/components/cashier-locked/cashier-locked-provider.tsx +++ b/packages/cashier/src/components/cashier-locked/cashier-locked-provider.tsx @@ -130,7 +130,7 @@ const getMessage = ({ window.LiveChatWidget.call('maximize')} + onClick={() => window.LiveChatWidget?.call('maximize')} />, ]} /> @@ -147,7 +147,7 @@ const getMessage = ({ window.LiveChatWidget.call('maximize')} + onClick={() => window.LiveChatWidget?.call('maximize')} />, ]} /> @@ -378,7 +378,7 @@ const getMessage = ({ window.LiveChatWidget.call('maximize')} + onClick={() => window.LiveChatWidget?.call('maximize')} />, ]} /> @@ -395,7 +395,7 @@ const getMessage = ({ window.LiveChatWidget.call('maximize')} + onClick={() => window.LiveChatWidget?.call('maximize')} />, ]} /> @@ -471,7 +471,7 @@ const getMessage = ({ window.LiveChatWidget.call('maximize')} + onClick={() => window.LiveChatWidget?.call('maximize')} />, ]} /> @@ -488,7 +488,7 @@ const getMessage = ({ window.LiveChatWidget.call('maximize')} + onClick={() => window.LiveChatWidget?.call('maximize')} />, ]} /> @@ -505,7 +505,7 @@ const getMessage = ({ window.LiveChatWidget.call('maximize')} + onClick={() => window.LiveChatWidget?.call('maximize')} />, ]} /> @@ -531,7 +531,7 @@ const getMessage = ({ window.LiveChatWidget.call('maximize')} + onClick={() => window.LiveChatWidget?.call('maximize')} />, ]} /> diff --git a/packages/cashier/src/components/side-notes/side-note-faq/side-note-faq.tsx b/packages/cashier/src/components/side-notes/side-note-faq/side-note-faq.tsx index 78fe6aeb4055..7d46da17c886 100644 --- a/packages/cashier/src/components/side-notes/side-note-faq/side-note-faq.tsx +++ b/packages/cashier/src/components/side-notes/side-note-faq/side-note-faq.tsx @@ -14,7 +14,7 @@ const SideNoteFAQ = ({ transaction_type }: TSideNoteFAQProps) => { const { isMobile } = useDevice(); const { is_eu } = client; - const onClickHandler = () => window.LiveChatWidget.call('maximize'); + const onClickHandler = () => window.LiveChatWidget?.call('maximize'); const deposit_faq_list = useMemo(() => { return [ diff --git a/packages/cashier/src/modules/cashier-onboarding/components/cashier-onboarding-side-notes/cashier-onboarding-side-note-fiat.tsx b/packages/cashier/src/modules/cashier-onboarding/components/cashier-onboarding-side-notes/cashier-onboarding-side-note-fiat.tsx index 86cfe0348dd1..03380c78ad82 100644 --- a/packages/cashier/src/modules/cashier-onboarding/components/cashier-onboarding-side-notes/cashier-onboarding-side-note-fiat.tsx +++ b/packages/cashier/src/modules/cashier-onboarding/components/cashier-onboarding-side-notes/cashier-onboarding-side-note-fiat.tsx @@ -19,7 +19,7 @@ const CashierOnboardingSideNoteFiat: React.FC = observer(() => { window.LiveChatWidget.call('maximize')} + onClick={() => window.LiveChatWidget?.call('maximize')} /> ), ]} diff --git a/packages/cashier/src/modules/deposit-fiat/deposit-fiat.tsx b/packages/cashier/src/modules/deposit-fiat/deposit-fiat.tsx index b1027bfdbdfb..f048c884f02e 100644 --- a/packages/cashier/src/modules/deposit-fiat/deposit-fiat.tsx +++ b/packages/cashier/src/modules/deposit-fiat/deposit-fiat.tsx @@ -11,7 +11,7 @@ const DepositFiat: React.FC = observer(() => { const { common, traders_hub } = useStore(); const { is_from_derivgo } = common; const { is_low_risk_cr_eu_real } = traders_hub; - const onClickHandler = () => window.LiveChatWidget.call('maximize'); + const onClickHandler = () => window.LiveChatWidget?.call('maximize'); return ( window.LiveChatWidget.call('maximize')} + onClick={() => window.LiveChatWidget?.call('maximize')} > {children || } diff --git a/packages/core/src/App/Components/Elements/WhatsApp/whatsapp.tsx b/packages/core/src/App/Components/Elements/WhatsApp/whatsapp.tsx index 729aa86764f9..da3babc848ce 100644 --- a/packages/core/src/App/Components/Elements/WhatsApp/whatsapp.tsx +++ b/packages/core/src/App/Components/Elements/WhatsApp/whatsapp.tsx @@ -3,14 +3,18 @@ import { Popover, Icon } from '@deriv/components'; import { localize } from '@deriv/translations'; import { useDevice } from '@deriv-com/ui'; import { URLConstants } from '@deriv-com/utils'; -import { useIsLiveChatWidgetAvailable } from '@deriv/hooks'; +import { useGrowthbookGetFeatureValue, useIsLiveChatWidgetAvailable } from '@deriv/hooks'; const WhatsApp = ({ showPopover, onClick }: { showPopover?: boolean; onClick?: () => void }) => { const { isDesktop } = useDevice(); const { is_livechat_available } = useIsLiveChatWidgetAvailable(); - if (!is_livechat_available) return null; + const [enable_freshworks_live_chat] = useGrowthbookGetFeatureValue({ + featureFlag: 'enable_freshworks_live_chat', + }); + + if (!is_livechat_available && !enable_freshworks_live_chat) return null; if (!isDesktop) return ( diff --git a/packages/core/src/App/Containers/OneTimeDepositModal/one-time-deposit-modal-content.tsx b/packages/core/src/App/Containers/OneTimeDepositModal/one-time-deposit-modal-content.tsx index 99e7cd03fb2d..3929b63759e2 100644 --- a/packages/core/src/App/Containers/OneTimeDepositModal/one-time-deposit-modal-content.tsx +++ b/packages/core/src/App/Containers/OneTimeDepositModal/one-time-deposit-modal-content.tsx @@ -9,7 +9,7 @@ import DepositCrypto from '@deriv/cashier/src/modules/deposit-crypto/components/ export const OneTimeDepositModalContent = ({ is_crypto_provider = false }: { is_crypto_provider?: boolean }) => { const { isDesktop } = useDevice(); - const onLiveChatClick = () => window.LiveChatWidget.call('maximize'); + const onLiveChatClick = () => window.LiveChatWidget?.call('maximize'); return (
{ closeRealAccountSignup(); - window.LiveChatWidget.call('maximize'); + window.LiveChatWidget?.call('maximize'); }} />, ]} diff --git a/packages/core/src/App/Containers/RealAccountSignup/signup-error-content.jsx b/packages/core/src/App/Containers/RealAccountSignup/signup-error-content.jsx index 346dd109bb90..136e83ded9b9 100644 --- a/packages/core/src/App/Containers/RealAccountSignup/signup-error-content.jsx +++ b/packages/core/src/App/Containers/RealAccountSignup/signup-error-content.jsx @@ -53,7 +53,7 @@ const Message = ({ code, message, details }) => { window.LiveChatWidget.call('maximize')} + onClick={() => window.LiveChatWidget?.call('maximize')} />, ]} /> @@ -105,7 +105,10 @@ const ErrorCTA = ({ code, onConfirm }) => { return ; case 'DuplicateAccount': return ( - window.LiveChatWidget.call('maximize')} /> + window.LiveChatWidget?.call('maximize')} + /> ); case 'InputValidationFailed': case 'PoBoxInAddress': diff --git a/packages/core/src/App/Containers/Redirect/redirect.jsx b/packages/core/src/App/Containers/Redirect/redirect.jsx index f31909f72637..242e76f48c9d 100644 --- a/packages/core/src/App/Containers/Redirect/redirect.jsx +++ b/packages/core/src/App/Containers/Redirect/redirect.jsx @@ -45,7 +45,7 @@ const Redirect = observer(() => { } const openLivechat = () => { - window.LiveChatWidget.call('maximize'); + window.LiveChatWidget?.call('maximize'); }; const url_query_string = window.location.search; diff --git a/packages/core/src/Stores/client-store.js b/packages/core/src/Stores/client-store.js index 00be86ca2101..32a55fe70c49 100644 --- a/packages/core/src/Stores/client-store.js +++ b/packages/core/src/Stores/client-store.js @@ -33,6 +33,7 @@ import { } from '@deriv/shared'; import { Analytics } from '@deriv-com/analytics'; import { URLConstants } from '@deriv-com/utils'; +import { getCountry } from '@deriv/utils'; import { getLanguage, localize, getRedirectionLanguage } from '@deriv/translations'; @@ -1789,7 +1790,7 @@ export default class ClientStore extends BaseStore { const broker = LocalStore?.get('active_loginid') ?.match(/[a-zA-Z]+/g) ?.join(''); - setTimeout(() => { + setTimeout(async () => { const analytics_config = { account_type: broker === 'null' ? 'unlogged' : broker, residence_country: this.residence, @@ -1798,7 +1799,7 @@ export default class ClientStore extends BaseStore { language: getLanguage(), device_language: navigator?.language || 'en-EN', user_language: getLanguage().toLowerCase(), - country: Cookies.get('clients_country') || Cookies?.getJSON('website_status')?.clients_country, + country: await getCountry(), utm_source: ppc_campaign_cookies?.utm_source, utm_medium: ppc_campaign_cookies?.utm_medium, utm_campaign: ppc_campaign_cookies?.utm_campaign, diff --git a/packages/core/src/Stores/notification-store.js b/packages/core/src/Stores/notification-store.js index f868e19756ab..57e6793e6510 100644 --- a/packages/core/src/Stores/notification-store.js +++ b/packages/core/src/Stores/notification-store.js @@ -823,7 +823,7 @@ export default class NotificationStore extends BaseStore { message: localize('Please contact us via live chat to unlock it.'), action: { onClick: () => { - window.LiveChatWidget.call('maximize'); + window.LiveChatWidget?.call('maximize'); }, text: localize('Go to live chat'), }, @@ -1077,7 +1077,7 @@ export default class NotificationStore extends BaseStore { message: localize('Please contact us via live chat to enable withdrawals.'), action: { onClick: () => { - window.LiveChatWidget.call('maximize'); + window.LiveChatWidget?.call('maximize'); }, text: localize('Go to live chat'), }, @@ -1273,7 +1273,7 @@ export default class NotificationStore extends BaseStore { ), action: { onClick: () => { - window.LiveChatWidget.call('maximize'); + window.LiveChatWidget?.call('maximize'); }, text: localize('Go to live chat'), }, @@ -1386,7 +1386,7 @@ export default class NotificationStore extends BaseStore { message: localize('Please contact us via live chat.'), action: { onClick: () => { - window.LiveChatWidget.call('maximize'); + window.LiveChatWidget?.call('maximize'); }, text: localize('Go to live chat'), }, @@ -1398,7 +1398,7 @@ export default class NotificationStore extends BaseStore { message: localize('Please contact us via live chat to enable withdrawals.'), action: { onClick: () => { - window.LiveChatWidget.call('maximize'); + window.LiveChatWidget?.call('maximize'); }, text: localize('Go to live chat'), }, @@ -1573,7 +1573,7 @@ export default class NotificationStore extends BaseStore { ), action: { onClick: async () => { - window.LiveChatWidget.call('maximize'); + window.LiveChatWidget?.call('maximize'); }, text: localize('Go to LiveChat'), }, @@ -1741,7 +1741,7 @@ export default class NotificationStore extends BaseStore { : { text: localize('Contact live chat'), onClick: () => { - window.LiveChatWidget.call('maximize'); + window.LiveChatWidget?.call('maximize'); }, }; diff --git a/packages/core/src/Utils/Analytics/index.ts b/packages/core/src/Utils/Analytics/index.ts index d50d46786673..2990ac9b1772 100644 --- a/packages/core/src/Utils/Analytics/index.ts +++ b/packages/core/src/Utils/Analytics/index.ts @@ -4,6 +4,7 @@ import { getLanguage } from '@deriv/translations'; import { LocalStore, getAppId } from '@deriv/shared'; import { MAX_MOBILE_WIDTH } from '../../Constants'; import FIREBASE_INIT_DATA from '../../../../api/src/remote_config.json'; +import { getCountry } from '@deriv/utils'; export const AnalyticsInitializer = async () => { const account_type = LocalStore?.get('active_loginid') @@ -24,22 +25,6 @@ export const AnalyticsInitializer = async () => { } : Cookies.getJSON('utm_data'); - /* - Temp solution to fetch country and handle experiments without causing inconsistencies to the users. - */ - - const getCountry = async () => { - try { - const response = await fetch('https://www.cloudflare.com/cdn-cgi/trace').catch(() => null); - const text = response ? await response.text().catch(() => '') : ''; - const entries = text ? text.split('\n').map(v => v.split('=', 2)) : []; - const data = entries.length ? Object.fromEntries(entries) : {}; - return data?.loc?.toLowerCase() ?? ''; - } catch { - return ''; - } - }; - const config = { growthbookKey: flags.marketing_growthbook ? process.env.GROWTHBOOK_CLIENT_KEY : undefined, growthbookDecryptionKey: flags.marketing_growthbook ? process.env.GROWTHBOOK_DECRYPTION_KEY : undefined, diff --git a/packages/hooks/src/useIsLiveChatWidgetAvailable.ts b/packages/hooks/src/useIsLiveChatWidgetAvailable.ts index a8a4bf7031d4..0c2255969546 100644 --- a/packages/hooks/src/useIsLiveChatWidgetAvailable.ts +++ b/packages/hooks/src/useIsLiveChatWidgetAvailable.ts @@ -4,7 +4,7 @@ const useIsLiveChatWidgetAvailable = () => { const [is_livechat_available, setIsLivechatAvailable] = useState(false); useEffect(() => { - window.LiveChatWidget.on('ready', data => { + window.LiveChatWidget?.on('ready', data => { if (data.state.availability === 'online') setIsLivechatAvailable(true); }); }, []); diff --git a/packages/hooks/src/useLiveChat.ts b/packages/hooks/src/useLiveChat.ts index 44310642c145..3d63130d6944 100644 --- a/packages/hooks/src/useLiveChat.ts +++ b/packages/hooks/src/useLiveChat.ts @@ -38,7 +38,7 @@ const useLiveChat = (client_information: TLiveChatClientInformation) => { useEffect(() => { if (is_client_store_initialized && cs_chat_livechat) { - window.LiveChatWidget.init(); + window.LiveChatWidget?.init(); } }, [is_client_store_initialized, cs_chat_livechat]); diff --git a/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-description.tsx b/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-description.tsx index ad8ad941cea5..2bc7728f2b51 100644 --- a/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-description.tsx +++ b/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-description.tsx @@ -34,7 +34,7 @@ const Dp2pBlockedDescription = () => { window.LiveChatWidget.call('maximize')} + onClick={() => window.LiveChatWidget?.call('maximize')} />, ]} /> diff --git a/packages/p2p/src/components/modal-manager/modals/ad-visibility-error-modal/ad-visibility-error-modal.tsx b/packages/p2p/src/components/modal-manager/modals/ad-visibility-error-modal/ad-visibility-error-modal.tsx index f82692d2ffd1..0153fa909c37 100644 --- a/packages/p2p/src/components/modal-manager/modals/ad-visibility-error-modal/ad-visibility-error-modal.tsx +++ b/packages/p2p/src/components/modal-manager/modals/ad-visibility-error-modal/ad-visibility-error-modal.tsx @@ -49,7 +49,7 @@ const AdVisibilityErrorModal = ({ error_code }: TAdVisibilityErrorModalProps) => window.LiveChatWidget.call('maximize')} + onClick={() => window.LiveChatWidget?.call('maximize')} />, ]} /> diff --git a/packages/shared/src/utils/constants/phone-number-verification.tsx b/packages/shared/src/utils/constants/phone-number-verification.tsx index c1e3086c21cd..c8d3d27a5a13 100644 --- a/packages/shared/src/utils/constants/phone-number-verification.tsx +++ b/packages/shared/src/utils/constants/phone-number-verification.tsx @@ -34,7 +34,7 @@ export const getUseRequestPhoneNumberOTPErrorMessage = ( window.LiveChatWidget.call('maximize')} + onClick={() => window.LiveChatWidget?.call('maximize')} />, ]} /> diff --git a/packages/utils/src/__tests__/getCountry.spec.ts b/packages/utils/src/__tests__/getCountry.spec.ts new file mode 100644 index 000000000000..4107d895c9db --- /dev/null +++ b/packages/utils/src/__tests__/getCountry.spec.ts @@ -0,0 +1,37 @@ +import getCountry from '../getCountry'; + +describe('getCountry', () => { + beforeEach(() => { + global.fetch = jest.fn() as jest.Mock; + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + it('should return the country code in lowercase when available', async () => { + // Mock fetch response + (global.fetch as jest.Mock).mockResolvedValue({ + text: async () => 'loc=US\nother=info\n', + }); + + const country = await getCountry(); + expect(country).toBe('us'); + }); + + it('should return an empty string if the loc field is not present', async () => { + (global.fetch as jest.Mock).mockResolvedValue({ + text: async () => 'other=info\n', + }); + + const country = await getCountry(); + expect(country).toBe(''); + }); + + it('should return an empty string if the fetch fails', async () => { + (global.fetch as jest.Mock).mockRejectedValue(new Error('Fetch failed')); + + const country = await getCountry(); + expect(country).toBe(''); + }); +}); diff --git a/packages/utils/src/getCountry.ts b/packages/utils/src/getCountry.ts new file mode 100644 index 000000000000..87af822bf755 --- /dev/null +++ b/packages/utils/src/getCountry.ts @@ -0,0 +1,17 @@ +/* +Temp solution for growthbook to fetch country and handle experiments/fratures without causing inconsistencies to the UI. +*/ + +const getCountry = async () => { + try { + const response = await fetch('https://www.cloudflare.com/cdn-cgi/trace').catch(() => null); + const text = response ? await response.text().catch(() => '') : ''; + const entries = text ? text.split('\n').map(v => v.split('=', 2)) : []; + const data = entries.length ? Object.fromEntries(entries) : {}; + return data?.loc?.toLowerCase() ?? ''; + } catch { + return ''; + } +}; + +export default getCountry; diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 1993d63747d8..4fb0407b2467 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -9,6 +9,7 @@ export { default as groupTransactionsByDay } from './groupTransactionsByDay'; export { default as getTruncatedString } from './getTruncatedString'; export { default as unFormatLocaleString } from './unFormatLocaleString'; export { default as getLoginHistoryFormattedData } from './getLoginHistoryFormattedData'; +export { default as getCountry } from './getCountry'; export * from './parse-url'; export * from './moment'; export * from './files'; diff --git a/packages/wallets/src/features/accounts/modules/TaxInformation/components/NeedHelpMessage/NeedHelpMessage.tsx b/packages/wallets/src/features/accounts/modules/TaxInformation/components/NeedHelpMessage/NeedHelpMessage.tsx index adca42a7272a..0ae52dd3eb2f 100644 --- a/packages/wallets/src/features/accounts/modules/TaxInformation/components/NeedHelpMessage/NeedHelpMessage.tsx +++ b/packages/wallets/src/features/accounts/modules/TaxInformation/components/NeedHelpMessage/NeedHelpMessage.tsx @@ -3,7 +3,7 @@ import { Localize } from '@deriv-com/translations'; import { InlineMessage, Text } from '@deriv-com/ui'; const NeedHelpMessage = () => { - const onClickLiveChat = () => window.LiveChatWidget.call('maximize'); + const onClickLiveChat = () => window.LiveChatWidget?.call('maximize'); return (
diff --git a/packages/wallets/src/features/cashier/modules/DepositLocked/DepositLockedContent.tsx b/packages/wallets/src/features/cashier/modules/DepositLocked/DepositLockedContent.tsx index 863cd6ced9e5..5090c93a2378 100644 --- a/packages/wallets/src/features/cashier/modules/DepositLocked/DepositLockedContent.tsx +++ b/packages/wallets/src/features/cashier/modules/DepositLocked/DepositLockedContent.tsx @@ -87,7 +87,7 @@ const getDepositLockedDesc = ({