diff --git a/src/botPage/bot/TradeEngine/Balance.js b/src/botPage/bot/TradeEngine/Balance.js
index 58ea161e25..8730573c2d 100644
--- a/src/botPage/bot/TradeEngine/Balance.js
+++ b/src/botPage/bot/TradeEngine/Balance.js
@@ -1,7 +1,6 @@
import { roundBalance } from '../../common/tools';
import { info } from '../broadcast';
-
-let balanceStr = '';
+import { observer as globalObserver } from '../../../common/utils/observer';
export default Engine =>
class Balance extends Engine {
@@ -11,8 +10,10 @@ export default Engine =>
balance: { balance: b, currency },
} = r;
- this.balance = roundBalance({ currency, balance: b });
- balanceStr = `${this.balance} ${currency}`;
+ const balance = roundBalance({ currency, balance: b });
+ const balanceStr = `${balance} ${currency}`;
+
+ globalObserver.setState({ balance, currency });
info({ accountID: this.accountInfo.loginid, balance: balanceStr });
});
@@ -20,17 +21,19 @@ export default Engine =>
// eslint-disable-next-line class-methods-use-this
getBalance(type) {
const { scope } = this.store.getState();
- let { balance } = this;
+ const currency = globalObserver.getState('currency');
+ let balance = globalObserver.getState('balance');
// Deduct trade `amount` in this scope for correct value in `balance`-block
if (scope === 'BEFORE_PURCHASE') {
balance = roundBalance({
- currency: this.tradeOptions.currency,
- balance : Number(balance) - this.tradeOptions.amount,
+ balance: Number(balance) - this.tradeOptions.amount,
+ currency,
});
- balanceStr = `${balance} ${this.tradeOptions.currency}`;
}
+ const balanceStr = `${balance}`;
+
return type === 'STR' ? balanceStr : Number(balance);
}
};
diff --git a/src/botPage/bot/TradeEngine/index.js b/src/botPage/bot/TradeEngine/index.js
index f93ffbd8ce..a9a2e03ea2 100644
--- a/src/botPage/bot/TradeEngine/index.js
+++ b/src/botPage/bot/TradeEngine/index.js
@@ -118,8 +118,15 @@ export default class TradeEngine extends Balance(Purchase(Sell(OpenContract(Prop
// Only subscribe to balance in browser, not for tests.
if (document) {
- this.api.subscribeToBalance().then(r => {
- this.balance = Number(r.balance.balance);
+ this.api.subscribeToBalance().then(response => {
+ const {
+ balance: { balance, currency },
+ } = response;
+
+ globalObserver.setState({
+ balance: Number(balance),
+ currency,
+ });
resolve();
});
} else {
diff --git a/src/botPage/bot/__tests__/BotApi.js b/src/botPage/bot/__tests__/BotApi.js
index dab0901c31..c9bed14728 100644
--- a/src/botPage/bot/__tests__/BotApi.js
+++ b/src/botPage/bot/__tests__/BotApi.js
@@ -32,6 +32,7 @@ describe('Interface', () => {
currency : 'USD',
duration : 5,
duration_unit: 't',
+ basis : 'stake',
});
watch('before').then(c => {
diff --git a/src/botPage/bot/__tests__/UI.js b/src/botPage/bot/__tests__/UI.js
index d37f3bef43..91a62c8489 100644
--- a/src/botPage/bot/__tests__/UI.js
+++ b/src/botPage/bot/__tests__/UI.js
@@ -38,6 +38,7 @@ expectReturnTrue(
prediction: undefined,
barrierOffset: undefined,
secondBarrierOffset: undefined,
+ basis: 'stake',
});
}
diff --git a/src/botPage/bot/__tests__/tools.js b/src/botPage/bot/__tests__/tools.js
index 1999d2bdf9..9dd018c4bf 100644
--- a/src/botPage/bot/__tests__/tools.js
+++ b/src/botPage/bot/__tests__/tools.js
@@ -15,7 +15,8 @@ export const start = options =>
`
Bot.start({
amount: 1,
- currency: 'USD', ${options || ''}
+ currency: 'USD', ${options || ''},
+ basis: 'stake',
});
`;
diff --git a/src/botPage/bot/tools.js b/src/botPage/bot/tools.js
index d4f535ec5b..2b509e9c58 100644
--- a/src/botPage/bot/tools.js
+++ b/src/botPage/bot/tools.js
@@ -9,7 +9,7 @@ export const tradeOptionToProposal = tradeOption =>
tradeOption.contractTypes.map(type => {
const proposal = {
duration_unit: tradeOption.duration_unit,
- basis : 'stake',
+ basis : tradeOption.basis,
currency : tradeOption.currency,
symbol : tradeOption.symbol,
duration : tradeOption.duration,
diff --git a/src/botPage/common/const.js b/src/botPage/common/const.js
index a35f5888bb..335b0a97da 100644
--- a/src/botPage/common/const.js
+++ b/src/botPage/common/const.js
@@ -8,10 +8,6 @@ const CRYPTO_CURRENCIES = ['BTC', 'ETH', 'LTC', 'BCH'];
const config = {
lists: {
- PAYOUTTYPE: [
- // [translate('Payout'), 'payout'],
- [translate('Stake'), 'stake'],
- ],
CRYPTO_CURRENCIES,
DETAILS: [
[translate('statement'), '1'],
@@ -232,9 +228,9 @@ const config = {
bbResult : [[translate('upper'), '1'], [translate('middle'), '0'], [translate('lower'), '2']],
macdFields: [[translate('Histogram'), '0'], [translate('MACD'), '1'], [translate('Signal'), '2']],
gd : {
- cid: '646610722767-7ivdbunktgtnumj23en9gkecbgtf2ur7.apps.googleusercontent.com',
- aid: 'binarybot-237009',
- api: 'AIzaSyBieTeLip_lVQZUimIuJypU1kJyqOvQRgc',
+ cid: '828416594271-qj2dnf4u2omg1iugangbtsrq6p0a55oc.apps.googleusercontent.com',
+ aid: 'derivbot-248506',
+ api: 'AIzaSyBDYQ7IIgGxM14IeAV5JrtaJNYjxB4A5jo',
},
};
diff --git a/src/botPage/view/View.js b/src/botPage/view/View.js
index b96e79b9d1..01fbc666f8 100644
--- a/src/botPage/view/View.js
+++ b/src/botPage/view/View.js
@@ -76,6 +76,8 @@ api.events.on('balance', response => {
const element = elTopMenuBalance;
element.textContent = `${balance} ${currency}`;
});
+
+ globalObserver.setState({ balance: b, currency });
});
const addBalanceForToken = token => {
diff --git a/src/botPage/view/blockly/blocks/trade/components.js b/src/botPage/view/blockly/blocks/trade/components.js
index a11467343e..a99f248f9b 100644
--- a/src/botPage/view/blockly/blocks/trade/components.js
+++ b/src/botPage/view/blockly/blocks/trade/components.js
@@ -61,11 +61,17 @@ export const duration = block => {
export const payout = block => {
if (!block.getInput('AMOUNT')) {
- block
- .appendValueInput('AMOUNT')
- .setCheck('Number')
- .appendField(`${translate('Stake')}:`)
- .appendField(new Blockly.FieldDropdown(config.lists.CURRENCY), 'CURRENCY_LIST');
+ const amountInput = block.appendValueInput('AMOUNT');
+
+ amountInput.setCheck('Number');
+
+ if (block.type === 'tradeOptions_payout') {
+ amountInput.appendField(`${translate('Payout')}:`);
+ } else {
+ amountInput.appendField(`${translate('Stake')}:`);
+ }
+
+ amountInput.appendField(new Blockly.FieldDropdown(config.lists.CURRENCY), 'CURRENCY_LIST');
}
};
diff --git a/src/botPage/view/blockly/blocks/trade/tradeOptions.js b/src/botPage/view/blockly/blocks/trade/tradeOptions.js
index 83581524c3..aa9b8c2a71 100644
--- a/src/botPage/view/blockly/blocks/trade/tradeOptions.js
+++ b/src/botPage/view/blockly/blocks/trade/tradeOptions.js
@@ -49,7 +49,7 @@ export default () => {
if (!symbol) return;
const getNestedTradeOptions = block => {
- if (block.type === 'tradeOptions') {
+ if (/^tradeOptions/.test(block.type)) {
this.pollForContracts(symbol).then(contracts => {
this.updateBarrierOffsetBlocks(contracts, false, false, [block.id]);
this.applyBarrierHandlebars('BARRIEROFFSETTYPE_LIST', [ev.blockId], true);
@@ -141,7 +141,7 @@ export default () => {
});
},
updatePredictionBlocks(contracts, updateOnly = []) {
- getBlocksByType('tradeOptions').forEach(tradeOptionsBlock => {
+ getBlocksByType(this.type).forEach(tradeOptionsBlock => {
if (tradeOptionsBlock.disabled) return;
if (updateOnly.length && !updateOnly.includes(tradeOptionsBlock.id)) return;
@@ -166,7 +166,7 @@ export default () => {
});
},
updateBarrierOffsetBlocks(contracts, useDefaultType = false, setDefaultValue = false, updateOnly = []) {
- getBlocksByType('tradeOptions').forEach(tradeOptionsBlock => {
+ getBlocksByType(this.type).forEach(tradeOptionsBlock => {
if (tradeOptionsBlock.disabled) return;
if (updateOnly.length && !updateOnly.includes(tradeOptionsBlock.id)) return;
@@ -241,7 +241,7 @@ export default () => {
});
},
updateDurationLists(contracts, useDefaultUnit = false, setMinDuration = false, updateOnly = []) {
- getBlocksByType('tradeOptions').forEach(tradeOptionsBlock => {
+ getBlocksByType(this.type).forEach(tradeOptionsBlock => {
if (tradeOptionsBlock.disabled) return;
if (updateOnly.length && !updateOnly.includes(tradeOptionsBlock.id)) return;
@@ -290,7 +290,7 @@ export default () => {
});
},
applyBarrierHandlebars(barrierFieldName, forceDistinct = false, updateOnly = []) {
- getBlocksByType('tradeOptions').forEach(tradeOptionsBlock => {
+ getBlocksByType(this.type).forEach(tradeOptionsBlock => {
if (tradeOptionsBlock.disabled) return;
if (updateOnly.length && !updateOnly.includes(tradeOptionsBlock.id)) return;
@@ -318,6 +318,8 @@ export default () => {
});
},
};
+ Blockly.Blocks.tradeOptions_payout = Blockly.Blocks.tradeOptions;
+
Blockly.JavaScript.tradeOptions = block => {
const durationValue = Blockly.JavaScript.valueToCode(block, 'DURATION', Blockly.JavaScript.ORDER_ATOMIC) || '0';
const durationType = block.getFieldValue('DURATIONTYPE_LIST');
@@ -366,8 +368,10 @@ export default () => {
prediction: ${predictionValue},
barrierOffset: ${barrierOffsetValue},
secondBarrierOffset: ${secondBarrierOffsetValue},
+ basis: '${block.type === 'tradeOptions_payout' ? 'payout' : 'stake'}',
});
`;
return code;
};
+ Blockly.JavaScript.tradeOptions_payout = Blockly.JavaScript.tradeOptions;
};
diff --git a/src/common/integrations/GoogleDrive.js b/src/common/integrations/GoogleDrive.js
index 1cdb4e61ee..9d748220a6 100644
--- a/src/common/integrations/GoogleDrive.js
+++ b/src/common/integrations/GoogleDrive.js
@@ -23,7 +23,7 @@ class GoogleDrive {
.init({
apiKey : this.apiKey,
clientId : this.clientId,
- scope : 'https://www.googleapis.com/auth/drive.file',
+ scope : 'https://www.googleapis.com/auth/drive',
discoveryDocs: ['https://www.googleapis.com/discovery/v1/apis/drive/v3/rest'],
})
.then(
@@ -85,9 +85,7 @@ class GoogleDrive {
if (response.error === 'access_denied') {
globalObserver.emit(
'ui.log.warn',
- translate(
- 'Please grant permission to view and manage Google Drive folders created with Binary Bot'
- )
+ translate('Please grant permission to view and manage your Google Drive files')
);
}
reject(response);
@@ -127,6 +125,7 @@ class GoogleDrive {
const userPickedFile = data => {
if (data.action === google.picker.Action.PICKED) {
const fileId = data.docs[0].id;
+
gapi.client.drive.files
.get({
alt : 'media',
@@ -136,10 +135,10 @@ class GoogleDrive {
.then(response => {
try {
const xmlDom = Blockly.Xml.textToDom(response.body);
- const loadFunction =
- xmlDom.hasAttribute('collection') && xmlDom.getAttribute('collection') === 'true'
- ? loadBlocks
- : loadWorkspace;
+ const isCollection =
+ xmlDom.hasAttribute('collection') && xmlDom.getAttribute('collection') === 'true';
+ const loadFunction = isCollection ? loadBlocks : loadWorkspace;
+
try {
loadFunction(xmlDom);
resolve();
@@ -156,6 +155,7 @@ class GoogleDrive {
if (error.status && error.status === 401) {
this.signOut();
}
+
trackAndEmitError(translate('There was an error retrieving data from Google Drive'), error);
reject(error);
});
@@ -171,11 +171,9 @@ class GoogleDrive {
gapi.client.drive.files
.list()
.then(() => {
- const mimeTypes = ['application/xml'];
const docsView = new google.picker.DocsView();
- docsView.setMimeTypes(mimeTypes.join(','));
docsView.setIncludeFolders(true);
- docsView.setOwnedByMe(true);
+ docsView.setMimeTypes(['text/xml', 'application/xml']);
const picker = new google.picker.PickerBuilder();
picker
@@ -194,6 +192,7 @@ class GoogleDrive {
if (error.status && error.status === 401) {
this.signOut();
}
+
trackAndEmitError(translate('There was an error listing files from Google Drive'), error);
reject(error);
});
@@ -205,51 +204,40 @@ class GoogleDrive {
getDefaultFolderId() {
return new Promise((resolve, reject) => {
// Avoid duplicate auth flow by checking if user is already authed
- const authorisePromise = [];
- if (!this.isAuthorised) {
- authorisePromise.push(this.authorise);
- }
- Promise.all(authorisePromise)
+ Promise.all(!this.isAuthorised ? this.authorise : [])
.then(() => {
- gapi.client.drive.files
- .list({ q: 'trashed=false' })
- // eslint-disable-next-line consistent-return
- .then(response => {
- const botFolder = response.result.files.find(
- file =>
- file.name === this.botFolderName &&
- file.mimeType === 'application/vnd.google-apps.folder'
- );
- if (botFolder) {
- return resolve(botFolder.id);
- }
- gapi.client.drive.files
- .create({
- resource: {
- name : this.botFolderName,
- mimeType: 'application/vnd.google-apps.folder',
- fields : 'id',
- },
- })
- .then(createFileResponse => resolve(createFileResponse.result.id))
- .catch(error => {
- if (error.status && error.status === 401) {
- this.signOut();
- }
- trackAndEmitError(
- translate('There was an error retrieving files from Google Drive'),
- error
- );
- reject(error);
- });
- })
- .catch(error => {
- if (error.status && error.status === 401) {
- this.signOut();
- }
- trackAndEmitError(translate('There was an error listing files from Google Drive'), error);
- reject(error);
- });
+ // eslint-disable-next-line
+ gapi.client.drive.files.list({ q: 'trashed=false' }).then(response => {
+ const folder = response.result.files.find(
+ file => file.mimeType === 'application/vnd.google-apps.folder'
+ );
+
+ if (folder) {
+ return resolve();
+ }
+
+ gapi.client.drive.files
+ .create({
+ resource: {
+ name : this.botFolderName,
+ mimeType: 'application/vnd.google-apps.folder',
+ fields : 'id',
+ },
+ })
+ .then(() => resolve())
+ .catch(error => {
+ if (error.status && error.status === 401) {
+ this.signOut();
+ }
+
+ trackAndEmitError(
+ translate('There was an error retrieving files from Google Drive'),
+ error
+ );
+
+ reject(error);
+ });
+ });
})
.catch(() => {
/* Auth error, already handled in authorise()-promise */
@@ -285,6 +273,7 @@ class GoogleDrive {
if (xhr.status === 401) {
this.signOut();
}
+
trackAndEmitError(translate('There was an error processing your request'), xhr.status);
reject();
}
diff --git a/static/xml/toolbox.xml b/static/xml/toolbox.xml
index 2dbce11e0b..56e5a54c00 100644
--- a/static/xml/toolbox.xml
+++ b/static/xml/toolbox.xml
@@ -259,6 +259,18 @@
+
+
+
+ 5
+
+
+
+
+ 1
+
+
+