diff --git a/packages/core/src/Stores/contract-trade-store.js b/packages/core/src/Stores/contract-trade-store.js index 3484eac77ba9..ec6e8ec2f8ef 100644 --- a/packages/core/src/Stores/contract-trade-store.js +++ b/packages/core/src/Stores/contract-trade-store.js @@ -8,12 +8,10 @@ import { isAccumulatorContractOpen, isCallPut, isDesktop, - isDigitContract, isEnded, isHighLow, isMultiplierContract, isTurbosContract, - isUpDownContract, isVanillaContract, LocalStore, setTradeURLParams, @@ -33,10 +31,10 @@ export default class ContractTradeStore extends BaseStore { error_message = ''; // Chart specific observables - saved_granularity = +LocalStore.get('contract_trade.granularity'); - saved_chart_type = LocalStore.get('contract_trade.chart_style'); - chart_type = ''; - granularity = null; + granularity = +LocalStore.get('contract_trade.granularity') || 0; + chart_type = LocalStore.get('contract_trade.chart_style') || 'line'; + prev_chart_type = ''; + prev_granularity = null; // Accumulator barriers data: accu_barriers_timeout_id = null; @@ -47,36 +45,34 @@ export default class ContractTradeStore extends BaseStore { super({ root_store }); makeObservable(this, { - accountSwitchListener: action.bound, accu_barriers_timeout_id: observable, accumulator_barriers_data: observable.struct, accumulator_contract_barriers_data: observable.struct, - addContract: action.bound, - chart_type: observable, clearAccumulatorBarriersData: action.bound, - clearError: action.bound, contracts: observable.shallow, - error_message: observable, - filtered_contracts: computed, - getContractById: action.bound, - granularity: observable, has_crossed_accu_barriers: computed, has_error: observable, - last_contract: computed, - markers_array: computed, - onUnmount: override, - prev_contract: computed, - removeContract: action.bound, - saveChartType: action.bound, - saved_chart_type: observable, - saved_granularity: observable, - saveGranularity: action.bound, - setChartTypeAndGranularity: action.bound, - setNewAccumulatorBarriersData: action.bound, + error_message: observable, + granularity: observable, + chart_type: observable, updateAccumulatorBarriersData: action.bound, updateChartType: action.bound, updateGranularity: action.bound, + markers_array: computed, + filtered_contracts: computed, + addContract: action.bound, + removeContract: action.bound, + accountSwitchListener: action.bound, + onUnmount: override, + prev_chart_type: observable, + prev_granularity: observable, updateProposal: action.bound, + last_contract: computed, + clearError: action.bound, + getContractById: action.bound, + prev_contract: computed, + savePreviousChartMode: action.bound, + setNewAccumulatorBarriersData: action.bound, }); this.root_store = root_store; @@ -137,22 +133,6 @@ export default class ContractTradeStore extends BaseStore { } } - setChartTypeAndGranularity(type, granularity) { - this.chart_type = type; - this.granularity = granularity; - if (this.granularity === 0) { - this.root_store.notifications.removeNotificationMessage(switch_to_tick_chart); - } - } - - saveChartType(chart_type) { - this.saved_chart_type = chart_type; - } - - saveGranularity(granularity) { - this.saved_granularity = granularity; - } - updateAccumulatorBarriersData({ accumulators_high_barrier, accumulators_low_barrier, @@ -222,19 +202,12 @@ export default class ContractTradeStore extends BaseStore { } updateChartType(type) { - const { contract_type } = JSON.parse(sessionStorage.getItem('trade_store')) || {}; - const is_ticks_contract = - isDigitContract(contract_type) || isAccumulatorContract(contract_type) || isUpDownContract(contract_type); LocalStore.set('contract_trade.chart_style', type); this.chart_type = type; setTradeURLParams({ chartType: this.chart_type }); - !is_ticks_contract && this.saveChartType(this.chart_type); } updateGranularity(granularity) { - const { contract_type } = JSON.parse(sessionStorage.getItem('trade_store')) || {}; - const is_ticks_contract = - isDigitContract(contract_type) || isAccumulatorContract(contract_type) || isUpDownContract(contract_type); const tick_chart_types = ['line', 'candles', 'hollow', 'ohlc']; if (granularity === 0 && tick_chart_types.indexOf(this.chart_type) === -1) { @@ -247,7 +220,11 @@ export default class ContractTradeStore extends BaseStore { this.root_store.notifications.removeNotificationMessage(switch_to_tick_chart); } setTradeURLParams({ granularity: this.granularity }); - !is_ticks_contract && this.saveGranularity(this.granularity); + } + + savePreviousChartMode(chart_type, granularity) { + this.prev_chart_type = chart_type; + this.prev_granularity = granularity; } applicable_contracts = () => { diff --git a/packages/shared/src/utils/contract/__tests__/trade-url-params-config.spec.ts b/packages/shared/src/utils/contract/__tests__/trade-url-params-config.spec.ts index 65f3472cd93e..2496d9ea8e42 100644 --- a/packages/shared/src/utils/contract/__tests__/trade-url-params-config.spec.ts +++ b/packages/shared/src/utils/contract/__tests__/trade-url-params-config.spec.ts @@ -4,9 +4,7 @@ import { TRADE_TYPES } from '../contract'; import { routes } from '../../routes'; const areaChartType = { text: 'area', value: 'line' }; -const candleChartType = { text: 'candle', value: 'candles' }; const oneTickInterval = '1t'; -const oneMinuteInterval = '1m'; const symbol = 'R_100'; describe('getTradeURLParams', () => { @@ -58,10 +56,10 @@ describe('getTradeURLParams', () => { }); it('should return an object with chartType & interval based on the URL query params when called without arguments', () => { - location.search = `?symbol=${symbol}&trade_type=${TRADE_TYPES.VANILLA}&chart_type=${candleChartType.text}&interval=${oneMinuteInterval}`; + location.search = `?symbol=${symbol}&trade_type=${TRADE_TYPES.ACCUMULATOR}&chart_type=${areaChartType.text}&interval=${oneTickInterval}`; expect(getTradeURLParams()).toMatchObject({ - chartType: candleChartType.value, - granularity: 60, + chartType: areaChartType.value, + granularity: 0, }); }); it('should return an object without granularity if interval in the URL is incorrect', () => { @@ -76,6 +74,13 @@ describe('getTradeURLParams', () => { granularity: 0, }); }); + it('should return an object with "area" chartType if interval is 1t even if chart_type in the URL is valid but not area', () => { + location.search = `?symbol=${symbol}&trade_type=${TRADE_TYPES.ACCUMULATOR}&chart_type=hollow&interval=${oneTickInterval}`; + expect(getTradeURLParams()).toMatchObject({ + chartType: areaChartType.value, + granularity: 0, + }); + }); it('should return an object with symbol based on the URL query param when active_symbols is passed', () => { location.search = `?symbol=${symbol}`; expect(getTradeURLParams({ active_symbols: activeSymbols })).toMatchObject({ @@ -83,10 +88,10 @@ describe('getTradeURLParams', () => { }); }); it('should return an object with showModal & without symbol if symbol in the URL is incorrect and when called with active_symbols', () => { - location.search = `?symbol=BLA&chart_type=${candleChartType.text}&interval=${oneMinuteInterval}`; + location.search = `?symbol=BLA&chart_type=${areaChartType.text}&interval=${oneTickInterval}`; expect(getTradeURLParams({ active_symbols: activeSymbols })).toMatchObject({ - chartType: candleChartType.value, - granularity: 60, + chartType: areaChartType.value, + granularity: 0, showModal: true, }); }); @@ -97,10 +102,10 @@ describe('getTradeURLParams', () => { }); }); it('should return an object with showModal & without contractType if trade_type in the URL is incorrect', () => { - location.search = `?trade_type=BLA&chart_type=${candleChartType.text}&interval=${oneMinuteInterval}`; + location.search = `?trade_type=BLA&chart_type=${areaChartType.text}&interval=${oneTickInterval}`; expect(getTradeURLParams({ contract_types_list: contractTypesList })).toMatchObject({ - chartType: candleChartType.value, - granularity: 60, + chartType: areaChartType.value, + granularity: 0, showModal: true, }); }); diff --git a/packages/shared/src/utils/contract/contract.tsx b/packages/shared/src/utils/contract/contract.tsx index 3d9685c5d9d5..af420b235a26 100644 --- a/packages/shared/src/utils/contract/contract.tsx +++ b/packages/shared/src/utils/contract/contract.tsx @@ -174,8 +174,6 @@ export const isResetContract = (contract_type = '') => /RESET/i.test(contract_ty export const isCryptoContract = (underlying = '') => underlying.startsWith('cry'); -export const isUpDownContract = (contract_type = '') => /rise_fall|high_low/i.test(contract_type); - export const getAccuBarriersDefaultTimeout = (symbol: string) => { return symbols_2s.includes(symbol) ? DELAY_TIME_1S_SYMBOL * 2 : DELAY_TIME_1S_SYMBOL; }; 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 7310e5bd41f4..d7cb1a7ced03 100644 --- a/packages/shared/src/utils/contract/trade-url-params-config.ts +++ b/packages/shared/src/utils/contract/trade-url-params-config.ts @@ -61,7 +61,7 @@ export const getTradeURLParams = ({ active_symbols = [], contract_types_list = { }>((acc, [key, value]) => ({ ...acc, [key]: value }), {}); const validInterval = tradeURLParamsConfig.interval.find(item => item.text === interval); const validChartType = tradeURLParamsConfig.chartType.find(item => item.text === chart_type); - const chartTypeParam = Number(validInterval?.value) === 0 ? 'candles' : validChartType?.value; + const chartTypeParam = Number(validInterval?.value) === 0 ? 'line' : validChartType?.value; const isSymbolValid = active_symbols.some(item => item.symbol === symbol); const contractList = Object.keys(contract_types_list).reduce((acc, key) => { const categories: TTradeTypesCategories['Ups & Downs']['categories'] = diff --git a/packages/stores/src/mockStore.ts b/packages/stores/src/mockStore.ts index da18e6b5c700..79270f8d30ed 100644 --- a/packages/stores/src/mockStore.ts +++ b/packages/stores/src/mockStore.ts @@ -660,13 +660,11 @@ const mock = (): TStores & { is_mock: boolean } => { last_contract: {}, markers_array: [], onUnmount: jest.fn(), + prev_chart_type: '', prev_contract: {}, + prev_granularity: null, removeContract: jest.fn(), - saveChartType: jest.fn(), - saved_chart_type: '', - saved_granularity: null, - saveGranularity: jest.fn(), - setChartTypeAndGranularity: jest.fn(), + savePreviousChartMode: jest.fn(), setNewAccumulatorBarriersData: jest.fn(), updateAccumulatorBarriersData: jest.fn(), updateChartType: jest.fn(), diff --git a/packages/stores/types.ts b/packages/stores/types.ts index 50dc2696623b..20a32f8bf7e8 100644 --- a/packages/stores/types.ts +++ b/packages/stores/types.ts @@ -986,13 +986,11 @@ type TContractTradeStore = { epoch_array: [number]; }>; onUnmount: () => void; + prev_chart_type: string; prev_contract: TContractStore | Record; + prev_granularity: number | null; removeContract: (data: { contract_id: string }) => void; - saveChartType: (chart_type: string) => void; - saved_chart_type: string; - saved_granularity: number | null; - saveGranularity: (granularity: number | null) => void; - setChartTypeAndGranularity: any; + savePreviousChartMode: (chart_type: string, granularity: number | null) => void; setNewAccumulatorBarriersData: ( new_barriers_data: TAccumulatorBarriersData, should_update_contract_barriers?: boolean diff --git a/packages/trader/src/Stores/Modules/Trading/trade-store.ts b/packages/trader/src/Stores/Modules/Trading/trade-store.ts index 612b09805093..e6817b8dd61b 100644 --- a/packages/trader/src/Stores/Modules/Trading/trade-store.ts +++ b/packages/trader/src/Stores/Modules/Trading/trade-store.ts @@ -1,47 +1,46 @@ import * as Symbol from './Actions/symbol'; import { - BARRIER_COLORS, - BARRIER_LINE_STYLES, + WS, ChartBarrierStore, cloneObject, - CONTRACT_TYPES, convertDurationLimit, extractInfoFromShortcode, findFirstOpenMarket, - formatMoney, getBarrierPipSize, - getCardLabelsV2, - getContractPath, - getContractSubtype, - getCurrencyDisplayCode, getMinPayout, getPlatformSettings, getPropertyValue, + getContractSubtype, getTradeNotificationMessage, - getTradeURLParams, - hasBarrier, - isAccumulatorContract, isBarrierSupported, + isAccumulatorContract, isCryptocurrency, - isDtraderV2Enabled, isEmptyObject, - isHighLow, isMarketClosed, isMultiplierContract, - isTouchContract, isTurbosContract, - isUpDownContract, - isVanillaContract, isVanillaFxContract, + isVanillaContract, pickDefaultSymbol, resetEndTimeOnVolatilityIndices, - routes, setLimitOrderBarriers, - setTradeURLParams, showDigitalOptionsUnavailableError, showUnavailableLocationError, + getCurrencyDisplayCode, + BARRIER_COLORS, + BARRIER_LINE_STYLES, TRADE_TYPES, - WS, + hasBarrier, + isHighLow, + CONTRACT_TYPES, + setTradeURLParams, + getTradeURLParams, + isTouchContract, + getCardLabelsV2, + formatMoney, + getContractPath, + routes, + isDtraderV2Enabled, } from '@deriv/shared'; import { Analytics } from '@deriv-com/analytics'; import type { TEvents } from '@deriv-com/analytics'; @@ -1288,32 +1287,27 @@ export default class TradeStore extends BaseStore { // when accumulator is selected, we need to change chart type to mountain and granularity to 0 // and we need to restore previous chart type and granularity when accumulator is unselected const { + prev_chart_type, + prev_granularity, chart_type, - saved_chart_type, - saved_granularity, - setChartTypeAndGranularity, + granularity, + savePreviousChartMode, updateChartType, updateGranularity, } = this.root_store.contract_trade || {}; - const has_line_chart = - isAccumulatorContract(obj_new_values.contract_type) || - isDigitTradeType(obj_new_values.contract_type) || - isUpDownContract(obj_new_values.contract_type); - if (obj_new_values.contract_type) { - if (!has_line_chart && (saved_chart_type || !Number.isNaN(saved_granularity))) { - if (saved_chart_type) { - updateChartType(saved_chart_type); - } - if (!Number.isNaN(saved_granularity)) { - updateGranularity(saved_granularity); - } - } else if (has_line_chart) { - setChartTypeAndGranularity('line', 0); - setTradeURLParams({ chartType: 'line', granularity: 0 }); - } else { - setChartTypeAndGranularity('candles', 60); - setTradeURLParams({ chartType: 'candles', granularity: 60 }); - } + if (isAccumulatorContract(obj_new_values.contract_type) || isDigitTradeType(obj_new_values.contract_type)) { + savePreviousChartMode(chart_type, granularity); + updateGranularity(0); + updateChartType('line'); + } else if ( + (obj_new_values.contract_type || obj_new_values.symbol) && + prev_chart_type && + prev_granularity && + (prev_chart_type !== chart_type || prev_granularity !== granularity) + ) { + updateGranularity(prev_granularity); + updateChartType(prev_chart_type); + savePreviousChartMode('', null); } if (/\bduration\b/.test(Object.keys(obj_new_values) as unknown as string)) { // TODO: fix this in input-field.jsx @@ -1845,14 +1839,17 @@ export default class TradeStore extends BaseStore { setChartModeFromURL() { const { chartType: chartTypeParam, granularity: granularityParam } = getTradeURLParams(); - const { chart_type, granularity, saveChartType, saveGranularity } = this.root_store.contract_trade; - if ( - (!isNaN(Number(granularityParam)) && granularityParam !== granularity) || - (chartTypeParam && chartTypeParam !== chart_type) - ) { - chartTypeParam && saveChartType(chartTypeParam); - granularityParam && saveGranularity(Number(granularityParam)); + const { chart_type, granularity, updateChartType, updateGranularity } = this.root_store.contract_trade; + if (!isNaN(Number(granularityParam)) && granularityParam !== granularity) { + updateGranularity(Number(granularityParam)); } + if (chartTypeParam && chartTypeParam !== chart_type) { + updateChartType(chartTypeParam); + } + setTradeURLParams({ + chartType: chartTypeParam ?? chart_type, + granularity: granularityParam ?? Number(granularity), + }); } setChartStatus(status: boolean, isFromChart?: boolean) { @@ -2006,6 +2003,14 @@ export default class TradeStore extends BaseStore { ) { this.prepareTradeStore(false); } + if (state === STATE_TYPES.SET_CHART_MODE) { + if (!isNaN(Number(option?.granularity))) { + this.root_store.contract_trade.updateGranularity(Number(option?.granularity)); + } + if (option?.chart_type_name) { + this.root_store.contract_trade.updateChartType(option?.chart_type_name); + } + } const { data, event_type } = getChartAnalyticsData(state as keyof typeof STATE_TYPES, option) as TPayload; if (data) { Analytics.trackEvent(event_type, {