swipedRight(true)}
color={active_index === 0 || props.is_disabled ? 'disabled' : ''}
/>
swipedLeft(true)}
color={
active_index + 1 === React.Children.toArray(children).length || props.is_disabled
? 'disabled'
diff --git a/packages/core/build/config.js b/packages/core/build/config.js
index 73fa1bc0ccf9..d82ee5fb688e 100644
--- a/packages/core/build/config.js
+++ b/packages/core/build/config.js
@@ -23,6 +23,22 @@ const copyConfig = base => {
from: path.resolve(__dirname, '../../../node_modules/@deriv/deriv-charts/dist'),
to: 'js/smartcharts/',
},
+ {
+ from: path.resolve(__dirname, '../../../node_modules/@deriv/deriv-charts-beta/dist'),
+ to: 'js/smartchartsbeta/',
+ },
+ {
+ from: path.resolve(__dirname, '../../../node_modules/@deriv/deriv-charts-beta/dist/chart/assets'),
+ to: 'assets',
+ },
+ {
+ from: path.resolve(__dirname, '../../../node_modules/@deriv/deriv-charts-beta/dist/chart/assets'),
+ to: 'contract/assets',
+ },
+ {
+ from: path.resolve(__dirname, '../../../node_modules/@deriv/deriv-charts-beta/dist/chart/assets'),
+ to: 'bot/assets',
+ },
{
from: path.resolve(__dirname, '../node_modules/@deriv/account/dist/account/js/'),
to: 'account/js',
@@ -167,7 +183,7 @@ const generateSWConfig = () => ({
},
{
urlPattern: ({ url }) => {
- return url.pathname.match(/^\/js\/(?!(.*((core\.[a-z_]*-json\.)|smartcharts))).*$/);
+ return url.pathname.match(/^\/js\/(?!(.*((core\.[a-z_]*-json\.)|smartcharts|smartchartsbeta))).*$/);
},
handler: 'CacheFirst',
options: {
@@ -179,7 +195,7 @@ const generateSWConfig = () => ({
},
{
urlPattern: ({ url }) => {
- return url.pathname.match(/^\/js\/smartcharts\//);
+ return url.pathname.match(/^\/js\/(smartcharts|smartchartsbeta)\//);
},
handler: 'CacheFirst',
options: {
diff --git a/packages/core/build/constants.js b/packages/core/build/constants.js
index e912721d4167..fc805f041b59 100644
--- a/packages/core/build/constants.js
+++ b/packages/core/build/constants.js
@@ -13,7 +13,6 @@ const TerserPlugin = require('terser-webpack-plugin');
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
const { GenerateSW } = require('workbox-webpack-plugin');
-const webpack = require('webpack');
const {
copyConfig,
@@ -47,6 +46,7 @@ const HOISTED_PACKAGES = {
'@deriv/components': path.resolve(__dirname, '../node_modules/@deriv/components'),
'@deriv/translations': path.resolve(__dirname, '../node_modules/@deriv/translations'),
'@deriv/deriv-charts': path.resolve(__dirname, '../../../node_modules/@deriv/deriv-charts'),
+ '@deriv/deriv-charts-beta': path.resolve(__dirname, '../../../node_modules/@deriv/deriv-charts-beta'),
};
const ALIASES = {
@@ -120,6 +120,11 @@ const MINIMIZERS = !IS_RELEASE
exclude: /(smartcharts)/,
parallel: 2,
}),
+ new TerserPlugin({
+ test: /\.js$/,
+ exclude: /(smartchartsbeta)/,
+ parallel: 2,
+ }),
new CssMinimizerPlugin(),
];
@@ -146,9 +151,6 @@ const plugins = ({ base, is_test_env }) => {
new PreloadWebpackPlugin(htmlPreloadConfig()),
new IgnorePlugin({ resourceRegExp: /^\.\/locale$/, contextRegExp: /moment$/ }),
new MiniCssExtractPlugin(cssConfig()),
- new webpack.optimize.LimitChunkCountPlugin({
- maxChunks: 10,
- }),
new CircularDependencyPlugin({ exclude: /node_modules/, failOnError: true }),
...(IS_RELEASE
? []
diff --git a/packages/core/build/webpack.config.js b/packages/core/build/webpack.config.js
index d586f5178f8a..892d59f8661e 100644
--- a/packages/core/build/webpack.config.js
+++ b/packages/core/build/webpack.config.js
@@ -41,7 +41,7 @@ module.exports = function (env) {
minChunks: 1,
maxSize: 2500000,
maxAsyncRequests: 30,
- maxInitialRequests: 3,
+ maxInitialRequests: 30,
automaticNameDelimiter: '~',
enforceSizeThreshold: 500000,
cacheGroups: {
diff --git a/packages/core/package.json b/packages/core/package.json
index 518d88fbfe24..69c5f41524b7 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -31,8 +31,8 @@
},
"homepage": "https://github.com/binary-com/deriv-app",
"devDependencies": {
- "@babel/plugin-proposal-unicode-property-regex": "^7.16.7",
"@babel/eslint-parser": "^7.17.0",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.16.7",
"@babel/preset-react": "^7.16.7",
"@types/react": "^18.0.7",
"@types/react-dom": "^18.0.0",
@@ -62,13 +62,13 @@
"lint-staged": "^10.4.0",
"mini-css-extract-plugin": "^1.3.4",
"mock-local-storage": "^1.1.8",
- "sass": "^1.62.1",
"postcss-loader": "^6.2.1",
"postcss-preset-env": "^7.4.3",
"postcss-scss": "^4.0.6",
"preload-webpack-plugin": "^3.0.0-beta.4",
"react-svg-loader": "^3.0.3",
"resolve-url-loader": "^3.1.2",
+ "sass": "^1.62.1",
"sass-loader": "^12.6.0",
"sass-resources-loader": "^2.1.1",
"stylelint-formatter-pretty": "^2.1.1",
@@ -87,6 +87,7 @@
},
"dependencies": {
"@babel/polyfill": "^7.4.4",
+ "@datadog/browser-rum": "^4.37.0",
"@deriv/account": "^1.0.0",
"@deriv/analytics": "^1.0.0",
"@deriv/api": "^1.0.0",
@@ -98,11 +99,12 @@
"@deriv/components": "^1.0.0",
"@deriv/deriv-api": "^1.0.13",
"@deriv/deriv-charts": "1.4.0",
+ "@deriv/deriv-charts-beta": "npm:@deriv/deriv-charts@^2.0.0-beta.14",
"@deriv/hooks": "^1.0.0",
"@deriv/p2p": "^0.7.3",
"@deriv/reports": "^1.0.0",
- "@deriv/stores": "^1.0.0",
"@deriv/shared": "^1.0.0",
+ "@deriv/stores": "^1.0.0",
"@deriv/trader": "^3.8.0",
"@deriv/translations": "^1.0.0",
"@deriv/utils": "^1.0.0",
@@ -112,8 +114,10 @@
"canvas-toBlob": "^1.0.0",
"classnames": "^2.2.6",
"crc-32": "^1.2.0",
+ "dotenv-webpack": "^8.0.1",
"extend": "^3.0.2",
"formik": "^2.1.4",
+ "framer-motion": "^6.5.1",
"i18next": "^22.4.6",
"js-cookie": "^2.2.1",
"loadjs": "^4.2.0",
@@ -132,13 +136,10 @@
"react-dom": "^17.0.2",
"react-i18next": "^11.11.0",
"react-loadable": "^5.5.0",
- "framer-motion": "^6.5.1",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"react-tiny-popover": "^7.0.1",
"react-transition-group": "4.4.2",
- "react-window": "^1.8.5",
- "dotenv-webpack": "^8.0.1",
- "@datadog/browser-rum": "^4.37.0"
+ "react-window": "^1.8.5"
}
}
diff --git a/packages/core/src/App/app.jsx b/packages/core/src/App/app.jsx
index 002be4ba2529..4c8bccaf7a4b 100644
--- a/packages/core/src/App/app.jsx
+++ b/packages/core/src/App/app.jsx
@@ -19,8 +19,6 @@ import { BrowserRouter as Router } from 'react-router-dom';
import { CFD_TEXT } from '../Constants/cfd-text';
import { FORM_ERROR_MESSAGES } from '../Constants/form-error-messages';
import AppContent from './AppContent';
-// TODO: Lazy load smartchart styles
-import '@deriv/deriv-charts/dist/smartcharts.css';
import 'Sass/app.scss';
const AppWithoutTranslation = ({ root_store }) => {
@@ -42,6 +40,14 @@ const AppWithoutTranslation = ({ root_store }) => {
React.useEffect(initCFDStore, []);
React.useEffect(() => {
+ const loadSmartchartsStyles = () => {
+ if (root_store.client.is_beta_chart) {
+ import('@deriv/deriv-charts-beta/dist/smartcharts.css');
+ } else {
+ import('@deriv/deriv-charts/dist/smartcharts.css');
+ }
+ };
+
initializeTranslations();
// TODO: [translation-to-shared]: add translation implemnentation in shared
@@ -49,6 +55,7 @@ const AppWithoutTranslation = ({ root_store }) => {
initFormErrorMessages(FORM_ERROR_MESSAGES);
setSharedCFDText(CFD_TEXT);
root_store.common.setPlatform();
+ loadSmartchartsStyles();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
diff --git a/packages/core/src/Stores/Helpers/__tests__/chart-markers.spec.ts b/packages/core/src/Stores/Helpers/__tests__/chart-markers.spec.ts
index e61f9b1c43a5..4bd868d6406d 100644
--- a/packages/core/src/Stores/Helpers/__tests__/chart-markers.spec.ts
+++ b/packages/core/src/Stores/Helpers/__tests__/chart-markers.spec.ts
@@ -1,5 +1,5 @@
import { TContractInfo } from '@deriv/shared';
-import { createTickMarkers } from '../chart-markers';
+import { createTickMarkers, getMarkerContractType, getStartText } from '../chart-markers';
describe('createTickMarkers', () => {
const previous_spot_classname = 'chart-spot__spot chart-spot__spot--accumulator-middle';
@@ -95,4 +95,30 @@ describe('createTickMarkers', () => {
`${previous_spot_classname}--preexit`
);
});
+
+ it('should get the correct contract type', () => {
+ contract_info.contract_type = 'ACCU';
+ expect(getMarkerContractType(contract_info)).toBe('AccumulatorContract');
+
+ contract_info.contract_type = 'DIGITMATCH';
+ expect(getMarkerContractType(contract_info)).toBe('DigitContract');
+
+ contract_info.contract_type = 'CALL';
+ contract_info.tick_count = 1;
+ expect(getMarkerContractType(contract_info)).toBe('TickContract');
+ });
+
+ it('should get the correct start text', () => {
+ contract_info.contract_type = 'ACCU';
+ contract_info.tick_count = undefined;
+ Object.assign(contract_info, {
+ contract_type: 'CALL',
+ tick_count: undefined,
+ profit: '1',
+ barrier: '1000',
+ currency: 'USD',
+ });
+ const result = getStartText(contract_info);
+ expect(result).toBe('+$1.00');
+ });
});
diff --git a/packages/core/src/Stores/Helpers/chart-markers.js b/packages/core/src/Stores/Helpers/chart-markers.js
index 9bd8fdb2afe5..c3d2be60db50 100644
--- a/packages/core/src/Stores/Helpers/chart-markers.js
+++ b/packages/core/src/Stores/Helpers/chart-markers.js
@@ -8,24 +8,33 @@ import {
getSpotCount,
} from './chart-marker-helpers';
import {
+ getDecimalPlaces,
getEndTime,
isAccumulatorContract,
isAccumulatorContractOpen,
+ isDigitContract,
+ isHighLow,
isSmartTraderContract,
isOpen,
+ isTouchContract,
+ isMultiplierContract,
+ isVanillaContract,
+ getContractStatus,
unique,
+ isTurbosContract,
} from '@deriv/shared';
+import { localize } from '@deriv/translations';
import { MARKER_TYPES_CONFIG } from '../Constants/markers';
import { getChartType } from './logic';
-export const createChartMarkers = (contract_info, is_delayed_markers_update) => {
+export const createChartMarkers = (contract_info, is_delayed_markers_update, is_beta_chart) => {
const { tick_stream } = contract_info;
const should_show_10_last_ticks = isAccumulatorContractOpen(contract_info) && tick_stream.length === 10;
let markers = [];
if (contract_info) {
const end_time = getEndTime(contract_info);
- const chart_type = getChartType(contract_info.date_start, end_time);
+ const chart_type = getChartType(contract_info.date_start, end_time, is_beta_chart);
if (contract_info.tick_count) {
const tick_markers = createTickMarkers(contract_info, is_delayed_markers_update);
@@ -140,3 +149,358 @@ export const createTickMarkers = (contract_info, is_delayed_markers_update) => {
});
return result;
};
+
+const dark_theme = {
+ bg: '#0e0e0e',
+ fg: '#ffffff',
+ grey_border: '#6e6e6e',
+ lost: '#cc2e3d',
+ open: '#377cfc',
+ sold: '#ffad3a',
+ won: '#00a79e',
+};
+
+const light_theme = {
+ bg: '#ffffff',
+ fg: '#333333',
+ grey_border: '#999999',
+ lost: '#ec3f3f',
+ open: '#377cfc',
+ sold: '#ffad3a',
+ won: '#4bb4b3',
+};
+
+function getColor({ status, profit, is_dark_theme, is_vanilla }) {
+ const colors = is_dark_theme ? dark_theme : light_theme;
+ let color = colors[status || 'open'];
+ if (is_vanilla) {
+ if (status === 'open') return colors.open;
+ return colors[profit > 0 ? 'won' : 'lost'];
+ }
+ if (status === 'open' && profit) {
+ color = colors[profit > 0 ? 'won' : 'lost'];
+ }
+ return color;
+}
+
+const currency_symbols = {
+ AUD: '\u0041\u0024',
+ EUR: '\u20AC',
+ GBP: '\u00A3',
+ JPY: '\u00A5',
+ USD: '\u0024',
+ BTC: '\u20bf',
+ BCH: '\ue901',
+ ETH: '\u0045',
+ ETC: '\ue900',
+ LTC: '\u0141',
+ UST: '\u20ae',
+};
+
+export const getMarkerContractType = contract_info => {
+ const { tick_count, contract_type } = contract_info;
+
+ if (isAccumulatorContract(contract_type)) {
+ return 'AccumulatorContract';
+ } else if (isDigitContract(contract_type)) {
+ return 'DigitContract';
+ }
+
+ return tick_count > 0 ? 'TickContract' : 'NonTickContract';
+};
+
+export const getStartText = contract_info => {
+ const { barrier, contract_type, currency, is_sold, profit, tick_count, tick_stream } = contract_info;
+ const is_non_tick_contract = !tick_count;
+
+ if (is_sold || isAccumulatorContract(contract_type)) return undefined;
+
+ // NonTickContract
+ if (is_non_tick_contract) {
+ if (!(profit && barrier)) return undefined;
+
+ const symbol = currency_symbols[currency] || '';
+ const decimal_places = getDecimalPlaces(currency);
+ const sign = profit < 0 ? '-' : profit > 0 ? '+' : ' ';
+ return `${sign}${symbol}${Math.abs(profit).toFixed(decimal_places)}`;
+ }
+
+ return `${Math.max(tick_stream.length - 1, 0)}/${tick_count}`;
+};
+
+export const getTickStreamMarkers = (contract_info, barrier_price) => {
+ function getTicks() {
+ if (is_accumulator_contract) {
+ return [];
+ } else if (is_digit_contract) {
+ return [undefined, ...tick_stream.slice(-1)];
+ }
+ return tick_stream;
+ }
+
+ const { contract_type, tick_stream } = contract_info;
+ const is_digit_contract = isDigitContract(contract_type);
+ const is_accumulator_contract = isAccumulatorContract(contract_type);
+
+ const last_tick = tick_stream.length > 1 ? tick_stream[tick_stream.length - 1] : null;
+ const [, ...ticks] = getTicks();
+
+ const markers = ticks.map(t => ({
+ epoch: t.epoch,
+ quote: t.tick,
+ type: 'tick',
+ }));
+
+ if (!is_digit_contract && !is_accumulator_contract && last_tick) {
+ markers.push({
+ epoch: last_tick.epoch,
+ quote: last_tick.quote,
+ type: 'latestTick',
+ });
+ markers.push({
+ epoch: last_tick.epoch,
+ quote: barrier_price,
+ type: 'latestTickBarrier',
+ });
+ }
+
+ return markers;
+};
+
+export function calculateMarker(contract_info, is_dark_theme, is_last_contract) {
+ if (!contract_info || isMultiplierContract(contract_info.contract_type)) {
+ return null;
+ }
+ const {
+ transaction_ids,
+ tick_stream,
+ date_start,
+ date_expiry,
+ entry_tick,
+ exit_tick,
+ entry_tick_time,
+ exit_tick_time,
+ contract_type,
+ tick_count,
+ barrier_count,
+ barrier,
+ high_barrier,
+ low_barrier,
+ shortcode,
+ status,
+ profit,
+ is_sold,
+ } = contract_info;
+ const is_accumulator_contract = isAccumulatorContract(contract_type);
+ const is_digit_contract = isDigitContract(contract_type);
+ const is_tick_contract = tick_count > 0;
+ const is_non_tick_contract = !is_tick_contract;
+ const is_high_low_contract = isHighLow({ shortcode });
+ const is_touch_contract = isTouchContract(contract_type);
+ const is_turbos = isTurbosContract(contract_type);
+
+ const end_time = is_tick_contract ? exit_tick_time : getEndTime(contract_info) || date_expiry;
+
+ let barrier_price;
+ if (is_digit_contract || is_accumulator_contract) {
+ barrier_price = +entry_tick;
+ } else if (+barrier_count === 1 && barrier) {
+ barrier_price = +barrier;
+ } else if (+barrier_count === 2 && high_barrier && low_barrier) {
+ barrier_price = +high_barrier;
+ }
+
+ if (!date_start) {
+ return null;
+ }
+ // if we have not yet received the first POC response
+ if (!transaction_ids) {
+ return {
+ type: getMarkerContractType(contract_info),
+ markers: [],
+ };
+ }
+
+ const markers = [];
+
+ const price = barrier_price || 0;
+
+ if (is_last_contract && !is_sold) {
+ markers.push({
+ epoch: date_start,
+ quote: is_digit_contract ? undefined : price,
+ type: 'activeStart',
+ text: localize('Start\nTime'),
+ });
+ }
+
+ if (date_start && entry_tick) {
+ const color = is_non_tick_contract ? getColor({ status: 'open', profit }) : undefined;
+ markers.push({
+ epoch: date_start,
+ quote: is_digit_contract ? undefined : price,
+ type: 'start',
+ text: getStartText(contract_info),
+ color,
+ });
+ }
+
+ if (entry_tick) {
+ markers.push({
+ epoch: entry_tick_time,
+ quote: price,
+ type: 'entry',
+ });
+
+ if (is_high_low_contract || is_touch_contract || is_turbos) {
+ markers.push({
+ epoch: entry_tick_time,
+ quote: entry_tick,
+ type: 'entryTick',
+ });
+ }
+ }
+
+ if (end_time) {
+ markers.push({
+ epoch: end_time,
+ quote: price,
+ type: 'end',
+ });
+ }
+
+ if (exit_tick) {
+ markers.push({
+ epoch: exit_tick_time,
+ quote: +exit_tick,
+ type: 'exit',
+ });
+ } else if (tick_stream?.length > 0) {
+ markers.push(...getTickStreamMarkers(contract_info, barrier_price));
+ }
+
+ if (is_accumulator_contract && tick_stream?.length > 0) {
+ const contract_status = getContractStatus({ contract_type, profit, exit_tick_time, status });
+ const is_accu_contract_ended = contract_status !== 'open';
+
+ if (is_accu_contract_ended) {
+ const exit = tick_stream[tick_stream.length - 1];
+ const previous_tick = tick_stream[tick_stream.length - 2] || exit;
+
+ markers.push(
+ ...getAccumulatorBarrierMarkers({
+ high_barrier,
+ low_barrier,
+ prev_epoch: previous_tick.epoch,
+ is_dark_mode_on: is_dark_theme,
+ contract_info,
+ })
+ );
+ }
+ }
+
+ return {
+ type: getMarkerContractType(contract_info),
+ markers,
+ color: getColor({
+ status,
+ profit: is_non_tick_contract || is_sold ? profit : undefined,
+ is_dark_theme,
+ is_vanilla: isVanillaContract(contract_type),
+ }),
+ };
+}
+
+function getAccumulatorBarrierMarkers({
+ contract_info,
+ high_barrier,
+ low_barrier,
+ is_accumulator_trade_without_contract = false,
+ is_dark_theme,
+ has_crossed_accu_barriers,
+ barrier_spot_distance,
+ prev_epoch: epoch,
+}) {
+ const { contract_type, profit, exit_tick_time, status, is_sold } = contract_info || {};
+
+ const contract_status = getContractStatus({ contract_type, profit, exit_tick_time, status });
+ const is_accu_contract_ended = contract_status !== 'open';
+
+ const getStatus = () => {
+ if (has_crossed_accu_barriers || contract_status === 'lost') {
+ return 'lost';
+ } else if (is_accumulator_trade_without_contract) {
+ return 'open';
+ }
+
+ return 'won';
+ };
+
+ const barrier_color = getColor({
+ status: getStatus(),
+ is_dark_theme,
+ });
+
+ const tick_color = is_accumulator_trade_without_contract
+ ? getColor({ status: 'fg', is_dark_theme })
+ : getColor({
+ is_dark_theme,
+ status: contract_status,
+ profit: is_sold || is_accu_contract_ended ? profit : null,
+ });
+
+ const markers = [
+ {
+ epoch,
+ quote: +high_barrier,
+ type: 'highBarrier',
+ color: barrier_color,
+ text: barrier_spot_distance ? `+${barrier_spot_distance}` : '',
+ },
+ {
+ epoch,
+ quote: +low_barrier,
+ type: 'lowBarrier',
+ color: barrier_color,
+ text: barrier_spot_distance ? `-${barrier_spot_distance}` : '',
+ },
+ {
+ epoch,
+ type: 'previousTick',
+ color: tick_color,
+ },
+ ];
+
+ return markers;
+}
+
+export function getAccumulatorMarkers({
+ prev_epoch,
+ high_barrier,
+ low_barrier,
+ is_accumulator_trade_without_contract = false,
+ has_crossed_accu_barriers = false,
+ is_dark_theme,
+ contract_info,
+ in_contract_details = false,
+ barrier_spot_distance,
+}) {
+ const markers = getAccumulatorBarrierMarkers({
+ contract_info,
+ high_barrier,
+ low_barrier,
+ is_accumulator_trade_without_contract,
+ is_dark_theme,
+ has_crossed_accu_barriers,
+ barrier_spot_distance,
+ prev_epoch,
+ });
+
+ return {
+ type: 'AccumulatorContract',
+ markers,
+ props: {
+ hasPersistentBorders: in_contract_details,
+ },
+ };
+}
diff --git a/packages/core/src/Stores/Helpers/logic.js b/packages/core/src/Stores/Helpers/logic.js
index bc492458a41e..cb58c20811a3 100644
--- a/packages/core/src/Stores/Helpers/logic.js
+++ b/packages/core/src/Stores/Helpers/logic.js
@@ -2,12 +2,12 @@ import moment from 'moment';
import { isAccumulatorContract, isEmptyObject, getEndTime } from '@deriv/shared';
import ServerTime from '../../_common/base/server_time';
-export const getChartConfig = contract_info => {
+export const getChartConfig = (contract_info, is_beta_chart) => {
if (isEmptyObject(contract_info)) return null;
const start = contract_info.date_start;
const end = getEndTime(contract_info);
const granularity = getChartGranularity(start, end || null);
- const chart_type = getChartType(start, end || null);
+ const chart_type = getChartType(start, end || null, is_beta_chart);
const is_accumulator_contract = isAccumulatorContract(contract_info.contract_type);
// setting start_epoch and scroll_to_epoch for accumulator contracts
// when contract is open, we get no more than 10 last ticks from BE, so we show 10 ticks when tick_stream.length === 10
@@ -18,7 +18,7 @@ export const getChartConfig = contract_info => {
const start_epoch = should_show_10_last_ticks ? first_tick_epoch : start;
const scroll_to_epoch = should_show_10_last_ticks ? first_tick_epoch : contract_info.purchase_time;
return {
- chart_type: contract_info.tick_count ? 'mountain' : chart_type,
+ chart_type: contract_info.tick_count ? (is_beta_chart ? 'line' : 'mountain') : chart_type,
granularity: contract_info.tick_count ? 0 : granularity,
end_epoch: end,
start_epoch,
@@ -37,10 +37,10 @@ const hour_to_granularity_map = [
const getExpiryTime = time => time || ServerTime.get().unix();
-export const getChartType = (start_time, expiry_time) => {
+export const getChartType = (start_time, expiry_time, is_beta_chart) => {
const duration = moment.duration(moment.unix(getExpiryTime(expiry_time)).diff(moment.unix(start_time))).asHours();
// use line chart if duration is equal or less than 1 hour
- return duration <= 1 ? 'mountain' : 'candle';
+ return duration <= 1 ? (is_beta_chart ? 'line' : 'mountain') : 'candle';
};
export const getChartGranularity = (start_time, expiry_time) =>
diff --git a/packages/core/src/Stores/client-store.js b/packages/core/src/Stores/client-store.js
index 3656e7599411..537ebadbd452 100644
--- a/packages/core/src/Stores/client-store.js
+++ b/packages/core/src/Stores/client-store.js
@@ -83,6 +83,7 @@ export default class ClientStore extends BaseStore {
has_enabled_two_fa = false;
has_changed_two_fa = false;
landing_companies = {};
+ is_beta_chart = false;
// All possible landing companies of user between all
standpoint = {
@@ -403,6 +404,8 @@ export default class ClientStore extends BaseStore {
setPrevRealAccountLoginid: action.bound,
setP2pAdvertiserInfo: action.bound,
setPrevAccountType: action.bound,
+ is_beta_chart: observable,
+ setIsBetaChart: action.bound,
});
reaction(
@@ -436,6 +439,8 @@ export default class ClientStore extends BaseStore {
() => !this.is_logged_in && this.root_store.ui && this.root_store.ui.is_real_acc_signup_on,
() => this.root_store.ui.closeRealAccountSignup()
);
+
+ this.setIsBetaChart();
}
get balance() {
@@ -1318,6 +1323,25 @@ export default class ClientStore extends BaseStore {
this.website_status = response.website_status;
this.responseWebsiteStatus(response);
setCurrencies(this.website_status);
+
+ // TODO: remove the below lines after full smartcharts v2 launch.
+ const domain = /deriv\.(com|me)/.test(window.location.hostname)
+ ? deriv_urls.DERIV_HOST_NAME
+ : window.location.hostname;
+ const { clients_country } = this.website_status;
+
+ const options = {
+ domain,
+ expires: 7,
+ };
+
+ try {
+ const cookie = Cookies.get('website_status') ? JSON.parse(Cookies.get('website_status')) : {};
+ cookie.clients_country = clients_country;
+ Cookies.set('website_status', cookie, options);
+ } catch (e) {
+ Cookies.set('website_status', { clients_country }, options);
+ }
}
async accountRealReaction(response) {
@@ -2755,5 +2779,22 @@ export default class ClientStore extends BaseStore {
return is_p2p_visible;
}
+
+ setIsBetaChart = () => {
+ const website_status = Cookies.get('website_status');
+ if (!website_status) return;
+
+ try {
+ const cookie_value = JSON.parse(website_status);
+
+ if (cookie_value && cookie_value.clients_country) {
+ const client_country = cookie_value.clients_country;
+ /// Show beta chart only for these countries
+ this.is_beta_chart = ['ke', 'in', 'pk'].includes(client_country);
+ }
+ } catch {
+ this.is_beta_chart = false;
+ }
+ };
}
/* eslint-enable */
diff --git a/packages/core/src/Stores/contract-store.js b/packages/core/src/Stores/contract-store.js
index 45bdfd5ee453..a53561eda0a5 100644
--- a/packages/core/src/Stores/contract-store.js
+++ b/packages/core/src/Stores/contract-store.js
@@ -23,7 +23,7 @@ import {
import { getChartConfig } from './Helpers/logic';
import { setLimitOrderBarriers, getLimitOrder } from './Helpers/limit-orders';
import { ChartBarrierStore } from './chart-barrier-store';
-import { createChartMarkers } from './Helpers/chart-markers';
+import { createChartMarkers, calculateMarker, getAccumulatorMarkers } from './Helpers/chart-markers';
import BaseStore from './base-store';
export default class ContractStore extends BaseStore {
@@ -63,6 +63,7 @@ export default class ContractStore extends BaseStore {
clearContractUpdateConfigValues: action.bound,
onChange: action.bound,
updateLimitOrder: action.bound,
+ getContractsArray: action.bound,
});
this.root_store = root_store;
@@ -109,7 +110,7 @@ export default class ContractStore extends BaseStore {
// ---- Normal properties ---
is_ongoing_contract = false;
- populateConfig(contract_info) {
+ populateConfig(contract_info, is_last_contract = false) {
const prev_contract_info = this.contract_info;
this.contract_info = contract_info;
this.end_time = getEndTime(this.contract_info);
@@ -118,9 +119,14 @@ export default class ContractStore extends BaseStore {
this.accu_low_barrier = accu_low_barrier;
// TODO: don't update the barriers & markers if they are not changed
this.updateBarriersArray(contract_info, this.root_store.ui.is_dark_mode_on);
- this.markers_array = createChartMarkers(this.contract_info);
- this.marker = calculate_marker(this.contract_info, { accu_high_barrier, accu_low_barrier });
- this.contract_config = getChartConfig(this.contract_info);
+ this.markers_array = createChartMarkers(this.contract_info, this.root_store.client.is_beta_chart);
+ this.marker = this.root_store.client.is_beta_chart
+ ? calculateMarker(this.contract_info, this.root_store.ui.is_dark_mode_on, is_last_contract, {
+ accu_high_barrier,
+ accu_low_barrier,
+ })
+ : calculate_marker(this.contract_info, { accu_high_barrier, accu_low_barrier });
+ this.contract_config = getChartConfig(this.contract_info, this.root_store.client.is_beta_chart);
this.display_status = getDisplayStatus(this.contract_info);
this.is_ended = isEnded(this.contract_info);
this.is_digit_contract = isDigitContract(this.contract_info.contract_type);
@@ -206,10 +212,15 @@ export default class ContractStore extends BaseStore {
},
is_dark_mode
);
- this.marker = calculate_marker(this.contract_info, {
- accu_high_barrier: this.accu_high_barrier,
- accu_low_barrier: this.accu_low_barrier,
- }); // this.marker is rendered as DelayedAccuBarriersMarker component
+ this.marker = this.root_store.client.is_beta_chart
+ ? calculateMarker(this.contract_info, this.root_store.ui.is_dark_mode_on, false, {
+ accu_high_barrier: this.accu_high_barrier,
+ accu_low_barrier: this.accu_low_barrier,
+ })
+ : calculate_marker(this.contract_info, {
+ accu_high_barrier: this.accu_high_barrier,
+ accu_low_barrier: this.accu_low_barrier,
+ }); // this.marker is rendered as DelayedAccuBarriersMarker component
return;
}
setTimeout(
@@ -221,7 +232,11 @@ export default class ContractStore extends BaseStore {
main_barrier?.updateBarriers(this.accu_high_barrier, this.accu_low_barrier);
}
// this.markers_array contains tick markers & start/end vertical lines in C.Details page
- this.markers_array = createChartMarkers(contract_info, true);
+ this.markers_array = createChartMarkers(
+ contract_info,
+ true,
+ this.root_store.client.is_beta_chart
+ );
// this observable controls the update of DelayedAccuBarriersMarker in C.Details page
this.accumulator_previous_spot_time = current_spot_time;
}
@@ -327,6 +342,28 @@ export default class ContractStore extends BaseStore {
this.root_store.portfolio.populateContractUpdate(response, this.contract_id);
});
}
+
+ getContractsArray() {
+ const { contract_type, high_barrier, low_barrier, tick_stream: ticks } = this.contract_info;
+
+ if (!isAccumulatorContract(contract_type)) return [];
+
+ const exit = ticks[ticks.length - 1];
+ const previous_tick = ticks[ticks.length - 2] || exit;
+
+ if (!previous_tick) return [];
+
+ const contract_markers = getAccumulatorMarkers({
+ high_barrier,
+ low_barrier,
+ prev_epoch: previous_tick.epoch,
+ is_dark_mode_on: this.root_store.ui.is_dark_mode_on,
+ contract_info: this.contract_info,
+ in_contract_details: true,
+ });
+
+ return [contract_markers];
+ }
}
function calculate_marker(contract_info, { accu_high_barrier, accu_low_barrier }) {
diff --git a/packages/core/src/Stores/contract-trade-store.js b/packages/core/src/Stores/contract-trade-store.js
index 2d4870f2f3b7..dd8ee31b1444 100644
--- a/packages/core/src/Stores/contract-trade-store.js
+++ b/packages/core/src/Stores/contract-trade-store.js
@@ -19,6 +19,7 @@ import {
} from '@deriv/shared';
import BaseStore from './base-store';
+import { getAccumulatorMarkers } from './Helpers/chart-markers';
import ContractStore from './contract-store';
export default class ContractTradeStore extends BaseStore {
@@ -30,7 +31,9 @@ export default class ContractTradeStore extends BaseStore {
// Chart specific observables
granularity = +LocalStore.get('contract_trade.granularity') || 0;
- chart_type = LocalStore.get('contract_trade.chart_type') || 'mountain';
+ chart_type = this.root_store.client.is_beta_chart
+ ? LocalStore.get('contract_trade.chart_style') || 'line'
+ : LocalStore.get('contract_trade.chart_type') || 'mountain';
prev_chart_type = '';
prev_granularity = null;
@@ -57,6 +60,7 @@ export default class ContractTradeStore extends BaseStore {
updateChartType: action.bound,
updateGranularity: action.bound,
markers_array: computed,
+ filtered_contracts: computed,
addContract: action.bound,
removeContract: action.bound,
accountSwitchListener: action.bound,
@@ -198,15 +202,23 @@ export default class ContractTradeStore extends BaseStore {
}
updateChartType(type) {
- LocalStore.set('contract_trade.chart_type', type);
+ if (this.root_store.client.is_beta_chart) {
+ LocalStore.set('contract_trade.chart_style', type);
+ } else {
+ LocalStore.set('contract_trade.chart_type', type);
+ }
this.chart_type = type;
}
updateGranularity(granularity) {
- const tick_chart_types = ['mountain', 'line', 'colored_line', 'spline', 'baseline'];
+ const tick_chart_types = this.root_store.client.is_beta_chart
+ ? ['line', 'candles', 'hollow', 'ohlc']
+ : ['mountain', 'line', 'colored_line', 'spline', 'baseline'];
+
if (granularity === 0 && tick_chart_types.indexOf(this.chart_type) === -1) {
- this.chart_type = 'mountain';
+ this.chart_type = this.root_store.client.is_beta_chart ? 'line' : 'mountain';
}
+
LocalStore.set('contract_trade.granularity', granularity);
this.granularity = granularity;
if (this.granularity === 0) {
@@ -293,6 +305,10 @@ export default class ContractTradeStore extends BaseStore {
);
}
+ get filtered_contracts() {
+ return this.applicable_contracts();
+ }
+
get markers_array() {
let markers = [];
const { contract_type: trade_type } = JSON.parse(sessionStorage.getItem('trade_store')) || {};
@@ -300,13 +316,18 @@ export default class ContractTradeStore extends BaseStore {
.map(c => c.marker)
.filter(m => m)
.map(m => toJS(m));
- if (markers.length) {
- markers[getLastContractMarkerIndex(markers)].is_last_contract = true;
+
+ if (!this.root_store.client.is_beta_chart) {
+ if (markers.length) {
+ markers[getLastContractMarkerIndex(markers)].is_last_contract = true;
+ }
}
const { current_spot_time, entry_tick_time, exit_tick_time } = this.last_contract.contract_info || {};
+
const should_show_poc_barriers =
(entry_tick_time && entry_tick_time !== current_spot_time) ||
(exit_tick_time && current_spot_time <= exit_tick_time);
+
const { accumulators_high_barrier, accumulators_low_barrier, barrier_spot_distance, proposal_prev_spot_time } =
(isAccumulatorContractOpen(this.last_contract.contract_info) &&
should_show_poc_barriers &&
@@ -315,22 +336,39 @@ export default class ContractTradeStore extends BaseStore {
this.accumulator_barriers_data ||
{};
if (trade_type === 'accumulator' && proposal_prev_spot_time && accumulators_high_barrier) {
- markers.push({
- type: 'TickContract',
- contract_info: {
- accu_barriers_difference: barrier_spot_distance && {
- top: `+${barrier_spot_distance}`,
- bottom: `-${barrier_spot_distance}`,
- font: isMobile() ? '10px IBM Plex Sans' : '14px IBM Plex Sans',
+ if (this.root_store.client.is_beta_chart) {
+ const is_open = isAccumulatorContractOpen(this.last_contract.contract_info);
+ markers.push(
+ getAccumulatorMarkers({
+ high_barrier: accumulators_high_barrier,
+ low_barrier: accumulators_low_barrier,
+ barrier_spot_distance,
+ prev_epoch: proposal_prev_spot_time,
+ has_crossed_accu_barriers: this.has_crossed_accu_barriers,
+ is_dark_theme: this.root_store.ui.is_dark_mode_on,
+ contract_info: is_open ? this.last_contract.contract_info : {},
+ is_accumulator_trade_without_contract: !is_open || !entry_tick_time,
+ })
+ );
+ }
+ if (!this.root_store.client.is_beta_chart) {
+ markers.push({
+ type: 'TickContract',
+ contract_info: {
+ accu_barriers_difference: barrier_spot_distance && {
+ top: `+${barrier_spot_distance}`,
+ bottom: `-${barrier_spot_distance}`,
+ font: isMobile() ? '10px IBM Plex Sans' : '14px IBM Plex Sans',
+ },
+ has_crossed_accu_barriers: this.has_crossed_accu_barriers,
+ is_accumulator_trade_without_contract:
+ !isAccumulatorContractOpen(this.last_contract.contract_info) || !entry_tick_time,
},
- has_crossed_accu_barriers: this.has_crossed_accu_barriers,
- is_accumulator_trade_without_contract:
- !isAccumulatorContractOpen(this.last_contract.contract_info) || !entry_tick_time,
- },
- key: 'dtrader_accumulator_barriers',
- price_array: [accumulators_high_barrier, accumulators_low_barrier],
- epoch_array: [proposal_prev_spot_time],
- });
+ key: 'dtrader_accumulator_barriers',
+ price_array: [accumulators_high_barrier, accumulators_low_barrier],
+ epoch_array: [proposal_prev_spot_time],
+ });
+ }
}
return markers;
}
@@ -353,15 +391,21 @@ export default class ContractTradeStore extends BaseStore {
return;
}
+ const is_last_contract = contract_id === this.last_contract.contract_id;
+
const contract = new ContractStore(this.root_store, { contract_id });
- contract.populateConfig({
- date_start: start_time,
- barrier,
- contract_type,
- longcode,
- underlying,
- limit_order,
- });
+
+ contract.populateConfig(
+ {
+ date_start: start_time,
+ barrier,
+ contract_type,
+ longcode,
+ underlying,
+ limit_order,
+ },
+ is_last_contract
+ );
this.contracts.push(contract);
this.contracts_map[contract_id] = contract;
@@ -400,7 +444,9 @@ export default class ContractTradeStore extends BaseStore {
if (response.proposal_open_contract) {
const contract_id = +response.proposal_open_contract.contract_id;
const contract = this.contracts_map[contract_id];
- contract.populateConfig(response.proposal_open_contract);
+ const is_last_contract = contract_id === this.last_contract.contract_id;
+ contract.populateConfig(response.proposal_open_contract, is_last_contract);
+
if (response.proposal_open_contract.is_sold) {
this.root_store.notifications.removeNotificationMessage(switch_to_tick_chart);
contract.cacheProposalOpenContractResponse(response);
diff --git a/packages/p2p/src/translations/th.json b/packages/p2p/src/translations/th.json
index 1129bd418342..9d683f2177b2 100644
--- a/packages/p2p/src/translations/th.json
+++ b/packages/p2p/src/translations/th.json
@@ -163,7 +163,7 @@
"1678804253": "ซื้อ {{ currency }}",
"1685888862": "เกิดข้อผิดพลาดภายใน",
"1691540875": "แก้ไขวิธีการชำระเงิน",
- "1699829275": "Cannot upload a file over 5MB",
+ "1699829275": "ไม่สามารถอัปโหลดไฟล์ขนาดเกิน 5MB",
"1703154819": "คุณกำลังแก้ไขโฆษณาเพื่อขาย <0>{{ target_amount }} {{ target_currency }}0>...",
"1721422292": "แสดงชื่อจริงของฉัน",
"1734661732": "ยอดคงเหลือ DP2P ของคุณคือ {{ dp2p_balance }}",
@@ -196,7 +196,7 @@
"2040110829": "เพิ่มขีดจำกัดวงเงินของฉัน",
"2060873863": "คำสั่งซื้อของคุณ {{order_id}} เสร็จสมบูรณ์แล้ว",
"2063890788": "ยกเลิกแล้ว",
- "2064304887": "We accept JPG, PDF, or PNG (up to 5MB).",
+ "2064304887": "เรายอมรับ JPG PDF หรือ PNG (สูงสุด 5MB)",
"2091671594": "สถานะ",
"2096014107": "นำมาใช้งาน",
"2104905634": "ยังไม่มีใครแนะนำเทรดเดอร์รายนี้เลย",
diff --git a/packages/reports/build/webpack.config.js b/packages/reports/build/webpack.config.js
index 1f931b337157..324718b45093 100644
--- a/packages/reports/build/webpack.config.js
+++ b/packages/reports/build/webpack.config.js
@@ -43,7 +43,6 @@ module.exports = function (env) {
'@deriv/shared': '@deriv/shared',
'@deriv/components': '@deriv/components',
'@deriv/translations': '@deriv/translations',
- '@deriv/deriv-charts': '@deriv/deriv-charts',
'@deriv/analytics': '@deriv/analytics',
},
/^@deriv\/shared\/.+$/,
diff --git a/packages/shared/src/utils/contract/contract.tsx b/packages/shared/src/utils/contract/contract.tsx
index 78367c1f5096..d414cd2d84f5 100644
--- a/packages/shared/src/utils/contract/contract.tsx
+++ b/packages/shared/src/utils/contract/contract.tsx
@@ -75,6 +75,8 @@ export const isAccumulatorContractOpen = (contract_info: TContractInfo = {}) =>
export const isMultiplierContract = (contract_type = '') => /MULT/i.test(contract_type);
+export const isTouchContract = (contract_type: string) => /TOUCH/i.test(contract_type);
+
export const isTurbosContract = (contract_type = '') => /TURBOS/i.test(contract_type);
export const isVanillaContract = (contract_type = '') => /VANILLA/i.test(contract_type);
diff --git a/packages/stores/src/mockStore.ts b/packages/stores/src/mockStore.ts
index 791978d00cd4..56844f2a1112 100644
--- a/packages/stores/src/mockStore.ts
+++ b/packages/stores/src/mockStore.ts
@@ -272,6 +272,8 @@ const mock = (): TStores & { is_mock: boolean } => {
real_account_creation_unlock_date: '',
has_any_real_account: false,
setPrevAccountType: jest.fn(),
+ prev_account_type: 'demo',
+ is_beta_chart: true,
setLoginInformation: jest.fn(),
init: jest.fn(),
setLoginId: jest.fn(),
diff --git a/packages/stores/types.ts b/packages/stores/types.ts
index dee3157a6bc6..43072269f195 100644
--- a/packages/stores/types.ts
+++ b/packages/stores/types.ts
@@ -507,6 +507,8 @@ type TClientStore = {
setFinancialAndTradingAssessment: (
payload: SetFinancialAssessmentRequest
) => Promise;
+ prev_account_type: string;
+ is_beta_chart: boolean;
};
type TCommonStoreError = {
diff --git a/packages/trader/build/webpack.config.js b/packages/trader/build/webpack.config.js
index 8a6b22981c89..fd630df2b694 100644
--- a/packages/trader/build/webpack.config.js
+++ b/packages/trader/build/webpack.config.js
@@ -44,10 +44,10 @@ module.exports = function (env) {
'@deriv/shared': '@deriv/shared',
'@deriv/components': '@deriv/components',
'@deriv/translations': '@deriv/translations',
- '@deriv/deriv-charts': '@deriv/deriv-charts',
'@deriv/account': '@deriv/account',
'@deriv/reports': '@deriv/reports',
'@deriv/analytics': '@deriv/analytics',
+ '@deriv/deriv-charts': '@deriv/deriv-charts',
},
/^@deriv\/shared\/.+$/,
/^@deriv\/components\/.+$/,
diff --git a/packages/trader/package.json b/packages/trader/package.json
index 97bfaed9bf79..3d73f9ecefdb 100644
--- a/packages/trader/package.json
+++ b/packages/trader/package.json
@@ -35,11 +35,11 @@
"devDependencies": {
"@babel/eslint-parser": "^7.17.0",
"@babel/preset-react": "^7.16.7",
- "@types/lodash.debounce": "^4.0.7",
"@testing-library/jest-dom": "^5.12.0",
"@testing-library/react": "^12.0.0",
"@testing-library/react-hooks": "^7.0.2",
"@testing-library/user-event": "^13.5.0",
+ "@types/lodash.debounce": "^4.0.7",
"@types/react": "^18.0.7",
"@types/react-dom": "^18.0.0",
"babel-loader": "^8.1.0",
@@ -65,12 +65,12 @@
"jsdom-global": "^2.1.1",
"mini-css-extract-plugin": "^1.3.4",
"mock-local-storage": "^1.1.8",
- "sass": "^1.62.1",
"postcss-loader": "^6.2.1",
"postcss-preset-env": "^7.4.3",
"postcss-scss": "^4.0.6",
"react-svg-loader": "^3.0.3",
"resolve-url-loader": "^3.1.2",
+ "sass": "^1.62.1",
"sass-loader": "^12.6.0",
"sass-resources-loader": "^2.1.1",
"stylelint-formatter-pretty": "^2.1.1",
@@ -90,6 +90,7 @@
"@deriv/api-types": "^1.0.118",
"@deriv/hooks": "^1.0.0",
"@deriv/deriv-charts": "1.4.0",
+ "@deriv/deriv-charts-beta": "npm:@deriv/deriv-charts@^2.0.0-beta.14",
"@deriv/reports": "^1.0.0",
"@deriv/shared": "^1.0.0",
"@deriv/stores": "^1.0.0",
@@ -98,6 +99,7 @@
"classnames": "^2.2.6",
"extend": "^3.0.2",
"formik": "^2.1.4",
+ "framer-motion": "^6.5.1",
"lodash.debounce": "^4.0.8",
"lodash.throttle": "^4.1.1",
"mobx": "^6.6.1",
@@ -110,7 +112,6 @@
"react-content-loader": "^6.2.0",
"react-dom": "^17.0.2",
"react-loadable": "^5.5.0",
- "framer-motion": "^6.5.1",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"react-transition-group": "4.4.2"
diff --git a/packages/trader/src/Modules/Contract/Components/InfoBox/info-box-longcode.tsx b/packages/trader/src/Modules/Contract/Components/InfoBox/info-box-longcode.tsx
index 411d3db56b60..05d36d0de2f2 100644
--- a/packages/trader/src/Modules/Contract/Components/InfoBox/info-box-longcode.tsx
+++ b/packages/trader/src/Modules/Contract/Components/InfoBox/info-box-longcode.tsx
@@ -10,7 +10,8 @@ const InfoBoxLongcode = ({ contract_info }: TInfoBoxLongcode) => {
const max_longcode_length = isMobile() ? 47 : 150;
const [is_collapsed, setIsCollapsed] = React.useState(true);
- const handleToggle = () => {
+ const handleToggle = (ev: React.MouseEvent) => {
+ ev.preventDefault();
setIsCollapsed(!is_collapsed);
};
diff --git a/packages/trader/src/Modules/Contract/Containers/contract-replay-widget.jsx b/packages/trader/src/Modules/Contract/Containers/contract-replay-widget.jsx
index a264cc08533b..9396435ce7dc 100644
--- a/packages/trader/src/Modules/Contract/Containers/contract-replay-widget.jsx
+++ b/packages/trader/src/Modules/Contract/Containers/contract-replay-widget.jsx
@@ -39,5 +39,8 @@ export const InfoBoxWidget = observer(() => {
});
// Chart widgets passed into SmartCharts
-export const ChartTopWidgets = () => } is_title_enabled={false} />;
+export const ChartTopWidgets = () => {
+ const { client } = useStore();
+ return } is_title_enabled={false} is_beta_chart={client.is_beta_chart} />;
+};
export const ChartBottomWidgets = () => } />;
diff --git a/packages/trader/src/Modules/Contract/Containers/contract-replay.jsx b/packages/trader/src/Modules/Contract/Containers/contract-replay.jsx
index ee9624c56174..c57529d967c4 100644
--- a/packages/trader/src/Modules/Contract/Containers/contract-replay.jsx
+++ b/packages/trader/src/Modules/Contract/Containers/contract-replay.jsx
@@ -15,6 +15,7 @@ import {
getContractTypeFeatureFlag,
getDurationPeriod,
getDurationUnitText,
+ getEndTime,
getPlatformRedirect,
isAccumulatorContract,
isDesktop,
@@ -32,16 +33,18 @@ import { useFeatureFlags } from '@deriv/hooks';
import ChartLoader from 'App/Components/Elements/chart-loader';
import ContractDrawer from 'App/Components/Elements/ContractDrawer';
import UnsupportedContractModal from 'App/Components/Elements/Modals/UnsupportedContractModal';
-import { SmartChart } from 'Modules/SmartChart';
+import SmartChartSwitcher from '../../Trading/Containers/smart-chart-switcher.jsx';
import { ChartBottomWidgets, ChartTopWidgets, DigitsWidget, InfoBoxWidget } from './contract-replay-widget.jsx';
import ChartMarker from 'Modules/SmartChart/Components/Markers/marker.jsx';
import DelayedAccuBarriersMarker from 'Modules/SmartChart/Components/Markers/delayed-accu-barriers-marker';
import allMarkers from 'Modules/SmartChart/Components/all-markers.jsx';
+import ChartMarkerBeta from 'Modules/SmartChartBeta/Components/Markers/marker.jsx';
import { observer, useStore } from '@deriv/stores';
import { useTraderStore } from 'Stores/useTraderStores';
const ContractReplay = observer(({ contract_id }) => {
const { common, contract_replay, ui } = useStore();
+ const [swipe_index, setSwipeIndex] = React.useState(0);
const { contract_store } = contract_replay;
const {
is_market_closed,
@@ -89,6 +92,10 @@ const ContractReplay = observer(({ contract_id }) => {
}
}, [is_trade_type_disabled, is_visible, onClickClose]);
+ const onChangeSwipeableIndex = index => {
+ setSwipeIndex(index);
+ };
+
if (!contract_info.underlying) return null;
const is_accumulator = isAccumulatorContract(contract_info.contract_type);
@@ -176,7 +183,11 @@ const ContractReplay = observer(({ contract_id }) => {
{is_digit_contract ? (
-
+
@@ -206,7 +217,7 @@ export default ContractReplay;
const ReplayChart = observer(({ is_accumulator_contract }) => {
const trade = useTraderStore();
- const { contract_replay, common, ui } = useStore();
+ const { contract_replay, client, common, ui } = useStore();
const { contract_store, chart_state, chartStateChange, margin } = contract_replay;
const {
accumulator_previous_spot_time,
@@ -214,6 +225,7 @@ const ReplayChart = observer(({ is_accumulator_contract }) => {
marker: accumulators_barriers_marker,
is_digit_contract,
barriers_array,
+ getContractsArray,
markers_array,
contract_info,
} = contract_store;
@@ -241,8 +253,9 @@ const ReplayChart = observer(({ is_accumulator_contract }) => {
const scroll_to_epoch = allow_scroll_to_epoch ? contract_config.scroll_to_epoch : undefined;
const all_ticks = audit_details ? audit_details.all_ticks : [];
const { wsForget, wsSubscribe, wsSendRequest, wsForgetStream } = trade;
+ const { is_beta_chart } = client;
- const accu_barriers_marker_component = allMarkers[accumulators_barriers_marker?.type];
+ const accu_barriers_marker_component = !is_beta_chart ? allMarkers[accumulators_barriers_marker?.type] : undefined;
const isBottomWidgetVisible = () => {
return isDesktop() && is_digit_contract;
@@ -255,6 +268,9 @@ const ReplayChart = observer(({ is_accumulator_contract }) => {
};
if (isMobile()) {
+ if (is_beta_chart) {
+ chart_margin.top = 48;
+ }
chart_margin.bottom = 48;
}
@@ -262,8 +278,12 @@ const ReplayChart = observer(({ is_accumulator_contract }) => {
};
const prev_start_epoch = usePrevious(start_epoch);
+ const has_ended = !!getEndTime(contract_info);
+
return (
- {
}
shouldDrawTicksFromContractInfo={is_accumulator_contract}
contractInfo={contract_info}
+ contracts_array={getContractsArray()}
+ isLive={!has_ended}
+ startWithDataFitMode={true}
>
- {markers_array.map(({ content_config, marker_config, react_key }) => (
-
- ))}
- {is_accumulator_contract && !!markers_array && (
+ {is_beta_chart &&
+ markers_array.map(({ content_config, marker_config, react_key }) => (
+
+ ))}
+ {!is_beta_chart &&
+ markers_array.map(({ content_config, marker_config, react_key }) => (
+
+ ))}
+ {!is_beta_chart && is_accumulator_contract && !!markers_array && (
{
{...accumulators_barriers_marker}
/>
)}
-
+
);
});
diff --git a/packages/trader/src/Modules/SmartChart/Components/Markers/accumulators-chart-elements.tsx b/packages/trader/src/Modules/SmartChart/Components/Markers/accumulators-chart-elements.tsx
index 7b5ae0171dcd..e22dbfdc0dd0 100644
--- a/packages/trader/src/Modules/SmartChart/Components/Markers/accumulators-chart-elements.tsx
+++ b/packages/trader/src/Modules/SmartChart/Components/Markers/accumulators-chart-elements.tsx
@@ -2,6 +2,7 @@ import { filterByContractType } from 'App/Components/Elements/PositionsDrawer/he
import React from 'react';
import AccumulatorsProfitLossTooltip from './accumulators-profit-loss-tooltip';
import { ProposalOpenContract } from '@deriv/api-types';
+import ChartMarkerBeta from 'Modules/SmartChartBeta/Components/Markers/marker.jsx';
import ChartMarker from './marker.jsx';
type TPositions = {
@@ -19,6 +20,7 @@ type TAccumulatorsChartElements = {
has_crossed_accu_barriers: boolean;
should_show_profit_text: React.ComponentProps['should_show_profit_text'];
symbol: string;
+ is_beta_chart?: boolean;
};
const AccumulatorsChartElements = ({
@@ -28,12 +30,15 @@ const AccumulatorsChartElements = ({
has_crossed_accu_barriers,
should_show_profit_text,
symbol,
+ is_beta_chart,
}: TAccumulatorsChartElements) => {
const accumulators_positions = all_positions.filter(
({ contract_info }) =>
contract_info && symbol === contract_info.underlying && filterByContractType(contract_info, 'accumulator')
);
+ const ChartMarkerComponent = is_beta_chart ? ChartMarkerBeta : ChartMarker;
+
return (
{!!accumulators_positions.length &&
@@ -42,10 +47,11 @@ const AccumulatorsChartElements = ({
key={contract_info.contract_id}
{...contract_info}
should_show_profit_text={should_show_profit_text}
+ is_beta_chart={is_beta_chart}
/>
))}
{has_crossed_accu_barriers && !!current_spot_time && (
-
type TAccumulatorsProfitLossText = Pick &
TProposalOpenContractProfit & {
className?: string;
+ is_beta_chart?: boolean;
};
const ACTIONS = {
@@ -25,6 +27,7 @@ const AccumulatorsProfitLossText = ({
currency,
className = 'sc-accumulators-profit-loss-text',
profit,
+ is_beta_chart,
}: TAccumulatorsProfitLossText) => {
const [is_fading_in, setIsFadingIn] = React.useState(false);
const [is_sliding, setIsSliding] = React.useState(false);
@@ -114,8 +117,14 @@ const AccumulatorsProfitLossText = ({
}
};
+ const FastMarkerComponent = is_beta_chart ? FastMarkerBeta : FastMarker;
+
return (
-
+
{getCurrencyDisplayCode(currency)}
-
+
);
};
diff --git a/packages/trader/src/Modules/SmartChart/Components/Markers/accumulators-profit-loss-tooltip.tsx b/packages/trader/src/Modules/SmartChart/Components/Markers/accumulators-profit-loss-tooltip.tsx
index a8a685ae56d6..eeef26cde243 100644
--- a/packages/trader/src/Modules/SmartChart/Components/Markers/accumulators-profit-loss-tooltip.tsx
+++ b/packages/trader/src/Modules/SmartChart/Components/Markers/accumulators-profit-loss-tooltip.tsx
@@ -4,6 +4,7 @@ import { CSSTransition } from 'react-transition-group';
import { Money, Text } from '@deriv/components';
import { localize } from '@deriv/translations';
import { FastMarker } from 'Modules/SmartChart';
+import { FastMarkerBeta } from 'Modules/SmartChartBeta';
import AccumulatorsProfitLossText from './accumulators-profit-loss-text';
import { ProposalOpenContract } from '@deriv/api-types';
import { isMobile } from '@deriv/shared';
@@ -18,6 +19,7 @@ type TAccumulatorsProfitLossText = React.ComponentProps {
const [is_tooltip_open, setIsTooltipOpen] = React.useState(false);
const won = profit >= 0;
@@ -95,10 +98,13 @@ const AccumulatorsProfitLossTooltip = ({
current_spot={current_spot}
current_spot_time={current_spot_time}
profit={profit}
+ is_beta_chart={is_beta_chart}
/>
);
+
+ const FastMarkerComponent = is_beta_chart ? FastMarkerBeta : FastMarker;
return is_sold && exit_tick_time ? (
-
+
setIsTooltipOpen(true)}
@@ -124,7 +130,7 @@ const AccumulatorsProfitLossTooltip = ({
-
+
) : null;
};
diff --git a/packages/trader/src/Modules/SmartChart/Components/top-widgets.jsx b/packages/trader/src/Modules/SmartChart/Components/top-widgets.jsx
index 1f6425d37b61..65017cd67ea7 100644
--- a/packages/trader/src/Modules/SmartChart/Components/top-widgets.jsx
+++ b/packages/trader/src/Modules/SmartChart/Components/top-widgets.jsx
@@ -5,14 +5,17 @@ import { DesktopWrapper, MobileWrapper, Text } from '@deriv/components';
import { localize } from '@deriv/translations';
import { isEnded, isAccumulatorContract, isDigitContract } from '@deriv/shared';
import { ChartTitle } from 'Modules/SmartChart';
+import { ChartTitleBeta } from 'Modules/SmartChartBeta';
import BuyToastNotification from './buy-toast-notification';
import { observer, useStore } from '@deriv/stores';
const RecentTradeInfo = observer(() => {
- const { contract_trade } = useStore();
- const { granularity, markers_array } = contract_trade;
+ const { contract_trade, client } = useStore();
+ const { granularity, filtered_contracts, markers_array } = contract_trade;
- const latest_tick_contract = markers_array[markers_array.length - 1];
+ const latest_tick_contract = client.is_beta_chart
+ ? filtered_contracts[filtered_contracts.length - 1]
+ : markers_array[markers_array.length - 1];
if (
!latest_tick_contract ||
!latest_tick_contract.contract_info.tick_stream ||
@@ -42,9 +45,11 @@ const TopWidgets = ({
open_market,
open,
is_digits_widget_active,
+ is_beta_chart,
}) => {
+ const ChartTitleComponent = is_beta_chart ? ChartTitleBeta : ChartTitle;
const ChartTitleLocal = (
-