diff --git a/src/botPage/bot/TradeEngine/Proposal.js b/src/botPage/bot/TradeEngine/Proposal.js index b9c70de348..75eacbf972 100644 --- a/src/botPage/bot/TradeEngine/Proposal.js +++ b/src/botPage/bot/TradeEngine/Proposal.js @@ -34,8 +34,8 @@ export default Engine => } return { - id : toBuy.id, - askPrice: toBuy.ask_price, + proposal: toBuy, + currency: this.tradeOption.currency, }; } renewProposalsOnPurchase() { @@ -138,10 +138,12 @@ export default Engine => return ( isNotEqual('duration') || + isNotEqual('duration_unit') || isNotEqual('amount') || isNotEqual('prediction') || isNotEqual('barrierOffset') || - isNotEqual('secondBarrierOffset') + isNotEqual('secondBarrierOffset') || + isNotEqual('symbol') ); } }; diff --git a/src/botPage/bot/TradeEngine/Purchase.js b/src/botPage/bot/TradeEngine/Purchase.js index e4d89c2d9c..64562faf24 100644 --- a/src/botPage/bot/TradeEngine/Purchase.js +++ b/src/botPage/bot/TradeEngine/Purchase.js @@ -14,20 +14,25 @@ export default Engine => return Promise.resolve(); } - const { id, askPrice } = this.selectProposal(contractType); - + const { currency, proposal } = this.selectProposal(contractType); const onSuccess = r => { const { buy } = r; + contractStatus({ id : 'contract.purchase_recieved', data: buy.transaction_id, + proposal, + currency, }); this.subscribeToOpenContract(buy.contract_id); this.store.dispatch(purchaseSuccessful()); this.renewProposalsOnPurchase(); + delayIndex = 0; + notify('info', `${translate('Bought')}: ${buy.longcode} (${translate('ID')}: ${buy.transaction_id})`); + info({ accountID : this.accountInfo.loginid, totalRuns : this.updateAndReturnTotalRuns(), @@ -37,13 +42,17 @@ export default Engine => }); }; - const action = () => this.api.buyContract(id, askPrice); this.isSold = false; + contractStatus({ id : 'contract.purchase_sent', - data: askPrice, + data: proposal.ask_price, + proposal, + currency, }); + const action = () => this.api.buyContract(proposal.id, proposal.ask_price); + if (!this.options.timeMachineEnabled) { return doUntilDone(action).then(onSuccess); } diff --git a/src/botPage/view/TradeInfoPanel/TradeTable.js b/src/botPage/view/TradeInfoPanel/TradeTable.js index 1ea1347b36..1d8eff86c2 100644 --- a/src/botPage/view/TradeInfoPanel/TradeTable.js +++ b/src/botPage/view/TradeInfoPanel/TradeTable.js @@ -3,7 +3,7 @@ import json2csv from 'json2csv'; import React, { Component } from 'react'; import ReactDataGrid from 'react-data-grid'; import { observer as globalObserver } from '../../../common/utils/observer'; -import { appendRow, updateRow, saveAs } from '../shared'; +import { appendRow, updateRow, saveAs, ticksService } from '../shared'; import { translate } from '../../../common/i18n'; import { roundBalance } from '../../common/tools'; import * as style from '../style'; @@ -57,6 +57,27 @@ export default class TradeTable extends Component { { key: 'contract_status', width: 70, resizable: true, name: translate('Status'), formatter: StatusFormat }, ]; } + + static getTradeObject(pipSizes, contract) { + const symbolPipSize = pipSizes[contract.underlying]; + const tradeObj = { + ...contract, + reference: `${contract.transaction_ids.buy}`, + buy_price: roundBalance({ balance: contract.buy_price, currency: contract.currency }), + timestamp: getTimestamp(contract.date_start), + }; + + if (contract.entry_tick) { + tradeObj.entry_tick = (+contract.entry_tick).toFixed(symbolPipSize); + } + + if (contract.exit_tick) { + tradeObj.exit_tick = (+contract.exit_tick).toFixed(symbolPipSize); + } + + return tradeObj; + } + componentWillMount() { const { api } = this.props; @@ -66,44 +87,50 @@ export default class TradeTable extends Component { this.export(); } }); + globalObserver.register('summary.clear', () => { this.setState({ [this.props.accountID]: { ...this.state.initial } }); globalObserver.emit('summary.disable_clear'); }); + globalObserver.register('bot.stop', () => { const accountData = this.state[this.props.accountID]; if (accountData && accountData.rows.length > 0) { globalObserver.emit('summary.enable_clear'); } }); - globalObserver.register('bot.contract', info => { - if (!info) { + + globalObserver.register('bot.contract', contract => { + if (!contract) { return; } - const timestamp = getTimestamp(info.date_start); - const tradeObj = { reference: info.transaction_ids.buy, ...info, timestamp }; - const { accountID } = tradeObj; - - const trade = { - ...tradeObj, - profit : getProfit(tradeObj), - contract_status : translate('Pending'), - contract_settled: false, - }; - const accountStat = this.getAccountStat(accountID); - - const { rows } = accountStat; - const prevRowIndex = rows.findIndex(t => t.reference === trade.reference); - - if (trade.is_expired && trade.is_sold && !trade.exit_tick) trade.exit_tick = '-'; + ticksService.requestPipSizes().then(pipSizes => { + const tradeObj = TradeTable.getTradeObject(pipSizes, contract); + const trade = { + ...tradeObj, + profit : getProfit(tradeObj), + contract_status : translate('Pending'), + contract_settled: false, + }; + + const { accountID } = tradeObj; + const accountStat = this.getAccountStat(accountID); + const { rows } = accountStat; + const prevRowIndex = rows.findIndex(t => t.reference === trade.reference); + + if (trade.is_expired && trade.is_sold && !trade.exit_tick) { + trade.exit_tick = '-'; + } - if (prevRowIndex >= 0) { - this.setState({ [accountID]: updateRow(prevRowIndex, trade, accountStat) }); - } else { - this.setState({ [accountID]: appendRow(trade, accountStat) }); - } + if (prevRowIndex >= 0) { + this.setState({ [accountID]: updateRow(prevRowIndex, trade, accountStat) }); + } else { + this.setState({ [accountID]: appendRow(trade, accountStat) }); + } + }); }); + globalObserver.register('contract.settled', contract => { const contractID = contract.contract_id; this.settleContract(api, contractID); @@ -139,40 +166,47 @@ export default class TradeTable extends Component { refreshContract(api, contractID) { return api.getContractInfo(contractID).then(r => { - const contract = r.proposal_open_contract; - const timestamp = getTimestamp(contract.date_start); - const tradeObj = { reference: contract.transaction_ids.buy, ...contract, timestamp }; - const { accountID } = this.props; - - const trade = { - ...tradeObj, - profit: getProfit(tradeObj), - }; - - if (trade.is_expired && trade.is_sold && !trade.exit_tick) trade.exit_tick = '-'; - - const { id } = this.state[accountID]; - const rows = this.state[accountID].rows.slice(); - const updatedRows = rows.map(row => { - const { reference } = row; - if (reference === trade.reference) { - return { - contract_status : translate('Settled'), - contract_settled: true, - reference, - ...trade, - }; + ticksService.requestPipSizes().then(pipSizes => { + const contract = r.proposal_open_contract; + const tradeObj = TradeTable.getTradeObject(pipSizes, contract); + const trade = { + ...tradeObj, + profit: getProfit(tradeObj), + }; + + if (trade.is_expired && trade.is_sold && !trade.exit_tick) { + trade.exit_tick = '-'; } - return row; + + const { accountID } = this.props; + const { id } = this.state[accountID]; + const rows = this.state[accountID].rows.slice(); + + const updatedRows = rows.map(row => { + const { reference } = row; + + if (reference === trade.reference) { + return { + contract_status : translate('Settled'), + contract_settled: true, + reference, + ...trade, + }; + } + return row; + }); + + this.setState({ [accountID]: { id, rows: updatedRows } }); }); - this.setState({ [accountID]: { id, rows: updatedRows } }); }); } + rowGetter(i) { const { accountID } = this.props; const { rows } = this.state[accountID]; return rows[rows.length - 1 - i]; } + export() { const { accountID } = this.props; diff --git a/src/botPage/view/TradeInfoPanel/index.js b/src/botPage/view/TradeInfoPanel/index.js index 125828dc4c..b9e7f02f18 100644 --- a/src/botPage/view/TradeInfoPanel/index.js +++ b/src/botPage/view/TradeInfoPanel/index.js @@ -5,6 +5,7 @@ import Summary from './Summary'; import TradeTable from './TradeTable'; import RunButton from './RunButton'; import ClearButton from './ClearButton'; +import { roundBalance } from '../../common/tools'; const resetAnimation = () => { $('.circle-wrapper') @@ -71,7 +72,14 @@ class AnimateTrade extends Component { if (contractStatus.id === 'contract.purchase_sent') { resetAnimation(); activateStage(0); - this.setState({ buy_price: contractStatus.data, stopMessage: this.indicatorMessages.stopping }); + + this.setState({ + buy_price: roundBalance({ + balance : contractStatus.proposal.ask_price, + currency: contractStatus.currency, + }), + stopMessage: this.indicatorMessages.stopping, + }); } else if (contractStatus.id === 'contract.purchase_recieved') { $('.line').addClass('active'); activateStage(1); @@ -81,6 +89,7 @@ class AnimateTrade extends Component { activateStage(2); this.setState({ sell_id: contractStatus.data, stopMessage: this.indicatorMessages.stopped }); } + activateStage(contractStatus.id); } render() { diff --git a/src/botPage/view/View.js b/src/botPage/view/View.js index d54b3df8ce..9dd37c1b1e 100644 --- a/src/botPage/view/View.js +++ b/src/botPage/view/View.js @@ -18,8 +18,8 @@ import Tour from './tour'; import TradeInfoPanel from './TradeInfoPanel'; import { showDialog } from '../bot/tools'; import Elevio from '../../common/elevio'; -import { updateConfigCurrencies } from '../common/const'; -import { roundBalance, isVirtual } from '../common/tools'; +import config, { updateConfigCurrencies } from '../common/const'; +import { isVirtual } from '../common/tools'; import { logoutAllTokens, getOAuthURL, @@ -66,8 +66,16 @@ api.events.on('balance', response => { balance: { balance: b, currency }, } = response; - const balance = (+roundBalance({ currency, balance: b })).toLocaleString(getLanguage().replace('_', '-')); - $('.topMenuBalance').text(`${balance} ${currency}`); + const elTopMenuBalances = document.querySelectorAll('.topMenuBalance'); + const localString = getLanguage().replace('_', '-'); + const balance = (+b).toLocaleString(localString, { + minimumFractionDigits: config.lists.CRYPTO_CURRENCIES.includes(currency) ? 8 : 2, + }); + + elTopMenuBalances.forEach(elTopMenuBalance => { + const element = elTopMenuBalance; + element.textContent = `${balance} ${currency}`; + }); }); const addBalanceForToken = token => { diff --git a/src/botPage/view/blockly/blocks/shared.js b/src/botPage/view/blockly/blocks/shared.js index f0151c106f..8170874564 100644 --- a/src/botPage/view/blockly/blocks/shared.js +++ b/src/botPage/view/blockly/blocks/shared.js @@ -404,7 +404,7 @@ export const getPredictionForContracts = (contracts, selectedContractType) => { if (contract && contract.last_digit_range) { predictionRange.push(...contract.last_digit_range); } else { - predictionRange.push(0); + predictionRange.push(1, 2, 3, 4, 5); } } return predictionRange; diff --git a/src/botPage/view/blockly/customBlockly.js b/src/botPage/view/blockly/customBlockly.js index db1fa80e52..01f238e1ea 100644 --- a/src/botPage/view/blockly/customBlockly.js +++ b/src/botPage/view/blockly/customBlockly.js @@ -358,3 +358,21 @@ Blockly.Toolbox.TreeNode.prototype.onClick_ = function(_e) { } this.updateRow(); }; + +/** + * Preload all the audio files so that they play quickly when asked for. + * @package + */ +Blockly.WorkspaceAudio.prototype.preload = function() { + for (var name in this.SOUNDS_) { + var sound = this.SOUNDS_[name]; + sound.volume = 0.01; + sound.play().catch(function() {}); + sound.pause(); + // iOS can only process one sound at a time. Trying to load more than one + // corrupts the earlier ones. Just load one and leave the others uncached. + if (goog.userAgent.IPAD || goog.userAgent.IPHONE) { + break; + } + } +}; diff --git a/src/botPage/view/index.js b/src/botPage/view/index.js index 113250da51..4daed78625 100644 --- a/src/botPage/view/index.js +++ b/src/botPage/view/index.js @@ -5,6 +5,7 @@ import View from './View'; import '../../common/binary-ui/dropdown'; import Elevio from '../../common/elevio'; import GTM from '../../common/gtm'; +import { isProduction } from '../../common/utils/tools'; $.ajaxSetup({ cache: false, @@ -14,7 +15,7 @@ $.ajaxSetup({ window._trackJs = { token : '346262e7ffef497d85874322fff3bbf8', application: 'binary-bot', - enabled : window.location.hostname !== 'localhost', + enabled : isProduction(), console : { display: false, }, diff --git a/static/css/_panel.scss b/static/css/_panel.scss index e4b7dcd604..b1fd3b21a0 100644 --- a/static/css/_panel.scss +++ b/static/css/_panel.scss @@ -59,9 +59,14 @@ $disabled-color: #F2F2F2; font-size: 11px; color: lightgray; } + #current-trade-status{ + margin-top: 3.5em; + } .stage { display: inline-block; margin: 0 8.68% 0 8.68%; + vertical-align: top; + max-width: 120px; .stage-tooltip .triangle { margin-top: 0.7em; margin-left: 50%; @@ -75,11 +80,13 @@ $disabled-color: #F2F2F2; } .stage-tooltip.top { margin-bottom: 0.5em; + margin-top: -2.5em; + position: absolute; } .stage-tooltip p { font-size: 11px; text-align: center; - margin-top: -0.9em; + margin-top: -0.91em; padding: 0.5em; border-radius: 0.5em; background-color: #fef1cf; @@ -101,6 +108,7 @@ $disabled-color: #F2F2F2; .stage-label { text-align: center; font-size: 11px; + min-height: 24px; } .circle-wrapper { width: $static-circle-diameter; diff --git a/static/xml/toolbox.xml b/static/xml/toolbox.xml index d19db21264..a5aff41962 100644 --- a/static/xml/toolbox.xml +++ b/static/xml/toolbox.xml @@ -241,7 +241,6 @@ -