- {show_label && (
+ {show_label && !is_value_hidden && (
-
-
-
- {toMoment(+spot_epoch).format('HH:mm:ss')}
-
-
+ {spot_epoch && (
+
+
+
+ {toMoment(+spot_epoch).format('HH:mm:ss')}
+
+
+ )}
)}
-
+
);
};
MarkerSpotLabel.defaultProps = {
align_label: 'top',
+ is_value_hidden: false,
};
MarkerSpotLabel.propTypes = {
align_label: PropTypes.oneOf(['top', 'bottom']),
has_hover_toggle: PropTypes.bool,
+ is_value_hidden: PropTypes.bool,
spot_className: PropTypes.string,
spot_count: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
spot_epoch: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
diff --git a/packages/core/src/Constants/contract.js b/packages/core/src/Constants/contract.js
index 61cbb5c4d08b..578efc82df9e 100644
--- a/packages/core/src/Constants/contract.js
+++ b/packages/core/src/Constants/contract.js
@@ -169,6 +169,11 @@ export const getUnsupportedContracts = () => ({
});
export const getSupportedContracts = is_high_low => ({
+ ACCU: {
+ button_name: localize('Buy'),
+ name: localize('Accumulator'),
+ position: 'top',
+ },
CALL: {
name: is_high_low ? localize('Higher') : localize('Rise'),
position: 'top',
@@ -224,9 +229,9 @@ export const getContractConfig = is_high_low => ({
...getUnsupportedContracts(),
});
-export const getContractTypeDisplay = (type, is_high_low = false) => {
- // console.log(getContractConfig(is_high_low)[type]);
- return getContractConfig(is_high_low)[type] ? getContractConfig(is_high_low)[type.toUpperCase()].name : '';
+export const getContractTypeDisplay = (type, is_high_low = false, show_button_name = false) => {
+ const contract_config = getContractConfig(is_high_low)[type];
+ return (show_button_name && contract_config.button_name) || contract_config.name || '';
};
export const getContractTypePosition = (type, is_high_low = false) =>
diff --git a/packages/core/src/Stores/Helpers/chart-marker-helpers.js b/packages/core/src/Stores/Helpers/chart-marker-helpers.js
index c62a63672c52..86f17feeb097 100644
--- a/packages/core/src/Stores/Helpers/chart-marker-helpers.js
+++ b/packages/core/src/Stores/Helpers/chart-marker-helpers.js
@@ -2,6 +2,7 @@ import extend from 'extend';
import {
formatMoney,
getEndTime,
+ isAccumulatorContract,
isDesktop,
isDigitContract,
isMobile,
@@ -21,8 +22,11 @@ const createMarkerConfig = (marker_type, x, y, content_config) =>
content_config,
});
-export const getSpotCount = (contract_info, spot_count) =>
- isDigitContract(contract_info.contract_type) ? spot_count + 1 : spot_count;
+export const getSpotCount = (contract_info, spot_count) => {
+ if (isDigitContract(contract_info.contract_type)) return spot_count + 1;
+ if (isAccumulatorContract(contract_info.contract_type)) return null;
+ return spot_count;
+};
// -------------------- Lines --------------------
export const createMarkerEndTime = contract_info => {
@@ -104,8 +108,9 @@ export const createMarkerSpotExit = (contract_info, tick, idx) => {
align_label: should_show_profit_label ? 'middle' : align_label,
spot_count,
spot_profit:
- should_show_profit_label &&
- `${formatMoney(contract_info.currency, contract_info.profit, true)} ${contract_info.currency}`,
+ (should_show_profit_label &&
+ `${formatMoney(contract_info.currency, contract_info.profit, true)} ${contract_info.currency}`) ||
+ '',
}
: {};
@@ -113,13 +118,16 @@ export const createMarkerSpotExit = (contract_info, tick, idx) => {
};
export const createMarkerSpotMiddle = (contract_info, tick, idx) => {
+ const is_accumulator = isAccumulatorContract(contract_info.contract_type);
const spot_count = getSpotCount(contract_info, idx);
const spot = tick.tick_display_value;
+ const spot_epoch = is_accumulator ? '' : `${tick.epoch}`;
const marker_config = createMarkerConfig(MARKER_TYPES_CONFIG.SPOT_MIDDLE.type, +tick.epoch, +spot, {
spot_value: `${spot}`,
- spot_epoch: `${tick.epoch}`,
+ spot_epoch,
align_label: tick.align_label,
+ is_value_hidden: is_accumulator,
spot_count,
});
marker_config.type = `${marker_config.type}_${idx}`;
diff --git a/packages/core/src/Stores/Helpers/chart-markers.js b/packages/core/src/Stores/Helpers/chart-markers.js
index 02ebb3291ab4..87e9475f0a1b 100644
--- a/packages/core/src/Stores/Helpers/chart-markers.js
+++ b/packages/core/src/Stores/Helpers/chart-markers.js
@@ -7,11 +7,15 @@ import {
createMarkerSpotMiddle,
getSpotCount,
} from './chart-marker-helpers';
-import { getEndTime, unique } from '@deriv/shared';
+import { getEndTime, isAccumulatorContract, unique } from '@deriv/shared';
import { MARKER_TYPES_CONFIG } from '../Constants/markers';
import { getChartType } from './logic';
export const createChartMarkers = contract_info => {
+ const { contract_type, status, tick_stream } = contract_info;
+ const should_show_10_last_ticks =
+ isAccumulatorContract(contract_type) && status === 'open' && tick_stream.length === 10;
+
let markers = [];
if (contract_info) {
const end_time = getEndTime(contract_info);
@@ -24,9 +28,11 @@ export const createChartMarkers = contract_info => {
const spot_markers = Object.keys(marker_spots).map(type => marker_spots[type](contract_info));
markers.push(...spot_markers);
}
- const line_markers = Object.keys(marker_lines).map(type => marker_lines[type](contract_info));
- markers.push(...line_markers);
-
+ if (!should_show_10_last_ticks) {
+ // don't draw start/end lines if only 10 last ticks are displayed
+ const line_markers = Object.keys(marker_lines).map(type => marker_lines[type](contract_info));
+ markers.push(...line_markers);
+ }
markers = markers.filter(m => !!m);
}
markers.forEach(marker => {
@@ -61,15 +67,31 @@ const addLabelAlignment = (tick, idx, arr) => {
};
const createTickMarkers = contract_info => {
- const tick_stream = unique(contract_info.tick_stream, 'epoch').map(addLabelAlignment);
+ const is_accumulator = isAccumulatorContract(contract_info.contract_type);
+ const is_contract_closed = contract_info.status && contract_info.exit_tick_time;
+ const available_ticks = (is_accumulator && contract_info.audit_details?.all_ticks) || contract_info.tick_stream;
+ const tick_stream = unique(available_ticks, 'epoch').map(addLabelAlignment);
const result = [];
+ if (is_contract_closed && is_accumulator) {
+ tick_stream.length = tick_stream.findIndex(tick => tick.epoch === contract_info.exit_tick_time) + 1;
+ }
+
tick_stream.forEach((tick, idx) => {
- const is_entry_spot = idx === 0 && +tick.epoch !== contract_info.exit_tick_time;
- const is_middle_spot = idx > 0 && +tick.epoch !== +contract_info.exit_tick_time;
- const is_exit_spot =
- +tick.epoch === +contract_info.exit_tick_time ||
- getSpotCount(contract_info, idx) === contract_info.tick_count;
+ const isEntrySpot = _tick => +_tick.epoch === contract_info.entry_tick_time;
+ const is_entry_spot =
+ +tick.epoch !== contract_info.exit_tick_time && (is_accumulator ? isEntrySpot(tick) : idx === 0);
+ // accumulators entry spot will be missing from tick_stream when contract is lasting for longer than 10 ticks
+ const entry_spot_index = is_accumulator ? tick_stream.findIndex(isEntrySpot) : 0;
+ const is_middle_spot = idx > entry_spot_index && +tick.epoch !== +contract_info.exit_tick_time;
+ const isExitSpot = (_tick, _idx) =>
+ +_tick.epoch === +contract_info.exit_tick_time ||
+ getSpotCount(contract_info, _idx) === contract_info.tick_count;
+ const is_exit_spot = isExitSpot(tick, idx);
+ const exit_spot_index = tick_stream.findIndex(isExitSpot);
+ const is_current_last_spot = idx === tick_stream.length - 1;
+ const is_preexit_spot = idx === exit_spot_index - 1 || idx === tick_stream.length - 2;
+ const has_accumulator_bold_marker = is_accumulator && (is_preexit_spot || is_current_last_spot || is_exit_spot);
let marker_config;
if (is_entry_spot) {
@@ -80,6 +102,12 @@ const createTickMarkers = contract_info => {
tick.align_label = 'top'; // force exit spot label to be 'top' to avoid overlapping
marker_config = createMarkerSpotExit(contract_info, tick, idx);
}
+ if (has_accumulator_bold_marker || (is_accumulator && is_middle_spot)) {
+ const spot_className = marker_config.content_config.spot_className;
+ marker_config.content_config.spot_className = `${spot_className} ${spot_className}--accumulator${
+ has_accumulator_bold_marker ? '-bold' : '-small'
+ }`;
+ }
if (marker_config) {
result.push(marker_config);
diff --git a/packages/core/src/Stores/Helpers/logic.js b/packages/core/src/Stores/Helpers/logic.js
index c6b563500fa9..bc492458a41e 100644
--- a/packages/core/src/Stores/Helpers/logic.js
+++ b/packages/core/src/Stores/Helpers/logic.js
@@ -1,5 +1,5 @@
import moment from 'moment';
-import { isEmptyObject, getEndTime } from '@deriv/shared';
+import { isAccumulatorContract, isEmptyObject, getEndTime } from '@deriv/shared';
import ServerTime from '../../_common/base/server_time';
export const getChartConfig = contract_info => {
@@ -8,13 +8,21 @@ export const getChartConfig = contract_info => {
const end = getEndTime(contract_info);
const granularity = getChartGranularity(start, end || null);
const chart_type = getChartType(start, end || null);
-
+ 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
+ const first_tick_epoch =
+ is_accumulator_contract && !!contract_info.tick_stream?.length && contract_info.tick_stream[0].epoch;
+ const should_show_10_last_ticks =
+ is_accumulator_contract && contract_info.status === 'open' && contract_info.tick_stream.length === 10;
+ 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,
granularity: contract_info.tick_count ? 0 : granularity,
end_epoch: end,
- start_epoch: start,
- scroll_to_epoch: contract_info.purchase_time,
+ start_epoch,
+ scroll_to_epoch,
};
};
diff --git a/packages/core/src/Stores/chart-barrier-store.js b/packages/core/src/Stores/chart-barrier-store.js
index 971159f520e5..c7b4d9b424ea 100644
--- a/packages/core/src/Stores/chart-barrier-store.js
+++ b/packages/core/src/Stores/chart-barrier-store.js
@@ -20,7 +20,12 @@ export class ChartBarrierStore {
onChartBarrierChange;
- constructor(high_barrier, low_barrier, onChartBarrierChange = null, { color, line_style, not_draggable } = {}) {
+ constructor(
+ high_barrier,
+ low_barrier,
+ onChartBarrierChange = null,
+ { color, hideBarrierLine, line_style, not_draggable, shade } = {}
+ ) {
makeObservable(this, {
color: observable,
lineStyle: observable,
@@ -43,6 +48,8 @@ export class ChartBarrierStore {
});
this.color = color;
+ this.hideBarrierLine = hideBarrierLine;
+ this.shade = shade;
this.lineStyle = line_style || BARRIER_LINE_STYLES.SOLID;
this.onChange = this.onBarrierChange;
@@ -50,9 +57,9 @@ export class ChartBarrierStore {
this.onChartBarrierChange =
typeof onChartBarrierChange === 'function' ? onChartBarrierChange.bind(this) : () => {};
- this.high = +high_barrier || 0; // 0 to follow the price
+ this.high = high_barrier || 0; // 0 to follow the price
if (low_barrier) {
- this.low = +low_barrier;
+ this.low = low_barrier;
}
this.shade = this.default_shade;
@@ -67,8 +74,8 @@ export class ChartBarrierStore {
if (!isFromChart) {
this.relative = /^[+-]/.test(high);
}
- this.high = +high || undefined;
- this.low = +low || undefined;
+ this.high = high || undefined;
+ this.low = low || undefined;
}
updateBarrierShade(should_display, contract_type) {
diff --git a/packages/core/src/Stores/contract-store.js b/packages/core/src/Stores/contract-store.js
index a9a8d5369250..1d74f25a598b 100644
--- a/packages/core/src/Stores/contract-store.js
+++ b/packages/core/src/Stores/contract-store.js
@@ -2,6 +2,7 @@ import { action, extendObservable, observable, toJS, makeObservable } from 'mobx
import {
isEnded,
isEqualObject,
+ isAccumulatorContract,
isMultiplierContract,
isDigitContract,
getDigitInfo,
@@ -11,6 +12,7 @@ import {
getContractValidationRules,
BARRIER_COLORS,
BARRIER_LINE_STYLES,
+ DEFAULT_SHADES,
isBarrierSupported,
getEndTime,
} from '@deriv/shared';
@@ -121,8 +123,9 @@ export default class ContractStore extends BaseStore {
}
const is_multiplier = isMultiplierContract(this.contract_info.contract_type);
+ const is_accumulator = isAccumulatorContract(this.contract_info.contract_type);
- if (is_multiplier && contract_info.contract_id && contract_info.limit_order) {
+ if ((is_accumulator || is_multiplier) && contract_info.contract_id && contract_info.limit_order) {
this.populateContractUpdateConfig(this.contract_info);
}
}
@@ -184,12 +187,17 @@ export default class ContractStore extends BaseStore {
if (contract_info) {
const { contract_type, barrier, entry_spot, high_barrier, low_barrier } = contract_info;
- if (isBarrierSupported(contract_type) && (barrier || high_barrier || entry_spot)) {
+ if (
+ isBarrierSupported(contract_type) &&
+ (barrier || high_barrier || (entry_spot && !isAccumulatorContract(contract_type)))
+ ) {
// create barrier only when it's available in response
const main_barrier = new ChartBarrierStore(barrier || high_barrier || entry_spot, low_barrier, null, {
color: is_dark_mode ? BARRIER_COLORS.DARK_GRAY : BARRIER_COLORS.GRAY,
- line_style: BARRIER_LINE_STYLES.SOLID,
+ line_style: !isAccumulatorContract(contract_type) && BARRIER_LINE_STYLES.SOLID,
not_draggable: true,
+ hideBarrierLine: isAccumulatorContract(contract_type),
+ shade: isAccumulatorContract(contract_type) && DEFAULT_SHADES['2'],
});
main_barrier.updateBarrierShade(true, contract_type);
@@ -211,7 +219,9 @@ export default class ContractStore extends BaseStore {
}
updateLimitOrder() {
- const limit_order = getLimitOrder(this);
+ const limit_order = isAccumulatorContract(this.contract_info.contract_type)
+ ? { take_profit: getLimitOrder(this).take_profit }
+ : getLimitOrder(this);
WS.contractUpdate(this.contract_id, limit_order).then(response => {
if (response.error) {
@@ -255,8 +265,13 @@ function calculate_marker(contract_info) {
high_barrier,
low_barrier,
} = contract_info;
- const ticks_epoch_array = tick_stream ? tick_stream.map(t => t.epoch) : [];
+ const is_accumulator_contract = isAccumulatorContract(contract_type);
const is_digit_contract = isDigitContract(contract_type);
+ const ticks_epochs =
+ (is_accumulator_contract && tick_stream?.length === 10
+ ? [entry_tick_time, ...tick_stream.map(t => t.epoch).slice(1)]
+ : tick_stream?.map(t => t.epoch)) || [];
+ const ticks_epoch_array = tick_stream ? ticks_epochs : [];
// window.ci = toJS(contract_info);
@@ -266,7 +281,7 @@ function calculate_marker(contract_info) {
} else if (+barrier_count === 1 && barrier) {
price_array = [+barrier];
} else if (+barrier_count === 2 && high_barrier && low_barrier) {
- price_array = [+low_barrier, +high_barrier];
+ price_array = [+high_barrier, +low_barrier];
}
if (entry_tick) {
diff --git a/packages/core/src/Stores/contract-trade-store.js b/packages/core/src/Stores/contract-trade-store.js
index 3e651aa2e2dd..7d5d47c2fbc0 100644
--- a/packages/core/src/Stores/contract-trade-store.js
+++ b/packages/core/src/Stores/contract-trade-store.js
@@ -7,9 +7,11 @@ import {
switch_to_tick_chart,
isCallPut,
getContractTypesConfig,
+ isAccumulatorContract,
+ extractInfoFromShortcode,
+ getAccumulatorBarriers,
} from '@deriv/shared';
import ContractStore from './contract-store';
-
import BaseStore from './base-store';
export default class ContractTradeStore extends BaseStore {
@@ -22,16 +24,24 @@ 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';
+ prev_chart_type = '';
+ prev_granularity = null;
+
+ // Accumulator barriers data:
+ accumulator_barriers_data = {};
constructor(root_store) {
super({ root_store });
makeObservable(this, {
+ accumulator_barriers_data: observable.ref,
+ clearAccumulatorBarriersData: action.bound,
contracts: observable.shallow,
has_error: observable,
error_message: observable,
granularity: observable,
chart_type: observable,
+ updateAccumulatorBarriersAndSpots: action.bound,
updateChartType: action.bound,
updateGranularity: action.bound,
markers_array: computed,
@@ -39,10 +49,14 @@ export default class ContractTradeStore extends BaseStore {
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,
+ savePreviousChartMode: action.bound,
+ should_highlight_current_spot: computed,
});
this.root_store = root_store;
@@ -53,6 +67,56 @@ export default class ContractTradeStore extends BaseStore {
// ----- Actions -----
// -------------------
+ clearAccumulatorBarriersData() {
+ this.accumulator_barriers_data = {};
+ }
+
+ updateAccumulatorBarriersAndSpots({
+ previous_spot,
+ previous_spot_time,
+ current_spot,
+ current_spot_time,
+ pip_size,
+ symbol,
+ tick_size_barrier,
+ current_symbol,
+ }) {
+ const { shortcode } =
+ this.root_store.portfolio.active_positions.find(
+ ({ type, contract_info: _contract_info }) =>
+ isAccumulatorContract(type) && _contract_info.underlying === current_symbol
+ )?.contract_info || {};
+
+ const updateAccumulatorBarriers = new_tick_size_barrier => {
+ const { high_barrier: accumulators_high_barrier, low_barrier: accumulators_low_barrier } =
+ getAccumulatorBarriers(new_tick_size_barrier, previous_spot, pip_size);
+ this.accumulator_barriers_data = {
+ ...this.accumulator_barriers_data,
+ [symbol]: {
+ ...this.accumulator_barriers_data[symbol],
+ accumulators_high_barrier,
+ accumulators_low_barrier,
+ current_spot,
+ current_spot_time,
+ previous_spot,
+ previous_spot_time,
+ },
+ };
+ };
+
+ if (shortcode) {
+ // has an ongoing ACCU contract
+ const result = extractInfoFromShortcode(shortcode);
+ const contract_tick_size_barrier = +result.tick_size_barrier;
+ if (contract_tick_size_barrier) {
+ updateAccumulatorBarriers(contract_tick_size_barrier);
+ }
+ } else {
+ // has no open ACCU contracts
+ updateAccumulatorBarriers(tick_size_barrier);
+ }
+ }
+
updateChartType(type) {
LocalStore.set('contract_trade.chart_type', type);
this.chart_type = type;
@@ -70,6 +134,11 @@ export default class ContractTradeStore extends BaseStore {
}
}
+ savePreviousChartMode(chart_type, granularity) {
+ this.prev_chart_type = chart_type;
+ this.prev_granularity = granularity;
+ }
+
applicable_contracts = () => {
const { symbol: underlying, contract_type: trade_type } = JSON.parse(localStorage.getItem('trade_store')) || {};
@@ -107,14 +176,41 @@ export default class ContractTradeStore extends BaseStore {
});
};
+ get should_highlight_current_spot() {
+ const { symbol } = JSON.parse(localStorage.getItem('trade_store')) || {};
+ const { accumulators_high_barrier, accumulators_low_barrier, current_spot } =
+ this.accumulator_barriers_data[symbol] || {};
+ return !!(
+ current_spot &&
+ accumulators_high_barrier &&
+ accumulators_low_barrier &&
+ (current_spot > accumulators_high_barrier || current_spot < accumulators_low_barrier)
+ );
+ }
+
get markers_array() {
- const markers = this.applicable_contracts()
+ let markers = [];
+ const { contract_type: trade_type, symbol } = JSON.parse(localStorage.getItem('trade_store')) || {};
+ markers = this.applicable_contracts()
.map(c => c.marker)
.filter(m => m)
.map(m => toJS(m));
if (markers.length) {
markers[markers.length - 1].is_last_contract = true;
}
+ const { accumulators_high_barrier, accumulators_low_barrier, previous_spot_time } =
+ this.accumulator_barriers_data[symbol] || {};
+ if (trade_type === 'accumulator' && previous_spot_time && accumulators_high_barrier) {
+ markers.push({
+ type: 'TickContract',
+ contract_info: {
+ is_accumulators_trade_without_contract: this.last_contract.contract_info?.status !== 'open',
+ },
+ key: 'accumulators_barriers_without_contract',
+ price_array: [accumulators_high_barrier, accumulators_low_barrier],
+ epoch_array: [previous_spot_time],
+ });
+ }
return markers;
}
diff --git a/packages/core/src/Stores/portfolio-store.js b/packages/core/src/Stores/portfolio-store.js
index 859e7f07cad8..66a70c44b9cc 100644
--- a/packages/core/src/Stores/portfolio-store.js
+++ b/packages/core/src/Stores/portfolio-store.js
@@ -84,6 +84,7 @@ export default class PortfolioStore extends BaseStore {
updateBarrierColor: action,
updateLimitOrderBarriers: action,
setContractType: action,
+ is_accumulator: computed,
is_multiplier: computed,
});
@@ -239,8 +240,11 @@ export default class PortfolioStore extends BaseStore {
const profit_loss = +proposal.profit;
// fix for missing barrier and entry_spot in proposal_open_contract API response, only re-assign if valid
- if (proposal.barrier) portfolio_position.barrier = +proposal.barrier;
- if (proposal.entry_spot) portfolio_position.entry_spot = +proposal.entry_spot;
+ Object.entries(proposal).forEach(([key, value]) => {
+ if (key === 'barrier' || key === 'high_barrier' || key === 'low_barrier' || key === 'entry_spot') {
+ portfolio_position[key] = +value;
+ }
+ });
// store contract proposal details that require modifiers
portfolio_position.indicative = new_indicative;
@@ -576,6 +580,10 @@ export default class PortfolioStore extends BaseStore {
this.contract_type = contract_type;
}
+ get is_accumulator() {
+ return this.contract_type === 'accumulator';
+ }
+
get is_multiplier() {
return this.contract_type === 'multiplier';
}
diff --git a/packages/core/src/public/images/common/static_images/accumulators_manual_desktop.mp4 b/packages/core/src/public/images/common/static_images/accumulators_manual_desktop.mp4
new file mode 100644
index 000000000000..ce930ea98757
Binary files /dev/null and b/packages/core/src/public/images/common/static_images/accumulators_manual_desktop.mp4 differ
diff --git a/packages/core/src/public/images/common/static_images/accumulators_manual_desktop.webm b/packages/core/src/public/images/common/static_images/accumulators_manual_desktop.webm
new file mode 100644
index 000000000000..bb041ad11b77
Binary files /dev/null and b/packages/core/src/public/images/common/static_images/accumulators_manual_desktop.webm differ
diff --git a/packages/core/src/public/images/common/static_images/accumulators_manual_desktop_dark.mp4 b/packages/core/src/public/images/common/static_images/accumulators_manual_desktop_dark.mp4
new file mode 100644
index 000000000000..751b279bb09f
Binary files /dev/null and b/packages/core/src/public/images/common/static_images/accumulators_manual_desktop_dark.mp4 differ
diff --git a/packages/core/src/public/images/common/static_images/accumulators_manual_desktop_dark.webm b/packages/core/src/public/images/common/static_images/accumulators_manual_desktop_dark.webm
new file mode 100644
index 000000000000..b058d574c698
Binary files /dev/null and b/packages/core/src/public/images/common/static_images/accumulators_manual_desktop_dark.webm differ
diff --git a/packages/core/src/public/images/common/static_images/accumulators_manual_mobile.mp4 b/packages/core/src/public/images/common/static_images/accumulators_manual_mobile.mp4
new file mode 100644
index 000000000000..9fbb0e7c8086
Binary files /dev/null and b/packages/core/src/public/images/common/static_images/accumulators_manual_mobile.mp4 differ
diff --git a/packages/core/src/public/images/common/static_images/accumulators_manual_mobile.webm b/packages/core/src/public/images/common/static_images/accumulators_manual_mobile.webm
new file mode 100644
index 000000000000..fb7a3be64ac7
Binary files /dev/null and b/packages/core/src/public/images/common/static_images/accumulators_manual_mobile.webm differ
diff --git a/packages/core/src/public/images/common/static_images/accumulators_manual_mobile_dark.mp4 b/packages/core/src/public/images/common/static_images/accumulators_manual_mobile_dark.mp4
new file mode 100644
index 000000000000..aa7bca082f43
Binary files /dev/null and b/packages/core/src/public/images/common/static_images/accumulators_manual_mobile_dark.mp4 differ
diff --git a/packages/core/src/public/images/common/static_images/accumulators_manual_mobile_dark.webm b/packages/core/src/public/images/common/static_images/accumulators_manual_mobile_dark.webm
new file mode 100644
index 000000000000..fff471c31d54
Binary files /dev/null and b/packages/core/src/public/images/common/static_images/accumulators_manual_mobile_dark.webm differ
diff --git a/packages/reports/src/Components/market-symbol-icon-row.jsx b/packages/reports/src/Components/market-symbol-icon-row.jsx
index 56ceb4b2c852..2a72cd29ac1f 100644
--- a/packages/reports/src/Components/market-symbol-icon-row.jsx
+++ b/packages/reports/src/Components/market-symbol-icon-row.jsx
@@ -5,7 +5,14 @@ import { extractInfoFromShortcode, isHighLow } from '@deriv/shared';
import { Icon, Popover, IconTradeTypes } from '@deriv/components';
import { getMarketName, getTradeTypeName } from '../Helpers/market-underlying';
-const MarketSymbolIconRow = ({ icon, payload, show_description, should_show_multiplier = true, is_vanilla }) => {
+const MarketSymbolIconRow = ({
+ icon,
+ payload,
+ show_description,
+ should_show_accumulator = true,
+ should_show_multiplier = true,
+ is_vanilla,
+}) => {
const should_show_category_icon = typeof payload.shortcode === 'string';
const info_from_shortcode = extractInfoFromShortcode(payload.shortcode);
const is_high_low = isHighLow({ shortcode_info: info_from_shortcode });
@@ -63,6 +70,9 @@ const MarketSymbolIconRow = ({ icon, payload, show_description, should_show_mult
{should_show_multiplier && info_from_shortcode.multiplier && (
x{info_from_shortcode.multiplier}
)}
+ {should_show_accumulator && info_from_shortcode.growth_rate && (
+
{info_from_shortcode.growth_rate * 100}%
+ )}
);
} else if (['deposit', 'hold', 'release', 'withdrawal', 'transfer'].includes(payload.action_type)) {
@@ -92,12 +102,12 @@ const MarketSymbolIconRow = ({ icon, payload, show_description, should_show_mult
};
MarketSymbolIconRow.propTypes = {
- action: PropTypes.string,
icon: PropTypes.node,
+ is_vanilla: PropTypes.bool,
payload: PropTypes.object,
show_description: PropTypes.bool,
should_show_multiplier: PropTypes.bool,
- is_vanilla: PropTypes.bool,
+ should_show_accumulator: PropTypes.bool,
};
export default MarketSymbolIconRow;
diff --git a/packages/reports/src/Constants/data-table-constants.js b/packages/reports/src/Constants/data-table-constants.js
index 99f9aedc33d7..b99e76688e99 100644
--- a/packages/reports/src/Constants/data-table-constants.js
+++ b/packages/reports/src/Constants/data-table-constants.js
@@ -1,7 +1,13 @@
import classNames from 'classnames';
import React from 'react';
-import { Icon, Label, Money, ContractCard, Popover } from '@deriv/components';
-import { isMobile, getCurrencyDisplayCode, getTotalProfit, shouldShowCancellation } from '@deriv/shared';
+import { Icon, Label, Money, ContractCard, ContractCardSell, Popover } from '@deriv/components';
+import {
+ isMobile,
+ getCurrencyDisplayCode,
+ getTotalProfit,
+ shouldShowCancellation,
+ getGrowthRatePercentage,
+} from '@deriv/shared';
import { localize, Localize } from '@deriv/translations';
import ProgressSliderStream from '../Containers/progress-slider-stream.jsx';
@@ -38,11 +44,9 @@ export const getStatementTableColumnsTemplate = currency => [
key: 'icon',
title: isMobile() ? '' : localize('Type'),
col_index: 'icon',
- renderCellContent: ({ cell_value, passthrough, row_obj }) => {
+ renderCellContent: ({ passthrough, row_obj }) => {
const icon = passthrough.isTopUp(row_obj) ? 'icCashierTopUp' : null;
- return (
-
;
},
},
{
@@ -101,11 +105,11 @@ export const getProfitTableColumnsTemplate = (currency, items_count) => [
key: 'icon',
title: isMobile() ? '' : localize('Type'),
col_index: 'action_type',
- renderCellContent: ({ cell_value, row_obj, is_footer }) => {
+ renderCellContent: ({ row_obj, is_footer }) => {
if (is_footer) {
return localize('Profit/loss on the last {{item_count}} contracts', { item_count: items_count });
}
- return
;
},
},
{
@@ -165,14 +169,14 @@ export const getProfitTableColumnsTemplate = (currency, items_count) => [
];
export const getOpenPositionsColumnsTemplate = currency => [
{
+ key: 'icon',
title: isMobile() ? '' : localize('Type'),
col_index: 'type',
- renderCellContent: ({ cell_value, row_obj, is_footer, is_vanilla }) => {
+ renderCellContent: ({ row_obj, is_footer, is_vanilla }) => {
if (is_footer) return localize('Total');
return (