Merge branch 'develop' of https://github.com/Superalgos/Superalgos into develop

This commit is contained in:
Julian Molina committed 2021-08-09 10:37:54 +02:00
commit e8d0f25947
349 files changed
+599990 -54274

No files matched your search

+73
View File
@@ -0,0 +1,73 @@
exports.newMultiProject = function () {
let thisObject = {
initialize: initialize
}
return thisObject;
function initialize() {
/*
First thing is to load the project schema file.
*/
let PROJECTS_SCHEMA = require(global.env.PATH_TO_PROJECTS_REQUIRED + '/' + 'ProjectsSchema.json')
/*
Here we will setup the CL object, with all the
projects and modules that will have inside.
*/
global.CL = {
projects: {}
}
for (let i = 0; i < PROJECTS_SCHEMA.length; i++) {
let projectDefinition = PROJECTS_SCHEMA[i]
global.CL.projects[projectDefinition.propertyName] = {}
let projectInstance = global.CL.projects[projectDefinition.propertyName]
projectInstance.utilities = {}
projectInstance.globals = {}
projectInstance.functionLibraries = {}
projectInstance.taskModules = {}
projectInstance.processModules = {}
projectInstance.botModules = {}
if (projectDefinition.CL === undefined) { continue }
/* Set up Utilities of this Project */
if (projectDefinition.CL.utilities !== undefined) {
for (let j = 0; j < projectDefinition.CL.utilities.length; j++) {
let utilityDefinition = projectDefinition.CL.utilities[j]
let path = global.env.PATH_TO_PROJECTS_REQUIRED + '/' + projectDefinition.name + '/' + 'CL' + '/' + 'Utilities' + '/' + utilityDefinition.fileName
let requiredObject = require(path)
let requiredFunction = requiredObject[utilityDefinition.functionName]
projectInstance.utilities[utilityDefinition.propertyName] = requiredFunction.call()
}
}
/* Set up Globals of this Project */
if (projectDefinition.CL.globals !== undefined) {
for (let j = 0; j < projectDefinition.CL.globals.length; j++) {
let globalDefinition = projectDefinition.CL.globals[j]
let path = global.env.PATH_TO_PROJECTS_REQUIRED + '/' + projectDefinition.name + '/' + 'CL' + '/' + 'Globals' + '/' + globalDefinition.fileName
let requiredObject = require(path)
let requiredFunction = requiredObject[globalDefinition.functionName]
projectInstance.globals[globalDefinition.propertyName] = requiredFunction.call()
}
}
/* Set up Function Libraries of this Project */
if (projectDefinition.CL.functionLibraries !== undefined) {
for (let j = 0; j < projectDefinition.CL.functionLibraries.length; j++) {
let functionLibraryDefinition = projectDefinition.CL.functionLibraries[j]
let path = global.env.PATH_TO_PROJECTS_REQUIRED + '/' + projectDefinition.name + '/' + 'CL' + '/' + 'Function-Libraries' + '/' + functionLibraryDefinition.fileName
let requiredObject = require(path)
let requiredFunction = requiredObject[functionLibraryDefinition.functionName]
projectInstance.functionLibraries[functionLibraryDefinition.propertyName] = requiredFunction.call()
}
}
}
}
}
+32 -3
View File
@@ -64,12 +64,26 @@ let EVENT_SERVER = require('./eventServer.js')
let TASK_MANAGER_SERVER = require('./taskManagerServer.js')
let CCXT_SERVER = require('./ccxtServer.js')
let WEB3_SERVER = require('./web3Server.js')
let GITHUB_SERVER = require('./githubServer.js')
/* Network Interfaces */
let WEB_SOCKETS_INTERFACE = require('./webSocketsServer.js')
let HTTP_INTERFACE = require('./httpInterface.js')
try {
/*
Setting up the modules that will be available for the Servers Running inside this Client
*/
let MULTI_PROJECT = require('./MultiProject.js');
let MULTI_PROJECT_MODULE = MULTI_PROJECT.newMultiProject()
MULTI_PROJECT_MODULE.initialize()
/*
Setting up external dependencies.
*/
CL.nodeModules = {
nodeFetch: require('node-fetch')
}
console.log('CLIENT SERVERS:')
console.log('')
@@ -87,7 +101,7 @@ try {
PROJECT_FILE_SERVER.initialize()
PROJECT_FILE_SERVER.run()
console.log('Project File Server ......................................... Started')
PLUGIN_SERVER = PLUGIN_SERVER.newPluginServer()
PLUGIN_SERVER.initialize()
PLUGIN_SERVER.run()
@@ -112,12 +126,17 @@ try {
CCXT_SERVER.initialize()
CCXT_SERVER.run()
console.log('CCXT Server ................................................. Started')
WEB3_SERVER = WEB3_SERVER.newWeb3Server()
WEB3_SERVER.initialize()
WEB3_SERVER.run()
console.log('WEB3 Server ................................................. Started')
GITHUB_SERVER = GITHUB_SERVER.newGithubServer()
GITHUB_SERVER.initialize()
GITHUB_SERVER.run()
console.log('Github Server ............................................... Started')
console.log('')
console.log('CLIENT INTERFACES:')
console.log('')
@@ -127,7 +146,16 @@ try {
WEB_SOCKETS_INTERFACE.run()
console.log('Web Sockets Interface ....................................... Listening at port ' + global.env.WEB_SOCKETS_INTERFACE_PORT)
HTTP_INTERFACE = HTTP_INTERFACE.newHttpInterface(WEB_SERVER, DATA_FILE_SERVER, PROJECT_FILE_SERVER, UI_FILE_SERVER, PLUGIN_SERVER, CCXT_SERVER, WEB3_SERVER)
HTTP_INTERFACE = HTTP_INTERFACE.newHttpInterface(
WEB_SERVER,
DATA_FILE_SERVER,
PROJECT_FILE_SERVER,
UI_FILE_SERVER,
PLUGIN_SERVER,
CCXT_SERVER,
WEB3_SERVER,
GITHUB_SERVER
)
HTTP_INTERFACE.initialize()
HTTP_INTERFACE.run()
console.log('Http Interface .............................................. Listening at port ' + global.env.HTTP_INTERFACE_PORT)
@@ -143,6 +171,7 @@ try {
console.log("What's next? This is the current development pipeline:")
console.log('')
console.log('Superalgos P2P Network ...................................... Will allow algo-traders to share trading signals with Superalgos users consuming these signals via a mobile app.')
console.log('Real-time Trading Signals ................................... Will allow users to emit trading signals and be rewarded with SA Tokens.')
console.log('Superalgos Mobile ........................................... Will allow users to consume trading signals for free and autonomously execute trades from their mobile phones.')
console.log('Ethereum Integration ........................................ Will allow mining data from an Ethereum network node, and bring it into the Superalgos workflow.')
+507
View File
@@ -0,0 +1,507 @@
exports.newGithubServer = function newGithubServer() {
const MODULE = "Github Server"
let thisObject = {
getGithubStars: getGithubStars,
getGithubWatchers: getGithubWatchers,
getGithubForks: getGithubForks,
mergePullRequests: mergePullRequests,
initialize: initialize,
finalize: finalize,
run: run
}
const GITHUB_API_WAITING_TIME = 250
return thisObject
function finalize() {
}
function initialize() {
}
function run() {
}
async function getGithubStars(repository, username, token) {
return await getGithubUsernames('activity', 'listStargazersForRepo', repository, username, token)
}
async function getGithubWatchers(repository, username, token) {
return await getGithubUsernames('activity', 'listWatchersForRepo', repository, username, token)
}
async function getGithubForks(repository, username, token) {
return await getGithubUsernames('repos', 'listForks', repository, username, token)
}
async function mergePullRequests(commitMessage, username, token) {
return await mergeGithubPullRequests(commitMessage, username, token)
}
async function getGithubUsernames(endpoint, method, repository, username, token) {
try {
repository = unescape(repository)
username = unescape(username)
token = unescape(token)
let error
let githubListArray = []
return await getRepoInfo()
async function getRepoInfo() {
await doGithub()
if (error !== undefined) {
let docs = {
project: 'Governance',
category: 'Topic',
type: 'Gov Error - Get Repository Information',
anchor: undefined,
placeholder: {}
}
return respondWithDocsObject(docs, error)
}
return {
result: global.DEFAULT_OK_RESPONSE.result,
githubListArray: githubListArray
}
}
async function doGithub() {
const { Octokit } = require("@octokit/rest")
const octokit = new Octokit({
auth: token,
userAgent: 'Superalgos Beta 11'
})
await getList()
async function getList() {
const repo = repository
const owner = 'Superalgos'
const per_page = 100 // Max
let page = 0
let lastPage = false
while (lastPage === false) {
try {
page++
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
let listResponse = await octokit[endpoint][method]({
owner,
repo,
per_page,
page
});
if (listResponse.data.length < 100) {
lastPage = true
}
for (let i = 0; i < listResponse.data.length; i++) {
let listItem = listResponse.data[i]
let githubUsername
switch (endpoint) {
case 'activity': {
githubUsername = listItem.login
break
}
case 'repos': {
githubUsername = listItem.owner.login
break
}
}
//console.log(listItem)
githubListArray.push(githubUsername)
}
console.log('[INFO] Github Server -> getRepoInfo -> doGithub -> getList -> ' + method + ' Page = ' + page)
console.log('[INFO] Github Server -> getRepoInfo -> doGithub -> getList -> ' + method + ' Received = ' + listResponse.data.length)
} catch (err) {
console.log(err)
if (err.stack.indexOf('last page') >= 0) {
return
} else {
console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->Method call produced an error.')
console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->err.stack = ' + err.stack)
console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->repository = ' + repository)
console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->username = ' + username)
console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->token starts with = ' + token.substring(0, 10) + '...')
console.log('[ERROR] Github Server -> getRepoInfo -> doGithub -> getList ->token ends with = ' + '...' + token.substring(token.length - 10))
error = err
}
}
}
}
}
} catch (err) {
console.log('[ERROR] Github Server -> getRepoInfo -> Method call produced an error.')
console.log('[ERROR] Github Server -> getRepoInfo -> err.stack = ' + err.stack)
console.log('[ERROR] Github Server -> getRepoInfo -> repository = ' + repository)
console.log('[ERROR] Github Server -> getRepoInfo -> username = ' + username)
console.log('[ERROR] Github Server -> getRepoInfo -> token starts with = ' + token.substring(0, 10) + '...')
console.log('[ERROR] Github Server -> getRepoInfo -> token ends with = ' + '...' + token.substring(token.length - 10))
let error = {
result: 'Fail Because',
message: err.message,
stack: err.stack
}
return error
}
}
async function mergeGithubPullRequests(commitMessage, username, token) {
try {
commitMessage = unescape(commitMessage)
username = unescape(username)
token = unescape(token)
const repository = 'Superalgos'
/* Unsavping # */
for (let i = 0; i < 10; i++) {
commitMessage = commitMessage.replace('_SLASH_', '/')
commitMessage = commitMessage.replace('_HASHTAG_', '#')
}
let error
let githubPrListArray = []
return await processOpenPullRequests()
async function processOpenPullRequests() {
await doGithub()
if (error !== undefined) {
let docs = {
project: 'Governance',
category: 'Topic',
type: 'Gov Error - Merge Pull Requests',
anchor: undefined,
placeholder: {}
}
return respondWithDocsObject(docs, error)
}
return {
result: global.DEFAULT_OK_RESPONSE.result
}
}
async function doGithub() {
try {
const repo = repository
const owner = 'Superalgos'
const { Octokit } = require("@octokit/rest")
const octokit = new Octokit({
auth: token,
userAgent: 'Superalgos Beta 11'
})
await getPrList()
await mergePrs()
async function getPrList() {
const per_page = 100 // Max
let page = 0
let lastPage = false
while (lastPage === false) {
try {
page++
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
let listResponse = await octokit.rest.pulls.list({
owner: owner,
repo: repo,
state: 'open',
head: 'develop',
base: 'develop',
sort: undefined,
direction: undefined,
per_page: per_page,
page: page
});
if (listResponse.data.length < 100) {
lastPage = true
}
console.log('[INFO] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList -> Receiving Page = ' + page)
for (let i = 0; i < listResponse.data.length; i++) {
let pullRequest = listResponse.data[i]
console.log('[INFO] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList -> Pull Request "' + pullRequest.title + '" found and added to the list to validate. ')
githubPrListArray.push(pullRequest)
}
console.log('[INFO] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList -> Received = ' + listResponse.data.length)
} catch (err) {
console.log(err)
if (err.stack.indexOf('last page') >= 0) {
return
} else {
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->Method call produced an error.')
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->err.stack = ' + err.stack)
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->repository = ' + repository)
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->username = ' + username)
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->token starts with = ' + token.substring(0, 10) + '...')
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> getPrList ->token ends with = ' + '...' + token.substring(token.length - 10))
error = err
}
}
}
}
async function mergePrs() {
/*
In order to automatically merge a PRs we will run several validations first.
We want to automate specifically the merging of Profile File changes at the
Governance System done by the same Github user name that matches the profile
changed. We will also not do the merge if there are more than one file at the
PR.
We will go through the list of open PRs and run the validations at each one of them.
*/
console.log('[INFO] Github Server -> mergeGithubPullRequests -> Ready to Validate ' + githubPrListArray.length + ' pull requests. ')
for (let i = 0; i < githubPrListArray.length; i++) {
let pullRequest = githubPrListArray[i]
/*
Lets get the files changed at this Pull Request.
*/
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
let listResponse = await octokit.rest.pulls.listFiles({
owner: owner,
repo: repo,
pull_number: pullRequest.number
});
/*
Validation #1: If the PR has more than one file, then we will not automatically
merge it.
*/
if (listResponse.data.length !== 1) {
console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #1 Failed -> Pull Request "' + pullRequest.title + '" not merged because it contains more than 1 file. -> fileCount = ' + listResponse.data.length)
/*
We will close PRs that contains any User Profile file together with other files in the same Pull Request.
This will avoid manual merges to include User Profile files.
*/
for (j = 0; j < listResponse.data.length; j++) {
let pullRequestFile = listResponse.data[j]
let fileContentUrl = pullRequestFile.raw_url
if (fileContentUrl.indexOf('Governance/Plugins/User-Profiles') >= 0) {
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
await octokit.rest.issues.createComment({
owner: owner,
repo: repo,
issue_number: pullRequest.number,
body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that a User Profile file... \n\n' + fileContentUrl + '\n\n...was submitted together with ' + (listResponse.data.length - 1) + ' other file/s. User Profiles files as per the Governance System rules, must be the only file present at a Pull Request in order to pass all the validations and be automatically merged.'
});
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
await octokit.rest.pulls.update({
owner: owner,
repo: repo,
pull_number: pullRequest.number,
state: 'closed'
});
break
}
}
continue
}
let pullRequestFile = listResponse.data[0]
/*
Validation #2: File Name must be the same to the Github Username of the PR owner.
*/
let fileContentUrl = pullRequestFile.raw_url
if (fileContentUrl.indexOf('Governance/Plugins/User-Profiles') < 0) {
/*
If it is not a user profile then there is no need to auto merge.
*/
console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #2 Failed -> Pull Request "' + pullRequest.title + '" not merged because the file modified at the Pull Request is not a User Profile file. -> fileContentUrl = ' + fileContentUrl)
continue
}
let splittedURL = fileContentUrl.split('/')
let fileName = splittedURL[splittedURL.length - 1]
let splittedFileName = fileName.split('.')
fileName = splittedFileName[0]
let githubUsername = pullRequest.user.login
if (githubUsername !== fileName) {
console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #2 Failed -> Pull Request "' + pullRequest.title + '" not merged because the Github Username is not equal to the File Name. -> Github Username = ' + githubUsername + '-> fileName = ' + fileName)
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
await octokit.rest.issues.createComment({
owner: owner,
repo: repo,
issue_number: pullRequest.number,
body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that the Github User "' + githubUsername + '" who submitted it, is not equal to the name of the User Profile Plugin File.\n\n File Name = "' + fileName + '"'
});
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
await octokit.rest.pulls.update({
owner: owner,
repo: repo,
pull_number: pullRequest.number,
state: 'closed'
});
continue
}
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
let fileContent = await CL.projects.foundations.utilities.webAccess.fetchAPIDataFile(fileContentUrl)
let userProfile = JSON.parse(fileContent)
/*
Validation #3: The file changed at the PR is a User Profile.
*/
if (userProfile.type !== 'User Profile') {
console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #3 Failed -> Pull Request "' + pullRequest.title + '" not merged because the file modified is not a User Profile. -> Type = ' + userProfile.type)
continue
}
/*
Validation #4: The message signed at the config is not the Github Username.
*/
let config = JSON.parse(userProfile.config)
let messageSigned = config.signature.message
if (messageSigned !== githubUsername) {
console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #4 Failed -> Pull Request "' + pullRequest.title + '" not merged because the Github Username is not equal to the Message Signed at the User Profile. -> Github Username = ' + githubUsername + '-> messageSigned = ' + messageSigned)
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
await octokit.rest.issues.createComment({
owner: owner,
repo: repo,
issue_number: pullRequest.number,
body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that the Github User "' + githubUsername + '" who submitted it, is not equal to the Message Signed at the User Profile.\n\n Message Signed = "' + messageSigned + '"'
});
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
await octokit.rest.pulls.update({
owner: owner,
repo: repo,
pull_number: pullRequest.number,
state: 'closed'
});
continue
}
/*
Validation #5: The name of the User Profile node is not the Github Username.
*/
if (userProfile.name !== githubUsername) {
console.log('[INFO] Github Server -> mergeGithubPullRequests -> Validation #5 Failed -> Pull Request "' + pullRequest.title + '" not merged because the Github Username is not equal to the User Profile node\'s name. -> Github Username = ' + githubUsername + '-> userProfile.name = ' + userProfile.name)
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
await octokit.rest.issues.createComment({
owner: owner,
repo: repo,
issue_number: pullRequest.number,
body: 'This Pull Request could not be automatically merged and was closed by the Superalgos Governance System because it was detected that the Github User "' + githubUsername + '" who submitted it, is not equal to the User Profile node\'s name.\n\n User Profile Name = "' + userProfile.name + '"'
});
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
await octokit.rest.pulls.update({
owner: owner,
repo: repo,
pull_number: pullRequest.number,
state: 'closed'
});
continue
}
/*
All validations passed, we will proceed an merge this Pull Request.
*/
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
let mergeResponse = await octokit.rest.pulls.merge({
owner: owner,
repo: repo,
pull_number: pullRequest.number,
commit_title: 'Changes in User Profile done by Profile Owner ' + githubUsername + ' automatically merged by Superalgos.'
});
if (mergeResponse.data.merged !== true) {
console.log('[WARN] Github Server -> mergeGithubPullRequests -> Merge Failed -> Pull Request "' + pullRequest.title + '" not merged because Github could not merge it. -> mergeResponse.message = ' + mergeResponse.data.message)
continue
} else {
console.log('[INFO] Github Server -> mergeGithubPullRequests -> Merge Succed -> Pull Request "' + pullRequest.title + '" successfully merged. -> mergeResponse.message = ' + mergeResponse.data.message)
await CL.projects.foundations.utilities.asyncFunctions.sleep(GITHUB_API_WAITING_TIME)
await octokit.rest.issues.createComment({
owner: owner,
repo: repo,
issue_number: pullRequest.number,
body: 'This Pull Request was automatically merged by the Superalgos Governance System because it was detected that the Github User " ' + githubUsername + '" who submitted it, modified its own User Profile Plugin File and nothning else but that file. All validations were successfull.'
});
continue
}
}
}
} catch (err) {
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> doGithub -> err.stack = ' + err.stack)
}
}
} catch (err) {
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> Method call produced an error.')
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> err.stack = ' + err.stack)
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> repository = ' + repository)
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> username = ' + username)
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> token starts with = ' + token.substring(0, 10) + '...')
console.log('[ERROR] Github Server -> mergeGithubPullRequests -> token ends with = ' + '...' + token.substring(token.length - 10))
let error = {
result: 'Fail Because',
message: err.message,
stack: err.stack
}
return error
}
}
function respondWithDocsObject(docs, error) {
if (error.message !== undefined) {
docs.placeholder.errorMessage = {
style: 'Error',
text: error.message
}
}
if (error.stack !== undefined) {
docs.placeholder.errorStack = {
style: 'Javascript',
text: error.stack
}
}
if (error.code !== undefined) {
docs.placeholder.errorCode = {
style: 'Json',
text: error.code
}
}
docs.placeholder.errorDetails = {
style: 'Json',
text: JSON.stringify(error, undefined, 4)
}
let customResponse = {
result: global.CUSTOM_FAIL_RESPONSE.result,
docs: docs
}
return customResponse
}
}
+72 -149
View File
@@ -1,4 +1,13 @@
exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVER, PROJECT_FILE_SERVER, UI_FILE_SERVER, PLUGIN_SERVER, CCXT_SERVER, WEB3_SERVER) {
exports.newHttpInterface = function newHttpInterface(
WEB_SERVER,
DATA_FILE_SERVER,
PROJECT_FILE_SERVER,
UI_FILE_SERVER,
PLUGIN_SERVER,
CCXT_SERVER,
WEB3_SERVER,
GITHUB_SERVER
) {
/*
IMPORTANT: If you are reviewing the code of the project please note
@@ -366,6 +375,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
}
break
}
case 'Save-Concept-Schema': {
getBody(processRequest)
@@ -396,6 +406,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
}
break
}
case 'Save-Topic-Schema': {
getBody(processRequest)
@@ -426,6 +437,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
}
break
}
case 'Save-Tutorial-Schema': {
getBody(processRequest)
@@ -456,6 +468,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
}
break
}
case 'Save-Review-Schema': {
getBody(processRequest)
@@ -486,6 +499,7 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
}
break
}
case 'Save-Book-Schema': {
getBody(processRequest)
@@ -1019,130 +1033,80 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
}
break
case 'Gov': {
switch (requestParameters[2]) { // switch by command
case 'getGithubStars': {
getProfiles('activity', 'listStargazersForRepo')
break
}
case 'getGithubWatchers': {
getProfiles('activity', 'listWatchersForRepo')
break
}
case 'getGithubForks': {
getProfiles('repos', 'listForks')
break
}
}
case 'GOV': {
/*
This is the Governance endpoint at the Http Interface. All methods
related to the Governance System are implemented here and routed
to the backend Servers that can process them.
*/
getBody(processRequest)
function getProfiles(endpoint, method) {
async function processRequest(body) {
try {
const GITHUB_API_WAITING_TIME = 250
const repository = unescape(requestParameters[3])
const username = unescape(requestParameters[4])
const token = unescape(requestParameters[5])
let error
let githubListArray = []
let params = JSON.parse(body)
getRepoInfo()
switch (params.method) {
case 'getGithubStars': {
async function getRepoInfo() {
await doGithub()
if (error !== undefined) {
let serverResponse = await GITHUB_SERVER.getGithubStars(
params.repository,
params.username,
params.token
)
let docs = {
project: 'Governance',
category: 'Topic',
type: 'Gov Error - Get Repository Information',
anchor: undefined,
placeholder: {}
}
respondWithDocsObject(docs, error)
respondWithContent(JSON.stringify(serverResponse), httpResponse)
return
}
case 'getGithubWatchers': {
respondWithContent(JSON.stringify(githubListArray), httpResponse)
}
let serverResponse = await GITHUB_SERVER.getGithubWatchers(
params.repository,
params.username,
params.token
)
async function doGithub() {
respondWithContent(JSON.stringify(serverResponse), httpResponse)
return
}
case 'getGithubForks': {
const { Octokit } = require("@octokit/rest")
let serverResponse = await GITHUB_SERVER.getGithubForks(
params.repository,
params.username,
params.token
)
const octokit = new Octokit({
auth: token,
userAgent: 'Superalgos Beta 11'
})
await getList()
respondWithContent(JSON.stringify(serverResponse), httpResponse)
return
}
case 'mergePullRequests': {
async function getList() {
const repo = repository
const owner = 'Superalgos'
const per_page = 100 // Max
let page = 0
let lastPage = false
let serverResponse = await GITHUB_SERVER.mergePullRequests(
params.commitMessage,
params.username,
params.token
)
while (lastPage === false) {
try {
page++
await sleep(GITHUB_API_WAITING_TIME)
let listResponse = await octokit[endpoint][method]({
owner,
repo,
per_page,
page
});
respondWithContent(JSON.stringify(serverResponse), httpResponse)
return
}
case 'payContributors': {
if (listResponse.data.length < 100) {
lastPage = true
}
let serverResponse = await WEB3_SERVER.payContributors(
params.signature
)
for (let i = 0; i < listResponse.data.length; i++) {
let listItem = listResponse.data[i]
let githubUsername
switch(endpoint) {
case 'activity' : {
githubUsername = listItem.login
break
}
case 'repos' : {
githubUsername = listItem.owner.login
break
}
}
//console.log(listItem)
githubListArray.push(githubUsername)
}
console.log('[INFO] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList -> ' + method + ' Page = ' + page)
console.log('[INFO] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList -> ' + method + ' Received = ' + listResponse.data.length)
} catch (err) {
console.log(err)
if (err.stack.indexOf('last page') >= 0) {
return
} else {
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->Method call produced an error.')
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->err.stack = ' + err.stack)
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->repository = ' + repository)
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->username = ' + username)
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->token starts with = ' + token.substring(0, 10) + '...')
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> doGithub -> getList ->token ends with = ' + '...' + token.substring(token.length - 10))
error = err
}
}
}
respondWithContent(JSON.stringify(serverResponse), httpResponse)
return
}
default: {
respondWithContent(JSON.stringify({ error: 'Method ' + params.method + ' is invalid.' }), httpResponse)
}
}
} catch (err) {
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> Method call produced an error.')
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> err.stack = ' + err.stack)
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> repository = ' + repository)
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> username = ' + username)
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> token starts with = ' + token.substring(0, 10) + '...')
console.log('[ERROR] httpInterface -> Gov -> getRepoInfo -> token ends with = ' + '...' + token.substring(token.length - 10))
console.log('[ERROR] httpInterface -> GOV -> Method call produced an error.')
console.log('[ERROR] httpInterface -> GOV -> err.stack = ' + err.stack)
console.log('[ERROR] httpInterface -> GOV -> Params Received = ' + body)
let error = {
result: 'Fail Because',
@@ -1152,43 +1116,8 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
respondWithContent(JSON.stringify(error), httpResponse)
}
}
function respondWithDocsObject(docs, error) {
if (error.message !== undefined) {
docs.placeholder.errorMessage = {
style: 'Error',
text: error.message
}
}
if (error.stack !== undefined) {
docs.placeholder.errorStack = {
style: 'Javascript',
text: error.stack
}
}
if (error.code !== undefined) {
docs.placeholder.errorCode = {
style: 'Json',
text: error.code
}
}
docs.placeholder.errorDetails = {
style: 'Json',
text: JSON.stringify(error, undefined, 4)
}
let customResponse = {
result: global.CUSTOM_FAIL_RESPONSE.result,
docs: docs
}
respondWithContent(JSON.stringify(customResponse), httpResponse)
}
}
break
}
case 'LegacyPlotter.js':
{
respondWithFile(global.env.PATH_TO_CLIENT + 'WebServer/LegacyPlotter.js', httpResponse)
@@ -2133,10 +2062,4 @@ exports.newHttpInterface = function newHttpInterface(WEB_SERVER, DATA_FILE_SERVE
return files.reduce((a, f) => a.concat(f), []);
}
}
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms)
})
}
}
+1993 -1364
View File
File diff suppressed because it is too large. Load diff
+6 -5
View File
@@ -7,14 +7,15 @@
"name": "Luis-Fernando-Molina"
},
"dependencies": {
"@octokit/rest": "^18.0.12",
"@octokit/rest": "^18.9.0",
"ccxt": "^1.51.98",
"child_process": "^1.0.2",
"lookpath": "^1.2.1",
"lookpath": "^1.2.2",
"open": "^6.4.0",
"rimraf": "^3.0.2",
"simple-git": "^2.31.0",
"web3": "^1.3.0",
"ws": "^7.4.6"
"simple-git": "^2.42.0",
"web3": "^1.5.0",
"ws": "^7.4.6",
"node-fetch": "2.6.1"
}
}
+357
View File
@@ -0,0 +1,357 @@
# Getting Started Guide
All procedures are the same for Windows, Linux, or Mac OS. Raspberry Pi terminal commands have been included for ease of use.
> **IMPORTANT:** Remote installations and minimalist hardware —both virtual and physical— are better suited for production deployments, where the use of the GUI is minimal. We highly recommend learning Superalgos in a local installation. Mastering the system takes time, and the use of the GUI to go through in-app tutorials is crucial during the learning process. Your experience will be orders of magnitude better if you follow this advice: leave remote installations and minimalist hardware for when you are ready to start trading live.
# Pre-Requisites
## 1. Node JS Installation
If you don't have it yet, download and install Node.js.
Node JS is an open-source server environment required to run Superalgos.
**A.** Go to the Node JS [download page](https://nodejs.org/en/download/).
**B.** Download your system’s installer. Select *LTS Recommended for Most Users* and click the big Windows or macOS Installer button. If you are on Linux, the installer is listed further down the page.
**C.** Run the installer with the default configuration — just click Next until Node.JS is fully installed. That's it! You can continue with step 2 (Git Installation).
<hr>
**NODE JS INSTALLATION FOR RASPBERRY PI USERS**
You may install Node.JS just like you would on any other machine as per the above instructions. As an alternative, you may also try the following from the SSH Terminal.
**NOTE:** It is best to use the most current and updated version of the FULL PiOS image.
```
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
```
Followed by:
```
sudo apt-get install -y nodejs
```
It is also required to install the Node Package Manager for dependancy management.
```
sudo apt install npm
```
You may also type the following to verify Node.js and NPM installation and version.
```
node -v
```
```
npm -v
```
<hr>
## 2. Git Installation
Download and install Git.
Git is an open-source distributed version control system required to download and stay up to date with Superalgos.
**A.** Go to the Git [download page](https://git-scm.com/downloads).
**B.** Download the version for your Operating System.
**C.** Run the installer with the default configuration — just click Next until Git is fully installed.
**IMPORTANT:** The latest version of Git is required to handle the authentication with GitHub.com.
**NOTE FOR MAC USERS:** Depending on your setup, installing Git may be optional. The native XCode Command Line Developer Tools seems to work well. If you do install Git, we have tested Tim Harper's binary installer successfully.
<hr>
**GIT INSTALLATION FOR RASPBERRY PI USERS**
Just like with Node.JS, you may follow the above instructions to install Git, or use the SSH Terminal command. The most recent version of PiOS has Git already installed, so this may give you an error. The error will not affect your installation.
```
sudo apt-get install git
```
<hr>
## 3. Google Chrome or Safari
Use Chrome, or Safari on Mac. These are the only tested browsers.
**A.** Go to the Chrome [download page](https://www.google.com/chrome/).
**B.** Run the installer.
Before you begin, it is recommended that you set up Chrome/Safari as your default browser.
**IMPORTANT:** Use Chrome/Safari so that you have a similar environment as the dev team in case you need help. We are not testing on any other browsers, and it is a well-known fact that browsers behave differently.
# Superalgos Client Installation
## 1. Fork the Superalgos Repository
**A.** Scroll the page all the way to the top. Find and click the **Fork** button to create your fork/copy of this repository. To fork Superalgos you need a Github account. If you don't have one, go ahead and create it.
**NOTE:** A Fork is required for your contributions to the project. The reason why Superalgos is free and open-source is that the project has set up a <a href="https://superalgos.org/community-business.shtml" target="_blank">Collective Business</a> in which all users may participate. The way to participate is to <a href="https://superalgos.org/community-contribute.shtml" target="_blank">contribute</a> to make Superalgos better. The project's <a href="https://superalgos.org/token-overview.shtml" target="_blank">token</a> is distributed among contributors.
## 2. Clone Your Fork
**A.** Once the fork is created, you will land on the page of your fork. Copy the URL from your browser's address bar.
**B.** In your computer/laptop/server, open a command prompt or terminal. Make sure you are in a directory where you have write permissions (on most systems the terminal will open in your user’s home directory, so you’re good). Clone the git repository using the command:
```
git clone <URL of your Superalgos fork>
```
For example, if your Github username is John, the command will look like this:
```
git clone https://github.com/John/Superalgos
```
This creates the `Superalgos` folder in the current directory, which contains the whole installation.
## 3. Install Node Dependencies
**A.** After the Superalgos directory has been installed, the final step of installation is to set up the necessary node dependencies.
**B.** In the same command prompt or terminal you just used, type the following command:
```
node setup
```
Then wait until you are able to type within the terminal again.
This command will install and configure all additional dependencies needed by Superalgos. It will also install desktop and start menu shortcuts.
**NOTE FOR USERS INSTALLING MULTIPLE INSTANCES OF SUPERALGOS ON THE SAME MACHINE:** In order to avoid name conflicts between shortcuts, make sure to rename each Superalgos directory before running `node setup`.
Congratulations your installation is complete!
> **The Usage section below explains how to run the app.**
<hr>
**DEPENDENCY INSTALLATION FOR RASPBERRY PI USERS**
As noted above, running `node setup` installs GUI shortcuts by default. To suppress this behavior in headless installations, add the `noShortcuts` flag as follows:
```
node setup noShortcuts
```
<hr>
**Troubleshooting Dependency Installation**
If you are having difficulty running the node setup command here are a few common issues that may be getting in the way.
**1.** Check the version of node and npm you have installed. Make sure that you are running an updated version of node greater than version 12 and npm greater than version 5. You can check which version you have by typing `node -v` and `npm -v` into a command prompt or terminal. If your version numbers are below these, you can update your installation by following the instructions outlined in the "Node JS Installation" step above.
**2.** If you are installing Superalgos in an administratively protected directory you will need to do one of the following:
- For Windows start your command prompt as an administrator.
- For Linux and Mac Systems make sure to add the sudo command to node setup. This will look like `sudo node setup`.
**3.** For Windows it is important that you have C:\Windows\System32 added to your global PATH. For instructions on how to do this google "add to the path on Windows 10."
<hr>
## 4. Installation Notes
**A.** You need to make a fork so that you may contribute work. Superalgos is a Community project and you are expected to contribute, like everyone else. You don't need to be a technical person to contribute. Fixing a typo in the docs or translating a paragraph into your native language are valuable contributions too. Superalgos has built-in features that make contributing easy. Help make Superalgos better and Superalgos will better serve you! [Free-riding is not cool](https://en.wikipedia.org/wiki/Free-rider_problem), particularly on free, open-source, Community-driven projects.
**B.** The software includes an in-app self-update command / feature. It will help you stay up-to-date with the latest version of the software. Updates are on-demand, so don't worry about undesired updates. The project moves very fast and new features become available regularly, particularly if you choose to run the software in the ```develop``` branch (you may switch branches from within the app).
**C.** It is a good idea to perodically run the `node setup` command to keep the underlying dependencies for your Superalgos installation up to date.
**D.** Before installing the client on a remote computer in an attempt to access the UI from a different machine, we highly recommend you do a standard installation on your PC / laptop first. Leave your Raspberry Pi or VPS for later, once you have done all available tutorials. This single tip will save you a lot of time: you don't need to add complexity before you learn how to handle the app, and the GUI performs best in a local installation.
# Usage
## 1. Run the Client and GUI
**A.** To run Superalgos, go to the Superalgos directory/folder and run this command:
```
node run
```
The Client will run on your terminal and the GUI will launch on your default browser. If Chrome/Safari is not your default browser, copy the URL, close the browser, open Chrome/Safari, and paste the URL. Be patient... it takes a few seconds to fully load the GUI.
A Welcome Tutorial pops-up automatically. You must do this Tutorial to finish the setup and to learn the basics. It's the ultimate onboarding experience, superior to all other resources available, including videos and the Docs.
![run-the-system-01](https://user-images.githubusercontent.com/13994516/107037804-e5fc6200-67bb-11eb-82f2-d0f40247fa14.gif)
If you are running a headless Raspberry Pi (one without a screen) you may need to change directories first and run Superalgos with the `minMemo` and `noBrowser` options.
```
cd Superalgos
```
then
```
node run minMemo noBrowser
```
In addition, you may use any of the automatically installed desktop and start menu shortcuts to launch Superalgos.
**NOTE:** Shortcuts are not currently supported on Mac. Collaborators are needed to finish this feature.
**B.** Enable Desktop Shortcut on Ubuntu
The majority of shortcuts that are automatically installed will work out of the box. Desktop shortcuts on Ubuntu, however, require a few additional steps to set up.
First, desktop icons need to be enabled within the Tweaks app.
* Check if Tweaks is installed.
* If not go to Ubuntu Software.
* Install Tweaks.
* Open Tweaks.
* Under extensions turn on Desktop Icons
![enable-ubuntu-shortcut](https://user-images.githubusercontent.com/55707292/117553927-f0780300-b019-11eb-9e36-46b509653283.gif)
**TIP:** If you do not see the desktop shortcut appear right away you may need to restart your computer.
Finally, you will need to enable the desktop shortcut.
* Right click Superalgos.desktop and select Allow Launching.
![allow-launching](https://user-images.githubusercontent.com/55707292/117553933-fcfc5b80-b019-11eb-872c-4fad81b184d2.gif)
Now both launcher and desktop shortcuts will launch Superalgos like any other program on your computer.
## 3. Usage Notes
We are testing the UI on Google Chrome and Safari on macOS only. It may work on other browsers as well &mdash; or not. If you are running on a different browser and ever need support, make sure you mention that fact upfront, or even better, try on Chrome/Safari first.
**TIP:** If your computer has 8 GB of RAM or less, use ```node run minMemo``` to run the system with minimal RAM requirements.
# Running Superalgos on a Headless Linux Server as a Daemon
If you’re running Superalgos on a headless linux server like a Raspberry Pi, you might want to run it as a daemon so it isn’t attached to your current login session. The easiest, most standard way to go about this is probably using `systemd`. Most linux distributions use it as default init system/service manager.
## Using `systemd`
Create a `superalgos.service` file looking like this (change `<user>` to your user name and `/path/to/Superalgos` to your Superalgos folder, for instance `/home/John/Superalgos`):
```
[Unit]
Description=Superalgos client
[Service]
Type=simple
User=<user>
WorkingDirectory=/path/to/Superalgos
ExecStart=/usr/bin/node run minMemo noBrowser
[Install]
WantedBy=multi-user.target
```
There is no need to run Superalgos as root so we’re running it as a user. The `minMemo` option assumes you’re running on a small machine like a Raspberry Pi, while `noBrowser` makes sense for running daemonized.
Now, as root (or using `sudo`), put the file `superalgos.service` you just created in `/etc/systemd/system/` and issue the command
```
systemctl enable superalgos
```
This will install the service so that Superalgos is started on boot. To start it manually, do (again as root or with `sudo`)
```
systemctl start superalgos
```
To see the output of Superalgos, use
```
journalctl -u superalgos
```
or to follow the output,
```
journalctl -u superalgos -f
```
# Uninstall
Superalgos writes nothing outside of the ```Superalgos``` folder other than shortcut files. To uninstall the software, follow these steps:
Open a terminal or command prompt and navigate to your main Superalgos directory and type the following command:
```
node uninstall
```
This will remove any shortcut files that have been installed.
Then simply delete the `Superalgos` folder. There will be nothing left on your computor.
# Welcome Tutorial
Once the app finishes loading, an interactive tutorial takes you by the hand and walks you all around the system while you learn the basic skills required to use the interface, mine data, backtest strategies, and even run a live trading session. It is highly recommended you follow the tutorial until the end, as it is carefully crafted to make your onboarding as easy as possible. Tutorials are the absolute best way to tackle the learning curve. You should do all tutorials before you start exploring other avenues on your own.
![welcome-tutorial-00](https://user-images.githubusercontent.com/13994516/107038771-4a6bf100-67bd-11eb-92e0-353525a972a9.gif)
**NOTE:** The tutorial uses Binance or Binance US as the exchange of choice. If you don’t have an account with Binance or Binance US, you will still be able to follow 100% of the tutorial. When you get to the live trading section, keep going even if you don't intend to run the session. You may learn how to work with other exchanges later on.
# Docker Deployments
Docker container images can be found at https://github.com/users/Superalgos/packages/container/package/superalgos
If you wish to run Superalgos over docker platform, follow these steps.
**Note:** This has not been extensively tested yet. If you run into troubles, please contact us at the [Superalgos Support Group](https://t.me/superalgossupport).
## 1. Install Docker
Follow the link to [install docker](https://docs.docker.com/engine/install/).
## 2. Run
### Option A. Using pre-built container
You will need to create local storage directories beforehand, by example with `mkdir Data-Storage Log-Files My-Workspaces`
```
docker run \
-d \
--rm \
--name superalgos \
-p 18041:18041 \
-p 34248:34248 \
-v $(pwd)/Data-Storage:/app/Data-Storage \
-v $(pwd)/Log-Files:/app/Log-Files \
-v $(pwd)/My-Workspaces:/app/My-Workspaces \
ghcr.io/superalgos/superalgos:latest
```
Now you can access the Superalgos UI at http://127.0.0.1:34248
To see console logs you can use `docker logs superalgos -f`
When you're done just exec `docker kill superalgos`
### Option B. Build container locally using docker-compose
Follow the link to [install docker-compose](https://docs.docker.com/compose/install/)
Run `docker-compose -f Docker/docker-compose.yml up`.
## Configure the Container Environment
### Available image tags
To avoid breaking changes, the `shasum hash` and the `release` tags are the best to use. These will generally ensure you are always running the same code. The other tags will change which code they are pointing to more frequently and without notice.
- `latest` : the absolute latest build
- `master` : the latest master branch build
- `develop` : the latest develop branch build
- `<shasum hash>` : a specific git commit hash
- `<release>` : corresponds with a Github Release (git tag), i.e. `beta-10`
### Environment variables
`PUID` and `GUID` environment variables can be used to help avoid permissions issues in the mounted volumes between the container environment and the local OS environment. The default `PUID` and `GUID` is `1000`. You can view the current user's PUID and GUID with the `id` command.
## Troubleshooting
Some users have reported the Docker installation was not working, and the root cause was that the ad blocker was blocking the scripts to run.
@@ -2,7 +2,14 @@
"type": "Tutorial",
"definition": {
"text": "The tutorial hierarchy features a free arrangement of Tutorial Topic and Tutorial Step nodes that make up a tutorial. Each node in the hierarchy, including the parent tutorial node, represents an HTML page that may be overlaid on top of both the Design Space and the Charting Space.",
"updated": 1617610222444
"updated": 1617610222444,
"translations": [
{
"language": "ES",
"text": "La jerarquía del tutorial presenta una disposición libre de los nodos Tutorial Topic y Tutorial Step que componen un tutorial. Cada nodo de la jerarquía, incluido el nodo del tutorial principal, representa una página HTML que puede superponerse en la parte superior de ambos Design Space y el Charting Space.",
"updated": 1627245866146
}
]
},
"paragraphs": [
{
@@ -0,0 +1,14 @@
exports.newFoundationsUtilitiesAsyncFunctions = function () {
let thisObject = {
sleep: sleep
}
return thisObject
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms)
})
}
}
@@ -0,0 +1,40 @@
exports.newFoundationsUtilitiesWebAccess = function () {
let thisObject = {
fetchAPIDataFile: fetchAPIDataFile
}
return thisObject
async function fetchAPIDataFile(url) {
let promise = new Promise((resolve, reject) => {
const fetch = CL.nodeModules.nodeFetch
/*
This is how we call the API.
*/
fetch(url)
.then((response) => {
if (response.status !== 200) {
console.log('[ERROR] fetchAPIData -> then -> url =' + url)
reject()
return
}
getResponseBody()
function getResponseBody() {
response.text().then(body => {
resolve(body)
})
}
})
.catch(err => {
console.log('[ERROR] fetchAPIData -> url =' + url)
reject()
})
}
)
return promise
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

@@ -1,26 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="206 -206 512 512" style="enable-background:new 206 -206 512 512;" xml:space="preserve">
<style type="text/css">
.st0{display:none;}
.st1{display:inline;}
.st2{fill:#E6EAEA;}
.st3{fill:#CDD4D5;}
.st4{fill:#FF8C29;}
.st5{fill:#FD6A33;}
</style>
<g id="Layer_3" class="st0">
<rect x="1030" y="-1030.4" class="st1" width="512" height="512.8"/>
</g>
<path class="st2" d="M462-206v512c141.4,0,256-114.6,256-256S603.4-206,462-206z"/>
<path class="st3" d="M206,50c0,141.4,114.6,256,256,256v-512C320.6-206,206-91.4,206,50z"/>
<polygon class="st4" points="462,-0.2 462,100.2 512.2,50 "/>
<polygon class="st5" points="411.8,50 462,100.2 462,-0.2 "/>
<polygon id="Fill-162" class="st4" points="576.2,50 576,50.2 622.6,96.8 669.4,50 622.2,2.9 575.6,49.5 "/>
<polygon class="st4" points="462,-157.4 462,-64.2 543.9,17.8 590.5,-28.8 "/>
<polygon class="st5" points="334.7,-30 381.2,16.6 462,-64.2 462,-157.4 "/>
<polygon class="st4" points="544.3,81.9 462,164.2 462,257.4 590.9,128.5 "/>
<polygon class="st5" points="380.5,82.6 333.9,129.2 462,257.4 462,164.2 "/>
<polygon class="st5" points="303,1.7 254.6,50 302.2,97.5 348.8,50.9 347.8,50 349.6,48.3 "/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><style>.cls-1{fill:#e6eaea;}.cls-2{fill:#ff8c29;}.cls-3{fill:#fd6a33;}</style></defs><title>binance-coin</title><g id="Circle"><g id="Circle_Back" data-name="Circle Back"><path class="cls-1" d="M0,256C0,397.4,114.6,512,256,512V0C114.6,0,0,114.6,0,256Z"/><path class="cls-1" d="M256,0V512c141.4,0,256-114.6,256-256S397.4,0,256,0Z"/></g></g><g id="bnb"><g id="Layer_2" data-name="Layer 2"><path class="cls-2" d="M189.8,228.8,256,162.6l66.23,66.23,38.52-38.52L256,85.56,151.28,190.28,189.8,228.8M85.56,256l38.52-38.53L162.6,256l-38.52,38.52ZM189.8,283.2,256,349.4l66.23-66.23,38.54,38.5,0,0L256,426.44,151.28,321.72l-.05-.05L189.8,283.2M349.4,256l38.52-38.52L426.44,256l-38.52,38.52Z"/><path class="cls-2" d="M295.07,256h0L256,216.89l-28.89,28.88h0l-3.32,3.32L217,255.94l-.06.05.06.06L256,295.11,295.09,256l0,0,0,0"/></g><polygon class="cls-3" points="151.28 190.28 189.8 228.8 189.8 228.8 256 162.6 256.02 162.62 256.02 85.58 256 85.56 151.28 190.28"/><rect class="cls-3" x="96.84" y="228.76" width="54.48" height="54.47" transform="translate(-144.68 162.73) rotate(-45)"/><polygon class="cls-3" points="189.8 283.2 189.8 283.2 151.23 321.67 151.28 321.72 256 426.44 256.02 426.42 256.02 349.38 256 349.4 189.8 283.2"/><polygon class="cls-3" points="227.11 245.77 223.79 249.09 216.95 255.94 216.89 255.99 216.95 256.05 256 295.11 256.02 295.09 256.02 216.91 256 216.89 227.11 245.77"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -0,0 +1 @@
<svg id="Layer_3" data-name="Layer 3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><style>.cls-1{fill:#e6eaea;}.cls-2{fill:#ff8c29;stroke:#f0b90b;}.cls-3{fill:#fd6a33;}</style></defs><title>binance-usd</title><path class="cls-1" d="M0,256C0,397.4,114.6,512,256,512V0C114.6,0,0,114.6,0,256Z"/><path class="cls-1" d="M256,0V512c141.4,0,256-114.6,256-256S397.4,0,256,0Z"/><g id="Layer_1-2" data-name="Layer 1-2"><path class="cls-2" d="M256,88l41.5,42.5L193,235l-41.5-41.5Z"/><path class="cls-2" d="M319,151l41.5,42.5L193,361l-41.5-41.5Z"/><path class="cls-2" d="M130,214l41.5,42.5L130,298,88.5,256.5Z"/><path class="cls-2" d="M382,214l41.5,42.5L256,424l-41.5-41.5Z"/></g><polygon class="cls-3" points="193 235 256 172 256 88 151.5 193.5 193 235"/><polygon class="cls-3" points="193 361 256 298 256 214.38 151.5 319.5 193 361"/><polygon class="cls-3" points="130 214 88.5 256.5 130 298 171.5 256.5 130 214"/><polygon class="cls-3" points="214.5 382.5 256 424 256 340.75 214.5 382.5"/></svg>

After

Width:  |  Height:  |  Size: 1004 B

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><style>.cls-1{fill:#e6eaea;}.cls-2{fill:#0295aa;}.cls-3{fill:#4acfd9;}</style></defs><title>chainlink</title><g id="circle"><g id="Circle_Back" data-name="Circle Back"><path class="cls-1" d="M0,256C0,397.4,114.6,512,256,512V0C114.6,0,0,114.6,0,256Z"/><path class="cls-1" d="M256,0V512c141.4,0,256-114.6,256-256S397.4,0,256,0Z"/></g></g><g id="link"><g id="Layer_1-2" data-name="Layer 1-2"><path class="cls-2" d="M256,156.52,342.23,206v99.45l-86,49.79-86.14-49.36V206.49l85.9-50m0-73L224.42,101.8l-86.08,50L106.73,170V342.47l31.61,18.24,86.2,49.49,31.61,18.23,31.61-18.23,85.9-49.85,31.61-18.24V169.4l-31.61-18.23L287.52,101.8,255.91,83.57Z"/></g><polygon class="cls-3" points="224.42 101.8 138.34 151.77 106.73 170.01 106.73 342.48 138.34 360.71 224.54 410.2 256 428.35 256 355.08 170.13 305.88 170.13 206.49 256 156.53 256 83.62 255.97 83.6 224.42 101.8"/><polygon class="cls-3" points="255.97 83.6 256 83.58 256 83.57 255.91 83.57 255.97 83.6"/></g></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><style>.cls-1{fill:#365558;}.cls-2{fill:#0295aa;}.cls-3{fill:#fff;}.cls-4{fill:#e6eaea;}</style></defs><title>euro</title><path class="cls-1" d="M1,257C1,398.4,115.6,513,257,513V1C115.6,1,1,115.6,1,257Z"/><path class="cls-2" d="M257,1V513c141.4,0,256-114.6,256-256S398.4,1,257,1Z"/><path class="cls-3" d="M317.66,328.42c-14.4,17.8-34.14,28.8-55.93,28.8-44.05,0-72.06-44.87-72.06-100.21s28-100.2,72.06-100.2c21.79,0,41.53,11,55.93,28.78l23.87-25.15c-20.33-26.86-49-43.65-80.87-43.65C199,116.79,156.51,179.56,156.51,257S199,397.21,260.66,397.21c31.84,0,60.53-16.77,80.87-43.65Z"/><rect class="cls-3" x="167.89" y="216.71" width="115.17" height="28.65"/><rect class="cls-3" x="167.89" y="270.08" width="115.17" height="27.23"/><path class="cls-4" d="M156.51,256.8c0,75.89,40.84,137.69,100.49,140.13v-40.1c-30.21-2.26-52.23-26.17-61.89-59.72H167.89V269.88h22.32q-.54-6.42-.54-13.07,0-5.91.43-11.65H167.89V216.51h27.22c9.66-33.54,31.68-57.46,61.89-59.72V116.68C197.35,119.11,156.51,180.91,156.51,256.8Z"/><polygon class="cls-4" points="167.89 216.51 167.89 245.16 190.1 245.16 257 245.16 257 216.51 195.11 216.51 167.89 216.51"/><polygon class="cls-4" points="167.89 269.88 167.89 297.12 195.11 297.12 257 297.12 257 269.88 190.21 269.88 167.89 269.88"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -0,0 +1 @@
<svg id="P_with_dark_bg" data-name="P with dark bg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><style>.cls-1{fill:#365558;}.cls-2{fill:#fff;}.cls-3{fill:#f0353d;}.cls-4{fill:#e6eaea;}</style></defs><title>polkadot</title><path class="cls-1" d="M0,256C0,397.4,114.6,512,256,512V0C114.6,0,0,114.6,0,256Z"/><path class="cls-1" d="M256,0V512c141.4,0,256-114.6,256-256S397.4,0,256,0Z"/><g id="P."><path class="cls-2" d="M256,105.36A114.53,114.53,0,0,0,141.58,219.78,119.75,119.75,0,0,0,147.64,257a16,16,0,0,0,30.27-10.29,80.48,80.48,0,0,1-4.54-29.36c1.21-42.68,35.71-77.79,78.39-79.91a82.46,82.46,0,0,1,9.08,164.66s-16,.91-23.91,2.12c-3.93.6-7,1.21-9.08,1.51a1.21,1.21,0,0,1-1.51-1.51l2.72-13.32,14.83-68.41A15.79,15.79,0,1,0,213,215.84s-35.72,166.48-36,168.3a15.79,15.79,0,0,0,30.87,6.66c.31-1.82,5.15-23.92,5.15-23.92a40.2,40.2,0,0,1,33.9-31.48c3.63-.6,17.86-1.51,17.86-1.51A114.43,114.43,0,0,0,256,105.36Z"/><path class="cls-3" d="M264.17,368.7A19.17,19.17,0,1,0,279,391.4C281.12,380.81,274.77,370.82,264.17,368.7Z"/></g><path class="cls-4" d="M167.92,267a16.15,16.15,0,0,0,10-20.28,80.48,80.48,0,0,1-4.54-29.36c1.21-42.68,35.71-77.79,78.39-79.91,1.42-.08,2.84-.11,4.24-.11v-32A114.53,114.53,0,0,0,141.58,219.78,119.75,119.75,0,0,0,147.64,257,16.14,16.14,0,0,0,167.92,267Z"/><path class="cls-4" d="M256,302.41c-5.37.37-13.95,1-19.07,1.82-3.93.6-7,1.21-9.08,1.51a1.21,1.21,0,0,1-1.51-1.51l2.72-13.32,14.83-68.41A15.79,15.79,0,1,0,213,215.84s-35.72,166.48-36,168.3a15.79,15.79,0,0,0,30.87,6.66c.31-1.82,5.15-23.92,5.15-23.92a40.2,40.2,0,0,1,33.9-31.48c1.63-.27,5.42-.6,9.08-.89Z"/></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><style>.cls-1{fill:#365558;}.cls-2{fill:#0295aa;}.cls-3{fill:#e6eaea;}.cls-4{fill:#cdd4d5;}</style></defs><title>solana2</title><g id="Circle"><g id="Circle_Back" data-name="Circle Back"><path class="cls-1" d="M0,256C0,397.4,114.6,512,256,512V0C114.6,0,0,114.6,0,256Z"/><path class="cls-2" d="M256,0V512c141.4,0,256-114.6,256-256S397.4,0,256,0Z"/></g></g><g id="Layer_9" data-name="Layer 9"><path class="cls-3" d="M346,232a8.59,8.59,0,0,0-6.15-2.62H127A4.48,4.48,0,0,0,124,237L166,280.05a8.59,8.59,0,0,0,6.15,2.62H385a4.48,4.48,0,0,0,3.08-7.62Z"/><path class="cls-3" d="M166,312.19a8.61,8.61,0,0,1,6.15-2.6H385a4.45,4.45,0,0,1,3.08,7.58L346,360.07a8.66,8.66,0,0,1-6.15,2.6H127a4.46,4.46,0,0,1-3.08-7.59Z"/><path class="cls-3" d="M166,151.93a8.66,8.66,0,0,1,6.15-2.6H385a4.46,4.46,0,0,1,3.08,7.59L346,199.81a8.61,8.61,0,0,1-6.15,2.6H127a4.45,4.45,0,0,1-3.08-7.58Z"/><path class="cls-4" d="M124,237,166,280.05a8.59,8.59,0,0,0,6.15,2.62H256V229.33H127A4.48,4.48,0,0,0,124,237Z"/><path class="cls-4" d="M166,312.19l-42,42.89a4.46,4.46,0,0,0,3.08,7.59H256V309.59H172.15A8.61,8.61,0,0,0,166,312.19Z"/><path class="cls-4" d="M166,151.93l-42,42.9a4.45,4.45,0,0,0,3.08,7.58H256V149.33H172.15A8.66,8.66,0,0,0,166,151.93Z"/></g></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><style>.cls-1{fill:#f0353d;}.cls-2{fill:#fd6a33;}.cls-3{fill:#fff;fill-rule:evenodd;}.cls-4{fill:#e6eaea;}</style></defs><title>swipe</title><path class="cls-1" d="M1,257C1,398.4,115.6,513,257,513V1C115.6,1,1,115.6,1,257Z"/><path class="cls-2" d="M257,1V513c141.4,0,256-114.6,256-256S398.4,1,257,1Z"/><path class="cls-3" d="M247.73,93.35a65.13,65.13,0,0,0-39.13,19.21c-7.85,7.77-15.28,15.74-23.23,23.59-4,4.08-8,8-12,12.08s-8.46,8.31-12.64,12.54-7.65,7.94-11.51,11.87q-9.06,9.06-18.13,18.18c-4.63,4.8-9.16,9.74-13.75,14.52-2.7,2.86-5.61,5.51-8.15,8.51a71.7,71.7,0,0,0-16.26,45.46c0,1,0,2,.06,2.95a59.48,59.48,0,0,0,7.29,27.19,103.3,103.3,0,0,0,9,14.43c2.24,3.15,3.87,3.1,6.83.66a15.21,15.21,0,0,0,1.58-1.53c2.9-3.06,5.75-6.12,8.71-9.17,4.18-4.39,8.46-8.76,12.64-13.2s8.71-9.32,13.09-13.9c2.09-2.25,4.32-4.32,6.42-6.53,4.48-4.74,8.87-9.62,13.35-14.31s9-9.07,13.4-13.65,9.77-10.2,14.7-15.25,9.12-9.37,13.7-14.06c6-6.17,11.78-12.49,17.68-18.65,3.67-3.77,7.44-7.39,11.11-11.11,5.09-5.09,9.83-10.19,14.83-15.28s8.71-8.51,13-12.89q14.35-14.5,28.66-29.18a18.62,18.62,0,0,0,1.73-1.93c2.35-3,2.54-3.62-.36-5.7A91.32,91.32,0,0,0,286.19,99,66.51,66.51,0,0,0,258,92.71h-.48a79.23,79.23,0,0,0-9.74.62h-.05Zm84.32,62.72h-.61a28.76,28.76,0,0,0-22,10.19q-.74.81-1.53,1.53l-15.59,15.28c-5.09,5.11-10.6,10.66-15.95,16-4.43,4.42-8.86,8.76-13.24,13.19s-9.07,9.38-13.81,14-9.78,9.5-14.67,14.27l-17.38,17.52L185,290.38l-42.75,42.89c-2.75,2.71-2.8,3.06,0,6C149.07,346.17,156,353,162.62,360a27.19,27.19,0,0,0,15.39,8.2,36.43,36.43,0,0,0,16.77-.56,25.33,25.33,0,0,0,11-5.86l16.92-16.34c4-3.81,8-7.58,11.92-11.46,7.84-7.77,15.58-15.59,23.43-23.3,6.37-6.27,12.9-12.48,19.36-18.75L304,266q12.38-12.17,24.91-24.36a5.46,5.46,0,0,1,9.62,1.08A37.2,37.2,0,0,1,345,263.8a38,38,0,0,1-.19,3.85A35.22,35.22,0,0,1,335.89,288c-6.12,6.58-12.64,12.79-19,19.11-4.53,4.48-9.17,8.86-13.71,13.39-5.86,5.81-11.61,11.72-17.47,17.53-.87,1-1.68,2-2.59,2.9l-5.76,6c-4.32,4.31-8.71,8.51-12.95,12.83s-9.1,9.38-13.63,14.11c-.41.45-.87.76-1.27,1.16-5.1,4.74-9.79,9.5-14.63,14.27-2.29,2.24-4.48,4.53-6.73,6.77-3.86,3.93-7.84,7.77-11.56,11.78-2.29,2.39-2.29,3.86.41,5.75a97.72,97.72,0,0,0,14.11,9,71.14,71.14,0,0,0,39.38,5.61A64.35,64.35,0,0,0,306.17,412c7.54-6.62,14.27-14.06,21.29-21.19,5.1-5.1,10.2-10.54,15.64-15.79l14.73-14.83c4.49-4.53,8.92-9.07,13.46-13.55s10.18-9.83,15.27-14.88,10.2-10.18,15.29-15.59a117.28,117.28,0,0,0,11.22-13.25,72.16,72.16,0,0,0,11.57-32,66,66,0,0,0-10.75-45.5A82.32,82.32,0,0,0,399.63,209c-14.11-14-28.18-28.12-42-42.44a32.15,32.15,0,0,0-23.87-10.65h-.19l-1.52.21Z"/><path class="cls-4" d="M249.36,226.28c-4.74,4.64-9.78,9.5-14.67,14.27l-17.38,17.52L185,290.38l-42.75,42.89c-2.75,2.71-2.8,3.06,0,6C149.07,346.17,156,353,162.62,360a27.19,27.19,0,0,0,15.39,8.2,36.43,36.43,0,0,0,16.77-.56,25.33,25.33,0,0,0,11-5.86l16.92-16.34c4-3.81,8-7.58,11.92-11.46,7.48-7.41,14.88-14.87,22.36-22.24V218.59C254.49,221.16,251.94,223.76,249.36,226.28Z"/><path class="cls-4" d="M249.52,375c-5.1,4.74-9.79,9.5-14.63,14.27-2.29,2.24-4.48,4.53-6.73,6.77-3.86,3.93-7.84,7.77-11.56,11.78-2.29,2.39-2.29,3.86.41,5.75a97.72,97.72,0,0,0,14.11,9A71.09,71.09,0,0,0,257,428.84V367.41c-2.08,2.15-4.18,4.34-6.21,6.46C250.38,374.32,249.92,374.63,249.52,375Z"/><path class="cls-4" d="M247.72,93.28v.07a65.13,65.13,0,0,0-39.13,19.21c-7.85,7.77-15.28,15.74-23.23,23.59-4,4.08-8,8-12,12.08s-8.46,8.31-12.64,12.54-7.65,7.94-11.51,11.87q-9.06,9.06-18.13,18.18c-4.63,4.8-9.16,9.74-13.75,14.52-2.7,2.86-5.61,5.51-8.15,8.51a71.7,71.7,0,0,0-16.26,45.46c0,1,0,2,.06,2.95a59.48,59.48,0,0,0,7.29,27.19,103.3,103.3,0,0,0,9,14.43c2.24,3.15,3.87,3.1,6.83.66a15.21,15.21,0,0,0,1.58-1.53c2.9-3.06,5.75-6.12,8.71-9.17,4.18-4.39,8.46-8.76,12.64-13.2s8.71-9.32,13.09-13.9c2.09-2.25,4.32-4.32,6.42-6.53,4.48-4.74,8.87-9.62,13.35-14.31s9-9.07,13.4-13.65S195.07,222.05,200,217s9.12-9.37,13.7-14.06c6-6.17,11.78-12.49,17.68-18.65,3.67-3.77,7.44-7.39,11.11-11.11,5-5,9.62-10,14.5-14.94V92.72a76.91,76.91,0,0,0-9.23.61Z"/></svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><style>.cls-1{fill:#fff;}.cls-2,.cls-3{fill:#f0353d;}.cls-3{fill-rule:evenodd;}</style></defs><title>uniswap</title><path class="cls-1" d="M0,256C0,397.4,114.6,512,256,512V0C114.6,0,0,114.6,0,256Z"/><path class="cls-1" d="M256,0V512c141.4,0,256-114.6,256-256S397.4,0,256,0Z"/><path class="cls-2" d="M219.79,150.55c-4.18-.65-4.36-.72-2.39-1,3.77-.58,12.68.21,18.82,1.67,14.33,3.4,27.36,12.13,41.28,27.62l3.7,4.12,5.29-.85c22.28-3.58,44.95-.74,63.91,8,5.22,2.41,13.44,7.21,14.47,8.44a22.43,22.43,0,0,1,1.34,5.62c1.41,9.34.7,16.49-2.15,21.84-1.56,2.91-1.65,3.83-.6,6.32a6.11,6.11,0,0,0,5.46,3.45c4.71,0,9.78-7.62,12.13-18.22l.94-4.21,1.85,2.09c10.14,11.5,18.11,27.17,19.47,38.32l.36,2.91L402,254a32.79,32.79,0,0,0-9.66-10.15c-6.81-4.5-14-6-33.06-7-17.21-.9-26.95-2.37-36.61-5.52-16.43-5.36-24.72-12.5-44.24-38.11-8.67-11.37-14-17.67-19.36-22.74C246.93,159,235,152.92,219.79,150.55Z"/><path class="cls-2" d="M368.75,176c.44-7.62,1.47-12.65,3.55-17.24a18.13,18.13,0,0,1,1.71-3.3,11.45,11.45,0,0,1-.79,3c-1.52,4.45-1.76,10.55-.72,17.64,1.32,9,2.07,10.29,11.58,20,4.46,4.56,9.65,10.31,11.53,12.78l3.42,4.49-3.42-3.21c-4.18-3.92-13.8-11.57-15.93-12.66-1.42-.74-1.63-.73-2.51.15s-1,2-1.09,7.74c-.18,8.92-1.39,14.65-4.33,20.38-1.59,3.09-1.84,2.43-.4-1.06,1.07-2.61,1.18-3.76,1.17-12.4,0-17.35-2.07-21.53-14.16-28.67-3.06-1.81-8.1-4.42-11.2-5.81a42.08,42.08,0,0,1-5.48-2.67c.34-.34,12.12,3.1,16.87,4.92,7.05,2.72,8.22,3.07,9.07,2.74C368.2,182.54,368.47,180.87,368.75,176Z"/><path class="cls-2" d="M227.92,205.64c-8.5-11.69-13.75-29.61-12.61-43l.35-4.15,1.93.36a48.44,48.44,0,0,1,12.82,4.77c8,4.88,11.52,11.31,15.07,27.82,1,4.84,2.4,10.31,3,12.17,1,3,4.82,9.94,7.92,14.47,2.23,3.26.75,4.8-4.18,4.36C244.7,221.75,234.5,214.7,227.92,205.64Z"/><path class="cls-2" d="M358.45,292.65c-39.68-16-53.65-29.85-53.65-53.25a37.25,37.25,0,0,1,.26-6.26,30.7,30.7,0,0,1,3.41,2.53c8,6.45,17.06,9.21,42,12.85,14.68,2.14,22.94,3.87,30.56,6.39,24.22,8,39.21,24.34,42.78,46.54,1,6.45.43,18.55-1.25,24.93-1.33,5-5.39,14.11-6.46,14.46-.3.1-.59-1-.67-2.6-.41-8.34-4.62-16.46-11.7-22.54C395.69,308.79,384.88,303.29,358.45,292.65Z"/><path class="cls-2" d="M330.6,299.28a70.54,70.54,0,0,0-1.92-8.39l-1-3,1.88,2.11a33.81,33.81,0,0,1,6.4,11.64c1.33,3.8,1.48,4.93,1.47,11.1s-.18,7.34-1.41,10.76a33.94,33.94,0,0,1-8.37,13.32c-7.25,7.38-16.57,11.46-30,13.16-2.33.29-9.15.79-15.14,1.1-15.09.78-25,2.41-34,5.54a7.34,7.34,0,0,1-2.54.61c-.36-.36,5.71-4,10.74-6.4,7.07-3.41,14.12-5.27,29.91-7.9,7.8-1.3,15.85-2.88,17.9-3.51C323.84,333.48,333.77,318.2,330.6,299.28Z"/><path class="cls-2" d="M348.79,331.59c-5.28-11.33-6.49-22.28-3.6-32.48.31-1.09.81-2,1.11-2a10.8,10.8,0,0,1,2.76,1.5c2.43,1.63,7.3,4.39,20.29,11.47,16.19,8.83,25.43,15.67,31.71,23.48a51,51,0,0,1,10.54,24.14c.93,5.39.39,18.34-1,23.76-4.36,17.09-14.48,30.52-28.92,38.35a37.32,37.32,0,0,1-4.22,2.1c-.2,0,.57-2,1.71-4.36,4.86-10.15,5.41-20,1.74-31-2.25-6.73-6.83-15-16.09-28.83C354.07,341.58,351.43,337.28,348.79,331.59Z"/><path class="cls-2" d="M199.74,392.74c14.72-12.43,33-21.26,49.73-24,7.2-1.16,19.18-.7,25.84,1,10.68,2.74,20.23,8.86,25.19,16.15,4.86,7.12,6.94,13.33,9.11,27.15.85,5.45,1.78,10.92,2.07,12.16,1.62,7.16,4.79,12.89,8.72,15.76,6.24,4.57,17,4.85,27.54.73a13.53,13.53,0,0,1,3.46-1.07c.38.38-4.94,3.94-8.69,5.81a29.57,29.57,0,0,1-14.4,3.5c-9.68,0-17.71-4.92-24.41-15a117.16,117.16,0,0,1-6.59-13.15c-7.08-16.14-10.57-21-18.79-26.44-7.15-4.68-16.37-5.52-23.31-2.12-9.12,4.47-11.66,16.12-5.13,23.5a20.2,20.2,0,0,0,11.39,6,12.15,12.15,0,0,0,13.76-12.18c0-4.85-1.87-7.62-6.56-9.74-6.41-2.89-13.3.49-13.27,6.52,0,2.56,1.13,4.18,3.71,5.34,1.65.75,1.69.81.34.53-5.88-1.22-7.26-8.31-2.53-13,5.68-5.65,17.42-3.16,21.45,4.56,1.7,3.24,1.89,9.69.42,13.59-3.31,8.72-13,13.31-22.73,10.81-6.65-1.7-9.36-3.54-17.39-11.81-13.95-14.36-19.36-17.15-39.47-20.28l-3.85-.61Z"/><path class="cls-3" d="M94.57,70.93C141.14,127.46,213,215.47,216.51,220.4c3,4.06,1.84,7.72-3.2,10.59a30.68,30.68,0,0,1-11.46,3.21,14.66,14.66,0,0,1-9.62-4.12c-1.89-1.79-9.53-13.2-27.17-40.57-13.49-20.94-24.79-38.31-25.1-38.6-.71-.67-.7-.65,23.72,43.05C179,221.4,184.2,231.1,184.2,232.39c0,2.64-.72,4-4,7.66-5.43,6-7.85,12.86-9.6,26.93-2,15.78-7.49,26.93-22.78,46-9,11.17-10.42,13.21-12.68,17.71-2.85,5.67-3.63,8.85-3.95,16a50,50,0,0,0,2.63,19.69c2,6.33,4.14,10.52,9.54,18.88,4.66,7.22,7.35,12.59,7.35,14.69,0,1.67.31,1.67,7.54,0,17.28-3.91,31.32-10.77,39.21-19.19,4.89-5.2,6-8.08,6.07-15.22,0-4.66-.14-5.64-1.4-8.33-2.05-4.37-5.79-8-14-13.63-10.8-7.39-15.41-13.33-16.69-21.5-1-6.71.17-11.44,6.15-24,6.18-13,7.71-18.48,8.75-31.54.67-8.44,1.59-11.77,4-14.44s4.8-3.73,11.06-4.58c10.21-1.4,16.7-4,22-9,4.64-4.27,6.57-8.38,6.87-14.57l.23-4.7-2.59-3c-9.38-10.93-139.67-154-140.25-154C87.59,62.34,90.68,66.2,94.57,70.93ZM156,355.27a8.31,8.31,0,0,0-2.55-10.94c-3.35-2.23-8.56-1.18-8.56,1.73,0,.88.49,1.53,1.6,2.09,1.85,1,2,2,.53,4.23s-1.36,4.19.33,5.52C150.08,360,154,358.86,156,355.27Z"/><path class="cls-3" d="M237,250.08Line truncated

After

Width:  |  Height:  |  Size: 5.2 KiB

@@ -1,36 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="-59 167 201 200" style="enable-background:new -59 167 201 200;" xml:space="preserve">
<style type="text/css">
.st0{display:none;fill:#FFFFFF;}
.st1{display:none;fill:#E6EAEA;}
.st2{fill:#F0353D;}
.st3{fill:#0295AA;}
.st4{fill:#FFFFFF;}
</style>
<title>BTC</title>
<desc>Created with Sketch.</desc>
<path class="st0" d="M66,270.3c-3.9-3.8-10.7-7.3-20.5-10.4v-21.3c2.8,0.3,4.9,1.4,6.4,3.3s2.3,4.7,2.5,8.3h16
c-0.4-7.5-2.7-13.4-7-17.7c-4.3-4.2-10.2-6.6-17.8-6.9v-7.5H42v104.2h3.6v-11.1c8.4-0.7,14.8-3.2,19.4-7.7
c4.6-4.5,6.9-10.5,6.9-17.9C71.8,279.2,69.9,274.1,66,270.3z M52.8,294.8c-1.7,1.9-4.1,3.1-7.3,3.5v-22.1c3.4,1.1,5.9,2.5,7.5,4.3
s2.3,4.1,2.3,6.8C55.4,290.4,54.5,292.9,52.8,294.8z"/>
<path class="st1" d="M38.5,218.1v7.5c-7.6,0.2-13.7,2.4-18.3,6.8c-4.6,4.4-6.8,10.2-6.8,17.3c0,6.4,1.9,11.5,5.7,15.1
c3.8,3.7,10.2,6.7,19.4,9.1v24.3c-3.4-0.7-5.9-2.2-7.7-4.7s-2.8-5.8-3-10H12.2c0,8.6,2.2,15.2,6.6,19.8s11,7.1,19.8,7.7v11.3H42
V218.1H38.5z M38.5,258.2c-3.2-1.1-5.6-2.4-7.1-4c-1.5-1.6-2.2-3.6-2.2-6c0-2.9,0.8-5.1,2.4-6.9c1.6-1.7,3.9-2.8,6.9-3.1V258.2z"/>
<path class="st0" d="M104.2,239c7.6,0,13.4,2.7,17.3,8c4,5.3,5.9,13.1,5.9,23.2c0,10.3-2,18.1-5.9,23.4c-3.9,5.3-9.7,7.9-17.4,7.9
H83.4V239L104.2,239L104.2,239z M104.2,250.6h-7.6v39.2h7.6c3.4,0,5.9-1.5,7.4-4.6c1.5-3,2.3-8,2.3-15c0-6.4-0.8-11.3-2.5-14.6
C109.8,252.3,107.4,250.6,104.2,250.6z"/>
<path class="st2" d="M141.5,267c0-55.1-44.6-99.8-99.6-100v200C97,366.8,141.5,322.1,141.5,267z"/>
<path class="st3" d="M41.5,167c-55.2,0-100,44.8-100,100s44.8,100,100,100c0.1,0,0.2,0,0.4,0V167C41.8,167,41.7,167,41.5,167z"/>
<polygon class="st4" points="1.8,206.8 -3.4,190.9 -8.6,206.8 -25.4,206.9 -11.8,216.7 -17,232.7 -3.4,222.8 10.1,232.7 5,216.7
18.5,206.9 "/>
<polygon class="st4" points="1.8,260.3 -3.4,244.3 -8.6,260.3 -25.4,260.3 -11.8,270.2 -17,286.1 -3.4,276.3 10.1,286.1 5,270.2
18.5,260.3 "/>
<polygon class="st4" points="1.8,313.7 -3.4,297.8 -8.6,313.7 -25.4,313.7 -11.8,323.6 -17,339.5 -3.4,329.7 10.1,339.5 5,323.6
18.5,313.7 "/>
<path class="st4" d="M-39.9,266.7l-5.2-15.9l13.5-9.9l-16.7,0l-3.4-10.4c-3.7,9.4-6,19.4-6.7,29.9l4.9-3.5L-39.9,266.7z"/>
<path class="st4" d="M-45,304.2l13.5-9.9l-16.7,0l-5.2-15.9l-3,9.1c2.1,10.1,5.7,19.6,10.6,28.3l5.9,4.3L-45,304.2z"/>
<path class="st4" d="M41.9,239.3V306h91.7c5.1-12,7.9-25.2,7.9-39c0-9.6-1.4-18.9-3.9-27.7H41.9z"/>
<rect x="41.5" y="239.3" class="st4" width="0.4" height="66.7"/>
</svg>
<svg id="Layer_13" data-name="Layer 13" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><style>.cls-1{fill:#f0353d;}.cls-2{fill:#0295aa;}.cls-3{fill:#fff;}</style></defs><title>us-dollar</title><path class="cls-1" d="M512,256C512,114.94,397.82.51,257,0V512C398.08,511.49,512,397.06,512,256Z"/><path class="cls-2" d="M256,0C114.69,0,0,114.69,0,256S114.69,512,256,512h1V0Z"/><polygon class="cls-3" points="154.37 101.89 141.06 61.18 127.74 101.89 84.74 102.14 119.55 127.23 106.24 168.19 141.06 142.85 175.62 168.19 162.56 127.23 197.12 102.14 154.37 101.89"/><polygon class="cls-3" points="154.37 238.85 141.06 197.89 127.74 238.85 84.74 238.85 119.55 264.19 106.24 304.9 141.06 279.81 175.62 304.9 162.56 264.19 197.12 238.85 154.37 238.85"/><polygon class="cls-3" points="154.37 375.55 141.06 334.85 127.74 375.55 84.74 375.55 119.55 400.9 106.24 441.6 141.06 416.51 175.62 441.6 162.56 400.9 197.12 375.55 154.37 375.55"/><path class="cls-3" d="M47.62,255.23,34.3,214.53l34.56-25.35H26.11l-8.7-26.62A254.35,254.35,0,0,0,.26,239.1l12.54-9Z"/><path class="cls-3" d="M34.56,351.23l34.56-25.34H26.37L13.06,285.18l-7.68,23.3a251.68,251.68,0,0,0,27.13,72.45l15.11,11Z"/><path class="cls-3" d="M257,185.09V355.84H491.78A254.9,254.9,0,0,0,512,256a259.28,259.28,0,0,0-10-70.91Z"/><rect class="cls-3" x="256" y="185.09" width="1.02" height="170.75"/></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -1,12 +1 @@
<svg width="112" height="112" viewBox="0 0 112 112" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path d="M56 112C67.0758 112 77.9028 108.716 87.1119 102.562C96.3211 96.4089 103.499 87.6629 107.737 77.4303C111.976 67.1976 113.085 55.9379 110.924 45.0749C108.763 34.212 103.43 24.2338 95.598 16.402C87.7662 8.57027 77.788 3.23679 66.9251 1.07602C56.0621 -1.08475 44.8024 0.0242338 34.5697 4.26274C24.3371 8.50125 15.5911 15.6789 9.4377 24.8881C3.28434 34.0972 0 44.9242 0 56C0 70.8521 5.89998 85.0959 16.402 95.598C26.9041 106.1 41.1479 112 56 112V112Z" fill="#23292F"/>
<path d="M76.49 32.15H84.91L67.4 49.62C64.3568 52.6598 60.2314 54.3673 55.93 54.3673C51.6286 54.3673 47.5032 52.6598 44.46 49.62L27 32.15H35.41L48.71 45.42C50.6375 47.3454 53.2506 48.4269 55.975 48.4269C58.6994 48.4269 61.3125 47.3454 63.24 45.42L76.49 32.15Z" fill="white"/>
<path d="M35.37 80.74H27L44.57 63.16C47.6132 60.1202 51.7386 58.4127 56.04 58.4127C60.3414 58.4127 64.4668 60.1202 67.51 63.16L85.12 80.74H76.71L63.31 67.36C61.3825 65.4346 58.7694 64.3531 56.045 64.3531C53.3206 64.3531 50.7075 65.4346 48.78 67.36L35.37 80.74Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="112" height="112" fill="white"/>
</clipPath>
</defs>
</svg>
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><style>.cls-1{fill:#365558;}.cls-2{fill:#e6eaea;}.cls-3{fill:#fff;}.cls-4{fill:none;}</style></defs><title>Artboard 1</title><path class="cls-1" d="M256,0V512c141.4,0,256-114.6,256-256S397.4,0,256,0Z"/><path class="cls-1" d="M0,256C0,397.4,114.6,512,256,512V0C114.6,0,0,114.6,0,256Z"/><g id="Canvas"><g id="xrp-symbol-white"><path id="Vector" class="cls-2" d="M353.83,141.41h40l-83.28,82.41a77.76,77.76,0,0,1-109.17,0l-83.28-82.41h40L221.43,204a49.26,49.26,0,0,0,69.14,0Z"/><path id="Vector_2" data-name="Vector 2" class="cls-2" d="M157.65,370.59h-40l83.8-82.92a77.74,77.74,0,0,1,109.16,0l83.8,82.92h-40l-63.78-63.12a49.26,49.26,0,0,0-69.14,0Z"/></g></g><path class="cls-3" d="M311.48,223.82l83.28-82.41h-40L291.47,204a49,49,0,0,1-34.57,14.17v28A77.34,77.34,0,0,0,311.48,223.82Z"/><path class="cls-3" d="M311.49,287.67a77.38,77.38,0,0,0-54.59-22.38v28a49,49,0,0,1,34.57,14.17l63.78,63.12h40Z"/><path class="cls-4" d="M158.56,370.59h-40l83.79-82.92a77.35,77.35,0,0,1,54.58-22.38V246.2a77.34,77.34,0,0,1-54.58-22.38L119,141.41h40L222.33,204a49,49,0,0,0,34.57,14.17V0H.9V512h256V293.3a49,49,0,0,0-34.57,14.17Z"/></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -1,6 +1,7 @@
{
"type": "Workspace",
"name": "API-Data-Fetcher-Bot-Demo",
"config": "{\n \"docsLanguage\": \"EN\",\n \"contributionsBranch\": \"develop\"\n}",
"rootNodes": [
{
"type": "Network",
@@ -929,7 +930,7 @@
"arrangementStyle": 0
},
"uiObject": {
"isRunning": true
"isRunning": false
},
"referenceParent": {
"type": "Data Mine",
@@ -2083,7 +2084,7 @@
"arrangementStyle": 0
},
"uiObject": {
"isRunning": true
"isRunning": false
},
"referenceParent": {
"type": "Market",
@@ -2112,7 +2113,7 @@
"arrangementStyle": 0
},
"uiObject": {
"isRunning": true
"isRunning": false
},
"referenceParent": {
"type": "Crypto Exchange",
@@ -2141,7 +2142,7 @@
"arrangementStyle": 0
},
"uiObject": {
"isRunning": true
"isRunning": false
},
"referenceParent": {
"type": "Project Definition",
@@ -2170,7 +2171,7 @@
"arrangementStyle": 0
},
"uiObject": {
"isRunning": true
"isRunning": false
}
}
},
@@ -9792,85 +9793,30 @@
"name": "New Plugin Data Mines",
"project": "Foundations",
"pluginFiles": [
{
"type": "Plugin File",
"name": "Masters",
"config": "{\n\"codeName\": \"\"\n}",
"project": "Foundations",
"pluginFilePosition": {
"type": "Plugin File Position",
"name": "Masters",
"project": "Foundations",
"id": "d5234bd2-ef4e-4856-a6a0-ce7659653a48",
"savedPayload": {
"position": {
"x": 18879.35218735615,
"y": 18688.55301821844
},
"targetPosition": {
"x": 30986.371225686038,
"y": 18236.288271084537
},
"floatingObject": {
"isPinned": true,
"isFrozen": false,
"isCollapsed": false,
"angleToParent": 2,
"distanceToParent": 3,
"arrangementStyle": 0
},
"uiObject": {
"isRunning": false
}
}
},
"id": "ecc1a524-de9b-4e73-8874-b99a7ea0402b",
"savedPayload": {
"position": {
"x": 31374.357288332292,
"y": 18123.931117466833
},
"targetPosition": {
"x": 31496.37828125503,
"y": 18397.994754759613
},
"floatingObject": {
"isPinned": false,
"isFrozen": false,
"isCollapsed": true,
"angleToParent": 2,
"distanceToParent": 3,
"arrangementStyle": 0
},
"uiObject": {
"isRunning": false
}
}
},
{
"type": "Plugin File",
"name": "Bollinger",
"config": "{\n\"codeName\": \"\"\n}",
"config": "{\"project\":\"Foundations\",\"fileName\":\"Bollinger\",\"folderName\":\"Data-Mines\",\"nodeType\":\"Data Mine\"}",
"project": "Foundations",
"pluginFilePosition": {
"type": "Plugin File Position",
"name": "Bollinger",
"project": "Foundations",
"id": "77c437a7-0ac2-40c1-aa84-6d48e46b287b",
"id": "75c333db-28b1-4c35-8a18-f1fad8d2b1f1",
"savedPayload": {
"position": {
"x": 34406.26298631758,
"y": 18688.60151122931
"x": 34398.489720814745,
"y": 18699.74774026896
},
"targetPosition": {
"x": 31558.751788500358,
"y": 18104.550474539472
"x": 31202.93400103489,
"y": 18335.621247514286
},
"floatingObject": {
"isPinned": true,
"isFrozen": false,
"isCollapsed": false,
"angleToParent": 2,
"angleToParent": 1,
"distanceToParent": 3,
"arrangementStyle": 0
},
@@ -9879,11 +9825,11 @@
}
}
},
"id": "cb988ae0-94c5-4afa-8425-0c64149613ce",
"id": "84c68fba-0d63-4064-a414-d951fec775e3",
"savedPayload": {
"position": {
"x": 31558.751788500358,
"y": 18104.550474539472
"x": 31202.93400103489,
"y": 18335.621247514286
},
"targetPosition": {
"x": 31496.37828125503,
@@ -9893,7 +9839,7 @@
"isPinned": false,
"isFrozen": false,
"isCollapsed": false,
"angleToParent": 2,
"angleToParent": 1,
"distanceToParent": 3,
"arrangementStyle": 0
},
@@ -9905,27 +9851,27 @@
{
"type": "Plugin File",
"name": "Candles",
"config": "{\n\"codeName\": \"\"\n}",
"config": "{\"project\":\"Foundations\",\"fileName\":\"Candles\",\"folderName\":\"Data-Mines\",\"nodeType\":\"Data Mine\"}",
"project": "Foundations",
"pluginFilePosition": {
"type": "Plugin File Position",
"name": "Candles",
"project": "Foundations",
"id": "433d2a13-18d4-4e92-b830-c93dfa571c11",
"id": "d905708f-d130-48e6-83b8-893d0949240c",
"savedPayload": {
"position": {
"x": 37747.067482786275,
"y": 18702.38150649338
"x": 37744.16120329444,
"y": 18702.53161753865
},
"targetPosition": {
"x": 31719.32172889825,
"y": 18197.255572851955
"x": 31465.019742274733,
"y": 18099.63818614913
},
"floatingObject": {
"isPinned": true,
"isFrozen": false,
"isCollapsed": false,
"angleToParent": 2,
"angleToParent": 1,
"distanceToParent": 3,
"arrangementStyle": 0
},
@@ -9934,11 +9880,11 @@
}
}
},
"id": "b9e0a7a6-35c0-4b5a-b07c-2cf97a252283",
"id": "c6e8a721-4e08-4a61-9a8f-bb2ea4733a55",
"savedPayload": {
"position": {
"x": 31719.32172889825,
"y": 18197.255572851955
"x": 31465.019742274733,
"y": 18099.63818614913
},
"targetPosition": {
"x": 31496.37828125503,
@@ -9948,7 +9894,62 @@
"isPinned": false,
"isFrozen": false,
"isCollapsed": false,
"angleToParent": 2,
"angleToParent": 1,
"distanceToParent": 3,
"arrangementStyle": 0
},
"uiObject": {
"isRunning": false
}
}
},
{
"type": "Plugin File",
"name": "Masters",
"config": "{\"project\":\"Foundations\",\"fileName\":\"Masters\",\"folderName\":\"Data-Mines\",\"nodeType\":\"Data Mine\"}",
"project": "Foundations",
"pluginFilePosition": {
"type": "Plugin File Position",
"name": "Masters",
"project": "Foundations",
"id": "06324e94-a092-4fb1-8811-e4d23b140776",
"savedPayload": {
"position": {
"x": 18872.50555584059,
"y": 18697.702768914136
},
"targetPosition": {
"x": 31770.44191854781,
"y": 18275.973761836874
},
"floatingObject": {
"isPinned": true,
"isFrozen": false,
"isCollapsed": false,
"angleToParent": 1,
"distanceToParent": 3,
"arrangementStyle": 0
},
"uiObject": {
"isRunning": false
}
}
},
"id": "005d766a-e9dd-4812-bdd6-5abb58702c0c",
"savedPayload": {
"position": {
"x": 31770.44191854781,
"y": 18275.973761836874
},
"targetPosition": {
"x": 31496.37828125503,
"y": 18397.994754759613
},
"floatingObject": {
"isPinned": false,
"isFrozen": false,
"isCollapsed": false,
"angleToParent": 1,
"distanceToParent": 3,
"arrangementStyle": 0
},
@@ -9960,27 +9961,27 @@
{
"type": "Plugin File",
"name": "Messari",
"config": "{\n\"codeName\": \"\"\n}",
"config": "{\"project\":\"Foundations\",\"fileName\":\"Messari\",\"folderName\":\"Data-Mines\",\"nodeType\":\"Data Mine\"}",
"project": "Foundations",
"pluginFilePosition": {
"type": "Plugin File Position",
"name": "Messari",
"project": "Foundations",
"id": "0f932f30-69f3-453a-89ca-638cd74027a6",
"id": "ee208a33-8b70-49b5-ba65-3aabf048f402",
"savedPayload": {
"position": {
"x": 14004.091418475993,
"y": 18772.527676799018
"x": 13990.856645070347,
"y": 18779.88165004605
},
"targetPosition": {
"x": 31794.734849865512,
"y": 18366.636215779316
"x": 31697.11746316269,
"y": 18620.93820240283
},
"floatingObject": {
"isPinned": true,
"isFrozen": false,
"isCollapsed": false,
"angleToParent": 2,
"angleToParent": 1,
"distanceToParent": 3,
"arrangementStyle": 0
},
@@ -9989,11 +9990,11 @@
}
}
},
"id": "20f5e091-1f43-4947-9657-7655caf87a68",
"id": "44374a6e-682a-4ad5-97d5-46e4ae005c7e",
"savedPayload": {
"position": {
"x": 31794.734849865512,
"y": 18366.636215779316
"x": 31697.11746316269,
"y": 18620.93820240283
},
"targetPosition": {
"x": 31496.37828125503,
@@ -10003,7 +10004,7 @@
"isPinned": false,
"isFrozen": false,
"isCollapsed": false,
"angleToParent": 2,
"angleToParent": 1,
"distanceToParent": 3,
"arrangementStyle": 0
},
@@ -10026,7 +10027,7 @@
"floatingObject": {
"isPinned": false,
"isFrozen": false,
"isCollapsed": false,
"isCollapsed": true,
"angleToParent": 1,
"distanceToParent": 3,
"arrangementStyle": 0
@@ -10044,17 +10045,17 @@
{
"type": "Plugin File",
"name": "Messari",
"config": "{\n\"codeName\": \"\"\n}",
"config": "{\n \"project\": \"Foundations\",\n \"fileName\": \"Messari\",\n \"folderName\": \"API-Maps\",\n \"nodeType\": \"API Map\"\n}",
"project": "Foundations",
"pluginFilePosition": {
"type": "Plugin File Position",
"name": "Messari",
"project": "Foundations",
"id": "da790e41-0b29-41af-b5a0-f582fea8375d",
"id": "f096906c-1652-40ff-be83-c4cc3002ff91",
"savedPayload": {
"position": {
"x": 14002.262986317575,
"y": 10768.059102958174
"x": 13996.87828125503,
"y": 10769.475239300944
},
"targetPosition": {
"x": 31646.37828125503,
@@ -10073,7 +10074,7 @@
}
}
},
"id": "272f2cfc-7440-4da4-bb2b-6466aeff6582",
"id": "72c44c87-355e-4012-95e5-229ef5fada58",
"savedPayload": {
"position": {
"x": 31646.37828125503,
@@ -10110,7 +10111,7 @@
"floatingObject": {
"isPinned": false,
"isFrozen": false,
"isCollapsed": false,
"isCollapsed": true,
"angleToParent": 1,
"distanceToParent": 3,
"arrangementStyle": 0
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -25,7 +25,7 @@
"config": true
},
"initialValues": {
"config": "{ \n\"codeName\": \"Type the code name of the asset\"\n}"
"config": "{ \n\"codeName\": \"Type_the_code_name_of_the_asset\"\n}"
},
"attachingRules": {
"compatibleTypes": "->Exchange Assets->"
@@ -107,6 +107,34 @@
{
"codeName": "DOGE",
"iconName": "dogecoin"
},
{
"codeName": "SOL",
"iconName": "solana"
},
{
"codeName": "DOT",
"iconName": "polkadot"
},
{
"codeName": "UNI",
"iconName": "uniswap"
},
{
"codeName": "BUSD",
"iconName": "binance-usd"
},
{
"codeName": "SXP",
"iconName": "swipe"
},
{
"codeName": "LINK",
"iconName": "chainlink"
},
{
"codeName": "EUR",
"iconName": "euro"
}
]
}
}
@@ -61,7 +61,7 @@
"name": "pluginFilePosition",
"type": "node",
"childType": "Plugin File Position",
"autoAdd": true
"autoAdd": false
}
]
}
@@ -37,6 +37,12 @@
"workDoneLabel": "Done",
"relatedUiObject": "Workspace",
"actionFunction": "payload.executeAction"
},
{
"action": "Check For Missing References",
"label": "Check For Missing References",
"relatedUiObject": "Workspace",
"actionFunction": "payload.executeAction"
}
],
"initialValues": {
@@ -2,7 +2,14 @@
"type": "Community Data Mines",
"definition": {
"text": "The Community Data Mines book is a compendium of data mines—and their indicators—contributed by the Community.",
"updated": 1622378343288
"updated": 1622378343288,
"translations": [
{
"language": "ES",
"text": "El Community Data Mines book es un compendio de minas de datos y sus indicadores aportados por la Comunidad.",
"updated": 1628046154075
}
]
},
"paragraphs": [
{
@@ -2,7 +2,14 @@
"type": "First Steps Tutorials",
"definition": {
"text": "This book walks you through the path that will help you learn Superalgos in the most efficient possible way. Interactive tutorials are the very best tool to tackle the learning curve. Doing the tutorials in the order proposed is highly recommended.",
"updated": 1610915328705
"updated": 1610915328705,
"translations": [
{
"language": "ES",
"text": "Este libro lo guía por el camino que lo ayudará a aprender Superalgos de la manera más eficiente posible. Los tutoriales interactivos son la mejor herramienta para abordar la curva de aprendizaje. Es muy recomendable hacer los tutoriales en el orden propuesto.",
"updated": 1628207193722
}
]
},
"paragraphs": [
{
@@ -2,7 +2,14 @@
"type": "CCXT",
"definition": {
"text": "CCXT is a popular open source library that aims to standarize crypto exchanges APIs so as to make it easier for trading bots developers to access crypto exchanges. ",
"updated": 1621694347383
"updated": 1621694347383,
"translations": [
{
"language": "ES",
"text": "CCXT es una biblioteca de código abierto popular que tiene como objetivo estandarizar los exchanges de criptomonedas APIs para que sea más fácil paralos trading bots developers to access crypto exchanges.",
"updated": 1628045764972
}
]
},
"paragraphs": [
{
@@ -2,7 +2,14 @@
"type": "Community",
"definition": {
"text": "The Community, or the Superalgos Community, is the group of entities participating in the Superalgos project, either actively contributing to advancing the project or passively using the Superalgos software.",
"updated": 1618832930339
"updated": 1618832930339,
"translations": [
{
"language": "ES",
"text": "La Community, o la Superalgos Community, es el grupo de entidades que participan en el proyecto Superalgos, ya sea contribuyendo activamente al avance del proyecto o utilizando pasivamente el software Superalgos.",
"updated": 1628046272721
}
]
},
"paragraphs": [
{
@@ -2,7 +2,14 @@
"type": "Detach Node",
"definition": {
"text": "Breaks the parent-offspring relationship that keeps the node attached to its parent. Once detached, the node is no longer computed as part of the hierarchy it was attached to. ",
"updated": 1610032559190
"updated": 1610032559190,
"translations": [
{
"language": "ES",
"text": "Rompe la relación entre padres e hijos que mantiene el nodo unido a su padre. Una vez desconectado, el nodo ya no se calcula como parte de la jerarquía a la que estaba adjunto.",
"updated": 1628035974832
}
]
},
"paragraphs": [
{
@@ -2,7 +2,14 @@
"type": "API Map",
"definition": {
"text": "An API Map represents the mapping of an API so that is can be consumed by bots within Superalgos. API Maps are created by users and shared as Plugins so that any other community member can use them with their bots. ",
"updated": 1621016177698
"updated": 1621016177698,
"translations": [
{
"language": "ES",
"text": "Un API Map representa el mapeo de una API para que pueda ser consumida por bots dentro de Superalgos. API Maps Son creados por los usuarios y compartidos como Plugins para que cualquier otro miembro de la comunidad pueda usarlos con sus bots.",
"updated": 1628046227514
}
]
},
"paragraphs": [
{
@@ -1,7 +1,14 @@
{
"type": "Chart Points",
"definition": {
"text": "A chart points groups definitions of coordinate points used to define polygons."
"text": "A chart points groups definitions of coordinate points used to define polygons.",
"translations": [
{
"language": "ES",
"text": "Un chart points agrupa definiciones de puntos de coordenadas que se utilizan para definir polígonos.",
"updated": 1628036795702
}
]
},
"paragraphs": [
{
@@ -1,87 +1,94 @@
{
"type": "Crypto Exchange",
"definition": {
"text": "A crypto exchange node holds the definitions of assets and markets in a specific exchange."
},
"paragraphs": [
{
"style": "Block",
"text": "Configuring"
"type": "Crypto Exchange",
"definition": {
"text": "A crypto exchange node holds the definitions of assets and markets in a specific exchange.",
"translations": [
{
"language": "ES",
"text": "Un nodo crypto exchangecontiene las definiciones de assets y mercados en un exchange.",
"updated": 1628205315370
}
]
},
{
"style": "Title",
"text": "Tested Exchanges",
"updated": 1615200855230
},
{
"style": "Text",
"text": "In theory, Superalgos supports dozens of exchanges. However, each exchange must go through a testing process, as not all of them conform to the standard proposed by the CCXT library.",
"updated": 1615201479524
},
{
"style": "List",
"text": "Binance Test Status",
"updated": 1615203667257
},
{
"style": "List",
"text": "Binance-US Test Status"
},
{
"style": "List",
"text": "Bitfinex Test Status"
},
{
"style": "List",
"text": "Bittrex Test Status"
},
{
"style": "List",
"text": "CoinbasePro Test Status"
},
{
"style": "List",
"text": "FTX Test Status",
"updated": 1615203669878
},
{
"style": "List",
"text": "Kraken Test Status",
"updated": 1615453046113
},
{
"style": "List",
"text": "Kucoin Test Status"
},
{
"style": "List",
"text": "Luno Test Status"
},
{
"style": "Title",
"text": "Crypto Exchange Configuration"
},
{
"style": "Text",
"text": "Each exchange may require a very specific configuration. This is determined during the exchange testing process. Consult the page of each exchange as listed above. If you are interested in testing a new exchange, go to the How to Test New Exchanges page.",
"updated": 1615201685376
},
{
"style": "Subtitle",
"text": "Properties",
"updated": 1609771684679
},
{
"style": "List",
"text": "codeName is the name of the exchange as handled in the code of the system."
},
{
"style": "List",
"text": "sandBox setting this parameter to true allows SuperAlgos to perform live trading on the exchanges sandbox or testnet if one is available."
},
{
"style": "List",
"text": "API holds a series of definitions used only in the case in which the sensor bot fetches trades (using the Historic-Trades process) instead of the OHLCV process that fetches one-minute candles and is the current default. In such a case, finding the right set of parameters to work with a specific exchange may be challenging, nd involves understanding how the exchanges API and the CCXT Library API work. In other words, there is no hard rule as of what each of the values should be. Determining each of this values requires exploring the exchange's API documentation, as well as the documentation of the CCXT Library."
}
]
}
"paragraphs": [
{
"style": "Block",
"text": "Configuring"
},
{
"style": "Title",
"text": "Tested Exchanges",
"updated": 1615200855230
},
{
"style": "Text",
"text": "In theory, Superalgos supports dozens of exchanges. However, each exchange must go through a testing process, as not all of them conform to the standard proposed by the CCXT library.",
"updated": 1615201479524
},
{
"style": "List",
"text": "Binance Test Status",
"updated": 1615203667257
},
{
"style": "List",
"text": "Binance-US Test Status"
},
{
"style": "List",
"text": "Bitfinex Test Status"
},
{
"style": "List",
"text": "Bittrex Test Status"
},
{
"style": "List",
"text": "CoinbasePro Test Status"
},
{
"style": "List",
"text": "FTX Test Status",
"updated": 1615203669878
},
{
"style": "List",
"text": "Kraken Test Status",
"updated": 1615453046113
},
{
"style": "List",
"text": "Kucoin Test Status"
},
{
"style": "List",
"text": "Luno Test Status"
},
{
"style": "Title",
"text": "Crypto Exchange Configuration"
},
{
"style": "Text",
"text": "Each exchange may require a very specific configuration. This is determined during the exchange testing process. Consult the page of each exchange as listed above. If you are interested in testing a new exchange, go to the How to Test New Exchanges page.",
"updated": 1615201685376
},
{
"style": "Subtitle",
"text": "Properties",
"updated": 1609771684679
},
{
"style": "List",
"text": "codeName is the name of the exchange as handled in the code of the system."
},
{
"style": "List",
"text": "sandBox setting this parameter to true allows SuperAlgos to perform live trading on the exchanges sandbox or testnet if one is available."
},
{
"style": "List",
"text": "API holds a series of definitions used only in the case in which the sensor bot fetches trades (using the Historic-Trades process) instead of the OHLCV process that fetches one-minute candles and is the current default. In such a case, finding the right set of parameters to work with a specific exchange may be challenging, nd involves understanding how the exchanges API and the CCXT Library API work. In other words, there is no hard rule as of what each of the values should be. Determining each of this values requires exploring the exchange's API documentation, as well as the documentation of the CCXT Library."
}
]
}
@@ -1,7 +1,14 @@
{
"type": "Exchange Accounts",
"definition": {
"text": "The exchange accounts node groups the different accounts the user may have with the corresponding exchange."
"text": "The exchange accounts node groups the different accounts the user may have with the corresponding exchange.",
"translations": [
{
"language": "ES",
"text": "El nodo exchange accounts agrupa las diferentes cuentas que el usuario pueda tener con el correspondiente exchange.",
"updated": 1628205361106
}
]
},
"paragraphs": [
{
@@ -1,7 +1,14 @@
{
"type": "Exchange Markets",
"definition": {
"text": "The exchange markets node groups the definitions of markets."
"text": "The exchange markets node groups the definitions of markets.",
"translations": [
{
"language": "ES",
"text": "El nodo exchange markets agrupa las definiciones de mercados.",
"updated": 1628046005046
}
]
},
"paragraphs": [
{
@@ -17,7 +17,7 @@
},
{
"style": "Text",
"text": "The indicator bot node holds all definitions required for an indicator bot to function. Definitions are split between the definition of processes and products. Processes are algorithms that go through an input dataset, perform certain calculations, and produce an output. Products are the outcome of the work produced by these algorithms, in the form of ellaborate data sets."
"text": "The indicator bot node holds all definitions required for an indicator bot to function. Definitions are split between the definition of processes and products. Processes are algorithms that go through an input dataset, perform certain calculations, and produce an output. Products are the outcome of the work produced by these algorithms, in the form of elaborate data sets."
},
{
"style": "Text",
@@ -42,4 +42,4 @@
"text": "codeName is the name of the bot as used within the code of the system."
}
]
}
}
@@ -1,7 +1,14 @@
{
"type": "Market",
"definition": {
"text": "A market is the definition of a pair of assets (i.e.: BTC-USDT) listed as a market in the corresponding exchange."
"text": "A market is the definition of a pair of assets (i.e.: BTC-USDT) listed as a market in the corresponding exchange.",
"translations": [
{
"language": "ES",
"text": "Un market es la definición de assets (i.e.: BTC-USDT) listados como mercado en el correspondiente exchange.",
"updated": 1628045938159
}
]
},
"paragraphs": [
{
@@ -1,7 +1,14 @@
{
"type": "Plugin File Position",
"definition": {
"text": "The position of the plugin file position node determines the position in the workspace on which the plugin hierarchy is placed."
"text": "The position of the plugin file position node determines the position in the workspace on which the plugin hierarchy is placed.",
"translations": [
{
"language": "ES",
"text": "La posición del plugin El nodo de posicin del archivo determina la posicin en el workspace en el que se coloca la jerarquía de plugin.",
"updated": 1628037843191
}
]
},
"paragraphs": [
{
@@ -1,7 +1,14 @@
{
"type": "Plugin File",
"definition": {
"text": "A plugin file is the JSON file that constitutes the plugin. In the context of the plugins hierarchy, a plugin is the definition of a hierarchy."
"text": "A plugin file is the JSON file that constitutes the plugin. In the context of the plugins hierarchy, a plugin is the definition of a hierarchy.",
"translations": [
{
"language": "ES",
"text": "Un pluginfile es el archivo JSON que constituye el complemento. En el contexto de la jerarquía de complementos, un complemento es la definición de una jerarquía.",
"updated": 1628043670168
}
]
},
"paragraphs": [
{
@@ -1,7 +1,14 @@
{
"type": "Plugin Trading Systems",
"definition": {
"text": "The plugin data mines node features the definitions of data mines to be included as plugins in the current workspace."
"text": "The plugin data mines node features the definitions of data mines to be included as plugins in the current workspace.",
"translations": [
{
"language": "ES",
"text": "El nodo plugin data mines presenta las definiciones de minas de datos que se incluirán como plugins ien la corriente workspace.",
"updated": 1628044185215
}
]
},
"paragraphs": [
{
@@ -1,7 +1,14 @@
{
"type": "Plugins",
"definition": {
"text": "The plugins hierarchy defines which plugins are to be included in the current workspace. In the context of this hierarchy, plugins are JSON files featuring the description of a hierarchy such as a data mine, trading mine, trading engine, or trading system."
"text": "The plugins hierarchy defines which plugins are to be included in the current workspace. In the context of this hierarchy, plugins are JSON files featuring the description of a hierarchy such as a data mine, trading mine, trading engine, or trading system.",
"translations": [
{
"language": "ES",
"text": "The plugins hierarchy define cual plugins se incluirán en el actual workspace. En el contexto de esta jerarquía, plugins son archivos JSON con la descripción de una jerarquía como un data mine, trading mine, trading engine, o trading system.",
"updated": 1628037249031
}
]
},
"paragraphs": [
{
@@ -1,7 +1,14 @@
{
"type": "Session Base Asset",
"definition": {
"text": "The base asset is the asset whose price is determined by the market. It is usually the first asset in the pair, as listed by the exchange."
"text": "The base asset is the asset whose price is determined by the market. It is usually the first asset in the pair, as listed by the exchange.",
"translations": [
{
"language": "ES",
"text": "El base asset es el asset cuyo precio lo determina el mercado. Por lo general, es el primer activo del par, según lo enumerado por el intercambio.",
"updated": 1628034596123
}
]
},
"paragraphs": [
{
@@ -1,7 +1,14 @@
{
"type": "Shapes",
"definition": {
"text": "The shapes node contains definitions of polygons and styles to be rendered on a per-period basis over the charts."
"text": "The shapes node contains definitions of polygons and styles to be rendered on a per-period basis over the charts.",
"translations": [
{
"language": "ES",
"text": "El shapes node contiene definiciones de polígonos y estilos que se deben representar por período en los gráficos.",
"updated": 1628036833969
}
]
},
"paragraphs": [
{
@@ -14,6 +14,13 @@
],
"definition": {
"text": "A Social Bots node is used to define the bots for each messaging application. These messaging bots are used to send announcements and receive commands used to interact with Superalgos.",
"updated": 1618222853055
"updated": 1618222853055,
"translations": [
{
"language": "ES",
"text": "Un nodo Social Bots se utiliza para definir los bots para cada aplicación de mensajería. Estos bots de mensajería se utilizan para enviar anuncios y recibir comandos que se utilizan para interactuar con Superalgos.",
"updated": 1628035119134
}
]
}
}
@@ -80,7 +80,7 @@
},
{
"style": "Text",
"text": "You may choose to apply a similar reasoning as with the open stage target rate for limit orders, but there is some nouance to consider if you are using market orders."
"text": "You may choose to apply a similar reasoning as with the open stage target rate for limit orders, but there is some nuance to consider if you are using market orders."
},
{
"style": "Callout",
@@ -109,7 +109,7 @@
},
{
"style": "Text",
"text": "To solve the above issue, you may use a more ellaborate formula for the target rate in the close stage:"
"text": "To solve the above issue, you may use a more elaborate formula for the target rate in the close stage:"
},
{
"style": "Javascript",
@@ -143,4 +143,4 @@
"text": "As you see, flexibility is a key design feature in Superalgos."
}
]
}
}
@@ -1,7 +1,14 @@
{
"type": "Trading Engine Reference",
"definition": {
"text": "A trading engine reference determines which trading engine the trading bot shall use to structure the data it processes while running the trading session."
"text": "A trading engine reference determines which trading engine the trading bot shall use to structure the data it processes while running the trading session.",
"translations": [
{
"language": "ES",
"text": "Un trading engine reference determina cual trading engine del trading bot utilizará para estructurar los datos que procesa mientras ejecuta el trading session.",
"updated": 1628035017172
}
]
},
"paragraphs": [
{
@@ -1,7 +1,14 @@
{
"type": "Trading System Reference",
"definition": {
"text": "A trading engine reference determines which trading system shall be evaluated by the trading bot to run the trading session."
"text": "A trading engine reference determines which trading system shall be evaluated by the trading bot to run the trading session.",
"translations": [
{
"language": "ES",
"text": "A trading engine la referencia determina cual trading system será evaluado por el bot de trading para ejecutar la sesión trading.",
"updated": 1628034798275
}
]
},
"paragraphs": [
{
@@ -11,6 +11,11 @@
"text": "Kontribusi anda telah terupload ke Superalgos Fork dan Pull Request telah dikirim ke penyimpanan utama Superalgos.",
"updated": 1613861035790,
"style": "Definition"
},
{
"language": "ES",
"text": "Tus contribuciones se cargaron en tu Superalgos Fork y Pull Request fue enviado al repositorio principal de Superalgos.",
"updated": 1628205473844
}
]
},
@@ -4,7 +4,14 @@
"type": "App Contribute Command",
"definition": {
"text": "This command allows you to contribute work to the project. The contribution goes to the Superalgos repository via a Pull Request from your Superalgos fork.",
"updated": 1610909304702
"updated": 1610909304702,
"translations": [
{
"language": "ES",
"text": "Este comando te permite contribuir con trabajo al proyecto. El aporte va al repositorio de Superalgos a través de un Pull Request de tu fork de Superalgos.",
"updated": 1628205171216
}
]
},
"paragraphs": [
{
@@ -9,7 +9,7 @@
"paragraphs": [
{
"style": "Success",
"text": "Also remeber that if you have tasks running at the same machine where the Superalgos Client is, they are still running the previous branch code. You need to restart them too after you restart the client.",
"text": "Also remember that if you have tasks running at the same machine where the Superalgos Client is, they are still running the previous branch code. You need to restart them too after you restart the client.",
"updated": 1610543634663
},
{
@@ -22,4 +22,4 @@
"updated": 1621288204638
}
]
}
}
@@ -4,7 +4,14 @@
"type": "Scales",
"definition": {
"text": "Time Machines feature a Time Scale, a Rate Scale, and a Time Frame Scale. Timeline charts may implement the last two.",
"updated": 1610137109400
"updated": 1610137109400,
"translations": [
{
"language": "ES",
"text": "Time Machines cuentan con un Time Scale, un Rate Scale, y un Time Frame Scale. Los gráficos de línea de tiempo pueden implementar los dos últimos.",
"updated": 1627309210785
}
]
},
"paragraphs": [
{
@@ -4,7 +4,14 @@
"type": "Plugin Workspaces",
"definition": {
"text": "Superalgos ships with several plugin workspaces set up by the community to facilitate user onboarding. This topic covers each of them and explains their purpose.",
"updated": 1616145035073
"updated": 1616145035073,
"translations": [
{
"language": "ES",
"text": "Superalgos conecta con varios plugin workspaces configurados por la comunidad para facilitar la incorporación de usuarios. Este tema cubre cada uno de ellos y explica su propósito.",
"updated": 1628037130662
}
]
},
"paragraphs": [
{
@@ -4,7 +4,14 @@
"type": "Tested Exchanges Plugin Workspace",
"definition": {
"text": "This workspace features the collection of Crypto Exchange nodes corresponding to exchanges that have been or are currently being tested. Use this workspace if you intend to test new exchanges.",
"updated": 1622624683862
"updated": 1622624683862,
"translations": [
{
"language": "ES",
"text": "Este workspace presenta la colección de nodos Crypto Exchange correspondiente a exchanges que han sido o están siendo probados actualmente. Utiliza este espacio de trabajo si tienes la intención de probar nuevos exchanges.",
"updated": 1628045858670
}
]
},
"paragraphs": [
{
@@ -4,7 +4,14 @@
"type": "Install a New Market Tutorial Plugin Workspace",
"definition": {
"text": "This workspace features a tutorial that teaches you how to work with different markets.",
"updated": 1622624869211
"updated": 1622624869211,
"translations": [
{
"language": "ES",
"text": "Este espacio de trabajo incluye un tutorial que le enseña cómo trabajar con diferentes mercados.",
"updated": 1628046098301
}
]
},
"paragraphs": [
{
@@ -42,7 +42,7 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/0_download-visual-studio.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/0_download-visual-studio.png",
"updated": 1623414213827
},
{
@@ -51,7 +51,7 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/1_open-explorer.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/1_open-explorer.png",
"updated": 1623407107099
},
{
@@ -65,12 +65,12 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/2_open-folder.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/2_open-folder.png",
"updated": 1623407112534
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/3_taskserver-folder.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/3_taskserver-folder.png",
"updated": 1623407118113
},
{
@@ -84,12 +84,12 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/4_add-folder.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/4_add-folder.png",
"updated": 1623407412773
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/5_projects-folder.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/5_projects-folder.png",
"updated": 1623407419399
},
{
@@ -99,7 +99,7 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/6_explorer-folders.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/6_explorer-folders.png",
"updated": 1623408036777
},
{
@@ -109,7 +109,7 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/7_save-workspace.png"
"text": "PNGs/Foundations/Docs/debugging-your-indicator/7_save-workspace.png"
},
{
"style": "Text",
@@ -28,7 +28,7 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/8_locate-singlemarket-in-tree.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/8_locate-singlemarket-in-tree.png",
"updated": 1623409023676
},
{
@@ -43,7 +43,7 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/9_find-line-for-breakpoint.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/9_find-line-for-breakpoint.png",
"updated": 1623409045497
},
{
@@ -36,7 +36,7 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/10_node-run.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/10_node-run.png",
"updated": 1623409808656
},
{
@@ -51,7 +51,7 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/11_start-debugging.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/11_start-debugging.png",
"updated": 1623409861513
},
{
@@ -61,7 +61,7 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/12_run-and-debug.png"
"text": "PNGs/Foundations/Docs/debugging-your-indicator/12_run-and-debug.png"
},
{
"style": "Text",
@@ -74,7 +74,7 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/13_network.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/13_network.png",
"updated": 1623410476464
},
{
@@ -89,12 +89,12 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/14_expand-data-tasks.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/14_expand-data-tasks.png",
"updated": 1623410569919
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/15_debug-your-indicator-task.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/15_debug-your-indicator-task.png",
"updated": 1623410589000
},
{
@@ -104,12 +104,12 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/16_run-ohlcvs.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/16_run-ohlcvs.png",
"updated": 1623411034335
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/17_run-dependencies.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/17_run-dependencies.png",
"updated": 1623411039717
},
{
@@ -119,7 +119,7 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/18_check-debug-terminal.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/18_check-debug-terminal.png",
"updated": 1623411066811
},
{
@@ -40,12 +40,12 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/19_breaking-point-indication.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/19_breaking-point-indication.png",
"updated": 1623411413725
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/20_stopped-at-breaking-point.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/20_stopped-at-breaking-point.png",
"updated": 1623411419203
},
{
@@ -62,7 +62,7 @@
},
{
"style": "Png",
"text": "PNGs/Superalgos/Docs/debugging-your-indicator/21_zoomed-in-getting-values.png",
"text": "PNGs/Foundations/Docs/debugging-your-indicator/21_zoomed-in-getting-values.png",
"updated": 1623411423507
},
{
@@ -11,6 +11,11 @@
"text": "Didalam dokumen ini menampilkan enam kategori halaman yaitu: nodes, concepts, topics, tutorials, reviews, dan books. Setiap kategori diwakilkan oleh sebuah tab dalam Docs Search Results.",
"updated": 1613859527741,
"style": "Definition"
},
{
"language": "ES",
"text": "Los documentos cuentan con seis categorías de páginas: Node, Concept, Topic, Tutorial, Review, y Book. Cada categoría está representada por una pestaña en los resultados de la búsqueda de Documentos.",
"updated": 1628205085106
}
]
},
@@ -14,8 +14,8 @@
},
{
"style": "Text",
"text": "Maybe you realized that you are doing repetitive actions at the Design Space and you can benefit from automating them. If your actions are constrained to manipulating the nodes at the workspace, by either creating new nodes, deleting existing ones, changing nodes configs, establishing references or some other similar stuff, then you might be able to create an Action function that can automate all this. This will allow you to stop doing those repetitive tasks youself and the ones that will come after you if you contribute these changes to the project.",
"updated": 1614940379811
"text": "Maybe you realized that you are doing repetitive actions at the Design Space and you can benefit from automating them. If your actions are constrained to manipulating the nodes at the workspace, by either creating new nodes, deleting existing ones, changing nodes configs, establishing references or something similar, then you might be able to create an Action function that can automate all this. This will allow you to complete the action with the click of a button and stop doing those repetitive tasks youself. Not to mention help make Superalgos easier to use for everyone once you contribute your action!",
"updated": 1628255167092
},
{
"style": "Title",
@@ -23,8 +23,8 @@
},
{
"style": "Text",
"text": "New Actions are implemented as functions inside a Function Library. So the basic workflow to implement a new Action is the following:",
"updated": 1614940407806
"text": "New Actions are implemented as functions inside a Function Library. So the basic workflow to implement a new Action is as follows:",
"updated": 1628255279553
},
{
"style": "List",
@@ -43,8 +43,8 @@
},
{
"style": "List",
"text": "Connect Menu Item to your Code: Finally you will connect the Menu Item to that function you wrote.",
"updated": 1614940545908
"text": "Connect Menu Item to your Code: Finally you will connect the Menu Item to the function you wrote.",
"updated": 1628255317721
}
]
}
@@ -14,17 +14,18 @@
},
{
"style": "Text",
"text": "Check out the page of the App Schema concept. After that, locate the App Schema file you will need to edit at the Projects folder. There is one App Schema file for Project, pick the right one and edit it with VS Code."
"text": "Check out the page of the App Schema concept. After that, locate the App Schema file you will need to edit at the Projects folder. There is one App Schema file for each Project, pick the right one and edit it with VS Code.",
"updated": 1628255380671
},
{
"style": "Warning",
"text": "Be carefull not to damage anything in the App Schema file while editing it. You will get into trouble if you do so. It can not only produce the UI not to load, but it can also damage the workspace you are working at.",
"updated": 1614940590024
"text": "Be carefull not to damage anything in the App Schema file while editing it. You will get into trouble if you do. It can not only cause the UI to not load, but also damage the workspace you are working at.",
"updated": 1628255452468
},
{
"style": "Success",
"text": "If you are not sure which project a certain node belongs to, there is a trick to find it out: close the Docs tab, and make focus on the node you want to add an Action to. While on focus, use Ctrl + Shift + Alt + F12 to log in the browser console the Node object. Inspect it to see the project property. Most likely it will be a Superalgos project's node.",
"updated": 1614940654950
"text": "If you are not sure which project a certain node belongs to, there is a trick to find it: close the Docs tab, and make focus on the node you want to add an Action to. While on focus, use Ctrl + Shift + Alt + F12 to log in the browser console the Node object. Inspect it to see the project property. Most likely it will be a Foundations project's node.",
"updated": 1628255532030
},
{
"style": "Title",
@@ -37,8 +38,8 @@
},
{
"style": "Json",
"text": "{\n \"action\": \"Add UI Object\",\n \"actionFunction\": \"payload.executeAction\",\n \"label\": \"Add Image\",\n \"relatedUiObject\": \"Image\"\n }",
"updated": 1614789262250
"text": "{\n \"action\": \"Add Missing Workspace Projects\",\n \"label\": \"Add Missing Projects\",\n \"relatedUiObject\": \"Workspace\",\n \"actionFunction\": \"payload.executeAction\"\n}",
"updated": 1628255951872
},
{
"style": "Text",
@@ -90,6 +91,11 @@
{
"style": "List",
"text": "propertyToCheckFor: read the previous property."
},
{
"style": "List",
"text": "workDoneLabel: text to display when action has completed",
"updated": 1628256114205
}
]
}
@@ -9,18 +9,18 @@
"paragraphs": [
{
"style": "Text",
"text": "The procedure to locate a suitable Function Library is very easy. Open the Projects folder, getting into the Project the Node where the action is going to be triggered at is defined. Inside that project Folder get into the UI folder and then into Function-Libraries folder.",
"updated": 1614940833232
"text": "The procedure to locate a suitable Function Library is very easy. Open the Projects folder, then open the Project associated with the Node you are attaching your action to. Inside that project Folder open the UI folder and then you will see the Function-Libraries folder.",
"updated": 1628256668116
},
{
"style": "Note",
"text": "Each file in there is a Function Library except for the one called ActionSwitch.js, which is the place where you connect the Action Function name you defined at the App Schema with the function that will host the code for the new Action.",
"updated": 1614928708817
"text": "Each file within the Function Library folder is a set of functions. The only exception to this is ActionSwitch.js. This file is the place where you will connect the Action Function name you defined at the App Schema with the function that will host the code for the new Action.",
"updated": 1628256808055
},
{
"style": "Text",
"text": "Inspect each of these files and see at their header the functions they already implement. After a quick scan over all of them you can decide which one is where your action belongs to. If you believe that your Action should be placed at a new Function Library, then you can try to add a new one and set it up at the Project Schema file, but that is out of the scope of this guide.",
"updated": 1614928780531
"text": "Inspect each of these files and see at their header the functions they already implement. After a quick scan over all of them you can decide which one fits best with your new action. If you believe that your Action should be placed at a new Function Library, then you can try to add a new one and set it up at the Project Schema file, but that is out of the scope of this guide.",
"updated": 1628256858024
},
{
"style": "Title",
@@ -3,18 +3,19 @@
"pageNumber": 4,
"type": "Automating Actions - Adding your Function",
"definition": {
"text": "Take a look at how other functions are implemented in the Function Library and try to follow that way.",
"updated": 1614941850917
"text": "Take a look at how other functions are implemented in the Function Library and try to follow the same format.",
"updated": 1628257476029
},
"paragraphs": [
{
"style": "Text",
"text": "The basic procedure is quite straight forward. First add the function name to the thisObject and the write you function at the most appropiate place at the Function Library. ",
"updated": 1614941084806
"text": "The basic procedure is quite straight forward. First add the function name to the thisObject and then write your function at the most appropiate place at the Function Library.",
"updated": 1628257461177
},
{
"style": "Important",
"text": "Please document your function the best you can, even if you see the other functions implemented at the same library poorly documented. See if you can make your function the best documented in the whole library."
"text": "Please document your function the best you can, even if you see other functions implemented at the same library poorly documented. See if you can make your function the best documented in the whole library.",
"updated": 1628257493687
},
{
"style": "Title",
@@ -9,8 +9,8 @@
"paragraphs": [
{
"style": "Text",
"text": "It is a very good idea to invest some time at the Utilities folder, scaning the files in there to see what you already have available to use at your actions. You will see that other actions in Function Libraries heavily rely on utilities functions defined at one of the files at the Utilities folder.",
"updated": 1614930012933
"text": "It is a very good idea to invest some time at the Utilities folder, scaning the files in there to see what you already have available to use at your actions. You will see that other actions in Function Libraries heavily rely on utilities functions defined at one of the files within the Utilities folder.",
"updated": 1628257595439
},
{
"style": "Title",
@@ -19,7 +19,8 @@
},
{
"style": "Text",
"text": "At runtime, all utility objects will be already instantiated by the time your Action function code runs. You just need to get to the object that host the utility funtion you want to execute via the UI Global Object that is available to you. For exmaple:"
"text": "At runtime, all utility objects will be already instantiated by the time your Action function code runs. You just need to get to the object that hosts the utility function you want to execute via the UI Global Object that is available to you. For example:",
"updated": 1628257649169
},
{
"style": "Javascript",
@@ -3,14 +3,14 @@
"pageNumber": 6,
"type": "Automating Actions - Using Function Libraries",
"definition": {
"text": "You might also as well other functions located at Function Libraries from within your Action Function. In order to do this, you just need to locate the instance of the Function Library Object and call any of it's functions.",
"updated": 1614942828678
"text": "You can also utilize other functions located within the Function Libraries to help build your Action Function. In order to do this, you just need to locate the instance of the Function Library Object and call any of it's functions.",
"updated": 1628257841959
},
"paragraphs": [
{
"style": "Text",
"text": "It is a very good idea to invest some time at the Function-Libraries folder, scaning the files in there to see what you already have available to use at your actions. You will see that other actions in Function Libraries heavily rely on functions defined at one of the files at the Function-Libraries folder.",
"updated": 1614942900881
"text": "It is a very good idea to invest some time at the Function-Libraries folder, scaning the files in there to see what you already have available to use at your actions. You will see that other actions in Function Libraries heavily rely on functions defined at one of the files within the Function-Libraries folder.",
"updated": 1628257873103
},
{
"style": "Title",
@@ -19,8 +19,8 @@
},
{
"style": "Text",
"text": "At runtime, all Funtion Library objects will be already instantiated by the time your Action function code runs. You just need to get to the object that host the Function Library funtion you want to execute via the UI Global Object that is available to you. For exmaple:",
"updated": 1614942976608
"text": "At runtime, all Function Library objects will be already instantiated by the time your Action function code runs. You just need to get to the object that host the Function Library funtion you want to execute via the UI Global Object that is available to you. For exmaple:",
"updated": 1628257884243
},
{
"style": "Javascript",
@@ -48,8 +48,8 @@
},
{
"style": "Text",
"text": "At your own Action Function you might likely need to execute these functions, belonging to popular actions done at Action Functions:",
"updated": 1614943932540
"text": "At your own Action Function you will likely need to execute these or similar functions, belonging to popular actions defined within other Action Functions:",
"updated": 1628257991399
},
{
"style": "Subtitle",
@@ -57,7 +57,8 @@
},
{
"style": "Text",
"text": "The following is an example on how to add a new children to an existing Node:"
"text": "The following is an example on how to add a new child to an existing Node:",
"updated": 1628258008587
},
{
"style": "Javascript",
@@ -87,13 +88,13 @@
},
{
"style": "Text",
"text": "Example of how to set the Reference Parent of a Node (in this case no Function Library is needed):",
"updated": 1614944033214
"text": "Example of how to set the Reference Parent of a Node:",
"updated": 1628258163153
},
{
"style": "Javascript",
"text": "node.payload.referenceParent = baseAsset\n",
"updated": 1614943688069
"text": "UI.projects.foundations.functionLibraries.attachDetach.referenceAttachNode(timeMachine, session)",
"updated": 1628258141256
},
{
"style": "Text",
@@ -3,8 +3,8 @@
"pageNumber": 8,
"type": "Automating Actions - Adding an Action Switch Case",
"definition": {
"text": "This steps create the mapping betwheen the actionFunction name you defined at the Menu Item of the node that can trigger your Action, and the function you coded inside a Function Library that will execute the code for the new Action. ",
"updated": 1614941772231
"text": "This step creates the mapping between the actionFunction name you defined at the Menu Item of the node to can trigger your Action, and the function you coded inside a Function Library that will execute the code for the new Action.",
"updated": 1628258863939
},
"paragraphs": [
{
@@ -18,8 +18,8 @@
},
{
"style": "Text",
"text": "Find within the list of cases some of the cases pointint to the same Function Library your new Action is hosted at, so that you can add a new case together with the rest.",
"updated": 1614937904095
"text": "Find within the list of cases some of the cases pointing to the same Function Library your new Action is hosted at, so that you can add a new case together with the rest.",
"updated": 1628258889849
},
{
"style": "Title",
@@ -37,8 +37,12 @@
},
{
"style": "Success",
"text": "As you can see will you most likely be sending the node and rootNodes parameters into your Action function. You might want to also send other parameters from data you might find into the action object available to you at that point.",
"updated": 1614938157839
"text": "As you can see you will most likely be sending the node and rootNodes parameters into your Action function. However, you might want to also send other parameters with data you find available within the system at this point into the action object. ",
"updated": 1628259076042
},
{
"style": "Note",
"text": "Setting a breakpoint here within Chrome's devTools is a convenient way to check the system for available data. "
},
{
"style": "Text",
@@ -14,7 +14,8 @@
},
{
"style": "Text",
"text": "In order to debug your action, you will need to open the developer tool, and at the Sources tab, locate the Function Library file where you added your action, place a breakpoint at the begining of your function and go and click at the node Menu Item you added."
"text": "In order to debug your action, you will need to open the developer tool, and at the Sources tab, locate the Function Library file where you added your action, place a breakpoint at the beginning of your function and go and click at the node Menu Item you added.",
"updated": 1628261072790
},
{
"style": "Success",
@@ -4,7 +4,14 @@
"type": "Hierarchies",
"definition": {
"text": "A hierarchy is a data structure representing an overarching, top-level concept, resulting in a long chain of nodes, usually with many ramifications. The system manages different types of hierarchies, each of them with a specific focus.",
"updated": 1609945718294
"updated": 1609945718294,
"translations": [
{
"language": "ES",
"text": "Un hierarchyes una estructura de datos que representa un concepto general de nivel superior, que da como resultado una larga cadena de nodos, generalmente con muchas ramificaciones. El sistema gestiona diferentes tipos de jerarquías, cada una de ellas con un enfoque específico.",
"updated": 1628044685355
}
]
},
"paragraphs": [
{
@@ -4,7 +4,14 @@
"type": "Node Attaching Rules",
"definition": {
"text": "Each Node Type can have a set of rules that defines to which Node Type it can attach itself to.",
"updated": 1609237513121
"updated": 1609237513121,
"translations": [
{
"language": "ES",
"text": "Cada Node Type puede tener un conjunto de reglas que defina a qué Node Type puede adherirse.",
"updated": 1628036385094
}
]
},
"paragraphs": [
{
@@ -4,7 +4,14 @@
"type": "Node Referencing Rules",
"definition": {
"text": "Each Node Type can have a set of rules that defines with which Node Type it can stablish a reference.",
"updated": 1609244259240
"updated": 1609244259240,
"translations": [
{
"language": "ES",
"text": "Cada Node Type puede tener un conjunto de reglas que defina con qué Node Type puede establecer una referencia.",
"updated": 1628036524256
}
]
},
"paragraphs": [
{
@@ -4,7 +4,14 @@
"type": "Backups",
"definition": {
"text": "The backup feature is designed to preserve the integrity of references as you would expect when you wish to restore a data structure to a previous state of affairs.",
"updated": 1611489612653
"updated": 1611489612653,
"translations": [
{
"language": "ES",
"text": "La función backup está diseñada para preservar la integridad de las referencias, como esperaría cuando desees restaurar una estructura de datos a un estado anterior.",
"updated": 1628036272845
}
]
},
"paragraphs": [
{
@@ -4,7 +4,14 @@
"type": "Clones",
"definition": {
"text": "The clone feature is designed to produce copies of data structures when you need to replicate structures of nodes and expect the copies to behave similarly to the original.",
"updated": 1615832633335
"updated": 1615832633335,
"translations": [
{
"language": "ES",
"text": "La función clone está diseñada para producir copias de estructuras de datos cuando necesita replicar estructuras de nodos y espera que las copias se comporten de manera similar al original.",
"updated": 1628036115149
}
]
},
"paragraphs": [
{
@@ -4,7 +4,14 @@
"type": "Shares",
"definition": {
"text": "The share feature works almost the same as the back up feature, but discarding personal information like exchange keys.",
"updated": 1611490590355
"updated": 1611490590355,
"translations": [
{
"language": "ES",
"text": "La función share funciona casi de la misma manera que la función de copia de seguridad, pero descarta información personal como exchanges keys.",
"updated": 1628037037100
}
]
},
"paragraphs": [
{
@@ -4,7 +4,14 @@
"type": "Plugins-Docs",
"definition": {
"text": "The branch Plugins-Docs is used by contributors of Plugins, documentations or tutorials. This branch in syncronized with Develop and Master everytime a new version is released, and it's purpose is to allow the flow of docs pages, plugins and tutorials into the master branch at a higher rate than changes at the codebase done at the Develop branch. This means that the Master branch might have many updates in between releases.",
"updated": 1622467789596
"updated": 1622467789596,
"translations": [
{
"language": "ES",
"text": "La rama Plugins-Docs es utilizada por los contribuyentes de Plugins, documentaciones o tutoriales. Esta rama está sincronizada con Develop y Master cada vez que se lanza una nueva versión, y su propósito es permitir el flujo de páginas de documentos, plugins ay tutoriales en la Master Branch a un ritmo mayor que los cambios en la base de código realizados en el la rama Develop. This means that the Master Branch puede tener muchas actualizaciones entre lanzamientos.",
"updated": 1628203486790
}
]
},
"paragraphs": [
{
@@ -4,7 +4,14 @@
"type": "Develop Group",
"definition": {
"text": "This is where developers meet to discuss building indicators, strategies, or improving the system.",
"updated": 1618833860687
"updated": 1618833860687,
"translations": [
{
"language": "ES",
"text": "Aquí es donde los desarrolladores se reúnen para discutir los indicadores de construcción, las estrategias o la mejora del sistema.",
"updated": 1628205506466
}
]
},
"paragraphs": [
{
Loaded 100 of 349 files, more files were not shown because too many files have changed in this diff. Show more