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 | 101 +++- 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 | 202 ++----- 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, 1441 insertions(+), 379 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 6498ac1baa..d8632b873c 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 b8313948f6..0ba8e156ba 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 e28e559c61..151b32673f 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 71cc1fbd8c..6366290d97 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 603e67113b..06d6a28c24 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 3072cd81be..6b8306aec8 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 fa474e5232..8699b842cc 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 ae291124ad..10f567085a 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 d1b87ade36..1551331c54 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 75e5b86f36..43e7160af8 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 da632e3fc8..8139e2be9d 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 e321a4be26..2c5d6e2437 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 c2e516e054..da31781112 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 6c9cd7a19f..36c65e4079 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 0000000000..1b780e8ed7 --- /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 b19bf9271e..07660f4b3d 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.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: options.buildDir || 'dist/', - storageConfig: options.storageConfig, - web3: options.web3 + buildDir: this.buildDir || 'dist/', + storageConfig: this.storageConfig, + bzz: this.bzz }); - embark.registerUploadCommand('swarm', this.upload_swarm.deploy.bind(this.upload_swarm)); + 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 26d11be109..0c00aad8ae 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 3abaacb114..2fab5d279c 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 2e0a1383b0..e476976835 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 a436b5bca0..8ece7a5650 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 d290081715..58672383ee 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 28aa1df62e..7efa9fbfdd 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 1d0e082098..afff2072cd 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 0000000000..b9e5e313c0 --- /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 0000000000..f6721453be --- /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 0000000000..be78c62e0b --- /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 e0043e37b4..3d355697a9 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 a815d5fa83..5c5f121aad 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); + componentDidMount(){ + __embarkContext.execWhenReady(() => { + if (EmbarkJS.isNewWeb3()) { + EmbarkJS.Messages.Providers.whisper.getWhisperVersion((err, version) => { + if(!err) + this.setState({whisperEnabled: true}) + else + console.log(err); + }); + } else { + if (EmbarkJS.Messages.providerName === 'whisper') { + EmbarkJS.Messages.getWhisperVersion((err, version) => { + if(!err) + this.setState({whisperEnabled: true}) + else + console.log(err); + }); + } } - }); - }); - $("#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); - } + this.setState({ + storageEnabled: true + }); }); - }); - - $("#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'); - } else { - EmbarkJS.Messages.setProvider('whisper'); - $("#status-communication").addClass('status-online'); - } - }); + _renderStatus(title, available){ + let className = available ? 'pull-right status-online' : 'pull-right status-offline'; + return + {title} + + ; } - $("#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 + "'})"); - }); + 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 0b17e193a6..55521af61d 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 9dccb92f34..638c816737 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 c3224ae9ed..c60b71434e 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 75aa795775..5921bd0e7d 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 466ed101cd..229aa0f265 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 8c3790a6fd..35edfb43f5 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 41400449a0..6acbdfd54f 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 c1edf6d3dd..55eb593a3d 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 0000000000..4d01d6b320 --- /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 0000000000..85f7685397 --- /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 0ca3ff1d5a..fb5a56bd45 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 8711dde1d8..b29e3d6ca8 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 0000000000..24a58c4e81 --- /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 c76728c048..88dfc1a87d 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 1b780e8ed7..37e4924e91 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 5921bd0e7d..2742387381 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 2c5d6e2437..2e81f94d08 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 da31781112..1c374cb5a9 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 37e4924e91..f46b8681db 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 2fab5d279c..27bd1f7b2f 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 e476976835..4112d58c65 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 58672383ee..96e06f9536 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 f46b8681db..9a415258aa 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 0c00aad8ae..fbe64924a0 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'); }); }); }