From a06077f69e50b1125e4989791bdbafb190696697 Mon Sep 17 00:00:00 2001 From: JhChoy Date: Tue, 19 Feb 2019 16:37:37 +0900 Subject: [PATCH 1/7] refactor: pull out global constant to root/config/Constant.js --- packages/vvisp/bin/error.js | 6 +++--- packages/vvisp/config/Constant.js | 20 +++++++++++++++++++ .../vvisp/scripts/deploy-service/constants.js | 2 -- .../vvisp/scripts/deploy-service/index.js | 5 +++-- .../deploy-service/preProcess/index.js | 4 +++- .../deploy-service/utils/writeState.js | 2 +- packages/vvisp/scripts/flatten.js | 4 +++- packages/vvisp/test/bin/error.test.js | 11 +++++----- .../test/scripts/deploy-service/index.test.js | 7 ++----- 9 files changed, 41 insertions(+), 20 deletions(-) create mode 100644 packages/vvisp/config/Constant.js diff --git a/packages/vvisp/bin/error.js b/packages/vvisp/bin/error.js index 5e113a9..9681f6b 100644 --- a/packages/vvisp/bin/error.js +++ b/packages/vvisp/bin/error.js @@ -2,6 +2,8 @@ const fs = require('fs'); const path = require('path'); const _ = require('lodash'); +const { SERVICE_PATH, SERVICE_FILE } = require('../config/Constant'); + const NETWORKS = { local: 'local', mainnet: 'mainnet', @@ -11,12 +13,11 @@ const NETWORKS = { custom: 'custom' }; -const SERVICE_PATH = path.join('./', 'service.vvisp.json'); const ENV_PATH = path.join('./', '.env'); function checkConfigExist() { if (!fs.existsSync(SERVICE_PATH)) { - throw new Error('service.vvisp.json file does not exist'); + throw new Error(`${SERVICE_FILE} file does not exist`); } } @@ -66,7 +67,6 @@ module.exports = { checkEnv, constants: { NETWORKS, - SERVICE_PATH, ENV_PATH } }; diff --git a/packages/vvisp/config/Constant.js b/packages/vvisp/config/Constant.js new file mode 100644 index 0000000..9c8fc53 --- /dev/null +++ b/packages/vvisp/config/Constant.js @@ -0,0 +1,20 @@ +const path = require('path'); + +const PROJECT_NAME = 'vvisp'; +const SERVICE_FILE = `service.${PROJECT_NAME}.json`; +const STATE_FILE = `state.${PROJECT_NAME}.json`; + +module.exports = { + TEST: { + MNEMONIC: + 'piano garage flag neglect spare title drill basic strong aware enforce fury', + URL: 'http://localhost:8545' + }, + PROJECT_NAME: PROJECT_NAME, + SERVICE_FILE: SERVICE_FILE, + SERVICE_PATH: path.join('./', SERVICE_FILE), + STATE_FILE: STATE_FILE, + STATE_PATH: path.join('./', STATE_FILE), + DEFAULT_CONFIG_FILE: `${PROJECT_NAME}-config.js`, + DEFAULT_NETWORK: `development` +}; diff --git a/packages/vvisp/scripts/deploy-service/constants.js b/packages/vvisp/scripts/deploy-service/constants.js index ea31075..79aa98a 100644 --- a/packages/vvisp/scripts/deploy-service/constants.js +++ b/packages/vvisp/scripts/deploy-service/constants.js @@ -4,8 +4,6 @@ module.exports = (function() { const web3 = getWeb3(); return { - SERVICE_PATH: path.join('./', 'service.vvisp.json'), - STATE_PATH: path.join('./', 'state.vvisp.json'), REGISTRY_PATH: path.join('./', 'contracts/upgradeable/VvispRegistry.sol'), TX_OPTIONS: { gasPrice: process.env.GAS_PRICE diff --git a/packages/vvisp/scripts/deploy-service/index.js b/packages/vvisp/scripts/deploy-service/index.js index 7938929..dea2955 100644 --- a/packages/vvisp/scripts/deploy-service/index.js +++ b/packages/vvisp/scripts/deploy-service/index.js @@ -7,6 +7,7 @@ module.exports = async function(options) { const { writeState } = require('./utils'); const DeployState = require('./DeployState'); const preProcess = require('./preProcess'); + const { PROJECT_NAME, SERVICE_FILE } = require('../../config/Constant'); const { deployBusinesses, deployNonUpgradeables, @@ -116,7 +117,7 @@ module.exports = async function(options) { options ); printOrSilent( - `You can see result in ${chalk.keyWord('state.haechi.json')}`, + `You can see result in ${chalk.keyWord(SERVICE_FILE)}`, options ); } else { @@ -138,7 +139,7 @@ module.exports = async function(options) { printOrSilent(chalk.error(`Service State Paused!`), options); printOrSilent( `Resume Process by Running ${chalk.keyWord( - 'vvisp deploy-service' + `${PROJECT_NAME} deploy-service` )} Again.`, options ); diff --git a/packages/vvisp/scripts/deploy-service/preProcess/index.js b/packages/vvisp/scripts/deploy-service/preProcess/index.js index 5ccd84a..81104ee 100644 --- a/packages/vvisp/scripts/deploy-service/preProcess/index.js +++ b/packages/vvisp/scripts/deploy-service/preProcess/index.js @@ -1,9 +1,11 @@ module.exports = async function(deployState, options) { const fs = require('fs-extra'); - const { SERVICE_PATH, STATE_PATH, VARIABLES } = require('../constants'); + const { SERVICE_PATH, STATE_PATH } = require('../../../config/Constant'); + const { VARIABLES } = require('../constants'); const { forIn, printOrSilent } = require('@haechi-labs/vvisp-utils'); let stateClone = deployState.getState(); + const config = fs.readJsonSync(SERVICE_PATH); let processState; diff --git a/packages/vvisp/scripts/deploy-service/utils/writeState.js b/packages/vvisp/scripts/deploy-service/utils/writeState.js index 5862da1..cd5e60e 100644 --- a/packages/vvisp/scripts/deploy-service/utils/writeState.js +++ b/packages/vvisp/scripts/deploy-service/utils/writeState.js @@ -1,7 +1,7 @@ module.exports = function(state, options) { const fs = require('fs'); const { printOrSilent } = require('@haechi-labs/vvisp-utils'); - const { STATE_PATH } = require('../constants'); + const { STATE_PATH } = require('../../../config/Constant'); const stateString = JSON.stringify(state, null, ' '); // printOrSilent(chalk.head('Service State Result'), options); // Just for debugging diff --git a/packages/vvisp/scripts/flatten.js b/packages/vvisp/scripts/flatten.js index 032f9e5..0248390 100644 --- a/packages/vvisp/scripts/flatten.js +++ b/packages/vvisp/scripts/flatten.js @@ -11,8 +11,10 @@ module.exports = async function(files, options) { const path = require('path'); const fs = require('fs'); + const { SERVICE_FILE } = require('../config/Constant'); + try { - const configRootPath = await getConfigRoot('service.vvisp.json'); + const configRootPath = await getConfigRoot(SERVICE_FILE); const relativeFilePaths = await getRelativeFilePathsFromRoot( configRootPath, files diff --git a/packages/vvisp/test/bin/error.test.js b/packages/vvisp/test/bin/error.test.js index dfdc739..be4454a 100644 --- a/packages/vvisp/test/bin/error.test.js +++ b/packages/vvisp/test/bin/error.test.js @@ -8,8 +8,9 @@ const _ = require('lodash'); const dotenv = require('dotenv').config; const { checkConfigExist, checkEnv, constants } = require('../../bin/error'); +const { SERVICE_PATH, SERVICE_FILE } = require('../../config/Constant'); -const { NETWORKS, SERVICE_PATH, ENV_PATH } = constants; +const { NETWORKS, ENV_PATH } = constants; describe('# error test', function() { this.timeout(50000); @@ -46,13 +47,13 @@ describe('# error test', function() { fs.removeSync(path.join(SERVICE_PATH)); }); - it('should throw error when service.vvisp.json file does not exist', function() { + it(`should throw error when ${SERVICE_FILE} file does not exist`, function() { expect(() => checkConfigExist()).to.throw( - 'service.vvisp.json file does not exist' + `${SERVICE_FILE} file does not exist` ); }); - it('should not throw error when service.vvisp.json exists', function() { + it(`should not throw error when ${SERVICE_FILE} exists`, function() { fs.writeJsonSync(SERVICE_PATH, { serviceName: 'test' }); expect(() => checkConfigExist()).to.not.throw(); fs.removeSync(path.join(SERVICE_PATH)); @@ -70,7 +71,7 @@ describe('# error test', function() { fs.moveSync(tmpENV, ENV_PATH, { overwrite: true }); }); - it('should throw error when service.vvisp.json file does not exist', function() { + it(`should throw error when ${SERVICE_FILE} file does not exist`, function() { expect(() => checkEnv()).to.throw('.env file does not exist'); }); diff --git a/packages/vvisp/test/scripts/deploy-service/index.test.js b/packages/vvisp/test/scripts/deploy-service/index.test.js index 860f4a3..e1e897c 100644 --- a/packages/vvisp/test/scripts/deploy-service/index.test.js +++ b/packages/vvisp/test/scripts/deploy-service/index.test.js @@ -5,11 +5,8 @@ require('dotenv').config(); const deployService = require('../../../scripts/deploy-service/'); const compareConfigAndState = require('../../../scripts/deploy-service/preProcess/compareConfigAndState'); -const { - PENDING_STATE, - SERVICE_PATH, - STATE_PATH -} = require('../../../scripts/deploy-service/constants'); +const { PENDING_STATE } = require('../../../scripts/deploy-service/constants'); +const { SERVICE_PATH, STATE_PATH } = require('../../../config/Constant'); const { hasInitArgs } = require('../../../scripts/deploy-service/utils'); const { forIn, From 762e821bfcc71e0082190e566f1334f625340dec Mon Sep 17 00:00:00 2001 From: JhChoy Date: Tue, 19 Feb 2019 16:26:02 +0900 Subject: [PATCH 2/7] refactor: make exporting util modules in vvisp-utils/utils --- packages/vvisp-utils/src/compile.js | 2 +- packages/vvisp-utils/src/{utils => }/compilerSupplier.js | 0 packages/vvisp-utils/src/deploy.js | 2 +- packages/vvisp-utils/src/{utils => }/filterPrivateKey.js | 0 packages/vvisp-utils/src/index.js | 4 ++++ packages/vvisp-utils/src/privateKeyToAddress.js | 2 +- .../vvisp-utils/test/{utils => }/filterPrivateKey.test.js | 2 +- 7 files changed, 8 insertions(+), 4 deletions(-) rename packages/vvisp-utils/src/{utils => }/compilerSupplier.js (100%) rename packages/vvisp-utils/src/{utils => }/filterPrivateKey.js (100%) rename packages/vvisp-utils/test/{utils => }/filterPrivateKey.test.js (96%) diff --git a/packages/vvisp-utils/src/compile.js b/packages/vvisp-utils/src/compile.js index 0b78eb7..5e7336a 100644 --- a/packages/vvisp-utils/src/compile.js +++ b/packages/vvisp-utils/src/compile.js @@ -103,7 +103,7 @@ module.exports = async function(filePath, options) { } async function getSolc() { - const CompilerSupplier = require('./utils/compilerSupplier'); + const CompilerSupplier = require('./compilerSupplier'); const supplier = new CompilerSupplier({ version: process.env.SOLC_VERSION ? process.env.SOLC_VERSION diff --git a/packages/vvisp-utils/src/utils/compilerSupplier.js b/packages/vvisp-utils/src/compilerSupplier.js similarity index 100% rename from packages/vvisp-utils/src/utils/compilerSupplier.js rename to packages/vvisp-utils/src/compilerSupplier.js diff --git a/packages/vvisp-utils/src/deploy.js b/packages/vvisp-utils/src/deploy.js index 04577e9..e5d6029 100644 --- a/packages/vvisp-utils/src/deploy.js +++ b/packages/vvisp-utils/src/deploy.js @@ -4,7 +4,7 @@ module.exports = async function( arguments, options ) { - const filterPrivateKey = require('./utils/filterPrivateKey'); + const filterPrivateKey = require('./filterPrivateKey'); privateKey = filterPrivateKey(privateKey); if (arguments && arguments.length === undefined) { diff --git a/packages/vvisp-utils/src/utils/filterPrivateKey.js b/packages/vvisp-utils/src/filterPrivateKey.js similarity index 100% rename from packages/vvisp-utils/src/utils/filterPrivateKey.js rename to packages/vvisp-utils/src/filterPrivateKey.js diff --git a/packages/vvisp-utils/src/index.js b/packages/vvisp-utils/src/index.js index 481b121..4eca284 100644 --- a/packages/vvisp-utils/src/index.js +++ b/packages/vvisp-utils/src/index.js @@ -1,6 +1,8 @@ const compile = require('./compile'); const compileAndDeploy = require('./compileAndDeploy'); +const compilerSupplier = require('./compilerSupplier'); const deploy = require('./deploy'); +const filterPrivateKey = require('./filterPrivateKey'); const forIn = require('./forIn'); const forInAsync = require('./forInAsync'); const getAllFiles = require('./getAllFiles'); @@ -22,7 +24,9 @@ const parseLogs = require('./parseLogs'); module.exports = { compile, compileAndDeploy, + compilerSupplier, deploy, + filterPrivateKey, forIn, forInAsync, getAllFiles, diff --git a/packages/vvisp-utils/src/privateKeyToAddress.js b/packages/vvisp-utils/src/privateKeyToAddress.js index 8bedf8e..11a7142 100644 --- a/packages/vvisp-utils/src/privateKeyToAddress.js +++ b/packages/vvisp-utils/src/privateKeyToAddress.js @@ -1,5 +1,5 @@ module.exports = function(privateKey) { - const filterPrivateKey = require('./utils/filterPrivateKey'); + const filterPrivateKey = require('./filterPrivateKey'); privateKey = filterPrivateKey(privateKey); const web3 = require('./getWeb3')(); diff --git a/packages/vvisp-utils/test/utils/filterPrivateKey.test.js b/packages/vvisp-utils/test/filterPrivateKey.test.js similarity index 96% rename from packages/vvisp-utils/test/utils/filterPrivateKey.test.js rename to packages/vvisp-utils/test/filterPrivateKey.test.js index 481619b..8401f07 100644 --- a/packages/vvisp-utils/test/utils/filterPrivateKey.test.js +++ b/packages/vvisp-utils/test/filterPrivateKey.test.js @@ -2,7 +2,7 @@ const chai = require('chai'); const expect = chai.expect; chai.should(); -const filterPrivateKey = require('../../src/utils/filterPrivateKey'); +const { filterPrivateKey } = require('../src'); const SAMPLE_PRIVATE_KEY = '8bb0722ff8cb8161da257dc2d3712a17db1753d1de2d8b6b27b0e4636d9899f6'; From 4dbfed53daa51e947283d8ca42f49aa106f82ad6 Mon Sep 17 00:00:00 2001 From: JhChoy Date: Thu, 21 Feb 2019 21:08:22 +0900 Subject: [PATCH 3/7] fix: fix getConfigRoot function async to sync --- packages/vvisp-utils/src/getConfigRoot.js | 4 ++-- packages/vvisp/scripts/flatten.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/vvisp-utils/src/getConfigRoot.js b/packages/vvisp-utils/src/getConfigRoot.js index a971473..c1ab502 100644 --- a/packages/vvisp-utils/src/getConfigRoot.js +++ b/packages/vvisp-utils/src/getConfigRoot.js @@ -1,8 +1,8 @@ -module.exports = async function(configFileName) { +module.exports = function(configFileName) { const findUp = require('find-up'); const path = require('path'); - let configPath = await findUp([configFileName]); + let configPath = findUp.sync([configFileName]); if (!configPath) { throw new Error(`${configFileName} is not found`); } diff --git a/packages/vvisp/scripts/flatten.js b/packages/vvisp/scripts/flatten.js index 0248390..41bd3cd 100644 --- a/packages/vvisp/scripts/flatten.js +++ b/packages/vvisp/scripts/flatten.js @@ -14,7 +14,7 @@ module.exports = async function(files, options) { const { SERVICE_FILE } = require('../config/Constant'); try { - const configRootPath = await getConfigRoot(SERVICE_FILE); + const configRootPath = getConfigRoot(SERVICE_FILE); const relativeFilePaths = await getRelativeFilePathsFromRoot( configRootPath, files From 49c2ce06dc441612e07d486514dabba800d65522 Mon Sep 17 00:00:00 2001 From: JhChoy Date: Thu, 21 Feb 2019 21:16:02 +0900 Subject: [PATCH 4/7] fix: allow getPrivateKey receive not 12 mnemonic words --- packages/vvisp-utils/src/getPrivateKey.js | 16 ++++------------ packages/vvisp-utils/test/getPrivateKey.test.js | 10 ++-------- 2 files changed, 6 insertions(+), 20 deletions(-) diff --git a/packages/vvisp-utils/src/getPrivateKey.js b/packages/vvisp-utils/src/getPrivateKey.js index e94f7c3..da9f8e7 100644 --- a/packages/vvisp-utils/src/getPrivateKey.js +++ b/packages/vvisp-utils/src/getPrivateKey.js @@ -26,18 +26,10 @@ module.exports = function(mnemonic, index) { .toString('hex'); function checkInputs(mnemonic, index) { - switch (mnemonic) { - case undefined || null: - throw new TypeError(`Input mnemonic is ${mnemonic}`); - default: - if (typeof mnemonic !== 'string') { - throw new TypeError('Input 12 words in string type'); - } else { - const wordsNumber = mnemonic.split(' ').length; - if (wordsNumber !== 12) { - throw new TypeError('Input 12 words, not ' + wordsNumber); - } - } + if (typeof mnemonic !== 'string') { + throw new TypeError( + `Input mnemonic is ${mnemonic}, it should be string type` + ); } switch (index) { case undefined || null: diff --git a/packages/vvisp-utils/test/getPrivateKey.test.js b/packages/vvisp-utils/test/getPrivateKey.test.js index 67e1d42..58b5f59 100644 --- a/packages/vvisp-utils/test/getPrivateKey.test.js +++ b/packages/vvisp-utils/test/getPrivateKey.test.js @@ -18,14 +18,8 @@ describe('# getPrivateKey test', function() { expect(() => getPrivateKey(['hello', 'there'])).to.throw(TypeError); }); - it('should reject when length of mnemonic is not 12', function() { - const mnemonic11 = - 'away clutch still element short tooth spy hood army split stomach'; - const mnemonic13 = - 'away clutch still element short tooth spy hood army split stomach sail still'; - expect(() => getPrivateKey('')).to.throw(TypeError); - expect(() => getPrivateKey(mnemonic11)).to.throw(TypeError); - expect(() => getPrivateKey(mnemonic13)).to.throw(TypeError); + it('should receive one word', function() { + expect(() => getPrivateKey('hello')).to.not.throw(); }); }); From f33dd23c2d9a404d93b677b91bf69724eb37f015 Mon Sep 17 00:00:00 2001 From: JhChoy Date: Mon, 25 Feb 2019 14:50:20 +0900 Subject: [PATCH 5/7] ci: make generate vvisp-config and ignore some files --- packages/vvisp-utils/test/ci.sh | 2 ++ packages/vvisp/package.json | 7 ++++++- packages/vvisp/test/ci.sh | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/vvisp-utils/test/ci.sh b/packages/vvisp-utils/test/ci.sh index 20b71cb..ff8124c 100755 --- a/packages/vvisp-utils/test/ci.sh +++ b/packages/vvisp-utils/test/ci.sh @@ -4,6 +4,8 @@ set -o errexit cp test/dummy/test.env . mv test.env .env +cp test/dummy/sample.vvisp-config.js . +mv sample.vvisp-config.js vvisp-config.js nyc --reporter=html --reporter=text mocha $(find ./test -name '*.test.js') --recursive nyc report --reporter=text-lcov | coveralls diff --git a/packages/vvisp/package.json b/packages/vvisp/package.json index 2cfbaf1..c866ef9 100644 --- a/packages/vvisp/package.json +++ b/packages/vvisp/package.json @@ -61,7 +61,6 @@ "bip39": "^2.5.0", "chalk": "^2.4.1", "commander": "^2.17.1", - "dotenv": "^5.0.1", "ethereumjs-tx": "^1.3.7", "ethereumjs-wallet": "^0.6.2", "find-up": "^3.0.0", @@ -87,5 +86,11 @@ "mitm": "^1.4.0", "rewire": "^4.0.1", "std-mocks": "^1.0.1" + }, + "nyc": { + "exclude": [ + "contractApis", + "test/dummy" + ] } } diff --git a/packages/vvisp/test/ci.sh b/packages/vvisp/test/ci.sh index 20b71cb..ff8124c 100755 --- a/packages/vvisp/test/ci.sh +++ b/packages/vvisp/test/ci.sh @@ -4,6 +4,8 @@ set -o errexit cp test/dummy/test.env . mv test.env .env +cp test/dummy/sample.vvisp-config.js . +mv sample.vvisp-config.js vvisp-config.js nyc --reporter=html --reporter=text mocha $(find ./test -name '*.test.js') --recursive nyc report --reporter=text-lcov | coveralls From 25a12771d901da0f2c8faf96e4978dc0859aee6a Mon Sep 17 00:00:00 2001 From: JhChoy Date: Mon, 25 Feb 2019 14:39:39 +0900 Subject: [PATCH 6/7] feat: make Config.js --- .gitignore | 1 + packages/vvisp-utils/package.json | 1 + packages/vvisp-utils/src/Config.js | 250 ++++++++++ packages/vvisp-utils/src/index.js | 2 + packages/vvisp-utils/test/Config.test.js | 447 ++++++++++++++++++ .../test/dummy/sample.vvisp-config.js | 33 ++ .../vvisp/test/dummy/sample.vvisp-config.js | 33 ++ 7 files changed, 767 insertions(+) create mode 100644 packages/vvisp-utils/src/Config.js create mode 100644 packages/vvisp-utils/test/Config.test.js create mode 100644 packages/vvisp-utils/test/dummy/sample.vvisp-config.js create mode 100644 packages/vvisp/test/dummy/sample.vvisp-config.js diff --git a/.gitignore b/.gitignore index 489f050..f1ffff1 100644 --- a/.gitignore +++ b/.gitignore @@ -41,6 +41,7 @@ package-lock.json contractApis state.vvisp.json service.vvisp.json +vvisp-config.js example.json example diff --git a/packages/vvisp-utils/package.json b/packages/vvisp-utils/package.json index fb1ee40..2197611 100644 --- a/packages/vvisp-utils/package.json +++ b/packages/vvisp-utils/package.json @@ -37,6 +37,7 @@ "dependencies": { "bip39": "^2.5.0", "chalk": "^2.4.1", + "truffle-provider": "^0.1.4", "ethereumjs-tx": "^1.3.7", "ethereumjs-wallet": "^0.6.2", "find-cache-dir": "^2.0.0", diff --git a/packages/vvisp-utils/src/Config.js b/packages/vvisp-utils/src/Config.js new file mode 100644 index 0000000..11cf9c1 --- /dev/null +++ b/packages/vvisp-utils/src/Config.js @@ -0,0 +1,250 @@ +// reference: https://github.com/trufflesuite/truffle/blob/40a9c615eee78f14854ced65766ed3d370da07ae/packages/truffle-config/index.js +const _ = require('lodash'); +const Provider = require('truffle-provider'); +const path = require('path'); + +const DEFAULT_CONFIG_FILE = 'vvisp-config.js'; +const DEFAULT_NETWORK = 'development'; + +const getConfigRoot = require('./getConfigRoot'); +const getPrivateKey = require('./getPrivateKey'); +const filterPrivateKey = require('./filterPrivateKey'); +const forIn = require('./forIn'); + +function Config() { + const self = this; + + const defaultTxOptions = { + gasLimit: 6721975, + gasPrice: 20000000000 // 20 gwei, + }; + + this._deepCopy = ['networks', 'compilers']; + + this._values = { + network: null, // default config is development + networks: {}, + verboseRpc: false, + gasLimit: null, + gasPrice: null, + from: null, + compilers: { + solc: { + settings: { + optimizer: { + enabled: false, + runs: 200 + }, + evmVersion: 'byzantium' + } + }, + vyper: {} + } + }; + + const props = { + network: {}, + networks: {}, + verboseRpc: {}, + compilers: {}, + + from: { + get: function() { + const value = self._values['from']; + if (typeof value === 'string') { + return value; + } else if (typeof value === 'object' && value !== null) { + return getPrivateKey(value.mnemonic, value.index); + } else { + throw new Error(`from is not set properly, got ${value}`); + } + }, + set: function(value) { + if (typeof value === 'string') { + self._values['from'] = filterPrivateKey(value); + return; + } else if (typeof value === 'object' && value !== null) { + if (typeof value.mnemonic === 'string') { + self._values['from'] = value; + return; + } + } + throw new TypeError(`${JSON.stringify(value)} is invalid key format`); + } + }, + network_config: { + get: function() { + const network = self.network; + + if (network === null || network === undefined) { + throw new Error( + 'Network not set. Cannot determine network to use. Set config.network or add option --network ' + ); + } + + return _.extend({}, defaultTxOptions, self.networks[network]); + }, + set: function() { + throw new Error( + 'Do not set config.network_config. Instead, set config.networks with the desired values.' + ); + } + }, + network_id: { + get: function() { + try { + return self.network_config.network_id; + } catch (e) { + return null; + } + }, + set: function() { + throw new Error( + 'Do not set config.network_id. Instead, set config.networks and then config.networks[].network_id' + ); + } + }, + gasLimit: { + get: function() { + try { + return self.network_config.gas || self.network_config.gasLimit; + } catch (e) { + return defaultTxOptions.gasLimit; + } + }, + set: function() { + throw new Error( + "Don't set config.gas directly. Instead, set config.networks and then config.networks[].gas" + ); + } + }, + gasPrice: { + get: function() { + try { + return self.network_config.gasPrice; + } catch (e) { + return defaultTxOptions.gasPrice; + } + }, + set: function() { + throw new Error( + "Don't set config.gasPrice directly. Instead, set config.networks and then config.networks[].gasPrice" + ); + } + }, + provider: { + get: function() { + if (!self.network) { + return null; + } + + const options = self.network_config; + options.verboseRpc = self.verboseRpc; + + return Provider.create(options); + }, + set: function() { + throw new Error( + "Don't set config.provider directly. Instead, set config.networks and then set config.networks[].provider" + ); + } + } + }; + + forIn(props, (value, key) => { + self.addProperty(key, value); + }); +} + +Config.prototype.addProperty = function(propertyName, descriptor = {}) { + Object.defineProperty(this, propertyName, { + get: + descriptor.get || + function() { + // value is specified + if (propertyName in this._values) { + return this._values[propertyName]; + } + + // default getter is specified + if (descriptor.default) { + return descriptor.default(); + } + + // descriptor is a function + return descriptor(); + }, + set: + descriptor.set || + function(value) { + this._values[propertyName] = descriptor.transform + ? descriptor.transform(value) + : value; + }, + configurable: true, + enumerable: true + }); +}; + +Config.prototype.merge = function(obj = {}) { + const self = this; + const clone = _.cloneDeep(obj); + + forIn(clone, (value, key) => { + if (self.hasOwnProperty(key)) { + if (typeof clone[key] === 'object' && self._deepCopy.includes(key)) { + self[key] = _.merge(self[key], clone[key]); + } else { + self[key] = clone[key]; + } + } + }); + + return this; +}; + +Config.search = (options = {}) => { + const configFileName = options.configFile || DEFAULT_CONFIG_FILE; + // if there is no file, getConfigRoot will throw error + return path.join(getConfigRoot(configFileName), configFileName); +}; + +Config.load = options => { + const file = Config.search(options); + + const config = new Config(); + + const fileConfig = require(file); + // TODO: file 읽지 않고 load/store 할 수 있도록 + config.merge(fileConfig); + config.merge(options); + + if (!config.network && config.networks.hasOwnProperty(DEFAULT_NETWORK)) { + config.network = DEFAULT_NETWORK; + } + + return config; +}; + +let storedConfig; + +Config.get = options => { + if (!storedConfig) { + storedConfig = Config.load(options); + } + + return storedConfig; +}; + +Config.setStore = config => { + if (!(config instanceof Config)) { + throw new TypeError('Should set an instance of Config'); + } + storedConfig = config; +}; + +Config.delete = () => { + storedConfig = undefined; +}; + +module.exports = Config; diff --git a/packages/vvisp-utils/src/index.js b/packages/vvisp-utils/src/index.js index 4eca284..9a0ab71 100644 --- a/packages/vvisp-utils/src/index.js +++ b/packages/vvisp-utils/src/index.js @@ -1,6 +1,7 @@ const compile = require('./compile'); const compileAndDeploy = require('./compileAndDeploy'); const compilerSupplier = require('./compilerSupplier'); +const Config = require('./Config'); const deploy = require('./deploy'); const filterPrivateKey = require('./filterPrivateKey'); const forIn = require('./forIn'); @@ -25,6 +26,7 @@ module.exports = { compile, compileAndDeploy, compilerSupplier, + Config, deploy, filterPrivateKey, forIn, diff --git a/packages/vvisp-utils/test/Config.test.js b/packages/vvisp-utils/test/Config.test.js new file mode 100644 index 0000000..909e254 --- /dev/null +++ b/packages/vvisp-utils/test/Config.test.js @@ -0,0 +1,447 @@ +const chai = require('chai'); +const expect = chai.expect; +chai.use(require('chai-as-promised')).should(); + +const Config = require('../src/Config'); +const DEFAULT_CONFIG_FILE = 'vvisp-config.js'; +const { getPrivateKey } = require('../src'); +const _ = require('lodash'); +const path = require('path'); +const fs = require('fs-extra'); +const Provider = require('truffle-provider'); + +const DEFAULT_TX_OPTIONS = { + gasLimit: 6721975, + gasPrice: 20000000000 // 20 gwei, +}; +const DEFAULT_NETWORK = 'development'; + +const SAMPLE_CONFIG_PATH = path.join( + __dirname, + './dummy/sample.vvisp-config.js' +); +const sampleConfig = require(SAMPLE_CONFIG_PATH); +const VVISP_CONFIG_PATH = path.join('./', DEFAULT_CONFIG_FILE); + +describe('# Config test', function() { + this.timeout(50000); + + let tmpConfigName = 'eoifhsoeudhf.js'; + const TMP_CONFIG_PATH = path.join('./', tmpConfigName); + + const sampleOption = { + network: 'coverage' + }; + + before(function() { + if (fs.existsSync(VVISP_CONFIG_PATH)) { + fs.moveSync(VVISP_CONFIG_PATH, TMP_CONFIG_PATH); + } + }); + + after(function() { + if (fs.existsSync(TMP_CONFIG_PATH)) { + fs.moveSync(TMP_CONFIG_PATH, VVISP_CONFIG_PATH); + } + }); + + describe('#merge()', function() { + let config; + + beforeEach(function() { + config = new Config(); + }); + + it('should merge with option', function() { + expect(config.network).to.equal(null); + config.merge(sampleOption); + expect(config.network).to.equal(sampleOption.network); + }); + + it('should ignore input property if config does not have', function() { + expect(config.hello).to.equal(undefined); + config.merge({ hello: 'hello' }); + expect(config.hello).to.equal(undefined); + }); + }); + + describe('#addProperty()', function() { + let config; + const samplePropertyName = 'hello'; + + beforeEach(function() { + config = new Config(); + }); + + describe('add getter', function() { + it('should add given getter if descriptor has', function() { + config.addProperty(samplePropertyName, { + get: () => { + return samplePropertyName; + } + }); + expect(config[samplePropertyName]).to.equal(samplePropertyName); + }); + + it('should return exist value if propertyName is registered already', function() { + config.addProperty('network', {}); + expect(config.network).to.equal(null); + }); + + it('should add default() of descriptor if propertyName is not registered already', function() { + config.addProperty(samplePropertyName, { + default: () => { + return samplePropertyName; + } + }); + expect(config[samplePropertyName]).to.equal(samplePropertyName); + }); + + it('should add descriptor if propertyName is not registered already and descriptor is function', function() { + config.addProperty(samplePropertyName, () => { + return samplePropertyName; + }); + expect(config[samplePropertyName]).to.equal(samplePropertyName); + }); + }); + + describe('add setter', function() { + let target = 'hi'; + const changedTo = 'bye'; + const setter = value => { + target = value; + }; + it('should add given setter if descriptor has', function() { + config.addProperty(samplePropertyName, { set: setter }); + config[samplePropertyName] = changedTo; + expect(target).to.equal(changedTo); + }); + + it('should transform() of descriptor and set if propertyName is registered already and descriptor has transform()', function() { + config.addProperty('network', { + transform: value => { + return value + changedTo; + } + }); + config['network'] = target; + expect(config['network']).to.equal(target + changedTo); + }); + + it('should add just setter if there is no descriptor', function() { + config.addProperty('network'); + config['network'] = target; + expect(config['network']).to.equal(target); + }); + }); + }); + + describe('.search()', function() { + needsConfigFile(); + + it('should throw when there is no config file', function() { + fs.removeSync(path.join('./', DEFAULT_CONFIG_FILE)); + expect(() => Config.search()).to.throw(); + }); + + it('should search default config file', function() { + const configPath = Config.search(); + path.parse(configPath).base.should.equal(DEFAULT_CONFIG_FILE); + const config = require(configPath); + expect(config).to.be.an('object'); + expect(config).to.have.property('networks'); + }); + + it('should search custom config file', function() { + const customConfigFile = 'custom-config.js'; + fs.copySync( + path.join('./', DEFAULT_CONFIG_FILE), + path.join('./', customConfigFile) + ); + const configPath = Config.search({ configFile: customConfigFile }); + path.parse(configPath).base.should.equal(customConfigFile); + const config = require(configPath); + expect(config).to.be.an('object'); + expect(config).to.have.property('networks'); + + fs.removeSync(path.join('./', customConfigFile)); + }); + }); + + describe('.load()', function() { + needsConfigFile(); + + it('should load config', function() { + const config = Config.load(); + expect(config).to.be.an.instanceOf(Config); + }); + }); + + describe('.get()', function() { + needsConfigFile(); + needsDelete(); + + it('should generate and return default config if config is not generated', function() { + expect(Config.get()).to.be.an.instanceOf(Config); + }); + + it('should return stored config if config is generated', function() { + Config.get(sampleOption); + expect(Config.get()).to.be.an.instanceOf(Config); + expect(Config.get().network).to.equal(sampleOption.network); + }); + }); + + describe('.setStore()', function() { + needsConfigFile(); + needsDelete(); + + it('should throw error if input config is not an instance of Config', function() { + expect(() => Config.setStore('hello')).to.throw(TypeError); + }); + + it('should set new config', function() { + const originalConfig = Config.get(); + Config.setStore(Config.load(sampleOption)); + const newConfig = Config.get(); + expect(originalConfig).not.to.equal(newConfig); + }); + }); + + describe('.delete()', function() { + needsConfigFile(); + needsDelete(); + + it('should delete stored config and .get() will return default config', function() { + const originalConfig = Config.get(sampleOption); + expect(originalConfig.network).to.equal(sampleOption.network); + expect(Config.get().network).to.equal(sampleOption.network); + Config.delete(); + + expect(Config.get().network).to.equal(DEFAULT_NETWORK); + }); + }); + + describe('property test', function() { + let config; + beforeEach(function() { + config = new Config(); + }); + + describe('#network', function() { + const networkName = DEFAULT_NETWORK; + it('should set network name', function() { + config.network = networkName; + config.network.should.equal(networkName); + }); + }); + + describe('#networks', function() { + const networks = sampleConfig.networks; + + it('should set networks', function() { + config.networks = networks; + expect(config.networks).to.deep.equal(networks); + }); + }); + + describe('#verboseRpc', function() { + const verboseRpc = true; + + it('should set verboseRpc', function() { + config.verboseRpc = verboseRpc; + expect(config.verboseRpc).to.equal(verboseRpc); + }); + }); + + describe('#compilers', function() { + const compilers = sampleConfig.compilers; + + it('should set compilers', function() { + config.compilers = compilers; + expect(config.compilers).to.deep.equal(compilers); + }); + }); + + describe('#from', function() { + const privateKey = + '0xb178cf12d4126ea1db48ca32e3ce6743580ca6646391996032fc76652d699977'; + const mnemonicObject = { + mnemonic: 'hello', + index: 3 + }; + + it('should not set invalid type', function() { + expect(() => { + config.from = 123; + }).to.throw(TypeError); + expect(() => { + config.from = [123]; + }).to.throw(TypeError); + expect(() => { + config.from = { a: 123 }; + }).to.throw(TypeError); + expect(() => { + config.from = undefined; + }).to.throw(TypeError); + expect(() => { + config.from = null; + }).to.throw(TypeError); + }); + + it('should set privateKey and return right key', function() { + config.from = privateKey; + config.from.should.equal(privateKey); + }); + + it('should set mnemonic and index and return right key', function() { + config.from = mnemonicObject; + config.from.should.equal( + getPrivateKey(mnemonicObject.mnemonic, mnemonicObject.index) + ); + }); + + it('should return null when it is not set', function() { + let getter; + expect(() => { + getter = config.from; + }).to.throw(Error); + }); + }); + + describe('needs networks set', function() { + const DEVELOPMENT = DEFAULT_NETWORK; + beforeEach(function() { + config.networks = sampleConfig.networks; + }); + + describe('#network_config', function() { + it('should not set directly', function() { + expect(() => { + config.network_config = sampleConfig.networks[DEVELOPMENT]; + }).to.throw(); + }); + + it('should not return when network is not set', function() { + let getter; + expect(() => { + getter = config.network_config; + }).to.throw(); + }); + + it('should return network_config', function() { + config.network = DEVELOPMENT; + expect(config.network_config).to.deep.equal( + _.extend({}, DEFAULT_TX_OPTIONS, sampleConfig.networks[DEVELOPMENT]) + ); + }); + }); + + describe('#network_id', function() { + it('should not set directly', function() { + expect(() => { + config.network_id = 3; + }).to.throw(); + }); + + it('should get right network_id', function() { + config.network = DEVELOPMENT; + const expectation = sampleConfig.networks[DEVELOPMENT].network_id; + config.network_id.should.equal(expectation); + }); + + it('should return null if network is not set', function() { + expect(config.network_id).to.equal(null); + }); + }); + + describe('#gasLimit', function() { + it('should not set directly', function() { + expect(() => { + config.gasLimit = 8000000; + }).to.throw(); + }); + + it('should return default gasLimit when network is not set', function() { + expect(config.gasLimit).to.equal(DEFAULT_TX_OPTIONS.gasLimit); + }); + + it('should return right gasLimit', function() { + config.network = DEVELOPMENT; + expect(config.gasLimit).to.equal( + sampleConfig.networks[DEVELOPMENT].gasLimit + ); + }); + + it('should allow to receive gas also instead of gasLimit', function() { + const tmpConfig = _.cloneDeep(sampleConfig); + delete tmpConfig.networks[DEVELOPMENT].gasLimit; + const sampleGas = 123123; + tmpConfig.networks[DEVELOPMENT].gas = sampleGas; + + config.networks = tmpConfig.networks; + config.network = DEVELOPMENT; + expect(config.gasLimit).to.equal(sampleGas); + }); + }); + + describe('#gasPrice', function() { + it('should not set directly', function() { + expect(() => { + config.gasPrice = 10000000000; + }).to.throw(); + }); + + it('should return default gas when network is not set', function() { + expect(config.gasPrice).to.equal(DEFAULT_TX_OPTIONS.gasPrice); + }); + + it('should return right gas', function() { + config.network = DEVELOPMENT; + expect(config.gasPrice).to.equal( + sampleConfig.networks[DEVELOPMENT].gasPrice + ); + }); + }); + + describe('#provider', function() { + it('should not set directly', function() { + expect(() => { + config.provider = 'something'; + }).to.throw(); + }); + + it('should return null when network is not set', function() { + expect(config.provider).to.equal(null); + }); + + it('should return right provider', function(done) { + config.network = DEVELOPMENT; + const provider = config.provider; + Provider.test_connection(provider, fail => { + done(fail); + }); + }); + }); + }); + }); +}); + +function needsConfigFile() { + beforeEach(function() { + fs.copySync(SAMPLE_CONFIG_PATH, path.join('./', DEFAULT_CONFIG_FILE)); + }); + + afterEach(function() { + fs.removeSync(path.join('./', DEFAULT_CONFIG_FILE)); + }); +} + +function needsDelete() { + beforeEach(function() { + Config.delete(); + }); + + afterEach(function() { + Config.delete(); + }); +} diff --git a/packages/vvisp-utils/test/dummy/sample.vvisp-config.js b/packages/vvisp-utils/test/dummy/sample.vvisp-config.js new file mode 100644 index 0000000..8c19b2f --- /dev/null +++ b/packages/vvisp-utils/test/dummy/sample.vvisp-config.js @@ -0,0 +1,33 @@ +module.exports = { + networks: { + development: { + host: 'localhost', + port: 8545, + network_id: '*', // eslint-disable-line camelcase + gasLimit: 123123, + gasPrice: 10000000000 + }, + coverage: { + host: 'localhost', + port: 8545, + network_id: '*' // eslint-disable-line camelcase + } + }, + compilers: { + solc: { + version: '0.4.25', // Fetch exact version from solc-bin (default: truffle's version) + settings: { + // See the solidity docs for advice about optimization and evmVersion + optimizer: { + enabled: false, + runs: 200 + }, + evmVersion: 'byzantium' + } + } + }, + from: { + mnemonic: 'hello', + index: 0 + } +}; diff --git a/packages/vvisp/test/dummy/sample.vvisp-config.js b/packages/vvisp/test/dummy/sample.vvisp-config.js new file mode 100644 index 0000000..8c19b2f --- /dev/null +++ b/packages/vvisp/test/dummy/sample.vvisp-config.js @@ -0,0 +1,33 @@ +module.exports = { + networks: { + development: { + host: 'localhost', + port: 8545, + network_id: '*', // eslint-disable-line camelcase + gasLimit: 123123, + gasPrice: 10000000000 + }, + coverage: { + host: 'localhost', + port: 8545, + network_id: '*' // eslint-disable-line camelcase + } + }, + compilers: { + solc: { + version: '0.4.25', // Fetch exact version from solc-bin (default: truffle's version) + settings: { + // See the solidity docs for advice about optimization and evmVersion + optimizer: { + enabled: false, + runs: 200 + }, + evmVersion: 'byzantium' + } + } + }, + from: { + mnemonic: 'hello', + index: 0 + } +}; From cf9958266edd38141b425b9659a4275c4e50dd5f Mon Sep 17 00:00:00 2001 From: JhChoy Date: Mon, 25 Feb 2019 14:48:10 +0900 Subject: [PATCH 7/7] fix: change getWeb3 to web3Store --- packages/vvisp-utils/src/deploy.js | 2 +- packages/vvisp-utils/src/getTxCount.js | 2 +- packages/vvisp-utils/src/getWeb3.js | 18 ------ packages/vvisp-utils/src/index.js | 4 +- .../vvisp-utils/src/privateKeyToAddress.js | 2 +- packages/vvisp-utils/src/sendTx.js | 9 ++- packages/vvisp-utils/src/web3Store.js | 35 ++++++++++++ packages/vvisp-utils/test/deploy.test.js | 17 ++++-- packages/vvisp-utils/test/getWeb3.test.js | 13 ----- packages/vvisp-utils/test/test.env.json | 4 ++ packages/vvisp-utils/test/web3Store.test.js | 57 +++++++++++++++++++ .../vvisp/scripts/deploy-service/index.js | 3 +- .../deploy-service/preProcess/index.js | 1 + .../deploy-service/utils/pathToInstance.js | 7 ++- 14 files changed, 127 insertions(+), 47 deletions(-) delete mode 100644 packages/vvisp-utils/src/getWeb3.js create mode 100644 packages/vvisp-utils/src/web3Store.js delete mode 100644 packages/vvisp-utils/test/getWeb3.test.js create mode 100644 packages/vvisp-utils/test/test.env.json create mode 100644 packages/vvisp-utils/test/web3Store.test.js diff --git a/packages/vvisp-utils/src/deploy.js b/packages/vvisp-utils/src/deploy.js index e5d6029..398770f 100644 --- a/packages/vvisp-utils/src/deploy.js +++ b/packages/vvisp-utils/src/deploy.js @@ -40,7 +40,7 @@ module.exports = async function( } const sendTx = require('./sendTx'); - const web3 = require('./getWeb3')(); + const web3 = require('./web3Store').get(); const inputs = { data: '0x' + bytecode, arguments }; const deployData = new web3.eth.Contract(abi).deploy(inputs).encodeABI(); diff --git a/packages/vvisp-utils/src/getTxCount.js b/packages/vvisp-utils/src/getTxCount.js index 9bbc35d..2b5477c 100644 --- a/packages/vvisp-utils/src/getTxCount.js +++ b/packages/vvisp-utils/src/getTxCount.js @@ -1,5 +1,5 @@ module.exports = async function(target) { - const web3 = require('./getWeb3')(); + const web3 = require('./web3Store').get(); if (web3.utils.isAddress(target)) { return web3.eth.getTransactionCount(target); } else { diff --git a/packages/vvisp-utils/src/getWeb3.js b/packages/vvisp-utils/src/getWeb3.js deleted file mode 100644 index 74f0253..0000000 --- a/packages/vvisp-utils/src/getWeb3.js +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = function() { - const Web3 = require('web3'); - - let url; - - if (process.env.NETWORK === 'local') { - url = `http://localhost:${process.env.PORT}`; - } else if (process.env.NETWORK === 'custom') { - url = process.env.URL; - } else { - url = `https://${process.env.NETWORK}.infura.io/${ - process.env.INFURA_API_KEY - }`; - } - const web3 = new Web3(new Web3.providers.HttpProvider(url)); - - return web3; -}; diff --git a/packages/vvisp-utils/src/index.js b/packages/vvisp-utils/src/index.js index 9a0ab71..3543d37 100644 --- a/packages/vvisp-utils/src/index.js +++ b/packages/vvisp-utils/src/index.js @@ -10,7 +10,7 @@ const getAllFiles = require('./getAllFiles'); const getCompiledContracts = require('./getCompiledContracts'); const getCycle = require('./getCycle'); const getTxCount = require('./getTxCount'); -const getWeb3 = require('./getWeb3'); +const web3Store = require('./web3Store'); const getPrivateKey = require('./getPrivateKey'); const printOrSilent = require('./printOrSilent'); const privateKeyToAddress = require('./privateKeyToAddress'); @@ -35,7 +35,7 @@ module.exports = { getCompiledContracts, getCycle, getTxCount, - getWeb3, + web3Store, getPrivateKey, printOrSilent, privateKeyToAddress, diff --git a/packages/vvisp-utils/src/privateKeyToAddress.js b/packages/vvisp-utils/src/privateKeyToAddress.js index 11a7142..099101e 100644 --- a/packages/vvisp-utils/src/privateKeyToAddress.js +++ b/packages/vvisp-utils/src/privateKeyToAddress.js @@ -1,7 +1,7 @@ module.exports = function(privateKey) { const filterPrivateKey = require('./filterPrivateKey'); privateKey = filterPrivateKey(privateKey); - const web3 = require('./getWeb3')(); + const web3 = require('./web3Store').get(); return web3.eth.accounts.privateKeyToAccount(privateKey).address; }; diff --git a/packages/vvisp-utils/src/sendTx.js b/packages/vvisp-utils/src/sendTx.js index fc77a7b..d7dfe28 100644 --- a/packages/vvisp-utils/src/sendTx.js +++ b/packages/vvisp-utils/src/sendTx.js @@ -1,9 +1,12 @@ module.exports = async function(_toAddr, _value, _privKey, options) { const Tx = require('ethereumjs-tx'); - const web3 = require('./getWeb3')(); + const web3 = require('./web3Store').get(); const privateKeyToAddress = require('./privateKeyToAddress'); const printOrSilent = require('./printOrSilent'); + const DEFAULT_GAS_LIMIT = web3.utils.toHex(4600000); + const DEFAULT_GAS_PRICE = web3.utils.toHex(10e9); + return main(_toAddr, _value, _privKey, options); async function main(_toAddr, _value, _privKey, options) { @@ -14,8 +17,8 @@ module.exports = async function(_toAddr, _value, _privKey, options) { // construct the transaction data const txData = { nonce: web3.utils.toHex(txCount), - gasLimit: options.gasLimit || web3.utils.toHex(4600000), // TODO: mv to config file - gasPrice: options.gasPrice || web3.utils.toHex(10e9), + gasLimit: options.gasLimit || DEFAULT_GAS_LIMIT, + gasPrice: options.gasPrice || DEFAULT_GAS_PRICE, to: _toAddr, from: fromAddr, value: _value || '0x', diff --git a/packages/vvisp-utils/src/web3Store.js b/packages/vvisp-utils/src/web3Store.js new file mode 100644 index 0000000..fb1f2cd --- /dev/null +++ b/packages/vvisp-utils/src/web3Store.js @@ -0,0 +1,35 @@ +const Web3 = require('web3'); + +let web3; +const voidWeb3 = new Web3(); +module.exports = (function() { + return { + /** + @dev setWithProvider set web3 with provider + */ + setWithProvider: provider => { + web3 = new Web3(provider); + }, + /** + @dev setWithURL set web3 with http url + */ + setWithURL: url => { + web3 = new Web3(new Web3.providers.HttpProvider(url)); + }, + /** + @dev get getter of stored web3, if there isn't, return void web3 + */ + get: () => { + if (!web3) { + return voidWeb3; + } + return web3; + }, + /** + @dev delete delete stored web3 for test + */ + delete: () => { + web3 = undefined; + } + }; +})(); diff --git a/packages/vvisp-utils/test/deploy.test.js b/packages/vvisp-utils/test/deploy.test.js index 0298251..3b24d7e 100644 --- a/packages/vvisp-utils/test/deploy.test.js +++ b/packages/vvisp-utils/test/deploy.test.js @@ -1,17 +1,17 @@ const chai = require('chai'); chai.use(require('chai-as-promised')).should(); -require('dotenv').config(); const { compile, deploy, getCompiledContracts, - getWeb3, + web3Store, getPrivateKey, privateKeyToAddress } = require('../src'); -const web3 = getWeb3(); const path = require('path'); +const fs = require('fs-extra'); +const testEnv = fs.readJsonSync(path.join(__dirname, 'test.env.json')); const RIGHT_CONTRACT = path.join(__dirname, '../contracts/DependencyA.sol'); const ARRAY_INPUT_CONTRACT = path.join( @@ -19,13 +19,18 @@ const ARRAY_INPUT_CONTRACT = path.join( '../contracts/DependencyD.sol' ); const NO_INPUT_CONTRACT = path.join(__dirname, '../contracts/SecondB.sol'); -const PRIV_KEY = getPrivateKey(process.env.MNEMONIC); +const PRIV_KEY = getPrivateKey(testEnv.mnemonic); const SENDER = privateKeyToAddress(PRIV_KEY); describe('# deploy test', function() { this.timeout(50000); + let web3; + before(async function() { + web3Store.setWithURL(testEnv.url); + web3 = web3Store.get(); + const compileOutput = await compile( [RIGHT_CONTRACT, ARRAY_INPUT_CONTRACT, NO_INPUT_CONTRACT], { silent: true } @@ -38,6 +43,10 @@ describe('# deploy test', function() { this.secondB = getCompiledContracts(compileOutput, NO_INPUT_CONTRACT); }); + after(function() { + web3Store.delete(); + }); + describe('# input arguments', function() { it('should reject wrong input arguments length', async function() { await deploy(this.dependencyA, PRIV_KEY).should.be.rejectedWith(Error); diff --git a/packages/vvisp-utils/test/getWeb3.test.js b/packages/vvisp-utils/test/getWeb3.test.js deleted file mode 100644 index e0fddfb..0000000 --- a/packages/vvisp-utils/test/getWeb3.test.js +++ /dev/null @@ -1,13 +0,0 @@ -const chai = require('chai'); -const expect = chai.expect; -chai.should(); - -const { getWeb3 } = require('../src'); -const dotenv = require('dotenv'); - -describe('# getWeb3 test', function() { - beforeEach(function() { - dotenv.config(); - }); // TODO: fill it - it('should ', function() {}); -}); diff --git a/packages/vvisp-utils/test/test.env.json b/packages/vvisp-utils/test/test.env.json new file mode 100644 index 0000000..4eedffe --- /dev/null +++ b/packages/vvisp-utils/test/test.env.json @@ -0,0 +1,4 @@ +{ + "mnemonic": "piano garage flag neglect spare title drill basic strong aware enforce fury", + "url": "http://localhost:8545" +} diff --git a/packages/vvisp-utils/test/web3Store.test.js b/packages/vvisp-utils/test/web3Store.test.js new file mode 100644 index 0000000..e0dbac5 --- /dev/null +++ b/packages/vvisp-utils/test/web3Store.test.js @@ -0,0 +1,57 @@ +const chai = require('chai'); +const expect = chai.expect; +chai.use(require('chai-as-promised')).should(); + +const Web3 = require('web3'); +const { web3Store } = require('../src'); + +const path = require('path'); +const fs = require('fs-extra'); +const testEnv = fs.readJsonSync(path.join(__dirname, 'test.env.json')); + +describe('web3Store', function() { + beforeEach(function() { + web3Store.delete(); + }); + + after(function() { + web3Store.delete(); + }); + + describe('#setWithProvider()', function() { + it('should set with provider', async function() { + web3Store.setWithProvider(new Web3.providers.HttpProvider(testEnv.url)); + const web3 = web3Store.get(); + expect(web3).to.be.an.instanceOf(Web3); + await web3.eth.getCoinbase().should.be.fulfilled; + }); + }); + + describe('#setWithURL()', function() { + it('should set with url', async function() { + web3Store.setWithURL(testEnv.url); + const web3 = web3Store.get(); + expect(web3).to.be.an.instanceOf(Web3); + await web3.eth.getCoinbase().should.be.fulfilled; + }); + }); + + describe('#get()', function() { + it('should return void web3 when it is not set', async function() { + const web3 = web3Store.get(); + expect(web3).to.be.an.instanceOf(Web3); + await web3.eth.getCoinbase().should.be.rejected; + }); + }); + + describe('#delete()', function() { + it('should delete stored web3', async function() { + web3Store.setWithURL(testEnv.url); + web3Store.delete(); + + const web3 = web3Store.get(); + expect(web3).to.be.an.instanceOf(Web3); + await web3.eth.getCoinbase().should.be.rejected; + }); + }); +}); diff --git a/packages/vvisp/scripts/deploy-service/index.js b/packages/vvisp/scripts/deploy-service/index.js index dea2955..e24bd1f 100644 --- a/packages/vvisp/scripts/deploy-service/index.js +++ b/packages/vvisp/scripts/deploy-service/index.js @@ -3,7 +3,7 @@ module.exports = async function(options) { checkEnv(); checkConfigExist(); - const { printOrSilent, getWeb3 } = require('@haechi-labs/vvisp-utils'); + const { printOrSilent } = require('@haechi-labs/vvisp-utils'); const { writeState } = require('./utils'); const DeployState = require('./DeployState'); const preProcess = require('./preProcess'); @@ -30,7 +30,6 @@ module.exports = async function(options) { notImportant: chk.gray, warning: chk.yellow }; - global.web3 = getWeb3(); await main(); diff --git a/packages/vvisp/scripts/deploy-service/preProcess/index.js b/packages/vvisp/scripts/deploy-service/preProcess/index.js index 81104ee..063798e 100644 --- a/packages/vvisp/scripts/deploy-service/preProcess/index.js +++ b/packages/vvisp/scripts/deploy-service/preProcess/index.js @@ -3,6 +3,7 @@ module.exports = async function(deployState, options) { const { SERVICE_PATH, STATE_PATH } = require('../../../config/Constant'); const { VARIABLES } = require('../constants'); const { forIn, printOrSilent } = require('@haechi-labs/vvisp-utils'); + const web3 = options.web3; let stateClone = deployState.getState(); diff --git a/packages/vvisp/scripts/deploy-service/utils/pathToInstance.js b/packages/vvisp/scripts/deploy-service/utils/pathToInstance.js index 8034a33..7258687 100644 --- a/packages/vvisp/scripts/deploy-service/utils/pathToInstance.js +++ b/packages/vvisp/scripts/deploy-service/utils/pathToInstance.js @@ -1,6 +1,9 @@ module.exports = function(compileOutput, filePath) { - const { getCompiledContracts, getWeb3 } = require('@haechi-labs/vvisp-utils'); - const web3 = getWeb3(); + const { + getCompiledContracts, + web3Store + } = require('@haechi-labs/vvisp-utils'); + const web3 = web3Store.get(); const abi = getCompiledContracts(compileOutput, filePath).interface; return new web3.eth.Contract(JSON.parse(abi));