diff --git a/src/schema/mutations/AddBot.js b/src/schema/mutations/AddBot.js new file mode 100644 index 000000000..d269a1d5f --- /dev/null +++ b/src/schema/mutations/AddBot.js @@ -0,0 +1,70 @@ +import logger from '../../utils/logger' +import { BotInputType, } from '../types/input' +import { BotType, } from '../types' +import { Ecosystem } from '../../models' + +export const args = { bot: { type: BotInputType } } + +const resolve = async (parent, { bot }, context) => { + logger.debug('addBot -> Dev team: %s. Bot: %s', bot.devTeam, bot.codeName) + try { + + let userEcosystem = await Ecosystem.findOne({ + authId: context.userId + }) + + if (!userEcosystem) { + throw 'Ecosystem not found for the user.' + } + + let newBotClone + for (let i = 0; i < userEcosystem.devTeams.length; i++) { + const auxTeam = userEcosystem.devTeams[i] + if (auxTeam.codeName === bot.devTeam) { + for (let j = 0; j < auxTeam.bots.length; j++) { + const auxBot = auxTeam.bots[j] + if (auxBot.codeName === bot.codeName) { + for (let k = 0; k < auxBot.products.length; k++) { + const auxProduct = auxBot.products[k] + if (auxProduct.codeName === bot.productCodeName) { + newBotClone = { + displayName: auxBot.displayName, + codeName: auxBot.codeName + '-' + bot.cloneId, + type: auxBot.type, + profilePicture: auxBot.profilePicture, + cloneId: bot.cloneId, + products: [auxProduct] + } + auxTeam.bots.push(newBotClone) + break + } + } + break + } + } + break + } + } + + if (newBotClone) { + await userEcosystem.save() + return newBotClone + } else { + throw 'Algobot not found.' + } + + } catch (err) { + logger.error('addBot -> Error: %s', err.message) + throw err + } +} + +const mutation = { + addBot: { + type: BotType, + args, + resolve, + } +} + +export default mutation; diff --git a/src/schema/mutations/CreateFile.js b/src/schema/mutations/CreateFile.js index ab2992f8b..a1dcdcb6b 100644 --- a/src/schema/mutations/CreateFile.js +++ b/src/schema/mutations/CreateFile.js @@ -6,7 +6,7 @@ import { writeFileContent } from '../../storage/providers/MinioStorage' export const args = { file: { type: FileInputType } } const resolve = async (parent, { file }, context) => { - logger.debug('createFile -> Entering Function.') + logger.debug('createFile -> Entering Function: ' + file.container + '/' + file.filePath) try { //TODO Add permissions await writeFileContent(file.container, file.filePath, file.fileContent) diff --git a/src/schema/mutations/RemoveBot.js b/src/schema/mutations/RemoveBot.js new file mode 100644 index 000000000..a09ce89f1 --- /dev/null +++ b/src/schema/mutations/RemoveBot.js @@ -0,0 +1,63 @@ +import logger from '../../utils/logger' +import { BotInputType, } from '../types/input' +import { BotType, } from '../types' +import { Ecosystem } from '../../models' + +export const args = { bot: { type: BotInputType } } + +const resolve = async (parent, { bot }, context) => { + logger.debug('removeBot -> Dev team: %s. Bot: %s', bot.devTeam, bot.codeName) + try { + + let userEcosystem = await Ecosystem.findOne({ + authId: context.userId + }) + + if (!userEcosystem) { + throw 'Ecosystem not found for the user.' + } + + let removedBotClone + for (let i = 0; i < userEcosystem.devTeams.length; i++) { + const auxTeam = userEcosystem.devTeams[i] + if (auxTeam.codeName === bot.devTeam) { + for (let j = 0; j < auxTeam.bots.length; j++) { + const auxBot = auxTeam.bots[j] + if (auxBot.codeName + '-' + bot.cloneId === bot.codeName) { + for (let k = 0; k < auxBot.products.length; k++) { + const auxProduct = auxBot.products[k] + if (auxProduct.codeName === bot.productCodeName) { + removedBotClone = auxBot + auxTeam.bots.splice(j, 1) + break + } + } + break + } + } + break + } + } + + if (removedBotClone) { + await userEcosystem.save() + return removedBotClone + } else { + throw 'Algobot not found.' + } + + } catch (err) { + logger.error('removeBot -> Error: %s', err.message) + throw err + } +} + +const mutation = { + removeBot: { + type: BotType, + args, + resolve, + } +} + +export default mutation; diff --git a/src/schema/mutations/index.js b/src/schema/mutations/index.js index 7e0b35711..be7aad941 100644 --- a/src/schema/mutations/index.js +++ b/src/schema/mutations/index.js @@ -5,13 +5,17 @@ import { import AddTeamMutation from './AddTeam' import DeleteTeamMutation from './DeleteTeam' import CreateFileMutation from './CreateFile' +import AddBotMutation from './AddBot' +import RemoveBotMutation from './RemoveBot' const Mutation = new GraphQLObjectType({ name: 'Mutation', fields: Object.assign( AddTeamMutation, DeleteTeamMutation, - CreateFileMutation + CreateFileMutation, + AddBotMutation, + RemoveBotMutation ) }) diff --git a/src/schema/queries/FileContent.js b/src/schema/queries/FileContent.js index ec30b555f..2b328b154 100644 --- a/src/schema/queries/FileContent.js +++ b/src/schema/queries/FileContent.js @@ -22,11 +22,12 @@ const resolve = async (parent, { file }, context) => { return fileContent } catch (err) { - if(err.message === 'The specified key does not exist.') + if (err.message === 'The specified key does not exist.') logger.warn('getFileContent -> Error: %s', err.message) - else - logger.error('getFileContent -> Error: %s', err.message) - throw err + else { + logger.error('getFileContent -> Error: %s', err.message) + throw err + } } } diff --git a/src/schema/types/input/Bot.js b/src/schema/types/input/Bot.js index 5b1ed1096..b71172621 100644 --- a/src/schema/types/input/Bot.js +++ b/src/schema/types/input/Bot.js @@ -8,11 +8,14 @@ const Type = new GraphQLInputObjectType({ name: 'BotInput', description: 'Payload for bot input.', fields: () => ({ + devTeam: { type: new GraphQLNonNull(GraphQLString) }, codeName: { type: new GraphQLNonNull(GraphQLString) }, - displayName: { type: new GraphQLNonNull(GraphQLString) }, + productCodeName: { type: new GraphQLNonNull(GraphQLString) }, + displayName: { type: GraphQLString }, repo: { type: GraphQLString }, configFile: { type: GraphQLString }, - cloneId: { type: GraphQLString } + cloneId: { type: GraphQLString }, + validPeriod: { type: GraphQLString }, }), }); diff --git a/src/schema/types/input/DataSet.js b/src/schema/types/input/DataSet.js new file mode 100644 index 000000000..71efbf934 --- /dev/null +++ b/src/schema/types/input/DataSet.js @@ -0,0 +1,19 @@ +import { + GraphQLInputObjectType, + GraphQLString, + GraphQLList +} from 'graphql'; + +const Type = new GraphQLInputObjectType({ + name: 'DataSetInput', + description: 'Payload for data set input.', + fields: () => ({ + codeName: { type: new GraphQLNonNull(GraphQLString) }, + type: { type: new GraphQLNonNull(GraphQLString) }, + filePath: { type: new GraphQLNonNull(GraphQLString) }, + fileName: { type: new GraphQLNonNull(GraphQLString) }, + validPeriods: { type: new GraphQLList(GraphQLString) } + }), +}); + +export default Type; diff --git a/src/schema/types/input/Exchange.js b/src/schema/types/input/Exchange.js new file mode 100644 index 000000000..738aca4ac --- /dev/null +++ b/src/schema/types/input/Exchange.js @@ -0,0 +1,15 @@ +import { + GraphQLInputObjectType, + GraphQLString, + GraphQLNonNull +} from 'graphql'; + +const Type = new GraphQLInputObjectType({ + name: 'ExchangeInput', + description: 'Payload for exchange input.', + fields: () => ({ + name: { type: new GraphQLNonNull(GraphQLString) } + }), +}); + +export default Type; diff --git a/src/schema/types/input/Plotter.js b/src/schema/types/input/Plotter.js new file mode 100644 index 000000000..1faa1a322 --- /dev/null +++ b/src/schema/types/input/Plotter.js @@ -0,0 +1,17 @@ +import { + GraphQLInputObjectType, + GraphQLString, + GraphQLNonNull +} from 'graphql'; + +const Type = new GraphQLInputObjectType({ + name: 'PlotterInput', + description: 'Payload for plotter input.', + fields: () => ({ + devTeam: { type: new GraphQLNonNull(GraphQLString) }, + codeName: { type: new GraphQLNonNull(GraphQLString) }, + moduleName: { type: new GraphQLNonNull(GraphQLString) } + }), +}); + +export default Type; diff --git a/src/schema/types/input/Product.js b/src/schema/types/input/Product.js new file mode 100644 index 000000000..9fb26fab2 --- /dev/null +++ b/src/schema/types/input/Product.js @@ -0,0 +1,24 @@ +import { + GraphQLInputObjectType, + GraphQLString, + GraphQLNonNull +} from 'graphql'; + +import { DataSetInputType } from './index'; +import { ExchangeInputType } from './index'; +import { PlotterInputType } from './index'; + +const Type = new GraphQLInputObjectType({ + name: 'ProductInput', + description: 'Payload for product input.', + fields: () => ({ + codeName: { type: new GraphQLNonNull(GraphQLString) }, + displayName: { type: new GraphQLNonNull(GraphQLString) }, + description: { type: GraphQLString }, + dataSets: { type: new GraphQLList(DataSetInputType) }, + exchangeList: { type: new GraphQLList(ExchangeInputType) }, + plotter: { type: PlotterInputType } + }), +}); + +export default Type; diff --git a/src/schema/types/input/index.js b/src/schema/types/input/index.js index 2e3d3dd55..6344400c3 100644 --- a/src/schema/types/input/index.js +++ b/src/schema/types/input/index.js @@ -3,11 +3,19 @@ import BotInputType from './Bot' import HostInputType from './Host' import FileInputType from './File' import DeleteTeamInputType from './DeleteTeam' +import DataSetInputType from './DataSet' +import ExchangeInputType from './Exchange' +import PlotterInputType from './Plotter' +import ProductInputType from './Product' export { TeamInputType, BotInputType, HostInputType, FileInputType, - DeleteTeamInputType + DeleteTeamInputType, + DataSetInputType, + ExchangeInputType, + PlotterInputType, + ProductInputType } diff --git a/src/storage/templates/Simulator/Commons.js b/src/storage/templates/Simulator/Commons.js index 570286d26..f96787ff9 100644 --- a/src/storage/templates/Simulator/Commons.js +++ b/src/storage/templates/Simulator/Commons.js @@ -1476,6 +1476,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { balanceAssetB = Number.MAX_SAFE_INTEGER } + let quotedBaseAsset = '"' + baseAsset + '"' + simulationRecord = { begin: candle.begin, end: candle.end, @@ -1509,7 +1511,8 @@ exports.newCommons = function newCommons(bot, logger, UTILITIES) { maximumBalanceA: maximumBalanceA, initialBalanceB: initialBalanceB, minimumBalanceB: minimumBalanceB, - maximumBalanceB: maximumBalanceB + maximumBalanceB: maximumBalanceB, + baseAsset: quotedBaseAsset } recordsArray.push(simulationRecord); diff --git a/src/storage/templates/Simulator/User.Bot.Daily.js b/src/storage/templates/Simulator/User.Bot.Daily.js index 7cc323c75..8cc5e30d0 100644 --- a/src/storage/templates/Simulator/User.Bot.Daily.js +++ b/src/storage/templates/Simulator/User.Bot.Daily.js @@ -168,7 +168,8 @@ record.maximumBalanceA + "," + record.initialBalanceB + "," + record.minimumBalanceB + "," + - record.maximumBalanceB + "]"; + record.maximumBalanceB + "," + + record.baseAsset + "]"; if (separator === "") { separator = ","; } diff --git a/src/storage/templates/Simulator/User.Bot.Market.js b/src/storage/templates/Simulator/User.Bot.Market.js index dcdcc835b..80afe2836 100644 --- a/src/storage/templates/Simulator/User.Bot.Market.js +++ b/src/storage/templates/Simulator/User.Bot.Market.js @@ -164,7 +164,8 @@ record.maximumBalanceA + "," + record.initialBalanceB + "," + record.minimumBalanceB + "," + - record.maximumBalanceB + "]"; + record.maximumBalanceB + "," + + record.baseAsset + "]"; if (separator === "") { separator = ","; } @@ -444,4 +445,3 @@ } } }; -