Skip to content
This repository was archived by the owner on Feb 22, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5b28f4a
Revamp Limits-dialog to enforce self-exclusion limits
Apr 25, 2019
0c9a052
Create Limits-dialog only when required, and catch uncaught Promise r…
Apr 25, 2019
208a52d
Create rules for panel elements
Apr 25, 2019
12b7020
Set node to v10.15.3 and force npm to 6.9.0
Apr 25, 2019
d6b66ca
Merge pull request #1447 from aaron-binary/set-travis-version
Apr 25, 2019
d32688e
Merge branch 'dev' of github.com:binary-com/binary-bot into mx-limits…
Apr 25, 2019
784e06e
Pass maxLoss to TradeEngine
Apr 25, 2019
61c9cdc
Update jQuery
Apr 26, 2019
55fc8a0
Merge pull request #1448 from aaron-binary/mx-limits-dialog
ashkanx Apr 26, 2019
f3cf675
Merge branch 'dev' into update-jquery
Apr 26, 2019
050a040
Merge pull request #1450 from aaron-binary/update-jquery
ashkanx Apr 26, 2019
7302bc3
Merge pull request #1452 from binary-com/dev
ashkanx Apr 26, 2019
1e7cee6
added auto refresh of contracts
Apr 26, 2019
e90db0d
Merge branch 'dev' into refresh-contracts
khalidibrahimio Apr 26, 2019
ed5551d
Set node to v10.15.3 and force npm to 6.9.0
Apr 25, 2019
a9b2ee3
added auto refresh of contracts
Apr 26, 2019
4a07500
Merge branch 'refresh-contracts' of github.com:Khalidxx/binary-bot in…
Apr 29, 2019
05ccace
code cleanup
Apr 29, 2019
2aa1e56
port update
Apr 29, 2019
01bbe73
added auto refresh of contracts
Apr 26, 2019
077b746
code cleanup
Apr 29, 2019
a2672cf
port update
Apr 29, 2019
2560a01
Merge branch 'refresh-contracts' of github.com:Khalidxx/binary-bot in…
khalidibrahimio May 2, 2019
a808528
added contract settled message
khalidibrahimio May 2, 2019
25b5e53
added translate and fixed style
khalidibrahimio May 3, 2019
65cedfb
status color
khalidibrahimio May 6, 2019
bf06c93
Merge pull request #1453 from Khalidxx/refresh-contracts
ashkanx May 6, 2019
a6e0d13
Merge pull request #1481 from binary-com/dev
ashkanx May 7, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
language: node_js
node_js: node
node_js: "10.15.3"
before_install: npm i -g npm@6.9.0
install: npm ci
cache:
directories:
- node_modules
311 changes: 108 additions & 203 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
"i18next-scanner": "1.9.4",
"immutable": "^3.8.2",
"jest": "^24.7.1",
"jquery": "3.2.1",
"jquery": "^3.4.0",
"jquery-ui": "1.12.1",
"jquery-ui-css": "1.11.4",
"js-interpreter": "^1.4.6",
Expand Down
8 changes: 6 additions & 2 deletions src/botPage/bot/TradeEngine/OpenContract.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { roundBalance } from '../../common/tools';
import { doUntilDone } from '../tools';
import { contractStatus, contract as broadcastContract } from '../broadcast';
import { contractStatus, contractSettled, contract as broadcastContract } from '../broadcast';
import { sell, openContractReceived } from './state/actions';

const AFTER_FINISH_TIMEOUT = 5;
Expand All @@ -27,7 +27,9 @@ export default Engine =>
contractStatus({
id : 'contract.sold',
data: contract.transaction_ids.sell,
contract,
});
contractSettled(contract);
this.contractId = '';
this.updateTotals(contract);
if (this.afterPromise) {
Expand Down Expand Up @@ -67,7 +69,9 @@ export default Engine =>
this.unsubscribeOpenContract();

doUntilDone(() => this.api.subscribeToOpenContract(contractId)).then(r => {
({ proposal_open_contract: { id: this.openContractId } } = r);
({
proposal_open_contract: { id: this.openContractId },
} = r);
});
}
resetSubscriptionTimeout(timeout = this.getContractDuration() + AFTER_FINISH_TIMEOUT) {
Expand Down
2 changes: 2 additions & 0 deletions src/botPage/bot/broadcast.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export const contract = c => globalObserver.emit('bot.contract', c);

export const contractStatus = c => globalObserver.emit('contract.status', c);

export const contractSettled = c => globalObserver.emit('contract.settled', c);

export const info = i => globalObserver.emit('bot.info', i);

export const notify = (className, message) => globalObserver.emit('Notify', { className, message, position: 'right' });
194 changes: 135 additions & 59 deletions src/botPage/view/Dialogs/Limits.js
Original file line number Diff line number Diff line change
@@ -1,59 +1,122 @@
import { LiveApi } from 'binary-live-api';
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { translate } from '../../../common/i18n';
import * as style from '../style';
import Dialog from './Dialog';
import { restrictInputCharacter } from '../shared';
import * as style from '../style';
import { getToken } from '../../../common/utils/storageManager';
import { showSpinnerInButton, removeSpinnerInButton, createUrl, translate } from '../../../common/utils/tools';

class LimitsContent extends PureComponent {
constructor() {
super();
this.state = {
error : '',
maxLoss : '',
maxTrades: '',
maxTrades: 0,
maxLosses: null,
};
}

submit() {
const maxLoss = parseFloat(this.state.maxLoss || 0);
const maxTrades = parseInt(this.state.maxTrades || 0);
this.setState({ error: '' });
if (maxTrades <= 0 || maxTrades > 100) {
this.setState({ error: 'Maximum number of trades should be between 1 and 100.' });

const onSave = () => {
this.props.onSave({
maxTrades: this.state.maxTrades,
maxLoss : this.state.maxLosses,
});
};

if (!this.state.maxLosses) {
this.updateMaxLosses()
.then(() => {
onSave();
})
.catch(() => {
this.setState({
error: translate(
'Please set your daily loss limit in the Self-Exclusion Facilities page to allow trading.'
),
});
});
return;
}
if (!maxLoss) {
this.setState({ error: 'Please enter a Maximum Loss amount greater than zero.' });

if (this.state.maxTrades <= 0 || this.state.maxTrades > 100) {
this.setState({ error: translate('Maximum consecutive trades should be between 1 and 100') });
return;
}
this.props.onSave({
maxLoss,
maxTrades,

onSave();
}

updateMaxLosses() {
return new Promise((resolve, reject) => {
const { api } = this.props;
const $startButton = $('#submit-trade-limits');
const initialText = $startButton.text();

showSpinnerInButton($startButton);

api.getSelfExclusion()
.then(response => {
const { max_losses: maxLosses } = response.get_self_exclusion;
let callback;

if (maxLosses) {
this.setState({ maxLosses });
callback = resolve;
} else {
callback = reject;
}

removeSpinnerInButton($startButton, initialText);
callback();
})
.catch(() => {
removeSpinnerInButton($startButton, initialText);
reject();
});
});
}

componentDidMount() {
const cleanupLayout = () => {
this.setState({
maxTrades: '',
maxLoss : '',
maxTrades: 0,
error : '',
});
};

const onDialogOpen = () => {
this.updateMaxLosses().catch(() => {});
};

$('#limits-dialog-component').dialog({
open : onDialogOpen,
close : cleanupLayout,
autoOpen: false,
});
}

onMaxTradeChange(e) {
if (restrictInputCharacter({ input: e.target.value, whitelistRegEx: '^[\\d]*$' })) {
this.setState({ maxTrades: e.target.value });
}
}
onMaxLossChange(e) {
if (restrictInputCharacter({ input: e.target.value, whitelistRegEx: '^\\d*\\.?\\d*$' })) {
this.setState({ maxLoss: e.target.value });

getDailyLossesLimit() {
if (this.state.maxLosses) {
const token = $('.account-id')
.first()
.attr('value');
const tokenObj = getToken(token);
const currency = tokenObj && tokenObj.loginInfo.currency;
return currency ? `${this.state.maxLosses} ${currency}` : `${this.state.maxLosses}`;
}
return translate('Not set');
}

render() {
return (
<form
Expand All @@ -62,65 +125,78 @@ class LimitsContent extends PureComponent {
className="dialog-content"
style={style.content}
>
<div>
<div style={style.inputRow}>
<label style={style.field} htmlFor="limitation-max-trades">
<input
style={style.input}
ref={el => {
this.maxTradesDiv = el;
}}
type="text"
id="limitation-max-trades"
step="1"
maxLength="3"
value={this.state.maxTrades}
onChange={(...args) => this.onMaxTradeChange(...args)}
/>
{translate('Maximum number of trades')}
</label>
</div>
<div style={style.inputRow}>
<label style={style.field} htmlFor="limitation-max-loss">
<input
style={style.input}
ref={el => {
this.maxLossDiv = el;
}}
value={this.state.maxLoss}
type="text"
id="limitation-max-loss"
step="any"
onChange={(...args) => this.onMaxLossChange(...args)}
/>
{translate('Maximum loss amount')}
</label>
</div>
{this.state.error ? <p style={style.error}>{this.state.error}</p> : null}
</div>
<p>
{translate(
'Trade limitations are required by our regulators. Your bot will conclude trading when one or both of the conditions are met.'
'We require you to set trade limitations in compliance with business regulations. Please note that your bot will only stop trading if any or both of the conditions below are met.'
)}
</p>
<div style={style.submitButton}>
<button type="submit">{translate('Start')}</button>
<div className="input-row">
<label>
{translate('Daily limit on losses:')} <strong>{this.getDailyLossesLimit()}</strong>
</label>
<div className="description">
{translate([
'This is the threshold that limits your potential losses for the day in all Binary.com platforms. Once your total loss reaches or exceeds this amount, your bot will stop trading. Please set a value in the [_1]Self-Exclusion Facilities page[_2].',
`<a href="${createUrl({
addLanguage : true,
path : 'user/security/self_exclusionws',
addHtmlExtension: true,
isNonBotPage : true,
})}" target="_blank">`,
'</a>',
])}
</div>
</div>
<div className="input-row">
<label htmlFor="limitation-max-trades">{translate('Maximum consecutive trades')}</label>
<div className="description">
{translate(
'This is the maximum number of trades that you allow your bot to execute for this run.'
)}
</div>
</div>
<div className="input-row">
<input
ref={el => {
this.maxTradesDiv = el;
}}
type="text"
id="limitation-max-trades"
step="1"
maxLength="3"
value={this.state.maxTrades}
onChange={(...args) => this.onMaxTradeChange(...args)}
data-lpignore={true}
/>
</div>
{this.state.error && <p style={style.error}>{this.state.error}</p>}
<div className="input-row last" style={style.submitButton}>
<button id="submit-trade-limits" type="submit">
{translate('Start')}
</button>
</div>
</form>
);
}
static props = {
onSave: PropTypes.func,
api : PropTypes.instanceOf(LiveApi),
};
}

export default class Limits extends Dialog {
constructor() {
constructor(api) {
const onSave = limits => {
this.limitsPromise(limits);
this.close();
};
super('limits-dialog', translate('Trade Limitations'), <LimitsContent onSave={onSave} />, style.dialogLayout);
super(
'limits-dialog',
translate('Trade Limitations'),
<LimitsContent onSave={onSave} api={api} />,
style.dialogLayout
);
this.registerCloseOnOtherDialog();
}
getLimits() {
this.open();
Expand Down
Loading