diff --git a/package-lock.json b/package-lock.json index 766ef280..cfa16ac6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -398,6 +398,11 @@ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + }, "axios": { "version": "0.24.0", "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", @@ -624,6 +629,11 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, "commander": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", @@ -729,6 +739,11 @@ "randomfill": "^1.0.3" } }, + "cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" + }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -1277,6 +1292,11 @@ } } }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -1344,6 +1364,16 @@ "web-streams-polyfill": "4.0.0-beta.1" } }, + "fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1413,6 +1443,11 @@ "type-fest": "^0.20.2" } }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -1662,6 +1697,11 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, "joi-browser": { "version": "13.4.0", "resolved": "https://registry.npmjs.org/joi-browser/-/joi-browser-13.4.0.tgz", @@ -1702,6 +1742,15 @@ "minimist": "^1.2.0" } }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, "kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -1818,6 +1867,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -2050,6 +2104,18 @@ "resolved": "https://registry.npmjs.org/promisify-child-process/-/promisify-child-process-4.1.1.tgz", "integrity": "sha512-/sRjHZwoXf1rJ+8s4oWjYjGRVKNK1DUnqfRC1Zek18pl0cN6k3yJ1cCbqd0tWNe4h0Gr+SY4vR42N33+T82WkA==" }, + "prompt": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.2.0.tgz", + "integrity": "sha512-iGerYRpRUg5ZyC+FJ/25G5PUKuWAGRjW1uOlhX7Pi3O5YygdK6R+KEaBjRbHSkU5vfS5PZCltSPZdDtUYwRCZA==", + "requires": { + "async": "~0.9.0", + "colors": "^1.1.2", + "read": "1.0.x", + "revalidator": "0.1.x", + "winston": "2.x" + } + }, "prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -2119,6 +2185,14 @@ "safe-buffer": "^5.1.0" } }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "requires": { + "mute-stream": "~0.0.4" + } + }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -2162,6 +2236,11 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "revalidator": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", + "integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=" + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -2270,6 +2349,11 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, "stream-browserify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", @@ -2469,6 +2553,11 @@ "which-boxed-primitive": "^1.0.2" } }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -2559,6 +2648,31 @@ "is-symbol": "^1.0.3" } }, + "winston": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.5.tgz", + "integrity": "sha512-TWoamHt5yYvsMarGlGEQE59SbJHqGsZV8/lwC+iCcGeAe0vUaOh+Lv6SYM17ouzC/a/LB1/hz/7sxFBtlu1l4A==", + "requires": { + "async": "~1.0.0", + "colors": "1.0.x", + "cycle": "1.0.x", + "eyes": "0.1.x", + "isstream": "0.1.x", + "stack-trace": "0.0.x" + }, + "dependencies": { + "async": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", + "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + } + } + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", diff --git a/package.json b/package.json index c8d91a5b..8e72f779 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "@aeternity/aeproject", "version": "4.0.0-alpha1", "description": "aeternity smart contract testing tool", + "main": "src/lib/index.js", "bin": { "aeproject": "./src/cli.js" }, diff --git a/src/cli.js b/src/cli.js index 4e4253ce..cc53fab1 100755 --- a/src/cli.js +++ b/src/cli.js @@ -2,7 +2,7 @@ const program = require('commander'); -const commands = require('./commands'); +const commands = require('./cli/commands'); const packageJson = require('../package.json'); const setupVersion = () => { diff --git a/src/commands.js b/src/cli/commands.js similarity index 61% rename from src/commands.js rename to src/cli/commands.js index 84482657..25022437 100644 --- a/src/commands.js +++ b/src/cli/commands.js @@ -1,17 +1,13 @@ -const compile = require('./compile/compile'); -const init = require('./init/init'); -const testConfig = require('./test/test'); -const env = require('./env/env/env'); -const node = require('./env/env/node/node'); -const compiler = require('./env/env/compiler/compiler'); -const deploy = require('./deploy/deploy'); -const config = require('./config'); +const compile = require('../compile/compile'); +const init = require('../init/init'); +const testConfig = require('../test/test'); +const env = require('../env/env'); +const deploy = require('../deploy/deploy'); +const config = require('../config/node-config.json'); const dockerIp = config.nodeConfiguration.dockerMachineIP; -const exportConfig = require('./export/export-config'); -const aeprojectConfigDefaultFileName = require('./export/constants').aeprojectConfigFileName; -const txInspector = require('./tx-inspector/tx-inspector'); -const compatibility = require('./compatibility/compatibility'); +const txInspector = require('../tx-inspector/tx-inspector'); +const compatibility = require('../compatibility/compatibility'); const nodeConfig = config.nodeConfiguration; const compilerConfig = config.compilerConfiguration; @@ -63,34 +59,6 @@ const addEnvOption = (program) => { }); }; -const addNodeOption = (program) => { - program - .command('node') - .description('Running a local node. Without any argument node will be run with --start argument') - .option('--stop', 'Stop the node') - .option('--start', 'Start the node') - .option('--info', 'Displays information about your current node status if any, and absolute path where it has been started from') - .option('--windows', 'Start the node in windows env') - .option('--docker-ip [default docker machine ip]', `Set docker machine IP, default is "${dockerIp}"`, dockerIp) - .option('--v [v]', `Specify node version, default is ${nodeConfig.imageVersion}`, nodeConfig.imageVersion) - .action(async (options) => { - await node.run(options); - }); -}; - -const addCompilerOption = (program) => { - program - .command('compiler') - .description('Running a local compiler. Without any arguments compiler will be run with --start argument') - .option('--stop', 'Stop the node') - .option('--start', 'Start the node') - .option('--info', 'Displays information about your current node status if any, and absolute path where it has been started from') - .option('--v [v]', `Specify compiler version, default is ${compilerConfig.imageVersion}`, compilerConfig.imageVersion) - .action(async (options) => { - await compiler.run(options); - }); -}; - const addDeployOption = (program) => { program .command('deploy') @@ -104,16 +72,6 @@ const addDeployOption = (program) => { }); }; -const addExportConfigOption = (program) => { - program - .command('export-config') - .description('Export miner account, few funded accounts and default node configuration.') - .option('--path [export path]', 'Path to export config file', aeprojectConfigDefaultFileName) - .action(async (options) => { - await exportConfig.run(options); - }); -}; - const addTxInspector = (program) => { program .command('inspect ') @@ -144,10 +102,7 @@ const initCommands = (program) => { addCompileOption(program); addTestOption(program); addEnvOption(program); - addNodeOption(program); - addCompilerOption(program); addDeployOption(program); - addExportConfigOption(program); addTxInspector(program); addCompatibility(program); }; diff --git a/src/compatibility/compatibility.js b/src/compatibility/compatibility.js index 6834596b..7ec244b8 100644 --- a/src/compatibility/compatibility.js +++ b/src/compatibility/compatibility.js @@ -1,7 +1,7 @@ const { exec } = require('promisify-child-process'); -const { print } = require('../utils'); +const { print } = require('../utils/utils'); -const nodeConfig = require('../config').nodeConfiguration; +const nodeConfig = require('../config/node-config.json').nodeConfiguration; async function run(option) { let { nodeVersion } = option; diff --git a/src/compile/compile.js b/src/compile/compile.js index c337928d..e7c463d4 100644 --- a/src/compile/compile.js +++ b/src/compile/compile.js @@ -1,40 +1,8 @@ -const { ContractCompilerAPI } = require('@aeternity/aepp-sdk'); - -const { printError, print } = require('../utils'); -const utils = require('../utils'); -const config = require('../config'); - -async function compileAndPrint(file, compiler) { - try { - const result = await compiler.compileContractAPI(utils.getContractContent(file), { filesystem: utils.getFilesystem(file) }); - print(`Contract '${file}' has been successfully compiled.`); - print(`=> bytecode: ${result}`); - } catch (error) { - const errorMessage = utils.checkNestedProperty(error.response, 'data') ? JSON.parse(error.response.data)[0] : error.message; - printError(`Contract '${file}' has not been compiled.`); - printError(`=> reason: ${JSON.stringify(errorMessage)}`); - } -} +const config = require('../config/config.json'); async function run(path, compilerUrl = config.compilerUrl) { print('===== Compiling contracts ====='); - print('\r'); - const compiler = await ContractCompilerAPI({ compilerUrl }); - print(`Compiler URL: ${compilerUrl}`); - print(`Compiler version: ${await compiler.getCompilerVersion()}`); - print('\r'); - print(`Contract path: ${path}`); - - // TODO check async await correct - if (path.includes('.aes')) { - compileAndPrint(path, compiler); - } else { - print('\r'); - const files = await utils.getFiles(`${process.cwd()}/${path}/`, '.*\.(aes)'); - files.forEach(async (file) => { - compileAndPrint(file, compiler); - }); - } + // TODO replace with ae cli } module.exports = { diff --git a/src/config/index.js b/src/config/index.js deleted file mode 100644 index cdd0b1e6..00000000 --- a/src/config/index.js +++ /dev/null @@ -1,22 +0,0 @@ -const { localhostParams } = require('./config.json'); -const { testNetParams } = require('./config.json'); -const { mainNetParams } = require('./config.json'); -const { keypair } = require('./config.json'); -const { compilerUrl } = require('./config.json'); - -const { config } = require('./node-config.json'); -const { defaultWallets } = require('./node-config.json'); -const { nodeConfiguration } = require('./node-config.json'); -const { compilerConfiguration } = require('./node-config.json'); - -module.exports = { - localhostParams, - testNetParams, - mainNetParams, - keypair, - compilerUrl, - config, - defaultWallets, - nodeConfiguration, - compilerConfiguration, -}; diff --git a/src/config/node-config.json b/src/config/node-config.json index a7988a5b..6d2b3a78 100644 --- a/src/config/node-config.json +++ b/src/config/node-config.json @@ -1,72 +1,16 @@ { - "config": { - "host": "http://localhost:3001", - "internalHost": "http://localhost:3001", - "keyPair": { - "secretKey": "bb9f0b01c8c9553cfbaf7ef81a50f977b1326801ebf7294d1c2cbccdedf27476e9bbf604e611b5460a3b3999e9771b6f60417d73ce7c5519e12f7e127a1225ca", - "publicKey": "ak_2mwRmUeYmfuW93ti9HMSUJzCk1EYcQEfikVSzgo6k2VghsWhgU" - }, - "amountToFund": 10000000000000000000 - }, - - "defaultWallets": [{ - "publicKey": "ak_fUq2NesPXcYZ1CcqBcGC3StpdnQw3iVxMA3YSeCNAwfN4myQk", - "secretKey": "7c6e602a94f30e4ea7edabe4376314f69ba7eaa2f355ecedb339df847b6f0d80575f81ffb0a297b7725dc671da0b1769b1fc5cbe45385c7b5ad1fc2eaf1d609d" - }, - { - "publicKey": "ak_tWZrf8ehmY7CyB1JAoBmWJEeThwWnDpU4NadUdzxVSbzDgKjP", - "secretKey": "7fa7934d142c8c1c944e1585ec700f671cbc71fb035dc9e54ee4fb880edfe8d974f58feba752ae0426ecbee3a31414d8e6b3335d64ec416f3e574e106c7e5412" - }, - { - "publicKey": "ak_FHZrEbRmanKUe9ECPXVNTLLpRP2SeQCLCT6Vnvs9JuVu78J7V", - "secretKey": "1509d7d0e113528528b7ce4bf72c3a027bcc98656e46ceafcfa63e56597ec0d8206ff07f99ea517b7a028da8884fb399a2e3f85792fe418966991ba09b192c91" - }, - { - "publicKey": "ak_RYkcTuYcyxQ6fWZsL2G3Kj3K5WCRUEXsi76bPUNkEsoHc52Wp", - "secretKey": "58bd39ded1e3907f0b9c1fbaa4456493519995d524d168e0b04e86400f4aa13937bcec56026494dcf9b19061559255d78deea3281ac649ca307ead34346fa621" - }, - { - "publicKey": "ak_2VvB4fFu7BQHaSuW5EkQ7GCaM5qiA5BsFUHjJ7dYpAaBoeFCZi", - "secretKey": "50458d629ae7109a98e098c51c29ec39c9aea9444526692b1924660b5e2309c7c55aeddd5ebddbd4c6970e91f56e8aaa04eb52a1224c6c783196802e136b9459" - }, - { - "publicKey": "ak_286tvbfP6xe4GY9sEbuN2ftx1LpavQwFVcPor9H4GxBtq5fXws", - "secretKey": "707881878eacacce4db463de9c7bf858b95c3144d52fafed4a41ffd666597d0393d23cf31fcd12324cd45d4784d08953e8df8283d129f357463e6795b40e88aa" - }, - { - "publicKey": "ak_f9bmi44rdvUGKDsTLp3vMCMLMvvqsMQVWyc3XDAYECmCXEbzy", - "secretKey": "9262701814da8149615d025377e2a08b5f10a6d33d1acaf2f5e703e87fe19c83569ecc7803d297fde01758f1bdc9e0c2eb666865284dff8fa39edb2267de70db" - }, - { - "publicKey": "ak_23p6pT7bajYMJRbnJ5BsbFUuYGX2PBoZAiiYcsrRHZ1BUY2zSF", - "secretKey": "e15908673cda8a171ea31333538437460d9ca1d8ba2e61c31a9a3d01a8158c398a14cd12266e480f85cc1dc3239ed5cfa99f3d6955082446bebfe961449dc48b" - }, - { - "publicKey": "ak_gLYH5tAexTCvvQA6NpXksrkPJKCkLnB9MTDFTVCBuHNDJ3uZv", - "secretKey": "6eb127925aa10d6d468630a0ca28ff5e1b8ad00db151fdcc4878362514d6ae865951b78cf5ef047cab42218e0d5a4020ad34821ca043c0f1febd27aaa87d5ed7" - }, - { - "publicKey": "ak_zPoY7cSHy2wBKFsdWJGXM7LnSjVt6cn1TWBDdRBUMC7Tur2NQ", - "secretKey": "36595b50bf097cd19423c40ee66b117ed15fc5ec03d8676796bdf32bc8fe367d82517293a0f82362eb4f93d0de77af5724fba64cbcf55542328bc173dbe13d33" - } - ], - - "nodeConfiguration": { - "configFileName": "docker-compose.yml", - "textToSearch": "aeternity/aeternity", - "dockerImage": "aeternity/aeternity", - "dockerServiceNodeName" : "node", - "dockerMachineIP" : "192.168.99.100", - "imageVersion": "v6.2.0", - "envLiteral": "NODE_TAG" - }, - - "compilerConfiguration": { - "configFileName": "docker-compose.compiler.yml", - "textToSearch": "aeternity/aesophia_http", - "dockerImage": "aeternity/aesophia_http", - "dockerServiceCompilerName": "compiler", - "imageVersion": "v6.0.2", - "envLiteral": "COMPILER_TAG" - } -} \ No newline at end of file + "nodeConfiguration": { + "imageVersion": "master", + "containerName": "aeproject_node", + "envLiteral": "NODE_TAG" + }, + "compilerConfiguration": { + "imageVersion": "v6.1.0", + "containerName": "aeproject_compiler", + "envLiteral": "COMPILER_TAG" + }, + "proxyConfiguration": { + "imageVersion": "latest", + "containerName": "aeproject_proxy" + } +} diff --git a/src/env/EnvService.js b/src/env/EnvService.js deleted file mode 100644 index 080ed048..00000000 --- a/src/env/EnvService.js +++ /dev/null @@ -1,415 +0,0 @@ -// TODO replace nodeStore/Service -const { exec, spawn } = require('promisify-child-process'); - -const fs = require('fs'); -const path = require('path'); -const {print, readSpawnOutput, readErrorSpawnOutput, sleep, capitalize,} = require('../utils'); -const utils = require('../utils'); - -const nodeConfig = require('../config'); - -const { config } = nodeConfig; - -const { defaultWallets } = nodeConfig; -let network = nodeConfig.localhostParams; -network.compilerUrl = nodeConfig.localhostParams.compilerUrl; - -const compilerConfigs = nodeConfig.compilerConfiguration; -const { nodeConfiguration } = nodeConfig; - -const DEFAULT_COMPILER_PORT = 3080; -const DEFAULT_NODE_PORT = 3001; -const MAX_SECONDS_TO_RUN_NODE = 90; -const DefaultColumnVariable = 'export COLUMNS=1000'; - -const POSSIBLE_ERRORS = [ - 'port is already allocated', - 'address already in use', - 'not found', - // messages when docker is blocked by firewall - 'request canceled', - 'Temporary failure in name resolution', - 'registry-1.docker.io', - 'forbidden by its access permissions', -]; - -const isWindowsPlatform = process.platform === 'win32'; - -class EnvService { - constructor(unit) { - this._unit = unit; - } - - async shouldProcessStart(running) { - if (!this.hasConfigFiles()) { - print('Process will be terminated!'); - return false; - } - - if (running) { - print('===== Compiler or Node is already running! ===== \n===== Please run the relevant command to start an image alone! ====='); - return false; - } - - if (await this.checkForAllocatedPort(DEFAULT_NODE_PORT, DEFAULT_COMPILER_PORT)) { - print(`\r\n===== Port [${DEFAULT_COMPILER_PORT}] or Port [${DEFAULT_NODE_PORT}] is already allocated! Process will be terminated! =====`); - print('Cannot start AE env, port is already allocated!'); - return false; - } - return true; - } - - hasConfigFiles() { - return this.hasCompilerConfigFiles() && this.hasNodeConfigFiles(); - } - - hasNodeConfigFiles() { - const neededNodeConfigFile = nodeConfiguration.configFileName; - const nodeConfigFilePath = path.resolve(process.cwd(), neededNodeConfigFile); - - const doesNodeConfigFileExists = fs.existsSync(nodeConfigFilePath); - - if (!doesNodeConfigFileExists) { - print(`Missing ${neededNodeConfigFile} file!`); - return false; - } - - let nodeFileContent = fs.readFileSync(nodeConfigFilePath, 'utf-8'); - - nodeFileContent = nodeFileContent.replace(/'/g, ''); - - if (nodeFileContent.indexOf(nodeConfiguration.textToSearch) < 0) { - print(`Invalid ${neededNodeConfigFile} file!`); - return false; - } - - return true; - } - - hasCompilerConfigFiles() { - const neededCompilerConfigFile = compilerConfigs.configFileName; - const compilerConfigFilePath = path.resolve(process.cwd(), neededCompilerConfigFile); - - const doesCompilerConfigFileExists = fs.existsSync(compilerConfigFilePath); - - if (!doesCompilerConfigFileExists) { - print(`Missing ${neededCompilerConfigFile} file!`); - return false; - } - - const compilerFileContent = fs.readFileSync(compilerConfigFilePath, 'utf-8'); - - if (compilerFileContent.indexOf(compilerConfigs.textToSearch) < 0) { - print(`Invalid ${neededCompilerConfigFile} file!`); - return false; - } - - return true; - } - - async start(image, nodeVersion, compilerVersion) { - let nodeVerEnvVar = `export ${nodeConfiguration.envLiteral}=${nodeVersion}`; - let compilerVerEnvVar = `export ${compilerConfigs.envLiteral}=${compilerVersion}`; - if (isWindowsPlatform) { - nodeVerEnvVar = `set "${nodeConfiguration.envLiteral}=${nodeVersion}"`; - compilerVerEnvVar = `set "${compilerConfigs.envLiteral}=${compilerVersion}"`; - } - - let runCommand; - switch (this._unit) { - case 'compiler': - runCommand = exec(`${compilerVerEnvVar} && docker-compose -f docker-compose.compiler.yml up -d`); - nodeService.save(this._unit); - break; - case 'node': - runCommand = exec(`${nodeVerEnvVar} && docker-compose -f docker-compose.yml up -d`); - nodeService.save(this._unit); - break; - default: - runCommand = exec(`${nodeVerEnvVar} && ${compilerVerEnvVar} && docker-compose -f docker-compose.yml -f docker-compose.compiler.yml up -d`); - nodeService.save(); - } - - // toggle loader - if (runCommand.stdout) { - runCommand.stdout.on('data', (data) => { - print(data.toString('utf8')); - }); - } - - let errorMessage = ''; - if (runCommand.stderr) { - runCommand.stderr.on('data', (data) => { - errorMessage += data.toString(); - console.log(data.toString('utf8')); - }); - } - - let counter = 0; - while (!(await this.isImageRunning(`${image}`))) { - for (const possibleError of POSSIBLE_ERRORS) { - if (errorMessage.indexOf(possibleError) >= 0) { - await this.stopAll(); - console.log('Cannot start AE Node!'); - throw new Error(errorMessage); - } - } - - process.stdout.write('.'); - sleep(1000); - - // prevent infinity loop - counter++; - if (counter >= MAX_SECONDS_TO_RUN_NODE) { - // if node is started and error message is another, - // we should stop docker - - await this.stopAll(); - throw new Error('Cannot start AE Node!'); - } - } - - return runCommand; - } - - async stopAll() { - if (nodeService.getNodePath() && nodeService.getCompilerPath()) { - await this.stopNode(); - await this.stopCompiler(); - } else if (nodeService.getNodePath()) { - await this.stopNode(); - } else if (nodeService.getCompilerPath()) { - await this.stopCompiler(); - } - } - - async stopNode() { - try { - await spawn('docker-compose', [ - '-f', - `${nodeService.getNodePath()}`, - 'down', - ]); - - print('===== Node was successfully stopped! ====='); - return nodeService.delete('node'); - } catch (error) { - if (readErrorSpawnOutput(error).indexOf('active endpoints')) { - nodeService.delete('node'); - return print('===== Node was successfully stopped! ====='); - } - - throw new Error(error); - } - } - - async stopCompiler() { - try { - await spawn('docker-compose', [ - '-f', - `${nodeService.getCompilerPath()}`, - 'down', - ]); - - print('===== Compiler was successfully stopped! ====='); - - return nodeService.delete('compiler'); - } catch (error) { - if (readErrorSpawnOutput(error).indexOf('active endpoints')) { - nodeService.delete('compiler'); - return print('===== Compiler was successfully stopped! ====='); - } - - throw new Error(error); - } - } - - async getInfo(options) { - const nodePath = nodeService.getNodePath(); - const compilerPath = nodeService.getCompilerPath(); - - if (isWindowsPlatform) { - if (!this._unit && nodePath && compilerPath) { - return exec(`docker-compose -f ${nodePath} -f ${compilerPath} ps`, options); - } if (this._unit.indexOf('node') >= 0 && nodePath) { - return exec(`docker-compose -f ${nodePath} ps`, options); - } if (this._unit.indexOf('compiler') >= 0 && compilerPath) { - return exec(`docker-compose -f ${compilerPath} ps`, options); - } - return exec('docker-compose -f docker-compose.yml -f docker-compose.compiler.yml ps', options); - } if (!this._unit && nodePath && compilerPath) { - return exec(`${DefaultColumnVariable} && docker-compose -f ${nodePath} -f ${compilerPath} ps`, options); - } if (this._unit.indexOf('node') >= 0 && nodePath) { - return exec(`${DefaultColumnVariable} && docker-compose -f ${nodePath} ps`, options); - } if (this._unit.indexOf('compiler') >= 0 && compilerPath) { - return exec(`${DefaultColumnVariable} && docker-compose -f ${compilerPath} ps`, options); - } - return exec(`${DefaultColumnVariable} && docker-compose -f docker-compose.yml -f docker-compose.compiler.yml ps`, options); - } - - async printInfo(running) { - if (!running) { - print(`===== ${capitalize(this._unit)} is not running! =====`); - return; - } - - const buff = await this.getInfo(); - const res = readSpawnOutput(buff); - - print(res); - } - - async isImageRunning(image, options) { - try { - let running = false; - - const result = await this.getInfo(options); - - let res = readSpawnOutput(result); - - if (res) { - res = res.split('\n'); - } - - if (Array.isArray(res)) { - res.map((line) => { - if (line.indexOf(image) >= 0 && line.includes('healthy')) { - running = true; - } - }); - } - - return running; - } catch (error) { - if (this.checkForMissingDirectory(error)) { - return false; - } - - if (error.stderr) { - console.log(error.stderr.toString('utf8')); - } else { - console.log(error.message || error); - } - - throw Error(error); - } - } - - checkForMissingDirectory(e) { - return (e.stderr && e.stderr.toString('utf-8').indexOf('No such file or directory') >= 0); - } - - async checkForAllocatedPort(...portArgs) { - let isAllocated = false; - - for (const port in portArgs) { - try { - const scanForAllocatedPort = await spawn('lsof', ['-i', `:${portArgs[port]}`]); - - if (scanForAllocatedPort.stdout) { - isAllocated = scanForAllocatedPort.stdout.toString('utf8').length > 0; - } - } catch (e) { - // Throws an error when there is no running port. Exceptions are handled elsewhere. - isAllocated = false || isAllocated; - } - } - - return isAllocated; - } - - printSuccessMsg() { - switch (this._unit) { - case 'compiler': - print(`\n\r===== ${capitalize(this._unit)} was successfully started! =====`); - break; - case 'node': - print(`\n\r===== ${capitalize(this._unit)} was successfully started! =====`); - print('===== Funding default wallets! ====='); - break; - default: - print('\n\r===== Node was successfully started! ====='); - print('===== Compiler was successfully started! ====='); - print('===== Funding default wallets! ====='); - } - } - - printStarMsg() { - switch (this._unit) { - case 'compiler': - case 'node': - print(`===== Starting ${capitalize(this._unit)} =====`); - break; - default: - print('===== Starting node and compiler ====='); - } - } - - async printInitialStopMsg() { - switch (this._unit) { - case 'compiler': - case 'node': - print(`===== Stopping ${capitalize(this._unit)} =====`); - break; - default: - print('===== Stopping node and compiler ====='); - } - } - - removePrefixFromIp(ip) { - if (!ip) { - return ''; - } - - return ip.replace('http://', '').replace('https://', ''); - } - - async fundWallets(nodeIp) { - await this.waitToMineCoins(nodeIp); - - let walletIndex = 0; - - const client = await utils.getClient(network); - await this.printBeneficiaryKey(client); - for (const wallet in defaultWallets) { - await this.fundWallet(client, defaultWallets[wallet].publicKey); - await this.printWallet(client, defaultWallets[wallet], `#${walletIndex++}`); - } - } - - async waitToMineCoins(nodeIp) { - try { - if (nodeIp) { - network = JSON.parse(JSON.stringify(network).replace(/localhost/g, nodeIp)); - } - - const client = await utils.getClient(network); - const heightOptions = { - interval: 8000, - attempts: 300, - }; - return await client.awaitHeight(10, heightOptions); - } catch (error) { - throw Error(error); - } - } - - async printBeneficiaryKey(client) { - await this.printWallet(client, config.keyPair, 'Miner'); - } - - async printWallet(client, keyPair, label) { - const keyPairBalance = await client.balance(keyPair.publicKey); - - print(`${label} ------------------------------------------------------------`); - print(`public key: ${keyPair.publicKey}`); - print(`private key: ${keyPair.secretKey}`); - print(`Wallet's balance is ${keyPairBalance}`); - } - - async fundWallet(client, recipient) { - await client.spend(config.amountToFund, recipient); - } -} - -module.exports = EnvService; diff --git a/src/env/env.js b/src/env/env.js new file mode 100644 index 00000000..7f53e0c0 --- /dev/null +++ b/src/env/env.js @@ -0,0 +1,87 @@ +const {spawn, exec} = require("promisify-child-process"); + +const {print, printError, readSpawnOutput} = require('../utils/utils'); +const {nodeConfiguration, compilerConfiguration, proxyConfiguration} = require('../config/node-config.json'); + +async function isEnvRunning() { + const info = await getInfo() + + if (info) { + const containers = [nodeConfiguration.containerName, compilerConfiguration.containerName, proxyConfiguration.containerName]; + return containers.every(containerName => { + const line = info.split('\n').find(line => line.includes(containerName)) + return line && line.includes('Up') + }) + } + + return false; +} + +async function run(option) { + const nodeVersion = option.nodeVersion || nodeConfiguration.imageVersion; + const compilerVersion = option.compilerVersion || compilerConfiguration.imageVersion; + + const running = await isEnvRunning(); + + if (option.info) { + await printInfo(running); + return; + } + + if (option.stop) { + await stopEnv(running); + return; + } + + await startEnv(nodeVersion, compilerVersion); +} + +async function stopEnv(running) { + if (!running) { + printError('===== Env is not running! ====='); + return; + } + + print('===== stopping env ====='); + + await spawn('docker-compose', [ + 'down', + '-v', + ]); + + print('===== Env was successfully stopped! ====='); +} + +async function startEnv(nodeVersion, compilerVersion) { + print('===== starting env ====='); + + await exec(`NODE_TAG=${nodeVersion} COMPILER_TAG=${compilerVersion} docker-compose pull`) + await exec(`NODE_TAG=${nodeVersion} COMPILER_TAG=${compilerVersion} docker-compose up -d`) + + print('===== Env was successfully started! ====='); +} + +async function printInfo(running) { + if (!running) { + printError('===== Compiler or Node is not running! ===== \n===== Please run the relevant command for your image! ====='); + return; + } + + print(await getInfo()); +} + + +async function getInfo() { + const info = await exec(`docker-compose ps`); + + if (info && info.stdout) { + return info.stdout; + } + + return null +} + +module.exports = { + run +}; + diff --git a/src/env/env/compiler/compiler.js b/src/env/env/compiler/compiler.js deleted file mode 100644 index 71144d29..00000000 --- a/src/env/env/compiler/compiler.js +++ /dev/null @@ -1,97 +0,0 @@ -const { - printError, - print, -} = require('../../../utils'); - -const nodeConfig = require('../../../config'); - -const compilerConfigs = nodeConfig.compilerConfiguration; - -const DEFAULT_COMPILER_PORT = 3080; - -const EnvService = require('../../EnvService'); - -class Compiler extends EnvService { - constructor() { - super('compiler'); - } - - async run(option) { - const compilerImage = compilerConfigs.dockerServiceCompilerName; - let { compilerVersion } = compilerConfigs; - - if (option.v) { - compilerVersion = option.v; - } - - try { - let running = await super.isImageRunning(compilerImage); - - if (option.info) { - await super.printInfo(running); - return; - } - - if (option.stop) { - // if not running, current env may be windows - // to reduce optional params we check is it running on windows env - if (!running) { - running = await super.isImageRunning(compilerImage); - } - - if (!running) { - printError('===== Compiler is not running! ====='); - return; - } - - super.printInitialStopMsg(); - - try { - await super.stopCompiler(); - } catch (error) { - printError(Buffer.from(error.stderr).toString('utf-8')); - } - - return; - } - - if (!await this.shouldProcessStart(running)) return; - - super.printStarMsg(); - - await super.start(compilerImage, null, compilerVersion); - - super.printSuccessMsg(); - } catch (e) { - printError(e.message || e); - } - } - - async shouldProcessStart(running) { - if (!super.hasCompilerConfigFiles()) { - print('Process will be terminated!'); - return false; - } - - if (running) { - print('\r\n===== Compiler already started and healthy! ====='); - return false; - } - - if (await super.checkForAllocatedPort(DEFAULT_COMPILER_PORT)) { - print(`\r\n===== Port [${DEFAULT_COMPILER_PORT}] is already allocated! Process will be terminated! =====`); - print('Cannot start AE compiler, port is already allocated!'); - return false; - } - - return true; - } -} - -const compiler = new Compiler(); - -module.exports = { - run: async (options) => { - await compiler.run(options); - }, -}; diff --git a/src/env/env/env.js b/src/env/env/env.js deleted file mode 100644 index c4e6eca3..00000000 --- a/src/env/env/env.js +++ /dev/null @@ -1,106 +0,0 @@ -const {print, printError, readSpawnOutput,} = require('../../utils'); -const { nodeConfiguration, compilerConfiguration } = require('../../config'); - -const EnvService = require('../EnvService'); - -class Env extends EnvService { - constructor() { - super(''); - } - - async printInfo(running) { - if (!running) { - printError('===== Compiler or Node is not running! ===== \n===== Please run the relevant command for your image! ====='); - return; - } - - const dockerInfoBuffer = await this.getInfo(); - const result = readSpawnOutput(dockerInfoBuffer); - - print(result); - } - - async areNodeAndCompilerRunning(...images) { - let running = true; - - for (const currImage in images) { - running = await super.isImageRunning(images[currImage]) && running; - } - - return running; - } - - async run(option) { - let running; - const dockerImage = nodeConfiguration.dockerServiceNodeName; - const compilerImage = compilerConfiguration.dockerServiceCompilerName; - - let { nodeVersion } = nodeConfiguration; - let { compilerVersion } = compilerConfiguration; - - if (option.nodeVersion) { - nodeVersion = option.nodeVersion; - } - - if (option.compilerVersion) { - compilerVersion = option.compilerVersion; - } - - running = await this.areNodeAndCompilerRunning(dockerImage, compilerImage); - - if (option.info) { - await this.printInfo(running); - return; - } - - if (option.stop) { - // if not running, current env may be windows - // to reduce optional params we check is it running on windows env - if (!running) { - // TODO line below to be deleted if tests for windows pass! Needs to be verified. - // running = await this.areNodeAndCompilerRunning(dockerImage, compilerImage) - printError('===== Compiler or Node is not running! ===== \n===== Please run the relevant command for your image! ====='); - return; - } - - super.printInitialStopMsg(); - - try { - await super.stopAll(); - } catch (error) { - printError(Buffer.from(error.stderr).toString('utf-8')); - } - - return; - } - - if (!await super.shouldProcessStart(running)) return; - - try { - super.printStarMsg(); - - await super.start(dockerImage, nodeVersion, compilerVersion); - - super.printSuccessMsg(); - - if (option.windows) { - const dockerIp = super.removePrefixFromIp(option.dockerIp); - await super.fundWallets(dockerIp); - } else { - await super.fundWallets(); - } - - print('\r\n===== Default wallets were successfully funded! ====='); - } catch (e) { - printError(e.message || e); - } - } -} - -const env = new Env(); - -module.exports = { - run: async (options) => { - await env.run(options); - }, -}; diff --git a/src/env/env/node/node.js b/src/env/env/node/node.js deleted file mode 100644 index 9ad1e375..00000000 --- a/src/env/env/node/node.js +++ /dev/null @@ -1,109 +0,0 @@ -const { - printError, - print, -} = require('../../../utils'); - -const nodeConfig = require('../../../config'); - -const { nodeConfiguration } = nodeConfig; - -const DEFAULT_NODE_PORT = 3001; - -const EnvService = require('../../EnvService'); - -class Node extends EnvService { - constructor() { - super('node'); - } - - async run(option) { - const dockerImage = nodeConfiguration.dockerServiceNodeName; - - let { nodeVersion } = nodeConfiguration; - - if (option.v) { - nodeVersion = option.v; - } - - try { - const running = await super.isImageRunning(dockerImage); - - if (option.info) { - await super.printInfo(running); - return; - } - - if (option.stop) { - // if not running, current env may be windows - // to reduce optional params we check is it running on windows env - - // TODO block below to be deleted if tests for windows pass! Needs to be verified. - // if (!running) { - // running = await super.isImageRunning(dockerImage); - // } - - if (!running) { - print('===== Node is not running! ====='); - return; - } - - super.printInitialStopMsg(); - - try { - await super.stopNode(); - } catch (error) { - printError(Buffer.from(error.stderr).toString('utf-8')); - } - - return; - } - - if (!await this.shouldProcessStart(running)) return; - - super.printStarMsg(); - - await super.start(dockerImage, nodeVersion, null); - - super.printSuccessMsg(); - - if (option.windows) { - const dockerIp = super.removePrefixFromIp(option.dockerIp); - await super.fundWallets(dockerIp); - } else { - await super.fundWallets(); - } - - print('\r\n===== Default wallets were successfully funded! ====='); - } catch (e) { - printError(e.message || e); - } - } - - async shouldProcessStart(running) { - if (!super.hasNodeConfigFiles()) { - print('Process will be terminated!'); - return false; - } - - if (running) { - print('\r\n===== Node already started and healthy! ====='); - return false; - } - - if (await super.checkForAllocatedPort(DEFAULT_NODE_PORT)) { - print(`\r\n===== Port [${DEFAULT_NODE_PORT}] is already allocated! Process will be terminated! =====`); - printError('Cannot start AE node, port is already allocated!'); - return false; - } - - return true; - } -} - -const node = new Node(); - -module.exports = { - run: async (options) => { - await node.run(options); - }, -}; diff --git a/src/export/constants.js b/src/export/constants.js deleted file mode 100644 index cd2fdb15..00000000 --- a/src/export/constants.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - aeprojectConfigFileName: './aeprojectConfig.json', -}; diff --git a/src/export/export-config.js b/src/export/export-config.js deleted file mode 100644 index be338f53..00000000 --- a/src/export/export-config.js +++ /dev/null @@ -1,78 +0,0 @@ -const path = require('path'); -const config = require('../config'); -const utils = require('../utils'); -const aeprojectConfigDefaultFileName = require('./constants').aeprojectConfigFileName; - -const DEFAULT_NUMBER_OF_WALLETS = 3; - -function exportMinerWallet(keypair) { - return { - minerWallet: { - publicKey: keypair.publicKey, - secretKey: keypair.secretKey, - }, - }; -} - -function exportWallets(defaultWallets) { - const wallets = []; - let index = 0; - for (const defaultWallet of defaultWallets) { - if (index >= DEFAULT_NUMBER_OF_WALLETS) { - break; - } - - wallets.push( - { - publicKey: defaultWallet.publicKey, - secretKey: defaultWallet.secretKey, - }, - ); - - index++; - } - - return wallets; -} - -function exportNodeConfiguration(config) { - const localHostParams = config.localhostParams; - - const localhostConfig = { - networkId: localHostParams.networkId, - host: localHostParams.url, - internalHost: localHostParams.url, - compilerUrl: config.compilerUrl, - }; - - return localhostConfig; -} - -async function writeToFile(aeprojectConfig, destination) { - await utils.createDirIfNotExists(destination); - if (!destination.endsWith('.json')) { - destination = path.join( - destination, - aeprojectConfigDefaultFileName, - ); - } - - utils.writeFileSync(destination, JSON.stringify(aeprojectConfig)); -} - -async function run(options) { - const localHostConfig = exportNodeConfiguration(config); - const minerKeyPair = exportMinerWallet(config.keypair); - const defaultWallets = exportWallets(config.defaultWallets); - - let aeprojectConfig = { ...localHostConfig }; - aeprojectConfig = Object.assign(aeprojectConfig, minerKeyPair); - aeprojectConfig.defaultWallets = defaultWallets; - - console.log(JSON.stringify(aeprojectConfig, null, 2)); - await writeToFile(aeprojectConfig, options.path); -} - -module.exports = { - run, -}; diff --git a/src/init/artifacts/ExampleContract.aes b/src/init/artifacts/ExampleContract.aes deleted file mode 100644 index c92a0bf8..00000000 --- a/src/init/artifacts/ExampleContract.aes +++ /dev/null @@ -1,28 +0,0 @@ -@compiler >= 6 - -include "./lib/ExampleLibrary.aes" - -contract CryptoHamster = - datatype event = NewHamster(indexed int, string, hash) - - record state = { hamsters : map(string, hash), next_id : int } - - stateful entrypoint init() = { hamsters = {}, next_id = 0 } - - entrypoint nameExists(name: string) : bool = - Map.member(name, state.hamsters) - - stateful entrypoint createHamster(hamsterName: string) = - require(!nameExists(hamsterName), "Name is already taken") - createHamsterByNameDNA(hamsterName, generateDNA(hamsterName)) - - entrypoint getHamsterDNA(hamsterName: string) : hash = - require(nameExists(hamsterName), "Hamster does not exist!") - state.hamsters[hamsterName] - - stateful function createHamsterByNameDNA(name: string, dna: hash) = - put(state{hamsters[name] = dna, next_id = (state.next_id + 1)}) - Chain.event(NewHamster(state.next_id, name, dna)) - - function generateDNA(name : string) : hash = - ExampleHelpers.getDNA(name) diff --git a/src/init/artifacts/ExampleLibrary.aes b/src/init/artifacts/ExampleLibrary.aes deleted file mode 100644 index 2018b7de..00000000 --- a/src/init/artifacts/ExampleLibrary.aes +++ /dev/null @@ -1,7 +0,0 @@ -@compiler >= 6 - -include "String.aes" - -namespace ExampleHelpers = - function getDNA(name: string): hash = - String.sha3(name) \ No newline at end of file diff --git a/src/init/artifacts/contracts/ExampleContract.aes b/src/init/artifacts/contracts/ExampleContract.aes new file mode 100644 index 00000000..5a889164 --- /dev/null +++ b/src/init/artifacts/contracts/ExampleContract.aes @@ -0,0 +1,4 @@ +@compiler >= 6 + +main contract Example = + entrypoint example(x : int) = x diff --git a/src/init/artifacts/deployTemplate.js b/src/init/artifacts/deployTemplate.js deleted file mode 100644 index 63de8b44..00000000 --- a/src/init/artifacts/deployTemplate.js +++ /dev/null @@ -1,39 +0,0 @@ -const {Universal, MemoryAccount, Node, Crypto,} = require('@aeternity/aepp-sdk'); -const contractUtils = require('../utils/contract-utils'); - -const NETWORKS = require('../config/network.json'); - -const DEFAULT_NETWORK_NAME = 'local'; - -const EXAMPLE_CONTRACT_SOURCE = './contracts/ExampleContract.aes'; - -const deploy = async (secretKey, network, compiler) => { - if (!secretKey) { - throw new Error('Required option missing: secretKey'); - } - const KEYPAIR = { - secretKey, - publicKey: Crypto.getAddressFromPriv(secretKey), - }; - const NETWORK_NAME = network || DEFAULT_NETWORK_NAME; - - const client = await Universal({ - nodes: [ - { name: NETWORK_NAME, instance: await Node({ url: NETWORKS[NETWORK_NAME].nodeUrl }) }, - ], - compilerUrl: compiler || NETWORKS[NETWORK_NAME].compilerUrl, - accounts: [MemoryAccount({ keypair: KEYPAIR })], - address: KEYPAIR.publicKey, - }); - // a filesystem object must be passed to the compiler if the contract uses custom includes - const filesystem = contractUtils.getFilesystem(EXAMPLE_CONTRACT_SOURCE); - // get content of contract - const contract_content = contractUtils.getContractContent(EXAMPLE_CONTRACT_SOURCE); - contract = await client.getContractInstance(contract_content, { filesystem }); - const deployment_result = await contract.deploy([]); - console.log(deployment_result); -}; - -module.exports = { - deploy, -}; diff --git a/src/init/artifacts/exampleTests.js b/src/init/artifacts/exampleTests.js deleted file mode 100644 index 87b2c3d0..00000000 --- a/src/init/artifacts/exampleTests.js +++ /dev/null @@ -1,76 +0,0 @@ -const chai = require('chai'); - -const { assert } = chai; - -const { Universal, MemoryAccount, Node } = require('@aeternity/aepp-sdk'); - -const NETWORKS = require('../config/network.json'); - -const NETWORK_NAME = 'local'; - -const { defaultWallets: WALLETS } = require('../config/wallets.json'); - -const contractUtils = require('../utils/contract-utils'); - -const EXAMPLE_CONTRACT_SOURCE = './contracts/ExampleContract.aes'; - -describe('ExampleContract', () => { - let contract; - let hamsterName; - - before(async () => { - const node = await Node({ url: NETWORKS[NETWORK_NAME].nodeUrl }); - const client = await Universal({ - nodes: [ - { name: NETWORK_NAME, instance: node }, - ], - compilerUrl: NETWORKS[NETWORK_NAME].compilerUrl, - accounts: [MemoryAccount({ keypair: WALLETS[0] })], - address: WALLETS[0].publicKey, - }); - try { - // a filesystem object must be passed to the compiler if the contract uses custom includes - const filesystem = contractUtils.getFilesystem(EXAMPLE_CONTRACT_SOURCE); - // get content of contract - const contract_content = contractUtils.getContractContent(EXAMPLE_CONTRACT_SOURCE); - // initialize the contract instance - contract = await client.getContractInstance(contract_content, { filesystem }); - } catch (err) { - console.error(err); - assert.fail('Could not initialize contract instance'); - } - }); - - it('Should deploy ExampleContract', async () => { - await contract.deploy([]); - }); - - it('Should check if hamster has been created', async () => { - hamsterName = 'C.Hamster'; - await contract.methods.createHamster(hamsterName); - const result = await contract.methods.nameExists(hamsterName); - assert.isTrue(result.decodedResult, 'hamster has not been created'); - }); - - it('Should REVERT if hamster already exists', async () => { - try { - await contract.methods.createHamster('C.Hamster'); - assert.fail('createHamster didn\'t fail'); - } catch (err) { - assert.include(err.message, 'Name is already taken', 'expected error message doesn\'t exist'); - } - }); - - it('Should return false if name does not exist', async () => { - hamsterName = 'DoesHamsterExist'; - const result = await contract.methods.nameExists(hamsterName); - assert.isFalse(result.decodedResult); - }); - - it('Should return true if the name exists', async () => { - hamsterName = 'DoesHamsterExist'; - await contract.methods.createHamster(hamsterName); - const result = await contract.methods.nameExists(hamsterName); - assert.isTrue(result.decodedResult); - }); -}); diff --git a/src/init/artifacts/git_ignore b/src/init/artifacts/git_ignore deleted file mode 100644 index 045477df..00000000 --- a/src/init/artifacts/git_ignore +++ /dev/null @@ -1,3 +0,0 @@ -.aeproject-store -.DS_Store -node_modules \ No newline at end of file diff --git a/src/init/artifacts/package.json b/src/init/artifacts/package.json deleted file mode 100644 index 42d468db..00000000 --- a/src/init/artifacts/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "aeproject-project", - "version": "1.0.0", - "description": "This is the default package.json generated for your project", - "main": "index.js", - "scripts": { - "test": "mocha ./test/**/*.js --timeout 0 --exit", - }, - "author": "", - "license": "ISC" -} diff --git a/src/init/artifacts/test/exampleTests.js b/src/init/artifacts/test/exampleTests.js new file mode 100644 index 00000000..ea31073b --- /dev/null +++ b/src/init/artifacts/test/exampleTests.js @@ -0,0 +1,35 @@ +const {assert} = require('chai'); +const {Universal, MemoryAccount, Node} = require('@aeternity/aepp-sdk'); +const {wallets, networks, utils} = require('@aeternity/aeproject'); + +const EXAMPLE_CONTRACT_SOURCE = './contracts/ExampleContract.aes'; + +describe('ExampleContract', () => { + let contract; + + before(async () => { + const client = await Universal({ + nodes: [{name: 'node', instance: await Node({url: networks.devmode.nodeUrl, ignoreVersion: true})}], + compilerUrl: networks.devmode.compilerUrl, + accounts: [MemoryAccount({keypair: wallets[0]})] + }); + + // a filesystem object must be passed to the compiler if the contract uses custom includes + const filesystem = utils.getFilesystem(EXAMPLE_CONTRACT_SOURCE); + + // get content of contract + const contract_content = utils.getContractContent(EXAMPLE_CONTRACT_SOURCE); + + // initialize the contract instance + contract = await client.getContractInstance(contract_content, {filesystem}); + }); + + it('deploy ExampleContract', async () => { + await contract.deploy(); + }); + + it('call ExampleContract', async () => { + const {decodedResult} = await contract.methods.example(42) + assert.equal(decodedResult, 42); + }); +}); diff --git a/src/init/artifacts/wallets.json b/src/init/artifacts/wallets.json deleted file mode 100644 index 853bc161..00000000 --- a/src/init/artifacts/wallets.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "defaultWallets": [ - { - "publicKey": "ak_fUq2NesPXcYZ1CcqBcGC3StpdnQw3iVxMA3YSeCNAwfN4myQk", - "secretKey": "7c6e602a94f30e4ea7edabe4376314f69ba7eaa2f355ecedb339df847b6f0d80575f81ffb0a297b7725dc671da0b1769b1fc5cbe45385c7b5ad1fc2eaf1d609d" - }, - { - "publicKey": "ak_tWZrf8ehmY7CyB1JAoBmWJEeThwWnDpU4NadUdzxVSbzDgKjP", - "secretKey": "7fa7934d142c8c1c944e1585ec700f671cbc71fb035dc9e54ee4fb880edfe8d974f58feba752ae0426ecbee3a31414d8e6b3335d64ec416f3e574e106c7e5412" - }, - { - "publicKey": "ak_FHZrEbRmanKUe9ECPXVNTLLpRP2SeQCLCT6Vnvs9JuVu78J7V", - "secretKey": "1509d7d0e113528528b7ce4bf72c3a027bcc98656e46ceafcfa63e56597ec0d8206ff07f99ea517b7a028da8884fb399a2e3f85792fe418966991ba09b192c91" - }, - { - "publicKey": "ak_RYkcTuYcyxQ6fWZsL2G3Kj3K5WCRUEXsi76bPUNkEsoHc52Wp", - "secretKey": "58bd39ded1e3907f0b9c1fbaa4456493519995d524d168e0b04e86400f4aa13937bcec56026494dcf9b19061559255d78deea3281ac649ca307ead34346fa621" - }, - { - "publicKey": "ak_2VvB4fFu7BQHaSuW5EkQ7GCaM5qiA5BsFUHjJ7dYpAaBoeFCZi", - "secretKey": "50458d629ae7109a98e098c51c29ec39c9aea9444526692b1924660b5e2309c7c55aeddd5ebddbd4c6970e91f56e8aaa04eb52a1224c6c783196802e136b9459" - }, - { - "publicKey": "ak_286tvbfP6xe4GY9sEbuN2ftx1LpavQwFVcPor9H4GxBtq5fXws", - "secretKey": "707881878eacacce4db463de9c7bf858b95c3144d52fafed4a41ffd666597d0393d23cf31fcd12324cd45d4784d08953e8df8283d129f357463e6795b40e88aa" - }, - { - "publicKey": "ak_f9bmi44rdvUGKDsTLp3vMCMLMvvqsMQVWyc3XDAYECmCXEbzy", - "secretKey": "9262701814da8149615d025377e2a08b5f10a6d33d1acaf2f5e703e87fe19c83569ecc7803d297fde01758f1bdc9e0c2eb666865284dff8fa39edb2267de70db" - }, - { - "publicKey": "ak_23p6pT7bajYMJRbnJ5BsbFUuYGX2PBoZAiiYcsrRHZ1BUY2zSF", - "secretKey": "e15908673cda8a171ea31333538437460d9ca1d8ba2e61c31a9a3d01a8158c398a14cd12266e480f85cc1dc3239ed5cfa99f3d6955082446bebfe961449dc48b" - }, - { - "publicKey": "ak_gLYH5tAexTCvvQA6NpXksrkPJKCkLnB9MTDFTVCBuHNDJ3uZv", - "secretKey": "6eb127925aa10d6d468630a0ca28ff5e1b8ad00db151fdcc4878362514d6ae865951b78cf5ef047cab42218e0d5a4020ad34821ca043c0f1febd27aaa87d5ed7" - }, - { - "publicKey": "ak_zPoY7cSHy2wBKFsdWJGXM7LnSjVt6cn1TWBDdRBUMC7Tur2NQ", - "secretKey": "36595b50bf097cd19423c40ee66b117ed15fc5ec03d8676796bdf32bc8fe367d82517293a0f82362eb4f93d0de77af5724fba64cbcf55542328bc173dbe13d33" - } - ] -} \ No newline at end of file diff --git a/src/init/constants.json b/src/init/constants.json index c20e5ca4..3911e0e4 100644 --- a/src/init/constants.json +++ b/src/init/constants.json @@ -1,24 +1,7 @@ { - "testDir": "./test", - "testTemplateFile": "exampleTests.js", - "testFileDestination": "./test/exampleTest.js", - "deployDir": "./deployment", - "deployTemplateFile": "deployTemplate.js", - "deployFileDestination": "./deployment/deploy.js", - "contractsDir": "./contracts", - "contractTemplateFile": "ExampleContract.aes", - "contractFileDestination": "./contracts/ExampleContract.aes", + "artifactsDest": "./", "artifactsDir": "/artifacts", - "dockerDir": "./docker", - "dockerTemplateDir": "docker", - "dockerFilesDestination": "./docker", - "dockerNodeYmlFile": "docker-compose.yml", - "dockerCompilerYmlFile": "docker-compose.compiler.yml", - "dockerNodeYmlFileDestination": "./docker-compose.yml", - "dockerCompilerYmlFileDestination": "./docker-compose.compiler.yml", - "gitIgnoreFile": ".gitignore", - "gitIgnoreContent": "git_ignore", - "sdkVersion": "8.2.1", - "aeNodeImage": "aeternity/aeternity:v6.2.0", - "aeCompilerImage": "aeternity/aesophia_http:v6.0.2" + "updateArtifactsDir": "/update-artifacts", + "aeNodeTag": "master", + "aeCompilerTag": "v6.1.2" } diff --git a/src/init/init.js b/src/init/init.js index 8b8639d4..e6695ae1 100644 --- a/src/init/init.js +++ b/src/init/init.js @@ -1,449 +1,59 @@ -const prompts = require('prompts'); -const yaml = require('js-yaml'); -const fs = require('fs'); -const path = require('path'); +const {exec} = require('promisify-child-process'); -const { sdkVersion } = require('./constants.json'); -const { execute, printError, print, createMissingFolder, copyFileOrDir, writeFileRelative, readFileRelative } = require('../utils'); -const config = require('../config'); +const constants = require('./constants.json'); +const {print} = require('../utils/utils'); + +const {copyFolderRecursiveSync, fileExists} = require('../utils/fs-utils'); async function run(update) { if (update) { - await updateAEprojectProjectLibraries(sdkVersion, update); - return; - } - - try { + await updateAEprojectProjectLibraries(); + } else { await createAEprojectProjectStructure(); - } catch (e) { - printError(e.message); - console.error(e); } } const createAEprojectProjectStructure = async () => { - print('===== Initializing AEproject ====='); - await installLibraries(); - - print('===== Creating project file & dir structure ====='); - - await setupContracts(); - await setupTests(); - await setupDeploy(); - await setupDocker(); - await setupConfig(); - await addIgnoreFile(); - - print('===== AEproject was successfully initialized! ====='); -}; - -const compareSdkVersions = async (_sdkVersion, cwd) => { - // get current sdk version - const userPackageJson = JSON.parse(fs.readFileSync(path.join(cwd, './package.json'), 'utf8')); - const userSdkVersion = userPackageJson.dependencies['@aeternity/aepp-sdk']; - - if (userSdkVersion) { - const userVersioning = userSdkVersion.split('.'); - const updateToVersioning = _sdkVersion.split('.'); - - const promptMessage = `Found newer or different version of sdk ${userSdkVersion}. Keep it, instead of ${_sdkVersion}?`; - - for (let i = 0; i < 3; i++) { - const user = userVersioning[i]; - const updateTo = updateToVersioning[i]; + print('===== initializing aeproject ====='); - if (!isNaN(user)) { - if (parseInt(user) > parseInt(updateTo)) { - if (await promptUpdate(promptMessage)) { - _sdkVersion = userSdkVersion; - break; - } - } - } else if (await promptUpdate(promptMessage)) { - _sdkVersion = userSdkVersion; - break; - } - } - } - - return _sdkVersion; -}; - -const updateAEprojectProjectLibraries = async (_sdkVersion, update) => { - print('===== Updating AEproject files ====='); - - _sdkVersion = await compareSdkVersions(_sdkVersion, process.cwd()); - - await setupDocker(true); - await installAEproject(update); + await setupArtifacts(); + await installDependencies(); - print('===== AEproject was successfully updated! ====='); + print('===== aeproject successfully initialized ====='); }; -const installLibraries = async () => { - const fileSource = `${__dirname}${constants.artifactsDir}/package.json`; - try { - copyFileOrDir(fileSource, './package.json'); - } catch (error) { - if (error.message.includes('already exists')) { - await prompt(error, copyFileOrDir, fileSource, './package.json'); - } else { - throw Error(error); - } - } - - await installAeppSDK(sdkVersion); - await installAEproject(); -}; +const updateAEprojectProjectLibraries = async () => { + print('===== updating aeproject ====='); -const installAeppSDK = async (_sdkVersion = '') => { - print('===== Installing aepp-sdk ====='); - await execute(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', 'install', [`@aeternity/aepp-sdk@${_sdkVersion}`, '--save-exact']); -}; + await updateArtifacts(); + await installDependencies(); -const installAEproject = async (isUpdate) => { - print('===== Installing other dependencies ====='); - await execute(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', 'install', ['prompts']); - await execute(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', 'install', ['chai', '--save-dev']); - await execute(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', 'install', ['mocha', '--save-dev']); + print('===== aeproject sucessfully initalized ====='); }; -const setupContracts = async () => { - print('===== Creating contracts & utils directory ====='); - let fileSource = `${__dirname}${constants.artifactsDir}/${constants.contractTemplateFile}`; - createMissingFolder(constants.contractsDir); - let destination = constants.contractFileDestination; - try { - copyFileOrDir(fileSource, destination); - } catch (error) { - if (error.message.includes('already exists')) { - await prompt(error, copyFileOrDir, fileSource, destination); - } else { - throw Error(error); - } - } - createMissingFolder(`${constants.contractsDir}/lib`); - fileSource = `${__dirname}${constants.artifactsDir}/ExampleLibrary.aes`; - destination = `${constants.contractsDir}/lib/ExampleLibrary.aes`; - try { - copyFileOrDir(fileSource, destination); - } catch (error) { - if (error.message.includes('already exists')) { - await prompt(error, copyFileOrDir, fileSource, destination); - } else { - throw Error(error); - } - } - createMissingFolder('./utils'); - fileSource = `${__dirname}/../utils/utils/contract-utils.js`; - destination = './utils/contract-utils.js'; - try { - copyFileOrDir(fileSource, destination); - } catch (error) { - if (error.message.includes('already exists')) { - await prompt(error, copyFileOrDir, fileSource, destination); - } else { - throw Error(error); - } +const installDependencies = async (_sdkVersion = '') => { + if (fileExists('./package.json')) { + print('===== installing dependencies ====='); + await exec(/^win/.test(process.platform) ? 'npm.cmd install' : 'npm install'); } }; -const setupConfig = async () => { - print('===== Creating config directory ====='); - createMissingFolder('./config'); - let fileSource = `${__dirname}/artifacts/network.json`; - let destination = './config/network.json'; - try { - copyFileOrDir(fileSource, destination); - } catch (error) { - if (error.message.includes('already exists')) { - await prompt(error, copyFileOrDir, fileSource, destination); - } else { - throw Error(error); - } - } - fileSource = `${__dirname}/artifacts/wallets.json`; - destination = './config/wallets.json'; - try { - copyFileOrDir(fileSource, destination); - } catch (error) { - if (error.message.includes('already exists')) { - await prompt(error, copyFileOrDir, fileSource, destination); - } else { - throw Error(error); - } - } -}; - -const setupTests = async () => { - print('===== Creating tests directory ====='); - const fileSource = `${__dirname}${constants.artifactsDir}/${constants.testTemplateFile}`; - createMissingFolder(constants.testDir, 'Creating tests file structure'); - - try { - copyFileOrDir(fileSource, constants.testFileDestination); - } catch (error) { - if (error.message.includes('already exists')) { - await prompt(error, copyFileOrDir, fileSource, constants.testFileDestination); - } else { - throw Error(error); - } - } -}; - -const setupDeploy = async () => { - print('===== Creating deploy directory ====='); - const fileSource = `${__dirname}${constants.artifactsDir}/${constants.deployTemplateFile}`; - createMissingFolder(constants.deployDir, 'Creating deploy directory file structure'); - - try { - copyFileOrDir(fileSource, constants.deployFileDestination); - } catch (error) { - if (error.message.includes('already exists')) { - await prompt(error, copyFileOrDir, fileSource, constants.deployFileDestination); - } else { - throw Error(error); - } - } -}; - -const setDockerImageVersion = (pathToDockerYmlFile, dockerImage) => { - const doc = yaml.safeLoad(fs.readFileSync(pathToDockerYmlFile, 'utf8')); - - const tokens = dockerImage.split(':'); - const imageLiteral = tokens[0]; - - for (const i in doc.services) { - const { image } = doc.services[i]; - - if (image.startsWith(imageLiteral)) { - doc.services[i].image = dockerImage; - } - } - - const yamlStr = yaml.safeDump(doc); - fs.writeFileSync(pathToDockerYmlFile, yamlStr, 'utf8'); -}; - -const setupDocker = async (isUpdate) => { - print('===== Creating docker directory ====='); - - const dockerFilesSource = `${__dirname}${constants.artifactsDir}/${constants.dockerTemplateDir}`; - const dockerNodeYmlFileSource = `${__dirname}${constants.artifactsDir}/${constants.dockerNodeYmlFile}`; - const dockerCompilerYmlFileSource = `${__dirname}${constants.artifactsDir}/${constants.dockerCompilerYmlFile}`; - - const nodeTokens = constants.aeNodeImage.split(':'); - const compilerTokens = constants.aeCompilerImage.split(':'); - - const nodeVersion = []; - const compilerVersion = []; - - if (isUpdate) { - const aeternityNodeImageLiteral = nodeTokens[0]; - const aeternityCompilerImageLiteral = compilerTokens[0]; +const setupArtifacts = async () => { + print('===== creating project file and directory structure ====='); - try { - // read user's node yml - const userNodeYmlPath = path.join(process.cwd(), constants.dockerNodeYmlFile); - const doc = yaml.safeLoad(fs.readFileSync(userNodeYmlPath, 'utf8')); - - for (const i in doc.services) { - const { image } = doc.services[i]; - - if (image.startsWith(aeternityNodeImageLiteral)) { - const imageTokens = image.split(':'); - const currentVersion = imageTokens[1]; - - nodeVersion.push(currentVersion); - } - } - } catch (e) { - console.log(e); - } - - try { - // read user's compiler yml - const userCompilerYmlPath = path.join(process.cwd(), constants.dockerCompilerYmlFile); - const doc = yaml.safeLoad(fs.readFileSync(userCompilerYmlPath, 'utf8')); - - for (const i in doc.services) { - const { image } = doc.services[i]; - - if (image.startsWith(aeternityCompilerImageLiteral)) { - const imageTokens = image.split(':'); - const currentVersion = imageTokens[1]; - - compilerVersion.push(currentVersion); - } - } - } catch (e) { - console.log(e); - } - } else { - nodeVersion.push(nodeTokens[1]); - compilerVersion.push(compilerTokens[1]); - } - - // set latest version - const aeternityNodeImageLiteral = nodeTokens[0]; - const aeternityCompilerImageLiteral = compilerTokens[0]; - - const defaultNodeVersion = nodeTokens[1]; - const defaultCompilerVersion = compilerTokens[1]; - - const promptNodeMessage = `Default node version is ${defaultNodeVersion}, found ${nodeVersion[0]}. Do you want to keep current .yml file with node version: ${nodeVersion[0]} instead of default one with ${defaultNodeVersion}?`; - const nodeResult = await compareVersion(nodeVersion[0], defaultNodeVersion, promptNodeMessage); - - const promptCompilerMessage = `Default compiler version is ${defaultCompilerVersion}, found ${compilerVersion[0]}. Do you want to keep current .yml file with compiler version: ${compilerVersion[0]} instead of default one with ${defaultCompilerVersion}?`; - const compilerResult = await compareVersion(compilerVersion[0], defaultCompilerVersion, promptCompilerMessage); - - if (nodeResult.version !== defaultNodeVersion) { - setDockerImageVersion(dockerNodeYmlFileSource, `${aeternityNodeImageLiteral}:${nodeResult.version}`); - } - - if (compilerResult.version !== defaultCompilerVersion) { - setDockerImageVersion(dockerCompilerYmlFileSource, `${aeternityCompilerImageLiteral}:${compilerResult.version}`); - } - - // PS: update user's files only if it choose default version - // docker-compose.yml - node config - if (nodeResult.version === defaultNodeVersion) { - try { - copyFileOrDir(dockerNodeYmlFileSource, constants.dockerNodeYmlFileDestination, { overwrite: nodeResult.isUserVersionGreater }); - } catch (error) { - if (error.message.includes('already exists')) { - await prompt(error, copyFileOrDir, dockerNodeYmlFileSource, constants.dockerNodeYmlFileDestination); - } else { - throw Error(error); - } - } - } - - if (compilerResult.version === defaultCompilerVersion) { - try { - copyFileOrDir(dockerCompilerYmlFileSource, constants.dockerCompilerYmlFileDestination, { overwrite: compilerResult.isUserVersionGreater }); - } catch (error) { - if (error.message.includes('already exists')) { - await prompt(error, copyFileOrDir, dockerCompilerYmlFileSource, constants.dockerCompilerYmlFileDestination); - } else { - throw Error(error); - } - } - } - - // ./docker files - try { - copyFileOrDir(dockerFilesSource, constants.dockerFilesDestination); - } catch (error) { - if (error.message.includes('already exists')) { - await prompt(error, copyFileOrDir, dockerFilesSource, constants.dockerFilesDestination); - } else { - throw Error(error); - } - } - - // set default image version if there are changes - if (nodeResult.version !== defaultNodeVersion) { - setDockerImageVersion(dockerNodeYmlFileSource, `${aeternityNodeImageLiteral}:\${${config.nodeConfiguration.envLiteral}}`); - } - - if (compilerResult.version !== defaultCompilerVersion) { - setDockerImageVersion(dockerCompilerYmlFileSource, `${aeternityCompilerImageLiteral}:\${${config.compilerConfiguration.envLiteral}}`); - } + await copyFolderRecursiveSync(`${__dirname}${constants.updateArtifactsDir}`, constants.artifactsDest); + await copyFolderRecursiveSync(`${__dirname}${constants.artifactsDir}`, constants.artifactsDest); }; -const addIgnoreFile = () => { - print('==== Adding additional files ===='); - const ignoreFileContent = readFileRelative(`${__dirname}${constants.artifactsDir}/${constants.gitIgnoreContent}`); - writeFileRelative(constants.gitIgnoreFile, ignoreFileContent); -}; - -async function prompt(error) { - const args = [...arguments]; - // [0] - error - // [1] - function to execute - // [..] rest = function arguments - - const funcToExecute = args[1]; - - // // Prompt user to input data in console. - const response = await prompts({ - type: 'text', - name: 'value', - message: `${error.message}\nDo you want to overwrite '${error.message.replace(' already exists.', '')}'? (YES/no):`, - // validate: value => value < 18 ? `some validation text` : true - }); - - const input = response.value; - if (input === 'YES' || input === 'yes' || input === 'Y' || input === 'y') { - funcToExecute(...args.slice(2), { - overwrite: true, - }); - - return true; - } - - console.log(`'${error.message.replace(' already exists.', '')}' will not be overwritten.`); - return false; -} +const updateArtifacts = async () => { + print('===== creating project file and directory structure ====='); -async function promptUpdate(message) { - // // Prompt user to input data in console. - const response = await prompts({ - type: 'text', - name: 'value', - message: `${message} (Y/n):`, - // validate: value => value < 18 ? `some validation text` : true - }); - - const input = response.value; - if (input === 'YES' || input === 'yes' || input === 'Y' || input === 'y') { - return true; - } - - return false; -} - -const compareVersion = async (currentVersion, defaultVersion, promptMessage) => { - const result = { - version: defaultVersion, - isUserVersionGreater: false, - }; - - if (!currentVersion) { - return result; - } - - const currentVersionTokens = currentVersion.replace('v', '').split('.'); - const defaultVersionTokens = defaultVersion.replace('v', '').split('.'); - - for (let i = 0; i < 3; i++) { - const user = currentVersionTokens[i]; - const updateTo = defaultVersionTokens[i]; - - if (!isNaN(updateTo) && !isNaN(user)) { - if (parseInt(user) > parseInt(updateTo)) { - result.isUserVersionGreater = true; - if (await promptUpdate(promptMessage)) { - // defaultVersion = currentVersion; - result.version = currentVersion; - break; - } - } - } else if (!isNaN(updateTo) && isNaN(user)) { - result.isUserVersionGreater = true; - if (await promptUpdate(promptMessage)) { - // defaultVersion = currentVersion; - result.version = currentVersion; - break; - } - } - } + let fileSource = `${__dirname}${constants.updateArtifactsDir}`; + let destination = constants.artifactsDest; - return result; + await copyFolderRecursiveSync(fileSource, destination); }; module.exports = { - run, - createAEprojectProjectStructure, + run }; diff --git a/src/init/update-artifacts/.gitignore b/src/init/update-artifacts/.gitignore new file mode 100644 index 00000000..e4cc2ffd --- /dev/null +++ b/src/init/update-artifacts/.gitignore @@ -0,0 +1,4 @@ +node_modules +.vscode +.idea/ +.DS_Store diff --git a/src/init/artifacts/docker-compose.yml b/src/init/update-artifacts/docker-compose.yml similarity index 55% rename from src/init/artifacts/docker-compose.yml rename to src/init/update-artifacts/docker-compose.yml index b4931d25..a92b1936 100644 --- a/src/init/artifacts/docker-compose.yml +++ b/src/init/update-artifacts/docker-compose.yml @@ -4,22 +4,25 @@ services: node: image: aeternity/aeternity:${NODE_TAG}-bundle hostname: node + container_name: aeproject_node environment: AETERNITY_CONFIG: /home/aeternity/aeternity.yaml volumes: - - './aeternity.yaml:/home/aeternity/aeternity.yaml' - - './accounts_test.json:/home/aeternity/node/data/aecore/.genesis/accounts_test.json' + - './docker/aeternity.yaml:/home/aeternity/aeternity.yaml' + - './docker/accounts.json:/home/aeternity/node/data/aecore/.genesis/accounts_test.json' compiler: image: aeternity/aesophia_http:${COMPILER_TAG} hostname: compiler + container_name: aeproject_compiler ports: - '3080:3080' proxy: image: nginx:latest hostname: proxy + container_name: aeproject_proxy ports: - '3001:3001' volumes: - - './nginx.conf:/etc/nginx/conf.d/default.conf' + - './docker/nginx.conf:/etc/nginx/conf.d/default.conf' diff --git a/src/init/artifacts/docker/accounts_test.json b/src/init/update-artifacts/docker/accounts.json similarity index 90% rename from src/init/artifacts/docker/accounts_test.json rename to src/init/update-artifacts/docker/accounts.json index 4020648e..6ce4cc51 100644 --- a/src/init/artifacts/docker/accounts_test.json +++ b/src/init/update-artifacts/docker/accounts.json @@ -8,5 +8,6 @@ "ak_f9bmi44rdvUGKDsTLp3vMCMLMvvqsMQVWyc3XDAYECmCXEbzy": 100000000000000000000000000000000, "ak_23p6pT7bajYMJRbnJ5BsbFUuYGX2PBoZAiiYcsrRHZ1BUY2zSF": 100000000000000000000000000000000, "ak_gLYH5tAexTCvvQA6NpXksrkPJKCkLnB9MTDFTVCBuHNDJ3uZv": 100000000000000000000000000000000, - "ak_zPoY7cSHy2wBKFsdWJGXM7LnSjVt6cn1TWBDdRBUMC7Tur2NQ": 100000000000000000000000000000000 -} \ No newline at end of file + "ak_zPoY7cSHy2wBKFsdWJGXM7LnSjVt6cn1TWBDdRBUMC7Tur2NQ": 100000000000000000000000000000000, + "ak_RdoCvwe7kxPu2VBv2gQAc1V81sGyTTuxFv36AcvNQYZN7qgut": 0 +} diff --git a/src/init/artifacts/docker/aeternity.yaml b/src/init/update-artifacts/docker/aeternity.yaml similarity index 90% rename from src/init/artifacts/docker/aeternity.yaml rename to src/init/update-artifacts/docker/aeternity.yaml index c1525d44..75a312b1 100644 --- a/src/init/artifacts/docker/aeternity.yaml +++ b/src/init/update-artifacts/docker/aeternity.yaml @@ -26,7 +26,7 @@ chain: name: "on_demand" mining: - beneficiary: "ak_GLab8McCgXqng1pZbQDmjbCLw6f48qGyP4zWqzqBVnYwdNWVc" + beneficiary: "ak_RdoCvwe7kxPu2VBv2gQAc1V81sGyTTuxFv36AcvNQYZN7qgut" beneficiary_reward_delay: 2 strictly_follow_top: true diff --git a/src/init/artifacts/docker/nginx.conf b/src/init/update-artifacts/docker/nginx.conf similarity index 100% rename from src/init/artifacts/docker/nginx.conf rename to src/init/update-artifacts/docker/nginx.conf diff --git a/src/init/update-artifacts/package.json b/src/init/update-artifacts/package.json new file mode 100644 index 00000000..8b81fd51 --- /dev/null +++ b/src/init/update-artifacts/package.json @@ -0,0 +1,16 @@ +{ + "name": "aeproject-project", + "version": "1.0.0", + "description": "This is the default package.json generated for your project", + "scripts": { + "test": "mocha ./test/**/*.js --timeout 0 --exit" + }, + "dependencies": { + "@aeternity/aepp-sdk": "^9.0.1" + }, + "devDependencies": { + "@aeternity/aeproject": "^3.0.5", + "chai": "^4.3.4", + "mocha": "^9.1.3" + } +} diff --git a/src/lib/index.js b/src/lib/index.js new file mode 100644 index 00000000..c62468b7 --- /dev/null +++ b/src/lib/index.js @@ -0,0 +1,9 @@ +const networks = require('./networks.json'); +const wallets = require('./wallets.json'); +const utils = require('./utils'); + +module.exports = { + utils: utils, + networks: networks, + wallets: wallets +} diff --git a/src/lib/networks.json b/src/lib/networks.json new file mode 100644 index 00000000..f39b155d --- /dev/null +++ b/src/lib/networks.json @@ -0,0 +1,14 @@ +{ + "testnet": { + "nodeUrl": "https://testnet.aeternity.io", + "compilerUrl": "https://latest.compiler.aepps.com" + }, + "mainnet": { + "nodeUrl": "https://mainnet.aeternity.io", + "compilerUrl": "https://latest.compiler.aepps.com" + }, + "devmode": { + "nodeUrl": "http://localhost:3001", + "compilerUrl": "http://localhost:3080" + } +} diff --git a/src/utils/contract-utils.js b/src/lib/utils.js similarity index 100% rename from src/utils/contract-utils.js rename to src/lib/utils.js diff --git a/src/lib/wallets.json b/src/lib/wallets.json new file mode 100644 index 00000000..085442a4 --- /dev/null +++ b/src/lib/wallets.json @@ -0,0 +1,46 @@ +[ + { + "publicKey": "ak_fUq2NesPXcYZ1CcqBcGC3StpdnQw3iVxMA3YSeCNAwfN4myQk", + "secretKey": "7c6e602a94f30e4ea7edabe4376314f69ba7eaa2f355ecedb339df847b6f0d80575f81ffb0a297b7725dc671da0b1769b1fc5cbe45385c7b5ad1fc2eaf1d609d" + }, + { + "publicKey": "ak_tWZrf8ehmY7CyB1JAoBmWJEeThwWnDpU4NadUdzxVSbzDgKjP", + "secretKey": "7fa7934d142c8c1c944e1585ec700f671cbc71fb035dc9e54ee4fb880edfe8d974f58feba752ae0426ecbee3a31414d8e6b3335d64ec416f3e574e106c7e5412" + }, + { + "publicKey": "ak_FHZrEbRmanKUe9ECPXVNTLLpRP2SeQCLCT6Vnvs9JuVu78J7V", + "secretKey": "1509d7d0e113528528b7ce4bf72c3a027bcc98656e46ceafcfa63e56597ec0d8206ff07f99ea517b7a028da8884fb399a2e3f85792fe418966991ba09b192c91" + }, + { + "publicKey": "ak_RYkcTuYcyxQ6fWZsL2G3Kj3K5WCRUEXsi76bPUNkEsoHc52Wp", + "secretKey": "58bd39ded1e3907f0b9c1fbaa4456493519995d524d168e0b04e86400f4aa13937bcec56026494dcf9b19061559255d78deea3281ac649ca307ead34346fa621" + }, + { + "publicKey": "ak_2VvB4fFu7BQHaSuW5EkQ7GCaM5qiA5BsFUHjJ7dYpAaBoeFCZi", + "secretKey": "50458d629ae7109a98e098c51c29ec39c9aea9444526692b1924660b5e2309c7c55aeddd5ebddbd4c6970e91f56e8aaa04eb52a1224c6c783196802e136b9459" + }, + { + "publicKey": "ak_286tvbfP6xe4GY9sEbuN2ftx1LpavQwFVcPor9H4GxBtq5fXws", + "secretKey": "707881878eacacce4db463de9c7bf858b95c3144d52fafed4a41ffd666597d0393d23cf31fcd12324cd45d4784d08953e8df8283d129f357463e6795b40e88aa" + }, + { + "publicKey": "ak_f9bmi44rdvUGKDsTLp3vMCMLMvvqsMQVWyc3XDAYECmCXEbzy", + "secretKey": "9262701814da8149615d025377e2a08b5f10a6d33d1acaf2f5e703e87fe19c83569ecc7803d297fde01758f1bdc9e0c2eb666865284dff8fa39edb2267de70db" + }, + { + "publicKey": "ak_23p6pT7bajYMJRbnJ5BsbFUuYGX2PBoZAiiYcsrRHZ1BUY2zSF", + "secretKey": "e15908673cda8a171ea31333538437460d9ca1d8ba2e61c31a9a3d01a8158c398a14cd12266e480f85cc1dc3239ed5cfa99f3d6955082446bebfe961449dc48b" + }, + { + "publicKey": "ak_gLYH5tAexTCvvQA6NpXksrkPJKCkLnB9MTDFTVCBuHNDJ3uZv", + "secretKey": "6eb127925aa10d6d468630a0ca28ff5e1b8ad00db151fdcc4878362514d6ae865951b78cf5ef047cab42218e0d5a4020ad34821ca043c0f1febd27aaa87d5ed7" + }, + { + "publicKey": "ak_zPoY7cSHy2wBKFsdWJGXM7LnSjVt6cn1TWBDdRBUMC7Tur2NQ", + "secretKey": "36595b50bf097cd19423c40ee66b117ed15fc5ec03d8676796bdf32bc8fe367d82517293a0f82362eb4f93d0de77af5724fba64cbcf55542328bc173dbe13d33" + }, + { + "publicKey": "ak_RdoCvwe7kxPu2VBv2gQAc1V81sGyTTuxFv36AcvNQYZN7qgut", + "secretKey": "bd2538555eaa4cb4a2a5714253149fce9ef182c9229ffcf31d00743b681c0b5d37ef7b538875c1567a3c1f5bf641e8dfb728620e04532685e425e997c11d0a54" + } +] diff --git a/src/test/aeproject-test.js b/src/test/aeproject-test.js deleted file mode 100644 index 75b0612f..00000000 --- a/src/test/aeproject-test.js +++ /dev/null @@ -1,55 +0,0 @@ -const { print } = require('../utils'); -const contractUtils = require('../utils'); -const nodeConfig = require('../config'); - -// TODO remove mocha and chai - -async function run(files) { - print('===== Starting Tests ====='); - const mochaConfig = { - useColors: true, - timeout: 550000, - exit: true, - }; - const mocha = await createMocha(mochaConfig, files); - setGlobalOptions(); - - for (let i = 0; i < files.length; i++) { - delete originalRequire.cache[files[i]]; - mocha.addFile(files[i]); - } - - await runMocha(mocha); -} - -const createMocha = async (config, files) => { - const mocha = new Mocha(config); - - files.forEach((file) => { - mocha.addFile(file); - }); - - return mocha; -}; - -const runMocha = (mocha) => new Promise((resolve, reject) => { - mocha.run((failures) => { - process.exitCode = failures ? 1 : 0; - if (failures) { - reject(failures); - } else { - resolve(); - } - }); -}); - -async function setGlobalOptions() { - global.assert = chai.assert; - global.utils = contractUtils; - global.minerWallet = nodeConfig.config.keyPair; - global.wallets = nodeConfig.defaultWallets; -} - -module.exports = { - run, -}; diff --git a/src/test/test.js b/src/test/test.js index ae67ffac..4e9cfcc7 100644 --- a/src/test/test.js +++ b/src/test/test.js @@ -1,12 +1,14 @@ const p = require('path'); -const aeprojectTest = require('./aeproject-test'); -const utils = require('../utils'); +const {print} = require("../utils/utils"); +const {getFiles} = require("../utils/fs-utils"); +const contractUtils = require("../lib/utils"); +const nodeConfig = require("../config/node-config.json"); const run = async (path) => { const workingDirectory = process.cwd(); if (path.includes('.js')) { - await aeprojectTest.run([path]); + await test([path]); return; } @@ -22,16 +24,63 @@ const run = async (path) => { testDirectory = workingDirectory; } - const files = await utils.getFiles(`${testDirectory}/test`, '.*\\.(js|es|es6|jsx|sol)$'); + const files = await getFiles(`${testDirectory}/test`, '.*\\.(js|es|es6|jsx|sol)$'); const cwd = process.cwd(); process.chdir(testDirectory); - await aeprojectTest.run(files); + await test(files); process.chdir(cwd); }; +async function test(files) { + print('===== Starting Tests ====='); + const mochaConfig = { + useColors: true, + timeout: 550000, + exit: true, + }; + const mocha = await createMocha(mochaConfig, files); + setGlobalOptions(); + + for (let i = 0; i < files.length; i++) { + delete originalRequire.cache[files[i]]; + mocha.addFile(files[i]); + } + + await runMocha(mocha); +} + +const createMocha = async (config, files) => { + const mocha = new Mocha(config); + + files.forEach((file) => { + mocha.addFile(file); + }); + + return mocha; +}; + +const runMocha = (mocha) => new Promise((resolve, reject) => { + mocha.run((failures) => { + process.exitCode = failures ? 1 : 0; + if (failures) { + reject(failures); + } else { + resolve(); + } + }); +}); + +async function setGlobalOptions() { + global.assert = chai.assert; + global.utils = contractUtils; + global.minerWallet = nodeConfig.config.keyPair; + global.wallets = nodeConfig.defaultWallets; +} + + module.exports = { run, }; diff --git a/src/tx-inspector/tx-inspector.js b/src/tx-inspector/tx-inspector.js index 8e24c946..f0b3d9bc 100644 --- a/src/tx-inspector/tx-inspector.js +++ b/src/tx-inspector/tx-inspector.js @@ -1,5 +1,5 @@ const { TransactionValidator, Node } = require('@aeternity/aepp-sdk'); -const utils = require('../utils'); +const utils = require('../utils/utils'); const { httpGet } = utils; diff --git a/src/utils/fs-utils.js b/src/utils/fs-utils.js index 242c1e68..ac9d8aa6 100644 --- a/src/utils/fs-utils.js +++ b/src/utils/fs-utils.js @@ -1,34 +1,51 @@ const fs = require('fs'); const path = require('path'); +const prompts = require('prompts'); -// TODO replace dir, fs methods +async function promptOverwrite(target) { + const response = await prompts({ + type: 'text', + name: 'value', + message: `Do you want to overwrite '${target}'? (y/N):`, + }); -// Print helper -const print = (msg, obj) => { - if (obj) { - console.log(msg, obj); - } else { - console.log(msg); - } -}; + const input = response.value.trim(); + return input === 'YES' || input === 'yes' || input === 'Y' || input === 'y' +} -// Print error helper -const printError = (msg) => { - console.log(msg); -}; +async function copyFolderRecursiveSync(srcDir, dstDir) { + let src, dst; -const createMissingFolder = (dir) => { - if (!fs.existsSync(dir)) { - fs.mkdirSync(dir); - } -}; + return fs.readdirSync(srcDir).reduce(async (accPromise, file) => { + await accPromise; + src = path.join(srcDir, file); + dst = path.join(dstDir, file); + + const stat = fs.statSync(src); + if (stat && stat.isDirectory()) { + if (!fs.existsSync(dst)) { + fs.mkdirSync(dst); + } + + await copyFolderRecursiveSync(src, dst) + } else { + if (!fs.existsSync(dst)) { + fs.writeFileSync(dst, fs.readFileSync(src)); + } else { + if (await promptOverwrite(dst)) { + fs.writeFileSync(dst, fs.readFileSync(src)); + } + } + } + }, Promise.resolve()); +} const copyFileOrDir = (sourceFileOrDir, destinationFileOrDir, copyOptions = {}) => { if (fs.existsSync(`${destinationFileOrDir}`) && !copyOptions.overwrite) { throw new Error(`${destinationFileOrDir} already exists.`); } - fs.copySync(sourceFileOrDir, destinationFileOrDir, copyOptions); + copySync(sourceFileOrDir, destinationFileOrDir, copyOptions); }; const getFiles = async function (directory, regex) { @@ -88,9 +105,6 @@ async function createDirIfNotExists(destination) { } module.exports = { - print, - printError, - createMissingFolder, copyFileOrDir, getFiles, readFile, @@ -100,4 +114,5 @@ module.exports = { fileExists, deleteCreatedFiles, createDirIfNotExists, + copyFolderRecursiveSync, }; diff --git a/src/utils/index.js b/src/utils/index.js deleted file mode 100644 index 763144d4..00000000 --- a/src/utils/index.js +++ /dev/null @@ -1,80 +0,0 @@ -const fsUtils = require('./fs-utils'); - -const { print } = fsUtils; -const { printError } = fsUtils; -const { createMissingFolder } = fsUtils; -const { copyFileOrDir } = fsUtils; -const { getFiles } = fsUtils; -const { readFileRelative } = fsUtils; -const { writeFileRelative } = fsUtils; -const { fileExists } = fsUtils; -const { readFile } = fsUtils; -const { deleteCreatedFiles } = fsUtils; -const { createDirIfNotExists } = fsUtils; -const writeFileSync = fsUtils.writeFile; - -const aeprojectUtils = require('./aeproject-utils'); - -const { getClient } = aeprojectUtils; -const { getNetwork } = aeprojectUtils; -const { getCompiler } = aeprojectUtils; -const { sleep } = aeprojectUtils; -const { execute } = aeprojectUtils; -const { aeprojectExecute } = aeprojectUtils; -const { config } = aeprojectUtils; -const { handleApiError } = aeprojectUtils; -const { logApiError } = aeprojectUtils; -const { timeout } = aeprojectUtils; -const { contractCompile } = aeprojectUtils; -const { checkNestedProperty } = aeprojectUtils; -const { winExec } = aeprojectUtils; -const { readSpawnOutput } = aeprojectUtils; -const { readErrorSpawnOutput } = aeprojectUtils; -const { capitalize } = aeprojectUtils; -const { addCaretToDependencyVersion } = aeprojectUtils; -const { prompt } = aeprojectUtils; - -const contract_utils = require('./contract-utils'); - -const { getFilesystem } = contract_utils; -const { getContractContent } = contract_utils; - -const SophiaUtil = require('./sophia-util'); -const { httpGet } = require('./http-utils'); - -module.exports = { - print, - printError, - createMissingFolder, - copyFileOrDir, - getFiles, - getClient, - getNetwork, - getCompiler, - sleep, - execute, - readFile, - deleteCreatedFiles, - config, - handleApiError, - logApiError, - timeout, - aeprojectExecute, - readFileRelative, - writeFileRelative, - fileExists, - SophiaUtil, - contractCompile, - checkNestedProperty, - createDirIfNotExists, - writeFileSync, - winExec, - httpGet, - readSpawnOutput, - readErrorSpawnOutput, - capitalize, - addCaretToDependencyVersion, - prompt, - getFilesystem, - getContractContent, -}; diff --git a/src/utils/aeproject-utils.js b/src/utils/utils.js similarity index 97% rename from src/utils/aeproject-utils.js rename to src/utils/utils.js index 0fc66080..003889f5 100644 --- a/src/utils/aeproject-utils.js +++ b/src/utils/utils.js @@ -13,6 +13,7 @@ const dependencyPathRgx = /"([\d\w\/\.\-\_]+)\"/gmi; const mainContractsPathRgx = /.*\//g; const COMPILER_URL_POSTFIX = '/compile'; +const defaultSpawnOptions = {encoding: 'utf8'}; const getClient = async function (network, keypair = config.keypair) { let client; @@ -128,7 +129,7 @@ const aeprojectExecute = async (command, args = [], options = {}) => execute('ae const execute = async (cli, command, args = [], options = {}) => { try { - const child = await spawn(cli, [command, ...args], options); + const child = await spawn(cli, [command, ...args], {...defaultSpawnOptions, ...options}); let result = child.stdout.toString('utf8'); result += child.stderr.toString('utf8'); @@ -320,6 +321,8 @@ async function prompt(promptMessage, functionToExecute) { } module.exports = { + print: console.log, + printError: console.error, config, getClient, getNetwork,