From 2bb977df76b2db9fe33cb99d86c4198ebf34df48 Mon Sep 17 00:00:00 2001 From: Eric Mastro Date: Mon, 30 Apr 2018 15:56:43 +1000 Subject: [PATCH 1/4] WIP to merge in other swarm changes Adding swarm to embarkjs. WIP. Add 'auto' setting for geth CORS and websockets origin * 'auto' now supported for `rpcCorsDomain` and `wsOrigins` in the blockchain config. * 'auto' set to the default value in blockchain config for test and demo apps. test add config and contract and add test addFileToPipeline test and registerBeforeDeploy with new arg add more registers but generation one fails in run WIP commit Undo changes to test config. Merge pull request #381 from embark-framework/features/cors-auto Add 'auto' setting for geth CORS and websockets origin fix a bug where upload cmd used plugin name don't error if it's an empty dapp with no contracts yet Merge pull request #383 from embark-framework/no_contracts don't error if it's an empty dapp with no contracts yet remove duplicated entry force zepplein version for travis Merge pull request #384 from embark-framework/chores/test-allpligin-apis Small fixes for plugin APIs intercept logs in the app itself - stopgap fix Merge pull request #385 from embark-framework/console_logs_fix intercept logs in the app itself - stopgap fix * removed unneeded provider property. * add 'swarm' as a provider in the storage.config * update method for swarm service check Merge branch 'develop' into features/add-swarm-to-embarkjs More work to add swarm to embarkjs * added eth-lib to parse result of swarm text * changed "currentStorage" and "currentMessages" to "currentProvider" for consistency. * added protocol to storage config * selectively starts storage service depending on which one is configured in the storage config * run service check for ipfs/swarm prior to uploaded * added swarm methods for embarkjs Updated code based on code review check if testrpc is installed and warn if not Merge pull request #386 from embark-framework/bug_fix/test-rpc-not-installed check if testrpc is installed and warn if not Removed timeout Removed spacer Merge pull request #382 from embark-framework/react-demo Updating embark demo to use react instead of jquery fix on contract add Merge pull request #387 from embark-framework/bug_fix/new-contract-in-empty-dapp Fix adding a contract redeploy with right config on config change fix tests reset watchers after build to make sure files remain watch Merge pull request #389 from embark-framework/bug_fix/file-changes-not-watched Fix files not being watched Merge pull request #388 from embark-framework/bug_fix/changing-contract-config Redeploy with right config on config change Added swarm support in embarkjs and isAvailable for messages/storage * reverted currentProvider back to currentStorage and currentMessages * added `EmbarkJS.Storage.isAvailable` and `EmbarkJS.Messages.isAvailable()` and underlying provider functions for Whisper, Orbit, IPFS, and Swarm * Finished swarm implementation in embarkjs plus cleanup * updated test app storage config to swarm to show swarm config option Merge branch 'develop' into features/add-swarm-to-embarkjs --- js/embark.js | 12 +- js/embarkjs/orbit.js | 8 + lib/cmds/blockchain/geth_commands.js | 4 +- lib/cmds/simulator.js | 12 +- lib/constants.json | 3 +- lib/contracts/code_generator.js | 2 + lib/contracts/compiler.js | 4 + lib/contracts/contracts.js | 9 + lib/contracts/deploy.js | 19 +- lib/core/config.js | 27 +- lib/core/engine.js | 71 ++- lib/index.js | 54 +- lib/modules/ipfs/embarkjs.js | 9 + lib/modules/ipfs/upload.js | 2 +- lib/modules/swarm/embarkjs.js | 84 +++ lib/modules/swarm/index.js | 107 +++- lib/modules/swarm/upload.js | 10 +- lib/modules/whisper/js/embarkjs.js | 12 + lib/modules/whisper/js/embarkjs_old_web3.js | 11 + lib/pipeline/watch.js | 15 + package-lock.json | 534 ++++++++++++++++-- package.json | 6 +- templates/boilerplate/config/blockchain.json | 4 +- templates/demo/app/components/blockchain.js | 91 +++ templates/demo/app/components/storage.js | 172 ++++++ templates/demo/app/components/whisper.js | 105 ++++ templates/demo/app/dapp.css | 4 + templates/demo/app/dapp.js | 204 ++----- templates/demo/app/index.html | 103 +--- templates/demo/config/blockchain.json | 4 +- templates/demo/package.json | 7 +- test/config.js | 4 +- test/contracts.js | 7 +- test_apps/contracts_app/blockchain.json | 4 +- test_apps/test_app/config/blockchain.json | 4 +- test_apps/test_app/config/storage.json | 10 +- .../contracts/pluginSimpleStorage.sol | 10 + .../embark-service/fileInPipeline.js | 1 + .../extensions/embark-service/index.js | 47 +- test_apps/test_app/package.json | 4 +- .../test_app/test/plugin_storage_spec.js | 26 + test_apps/test_app/test/token_spec.js | 2 - 42 files changed, 1445 insertions(+), 383 deletions(-) create mode 100644 lib/modules/swarm/embarkjs.js create mode 100644 templates/demo/app/components/blockchain.js create mode 100644 templates/demo/app/components/storage.js create mode 100644 templates/demo/app/components/whisper.js create mode 100644 test_apps/test_app/extensions/embark-service/contracts/pluginSimpleStorage.sol create mode 100644 test_apps/test_app/extensions/embark-service/fileInPipeline.js create mode 100644 test_apps/test_app/test/plugin_storage_spec.js diff --git a/js/embark.js b/js/embark.js index 6498ac1b..d8632b87 100644 --- a/js/embark.js +++ b/js/embark.js @@ -182,9 +182,7 @@ EmbarkJS.Contract.prototype.send = function(value, unit, _options) { EmbarkJS.Storage = {}; -EmbarkJS.Storage.Providers = { - SWARM: 'swarm' -}; +EmbarkJS.Storage.Providers = {}; EmbarkJS.Storage.saveText = function(text) { if (!this.currentStorage) { @@ -230,6 +228,10 @@ EmbarkJS.Storage.setProvider = function(provider, options) { return providerObj.setProvider(options); }; +EmbarkJS.Storage.isAvailable = function(){ + return this.currentStorage.isAvailable(); +}; + EmbarkJS.Messages = {}; EmbarkJS.Messages.Providers = {}; @@ -250,6 +252,10 @@ EmbarkJS.Messages.setProvider = function(provider, options) { return providerObj.setProvider(options); }; +EmbarkJS.Messages.isAvailable = function(){ + return this.currentMessages.isAvailable(); +}; + EmbarkJS.Messages.sendMessage = function(options) { if (!this.currentMessages) { throw new Error('Messages provider not set; e.g EmbarkJS.Messages.setProvider("whisper")'); diff --git a/js/embarkjs/orbit.js b/js/embarkjs/orbit.js index b8313948..0ba8e156 100644 --- a/js/embarkjs/orbit.js +++ b/js/embarkjs/orbit.js @@ -85,3 +85,11 @@ EmbarkJS.Messages.Orbit.listenTo = function(options) { return promise; }; +// TODO: needs a real check for availability +// TODO: not tested as orbit is not loaded and therefore the provider is not available +EmbarkJS.Messages.Orbit.isAvailable = function(){ + return new Promise((resolve) => { + if(!this.orbit) resolve(false); + resolve(true); + }); +} \ No newline at end of file diff --git a/lib/cmds/blockchain/geth_commands.js b/lib/cmds/blockchain/geth_commands.js index e28e559c..151b3267 100644 --- a/lib/cmds/blockchain/geth_commands.js +++ b/lib/cmds/blockchain/geth_commands.js @@ -103,14 +103,14 @@ class GethCommands { if (config.wsOrigins) { if (config.wsOrigins === '*') { console.log('=================================='); - console.log('rpcCorsDomain set to *'); + console.log('wsOrigins set to *'); console.log('make sure you know what you are doing'); console.log('=================================='); } cmd += "--wsorigins \"" + config.wsOrigins + "\" "; } else { console.log('=================================='); - console.log('warning: cors is not set'); + console.log('warning: wsOrigins is not set'); console.log('=================================='); } } diff --git a/lib/cmds/simulator.js b/lib/cmds/simulator.js index 71cc1fbd..6366290d 100644 --- a/lib/cmds/simulator.js +++ b/lib/cmds/simulator.js @@ -3,11 +3,20 @@ let shelljs = require('shelljs'); class Simulator { constructor(options) { this.blockchainConfig = options.blockchainConfig; + this.logger = options.logger; } run(options) { let cmds = []; + const testrpc = shelljs.which('testrpc'); + const ganache = shelljs.which('ganache-cli'); + if (!testrpc && !ganache) { + this.logger.warn('Ganache CLI (TestRPC) is not installed on your machine'); + this.logger.info('You can install it by running: npm -g install ganache-cli'); + process.exit(); + } + cmds.push("-p " + (this.blockchainConfig.rpcPort || options.port || 8545)); cmds.push("-h " + (this.blockchainConfig.rpcHost || options.host || 'localhost')); cmds.push("-a " + (options.numAccounts || 10)); @@ -26,7 +35,8 @@ class Simulator { cmds.push("-b \"" + (simulatorBlocktime) +"\""); } - shelljs.exec('testrpc ' + cmds.join(' '), {async : true}); + const program = ganache ? 'ganache-cli' : 'testrpc'; + shelljs.exec(`${program} ${cmds.join(' ')}`, {async : true}); } } diff --git a/lib/constants.json b/lib/constants.json index 603e6711..06d6a28c 100644 --- a/lib/constants.json +++ b/lib/constants.json @@ -13,6 +13,7 @@ "any": "any" }, "events": { - "contextChange": "contextChange" + "contractFilesChanged": "contractFilesChanged", + "contractConfigChanged": "contractConfigChanged" } } diff --git a/lib/contracts/code_generator.js b/lib/contracts/code_generator.js index 3072cd81..6b8306ae 100644 --- a/lib/contracts/code_generator.js +++ b/lib/contracts/code_generator.js @@ -19,6 +19,8 @@ const Templates = { class CodeGenerator { constructor(options) { this.blockchainConfig = options.blockchainConfig || {}; + this.rpcHost = this.blockchainConfig.rpcHost || ''; + this.rpcPort = this.blockchainConfig.rpcPort || ''; this.contractsConfig = options.contractsConfig || {}; this.storageConfig = options.storageConfig || {}; this.communicationConfig = options.communicationConfig || {}; diff --git a/lib/contracts/compiler.js b/lib/contracts/compiler.js index fa474e52..8699b842 100644 --- a/lib/contracts/compiler.js +++ b/lib/contracts/compiler.js @@ -10,6 +10,10 @@ class Compiler { const self = this; let available_compilers = {}; + if (contractFiles.length === 0) { + return cb(null, {}); + } + let pluginCompilers = self.plugins.getPluginsProperty('compilers', 'compilers'); pluginCompilers.forEach(function (compilerObject) { available_compilers[compilerObject.extension] = compilerObject.cb; diff --git a/lib/contracts/contracts.js b/lib/contracts/contracts.js index ae291124..10f56708 100644 --- a/lib/contracts/contracts.js +++ b/lib/contracts/contracts.js @@ -3,6 +3,7 @@ let async = require('async'); let Compiler = require('./compiler.js'); let utils = require('../utils/utils.js'); +const constants = require('../constants'); // TODO: create a contract object @@ -16,6 +17,14 @@ class ContractsManager { this.contractDependencies = {}; this.gasLimit = options.gasLimit; this.deployOnlyOnConfig = false; + this.events = options.events; + + this.events.on(constants.events.contractFilesChanged, (newContractFiles) => { + this.contractFiles = newContractFiles; + }); + this.events.on(constants.events.contractConfigChanged, (newContracts) => { + this.contractsConfig = newContracts; + }); } build(done) { diff --git a/lib/contracts/deploy.js b/lib/contracts/deploy.js index d1b87ade..1551331c 100644 --- a/lib/contracts/deploy.js +++ b/lib/contracts/deploy.js @@ -280,17 +280,17 @@ class Deploy { // calling each beforeDeploy handler declared by the plugin async.eachSeries(plugin.beforeDeploy, (beforeDeployFn, eachCb) => { + function beforeDeployCb(resObj){ + contract.code = resObj.contractCode; + eachCb(); + } beforeDeployFn({ embarkDeploy: self, pluginConfig: plugin.pluginConfig, deploymentAccount: deploymentAccount, contract: contract, - callback: - (function(resObj){ - contract.code = resObj.contractCode; - eachCb(); - }) - }); + callback: beforeDeployCb + }, beforeDeployCb); }, () => { //self.logger.info('All beforeDeploy handlers of the plugin has processed.'); eachPluginCb(); @@ -352,8 +352,9 @@ class Deploy { deployAll(done) { let self = this; this.logger.info("deploying contracts"); + let contracts = this.contractsManager.listContracts(); - async.eachOfSeries(this.contractsManager.listContracts(), + async.eachOfSeries(contracts, function (contract, key, callback) { self.logger.trace(arguments); self.checkAndDeployContract(contract, null, callback); @@ -364,6 +365,10 @@ class Deploy { self.logger.error(err.message); self.logger.debug(err.stack); } + if (contracts.length === 0) { + self.logger.info("no contracts found"); + return done(); + } self.logger.info("finished deploying contracts"); self.logger.trace(arguments); done(err); diff --git a/lib/core/config.js b/lib/core/config.js index 75e5b86f..43e7160a 100644 --- a/lib/core/config.js +++ b/lib/core/config.js @@ -3,6 +3,7 @@ const File = require('./file.js'); const Plugins = require('./plugins.js'); const utils = require('../utils/utils.js'); const path = require('path'); +const deepEqual = require('deep-equal'); const constants = require('../constants'); var Config = function(options) { @@ -102,7 +103,9 @@ Config.prototype._getFileOrOject = function(object, filePath, property) { Config.prototype.loadBlockchainConfigFile = function() { var configObject = { "default": { - "enabled": true + "enabled": true, + "rpcCorsDomain": "auto", + "wsOrigins": "auto" } }; @@ -141,7 +144,12 @@ Config.prototype.loadContractsConfigFile = function() { let configFilePath = this._getFileOrOject(this.configDir, 'contracts.json', 'contracts'); - this.contractsConfig = this._mergeConfig(configFilePath, configObject, this.env); + const newContractsConfig = this._mergeConfig(configFilePath, configObject, this.env); + + if (!deepEqual(newContractsConfig, this.contractsConfig)) { + this.events.emit(constants.events.contractConfigChanged, newContractsConfig); + this.contractsConfig = newContractsConfig; + } }; Config.prototype.loadExternalContractsFiles = function() { @@ -175,9 +183,10 @@ Config.prototype.loadStorageConfigFile = function() { "default": { "versions": versions, "enabled": true, - "available_providers": ["ipfs"], + "available_providers": ["ipfs", "swarm"], "ipfs_bin": "ipfs", "provider": "ipfs", + "protocol": "http", "host": "localhost", "port": 5001, "getUrl": "http://localhost:8080/ipfs/" @@ -217,8 +226,12 @@ Config.prototype.loadWebServerConfigFile = function() { }; Config.prototype.loadEmbarkConfigFile = function() { - var contracts = this.embarkConfig.contracts; - this.contractsFiles = this.loadFiles(contracts); + const contracts = this.embarkConfig.contracts; + const newContractsFiles = this.loadFiles(contracts); + if (!this.contractFiles || newContractsFiles.length !== this.contractFiles.length || !deepEqual(newContractsFiles, this.contractFiles)) { + this.events.emit(constants.events.contractFilesChanged, newContractsFiles); + this.contractsFiles = newContractsFiles; + } // determine contract 'root' directories this.contractDirectories = contracts.map((dir) => { return dir.split("**")[0]; @@ -286,7 +299,7 @@ Config.prototype.loadFiles = function(files) { } }); filesFromPlugins.filter(function(file) { - if (utils.fileMatchesPattern(files, file.intendedPath)) { + if ((file.intendedPath && utils.fileMatchesPattern(files, file.intendedPath)) || utils.fileMatchesPattern(files, file.file)) { readFiles.push(file); } }); @@ -301,7 +314,7 @@ Config.prototype.loadPluginContractFiles = function() { contractsPlugins.forEach(function(plugin) { plugin.contractsFiles.forEach(function(file) { var filename = file.replace('./',''); - self.contractsFiles.push(new File({filename: filename, type: File.types.custom, resolver: function(callback) { + self.contractsFiles.push(new File({filename: filename, type: File.types.custom, path: filename, resolver: function(callback) { callback(plugin.loadPluginFile(file)); }})); }); diff --git a/lib/core/engine.js b/lib/core/engine.js index da632e3f..8139e2be 100644 --- a/lib/core/engine.js +++ b/lib/core/engine.js @@ -35,6 +35,53 @@ class Engine { this.servicesMonitor.addCheck('embarkVersion', function (cb) { return cb({name: 'Embark ' + self.version, status: 'on'}); }, 0); + + if (this.interceptLogs || this.interceptLogs === undefined) { + this.doInterceptLogs(); + } + } + + doInterceptLogs() { + var self = this; + let context = {}; + context.console = console; + + let normalizeInput = function(input) { + let args = Object.values(input); + if (args.length === 0) { + return ""; + } + if (args.length === 1) { + if (Array.isArray(args[0])) { return args[0].join(','); } + return args[0] || ""; + } + return ('[' + args.map((x) => { + if (x === null) { return "null"; } + if (x === undefined) { return "undefined"; } + if (Array.isArray(x)) { return x.join(','); } + return x; + }).toString() + ']'); + }; + + context.console.log = function() { + self.logger.info(normalizeInput(arguments)); + }; + context.console.warn = function() { + self.logger.warn(normalizeInput(arguments)); + }; + context.console.info = function() { + self.logger.info(normalizeInput(arguments)); + }; + context.console.debug = function() { + // TODO: ue JSON.stringify + self.logger.debug(normalizeInput(arguments)); + }; + context.console.trace = function() { + self.logger.trace(normalizeInput(arguments)); + }; + context.console.dir = function() { + self.logger.dir(normalizeInput(arguments)); + }; } startMonitor() { @@ -99,17 +146,11 @@ class Engine { self.currentAbi = abi; self.contractsJSON = contractsJSON; pipeline.build(abi, contractsJSON, null, function() { + self.watch.restart(); // Necessary because changing a file while it is writing can stop it from being watched self.events.emit('outputDone'); }); }); }); - // TODO: still need to redeploy contracts because the original contracts - // config is being corrupted - this.events.on('file-event', function(fileType, _path) { - if (fileType === 'asset') { - self.events.emit('asset-changed', self.contractsManager); - } - }); } codeGeneratorService(_options) { @@ -150,7 +191,8 @@ class Engine { contractsConfig: this.config.contractsConfig, logger: this.logger, plugins: this.plugins, - gasLimit: false + gasLimit: false, + events: this.events }); this.deployManager = new DeployManager({ @@ -164,7 +206,12 @@ class Engine { onlyCompile: options.onlyCompile }); - this.events.on('file-event', function (fileType, _path) { + this.events.on('file-event', function (fileType) { + // TODO: still need to redeploy contracts because the original contracts + // config is being corrupted + if (fileType === 'asset') { + self.events.emit('asset-changed', self.contractsManager); + } // TODO: for now need to deploy on asset chanes as well // because the contractsManager config is corrupted after a deploy if (fileType === 'contract' || fileType === 'config') { @@ -177,8 +224,8 @@ class Engine { fileWatchService(_options) { this.events.emit("status", "Watching for changes"); - let watch = new Watch({logger: this.logger, events: this.events}); - watch.start(); + this.watch = new Watch({logger: this.logger, events: this.events}); + this.watch.start(); } webServerService() { @@ -200,7 +247,7 @@ class Engine { this.registerModule('swarm', { addCheck: this.servicesMonitor.addCheck.bind(this.servicesMonitor), storageConfig: this.config.storageConfig, - web3: _options.web3 + bzz: _options.bzz }); } diff --git a/lib/index.js b/lib/index.js index e321a4be..2c5d6e24 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,5 +1,6 @@ let async = require('async'); const constants = require('./constants'); +const _ = require('underscore'); // require("./utils/debug_util.js")(__filename, async); require('colors'); @@ -39,13 +40,25 @@ class Embark { blockchain(env, client) { this.context = [constants.contexts.blockchain]; - return require('./cmds/blockchain/blockchain.js')(this.config.blockchainConfig, client, env).run(); + let blockchainConfig = this.config.blockchainConfig; + let storageConfig = this.config.storageConfig; + let webServerConfig = this.config.webServerConfig; + + if(blockchainConfig.rpcCorsDomain === 'auto') { + if(webServerConfig) blockchainConfig.rpcCorsDomain = `http://${webServerConfig.host}:${webServerConfig.port}`; + if(storageConfig) blockchainConfig.rpcCorsDomain += `${blockchainConfig.rpcCorsDomain.length ? ',' : ''}${storageConfig.protocol}://${storageConfig.host}:${storageConfig.port}`; + } + if(blockchainConfig.wsOrigins === 'auto') { + if(webServerConfig) blockchainConfig.wsOrigins = `http://${webServerConfig.host}:${webServerConfig.port}`; + if(storageConfig) blockchainConfig.wsOrigins += `${blockchainConfig.wsOrigins.length ? ',' : ''}${storageConfig.protocol}://${storageConfig.host}:${storageConfig.port}`; + } + return require('./cmds/blockchain/blockchain.js')(blockchainConfig, client, env).run(); } simulator(options) { this.context = options.context || [constants.contexts.simulator, constants.contexts.blockchain]; let Simulator = require('./cmds/simulator.js'); - let simulator = new Simulator({blockchainConfig: this.config.blockchainConfig}); + let simulator = new Simulator({blockchainConfig: this.config.blockchainConfig, logger: this.logger}); simulator.run(options); } @@ -115,7 +128,7 @@ class Embark { engine.startService("pipeline"); engine.startService("codeGenerator"); engine.startService("deployment"); - engine.startService("ipfs"); + engine.startService(engine.config.storageConfig.provider, {bzz: engine.web3.bzz}); engine.events.on('check:backOnline:Ethereum', function () { engine.logger.info('Ethereum node detected..'); @@ -128,6 +141,7 @@ class Embark { engine.events.on('outputDone', function () { engine.logger.info("Looking for documentation? You can find it at ".cyan + "http://embark.readthedocs.io/".green.underline + ".".cyan); engine.logger.info("Ready".underline); + engine.events.emit("status", "Ready".green); }); engine.deployManager.deployContracts(function (err) { @@ -147,7 +161,6 @@ class Embark { engine.logger.info(err.stack); } else { engine.events.emit('firstDeploymentDone'); - engine.events.emit("status", "Ready".green); let size = windowSize.get(); if (size.height < 40 || size.width < 118) { @@ -188,6 +201,7 @@ class Embark { engine.startService("codeGenerator"); engine.startService("deployment"); engine.startService("ipfs"); + engine.startService("swarm", {bzz: engine.web3.bzz}); callback(); }, function deploy(callback) { @@ -297,10 +311,29 @@ class Embark { engine.startService("pipeline"); engine.startService("codeGenerator"); engine.startService("deployment"); - engine.startService("ipfs"); - engine.startService("swarm", {buildDir:'dist/',web3: engine.web3}); + engine.startService(platform.toLowerCase(), {bzz: engine.web3.bzz}); + engine.startMonitor(); callback(); }, + function checkStorageService(callback){ + let checkFn; + _.find(engine.servicesMonitor.checkList, (value, key) => { + if(key.toLowerCase() === platform.toLowerCase()){ + checkFn = value; + return true; + } + }); + if(!checkFn || typeof checkFn.fn !== 'function') callback(); + else{ + checkFn.fn(function(serviceCheckResult){ + if(!serviceCheckResult.status || serviceCheckResult.status === 'off'){ + callback({message:`Cannot upload: ${platform} node is not running on http://${engine.config.storageConfig.host}:${engine.config.storageConfig.port}.`}); + } else { + callback(null); + } + }); + } + }, function setupStoragePlugin(callback){ let pluginList = engine.plugins.listPlugins(); if (pluginList.length > 0) { @@ -312,15 +345,16 @@ class Embark { if (cmdPlugins.length > 0) { cmdPlugin = cmdPlugins.find((pluginCmd) => { - return pluginCmd.name == platform; + return pluginCmd.uploadCmds.some(uploadCmd => { + return uploadCmd.cmd === platform; + }); }); } if (!cmdPlugin) { engine.logger.info('try "embark upload ipfs" or "embark upload swarm"'.green); callback({message: 'unknown platform: ' + platform}); - } else { - callback(); - } + } + else callback(null); }, function deploy(callback) { // 2. upload to storage (outputDone event triggered after webpack finished) diff --git a/lib/modules/ipfs/embarkjs.js b/lib/modules/ipfs/embarkjs.js index c2e516e0..da317811 100644 --- a/lib/modules/ipfs/embarkjs.js +++ b/lib/modules/ipfs/embarkjs.js @@ -100,6 +100,15 @@ __embarkIPFS.uploadFile = function(inputSelector) { return promise; }; +__embarkIPFS.isAvailable = function(){ + return new Promise((resolve) => { + if(!this.ipfsConnection) resolve(false); + this.ipfsConnection.id() + .then((id) => { resolve(Boolean(id)); }) + .catch(() => { resolve(false); }); + }); +}; + __embarkIPFS.getUrl = function(hash) { return (this._getUrl || "http://localhost:8080/ipfs/") + hash; }; diff --git a/lib/modules/ipfs/upload.js b/lib/modules/ipfs/upload.js index 6c9cd7a1..36c65e40 100644 --- a/lib/modules/ipfs/upload.js +++ b/lib/modules/ipfs/upload.js @@ -29,7 +29,7 @@ class IPFS { function runCommand(ipfs_bin, callback) { let cmd = `"${ipfs_bin}" add -r ${self.buildDir}`; console.log(("=== adding " + self.buildDir + " to ipfs").green); - console.trace(cmd); + console.debug(cmd); shelljs.exec(cmd, {silent:true}, function(code, stdout, stderr){ // {silent:true}: don't echo cmd output so it can be controlled via logLevel console.log(stdout.green); callback(stderr, stdout); diff --git a/lib/modules/swarm/embarkjs.js b/lib/modules/swarm/embarkjs.js new file mode 100644 index 00000000..1b780e8e --- /dev/null +++ b/lib/modules/swarm/embarkjs.js @@ -0,0 +1,84 @@ +let __embarkSwarm = {}; +const bytes = require("eth-lib/lib/bytes"); + +__embarkSwarm.setProvider = function(options) { + this.bzz = web3.bzz; + this.protocol = options.protocol; + this.host = options.host; + this.port = options.port; + this.connectUrl = `${options.protocol}://${options.host}:${options.port}`; + this.connectError = new Error(`Cannot connect to Swarm node on ${this.connectUrl}`); + this._getUrl = options.getUrl || `${this.connectUrl}/bzzr:/`; + + var promise = new Promise((resolve, reject) => { + try { + if(!this.bzz.currentProvider) { + this.bzz.setProvider(`${options.protocol}://${options.host}:${options.port}`); + } + resolve(this); + } catch (err) { + console.log(err); + reject(this.connectError); + } + }); + return promise; +}; + +__embarkSwarm.isAvailable = function(){ + return new Promise((resolve, reject) => { + if(!this.bzz) resolve(false); + this.bzz.isAvailable() + .then(resolve) + .catch(() => { reject(this.connectError); }); + }); +}; + +__embarkSwarm.saveText = function(text) { + return new Promise((resolve, reject) => { + this.isAvailable().then((isAvailable) => { + if(!isAvailable) reject(this.connectError); + this.bzz.upload(text) + .then(resolve) + .catch(reject); + }).catch(reject); + }); +}; + +__embarkSwarm.get = function(hash) { + return new Promise((resolve, reject) => { + this.isAvailable().then((isAvailable) => { + if(!isAvailable) reject(this.connectError); + this.bzz.download(hash) + .then((uint8Array) => resolve(bytes.toString(bytes.fromUint8Array(uint8Array)))) + .catch(reject); + }).catch(reject); + }); +}; + +__embarkSwarm.uploadFile = function(inputSelector) { + let file = inputSelector[0].files[0]; + + if (file === undefined) { + throw new Error('no file found'); + } + + return new Promise((resolve, reject) => { + var reader = new FileReader(); + reader.onloadend = (event) => { + var fileContent = new Uint8Array(event.target.result); + this.isAvailable().then((isAvailable) => { + if(!isAvailable) reject(this.connectError); + this.bzz.upload(fileContent) + .then(resolve) + .catch(reject); + }).catch(reject); + }; + reader.onerror = reject; + reader.readAsArrayBuffer(file); + }); +}; + +__embarkSwarm.getUrl = function(hash) { + return this._getUrl + hash; +}; + diff --git a/lib/modules/swarm/index.js b/lib/modules/swarm/index.js index b19bf927..07660f4b 100644 --- a/lib/modules/swarm/index.js +++ b/lib/modules/swarm/index.js @@ -1,19 +1,112 @@ let UploadSwarm = require('./upload.js'); +let utils = require('../../utils/utils.js'); +let fs = require('../../core/fs.js'); class Swarm { constructor(embark, options) { this.logger = embark.logger; + this.events = embark.events; + this.buildDir = options.buildDir; + this.storageConfig = options.storageConfig; + this.host = options.host || this.storageConfig.host; + this.port = options.port || this.storageConfig.port; + this.addCheck = options.addCheck; + this.embark = embark; + this.bzz = options.bzz; - this.upload_swarm = new UploadSwarm({ - buildDir: options.buildDir || 'dist/', - storageConfig: options.storageConfig, - web3: options.web3 - }); - - embark.registerUploadCommand('swarm', this.upload_swarm.deploy.bind(this.upload_swarm)); + this.initSwarmProvider(); + this.commandlineDeploy(); + this.setServiceCheck(); + this.addSwarmToEmbarkJS(); + this.addSetProvider(); } + initSwarmProvider(){ + if(!this.bzz.currentProvider) { + this.bzz.setProvider(`http://${this.host}:${this.port}`); + } + } + + commandlineDeploy() { + this.upload_swarm = new UploadSwarm({ + buildDir: this.buildDir || 'dist/', + storageConfig: this.storageConfig, + bzz: this.bzz + }); + + this.embark.registerUploadCommand('swarm', this.upload_swarm.deploy.bind(this.upload_swarm)); + } + + + setServiceCheck() { + let self = this; + + let storageConfig = this.storageConfig; + + if (!storageConfig.enabled) { + return; + } + if (storageConfig.provider !== 'swarm' && storageConfig.available_providers.indexOf("swarm") < 0) { + return; + } + + this.events.on('check:backOnline:Swarm', function () { + self.logger.info('Swarm node detected...'); + }); + + this.events.on('check:wentOffline:Swarm', function () { + self.logger.info('Swarm node is offline...'); + }); + + if (!this.addCheck) { + return; + } + + // add check for console + this.addCheck('Swarm', function(cb){ + self.logger.trace("Checking Swarm availability..."); + self.bzz.isAvailable().then(result => { + return cb({name: "Swarm ", status: result ? 'on':'off'}); + }).catch(err => { + self.logger.trace("Check Swarm availability error: " + err); + return cb({name: "Swarm ", status: 'off'}); + }); + }); + } + + addSwarmToEmbarkJS() { + // TODO: make this a shouldAdd condition + if (this.storageConfig === {}) { + return; + } + + if ((this.storageConfig.available_providers.indexOf('swarm') < 0) && (this.storageConfig.provider !== 'swarm' || this.storageConfig.enabled !== true)) { + return; + } + + let code = ""; + code += "\n" + fs.readFileSync(utils.joinPath(__dirname, 'embarkjs.js')).toString(); + code += "\nEmbarkJS.Storage.registerProvider('swarm', __embarkSwarm);"; + + this.embark.addCodeToEmbarkJS(code); + } + + addSetProvider() { + let config = JSON.stringify({ + host: this.storageConfig.host, + port: this.storageConfig.port, + protocol: this.storageConfig.protocol, + getUrl: this.storageConfig.getUrl + }); + let code = "\nEmbarkJS.Storage.setProvider('swarm'," + config + ");"; + + let shouldInit = (storageConfig) => { + return (storageConfig.provider === 'swarm' && storageConfig.enabled === true); + }; + + this.embark.addProviderInit('storage', code, shouldInit); + } } module.exports = Swarm; diff --git a/lib/modules/swarm/upload.js b/lib/modules/swarm/upload.js index 26d11be1..0c00aad8 100644 --- a/lib/modules/swarm/upload.js +++ b/lib/modules/swarm/upload.js @@ -5,7 +5,7 @@ class Swarm { constructor(options) { this.options = options; this.buildDir = options.buildDir || 'dist/'; - this.web3 = options.web3; + this.bzz = options.bzz; this.storageConfig = options.storageConfig; } @@ -13,15 +13,11 @@ class Swarm { return new Promise((resolve, reject) => { console.log("deploying to swarm!"); let self = this; - let web3 = this.web3; + let bzz = this.bzz; async.waterfall([ - function setProvider(callback){ - web3.bzz.setProvider(`http://${self.storageConfig.host}:${self.storageConfig.port}`); - callback(); - }, function runCommand(callback) { console.log(("=== adding " + self.buildDir + " to swarm").green); - web3.bzz.upload({ + bzz.upload({ path: self.buildDir, // path to data / file / directory kind: "directory", // could also be "file" or "data" defaultFile: "index.html" // optional, and only for kind === "directory" diff --git a/lib/modules/whisper/js/embarkjs.js b/lib/modules/whisper/js/embarkjs.js index 3abaacb1..2fab5d27 100644 --- a/lib/modules/whisper/js/embarkjs.js +++ b/lib/modules/whisper/js/embarkjs.js @@ -97,3 +97,15 @@ __embarkWhisperNewWeb3.getWhisperVersion = function(cb) { }); }; +__embarkWhisperNewWeb3.isAvailable = function(){ + return new Promise((resolve, reject) => { + if(!this.web3.shh) resolve(false); + try{ + this.getWhisperVersion((err) => { + resolve(Boolean(!err)); + }); + } + catch(err){ reject(err); } + }); +}; + diff --git a/lib/modules/whisper/js/embarkjs_old_web3.js b/lib/modules/whisper/js/embarkjs_old_web3.js index 2e0a1383..e4769768 100644 --- a/lib/modules/whisper/js/embarkjs_old_web3.js +++ b/lib/modules/whisper/js/embarkjs_old_web3.js @@ -107,3 +107,14 @@ __embarkWhisperOld.getWhisperVersion = function(cb) { }); }; +__embarkWhisperOld.isAvailable = function(){ + return new Promise((resolve, reject) => { + if(!this.web3) resolve(false); + try{ + this.getWhisperVersion((err) => { + resolve(Boolean(!err)); + }); + } + catch(err){ reject(err); } + }); +}; diff --git a/lib/pipeline/watch.js b/lib/pipeline/watch.js index a436b5bc..8ece7a56 100644 --- a/lib/pipeline/watch.js +++ b/lib/pipeline/watch.js @@ -9,6 +9,7 @@ class Watch { constructor(options) { this.logger = options.logger; this.events = options.events; + this.fileWatchers = []; } start() { @@ -32,6 +33,19 @@ class Watch { this.logger.info("ready to watch file changes"); } + restart() { + this.stop(); + this.start(); + } + + stop() { + this.fileWatchers.forEach(fileWatcher => { + fileWatcher.close(); + fileWatcher = null; + }); + this.fileWatchers = []; + } + watchAssets(embarkConfig, callback) { let self = this; let appConfig = embarkConfig.app; @@ -102,6 +116,7 @@ class Watch { let configWatcher = chokidar.watch(files, { ignored: /[\/\\]\./, persistent: true, ignoreInitial: true, followSymlinks: true }); + this.fileWatchers.push(configWatcher); configWatcher .on('add', path => changeCallback('add', path)) diff --git a/package-lock.json b/package-lock.json index d2900817..58672383 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.2.tgz", "integrity": "sha512-Q3FWsbdmkQd1ib11A4XNWQvRD//5KpPoGawA8aB2DR7pWKoW9XQv3+dGxD/Z1eVFze23Okdo27ZQytVFlweKvQ==", "requires": { - "@types/node": "9.6.6" + "@types/node": "10.0.0" } }, "@types/lockfile": { @@ -32,16 +32,16 @@ "integrity": "sha512-pD6JuijPmrfi84qF3/TzGQ7zi0QIX+d7ZdetD6jUA6cp+IsCzAquXZfi5viesew+pfpOTIdAVKuh1SHA7KeKzg==" }, "@types/node": { - "version": "9.6.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.6.tgz", - "integrity": "sha512-SJe0g5cZeGNDP5sD8mIX3scb+eq8LQQZ60FXiKZHipYSeEFZ5EKml+NNMiO76F74TY4PoMWlNxF/YRY40FOvZQ==" + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.0.0.tgz", + "integrity": "sha512-kctoM36XiNZT86a7tPsUje+Q/yl+dqELjtYApi0T5eOQ90Elhu0MI10rmYk44yEP4v1jdDvtjQ9DFtpRtHf2Bw==" }, "@types/node-fetch": { "version": "1.6.9", "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-1.6.9.tgz", "integrity": "sha512-n2r6WLoY7+uuPT7pnEtKJCmPUGyJ+cbyBR8Avnu4+m1nzz7DwBVuyIvvlBzCZ/nrpC7rIgb3D6pNavL7rFEa9g==", "requires": { - "@types/node": "9.6.6" + "@types/node": "10.0.0" } }, "@types/semver": { @@ -54,7 +54,7 @@ "resolved": "https://registry.npmjs.org/@types/tar/-/tar-4.0.0.tgz", "integrity": "sha512-YybbEHNngcHlIWVCYsoj7Oo1JU9JqONuAlt1LlTH/lmL8BMhbzdFUgReY87a05rY1j8mfK47Del+TCkaLAXwLw==", "requires": { - "@types/node": "9.6.6" + "@types/node": "10.0.0" } }, "@types/url-join": { @@ -166,12 +166,236 @@ "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" }, "anymatch": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "requires": { - "micromatch": "2.3.11", + "micromatch": "3.1.10", "normalize-path": "2.1.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==" + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + } } }, "argparse": { @@ -186,6 +410,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, "requires": { "arr-flatten": "1.1.0" } @@ -229,7 +454,8 @@ "array-unique": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true }, "arrify": { "version": "1.0.1", @@ -1177,6 +1403,7 @@ "version": "1.8.5", "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, "requires": { "expand-range": "1.8.2", "preserve": "0.2.0", @@ -1455,19 +1682,110 @@ "dev": true }, "chokidar": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", - "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz", + "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==", "requires": { - "anymatch": "1.3.2", + "anymatch": "2.0.0", "async-each": "1.0.1", + "braces": "2.3.2", "fsevents": "1.1.3", - "glob-parent": "2.0.0", + "glob-parent": "3.1.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", - "is-glob": "2.0.1", + "is-glob": "4.0.0", + "normalize-path": "2.1.1", "path-is-absolute": "1.0.1", - "readdirp": "2.1.0" + "readdirp": "2.1.0", + "upath": "1.0.4" + }, + "dependencies": { + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=" + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "0.1.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + } } }, "chownr": { @@ -2138,6 +2456,11 @@ } } }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -2677,16 +3000,12 @@ "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, "eth-lib": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", - "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", + "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", "requires": { "bn.js": "4.11.8", "elliptic": "6.4.0", - "keccakjs": "0.2.1", - "nano-json-stream-parser": "0.1.2", - "servify": "0.1.12", - "ws": "3.3.3", "xhr-request-promise": "0.1.2" } }, @@ -2772,6 +3091,7 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, "requires": { "is-posix-bracket": "0.1.1" } @@ -2780,6 +3100,7 @@ "version": "1.8.2", "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, "requires": { "fill-range": "2.2.3" } @@ -2821,20 +3142,6 @@ "vary": "1.1.2" }, "dependencies": { - "finalhandler": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", - "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", - "requires": { - "debug": "2.6.9", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.4.0", - "unpipe": "1.0.0" - } - }, "setprototypeof": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", @@ -2886,6 +3193,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, "requires": { "is-extglob": "1.0.0" } @@ -2977,12 +3285,14 @@ "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true }, "fill-range": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, "requires": { "is-number": "2.1.0", "isobject": "2.1.0", @@ -3111,6 +3421,7 @@ "version": "0.1.5", "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, "requires": { "for-in": "1.0.2" } @@ -4188,6 +4499,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, "requires": { "glob-parent": "2.0.0", "is-glob": "2.0.1" @@ -4202,6 +4514,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, "requires": { "is-glob": "2.0.1" } @@ -5182,12 +5495,14 @@ "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true }, "is-equal-shallow": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, "requires": { "is-primitive": "2.0.0" } @@ -5200,7 +5515,8 @@ "is-extglob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true }, "is-finite": { "version": "1.0.2", @@ -5227,6 +5543,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, "requires": { "is-extglob": "1.0.0" } @@ -5255,6 +5572,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, "requires": { "kind-of": "3.2.2" } @@ -5326,12 +5644,14 @@ "is-posix-bracket": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true }, "is-primitive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true }, "is-promise": { "version": "1.0.1", @@ -5396,6 +5716,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, "requires": { "isarray": "1.0.0" } @@ -6189,6 +6510,7 @@ "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, "requires": { "arr-diff": "2.0.0", "array-unique": "0.2.1", @@ -6647,7 +6969,6 @@ "version": "1.0.35", "resolved": "https://registry.npmjs.org/node-webcrypto-ossl/-/node-webcrypto-ossl-1.0.35.tgz", "integrity": "sha1-FCJVeb0J9dY7CtbO4LqAD4xqBg0=", - "optional": true, "requires": { "mkdirp": "0.5.1", "nan": "2.9.2", @@ -6834,6 +7155,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, "requires": { "for-own": "0.1.5", "is-extendable": "0.1.1" @@ -7132,6 +7454,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, "requires": { "glob-base": "0.3.0", "is-dotfile": "1.0.3", @@ -7846,7 +8169,8 @@ "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true }, "private": { "version": "0.1.8", @@ -8097,6 +8421,7 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", + "dev": true, "requires": { "is-number": "3.0.0", "kind-of": "4.0.0" @@ -8106,6 +8431,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, "requires": { "kind-of": "3.2.2" }, @@ -8114,6 +8440,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -8124,6 +8451,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, "requires": { "is-buffer": "1.1.6" } @@ -8286,6 +8614,7 @@ "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", + "dev": true, "requires": { "is-equal-shallow": "0.1.3" } @@ -9589,6 +9918,20 @@ "base64-js": "1.2.3", "ieee754": "1.1.8" } + }, + "eth-lib": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0", + "keccakjs": "0.2.1", + "nano-json-stream-parser": "0.1.2", + "servify": "0.1.12", + "ws": "3.3.3", + "xhr-request-promise": "0.1.2" + } } } }, @@ -10014,9 +10357,9 @@ } }, "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.0.tgz", + "integrity": "sha512-4IV1DSSxC1QK48j9ONFK1MoIAKKkbE8i7u55w2R6IqBqbT7A/iG7aZBCR2Bi8piF0Uz+i/MG1aeqLwl/5vqF+A==" }, "underscore.string": { "version": "3.3.4", @@ -10642,6 +10985,13 @@ "got": "7.1.0", "swarm-js": "0.1.37", "underscore": "1.8.3" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } } }, "web3-core": { @@ -10663,6 +11013,13 @@ "underscore": "1.8.3", "web3-eth-iban": "1.0.0-beta.34", "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } } }, "web3-core-method": { @@ -10675,6 +11032,13 @@ "web3-core-promievent": "1.0.0-beta.34", "web3-core-subscriptions": "1.0.0-beta.34", "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } } }, "web3-core-promievent": { @@ -10696,6 +11060,13 @@ "web3-providers-http": "1.0.0-beta.34", "web3-providers-ipc": "1.0.0-beta.34", "web3-providers-ws": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } } }, "web3-core-subscriptions": { @@ -10706,6 +11077,13 @@ "eventemitter3": "1.1.1", "underscore": "1.8.3", "web3-core-helpers": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } } }, "web3-eth": { @@ -10725,6 +11103,13 @@ "web3-eth-personal": "1.0.0-beta.34", "web3-net": "1.0.0-beta.34", "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } } }, "web3-eth-abi": { @@ -10742,6 +11127,11 @@ "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" } } }, @@ -10772,6 +11162,11 @@ "xhr-request-promise": "0.1.2" } }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, "uuid": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", @@ -10792,6 +11187,13 @@ "web3-core-subscriptions": "1.0.0-beta.34", "web3-eth-abi": "1.0.0-beta.34", "web3-utils": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } } }, "web3-eth-iban": { @@ -10849,6 +11251,13 @@ "oboe": "2.1.3", "underscore": "1.8.3", "web3-core-helpers": "1.0.0-beta.34" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } } }, "web3-providers-ws": { @@ -10859,6 +11268,13 @@ "underscore": "1.8.3", "web3-core-helpers": "1.0.0-beta.34", "websocket": "1.0.25" + }, + "dependencies": { + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + } } }, "web3-shh": { @@ -10890,6 +11306,25 @@ "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha1-UzRK2xRhehP26N0s4okF0cC6MhU=" + }, + "eth-lib": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", + "integrity": "sha512-B8czsfkJYzn2UIEMwjc7Mbj+Cy72V+/OXH/tb44LV8jhrjizQJJ325xMOMyk3+ETa6r6oi0jsUY14+om8mQMWA==", + "requires": { + "bn.js": "4.11.6", + "elliptic": "6.4.0", + "keccakjs": "0.2.1", + "nano-json-stream-parser": "0.1.2", + "servify": "0.1.12", + "ws": "3.3.3", + "xhr-request-promise": "0.1.2" + } + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" } } }, @@ -10897,7 +11332,6 @@ "version": "0.1.19", "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-0.1.19.tgz", "integrity": "sha1-8CTjoCu8oW3tRtJpaMQlNaORJNw=", - "optional": true, "requires": { "tslib": "1.9.0" } diff --git a/package.json b/package.json index 28aa1df6..7efa9fbf 100644 --- a/package.json +++ b/package.json @@ -30,11 +30,13 @@ "babel-preset-es2017": "6.24.1", "babel-preset-react": "^6.24.1", "blessed": "^0.1.81", - "chokidar": "^1.6.0", + "chokidar": "^2.0.3", "colors": "^1.1.2", "commander": "^2.15.1", "css-loader": "^0.28.11", + "deep-equal": "^1.0.1", "ejs": "^2.5.8", + "eth-lib": "^0.2.8", "ethereumjs-testrpc": "^6.0.3", "file-loader": "^1.1.5", "finalhandler": "^1.1.1", @@ -57,7 +59,7 @@ "style-loader": "^0.19.0", "tar": "^3.1.5", "toposort": "^1.0.0", - "underscore": "^1.8.3", + "underscore": "^1.9.0", "underscore.string": "^3.3.4", "url-loader": "^0.6.2", "viz.js": "^1.8.1", diff --git a/templates/boilerplate/config/blockchain.json b/templates/boilerplate/config/blockchain.json index 1d0e0820..afff2072 100644 --- a/templates/boilerplate/config/blockchain.json +++ b/templates/boilerplate/config/blockchain.json @@ -9,12 +9,12 @@ "maxpeers": 0, "rpcHost": "localhost", "rpcPort": 8545, - "rpcCorsDomain": "http://localhost:8000", + "rpcCorsDomain": "auto", "account": { "password": "config/development/password" }, "targetGasLimit": 8000000, - "wsOrigins": "http://localhost:8000", + "wsOrigins": "auto", "wsRPC": true, "wsHost": "localhost", "wsPort": 8546, diff --git a/templates/demo/app/components/blockchain.js b/templates/demo/app/components/blockchain.js new file mode 100644 index 00000000..b9e5e313 --- /dev/null +++ b/templates/demo/app/components/blockchain.js @@ -0,0 +1,91 @@ +import EmbarkJS from 'Embark/EmbarkJS'; +import SimpleStorage from 'Embark/contracts/SimpleStorage'; +import React from 'react'; +import { Form, FormGroup, FormControl, HelpBlock, Button } from 'react-bootstrap'; + +class Blockchain extends React.Component { + + constructor(props) { + super(props); + + this.state = { + valueSet: 10, + valueGet: "", + logs: [] + } + } + + handleChange(e){ + this.setState({valueSet: e.target.value}); + } + + setValue(e){ + e.preventDefault(); + + var value = parseInt(this.state.valueSet, 10); + + // If web3.js 1.0 is being used + if (EmbarkJS.isNewWeb3()) { + SimpleStorage.methods.set(value).send({from: web3.eth.defaultAccount}); + this._addToLog("SimpleStorage.methods.set(value).send({from: web3.eth.defaultAccount})"); + } else { + SimpleStorage.set(value); + this._addToLog("#blockchain", "SimpleStorage.set(" + value + ")"); + } + } + + getValue(e){ + e.preventDefault(); + + if (EmbarkJS.isNewWeb3()) { + SimpleStorage.methods.get().call() + .then(_value => this.setState({valueGet: _value})) + this._addToLog("SimpleStorage.methods.get(console.log)"); + } else { + SimpleStorage.get() + .then(_value => this.setState({valueGet: _value})); + this._addToLog("SimpleStorage.get()"); + } + } + + _addToLog(txt){ + this.state.logs.push(txt); + this.setState({logs: this.state.logs}); + } + + render(){ + return ( +

1. Set the value in the blockchain

+
+ + this.handleChange(e)} /> + + Once you set the value, the transaction will need to be mined and then the value will be updated on the blockchain. + +
+ +

2. Get the current value

+
+ + current value is {this.state.valueGet} + + Click the button to get the current value. The initial value is 100. + +
+ +

3. Contract Calls

+

Javascript calls being made:

+
+ { + this.state.logs.map((item, i) =>

{item}

) + } +
+
+ ); + } + } + + export default Blockchain; \ No newline at end of file diff --git a/templates/demo/app/components/storage.js b/templates/demo/app/components/storage.js new file mode 100644 index 00000000..f6721453 --- /dev/null +++ b/templates/demo/app/components/storage.js @@ -0,0 +1,172 @@ +import EmbarkJS from 'Embark/EmbarkJS'; +import React from 'react'; +import { Alert, Form, FormGroup, FormControl, HelpBlock, Button } from 'react-bootstrap'; + +class Storage extends React.Component { + + constructor(props) { + super(props); + + this.state = { + textToSave: 'hello world!', + generatedHash: '', + loadText: '', + storedText: '', + fileToUpload: null, + fileHash: '', + imageToDownload: '', + url: '', + logs: [], + storageError: '' + }; + } + + handleChange(e, name){ + this.state[name] = e.target.value; + this.setState(this.state); + } + + handleFileUpload(e){ + this.setState({ fileToUpload: [e.target] }); + } + + addToLog(txt){ + this.state.logs.push(txt); + this.setState({logs: this.state.logs}); + } + + setText(e){ + e.preventDefault(); + + EmbarkJS.Storage.saveText(this.state.textToSave) + .then((hash) => { + this.setState({ + generatedHash: hash, + loadText: hash, + storageError: '' + }); + this.addToLog("EmbarkJS.Storage.saveText('" + this.state.textToSave + "').then(function(hash) { })"); + }) + .catch((err) => { + if(err){ + this.setState({storageError: err.message}); + console.log("Storage saveText Error => " + err.message); + } + }); + } + + loadHash(e){ + e.preventDefault(); + + EmbarkJS.Storage.get(this.state.loadText) + .then((content) => { + this.setState({storedText: content, storageError: ''}); + this.addToLog("EmbarkJS.Storage.get('" + this.state.loadText + "').then(function(content) { })"); + }) + .catch((err) => { + if(err){ + this.setState({storageError: err.message}) + console.log("Storage get Error => " + err.message); + } + }); + } + + uploadFile(e){ + e.preventDefault(); + + EmbarkJS.Storage.uploadFile(this.state.fileToUpload) + .then((hash) => { + this.setState({ + fileHash: hash, + imageToDownload: hash, + storageError: '' + }); + this.addToLog("EmbarkJS.Storage.uploadFile(this.state.fileToUpload).then(function(hash) { })"); + }) + .catch((err) => { + if(err){ + this.setState({storageError: err.message}); + console.log("Storage uploadFile Error => " + err.message); + } + }); + } + + loadFile(e){ + let _url = EmbarkJS.Storage.getUrl(this.state.imageToDownload); + this.setState({url: _url}) + this.addToLog("EmbarkJS.Storage.getUrl('" + this.state.imageToDownload + "')"); + } + + render(){ + return + { + !this.props.enabled ? + + The node you are using does not support IPFS. Please ensure CORS is setup for the IPFS node. + : '' + } + { + this.state.storageError !== '' ? + {this.state.storageError} + : '' + } +

Save text to storage

+
+ + this.handleChange(e, 'textToSave')} /> + + generated Hash: {this.state.generatedHash} + +
+ +

Load text from storage given an hash

+
+ + this.handleChange(e, 'loadText')} /> + + result: {this.state.storedText} + +
+ +

Upload file to storage

+
+ + this.handleFileUpload(e)} /> + + generated hash: {this.state.fileHash} + +
+ +

Get file or image from storage

+
+ + this.handleChange(e, 'imageToDownload')} /> + + file available at: {this.state.url} + + +
+ +

Javascript calls being made:

+
+

EmbarkJS.Storage.setProvider('ipfs',{'{'}server: 'localhost', port: '5001'{'}'})

+ { + this.state.logs.map((item, i) =>

{item}

) + } +
+
; + } +} + +export default Storage; \ No newline at end of file diff --git a/templates/demo/app/components/whisper.js b/templates/demo/app/components/whisper.js new file mode 100644 index 00000000..be78c62e --- /dev/null +++ b/templates/demo/app/components/whisper.js @@ -0,0 +1,105 @@ +import EmbarkJS from 'Embark/EmbarkJS'; +import React from 'react'; +import { Alert, Form, FormGroup, FormControl, HelpBlock, Button } from 'react-bootstrap'; + +class Whisper extends React.Component { + + constructor(props) { + super(props); + + this.state = { + listenTo: '', + channel: '', + message: '', + subscribedChannels: [], + messageList: [], + logs: [] + } + } + + handleChange(e, name){ + this.state[name] = e.target.value; + this.setState(this.state); + } + + sendMessage(e){ + e.preventDefault(); + EmbarkJS.Messages.sendMessage({topic: this.state.channel, data: this.state.message}); + this.addToLog("EmbarkJS.Messages.sendMessage({topic: '" + this.state.channel + "', data: '" + this.state.message + "'})"); + } + + listenToChannel(e){ + e.preventDefault(); + + this.state.subscribedChannels.push(`subscribed to ${this.state.listenTo} now try sending a message`); + + EmbarkJS.Messages.listenTo({topic: [this.state.listenTo]}) + .then(message => this.state.messageList.push(`channel: ${this.state.listenTo} message: ${message}`)) + + this.addToLog("EmbarkJS.Messages.listenTo({topic: ['" + this.state.listenTo + "']}).then(function(message) {})"); + } + + addToLog(txt){ + this.state.logs.push(txt); + this.setState({logs: this.state.logs}); + } + + render(){ + return ( + + { + !this.props.enabled ? + + The node you are using does not support Whisper + The node uses an unsupported version of Whisper + : '' + } +

Listen To channel

+
+ + this.handleChange(e, 'listenTo')} /> + +
+ { this.state.subscribedChannels.map((item, i) =>

{item}

) } +
+

messages received:

+
+ { this.state.messageList.map((item, i) =>

{item}

) } +
+
+
+ +

Send Message

+
+ + this.handleChange(e, 'channel')} /> + this.handleChange(e, 'message')} /> + + +
+ +

Javascript calls being made:

+
+

EmbarkJS.Messages.setProvider('whisper')

+ { + this.state.logs.map((item, i) =>

{item}

) + } +
+
+ ); + } +} + +export default Whisper; diff --git a/templates/demo/app/dapp.css b/templates/demo/app/dapp.css index e0043e37..3d355697 100644 --- a/templates/demo/app/dapp.css +++ b/templates/demo/app/dapp.css @@ -47,3 +47,7 @@ div { -webkit-border-radius: 10px; border-radius: 10px; } + +input.form-control { + margin-right: 5px; +} \ No newline at end of file diff --git a/templates/demo/app/dapp.js b/templates/demo/app/dapp.js index a815d5fa..5c5f121a 100644 --- a/templates/demo/app/dapp.js +++ b/templates/demo/app/dapp.js @@ -1,161 +1,75 @@ -/*globals $, SimpleStorage, document*/ +import React from 'react'; +import ReactDOM from 'react-dom'; +import { Tabs, Tab } from 'react-bootstrap'; -import $ from 'jquery'; -import 'bootstrap'; -import 'bootstrap/dist/css/bootstrap.min.css'; import EmbarkJS from 'Embark/EmbarkJS'; -import SimpleStorage from 'Embark/contracts/SimpleStorage'; +import Blockchain from './components/blockchain'; +import Whisper from './components/whisper'; +import Storage from './components/storage'; import './dapp.css'; -var addToLog = function(id, txt) { - $(id + " .logs").append("
" + txt); -}; +class App extends React.Component { -// =========================== -// Blockchain example -// =========================== -$(document).ready(function() { + constructor(props) { + super(props); - $("#blockchain button.set").click(function() { - var value = parseInt($("#blockchain input.text").val(), 10); - - // If web3.js 1.0 is being used - if (EmbarkJS.isNewWeb3()) { - SimpleStorage.methods.set(value).send({from: web3.eth.defaultAccount}); - addToLog("#blockchain", "SimpleStorage.methods.set(value).send({from: web3.eth.defaultAccount})"); - } else { - SimpleStorage.set(value); - addToLog("#blockchain", "SimpleStorage.set(" + value + ")"); + this.state = { + whisperEnabled: false, + storageEnabled: false } + } - }); - - $("#blockchain button.get").click(function() { - // If web3.js 1.0 is being used - if (EmbarkJS.isNewWeb3()) { - SimpleStorage.methods.get().call(function(err, value) { - $("#blockchain .value").html(value); - }); - addToLog("#blockchain", "SimpleStorage.methods.get(console.log)"); - } else { - SimpleStorage.get().then(function(value) { - $("#blockchain .value").html(value.toNumber()); - }); - addToLog("#blockchain", "SimpleStorage.get()"); - } - }); - -}); - -// =========================== -// Storage (IPFS) example -// =========================== -$(document).ready(function() { - // automatic set if config/storage.json has "enabled": true and "provider": "ipfs" - //EmbarkJS.Storage.setProvider('ipfs',{server: 'localhost', port: '5001'}); - - $("#storage .error").hide(); - //EmbarkJS.Storage.ipfsConnection.version() - // .then(function(){ - $("#status-storage").addClass('status-online'); - $("#storage-controls").show(); - // }) - // .catch(function(err) { - // if(err){ - // console.log("IPFS Connection Error => " + err.message); - // $("#storage .error").show(); - // $("#status-storage").addClass('status-offline'); - // $("#storage-controls").hide(); - // } - // }); - - $("#storage button.setIpfsText").click(function() { - var value = $("#storage input.ipfsText").val(); - EmbarkJS.Storage.saveText(value).then(function(hash) { - $("span.textHash").html(hash); - $("input.textHash").val(hash); - addToLog("#storage", "EmbarkJS.Storage.saveText('" + value + "').then(function(hash) { })"); - }) - .catch(function(err) { - if(err){ - console.log("IPFS saveText Error => " + err.message); - } - }); - }); - - $("#storage button.loadIpfsHash").click(function() { - var value = $("#storage input.textHash").val(); - EmbarkJS.Storage.get(value).then(function(content) { - $("span.ipfsText").html(content); - addToLog("#storage", "EmbarkJS.Storage.get('" + value + "').then(function(content) { })"); - }) - .catch(function(err) { - if(err){ - console.log("IPFS get Error => " + err.message); - } - }); - }); - - $("#storage button.uploadFile").click(function() { - var input = $("#storage input[type=file]"); - EmbarkJS.Storage.uploadFile(input).then(function(hash) { - $("span.fileIpfsHash").html(hash); - $("input.fileIpfsHash").val(hash); - addToLog("#storage", "EmbarkJS.Storage.uploadFile($('input[type=file]')).then(function(hash) { })"); - }) - .catch(function(err) { - if(err){ - console.log("IPFS uploadFile Error => " + err.message); - } - }); - }); - - $("#storage button.loadIpfsFile").click(function() { - var hash = $("#storage input.fileIpfsHash").val(); - var url = EmbarkJS.Storage.getUrl(hash); - var link = '' + url + ''; - $("span.ipfsFileUrl").html(link); - $(".ipfsImage").attr('src', url); - addToLog("#storage", "EmbarkJS.Storage.getUrl('" + hash + "')"); - }); - -}); - -// =========================== -// Communication (Whisper) example -// =========================== -$(document).ready(function() { - - $("#communication .error").hide(); - $("#communication .errorVersion").hide(); - if (EmbarkJS.Messages.providerName === 'whisper') { - EmbarkJS.Messages.getWhisperVersion(function(err, version) { - if (err) { - $("#communication .error").show(); - $("#communication-controls").hide(); - $("#status-communication").addClass('status-offline'); + componentDidMount(){ + __embarkContext.execWhenReady(() => { + if (EmbarkJS.isNewWeb3()) { + EmbarkJS.Messages.Providers.whisper.getWhisperVersion((err, version) => { + if(!err) + this.setState({whisperEnabled: true}) + else + console.log(err); + }); } else { - EmbarkJS.Messages.setProvider('whisper'); - $("#status-communication").addClass('status-online'); + if (EmbarkJS.Messages.providerName === 'whisper') { + EmbarkJS.Messages.getWhisperVersion((err, version) => { + if(!err) + this.setState({whisperEnabled: true}) + else + console.log(err); + }); + } } + + this.setState({ + storageEnabled: true + }); }); } - $("#communication button.listenToChannel").click(function() { - var channel = $("#communication .listen input.channel").val(); - $("#communication #subscribeList").append("
subscribed to " + channel + " now try sending a message"); - EmbarkJS.Messages.listenTo({topic: [channel]}).then(function(message) { - $("#communication #messagesList").append("
channel: " + channel + " message: " + message); - }); - addToLog("#communication", "EmbarkJS.Messages.listenTo({topic: ['" + channel + "']}).then(function(message) {})"); - }); - $("#communication button.sendMessage").click(function() { - var channel = $("#communication .send input.channel").val(); - var message = $("#communication .send input.message").val(); - EmbarkJS.Messages.sendMessage({topic: channel, data: message}); - addToLog("#communication", "EmbarkJS.Messages.sendMessage({topic: '" + channel + "', data: '" + message + "'})"); - }); + _renderStatus(title, available){ + let className = available ? 'pull-right status-online' : 'pull-right status-offline'; + return + {title} + + ; + } -}); + render(){ + return (

Embark - Usage Example

+ + + + + + + + + + + +
); + } +} + +ReactDOM.render(, document.getElementById('app')); diff --git a/templates/demo/app/index.html b/templates/demo/app/index.html index 0b17e193..55521af6 100644 --- a/templates/demo/app/index.html +++ b/templates/demo/app/index.html @@ -1,107 +1,12 @@ Embark - SimpleStorage Demo - - + + -

Embark - Usage Example

- - - -
-
-

1. Set the value in the blockchain

-
- - -

Once you set the value, the transaction will need to be mined and then the value will be updated on the blockchain.

-
- -

2. Get the current value

-
-
- current value is -
- -

Click the button to get the current value. The initial value is 100.

-
- -

3. Contract Calls

-

Javascript calls being made:

-
-
+
-
- -
- -

Save text to IPFS

-
- - -

generated Hash:

-
- -

Load text from IPFS given an hash

-
- - -

result:

-
- -

upload file to ipfs

-
- - -

generated hash:

-
- -

Get file or image from ipfs

-
- - -

file available at:

-

-
- -

Javascript calls being made:

-
-
EmbarkJS.Storage.setProvider('ipfs',{server: 'localhost', port: '5001'}) -
-
-
-
- - -
-

Listen To channel

-
- - -
-

messages received:

-

-
- -

Send Message

-
- - - -
- -

Javascript calls being made:

-
-
EmbarkJS.Messages.setProvider('whisper') -
-
-
-
- + diff --git a/templates/demo/config/blockchain.json b/templates/demo/config/blockchain.json index 9dccb92f..638c8167 100644 --- a/templates/demo/config/blockchain.json +++ b/templates/demo/config/blockchain.json @@ -9,12 +9,12 @@ "maxpeers": 0, "rpcHost": "localhost", "rpcPort": 8545, - "rpcCorsDomain": "http://localhost:8000", + "rpcCorsDomain": "auto", "account": { "password": "config/development/password" }, "targetGasLimit": 8000000, - "wsOrigins": "http://localhost:8000", + "wsOrigins": "auto", "wsRPC": true, "wsHost": "localhost", "wsPort": 8546, diff --git a/templates/demo/package.json b/templates/demo/package.json index c3224ae9..c60b7143 100644 --- a/templates/demo/package.json +++ b/templates/demo/package.json @@ -9,8 +9,9 @@ "author": "", "license": "ISC", "homepage": "", - "devDependencies": { - "bootstrap": "^3.3.6", - "jquery": "^1.11.3" + "dependencies": { + "react": "^16.3.2", + "react-bootstrap": "^0.32.1", + "react-dom": "^16.3.2" } } diff --git a/test/config.js b/test/config.js index 75aa7957..5921bd0e 100644 --- a/test/config.js +++ b/test/config.js @@ -3,11 +3,13 @@ const Config = require('../lib/core/config.js'); const Plugins = require('../lib/core/plugins.js'); const assert = require('assert'); const TestLogger = require('../lib/tests/test_logger.js'); +const Events = require('../lib/core/events'); describe('embark.Config', function () { let config = new Config({ env: 'myenv', - configDir: './test/test1/config/' + configDir: './test/test1/config/', + events: new Events() }); config.plugins = new Plugins({plugins: {}}); config.logger = new TestLogger({}); diff --git a/test/contracts.js b/test/contracts.js index 466ed101..229aa0f2 100644 --- a/test/contracts.js +++ b/test/contracts.js @@ -3,6 +3,7 @@ let ContractsManager = require('../lib/contracts/contracts.js'); let Logger = require('../lib/core/logger.js'); let File = require('../lib/core/file.js'); let TestLogger = require('../lib/tests/test_logger.js'); +let Events = require('../lib/core/events'); let assert = require('assert'); //let SolidityCompiler = require('../lib/modules/solidity'); @@ -55,7 +56,8 @@ describe('embark.Contracts', function() { } } }, - logger: new Logger({}) + logger: new Logger({}), + events: new Events() }); describe('#build', function() { @@ -146,7 +148,8 @@ describe('embark.Contracts', function() { } } }, - logger: new Logger({}) + logger: new Logger({}), + events: new Events() }); describe('#build', function() { diff --git a/test_apps/contracts_app/blockchain.json b/test_apps/contracts_app/blockchain.json index 8c3790a6..35edfb43 100644 --- a/test_apps/contracts_app/blockchain.json +++ b/test_apps/contracts_app/blockchain.json @@ -9,12 +9,12 @@ "maxpeers": 0, "rpcHost": "localhost", "rpcPort": 8545, - "rpcCorsDomain": "http://localhost:8000", + "rpcCorsDomain": "auto", "account": { "password": "development/password" }, "targetGasLimit": 8000000, - "wsOrigins": "http://localhost:8000", + "wsOrigins": "auto", "wsRPC": true, "wsHost": "localhost", "wsPort": 8546 diff --git a/test_apps/test_app/config/blockchain.json b/test_apps/test_app/config/blockchain.json index 41400449..6acbdfd5 100644 --- a/test_apps/test_app/config/blockchain.json +++ b/test_apps/test_app/config/blockchain.json @@ -9,12 +9,12 @@ "maxpeers": 0, "rpcHost": "localhost", "rpcPort": 8545, - "rpcCorsDomain": "http://localhost:8000", + "rpcCorsDomain": "auto", "account": { "password": "config/development/password" }, "targetGasLimit": 8000000, - "wsOrigins": "http://localhost:8000", + "wsOrigins": "auto", "wsRPC": true, "wsHost": "localhost", "wsPort": 8546 diff --git a/test_apps/test_app/config/storage.json b/test_apps/test_app/config/storage.json index c1edf6d3..55eb593a 100644 --- a/test_apps/test_app/config/storage.json +++ b/test_apps/test_app/config/storage.json @@ -1,7 +1,7 @@ { "default": { "enabled": true, - "available_providers": ["ipfs"], + "available_providers": ["ipfs", "swarm"], "ipfs_bin": "ipfs", "provider": "ipfs", "host": "localhost", @@ -9,10 +9,10 @@ }, "development": { "enabled": true, - "provider": "ipfs", - "host": "localhost", - "port": 5001, - "getUrl": "http://localhost:8080/ipfs/" + "provider": "swarm", + "host": "swarm-gateways.net", + "port": 80, + "getUrl": "http://swarm-gateways.net/bzzr:/" }, "livenet": { "enabled": true, diff --git a/test_apps/test_app/extensions/embark-service/contracts/pluginSimpleStorage.sol b/test_apps/test_app/extensions/embark-service/contracts/pluginSimpleStorage.sol new file mode 100644 index 00000000..4d01d6b3 --- /dev/null +++ b/test_apps/test_app/extensions/embark-service/contracts/pluginSimpleStorage.sol @@ -0,0 +1,10 @@ +pragma solidity ^0.4.18; +contract PluginStorage { + address public simpleStorageAddress; + address simpleStorageAddress2; + + function PluginStorage(address addr) public { + simpleStorageAddress = addr; + } + +} diff --git a/test_apps/test_app/extensions/embark-service/fileInPipeline.js b/test_apps/test_app/extensions/embark-service/fileInPipeline.js new file mode 100644 index 00000000..85f76853 --- /dev/null +++ b/test_apps/test_app/extensions/embark-service/fileInPipeline.js @@ -0,0 +1 @@ +console.log('File added to the pipeline using embark.addFileToPipeline'); diff --git a/test_apps/test_app/extensions/embark-service/index.js b/test_apps/test_app/extensions/embark-service/index.js index 0ca3ff1d..fb5a56bd 100644 --- a/test_apps/test_app/extensions/embark-service/index.js +++ b/test_apps/test_app/extensions/embark-service/index.js @@ -1,12 +1,47 @@ -var Haml = require('haml'); +const Haml = require('haml'); -module.exports = function(embark) { - embark.registerServiceCheck('PluginService', function(cb) { +module.exports = function (embark) { + embark.registerServiceCheck('PluginService', function (cb) { cb({name: "ServiceName", status: "on"}); }); - embark.registerPipeline((embark.pluginConfig.files || ['**/*.haml']), function(opts) { - var source = opts.source; - return Haml.render(source); + embark.registerPipeline((embark.pluginConfig.files || ['**/*.haml']), function (opts) { + return Haml.render(opts.source); }); + + embark.registerContractConfiguration({ + "default": { + "contracts": { + "PluginStorage": { + "args": ["$SimpleStorage"] + } + } + } + }); + embark.addContractFile("./contracts/pluginSimpleStorage.sol"); + + embark.addFileToPipeline('./fileInPipeline.js'); + embark.addFileToPipeline('./fileInPipeline.js', 'js/fileInPipeline.js'); + + embark.registerBeforeDeploy(function (options, callback) { + // Just calling register to prove it works. We don't actually want to change the contracts + callback({contractCode: options.contract.code}); + }); + + embark.registerClientWeb3Provider(function(options) { + return "web3 = new Web3(new Web3.providers.HttpProvider('http://" + options.rpcHost + ":" + options.rpcPort + "'));"; + }); + + embark.registerConsoleCommand((cmd) => { + if (cmd === "hello") { + return "hello there!"; + } + // continue to embark or next plugin; + return false; + }); + + embark.events.on("contractsDeployed", function() { + embark.logger.info("plugin says: your contracts have been deployed"); + }); + }; diff --git a/test_apps/test_app/package.json b/test_apps/test_app/package.json index 8711dde1..b29e3d6c 100644 --- a/test_apps/test_app/package.json +++ b/test_apps/test_app/package.json @@ -14,11 +14,11 @@ }, "dependencies": { "bootstrap": "^3.3.6", - "embark-service": "./extensions/embark-service", + "embark-service": "file:extensions/embark-service", "jquery": "^1.11.3", "react": "^16.0.0", "react-bootstrap": "^0.32.0", "react-dom": "^16.2.0", - "zeppelin-solidity": "^1.8.0" + "zeppelin-solidity": "1.8.0" } } diff --git a/test_apps/test_app/test/plugin_storage_spec.js b/test_apps/test_app/test/plugin_storage_spec.js new file mode 100644 index 00000000..24a58c4e --- /dev/null +++ b/test_apps/test_app/test/plugin_storage_spec.js @@ -0,0 +1,26 @@ +/*global contract, before, EmbarkSpec, PluginStorage, SimpleStorage, it*/ +const assert = require('assert'); + +contract("PluginSimpleStorage", function () { + this.timeout(0); + + before((done) => { + const contractsConfig = { + "SimpleStorage": { + args: [100] + }, + "PluginStorage": { + args: ["$SimpleStorage"] + } + }; + EmbarkSpec.deployAll(contractsConfig, () => { + done(); + }); + }); + + it("set SimpleStorage address", async function () { + let result = await PluginStorage.methods.simpleStorageAddress().call(); + assert.equal(result.toString(), SimpleStorage.options.address); + }); + +}); diff --git a/test_apps/test_app/test/token_spec.js b/test_apps/test_app/test/token_spec.js index c76728c0..88dfc1a8 100644 --- a/test_apps/test_app/test/token_spec.js +++ b/test_apps/test_app/test/token_spec.js @@ -13,8 +13,6 @@ describe("Token", function() { var contractsConfig = { "ZAMyLib": { }, - "Token": { - }, "SimpleStorage": { args: [100] }, From 72cce7d4d2d1a860331d99a334eb25b40ed6c88f Mon Sep 17 00:00:00 2001 From: emizzle Date: Mon, 30 Apr 2018 22:07:37 +1000 Subject: [PATCH 2/4] Fixes to make lint and tests happy --- lib/modules/swarm/embarkjs.js | 1 + test/config.js | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/modules/swarm/embarkjs.js b/lib/modules/swarm/embarkjs.js index 1b780e8e..37e4924e 100644 --- a/lib/modules/swarm/embarkjs.js +++ b/lib/modules/swarm/embarkjs.js @@ -1,3 +1,4 @@ +/*global web3 */ let __embarkSwarm = {}; const bytes = require("eth-lib/lib/bytes"); diff --git a/test/config.js b/test/config.js index 5921bd0e..27423873 100644 --- a/test/config.js +++ b/test/config.js @@ -27,6 +27,7 @@ describe('embark.Config', function () { "rpcHost": "localhost", "rpcPort": 8545, "rpcCorsDomain": "http://localhost:8000", + "wsOrigins": "auto", "account": { "password": "config/development/password" } From 2ad852667ef68f2c0c14a9436add1bb981f4ca5d Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Tue, 1 May 2018 09:38:13 -0400 Subject: [PATCH 3/4] add early returns and lint --- lib/index.js | 23 ++++++------- lib/modules/ipfs/embarkjs.js | 38 ++++++++++++--------- lib/modules/swarm/embarkjs.js | 38 +++++++++++++-------- lib/modules/whisper/js/embarkjs.js | 37 ++++++++++++-------- lib/modules/whisper/js/embarkjs_old_web3.js | 29 +++++++++------- package-lock.json | 17 +++++---- 6 files changed, 108 insertions(+), 74 deletions(-) diff --git a/lib/index.js b/lib/index.js index 2c5d6e24..2e81f94d 100644 --- a/lib/index.js +++ b/lib/index.js @@ -323,16 +323,15 @@ class Embark { return true; } }); - if(!checkFn || typeof checkFn.fn !== 'function') callback(); - else{ - checkFn.fn(function(serviceCheckResult){ - if(!serviceCheckResult.status || serviceCheckResult.status === 'off'){ - callback({message:`Cannot upload: ${platform} node is not running on http://${engine.config.storageConfig.host}:${engine.config.storageConfig.port}.`}); - } else { - callback(null); - } - }); + if (!checkFn || typeof checkFn.fn !== 'function') { + return callback(); } + checkFn.fn(function (serviceCheckResult) { + if (!serviceCheckResult.status || serviceCheckResult.status === 'off') { + return callback({message: `Cannot upload: ${platform} node is not running on http://${engine.config.storageConfig.host}:${engine.config.storageConfig.port}.`}); + } + callback(); + }); }, function setupStoragePlugin(callback){ let pluginList = engine.plugins.listPlugins(); @@ -352,9 +351,9 @@ class Embark { } if (!cmdPlugin) { engine.logger.info('try "embark upload ipfs" or "embark upload swarm"'.green); - callback({message: 'unknown platform: ' + platform}); - } - else callback(null); + return callback({message: 'unknown platform: ' + platform}); + } + callback(); }, function deploy(callback) { // 2. upload to storage (outputDone event triggered after webpack finished) diff --git a/lib/modules/ipfs/embarkjs.js b/lib/modules/ipfs/embarkjs.js index da317811..1c374cb5 100644 --- a/lib/modules/ipfs/embarkjs.js +++ b/lib/modules/ipfs/embarkjs.js @@ -2,9 +2,9 @@ import IpfsApi from 'ipfs-api'; let __embarkIPFS = {}; -__embarkIPFS.setProvider = function(options) { +__embarkIPFS.setProvider = function (options) { var self = this; - var promise = new Promise(function(resolve, reject) { + var promise = new Promise(function (resolve, reject) { try { if (options === undefined) { self.ipfsConnection = IpfsApi('localhost', '5001'); @@ -30,14 +30,14 @@ __embarkIPFS.setProvider = function(options) { return promise; }; -__embarkIPFS.saveText = function(text) { +__embarkIPFS.saveText = function (text) { const self = this; - var promise = new Promise(function(resolve, reject) { + var promise = new Promise(function (resolve, reject) { if (!self.ipfsConnection) { var connectionError = new Error('No IPFS connection. Please ensure to call Embark.Storage.setProvider()'); reject(connectionError); } - self.ipfsConnection.add(self.ipfsConnection.Buffer.from(text), function(err, result) { + self.ipfsConnection.add(self.ipfsConnection.Buffer.from(text), function (err, result) { if (err) { reject(err); } else { @@ -49,11 +49,11 @@ __embarkIPFS.saveText = function(text) { return promise; }; -__embarkIPFS.get = function(hash) { +__embarkIPFS.get = function (hash) { const self = this; // TODO: detect type, then convert if needed //var ipfsHash = web3.toAscii(hash); - var promise = new Promise(function(resolve, reject) { + var promise = new Promise(function (resolve, reject) { if (!self.ipfsConnection) { var connectionError = new Error('No IPFS connection. Please ensure to call Embark.Storage.setProvider()'); reject(connectionError); @@ -69,7 +69,7 @@ __embarkIPFS.get = function(hash) { return promise; }; -__embarkIPFS.uploadFile = function(inputSelector) { +__embarkIPFS.uploadFile = function (inputSelector) { const self = this; var file = inputSelector[0].files[0]; @@ -77,16 +77,16 @@ __embarkIPFS.uploadFile = function(inputSelector) { throw new Error('no file found'); } - var promise = new Promise(function(resolve, reject) { + var promise = new Promise(function (resolve, reject) { if (!self.ipfsConnection) { var connectionError = new Error('No IPFS connection. Please ensure to call Embark.Storage.setProvider()'); reject(connectionError); } var reader = new FileReader(); - reader.onloadend = function() { + reader.onloadend = function () { var fileContent = reader.result; var buffer = self.ipfsConnection.Buffer.from(fileContent); - self.ipfsConnection.add(buffer, function(err, result) { + self.ipfsConnection.add(buffer, function (err, result) { if (err) { reject(err); } else { @@ -100,16 +100,22 @@ __embarkIPFS.uploadFile = function(inputSelector) { return promise; }; -__embarkIPFS.isAvailable = function(){ +__embarkIPFS.isAvailable = function () { return new Promise((resolve) => { - if(!this.ipfsConnection) resolve(false); + if (!this.ipfsConnection) { + return resolve(false); + } this.ipfsConnection.id() - .then((id) => { resolve(Boolean(id)); }) - .catch(() => { resolve(false); }); + .then((id) => { + resolve(Boolean(id)); + }) + .catch(() => { + resolve(false); + }); }); }; -__embarkIPFS.getUrl = function(hash) { +__embarkIPFS.getUrl = function (hash) { return (this._getUrl || "http://localhost:8080/ipfs/") + hash; }; diff --git a/lib/modules/swarm/embarkjs.js b/lib/modules/swarm/embarkjs.js index 37e4924e..f46b8681 100644 --- a/lib/modules/swarm/embarkjs.js +++ b/lib/modules/swarm/embarkjs.js @@ -2,7 +2,7 @@ let __embarkSwarm = {}; const bytes = require("eth-lib/lib/bytes"); -__embarkSwarm.setProvider = function(options) { +__embarkSwarm.setProvider = function (options) { this.bzz = web3.bzz; this.protocol = options.protocol; this.host = options.host; @@ -13,7 +13,7 @@ __embarkSwarm.setProvider = function(options) { var promise = new Promise((resolve, reject) => { try { - if(!this.bzz.currentProvider) { + if (!this.bzz.currentProvider) { this.bzz.setProvider(`${options.protocol}://${options.host}:${options.port}`); } resolve(this); @@ -25,19 +25,25 @@ __embarkSwarm.setProvider = function(options) { return promise; }; -__embarkSwarm.isAvailable = function(){ +__embarkSwarm.isAvailable = function () { return new Promise((resolve, reject) => { - if(!this.bzz) resolve(false); + if (!this.bzz) { + return resolve(false); + } this.bzz.isAvailable() .then(resolve) - .catch(() => { reject(this.connectError); }); + .catch(() => { + reject(this.connectError); + }); }); }; -__embarkSwarm.saveText = function(text) { +__embarkSwarm.saveText = function (text) { return new Promise((resolve, reject) => { this.isAvailable().then((isAvailable) => { - if(!isAvailable) reject(this.connectError); + if (!isAvailable) { + return reject(this.connectError); + } this.bzz.upload(text) .then(resolve) .catch(reject); @@ -45,10 +51,12 @@ __embarkSwarm.saveText = function(text) { }); }; -__embarkSwarm.get = function(hash) { +__embarkSwarm.get = function (hash) { return new Promise((resolve, reject) => { this.isAvailable().then((isAvailable) => { - if(!isAvailable) reject(this.connectError); + if (!isAvailable) { + return reject(this.connectError); + } this.bzz.download(hash) .then((uint8Array) => resolve(bytes.toString(bytes.fromUint8Array(uint8Array)))) .catch(reject); @@ -56,7 +64,7 @@ __embarkSwarm.get = function(hash) { }); }; -__embarkSwarm.uploadFile = function(inputSelector) { +__embarkSwarm.uploadFile = function (inputSelector) { let file = inputSelector[0].files[0]; if (file === undefined) { @@ -68,10 +76,12 @@ __embarkSwarm.uploadFile = function(inputSelector) { reader.onloadend = (event) => { var fileContent = new Uint8Array(event.target.result); this.isAvailable().then((isAvailable) => { - if(!isAvailable) reject(this.connectError); + if (!isAvailable) { + return reject(this.connectError); + } this.bzz.upload(fileContent) - .then(resolve) - .catch(reject); + .then(resolve) + .catch(reject); }).catch(reject); }; reader.onerror = reject; @@ -79,7 +89,7 @@ __embarkSwarm.uploadFile = function(inputSelector) { }); }; -__embarkSwarm.getUrl = function(hash) { +__embarkSwarm.getUrl = function (hash) { return this._getUrl + hash; }; diff --git a/lib/modules/whisper/js/embarkjs.js b/lib/modules/whisper/js/embarkjs.js index 2fab5d27..27bd1f7b 100644 --- a/lib/modules/whisper/js/embarkjs.js +++ b/lib/modules/whisper/js/embarkjs.js @@ -3,7 +3,7 @@ // for the whisper v5 and web3.js 1.0 let __embarkWhisperNewWeb3 = {}; -__embarkWhisperNewWeb3.setProvider = function(options) { +__embarkWhisperNewWeb3.setProvider = function (options) { const self = this; let provider; if (options === undefined) { @@ -13,12 +13,16 @@ __embarkWhisperNewWeb3.setProvider = function(options) { } // TODO: take into account type self.web3 = new Web3(new Web3.providers.WebsocketProvider("ws://" + provider)); - self.getWhisperVersion(function(err, version) { + self.getWhisperVersion(function (err, version) { if (err) { console.log("whisper not available"); } else if (version >= 5) { - self.web3.shh.newSymKey().then((id) => { self.symKeyID = id; }); - self.web3.shh.newKeyPair().then((id) => { self.sig = id; }); + self.web3.shh.newSymKey().then((id) => { + self.symKeyID = id; + }); + self.web3.shh.newKeyPair().then((id) => { + self.sig = id; + }); } else { throw new Error("version of whisper not supported"); } @@ -26,7 +30,7 @@ __embarkWhisperNewWeb3.setProvider = function(options) { }); }; -__embarkWhisperNewWeb3.sendMessage = function(options) { +__embarkWhisperNewWeb3.sendMessage = function (options) { var topics, data, ttl, payload; topics = options.topic || options.topics; data = options.data || options.payload; @@ -56,10 +60,11 @@ __embarkWhisperNewWeb3.sendMessage = function(options) { powTarget: powTarget }; - this.web3.shh.post(message, function() { }); + this.web3.shh.post(message, function () { + }); }; -__embarkWhisperNewWeb3.listenTo = function(options) { +__embarkWhisperNewWeb3.listenTo = function (options) { var topics = options.topic || options.topics; let promise = new __MessageEvents(); @@ -73,7 +78,7 @@ __embarkWhisperNewWeb3.listenTo = function(options) { let filter = this.web3.shh.subscribe("messages", { symKeyID: this.symKeyID, topics: topics - }).on('data', function(result) { + }).on('data', function (result) { var payload = JSON.parse(EmbarkJS.Utils.toAscii(result.payload)); var data; data = { @@ -91,21 +96,25 @@ __embarkWhisperNewWeb3.listenTo = function(options) { return promise; }; -__embarkWhisperNewWeb3.getWhisperVersion = function(cb) { - this.web3.shh.getVersion(function(err, version) { +__embarkWhisperNewWeb3.getWhisperVersion = function (cb) { + this.web3.shh.getVersion(function (err, version) { cb(err, version); }); }; -__embarkWhisperNewWeb3.isAvailable = function(){ +__embarkWhisperNewWeb3.isAvailable = function () { return new Promise((resolve, reject) => { - if(!this.web3.shh) resolve(false); - try{ + if (!this.web3.shh) { + return resolve(false); + } + try { this.getWhisperVersion((err) => { resolve(Boolean(!err)); }); } - catch(err){ reject(err); } + catch (err) { + reject(err); + } }); }; diff --git a/lib/modules/whisper/js/embarkjs_old_web3.js b/lib/modules/whisper/js/embarkjs_old_web3.js index e4769768..4112d58c 100644 --- a/lib/modules/whisper/js/embarkjs_old_web3.js +++ b/lib/modules/whisper/js/embarkjs_old_web3.js @@ -3,7 +3,7 @@ // for the old version of whisper and web3.js let __embarkWhisperOld = {}; -__embarkWhisperOld.setProvider = function(options) { +__embarkWhisperOld.setProvider = function (options) { const self = this; let provider; if (options === undefined) { @@ -12,7 +12,7 @@ __embarkWhisperOld.setProvider = function(options) { provider = options.server + ':' + options.port; } self.web3 = new Web3(new Web3.providers.HttpProvider("http://" + provider)); - self.getWhisperVersion(function(err, version) { + self.getWhisperVersion(function (err, version) { if (err) { console.log("whisper not available"); } else if (version >= 5) { @@ -24,7 +24,7 @@ __embarkWhisperOld.setProvider = function(options) { }); }; -__embarkWhisperOld.sendMessage = function(options) { +__embarkWhisperOld.sendMessage = function (options) { var topics, data, ttl, priority, payload; topics = options.topic || options.topics; data = options.data || options.payload; @@ -59,10 +59,11 @@ __embarkWhisperOld.sendMessage = function(options) { priority: priority }; - return this.web3.shh.post(message, function() { }); + return this.web3.shh.post(message, function () { + }); }; -__embarkWhisperOld.listenTo = function(options) { +__embarkWhisperOld.listenTo = function (options) { var topics, _topics; topics = options.topic || options.topics; _topics = []; @@ -80,7 +81,7 @@ __embarkWhisperOld.listenTo = function(options) { let promise = new __MessageEvents(); - let filter = this.web3.shh.filter(filterOptions, function(err, result) { + let filter = this.web3.shh.filter(filterOptions, function (err, result) { var payload = JSON.parse(EmbarkJS.Utils.toAscii(result.payload)); var data; if (err) { @@ -101,20 +102,24 @@ __embarkWhisperOld.listenTo = function(options) { return promise; }; -__embarkWhisperOld.getWhisperVersion = function(cb) { - this.web3.version.getWhisper(function(err, _res) { +__embarkWhisperOld.getWhisperVersion = function (cb) { + this.web3.version.getWhisper(function (err, _res) { cb(err, self.web3.version.whisper); }); }; -__embarkWhisperOld.isAvailable = function(){ +__embarkWhisperOld.isAvailable = function () { return new Promise((resolve, reject) => { - if(!this.web3) resolve(false); - try{ + if (!this.web3) { + return resolve(false); + } + try { this.getWhisperVersion((err) => { resolve(Boolean(!err)); }); } - catch(err){ reject(err); } + catch (err) { + reject(err); + } }); }; diff --git a/package-lock.json b/package-lock.json index 58672383..96e06f95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6025,7 +6025,7 @@ "lockfile": "1.0.4", "node-fetch": "2.1.2", "semver": "5.5.0", - "tar": "4.4.1", + "tar": "4.4.2", "url-join": "4.0.0" }, "dependencies": { @@ -6060,21 +6060,26 @@ "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz", "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", "requires": { - "safe-buffer": "5.1.1", + "safe-buffer": "5.1.2", "yallist": "3.0.2" } }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "tar": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.1.tgz", - "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.2.tgz", + "integrity": "sha512-BfkE9CciGGgDsATqkikUHrQrraBCO+ke/1f6SFAEMnxyyfN9lxC+nW1NFWMpqH865DhHIy9vQi682gk1X7friw==", "requires": { "chownr": "1.0.1", "fs-minipass": "1.2.5", "minipass": "2.2.4", "minizlib": "1.1.0", "mkdirp": "0.5.1", - "safe-buffer": "5.1.1", + "safe-buffer": "5.1.2", "yallist": "3.0.2" } }, From 3bf5093f1b3ef3f792944cbbae5b794abb6461a0 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Tue, 1 May 2018 10:20:27 -0400 Subject: [PATCH 4/4] more linting and add condition in case of no hash --- lib/modules/swarm/embarkjs.js | 7 +++---- lib/modules/swarm/upload.js | 7 +++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/lib/modules/swarm/embarkjs.js b/lib/modules/swarm/embarkjs.js index f46b8681..9a415258 100644 --- a/lib/modules/swarm/embarkjs.js +++ b/lib/modules/swarm/embarkjs.js @@ -11,7 +11,7 @@ __embarkSwarm.setProvider = function (options) { this.connectError = new Error(`Cannot connect to Swarm node on ${this.connectUrl}`); this._getUrl = options.getUrl || `${this.connectUrl}/bzzr:/`; - var promise = new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { try { if (!this.bzz.currentProvider) { this.bzz.setProvider(`${options.protocol}://${options.host}:${options.port}`); @@ -22,7 +22,6 @@ __embarkSwarm.setProvider = function (options) { reject(this.connectError); } }); - return promise; }; __embarkSwarm.isAvailable = function () { @@ -72,9 +71,9 @@ __embarkSwarm.uploadFile = function (inputSelector) { } return new Promise((resolve, reject) => { - var reader = new FileReader(); + const reader = new FileReader(); reader.onloadend = (event) => { - var fileContent = new Uint8Array(event.target.result); + const fileContent = new Uint8Array(event.target.result); this.isAvailable().then((isAvailable) => { if (!isAvailable) { return reject(this.connectError); diff --git a/lib/modules/swarm/upload.js b/lib/modules/swarm/upload.js index 0c00aad8..fbe64924 100644 --- a/lib/modules/swarm/upload.js +++ b/lib/modules/swarm/upload.js @@ -28,6 +28,9 @@ class Swarm { .catch(callback); }, function printUrls(dir_hash, callback) { + if (!dir_hash) { + return callback('No directory hash was returned'); + } console.log((`=== DApp available at ${self.storageConfig.getUrl}${dir_hash}/`).green); callback(); @@ -36,9 +39,9 @@ class Swarm { if (err) { console.log("error uploading to swarm".red); console.log(err); - reject(err); + return reject(err); } - else resolve('successfully uploaded to swarm'); + resolve('successfully uploaded to swarm'); }); }); }