diff --git a/.gitignore b/.gitignore
index 402b59b95..7ab8c3a90 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,9 @@ bin/*
*.cache
node_modules/*
exchange/Auth0.js
+configs/Email.Config.json
+
+configs/User.Profile.json
+configs/Execution.Config.json
+configs/Secret.Keys.json
+.env
diff --git a/Assistant.js b/Assistant.js
index 6f8b9b7f4..f5e86c857 100644
--- a/Assistant.js
+++ b/Assistant.js
@@ -918,10 +918,6 @@
try {
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> Entering function."); }
- if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pType = " + pType); }
- if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pRate = " + pRate); }
- if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pAmountA = " + pAmountA); }
- if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pAmountB = " + pAmountB); }
/* Removing extra decimals. */
@@ -929,6 +925,11 @@
pAmountA = thisObject.truncDecimals(pAmountA);
pAmountB = thisObject.truncDecimals(pAmountB);
+ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pType = " + pType); }
+ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pRate = " + pRate); }
+ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pAmountA = " + pAmountA); }
+ if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] putPosition -> pAmountB = " + pAmountB); }
+
/* Validations that the limits are not surpassed. */
if (pType === 'buy') {
@@ -947,24 +948,6 @@
callBackFunction(err);
return;
}
-
- let aRate = thisObject.truncDecimals(pAmountA / pRate);
-
- if (aRate !== pAmountB) {
-
- logger.write(MODULE_NAME, "[ERROR] putPosition -> Input Validations -> pAmountA / pRate !== pAmountB.");
- logger.write(MODULE_NAME, "[ERROR] putPosition -> Input Validations -> pAmountA = " + pAmountA);
- logger.write(MODULE_NAME, "[ERROR] putPosition -> Input Validations -> pAmountB = " + pAmountB);
- logger.write(MODULE_NAME, "[ERROR] putPosition -> Input Validations -> pRate = " + pRate);
-
- let err = {
- result: global.DEFAULT_FAIL_RESPONSE.result,
- message: 'pAmountB * pRate !== pAmountA'
- };
-
- callBackFunction(err);
- return;
- }
}
if (pType === 'sell') {
@@ -983,24 +966,6 @@
callBackFunction(err);
return;
}
-
- let bRate = thisObject.truncDecimals(pAmountB * pRate);
-
- if (bRate !== pAmountA) {
-
- logger.write(MODULE_NAME, "[ERROR] putPosition -> Input Validations -> pAmountB * pRate !== pAmountA.");
- logger.write(MODULE_NAME, "[ERROR] putPosition -> Input Validations -> pAmountA = " + pAmountA);
- logger.write(MODULE_NAME, "[ERROR] putPosition -> Input Validations -> pAmountB = " + pAmountB);
- logger.write(MODULE_NAME, "[ERROR] putPosition -> Input Validations -> pRate = " + pRate);
-
- let err = {
- result: global.DEFAULT_FAIL_RESPONSE.result,
- message: 'pAmountB * pRate !== pAmountA'
- };
-
- callBackFunction(err);
- return;
- }
}
/* All validations passed, we proceed. */
@@ -1017,8 +982,8 @@
if (pRate !== marketRate) {
- logger.write(MODULE_NAME, "[ERROR] putPosition -> Input Validations -> putPosition Rate can not be different to marketRate while in Backtesting Mode. ");
- onResponse(global.DEFAULT_FAIL_RESPONSE, positionId);
+ logger.write(MODULE_NAME, "[WARNING] putPosition -> Input Validations -> putPosition Rate can is different to marketRate while in Backtesting Mode. ");
+ //onResponse(global.DEFAULT_FAIL_RESPONSE, positionId);
}
let positionId = Math.trunc(Math.random(1) * 1000000);
@@ -1393,45 +1358,8 @@
}
function sendEmail(pTitle, pBody, pTo) {
- try {
-
- /**
- Email configuration is not available when running the bot on the browser.
- */
- if (global.CURRENT_EXECUTION_AT === "Browser") {
- logger.write(MODULE_NAME, "[WARN] sendEmail -> Send emails is disabled from the browser.");
- return;
- }
-
- let emailList = pTo; //TODO Pending to add spam controller
- let runIndex = context.statusReport.runs.length - 1;
-
- let transporter = nodemailer.createTransport({
- service: global.EMAIL_CONFIG.service,
- auth: {
- user: global.EMAIL_CONFIG.user,
- pass: global.EMAIL_CONFIG.pass
- }
- });
-
- let mailOptions = {
- from: global.EMAIL_CONFIG.from,
- bcc: emailList,
- subject: bot.startMode + "." + runIndex + ' - ' + pTitle,
- text: pBody
- };
-
- transporter.sendMail(mailOptions, function (error, info) {
- if (error) {
- logger.write(MODULE_NAME, "[ERROR] sendEmail -> err = " + error);
- } else {
- logger.write(MODULE_NAME, "[INFO] sendEmail -> Email sent = " + info.response);
- }
- });
-
- } catch (err) {
- logger.write(MODULE_NAME, "[ERROR] sendEmail -> err = " + err.message);
- }
+ logger.write(MODULE_NAME, "[WARN] sendEmail -> Send emails is currently disabled.");
+ return;
}
function truncDecimals(pFloatValue, pDecimals) {
diff --git a/Context.js b/Context.js
index c834d8d1a..df5cd196f 100644
--- a/Context.js
+++ b/Context.js
@@ -169,7 +169,6 @@
} catch (err) {
logger.write(MODULE_NAME, "[ERROR] initialize -> getStatusReport -> err = " + err.message);
- logger.write(MODULE_NAME, "[ERROR] initialize -> getStatusReport -> key = " + key);
callBack(global.DEFAULT_FAIL_RESPONSE);
}
}
diff --git a/ExtractionBotProcessMainLoop.js b/ExtractionBotProcessMainLoop.js
index 235f07587..e3caf7318 100644
--- a/ExtractionBotProcessMainLoop.js
+++ b/ExtractionBotProcessMainLoop.js
@@ -50,7 +50,11 @@
switch (global.CURRENT_EXECUTION_AT) { // This is what determines if the bot is loaded from the devTeam or an endUser copy.
case "Cloud": {
- filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name; // DevTeams bots only are run at the cloud.
+ if (global.RUN_AS_TEAM) {
+ filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name; // DevTeams bots only are run at the cloud.
+ } else {
+ filePath = global.DEV_TEAM + "/" + "members" + "/" + global.USER_LOGGED_IN + "/" + global.CURRENT_BOT_REPO + "/" + pProcessConfig.name; // DevTeam Members bots only are run at the browser.
+ }
break;
}
case "Browser": {
@@ -154,8 +158,6 @@
return str.length < max ? pad(" " + str, max) : str;
}
- console.log(new Date().toISOString() + " " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) + " " + pad(pMonth, 2) + "/" + pad(pYear, 4) + " Entered into Main Loop # " + pad(Number(bot.loopCounter) + 1, 8));
-
/* For each loop we want to create a new log file. */
logger = DEBUG_MODULE.newDebugLog();
@@ -178,6 +180,11 @@
bot.processDatetime = new Date(); // This will be considered the process date and time, so as to have it consistenly all over the execution.
+ /* High level log entry */
+
+ console.log(bot.processDatetime.toISOString() + " " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) + " " + pad(pMonth, 2) + "/" + pad(pYear, 4)
+ + " Entered into Main Loop # " + pad(Number(bot.loopCounter), 8));
+
/* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */
let userBot;
diff --git a/IndicatorBotProcessMainLoop.js b/IndicatorBotProcessMainLoop.js
index 9cd328bf9..5ed0969df 100644
--- a/IndicatorBotProcessMainLoop.js
+++ b/IndicatorBotProcessMainLoop.js
@@ -50,7 +50,11 @@
switch (global.CURRENT_EXECUTION_AT) { // This is what determines if the bot is loaded from the devTeam or an endUser copy.
case "Cloud": {
- filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name; // DevTeams bots only are run at the cloud.
+ if (global.RUN_AS_TEAM) {
+ filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name; // DevTeams bots only are run at the cloud.
+ } else {
+ filePath = global.DEV_TEAM + "/" + "members" + "/" + global.USER_LOGGED_IN + "/" + global.CURRENT_BOT_REPO + "/" + pProcessConfig.name; // DevTeam Members bots only are run at the browser.
+ }
break;
}
case "Browser": {
@@ -155,8 +159,6 @@
return str.length < max ? pad(" " + str, max) : str;
}
- console.log(new Date().toISOString() + " " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) + " " + pad(pMonth, 2) + "/" + pad(pYear, 4) + " Entered into Main Loop # " + pad(Number(bot.loopCounter) + 1, 8 ));
-
/* For each loop we want to create a new log file. */
logger = DEBUG_MODULE.newDebugLog();
@@ -178,6 +180,11 @@
bot.processDatetime = new Date(); // This will be considered the process date and time, so as to have it consistenly all over the execution.
+ /* High level log entry */
+
+ console.log(bot.processDatetime.toISOString() + " " + pad(bot.codeName, 20) + " " + pad(bot.process, 30) + " " + pad(pMonth, 2) + "/" + pad(pYear, 4)
+ + " Entered into Main Loop # " + pad(Number(bot.loopCounter), 8));
+
/* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */
let userBot;
diff --git a/Integrations/OperationsModuleIntegration.js b/Integrations/OperationsModuleIntegration.js
new file mode 100644
index 000000000..b8de71616
--- /dev/null
+++ b/Integrations/OperationsModuleIntegration.js
@@ -0,0 +1,61 @@
+const axios = require('axios')
+const appRoot = require('app-root-path')
+const { logger } = require(`${appRoot}/utils/logger`)
+const auth = require(`${appRoot}/utils/auth`)
+
+exports.updateExecutionResults = async function (summaryDate, buyAverage, sellAverage,
+ marketRate, combinedProfitsA, combinedProfitsB) {
+
+ logger.debug('updateExecutionResults -> Entering Function.')
+
+ try {
+
+ const accessToken = await auth.authenticate()
+
+ const operationsResponse = await axios({
+ url: process.env.GATEWAY_ENDPOINT,
+ method: 'post',
+ data: {
+ query: `
+ mutation($id: ID!, $summaryDate: Int!, $buyAverage: Float!, $sellAverage: Float!,
+ $marketRate: Float!, $combinedProfitsA: Float!, $combinedProfitsB: Float!,
+ $assetA: String!, $assetB: String!){
+ operations_UpdateExecutionSummary(
+ id: $id,
+ summaryDate: $summaryDate,
+ buyAverage: $buyAverage,
+ sellAverage: $sellAverage,
+ marketRate: $marketRate,
+ combinedProfitsA: $combinedProfitsA,
+ combinedProfitsB: $combinedProfitsB,
+ assetA: $assetA,
+ assetB: $assetB
+ )
+ }
+ `,
+ variables: {
+ id: process.env.CLONE_ID,
+ summaryDate: summaryDate,
+ buyAverage: buyAverage,
+ sellAverage: sellAverage,
+ marketRate: marketRate,
+ combinedProfitsA: combinedProfitsA,
+ combinedProfitsB: combinedProfitsB,
+ assetA: global.MARKET.assetA,
+ assetB: global.MARKET.assetB
+ },
+ },
+ headers: {
+ authorization: 'Bearer ' + accessToken
+ }
+ })
+
+ if (!operationsResponse.data.errors)
+ logger.debug('updateExecutionResults -> Operations Module Response: %s', operationsResponse.data.data.operations_UpdateExecutionSummary)
+ else throw new Error(operationsResponse.data.errors[0].message)
+
+ } catch (error) {
+ logger.error('updateExecutionResults -> Error: ' + error.stack)
+ throw new Error('There has been an error updating the execution report: ' + error)
+ }
+}
\ No newline at end of file
diff --git a/Project.njsproj b/Project.njsproj
index 516525a6d..fe4d8f923 100644
--- a/Project.njsproj
+++ b/Project.njsproj
@@ -33,6 +33,12 @@
Code
+
+ Code
+
+
+ Code
+
Code
@@ -45,6 +51,9 @@
+
+ Code
+
Code
@@ -68,6 +77,7 @@
Code
+
Code
@@ -82,6 +92,8 @@
+
+
diff --git a/Root.js b/Root.js
index 4c0f321dd..86486ae54 100644
--- a/Root.js
+++ b/Root.js
@@ -1,4 +1,5 @@
-
+const appRoot = require('app-root-path')
+const operationsIntegration = require(`${appRoot}/Integrations/OperationsModuleIntegration`)
exports.newRoot = function newRoot() {
@@ -210,7 +211,7 @@ exports.newRoot = function newRoot() {
for (let p = 0; p < global.PLATFORM_CONFIG.executionList.length; p++) {
- let listItem = PLATFORM_CONFIG.executionList[p];
+ let listItem;
/*
The local configuration allows to select the configuration to run
@@ -218,17 +219,16 @@ exports.newRoot = function newRoot() {
Here we check that the local configuration for the execution
exist, if it doesn't exist we will take the one on the server.
*/
- let executionListItem;
if (global.EXECUTION_CONFIG === undefined) {
- executionListItem = listItem;
+ listItem = PLATFORM_CONFIG.executionList[p];
} else {
- executionListItem = global.EXECUTION_CONFIG.executionList[p];
+ listItem = global.EXECUTION_CONFIG.executionList[p];
}
- if (listItem.enabled !== "true" || executionListItem.enabled !== "true") {
+ if (listItem === undefined || listItem.enabled !== "true") {
console.log(logDisplace + "Root : [INFO] start -> Skipping process for being disabled.");
- console.log(logDisplace + "Root : [INFO] start -> listItem.process = " + listItem.process);
+ console.log(logDisplace + "Root : [INFO] start -> listItem.process = " + PLATFORM_CONFIG.executionList[p].process);
continue;
}
@@ -344,7 +344,7 @@ exports.newRoot = function newRoot() {
if (FULL_LOG === true) { console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> listItem.process = " + listItem.process); }
let processConfig = botConfig.processes[i];
-
+ processConfig.startMode = global.EXECUTION_CONFIG.startMode // Override file storage configuration
try {
/*
@@ -529,8 +529,9 @@ exports.newRoot = function newRoot() {
if (processConfig.startMode.live !== undefined) {
if (processConfig.startMode.live.run === "true" && global.EXECUTION_CONFIG.startMode.live.run === "true") {
-
+
botConfig.startMode = "Live";
+ console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> Start Mode = " + botConfig.startMode);
let month = pad((new Date()).getUTCMonth() + 1, 2);
let year = (new Date()).getUTCFullYear();
@@ -558,6 +559,8 @@ exports.newRoot = function newRoot() {
if (processConfig.startMode.backtest.run === "true" && global.EXECUTION_CONFIG.startMode.backtest.run === "true") {
botConfig.startMode = "Backtest";
+ console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> Start Mode = " + botConfig.startMode);
+
botConfig.backtest = processConfig.startMode.backtest;
/* We override these waitTimes to the one specified at the backtest configuration. */
@@ -586,6 +589,8 @@ exports.newRoot = function newRoot() {
if (processConfig.startMode.competition.run === "true" && global.EXECUTION_CONFIG.startMode.competition.run === "true") {
botConfig.startMode = "Competition";
+ console.log(logDisplace + "Root : [INFO] start -> findProcess -> Process found at the bot configuration file. -> Start Mode = " + botConfig.startMode);
+
botConfig.competition = processConfig.startMode.competition;
if (processConfig.startMode.competition.resumeExecution === "false" && global.EXECUTION_CONFIG.startMode.competition.resumeExecution === "false") {
@@ -836,11 +841,11 @@ exports.newRoot = function newRoot() {
}
- let clonName = "Clon" + clonKey;
+ let clonName = botConfig.codeName + "-" + "Clon" + clonKey + "-" + process.env.CLONE_ID;
- botConfig.filePathRoot = botConfig.devTeam + "/" + botConfig.codeName + "-" + clonName + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + botConfig.dataSetVersion;
+ botConfig.filePathRoot = botConfig.devTeam + "/" + clonName + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + botConfig.dataSetVersion;
- botConfig.instance = "Clon" + clonKey;
+ botConfig.instance = clonName;
botConfig.instanceIndex = i;
setTimeout(execute, i * Math.random() * 10 * 1000);
@@ -856,7 +861,11 @@ exports.newRoot = function newRoot() {
/* If the bot does not have any genes at all */
let genes = {};
- pBotConfig.instance = "Master";
+ let clonName = botConfig.codeName + "-" + process.env.CLONE_ID;
+
+ botConfig.filePathRoot = botConfig.devTeam + "/" + clonName + "/" + global.PLATFORM_CONFIG.codeName + "." + global.PLATFORM_CONFIG.version.major + "." + global.PLATFORM_CONFIG.version.minor + "/" + global.EXCHANGE_NAME + "/" + botConfig.dataSetVersion;
+
+ pBotConfig.instance = clonName;
pBotConfig.instanceIndex = 0;
createBotInstance(genes, 1, pBotConfig);
@@ -883,7 +892,7 @@ exports.newRoot = function newRoot() {
tradingBotMainLoop.run(pGenes, pTotalInstances, whenRunFinishes);
- function whenRunFinishes(err) {
+ function whenRunFinishes(err, context) {
pBotConfig.loopCounter = 0;
@@ -909,6 +918,20 @@ exports.newRoot = function newRoot() {
console.log(logDisplace + "Root : [ERROR] start -> findProcess -> runTradingBot -> createBotInstance -> onInitializeReady -> whenStartFinishes -> Bot execution finished with errors. Please check the logs.");
logger.persist();
}
+
+ // Update operations module with latest context
+ if (context !== undefined) {
+ let lastExecution = context.executionHistory[context.executionHistory.length - 1]
+ let date = lastExecution[0] / 1000 | 0
+ let buyAvgRate = lastExecution[1]
+ let sellAvgRate = lastExecution[2]
+ let marketRate = lastExecution[7]
+ let combinedProfitsA = lastExecution[13]
+ let combinedProfitsB = lastExecution[14]
+
+ operationsIntegration.updateExecutionResults(date, buyAvgRate, sellAvgRate,
+ marketRate, combinedProfitsA, combinedProfitsB)
+ }
}
} else {
diff --git a/Run.js b/Run.js
index 937991c36..2abe7cb4c 100644
--- a/Run.js
+++ b/Run.js
@@ -1,10 +1,10 @@
-
-global.CURRENT_ENVIRONMENT = "Develop";
-global.CURRENT_EXECUTION_AT = "Browser";
+require('dotenv').config()
+
+global.CURRENT_ENVIRONMENT = "Develop";
+global.CURRENT_EXECUTION_AT = "Cloud";
global.SHALL_BOT_STOP = false;
-global.USER_LOGGED_IN = "Ciencias";
-global.DEV_TEAM = "AAMasters";
global.AT_BREAKPOINT = false; // This is used only when running at the browser.
+global.RUN_AS_TEAM = false;
/* Default parameters can be changed by the execution configuration */
global.EXCHANGE_NAME = "Poloniex";
@@ -15,6 +15,7 @@ global.MARKET = {
process.on('uncaughtException', function (err) {
console.log('[INFO] Run -> uncaughtException -> err.message = ' + err.message);
+ console.log('[INFO] Run -> uncaughtException -> err.stack = ', err.stack);
return;
});
@@ -36,38 +37,155 @@ process.on('exit', function (code) {
}
});
-global.USER_PROFILE = {};
-global.EMAIL_CONFIG = {};
+readExecutionConfiguration();
-readStoragePermissions();
+function readExecutionConfiguration() {
+ try {
+ console.log("[INFO] Run -> readExecutionConfiguration -> Entering function. ");
+ let startMode
+
+ // Environment Configuration
+ global.CURRENT_ENVIRONMENT = process.env.PLATFORM_ENVIRONMENT
+ global.GATEWAY_ENDPOINT = process.env.GATEWAY_ENDPOINT
+
+ // General Financial Being Configuration
+ global.DEV_TEAM = process.env.DEV_TEAM
+ global.CURRENT_BOT_REPO = process.env.BOT + "-" + process.env.TYPE + "-Bot"
+ global.RUN_AS_TEAM = (process.env.RUN_AS_TEAM === "true")
+ global.USER_LOGGED_IN = process.env.USER_LOGGED_IN
+
+ if (process.env.TYPE === 'Trading') {
+ let live = {
+ run: "false",
+ resumeExecution: process.env.RESUME_EXECUTION
+ }
+
+ let backtest = {
+ run: "false",
+ resumeExecution: process.env.RESUME_EXECUTION,
+ beginDatetime: process.env.BEGIN_DATE_TIME,
+ endDatetime: process.env.END_DATE_TIME,
+ waitTime: process.env.WAIT_TIME
+ }
+
+ let competition = {
+ run: "false",
+ resumeExecution: process.env.RESUME_EXECUTION,
+ beginDatetime: process.env.BEGIN_DATE_TIME,
+ endDatetime: process.env.END_DATE_TIME
+ }
+
+ startMode = {
+ live: live,
+ backtest: backtest,
+ competition: competition
+ }
+ } else if (process.env.TYPE === 'Indicator' || process.env.TYPE === 'Extractor') {
+ let allMonths = {
+ run: "false",
+ minYear: process.env.MIN_YEAR,
+ maxYear: process.env.MAX_YEAR
+ }
+ let oneMonth = {
+ run: "false",
+ year: process.env.MIN_YEAR,
+ month: process.env.MONTH
+ }
+ let noTime = {
+ run: "false"
+ }
+ let fixedInterval = {
+ run: "false",
+ interval: process.env.INTERVAL
+ }
+
+ startMode = {
+ allMonths: allMonths,
+ oneMonth: oneMonth,
+ noTime: noTime,
+ fixedInterval: fixedInterval
+ }
+ } else {
+ console.log("[ERROR] readExecutionConfiguration -> Bot Type is invalid." );
+ throw new Error("readExecutionConfiguration -> Bot Type is invalid.")
+ }
+
+ startMode[process.env.START_MODE].run = "true"
+
+ let executionList = [{
+ enabled: "true",
+ devTeam: process.env.DEV_TEAM,
+ bot: process.env.BOT,
+ process: process.env.PROCESS,
+ repo: global.CURRENT_BOT_REPO
+ }]
+
+ global.EXECUTION_CONFIG = {
+ executionList: executionList,
+ startMode: startMode
+ };
+
+ readStoragePermissions();
+ }
+
+ catch (err) {
+ console.log("[ERROR] readExecutionConfiguration -> err = " + err.message);
+ console.log("[ERROR] readExecutionConfiguration -> err = " + err.stack);
+ }
+}
function readStoragePermissions() {
-
let filePath;
try {
console.log( "[INFO] Run -> readStoragePermissions -> Entering function. ");
- let fs = require('fs');
- filePath = '../' + 'User-Profile' + '/' + 'User.Profile.json';
- global.USER_PROFILE = JSON.parse(fs.readFileSync(filePath, 'utf8'));
+ /* Dinamically generating the azure storage permissions for the bot to run */
+ global.STORAGE_BASE_URL = process.env.STORAGE_BASE_URL
+ global.USER_PROFILE = {}
+ const MAX_STORAGE_PERMISSION_DAYS = 10;
+ const STORAGE_ACCESS_MANAGER = require('./StorageAccessManager');
+ storageAccessManager = STORAGE_ACCESS_MANAGER.newStorageAccessManager();
+ storageAccessManager.initialize(process.env.STORAGE_CONNECTION_STRING, onInitialized);
- /* Here we will rearrange the storage permissions array into a map, so that it can be easily consumed when needed. */
+ function onInitialized() {
- let permissionsMap = new Map;
+ /* Here we will rearrange the storage permissions array into a map, so that it can be easily consumed when needed. */
- for (i = 0; i < global.USER_PROFILE.storagePermissions.length; i++) {
+ let permissionsMap = new Map;
- let permission = global.USER_PROFILE.storagePermissions[i];
+ let containers = ["AAPlatform", "AAMasters", "AAVikings", global.DEV_TEAM]
+ let container;
+ let key;
+ let value;
- permissionsMap.set(permission[0], permission[1]);
+ for (let i = 0; i < containers.length; i++) {
+
+ container = containers[i];
+ let readPermission = storageAccessManager.getPermission(container.toLowerCase(), "READ", MAX_STORAGE_PERMISSION_DAYS);
+
+ key = container + ".READ";
+ value = readPermission;
+
+ permissionsMap.set(key, value);
+
+ }
+
+ let writePermission = storageAccessManager.getPermission(container.toLowerCase(), "WRITE", MAX_STORAGE_PERMISSION_DAYS);
+
+ key = container + ".WRITE";
+ value = writePermission;
+
+ permissionsMap.set(key, value);
+
+ global.USER_PROFILE.storagePermissions = permissionsMap;
+ global.USER_PROFILE.connectionString = "";
+ process.env.STORAGE_CONNECTION_STRING = "";
+
+ startRoot();
}
-
- global.USER_PROFILE.storagePermissions = permissionsMap;
-
- readEmailConfiguration();
}
catch (err) {
console.log("[ERROR] Run -> readStoragePermissions -> err = " + err.message);
@@ -75,74 +193,6 @@ function readStoragePermissions() {
}
}
-function readEmailConfiguration() {
-
- let filePath;
-
- try {
- console.log( "Run : [INFO] readEmailConfiguration -> Entering function. ");
-
- let fs = require('fs');
- filePath = '../' + 'Email-Config' + '/' + 'Email.Config.json';
- global.EMAIL_CONFIG = JSON.parse(fs.readFileSync(filePath, 'utf8'));
-
- readExecutionConfiguration();
- }
- catch (err) {
- console.log("[ERROR] Run -> readEmailConfiguration -> err = " + err.message);
- console.log("[HINT] Run -> You need to have a file at this path -> " + filePath);
- }
-}
-
-function readExecutionConfiguration() {
- let filePath;
- try {
- let fs = require('fs');
- filePath = '../Execution-Config/Execution.Config.json';
- let executionProperties = JSON.parse(fs.readFileSync(filePath, 'utf8'));
- global.DEV_TEAM = executionProperties.devTeam;
- global.EXCHANGE_NAME = executionProperties.exchangeName;
- global.MARKET = executionProperties.market;
- global.EXECUTION_CONFIG = {
- executionList: executionProperties.executionList,
- startMode: executionProperties.startMode
- };
-
- readExchangeAPIKey();
- }
- catch (err) {
- console.log("[ERROR] readExecutionConfiguration -> err = " + err.message);
- console.log("[HINT] You need to have a file at this path -> " + filePath);
- }
-}
-
-//TODO Move this method inside ExchangeAPI
-function readExchangeAPIKey() {
-
- try {
- console.log( "[INFO] Run -> readExchangeAPIKey -> Entering function. ");
-
- let fs = require('fs');
- let filePath = '../' + 'Exchange-Keys' + '/' + 'Secret.Keys' + '.json';
-
- global.EXCHANGE_KEYS = JSON.parse(fs.readFileSync(filePath, 'utf8'));
- startRoot();
- }
- catch (err) {
- console.log("[ERROR] Run -> readExchangeAPIKey -> err = " + err.message);
- console.log("[HINT] Run -> You need to have a file at this path -> " + filePath);
-
- global.EXCHANGE_KEYS = {
- Poloniex: [{
- Key: "",
- Secret: ""
- }]
- }
-
- startRoot();
- }
-}
-
function startRoot() {
console.log( "[INFO] Run -> startRoot -> Entering function. ");
diff --git a/StorageAccessManager.js b/StorageAccessManager.js
new file mode 100644
index 000000000..9a36d9d25
--- /dev/null
+++ b/StorageAccessManager.js
@@ -0,0 +1,62 @@
+exports.newStorageAccessManager = function newStorageAccessManager() {
+
+ let thisObject = {
+ getPermission: getPermission,
+ initialize: initialize
+ }
+
+ let connectionString;
+
+ return thisObject;
+
+ function initialize(pConnectionString, callBackFunction) {
+
+ connectionString = pConnectionString;
+
+ callBackFunction();
+ }
+
+ function getPermission(pContainer, pType, pDays) {
+
+ let azure = require('azure-storage');
+ let blobService = azure.createBlobService(connectionString);
+
+ let startDate = new Date();
+ startDate.setDate(startDate.getDate() - 1);
+
+ let expiryDate = new Date(startDate);
+ expiryDate.setDate(startDate.getDate() + pDays);
+
+ let azurePermissions;
+
+ switch (pType) {
+ case "READ": {
+ azurePermissions = azure.BlobUtilities.SharedAccessPermissions.READ;
+ break;
+ }
+ case "WRITE": {
+ azurePermissions = azure.BlobUtilities.SharedAccessPermissions.WRITE;
+ break;
+ }
+ case "DELETE": {
+ azurePermissions = azure.BlobUtilities.SharedAccessPermissions.DELETE;
+ break;
+ }
+ }
+
+ let blobName = undefined;
+
+ let sharedAccessPolicy = {
+ AccessPolicy: {
+ Permissions: azurePermissions,
+ Start: startDate,
+ Expiry: expiryDate
+ }
+ };
+
+ let sasToken = blobService.generateSharedAccessSignature(pContainer, blobName, sharedAccessPolicy);
+
+ return "BlobEndpoint=" + global.STORAGE_BASE_URL + ";SharedAccessSignature=" + sasToken + "";
+ }
+}
+
diff --git a/TradingBotProcessMainLoop.js b/TradingBotProcessMainLoop.js
index 21b9845bf..b31cc9492 100644
--- a/TradingBotProcessMainLoop.js
+++ b/TradingBotProcessMainLoop.js
@@ -52,7 +52,12 @@
switch (global.CURRENT_EXECUTION_AT) { // This is what determines if the bot is loaded from the devTeam or an endUser copy.
case "Cloud": {
- filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name; // DevTeams bots only are run at the cloud.
+ if (global.RUN_AS_TEAM) {
+ filePath = global.DEV_TEAM + "/" + "bots" + "/" + bot.repo + "/" + pProcessConfig.name; // DevTeams bots only are run at the cloud.
+ } else {
+ filePath = global.DEV_TEAM + "/" + "members" + "/" + global.USER_LOGGED_IN + "/" + global.CURRENT_BOT_REPO + "/" + pProcessConfig.name; // DevTeam Members bots only are run at the browser.
+ }
+
break;
}
case "Browser": {
@@ -134,6 +139,8 @@
function run(pGenes, pTotalAlgobots, callBackFunction) {
+ let context;
+
try {
if (FULL_LOG === true) { parentLogger.write(MODULE_NAME, "[INFO] run -> Entering function."); }
@@ -160,8 +167,6 @@
return str.length < max ? pad(" " + str, max) : str;
}
- console.log(new Date().toISOString() + " " + pad(bot.codeName, 20) + " " + pad(bot.instance, 20) + " " + pad(bot.process, 30) + " Entered into Main Loop # " + pad(Number(bot.loopCounter) + 1, 8));
-
/* For each loop we want to create a new log file. */
logger = DEBUG_MODULE.newDebugLog();
@@ -176,7 +181,7 @@
/* We define here all the modules that the rest of the infraestructure, including the bots themselves can consume. */
const UTILITIES = require(ROOT_DIR + 'CloudUtilities');
- const EXCHANGE_API = require(ROOT_DIR + 'Exchange/ExchangeAPI');
+ const EXCHANGE_API = require(ROOT_DIR + 'exchange/ExchangeAPI');
const CONTEXT = require(ROOT_DIR + 'Context');
const ASSISTANT = require(ROOT_DIR + 'Assistant');
const STATUS_REPORT = require(ROOT_DIR + 'StatusReport');
@@ -289,7 +294,7 @@
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
- callBackFunction(global.DEFAULT_OK_RESPONSE);
+ callBackFunction(global.DEFAULT_OK_RESPONSE, context);
return;
}
}
@@ -341,7 +346,7 @@
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
- callBackFunction(global.DEFAULT_OK_RESPONSE);
+ callBackFunction(global.DEFAULT_OK_RESPONSE, context);
return;
}
}
@@ -361,7 +366,7 @@
}
}
- if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> bot.processDatetime = " + bot.processDatetime); }
+ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] run -> loop -> bot.processDatetime = " + bot.processDatetime.toISOString()); }
if (global.AT_BREAKPOINT === true) {
@@ -369,9 +374,13 @@
}
- /* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */
+ /* High level log entry */
- let context;
+ console.log(new Date().toISOString() + " " + pad(bot.codeName, 20) + " " + pad(bot.devTeam, 20) + " " + pad(bot.process, 30)
+ + " " + bot.startMode + " Entered into Main Loop # " + pad(Number(bot.loopCounter), 8) + " bot.processDatetime = " + bot.processDatetime.toISOString());
+
+ /* We will prepare first the infraestructure needed for the bot to run. There are 3 modules we need to sucessfullly initialize first. */
+
let exchangeAPI;
let assistant;
let userBot;
@@ -994,7 +1003,7 @@
clearTimeout(nextLoopTimeoutHandle);
clearTimeout(checkLoopHealthHandle);
bot.enableCheckLoopHealth = false;
- callBackFunction(global.DEFAULT_OK_RESPONSE);
+ callBackFunction(global.DEFAULT_OK_RESPONSE, context);
return;
}
@@ -1184,6 +1193,7 @@
callBackFunction(err);
}
}
+
}
catch (err) {
diff --git a/exchange/ExchangeAPI.js b/exchange/ExchangeAPI.js
index 0d56607fe..2ad5eddfd 100644
--- a/exchange/ExchangeAPI.js
+++ b/exchange/ExchangeAPI.js
@@ -5,12 +5,12 @@
This module allows trading bots to connect to the exchange and do trading operations on it. So far it can only work with Poloniex.
*/
- const _ = require('lodash');
- const isValidOrder = require('./exchangeUtils').isValidOrder;
+ const _ = require('lodash')
+ const isValidOrder = require('./exchangeUtils').isValidOrder
const graphqlClient = require('graphql-client')
- const request = require('request')
- const authOptions = require('./Auth0')
-
+ const appRoot = require('app-root-path')
+ const auth = require(`${appRoot}/utils/auth`)
+
let MODULE_NAME = "Exchange API";
let thisObject = {
@@ -29,7 +29,7 @@
return thisObject;
- function initialize(callBackFunction) {
+ async function initialize(callBackFunction) {
try {
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] initialize -> Entering function."); }
@@ -37,28 +37,17 @@
// TODO integrate with financial beings module to get the exchange
let botExchange = 'Poloniex';
let exchange = botExchange.toLowerCase() + 'Client.js';
- let api = require('./Wrappers/' + exchange);
-
- request(authOptions, onTokenResponse);
+ let api = require('./wrappers/' + exchange);
- function onTokenResponse(error, response, body) {
- if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] onTokenResponse -> Entering function."); }
+ const accessToken = await auth.authenticate()
- if (error) {
- logger.write(MODULE_NAME, "[ERROR] onTokenResponse -> err = " + error.message);
- callBackFunction(global.DEFAULT_FAIL_RESPONSE);
- } else {
- if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] onTokenResponse -> Token Received."); }
- let response = JSON.parse(body)
- let authToken = response.access_token
- let keyVaultAPI = createKeyVaultAPIClient(authToken)
- apiClient = api.newAPIClient(keyVaultAPI, logger);
+ let keyVaultAPI = createKeyVaultAPIClient(accessToken)
+ apiClient = api.newAPIClient(keyVaultAPI, logger);
+
+ callBackFunction(global.DEFAULT_OK_RESPONSE);
- callBackFunction(global.DEFAULT_OK_RESPONSE);
- }
- }
} catch (err) {
- logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.message);
+ logger.write(MODULE_NAME, "[ERROR] initialize -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
@@ -67,7 +56,7 @@
if (global.LOG_CONTROL[MODULE_NAME].logInfo === true) { logger.write(MODULE_NAME, "[INFO] createKeyVaultAPIClient -> Entering function."); }
const keyVaultAPI = graphqlClient({
- url: 'https://app-api.advancedalgos.net/graphql',
+ url: global.GATEWAY_ENDPOINT,
headers: {
Authorization: 'Bearer ' + authToken
}
diff --git a/package-lock.json b/package-lock.json
index e49ce5eda..fb0afbaa8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -134,6 +134,11 @@
"fclone": "1.0.11"
}
},
+ "app-root-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-2.1.0.tgz",
+ "integrity": "sha1-mL9lmTJ+zqGZMJhm6BQDaP0uZGo="
+ },
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
@@ -155,6 +160,14 @@
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
},
+ "async": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz",
+ "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==",
+ "requires": {
+ "lodash": "4.17.11"
+ }
+ },
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -170,6 +183,40 @@
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
},
+ "axios": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
+ "integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
+ "requires": {
+ "follow-redirects": "1.6.1",
+ "is-buffer": "1.1.6"
+ }
+ },
+ "azure-storage": {
+ "version": "2.10.2",
+ "resolved": "https://registry.npmjs.org/azure-storage/-/azure-storage-2.10.2.tgz",
+ "integrity": "sha512-pOyGPya9+NDpAfm5YcFfklo57HfjDbYLXxs4lomPwvRxmb0Di/A+a+RkUmEFzaQ8S13CqxK40bRRB0sjj2ZQxA==",
+ "requires": {
+ "browserify-mime": "1.2.9",
+ "extend": "3.0.2",
+ "json-edm-parser": "0.1.2",
+ "md5.js": "1.3.4",
+ "readable-stream": "2.0.6",
+ "request": "2.88.0",
+ "underscore": "1.8.3",
+ "uuid": "3.3.2",
+ "validator": "9.4.1",
+ "xml2js": "0.2.8",
+ "xmlbuilder": "9.0.7"
+ },
+ "dependencies": {
+ "underscore": {
+ "version": "1.8.3",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz",
+ "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI="
+ }
+ }
+ },
"bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
@@ -179,6 +226,16 @@
"tweetnacl": "0.14.5"
}
},
+ "browserify-mime": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/browserify-mime/-/browserify-mime-1.2.9.tgz",
+ "integrity": "sha1-rrGvKN5sDXpqLOQK22j/GEIq8x8="
+ },
+ "buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
+ },
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
@@ -189,6 +246,56 @@
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
},
+ "color": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz",
+ "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==",
+ "requires": {
+ "color-convert": "1.9.3",
+ "color-string": "1.5.3"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
+ },
+ "color-string": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
+ "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
+ "requires": {
+ "color-name": "1.1.3",
+ "simple-swizzle": "0.2.2"
+ }
+ },
+ "colornames": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz",
+ "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y="
+ },
+ "colors": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz",
+ "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg=="
+ },
+ "colorspace": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.1.tgz",
+ "integrity": "sha512-pI3btWyiuz7Ken0BWh9Elzsmv2bM9AhA7psXib4anUXy/orfZ/E0MbQwhSOG/9L8hLlalqrU0UhOuqxW1YjmVw==",
+ "requires": {
+ "color": "3.0.0",
+ "text-hex": "1.0.0"
+ }
+ },
"combined-stream": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
@@ -210,11 +317,34 @@
"assert-plus": "1.0.0"
}
},
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
+ "diagnostics": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz",
+ "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==",
+ "requires": {
+ "colorspace": "1.1.1",
+ "enabled": "1.0.2",
+ "kuler": "1.0.1"
+ }
+ },
+ "dotenv": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz",
+ "integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w=="
+ },
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -225,6 +355,22 @@
"safer-buffer": "2.1.2"
}
},
+ "ecdsa-sig-formatter": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz",
+ "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=",
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "enabled": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz",
+ "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=",
+ "requires": {
+ "env-variable": "0.0.5"
+ }
+ },
"encoding": {
"version": "0.1.12",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
@@ -233,6 +379,11 @@
"iconv-lite": "0.4.24"
}
},
+ "env-variable": {
+ "version": "0.0.5",
+ "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz",
+ "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA=="
+ },
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@@ -253,11 +404,29 @@
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
},
+ "fast-safe-stringify": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz",
+ "integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg=="
+ },
"fclone": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz",
"integrity": "sha1-EOhdo4v+p/xZk0HClu4ddyZu5kA="
},
+ "fecha": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz",
+ "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg=="
+ },
+ "follow-redirects": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.6.1.tgz",
+ "integrity": "sha512-t2JCjbzxQpWvbhts3l6SH1DKzSrx8a+SsaVf4h6bG4kOXUuPYS/kg2Lr4gQSb7eemaHqJkOThF1BGyjlUkO1GQ==",
+ "requires": {
+ "debug": "3.1.0"
+ }
+ },
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
@@ -334,6 +503,15 @@
"har-schema": "2.0.0"
}
},
+ "hash-base": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
+ "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+ "requires": {
+ "inherits": "2.0.1",
+ "safe-buffer": "5.1.2"
+ }
+ },
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
@@ -357,6 +535,16 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
"integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE="
},
+ "is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
+ },
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
@@ -367,6 +555,11 @@
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
"isomorphic-fetch": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
@@ -392,6 +585,14 @@
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
"optional": true
},
+ "json-edm-parser": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/json-edm-parser/-/json-edm-parser-0.1.2.tgz",
+ "integrity": "sha1-HmCw/vG8CvZ7wNFG393lSGzWFbQ=",
+ "requires": {
+ "jsonparse": "1.2.0"
+ }
+ },
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
@@ -407,6 +608,34 @@
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
+ "jsonparse": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.2.0.tgz",
+ "integrity": "sha1-XAxWhRBxYOcv50ib3eoLRMK8Z70="
+ },
+ "jsonwebtoken": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.4.0.tgz",
+ "integrity": "sha512-coyXjRTCy0pw5WYBpMvWOMN+Kjaik2MwTUIq9cna/W7NpO9E+iYbumZONAz3hcr+tXFJECoQVrtmIoC3Oz0gvg==",
+ "requires": {
+ "jws": "3.2.1",
+ "lodash.includes": "4.3.0",
+ "lodash.isboolean": "3.0.3",
+ "lodash.isinteger": "4.0.4",
+ "lodash.isnumber": "3.0.3",
+ "lodash.isplainobject": "4.0.6",
+ "lodash.isstring": "4.0.1",
+ "lodash.once": "4.1.1",
+ "ms": "2.1.1"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+ }
+ }
+ },
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -418,11 +647,101 @@
"verror": "1.10.0"
}
},
+ "jwa": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.2.0.tgz",
+ "integrity": "sha512-Grku9ZST5NNQ3hqNUodSkDfEBqAmGA1R8yiyPHOnLzEKI0GaCQC/XhFmsheXYuXzFQJdILbh+lYBiliqG5R/Vg==",
+ "requires": {
+ "buffer-equal-constant-time": "1.0.1",
+ "ecdsa-sig-formatter": "1.0.10",
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "jws": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.1.tgz",
+ "integrity": "sha512-bGA2omSrFUkd72dhh05bIAN832znP4wOU3lfuXtRBuGTbsmNmDXMQg28f0Vsxaxgk4myF5YkKQpz6qeRpMgX9g==",
+ "requires": {
+ "jwa": "1.2.0",
+ "safe-buffer": "5.1.2"
+ }
+ },
+ "kuler": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz",
+ "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==",
+ "requires": {
+ "colornames": "1.1.1"
+ }
+ },
"lodash": {
"version": "4.17.11",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
},
+ "lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8="
+ },
+ "lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY="
+ },
+ "lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M="
+ },
+ "lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w="
+ },
+ "lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs="
+ },
+ "lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE="
+ },
+ "lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
+ },
+ "logform": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/logform/-/logform-1.10.0.tgz",
+ "integrity": "sha512-em5ojIhU18fIMOw/333mD+ZLE2fis0EzXl1ZwHx4iQzmpQi6odNiY/t+ITNr33JZhT9/KEaH+UPIipr6a9EjWg==",
+ "requires": {
+ "colors": "1.3.3",
+ "fast-safe-stringify": "2.0.6",
+ "fecha": "2.3.3",
+ "ms": "2.1.1",
+ "triple-beam": "1.3.0"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+ "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+ }
+ }
+ },
+ "md5.js": {
+ "version": "1.3.4",
+ "resolved": "http://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
+ "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
+ "requires": {
+ "hash-base": "3.0.4",
+ "inherits": "2.0.1"
+ }
+ },
"mime-db": {
"version": "1.36.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz",
@@ -436,6 +755,11 @@
"mime-db": "1.36.0"
}
},
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
"node-fetch": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
@@ -460,11 +784,21 @@
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
},
+ "one-time": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz",
+ "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4="
+ },
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
},
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
+ },
"psl": {
"version": "1.1.29",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz",
@@ -485,6 +819,19 @@
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
},
+ "readable-stream": {
+ "version": "2.0.6",
+ "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
+ "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.1",
+ "isarray": "1.0.0",
+ "process-nextick-args": "1.0.7",
+ "string_decoder": "0.10.31",
+ "util-deprecate": "1.0.2"
+ }
+ },
"request": {
"version": "2.88.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
@@ -527,6 +874,19 @@
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
+ "sax": {
+ "version": "0.5.8",
+ "resolved": "http://registry.npmjs.org/sax/-/sax-0.5.8.tgz",
+ "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE="
+ },
+ "simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
+ "requires": {
+ "is-arrayish": "0.3.2"
+ }
+ },
"sshpk": {
"version": "1.14.2",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
@@ -543,11 +903,26 @@
"tweetnacl": "0.14.5"
}
},
+ "stack-trace": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
+ "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA="
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+ },
"symbol-observable": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz",
"integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ=="
},
+ "text-hex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz",
+ "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="
+ },
"tough-cookie": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
@@ -557,6 +932,11 @@
"punycode": "1.4.1"
}
},
+ "triple-beam": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz",
+ "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw=="
+ },
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
@@ -584,11 +964,21 @@
"inherits": "2.0.1"
}
},
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
},
+ "validator": {
+ "version": "9.4.1",
+ "resolved": "http://registry.npmjs.org/validator/-/validator-9.4.1.tgz",
+ "integrity": "sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA=="
+ },
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
@@ -604,6 +994,112 @@
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz",
"integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q=="
},
+ "winston": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/winston/-/winston-3.1.0.tgz",
+ "integrity": "sha512-FsQfEE+8YIEeuZEYhHDk5cILo1HOcWkGwvoidLrDgPog0r4bser1lEIOco2dN9zpDJ1M88hfDgZvxe5z4xNcwg==",
+ "requires": {
+ "async": "2.6.1",
+ "diagnostics": "1.1.1",
+ "is-stream": "1.1.0",
+ "logform": "1.10.0",
+ "one-time": "0.0.4",
+ "readable-stream": "2.3.6",
+ "stack-trace": "0.0.10",
+ "triple-beam": "1.3.0",
+ "winston-transport": "4.3.0"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "2.0.0",
+ "safe-buffer": "5.1.2",
+ "string_decoder": "1.1.1",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ }
+ }
+ },
+ "winston-transport": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz",
+ "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==",
+ "requires": {
+ "readable-stream": "2.3.6",
+ "triple-beam": "1.3.0"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "process-nextick-args": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
+ },
+ "readable-stream": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+ "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
+ "requires": {
+ "core-util-is": "1.0.2",
+ "inherits": "2.0.3",
+ "isarray": "1.0.0",
+ "process-nextick-args": "2.0.0",
+ "safe-buffer": "5.1.2",
+ "string_decoder": "1.1.1",
+ "util-deprecate": "1.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "requires": {
+ "safe-buffer": "5.1.2"
+ }
+ }
+ }
+ },
+ "xml2js": {
+ "version": "0.2.8",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.2.8.tgz",
+ "integrity": "sha1-m4FpCTFjH/CdGVdUn69U9PmAs8I=",
+ "requires": {
+ "sax": "0.5.8"
+ }
+ },
+ "xmlbuilder": {
+ "version": "9.0.7",
+ "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
+ "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
+ },
"zen-observable": {
"version": "0.8.9",
"resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.9.tgz",
diff --git a/package.json b/package.json
index 16aaf5699..fa8757b2c 100644
--- a/package.json
+++ b/package.json
@@ -10,15 +10,20 @@
"license": "ISC",
"dependencies": {
"apollo-boost": "^0.1.16",
+ "app-root-path": "^2.1.0",
"assert": "^1.4.1",
+ "axios": "^0.18.0",
+ "azure-storage": "^2.8.2",
+ "dotenv": "^6.0.0",
"graphql": "^14.0.2",
"graphql-client": "^2.0.1",
+ "jsonwebtoken": "^8.4.0",
"lodash": "^4.17.11",
"nodemailer": "^4.6.8",
"nonce": "^1.0.4",
"querystring": "^0.2.0",
- "request": "^2.88.0",
"retry": "^0.12.0",
- "underscore": "^1.9.1"
+ "underscore": "^1.9.1",
+ "winston": "^3.1.0"
}
}
diff --git a/this.config.json b/this.config.json
index 3a23977c8..d4a37b864 100644
--- a/this.config.json
+++ b/this.config.json
@@ -14,35 +14,35 @@
"repo": "AAMariam-Trading-Bot"
},
{
- "enabled": "true",
+ "enabled": "false",
"devTeam": "AAMasters",
"bot": "AACharly",
"process": "Poloniex-Live-Trades",
"repo": "AACharly-Extraction-Bot"
},
{
- "enabled": "true",
+ "enabled": "false",
"devTeam": "AAMasters",
"bot": "AACharly",
"process": "Poloniex-Hole-Fixing",
"repo": "AACharly-Extraction-Bot"
},
{
- "enabled": "true",
+ "enabled": "false",
"devTeam": "AAMasters",
"bot": "AABruce",
"process": "One-Min-Daily-Candles-Volumes",
"repo": "AABruce-Indicator-Bot"
},
{
- "enabled": "true",
+ "enabled": "false",
"devTeam": "AAMasters",
"bot": "AAOlivia",
"process": "Multi-Period-Daily",
"repo": "AAOlivia-Indicator-Bot"
},
{
- "enabled": "true",
+ "enabled": "false",
"devTeam": "AAMasters",
"bot": "AAOlivia",
"process": "Multi-Period-Market",
diff --git a/utils/auth.js b/utils/auth.js
new file mode 100644
index 000000000..c7f0b8d87
--- /dev/null
+++ b/utils/auth.js
@@ -0,0 +1,39 @@
+const axios = require('axios')
+const appRoot = require('app-root-path')
+const { logger } = require(`${appRoot}/utils/logger`)
+
+exports.authenticate = async function () {
+ try {
+
+ if (!global.ACCESS_TOKEN) {
+ logger.debug('authenticate -> Entering Function.')
+
+ const authBody = '{"client_id":"' + process.env.AUTH_CLIENT_ID
+ + '","client_secret": "' + process.env.AUTH_CLIENT_SECRET
+ + '","audience":"' + process.env.AUTH_AUDIENCE
+ + '","grant_type":"client_credentials"}'
+
+ let authResponse = await axios({
+ url: process.env.AUTH_URL,
+ method: 'post',
+ data: authBody,
+ headers: { 'content-type': 'application/json' }
+ })
+
+ if (!authResponse.data.errors)
+ global.ACCESS_TOKEN = authResponse.data.access_token
+ else throw new Error(operationsResponse.data.errors[0].message)
+
+ process.env.AUTH_CLIENT_ID = ""
+ process.env.AUTH_CLIENT_SECRET = ""
+ process.env.AUTH_AUDIENCE = ""
+ process.env.AUTH_URL = ""
+ }
+
+ return global.ACCESS_TOKEN
+
+ } catch (error) {
+ logger.error('authenticate -> Error: ' + error.stack)
+ throw new Error('There has been an error on the authentication: ' + error)
+ }
+}
\ No newline at end of file
diff --git a/utils/logger.js b/utils/logger.js
new file mode 100644
index 000000000..1cc942d0c
--- /dev/null
+++ b/utils/logger.js
@@ -0,0 +1,40 @@
+const winston = require('winston')
+const appRoot = require('app-root-path')
+const util = require('util')
+
+const options = {
+ file: {
+ level: 'info',
+ filename: `${appRoot}/logs/app.log`,
+ handleExceptions: true,
+ json: true,
+ maxsize: 5242880, // 5MB
+ maxFiles: 5,
+ colorize: false,
+ timestamp: true
+ },
+ console: {
+ level: 'debug',
+ handleExceptions: true,
+ json: false,
+ colorize: true,
+ timestamp: true
+ }
+}
+
+exports.logger = winston.createLogger({
+ level: 'info',
+ format: winston.format.combine(
+ winston.format.colorize(),
+ winston.format.splat(),
+ winston.format.timestamp({ format: 'YY/MM/DD HH:mm' }),
+ winston.format.printf(
+ info => `${info.timestamp} - ${info.level}: ${JSON.parse(JSON.stringify(util.inspect(info.message)))}`
+ )
+ ),
+ transports: [
+ new winston.transports.File(options.file),
+ new winston.transports.Console(options.console)
+ ],
+ exitOnError: false // do not exit on handled exceptions
+})
\ No newline at end of file