diff --git a/js/embark.js b/js/embark.js index 1b0b324f4..45d22c333 100644 --- a/js/embark.js +++ b/js/embark.js @@ -231,6 +231,9 @@ EmbarkJS.Storage.setProvider = function(provider, options) { }; EmbarkJS.Storage.isAvailable = function(){ + if (!this.currentStorage) { + throw new Error('Storage provider not set; e.g EmbarkJS.Storage.setProvider("ipfs")'); + } return this.currentStorage.isAvailable(); }; diff --git a/lib/cmd.js b/lib/cmd.js index 2550e48fa..0e5c51996 100644 --- a/lib/cmd.js +++ b/lib/cmd.js @@ -203,7 +203,7 @@ class Cmd { .option('--loglevel [loglevel]', __('level of logging to display') + ' ["error", "warn", "info", "debug", "trace"]', /^(error|warn|info|debug|trace)$/i, 'debug') .option('--locale [locale]', __('language to use (default: en)')) .option('-c, --client [client]', __('Use a specific ethereum client or simulator (supported: %s)', 'geth, testrpc')) - .description(__('Upload your dapp to a decentralized storage') + ' (e.g embark upload ipfs).') + .description(__('Upload your dapp to a decentralized storage') + '.') .action(function (env, _options) { i18n.setOrDetectLocale(_options.locale); _options.env = env || 'development'; diff --git a/lib/cmds/blockchain/blockchain.js b/lib/cmds/blockchain/blockchain.js index 0fe6a4905..213ac4fed 100644 --- a/lib/cmds/blockchain/blockchain.js +++ b/lib/cmds/blockchain/blockchain.js @@ -120,6 +120,7 @@ Blockchain.prototype.run = function() { return; } args = _.compact(args); + console.trace(`Geth command: ${cmd} ${args.join(' ')}`); self.child = child_process.spawn(cmd, args, {cwd: process.cwd()}); self.child.on('error', (err) => { diff --git a/lib/core/config.js b/lib/core/config.js index b7c2f74dd..6d88b1ab5 100644 --- a/lib/core/config.js +++ b/lib/core/config.js @@ -78,17 +78,27 @@ Config.prototype._updateBlockchainCors = function(){ let blockchainConfig = this.blockchainConfig; let storageConfig = this.storageConfig; let webServerConfig = this.webServerConfig; - let cors = ''; + let corsParts = []; if(webServerConfig && webServerConfig.enabled) { - let webServerPort = webServerConfig.port ? `:${webServerConfig.port}` : ''; - if(webServerConfig.host) cors = `http://${webServerConfig.host}${webServerPort}`; + if(webServerConfig.host) corsParts.push(utils.buildUrlFromConfig(webServerConfig)); } if(storageConfig && storageConfig.enabled) { - let storagePort = storageConfig.port ? `:${storageConfig.port}` : ''; - if(storageConfig.host) cors += `${cors.length ? ',' : ''}${storageConfig.protocol || 'http'}://${storageConfig.host}${storagePort}`; + // if getUrl is specified in the config, that needs to be included in cors + // instead of the concatenated protocol://host:port + if(storageConfig.upload.getUrl) { + // remove /ipfs or /bzz: from getUrl if it's there + let getUrlParts = storageConfig.upload.getUrl.split('/'); + getUrlParts = getUrlParts.slice(0, 3); + corsParts.push(getUrlParts.join('/')); + } + // use our modified getUrl or in case it wasn't specified, use a built url + else{ + corsParts.push(utils.buildUrlFromConfig(storageConfig.upload)); + } } + let cors = corsParts.join(','); if(blockchainConfig.rpcCorsDomain === 'auto' && cors.length) blockchainConfig.rpcCorsDomain = cors; if(blockchainConfig.wsOrigins === 'auto' && cors.length) blockchainConfig.wsOrigins = cors; }; @@ -209,7 +219,7 @@ Config.prototype.loadExternalContractsFiles = function() { }; Config.prototype.loadStorageConfigFile = function() { - var versions = utils.recursiveMerge({"ipfs-api": "17.2.4"}, this.embarkConfig.versions || {}); + var versions = utils.recursiveMerge({"ipfs-api": "17.2.4", "p-iteration": "1.1.7"}, this.embarkConfig.versions || {}); var configObject = { "default": { @@ -217,11 +227,14 @@ Config.prototype.loadStorageConfigFile = function() { "enabled": true, "available_providers": ["ipfs", "swarm"], "ipfs_bin": "ipfs", - "provider": "ipfs", - "protocol": "http", - "host": "localhost", - "port": 5001, - "getUrl": "http://localhost:8080/ipfs/" + "upload": { + "provider": "ipfs", + "protocol": "http", + "host": "localhost", + "port": 5001, + "getUrl": "http://localhost:8080/ipfs/" + }, + "dappConnection": [{"provider": "ipfs", "host": "localhost", "port": 5001, "getUrl": "http://localhost:8080/ipfs/"}] } }; diff --git a/lib/core/engine.js b/lib/core/engine.js index cf7336e24..f1fb33420 100644 --- a/lib/core/engine.js +++ b/lib/core/engine.js @@ -107,10 +107,9 @@ class Engine { "fileWatcher": this.fileWatchService, "webServer": this.webServerService, "namingSystem": this.namingSystem, - "ipfs": this.ipfsService, "web3": this.web3Service, "libraryManager": this.libraryManagerService, - "swarm": this.swarmService + "storage": this.storageService }; let service = services[serviceName]; @@ -135,7 +134,6 @@ class Engine { logger: this.logger, plugins: this.plugins }); - this.events.on('code-generator-ready', function () { self.events.request('code', function (abi, contractsJSON) { pipeline.build(abi, contractsJSON, null, () => { @@ -264,20 +262,18 @@ class Engine { }); } - ipfsService(_options) { - this.registerModule('ipfs', { + storageService(_options) { + this.registerModule('storage', { addCheck: this.servicesMonitor.addCheck.bind(this.servicesMonitor), + storageConfig: this.config.storageConfig, + webServerConfig: this.config.webServerConfig, + blockchainConfig: this.config.blockchainConfig, host: _options.host, - port: _options.port - }); - } - - swarmService(_options) { - this.registerModule('swarm', { - addCheck: this.servicesMonitor.addCheck.bind(this.servicesMonitor), - // TODO: this should not be needed and should be deducted from the config instead - // the eth provider is not necessary the same as the swarm one - bzz: this.blockchain.web3.bzz + port: _options.port, + servicesMonitor: this.servicesMonitor, + events: this.events, + logger: this.logger, + context: this.context }); } diff --git a/lib/i18n/locales/en.json b/lib/i18n/locales/en.json index 4b25e6ba8..d97da559e 100644 --- a/lib/i18n/locales/en.json +++ b/lib/i18n/locales/en.json @@ -124,23 +124,42 @@ "Blockchain node is ready": "Blockchain node is ready", "terminating due to error": "terminating due to error", "Unable to start the blockchain process. Is Geth installed?": "Unable to start the blockchain process. Is Geth installed?", - "Cannot upload: {{platform}} node is not running on {{protocol}}://{{host}}:{{port}}.": "Cannot upload: {{platform}} node is not running on {{protocol}}://{{host}}:{{port}}.", "Error while downloading the file": "Error while downloading the file", "Error while loading the content of ": "Error while loading the content of ", - "no contracts found": "no contracts found", - "DApp path length is too long: \"": "DApp path length is too long: \"", - "This is known to cause issues with some applications, please consider reducing your DApp path's length to 66 characters or less.": "This is known to cause issues with some applications, please consider reducing your DApp path's length to 66 characters or less.", - "DApp path length is too long: ": "DApp path length is too long: ", - "WARNING! DApp path length is too long: ": "WARNING! DApp path length is too long: ", - "This is known to cause issues with starting geth, please consider reducing your DApp path's length to 66 characters or less.": "This is known to cause issues with starting geth, please consider reducing your DApp path's length to 66 characters or less.", + "IPFS node is offline": "IPFS node is offline", + "IPFS node detected": "IPFS node detected", + "Webserver is offline": "Webserver is offline", "Installing packages...": "Installing packages...", "Next steps:": "Next steps:", "open another console in the same directory and run": "open another console in the same directory and run", + "deploying to swarm!": "deploying to swarm!", + "adding %s to swarm": "adding %s to swarm", + "successfully uploaded to swarm": "successfully uploaded to swarm", + "Cannot upload: {{plaform}} node is not running on {{protocol}}://{{host}}{{port}}.": "Cannot upload: {{platform}} node is not running on {{protocol}}://{{host}}{{port}}.", + "no contracts found": "no contracts found", + "IPFS node is offline": "IPFS node is offline", + "IPFS node detected": "IPFS node detected", + "Webserver is offline": "Webserver is offline", + "DApp path length is too long: \"": "DApp path length is too long: \"", + "This is known to cause issues with some applications, please consider reducing your DApp path's length to 66 characters or less.": "This is known to cause issues with some applications, please consider reducing your DApp path's length to 66 characters or less.", "For more info go to http://embark.status.im": "For more info go to http://embark.status.im", + "Cannot upload: {{platform}} node is not running on {{protocol}}://{{host}}{{port}}.": "Cannot upload: {{platform}} node is not running on {{protocol}}://{{host}}{{port}}.", + "DApp path length is too long: ": "DApp path length is too long: ", + "WARNING! DApp path length is too long: ": "WARNING! DApp path length is too long: ", + "This is known to cause issues with starting geth, please consider reducing your DApp path's length to 66 characters or less.": "This is known to cause issues with starting geth, please consider reducing your DApp path's length to 66 characters or less.", "%s is not installed on your machine": "%s is not installed on your machine", "You can install it by visiting: %s": "You can install it by visiting: %s", - "IPFS node is offline": "IPFS node is offline", "Starting ipfs process": "Starting ipfs process", "ipfs process started": "ipfs process started", - "IPFS node detected": "IPFS node detected" -} + "Starting swarm process": "Starting swarm process", + "swarm process started": "swarm process started", + "Storage process for swarm ended before the end of this process. Code: 12": "Storage process for swarm ended before the end of this process. Code: 12", + "Storage process for swarm ended before the end of this process. Code: 1": "Storage process for swarm ended before the end of this process. Code: 1", + "Storage process for ipfs ended before the end of this process. Code: 12": "Storage process for ipfs ended before the end of this process. Code: 12", + "Blockchain process ended before the end of this process. Code: %s": "Blockchain process ended before the end of this process. Code: %s", + "Cannot start {{platform}} node on {{protocol}}://{{host}}{{port}}.": "Cannot start {{platform}} node on {{protocol}}://{{host}}{{port}}.", + "Cannot upload: {{platform}} node is not running on {{url}}.": "Cannot upload: {{platform}} node is not running on {{url}}.", + "Cannot start {{platform}} node on {{url}}.": "Cannot start {{platform}} node on {{url}}.", + "Storage process for swarm ended before the end of this process. Code: 0": "Storage process for swarm ended before the end of this process. Code: 0", + "error uploading to swarm": "error uploading to swarm" +} \ No newline at end of file diff --git a/lib/index.js b/lib/index.js index f8a0f6457..4d3e8918c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,8 +1,5 @@ let async = require('async'); const constants = require('./constants'); -const _ = require('underscore'); -const StorageProcessesLauncher = require('./processes/storageProcesses/storageProcessesLauncher'); -// require("./utils/debug_util.js")(__filename, async); require('colors'); @@ -67,42 +64,6 @@ class Embark { templateGenerator.generate(destinationFolder, name); } - _checkStorageEndpoint(engine, platform, callback) { - let checkFn; - _.find(engine.servicesMonitor.checkList, (value, key) => { - if(key.toLowerCase() === platform.toLowerCase()){ - checkFn = value; - return true; - } - }); - if (!checkFn || typeof checkFn.fn !== 'function') { - return callback(); - } - - checkFn.fn(function (serviceCheckResult) { - if (!serviceCheckResult.status || serviceCheckResult.status === 'off') { - return callback('No node'); - } - callback(); - }); - } - - _startStorageNode(engine, platform, callback) { - const storageProcessesLauncher = new StorageProcessesLauncher({ - logger: engine.logger, - events: engine.events, - storageConfig: engine.config.storageConfig, - webServerConfig: engine.config.webServerConfig - }); - return storageProcessesLauncher.launchProcess(platform.toLowerCase(), (err) => { - if (err) { - engine.logger.error(err); - return callback(err); - } - callback(); - }); - } - run(options) { let self = this; self.context = options.context || [constants.contexts.run, constants.contexts.build]; @@ -159,11 +120,10 @@ class Embark { engine.startService("web3"); engine.startService("pipeline"); engine.startService("deployment"); + engine.startService("storage"); engine.startService("codeGenerator"); engine.startService("namingSystem"); - // TODO: this should be just 'storage' and the storage should figure out the module - engine.startService(engine.config.storageConfig.provider); - + engine.events.on('check:backOnline:Ethereum', function () { engine.logger.info(__('Ethereum node detected') + '..'); engine.config.reloadConfig(); @@ -172,20 +132,6 @@ class Embark { }); }); - // Check storage - const platform = engine.config.storageConfig.provider; - self._checkStorageEndpoint(engine, platform, (err) => { - if (!err) { - return; - } - self._startStorageNode(engine, platform, (err) => { - if (err) { - engine.logger.error('Error while starting a storage process for ' + platform); - engine.logger.error(err); - } - }); - }); - engine.events.on('outputDone', function () { engine.logger.info((__("Looking for documentation? You can find it at") + " ").cyan + "http://embark.status.im/docs/".green.underline + ".".cyan); engine.logger.info(__("Ready").underline); @@ -249,10 +195,8 @@ class Embark { engine.startService("web3"); engine.startService("pipeline"); engine.startService("deployment", {onlyCompile: options.onlyCompile}); + engine.startService("storage"); engine.startService("codeGenerator"); - // TODO: this should be just 'storage' and the storage should figure out the modules to load - engine.startService("ipfs"); - engine.startService("swarm"); callback(); }, function deploy(callback) { @@ -305,6 +249,7 @@ class Embark { engine.startService("libraryManager"); engine.startService("pipeline"); engine.startService("deployment", {onlyCompile: true}); + engine.startService("codeGenerator"); engine.events.request('deploy:contracts', function(err) { @@ -335,7 +280,6 @@ class Embark { } upload(options) { - const self = this; this.context = options.context || [constants.contexts.upload, constants.contexts.build]; let engine = new Engine({ @@ -351,11 +295,12 @@ class Embark { events: options.events, logger: options.logger, config: options.config, - plugins: options.plugins + plugins: options.plugins, + context: this.context }); engine.init(); - let platform = engine.config.storageConfig.provider; + let platform = engine.config.storageConfig.upload.provider; let cmdPlugin; async.waterfall([ @@ -367,35 +312,11 @@ class Embark { engine.startService("web3"); engine.startService("pipeline"); engine.startService("deployment"); + engine.startService("storage"); engine.startService("codeGenerator"); - // TODO: this should be just 'storage' and the storage should figure out the modules to load - engine.startService(platform.toLowerCase()); engine.startMonitor(); callback(); }, - function checkStorageService(callback){ - - const errorObj = {message: __('Cannot upload: {{platform}} node is not running on {{protocol}}://{{host}}:{{port}}.', {platform: platform, protocol: engine.config.storageConfig.protocol, host: engine.config.storageConfig.host, port: engine.config.storageConfig.port})}; - - self._checkStorageEndpoint(engine, platform, function (err) { - if (!err) { - return callback(); - } - self._startStorageNode(engine, platform, (err) => { - if (err) { - engine.logger.error(err); - return callback(errorObj); - } - // Check endpoint again to see if really did start - self._checkStorageEndpoint(engine, platform, (err) => { - if (err) { - return callback(errorObj); - } - callback(); - }); - }); - }); - }, function setupStoragePlugin(callback){ let pluginList = engine.plugins.listPlugins(); if (pluginList.length > 0) { @@ -413,8 +334,7 @@ class Embark { }); } if (!cmdPlugin) { - engine.logger.info(__('try "{{ipfs}}" or "{{swarm}}"', {ipfs: 'embark upload ipfs', swarm: 'embark upload swarm'}).green); - return callback({message: 'unknown platform: ' + platform}); + return callback({message: __('platform "{{platform}}" is specified as the upload provider, however no plugins have registered an upload command for "{{platform}}".', {platform: platform})}); } callback(); }, diff --git a/lib/modules/ipfs/embarkjs.js b/lib/modules/ipfs/embarkjs.js index 1c374cb5a..82bf19324 100644 --- a/lib/modules/ipfs/embarkjs.js +++ b/lib/modules/ipfs/embarkjs.js @@ -7,23 +7,24 @@ __embarkIPFS.setProvider = function (options) { var promise = new Promise(function (resolve, reject) { try { if (options === undefined) { - self.ipfsConnection = IpfsApi('localhost', '5001'); + self._config = options; + self._ipfsConnection = IpfsApi('localhost', '5001'); self._getUrl = "http://localhost:8080/ipfs/"; } else { - var ipfsOptions = {host: options.server, protocol: 'http'}; + var ipfsOptions = {host: options.host || options.server, protocol: 'http'}; if (options.protocol) { ipfsOptions.protocol = options.protocol; } if (options.port && options.port !== 'false') { ipfsOptions.port = options.port; } - self.ipfsConnection = IpfsApi(ipfsOptions); + self._ipfsConnection = IpfsApi(ipfsOptions); self._getUrl = options.getUrl || "http://localhost:8080/ipfs/"; } resolve(self); } catch (err) { - console.log(err); - self.ipfsConnection = null; + console.error(err); + self._ipfsConnection = null; reject(new Error('Failed to connect to IPFS')); } }); @@ -33,11 +34,11 @@ __embarkIPFS.setProvider = function (options) { __embarkIPFS.saveText = function (text) { const self = this; var promise = new Promise(function (resolve, reject) { - if (!self.ipfsConnection) { + 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 { @@ -54,11 +55,11 @@ __embarkIPFS.get = function (hash) { // TODO: detect type, then convert if needed //var ipfsHash = web3.toAscii(hash); var promise = new Promise(function (resolve, reject) { - if (!self.ipfsConnection) { + if (!self._ipfsConnection) { var connectionError = new Error('No IPFS connection. Please ensure to call Embark.Storage.setProvider()'); reject(connectionError); } - self.ipfsConnection.get(hash, function (err, files) { + self._ipfsConnection.get(hash, function (err, files) { if (err) { return reject(err); } @@ -78,15 +79,15 @@ __embarkIPFS.uploadFile = function (inputSelector) { } var promise = new Promise(function (resolve, reject) { - if (!self.ipfsConnection) { + 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 () { var fileContent = reader.result; - var buffer = self.ipfsConnection.Buffer.from(fileContent); - self.ipfsConnection.add(buffer, function (err, result) { + var buffer = self._ipfsConnection.Buffer.from(fileContent); + self._ipfsConnection.add(buffer, function (err, result) { if (err) { reject(err); } else { @@ -102,10 +103,10 @@ __embarkIPFS.uploadFile = function (inputSelector) { __embarkIPFS.isAvailable = function () { return new Promise((resolve) => { - if (!this.ipfsConnection) { + if (!this._ipfsConnection) { return resolve(false); } - this.ipfsConnection.id() + this._ipfsConnection.id() .then((id) => { resolve(Boolean(id)); }) @@ -119,3 +120,4 @@ __embarkIPFS.getUrl = function (hash) { return (this._getUrl || "http://localhost:8080/ipfs/") + hash; }; + diff --git a/lib/modules/ipfs/index.js b/lib/modules/ipfs/index.js index 146a96ac3..be0eb7fef 100644 --- a/lib/modules/ipfs/index.js +++ b/lib/modules/ipfs/index.js @@ -1,7 +1,8 @@ -let UploadIPFS = require('./upload.js'); -let utils = require('../../utils/utils.js'); -let fs = require('../../core/fs.js'); -let IpfsApi = require('ipfs-api'); +const UploadIPFS = require('./upload.js'); +const utils = require('../../utils/utils.js'); +const fs = require('../../core/fs.js'); +const IpfsApi = require('ipfs-api'); +const _ = require('underscore'); class IPFS { @@ -9,23 +10,18 @@ class IPFS { this.logger = embark.logger; this.events = embark.events; this.buildDir = options.buildDir; - this.storageConfig = embark.config.storageConfig; - this.host = options.host || this.storageConfig.host; - this.port = options.port || this.storageConfig.port; + this.storageConfig = options.storageConfig; + this.host = options.host || this.storageConfig.upload.host; + this.port = options.port || this.storageConfig.upload.port; + this.protocol = options.protocol || this.storageConfig.upload.protocol; this.addCheck = options.addCheck; this.embark = embark; - - this.commandlineDeploy(); - this.setServiceCheck(); - this.addIPFSToEmbarkJS(); - this.addSetProvider(); - this.addIpfsObjectToConsole(); } commandlineDeploy() { let upload_ipfs = new UploadIPFS({ buildDir: this.buildDir || 'dist/', - storageConfig: this.storageConfig, + storageConfig: this.storageConfig.upload, configIpfsBin: this.storageConfig.ipfs_bin || "ipfs" }); @@ -40,7 +36,7 @@ class IPFS { if (!storageConfig.enabled) { return; } - if (storageConfig.provider !== 'ipfs' && storageConfig.available_providers.indexOf("ipfs") < 0) { + if (_.findWhere(this.storageConfig.dappConnection, {'provider': 'ipfs'}) === undefined && (storageConfig.upload.provider !== 'ipfs' || storageConfig.available_providers.indexOf("ipfs") < 0)) { return; } @@ -58,7 +54,13 @@ class IPFS { self.addCheck('IPFS', function (cb) { self.logger.trace("Checking IPFS version..."); - utils.httpGetJson('http://' + self.host + ':' + self.port + '/api/v0/version', function (err, body) { + let url = (self.protocol || 'http') + '://' + self.host + ':' + self.port + '/api/v0/version'; + if(self.protocol !== 'https'){ + utils.httpGetJson(url, versionCb); + } else { + utils.httpsGetJson(url, versionCb); + } + function versionCb(err, body) { if (err) { self.logger.trace("Check IPFS version error: " + err); return cb({name: "IPFS ", status: 'off'}); @@ -67,18 +69,18 @@ class IPFS { return cb({name: ("IPFS " + body.Version), status: 'on'}); } return cb({name: "IPFS ", status: 'on'}); - }); + } }); } - addIPFSToEmbarkJS() { + addProviderToEmbarkJS() { const self = this; // TODO: make this a shouldAdd condition if (this.storageConfig === {}) { return; } - if ((this.storageConfig.available_providers.indexOf('ipfs') < 0) && (this.storageConfig.provider !== 'ipfs' || this.storageConfig.enabled !== true)) { + if (this.storageConfig.available_providers.indexOf('ipfs') < 0 || _.findWhere(this.storageConfig.dappConnection, {'provider': 'ipfs'}) === undefined || this.storageConfig.enabled !== true) { return; } @@ -91,6 +93,15 @@ class IPFS { } }); + self.events.request("version:get:p-iteration", function(pIterationVersion) { + let currentPIterationVersion = require('../../../package.json').dependencies["p-iteration"]; + if (pIterationVersion !== currentPIterationVersion) { + self.events.request("version:getPackageLocation", "p-iteration", pIterationVersion, function(err, location) { + self.embark.registerImportFile("p-iteration", fs.dappPath(location)); + }); + } + }); + let code = ""; code += "\n" + fs.readFileSync(utils.joinPath(__dirname, 'embarkjs.js')).toString(); code += "\nEmbarkJS.Storage.registerProvider('ipfs', __embarkIPFS);"; @@ -98,24 +109,8 @@ class IPFS { this.embark.addCodeToEmbarkJS(code); } - addSetProvider() { - let config = JSON.stringify({ - server: this.storageConfig.host, - port: this.storageConfig.port, - protocol: this.storageConfig.protocol, - getUrl: this.storageConfig.getUrl - }); - let code = "\nEmbarkJS.Storage.setProvider('ipfs'," + config + ");"; - - let shouldInit = (storageConfig) => { - return (storageConfig.provider === 'ipfs' && storageConfig.enabled === true); - }; - - this.embark.addProviderInit('storage', code, shouldInit); - } - - addIpfsObjectToConsole() { - let ipfs = IpfsApi(this.storageConfig.host, this.storageConfig.port); + addObjectToConsole() { + let ipfs = IpfsApi(this.host, this.port); this.events.emit("runcode:register", "ipfs", ipfs); } diff --git a/lib/modules/ipfs/upload.js b/lib/modules/ipfs/upload.js index 273b2f452..8837ffde5 100644 --- a/lib/modules/ipfs/upload.js +++ b/lib/modules/ipfs/upload.js @@ -44,7 +44,7 @@ class IPFS { }, function printUrls(dir_hash, callback) { console.log(("=== " + __("DApp available at") + " http://localhost:8080/ipfs/" + dir_hash + "/").green); - console.log(("=== " + __("DApp available at") + " http://gateway.ipfs.io/ipfs/" + dir_hash + "/").green); + console.log(("=== " + __("DApp available at") + " http://ipfs.infura.io/ipfs/" + dir_hash + "/").green); callback(); } diff --git a/lib/modules/specialconfigs/index.js b/lib/modules/specialconfigs/index.js index 25b299df4..b2b00a09d 100644 --- a/lib/modules/specialconfigs/index.js +++ b/lib/modules/specialconfigs/index.js @@ -55,6 +55,7 @@ class SpecialConfigs { self.replaceWithAddresses(cmd, nextMapCb); }, (err, result) => { if (err) { + self.logger.trace(err); return cb(new Error("error running afterDeploy")); } let onDeployCode = result; diff --git a/lib/modules/storage/embarkjs.js b/lib/modules/storage/embarkjs.js new file mode 100644 index 000000000..8f7c41513 --- /dev/null +++ b/lib/modules/storage/embarkjs.js @@ -0,0 +1,36 @@ +/* global EmbarkJS */ + +import {findSeries} from 'p-iteration'; + +let __embarkStorage = {}; + +__embarkStorage.setProviders = async function (dappConnOptions) { + try { + let workingConnFound = await findSeries(dappConnOptions, async (dappConn) => { + if(dappConn === '$BZZ' || dappConn.provider === 'swarm'){ + let options = dappConn; + if(dappConn === '$BZZ') options = {"useOnlyGivenProvider": true}; + try{ + await EmbarkJS.Storage.setProvider('swarm', options); + let isAvailable = await EmbarkJS.Storage.isAvailable(); + return isAvailable; + }catch(err){ + return false; // catch errors for when bzz object not initialised but config has requested it to be used + } + } + else if(dappConn.provider === 'ipfs') { + // set the provider then check the connection, if true, use that provider, else, check next provider + try{ + await EmbarkJS.Storage.setProvider('ipfs', dappConn); + let isAvailable = await EmbarkJS.Storage.isAvailable(); + return isAvailable; + } catch(err) { + return false; + } + } + }); + if(!workingConnFound) throw new Error('Could not connect to a storage provider using any of the dappConnections in the storage config'); + } catch (err) { + throw new Error('Failed to connect to a storage provider: ' + err.message); + } + }; diff --git a/lib/modules/storage/index.js b/lib/modules/storage/index.js new file mode 100644 index 000000000..3327524f1 --- /dev/null +++ b/lib/modules/storage/index.js @@ -0,0 +1,217 @@ + +const utils = require('../../utils/utils.js'); +const fs = require('../../core/fs.js'); +const _ = require('underscore'); +const async = require('async'); +const StorageProcessesLauncher = require('../../processes/storageProcesses/storageProcessesLauncher'); +const constants = require('../../constants'); + +class Storage { + constructor(embark, options){ + this._embark = embark; + this._options = options; + this._storageConfig = options.storageConfig; + this._webServerConfig = options.webServerConfig; + this._blockchainConfig = options.blockchainConfig; + this._servicesMonitor = options.servicesMonitor; + this._events = options.events; + this._logger = options.logger; + + // filter list of dapp connections based on available_providers set in config + let hasSwarm = _.contains(this._storageConfig.available_providers, 'swarm'); // don't need to eval this in every loop iteration + // contains valid dapp storage providers + this._validDappProviders = _.filter(this._storageConfig.dappConnection, (conn) => { + return _.contains(this._storageConfig.available_providers, conn.provider) || (conn === '$BZZ' && hasSwarm); + }); + + this.initStorageForEmbark(); + this.initStorageForDapp(); + + // don't start storage processes on build command, only on upload or run + if(_.contains(options.context, constants.contexts.upload) || _.contains(options.context, constants.contexts.run)){ + this.startStorageProcesses(); + } + } + + _checkStorageEndpoint(platform, callback) { + let checkFn; + let self = this; + self._logger.trace(`Storage module: Checking ${platform} availability...`); + _.find(self._servicesMonitor.checkList, (value, key) => { + if(key.toLowerCase() === platform.toLowerCase()){ + checkFn = value; + return true; + } + }); + if (!checkFn || typeof checkFn.fn !== 'function') { + self._logger.trace(`Storage module: Check for ${platform} node does not exist.`); + return callback(); + } + + checkFn.fn(function (serviceCheckResult) { + if (!serviceCheckResult.status || serviceCheckResult.status === 'off') { + self._logger.trace(`Storage module: ${platform} node not available.`); + return callback('No node'); + } + callback(); + }); + } + + _startStorageNode(platform, callback) { + let self = this; + const storageProcessesLauncher = new StorageProcessesLauncher({ + logger: self._logger, + events: self._events, + storageConfig: self._storageConfig, + webServerConfig: self._webServerConfig, + blockchainConfig: self._blockchainConfig + }); + self._logger.trace(`Storage module: Launching ${platform} process...`); + return storageProcessesLauncher.launchProcess(platform.toLowerCase(), (err) => { + if (err) { + self._logger.error(err); + return callback(err); + } + callback(); + }); + } + + /// Initializes a storage provider for Embark upload + initStorageForEmbark(){ + let storageProviderCls = require(`../${this._storageConfig.upload.provider}/index.js`); + let uploadProvider = new storageProviderCls(this._embark, this._options); /*eslint no-new: "off"*/ + + if(typeof uploadProvider.commandlineDeploy == 'function') uploadProvider.commandlineDeploy(); + if(typeof uploadProvider.setServiceCheck == 'function') uploadProvider.setServiceCheck(); + if(typeof uploadProvider.addObjectToConsole == 'function') uploadProvider.addObjectToConsole(); + } + + /** + * Initializes a storage provider for EmbarkJS + * + * @return {void} + */ + initStorageForDapp(){ + // now we need to add instantiate any dappConnection/available_providers storage providers to add + // their provider code to embarkjs + this._validDappProviders.forEach(dappConn => { + if(!dappConn.provider) return; + let storageProviderCls = require(`../${dappConn.provider}/index.js`); + + // override options with dappConnection settings + let storageOptions = this._options; + storageOptions.protocol = dappConn.protocol; + storageOptions.host = dappConn.host; + storageOptions.port = dappConn.port; + + // then instantiate the storage provdier class + let storageProvider = new storageProviderCls(this._embark, storageOptions); /*eslint no-new: "off"*/ + + // register the service check so we can use it to check if the process is running before spawning it + // check that it hasn't already been done above + if(dappConn.provider !== this._storageConfig.upload.provider){ + if(typeof storageProvider.setServiceCheck == 'function') storageProvider.setServiceCheck(); + } + + // add __embarkSwarm and __embarkIPFS objects to EmbarkJS + if(typeof storageProvider.addProviderToEmbarkJS == 'function') storageProvider.addProviderToEmbarkJS(); + }); + + // add the storage provider code (__embarkStorage) to embarkjs + this.addProviderToEmbarkJS(); + + // add the code to call setProviders in embarkjs after embark is ready + this.addSetProviders(); + } + + /** + * Adds the storage provider code (__embarkStorage) to embarkjs + * + * @returns {void} + */ + addProviderToEmbarkJS(){ + // TODO: make this a shouldAdd condition + if (this._storageConfig === {} || !this._storageConfig.dappConnection || !this._storageConfig.dappConnection.length) { + return; + } + + let code = "\n" + fs.readFileSync(utils.joinPath(__dirname, 'embarkjs.js')).toString(); + + this._embark.addCodeToEmbarkJS(code); + } + + /** + * Adds the code to call setProviders in embarkjs after embark is ready + * + * @returns {void} + */ + addSetProviders() { + + let code = `\n__embarkStorage.setProviders(${JSON.stringify(this._validDappProviders)});`; + let shouldInit = (storageConfig) => { + return (this._validDappProviders !== undefined && this._validDappProviders.length > 0 && storageConfig.enabled === true); + }; + + this._embark.addProviderInit('storage', code, shouldInit); + } + + startStorageProcesses(){ + let platform = this._storageConfig.upload.provider; + let self = this; + + async.waterfall([ + function checkStorageService(callback){ + const errorObj = {message: __('Cannot upload: {{platform}} node is not running on {{url}}.', {platform: platform, url: utils.buildUrlFromConfig(self._storageConfig.upload)})}; + + // start the upload storage node + self._checkStorageEndpoint(platform, function (err) { + if (!err) { + return callback(); + } + self._startStorageNode(platform, (err) => { + if (err) { + self._logger.error(err); + return callback(errorObj); + } + // Check endpoint again to see if really did start + self._checkStorageEndpoint(platform, (err) => { + if (err) { + return callback(errorObj); + } + callback(); + }); + }); + }); + }, + function checkDappConnectionStorageService(callback){ + // start any dappConnection storage nodes + self._validDappProviders.forEach(dappConn => { + if(!dappConn.provider || dappConn.provider === platform) return; // don't start the process we've just started above + + const errorObj = {message: __('Cannot start {{platform}} node on {{url}}.', {platform: dappConn.provider, url: utils.buildUrlFromConfig(dappConn)})}; + + self._checkStorageEndpoint(dappConn.provider, function (err) { + if (!err) { + return callback(); + } + self._startStorageNode(dappConn.provider, (err) => { + if (err) { + self._logger.error(err); + return callback(errorObj); + } + // Check endpoint again to see if really did start + self._checkStorageEndpoint(dappConn.provider, (err) => { + if (err) { + return callback(errorObj); + } + callback(); + }); + }); + }); + }); + } + ]); + } +} + +module.exports = Storage; diff --git a/lib/modules/swarm/embarkjs.js b/lib/modules/swarm/embarkjs.js index 9a415258a..553cdb6fb 100644 --- a/lib/modules/swarm/embarkjs.js +++ b/lib/modules/swarm/embarkjs.js @@ -3,36 +3,47 @@ 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:/`; + let protocol = options.protocol || 'http'; + let port = options.port ? `:${options.port}` : ''; + + this._config = options; + this._connectUrl = `${protocol}://${options.host}${port}`; + this._connectError = new Error(`Cannot connect to Swarm node on ${this._connectUrl}`); return new Promise((resolve, reject) => { try { - if (!this.bzz.currentProvider) { - this.bzz.setProvider(`${options.protocol}://${options.host}:${options.port}`); + if (!web3.bzz.currentProvider && !options.useOnlyGivenProvider) { + web3.bzz.setProvider(this._connectUrl); + } + else if(options.useOnlyGivenProvider && web3.bzz.givenProvider !== null){ + web3.bzz.setProvider(web3.bzz.givenProvider); } resolve(this); } catch (err) { console.log(err); - reject(this.connectError); + reject(this._connectError); } }); }; __embarkSwarm.isAvailable = function () { return new Promise((resolve, reject) => { - if (!this.bzz) { + // if web3 swarm object doesn't exist + if (!web3.bzz) { return resolve(false); } - this.bzz.isAvailable() + // swarm obj exists, but has no provider set (seems to happen a LOT!), + // try setting the provider to our currently set provider again + else if(!web3.bzz.currentProvider && this._config.host){ + web3.bzz.setProvider(this._connectUrl); + } + if (!web3.bzz.currentProvider) { + return resolve(false); + } + web3.bzz.isAvailable() .then(resolve) .catch(() => { - reject(this.connectError); + reject(this._connectError); }); }); }; @@ -41,9 +52,9 @@ __embarkSwarm.saveText = function (text) { return new Promise((resolve, reject) => { this.isAvailable().then((isAvailable) => { if (!isAvailable) { - return reject(this.connectError); + return reject(this._connectError); } - this.bzz.upload(text) + web3.bzz.upload(text) .then(resolve) .catch(reject); }).catch(reject); @@ -54,9 +65,9 @@ __embarkSwarm.get = function (hash) { return new Promise((resolve, reject) => { this.isAvailable().then((isAvailable) => { if (!isAvailable) { - return reject(this.connectError); + return reject(this._connectError); } - this.bzz.download(hash) + web3.bzz.download(hash) .then((uint8Array) => resolve(bytes.toString(bytes.fromUint8Array(uint8Array)))) .catch(reject); }).catch(reject); @@ -76,9 +87,9 @@ __embarkSwarm.uploadFile = function (inputSelector) { const fileContent = new Uint8Array(event.target.result); this.isAvailable().then((isAvailable) => { if (!isAvailable) { - return reject(this.connectError); + return reject(this._connectError); } - this.bzz.upload(fileContent) + web3.bzz.upload(fileContent) .then(resolve) .catch(reject); }).catch(reject); @@ -89,6 +100,6 @@ __embarkSwarm.uploadFile = function (inputSelector) { }; __embarkSwarm.getUrl = function (hash) { - return this._getUrl + hash; + return `${this._config.getUrl || this._connectUrl + '/bzz:/'}${hash}`; }; diff --git a/lib/modules/swarm/index.js b/lib/modules/swarm/index.js index b6479b942..8d6b35f85 100644 --- a/lib/modules/swarm/index.js +++ b/lib/modules/swarm/index.js @@ -1,6 +1,8 @@ -let UploadSwarm = require('./upload.js'); -let utils = require('../../utils/utils.js'); -let fs = require('../../core/fs.js'); +const UploadSwarm = require('./upload.js'); +const utils = require('../../utils/utils.js'); +const fs = require('../../core/fs.js'); +const Web3Bzz = require('web3-bzz'); +const _ = require('underscore'); class Swarm { @@ -8,30 +10,22 @@ class Swarm { this.logger = embark.logger; this.events = embark.events; this.buildDir = options.buildDir; - this.storageConfig = embark.config.storageConfig; - this.host = options.host || this.storageConfig.host; - this.port = options.port || this.storageConfig.port; + this.storageConfig = options.storageConfig; 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}`); - } + + this.providerUrl = utils.buildUrl(options.protocol || options.storageConfig.upload.protocol, options.host || options.storageConfig.upload.host, options.port || options.storageConfig.upload.port); + + this.getUrl = options.storageConfig.upload.getUrl || this.providerUrl + '/bzz:/'; + + this.bzz = new Web3Bzz(this.providerUrl); } commandlineDeploy() { this.upload_swarm = new UploadSwarm({ buildDir: this.buildDir || 'dist/', storageConfig: this.storageConfig, + getUrl: this.getUrl, bzz: this.bzz }); @@ -47,7 +41,7 @@ class Swarm { if (!storageConfig.enabled) { return; } - if (storageConfig.provider !== 'swarm' && storageConfig.available_providers.indexOf("swarm") < 0) { + if (_.findWhere(this.storageConfig.dappConnection, {'provider': 'swarm'}) === undefined && (storageConfig.upload.provider !== 'swarm' || storageConfig.available_providers.indexOf("swarm") < 0)) { return; } @@ -75,38 +69,32 @@ class Swarm { }); } - addSwarmToEmbarkJS() { + addProviderToEmbarkJS() { + let self = this; // 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)) { + if (this.storageConfig.available_providers.indexOf('swarm') < 0 || _.findWhere(this.storageConfig.dappConnection, {'provider': 'swarm'}) === undefined || this.storageConfig.enabled !== true) { return; } + this.events.request("version:get:p-iteration", function(pIterationVersion) { + let currentPIterationVersion = require('../../../package.json').dependencies["p-iteration"]; + if (pIterationVersion !== currentPIterationVersion) { + self.events.request("version:getPackageLocation", "p-iteration", pIterationVersion, function(err, location) { + self.embark.registerImportFile("p-iteration", fs.dappPath(location)); + }); + } + }); + 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 4defd9118..995cafb90 100644 --- a/lib/modules/swarm/upload.js +++ b/lib/modules/swarm/upload.js @@ -7,6 +7,7 @@ class Swarm { this.buildDir = options.buildDir || 'dist/'; this.bzz = options.bzz; this.storageConfig = options.storageConfig; + this.getUrl = options.getUrl; } deploy() { @@ -31,7 +32,8 @@ class Swarm { if (!dir_hash) { return callback('No directory hash was returned'); } - console.log(("=== " + __("DApp available at") + `${self.storageConfig.getUrl}${dir_hash}/`).green); + console.log(("=== " + __("DApp available at") + ` ${self.getUrl}${dir_hash}/`).green); + console.log(("=== " + __("DApp available at") + ` http://swarm-gateways.net/bzz:/${dir_hash}`).green); callback(); } diff --git a/lib/processes/storageProcesses/ipfs.js b/lib/processes/storageProcesses/ipfs.js index 226c78644..933505020 100644 --- a/lib/processes/storageProcesses/ipfs.js +++ b/lib/processes/storageProcesses/ipfs.js @@ -8,6 +8,8 @@ class IPFSProcess extends ProcessWrapper { constructor(_options) { super(); + this.cors = _options.cors; + this.checkIPFSVersion(); this.startIPFSDaemon(); } @@ -31,6 +33,8 @@ class IPFSProcess extends ProcessWrapper { startIPFSDaemon() { const self = this; + + // spawn the daemon (muhaha) this.child = child_process.spawn('ipfs', ['daemon']); this.child.on('error', (err) => { @@ -45,7 +49,41 @@ class IPFSProcess extends ProcessWrapper { data = data.toString(); if (!self.readyCalled && data.indexOf('Daemon is ready') > -1) { self.readyCalled = true; - self.send({result: constants.storage.initiated}); + + // update IPFS cors before spawning a daemon (muhaha) + console.log(`RUNNING IPFS CORS UPDATE COMMAND: ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin "[\\"${self.cors.join('\\", \\"')}\\"]"`); + child_process.exec(`ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin "[\\"${self.cors.join('\\", \\"')}\\"]"`, {silent: true}, (err, stdout, _stderr) => { + if(err){ + err = err.toString(); + console.error('IPFS CORS update error: ', err); + } + if(_stderr){ + _stderr = _stderr.toString(); + console.error(`IPFS CORS update error: ${_stderr}`); + } + child_process.exec('ipfs config --json API.HTTPHeaders.Access-Control-Allow-Credentials "[\\"true\\"]"', {silent: true}, (err, stdout, _stderr) => { + if(err){ + err = err.toString(); + console.error('IPFS CORS update error: ', err); + } + if(_stderr){ + _stderr = _stderr.toString(); + console.error(`IPFS CORS update error: ${_stderr}`); + } + child_process.exec('ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods "[\\"PUT\\", \\"POST\\", \\"GET\\"]"', {silent: true}, (err, stdout, _stderr) => { + if(err){ + err = err.toString(); + console.error('IPFS CORS update error: ', err); + } + if(_stderr){ + _stderr = _stderr.toString(); + console.error(`IPFS CORS update error: ${_stderr}`); + } + + self.send({result: constants.storage.initiated}); + }); + }); + }); } console.log('IPFS: ' + data); }); @@ -54,6 +92,8 @@ class IPFSProcess extends ProcessWrapper { console.error('IPFS exited with error code ' + code); } }); + + } kill() { diff --git a/lib/processes/storageProcesses/storageProcessesLauncher.js b/lib/processes/storageProcesses/storageProcessesLauncher.js index 49a1ddf41..14e86ee9f 100644 --- a/lib/processes/storageProcesses/storageProcessesLauncher.js +++ b/lib/processes/storageProcesses/storageProcessesLauncher.js @@ -9,8 +9,11 @@ class StorageProcessesLauncher { this.events = options.events; this.storageConfig = options.storageConfig; this.webServerConfig = options.webServerConfig; + this.blockchainConfig = options.blockchainConfig; this.processes = {}; + this.cors = this.buildCors(); + this.events.on('exit', () => { Object.keys(this.processes).forEach(processName => { this.processes[processName].send('exit'); @@ -18,6 +21,53 @@ class StorageProcessesLauncher { }); } + buildCors(storageName) + { + let corsParts = []; + // add our webserver CORS + if(this.webServerConfig.enabled){ + if (this.webServerConfig && this.webServerConfig.host) { + corsParts.push(utils.buildUrlFromConfig(this.webServerConfig)); + } + else corsParts.push('http://localhost:8000'); + } + + // add all dapp connection storage + if(this.storageConfig.enabled) { + this.storageConfig.dappConnection.forEach(dappConn => { + if(dappConn.provider === storageName) return; // do not add CORS URL for ourselves + if(dappConn.getUrl || dappConn.host){ + + // if getUrl is specified in the config, that needs to be included in cors + // instead of the concatenated protocol://host:port + if(dappConn.getUrl) { + // remove /ipfs or /bzz: from getUrl if it's there + let getUrlParts = dappConn.getUrl.split('/'); + getUrlParts = getUrlParts.slice(0, 3); + corsParts.push(getUrlParts.join('/')); + } + // in case getUrl wasn't specified, use a built url + else{ + corsParts.push(utils.buildUrlFromConfig(dappConn)); + } + } + }); + } + + if(this.blockchainConfig.enabled) { + // add our rpc endpoints to CORS + if(this.blockchainConfig.rpcHost && this.blockchainConfig.rpcPort){ + corsParts.push(`http://${this.blockchainConfig.rpcHost}:${this.blockchainConfig.rpcPort}`); + } + + // add our ws endpoints to CORS + if(this.blockchainConfig.wsRPC && this.blockchainConfig.wsHost && this.blockchainConfig.wsPort){ + corsParts.push(`ws://${this.blockchainConfig.wsHost}:${this.blockchainConfig.wsPort}`); + } + } + return corsParts; + } + processExited(storageName, code) { this.logger.error(__(`Storage process for ${storageName} ended before the end of this process. Code: ${code}`)); } @@ -37,13 +87,13 @@ class StorageProcessesLauncher { modulePath: filePath, logger: self.logger, events: self.events, - silent: true, + silent: self.logger.logLevel !== 'trace', exitCallback: self.processExited.bind(this, storageName) }); self.processes[storageName].send({ action: constants.blockchain.init, options: { storageConfig: self.storageConfig, - webServerConfig: self.webServerConfig + cors: self.buildCors(storageName) } }); diff --git a/lib/processes/storageProcesses/swarm.js b/lib/processes/storageProcesses/swarm.js index 49909d735..8bbf37cae 100644 --- a/lib/processes/storageProcesses/swarm.js +++ b/lib/processes/storageProcesses/swarm.js @@ -9,7 +9,7 @@ class SwarmProcess extends ProcessWrapper { constructor(options) { super(); this.storageConfig = options.storageConfig; - this.webServerConfig = options.webServerConfig; + this.cors = options.cors; } startSwarmDaemon() { @@ -17,16 +17,13 @@ class SwarmProcess extends ProcessWrapper { if (!this.storageConfig.account || !this.storageConfig.account.address || !this.storageConfig.account.password) { return 'Account address and password are needed in the storage config to start the Swarm process'; } - let corsDomain = 'http://localhost:8000'; - if (self.webServerConfig && self.webServerConfig && self.webServerConfig.host && self.webServerConfig.port) { - corsDomain = `http://${self.webServerConfig.host}:${self.webServerConfig.port}`; - } const args = [ `--bzzaccount=${this.storageConfig.account.address}`, `--password=${fs.dappPath(this.storageConfig.account.password)}`, - `--corsdomain=${corsDomain}` + `--corsdomain=${self.cors.join(',')}` ]; + console.trace('Starting swarm process with arguments: ' + args.join(' ')); this.child = child_process.spawn(this.storageConfig.swarmPath || 'swarm', args); this.child.on('error', (err) => { diff --git a/lib/utils/utils.js b/lib/utils/utils.js index dbad68349..6d92422f1 100644 --- a/lib/utils/utils.js +++ b/lib/utils/utils.js @@ -69,6 +69,17 @@ function httpGetJson(url, callback) { }); } +function httpsGetJson(url, callback) { + httpGetRequest(https, url, function(err, body) { + try { + let parsed = JSON.parse(body); + return callback(err, parsed); + } catch(e) { + return callback(e); + } + }); +} + function runCmd(cmd, options) { let result = shelljs.exec(cmd, options || {silent: true}); if (result.code !== 0) { @@ -199,6 +210,39 @@ function normalizeInput(input) { }).toString() + ']'); } +/** + * Builds a URL + * + * @param {string} protocol + * The URL protocol, defaults to http. + * @param {string} host + * The URL host, required. + * @param {string} port + * The URL port, default to empty string. + * @returns {string} the constructued URL, with defaults + */ +function buildUrl (protocol, host, port){ + if(!host) throw new Error('utils.buildUrl: parameter \'host\' is required'); + if(port) port = ':' + port; + else port = ''; + return `${protocol || 'http'}://${host}${port}`; +} + +/** + * Builds a URL + * + * @param {object} configObj Object containing protocol, host, and port to be used to construct the url. + * * protocol {String} (optional) The URL protocol, defaults to http. + * * host {String} (required) The URL host. + * * port {String} (optional) The URL port, default to empty string. + * @returns {string} the constructued URL, with defaults + */ +function buildUrlFromConfig (configObj){ + if(!configObj) throw new Error('[utils.buildUrlFromConfig]: config object must cannot be null'); + if(!configObj.host) throw new Error('[utils.buildUrlFromConfig]: object must contain a \'host\' property'); + return this.buildUrl(configObj.protocol, configObj.host, configObj.port); +} + module.exports = { joinPath: joinPath, filesMatchingPattern: filesMatchingPattern, @@ -208,6 +252,7 @@ module.exports = { httpGet: httpGet, httpsGet: httpsGet, httpGetJson: httpGetJson, + httpsGetJson: httpsGetJson, runCmd: runCmd, cd: cd, sed: sed, @@ -219,5 +264,7 @@ module.exports = { getExternalContractUrl, toChecksumAddress: toChecksumAddress, sha3: sha3, - normalizeInput + normalizeInput, + buildUrl, + buildUrlFromConfig }; diff --git a/lib/versions/library_manager.js b/lib/versions/library_manager.js index 3eb1f72b6..66527767b 100644 --- a/lib/versions/library_manager.js +++ b/lib/versions/library_manager.js @@ -23,15 +23,17 @@ class LibraryManager { let solcVersionInConfig = this.contractsConfig.versions.solc; let web3VersionInConfig = this.contractsConfig.versions["web3"]; let ipfsApiVersion = this.storageConfig.versions["ipfs-api"]; + let pIterationVersion = this.storageConfig.versions["p-iteration"]; this.versions['solc'] = solcVersionInConfig; this.versions['web3'] = web3VersionInConfig; this.versions['ipfs-api'] = ipfsApiVersion; + this.versions['p-iteration'] = pIterationVersion; Object.keys(this.versions).forEach(versionKey => { const newVersion = this.versions[versionKey].trim(); if (newVersion !== this.versions[versionKey]) { - this.embark.logger.warn(__('There a a space in the version of {{versionKey}}. We corrected it for you ({{correction}}).', {versionKey: versionKey, correction: `"${this.versions[versionKey]}" => "${newVersion}"`})); + this.embark.logger.warn(__('There is a space in the version of {{versionKey}}. We corrected it for you ({{correction}}).', {versionKey: versionKey, correction: `"${this.versions[versionKey]}" => "${newVersion}"`})); this.versions[versionKey] = newVersion; } }); diff --git a/package-lock.json b/package-lock.json index 7a27172d7..d9b764ae8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -434,6 +434,22 @@ } } }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.5" + } + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -1626,7 +1642,7 @@ "browserify-zlib": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "integrity": "sha1-KGlFnZqjviRf6P4sofRuLn9U1z8=", "requires": { "pako": "1.0.6" } @@ -1847,7 +1863,7 @@ "anymatch": "2.0.0", "async-each": "1.0.1", "braces": "2.3.2", - "fsevents": "1.2.4", + "fsevents": "1.2.3", "glob-parent": "3.1.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", @@ -2232,6 +2248,11 @@ "date-now": "0.1.4" } }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, "constants-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", @@ -2644,6 +2665,12 @@ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" }, + "deep-extend": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz", + "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==", + "optional": true + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -2716,6 +2743,12 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "optional": true + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -2743,6 +2776,12 @@ "repeating": "2.0.1" } }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "optional": true + }, "detect-node": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz", @@ -2781,7 +2820,7 @@ "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" + "integrity": "sha1-PTH1AZGmdJ3RN1p/Ui6CPULlTto=" }, "drbg.js": { "version": "1.0.1", @@ -2889,7 +2928,7 @@ "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "integrity": "sha1-RoTXF3mtOa8Xfj8AeZb3xnyFJhg=", "requires": { "prr": "1.0.1" } @@ -4218,465 +4257,13 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.3.tgz", + "integrity": "sha512-X+57O5YkDTiEQGiw8i7wYc2nQgweIekqkepI8Q3y4wVlurgBt2SuwxTeYUYMZIGpLZH3r/TsMjczCMXE5ZOt7Q==", "optional": true, "requires": { "nan": "2.9.2", - "node-pre-gyp": "0.10.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "optional": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.3.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.0.1", - "bundled": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.5.1", - "bundled": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "optional": true, - "requires": { - "minipass": "2.2.4" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "optional": true, - "requires": { - "aproba": "1.2.0", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "optional": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.21", - "bundled": true, - "optional": true, - "requires": { - "safer-buffer": "2.1.2" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "optional": true, - "requires": { - "minimatch": "3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "optional": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "requires": { - "brace-expansion": "1.1.11" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true - }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "requires": { - "safe-buffer": "5.1.1", - "yallist": "3.0.2" - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "optional": true, - "requires": { - "minipass": "2.2.4" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "needle": { - "version": "2.2.0", - "bundled": true, - "optional": true, - "requires": { - "debug": "2.6.9", - "iconv-lite": "0.4.21", - "sax": "1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.10.0", - "bundled": true, - "optional": true, - "requires": { - "detect-libc": "1.0.3", - "mkdirp": "0.5.1", - "needle": "2.2.0", - "nopt": "4.0.1", - "npm-packlist": "1.1.10", - "npmlog": "4.1.2", - "rc": "1.2.7", - "rimraf": "2.6.2", - "semver": "5.5.0", - "tar": "4.4.1" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "optional": true, - "requires": { - "abbrev": "1.1.1", - "osenv": "0.1.5" - } - }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true, - "optional": true - }, - "npm-packlist": { - "version": "1.1.10", - "bundled": true, - "optional": true, - "requires": { - "ignore-walk": "3.0.1", - "npm-bundled": "1.0.3" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "optional": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "optional": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "rc": { - "version": "1.2.7", - "bundled": true, - "optional": true, - "requires": { - "deep-extend": "0.5.1", - "ini": "1.3.5", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "optional": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.1.1", - "util-deprecate": "1.0.2" - } - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "optional": true, - "requires": { - "glob": "7.1.2" - } - }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "optional": true - }, - "semver": { - "version": "5.5.0", - "bundled": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "optional": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "optional": true - }, - "tar": { - "version": "4.4.1", - "bundled": true, - "optional": true, - "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", - "yallist": "3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "optional": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "optional": true, - "requires": { - "string-width": "1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true - }, - "yallist": { - "version": "3.0.2", - "bundled": true - } + "node-pre-gyp": "0.9.1" } }, "fstream": { @@ -4700,6 +4287,48 @@ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "optional": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "optional": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=" + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "requires": { + "is-property": "1.0.2" + } + }, "get-caller-file": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", @@ -5208,6 +4837,12 @@ "has-symbol-support-x": "1.4.2" } }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "optional": true + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -5484,6 +5119,15 @@ "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", "dev": true }, + "ignore-walk": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", + "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, "ignorefs": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ignorefs/-/ignorefs-1.2.0.tgz", @@ -5541,6 +5185,12 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "optional": true + }, "inquirer": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", @@ -6097,7 +5747,7 @@ "json-loader": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", - "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==" + "integrity": "sha1-3KFKcCNf+C8KyaOr62DTN6NlGF0=" }, "json-parse-better-errors": { "version": "1.0.1", @@ -7454,6 +7104,17 @@ } } }, + "needle": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.1.tgz", + "integrity": "sha512-t/ZswCM9JTWjAdXS9VpvqhI2Ct2sL2MdY4fUXqGJaGBk13ge99ObqRksRTbBE56K+wxUXwwfZYOuZHifFW9q+Q==", + "optional": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.19", + "sax": "1.2.4" + } + }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", @@ -7512,7 +7173,7 @@ "node-libs-browser": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "integrity": "sha1-X5QmPUBPbkR2fXJpAf/wVHjWAN8=", "requires": { "assert": "1.4.1", "browserify-zlib": "0.2.0", @@ -7544,6 +7205,83 @@ "resolved": "https://registry.npmjs.org/node-object-hash/-/node-object-hash-1.3.0.tgz", "integrity": "sha512-/IHFGoMJWIAcFbrI3KYx6TUmHdBXRZXACAVbkHzYB39JZzoVqgme7wcMnhrOwCvrO8HfIipFTBhELJFMhiw1mg==" }, + "node-pre-gyp": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.9.1.tgz", + "integrity": "sha1-8RwHUW3ZL4cZnbx+GDjqt81WyeA=", + "optional": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.1", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.2" + }, + "dependencies": { + "minipass": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.3.tgz", + "integrity": "sha512-/jAn9/tEX4gnpyRATxgHEOV6xbcyxgT7iUnxo9Y3+OB0zX00TgKIv/2FZCf5brBbICcwbLqVv2ImjvWWrQMSYw==", + "optional": true, + "requires": { + "safe-buffer": "5.1.2", + "yallist": "3.0.2" + } + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "optional": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "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.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.2.tgz", + "integrity": "sha512-BfkE9CciGGgDsATqkikUHrQrraBCO+ke/1f6SFAEMnxyyfN9lxC+nW1NFWMpqH865DhHIy9vQi682gk1X7friw==", + "optional": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.3.3", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.2", + "yallist": "3.0.2" + } + }, + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" + } + } + }, + "node-webcrypto-ossl": { + "version": "1.0.35", + "resolved": "https://registry.npmjs.org/node-webcrypto-ossl/-/node-webcrypto-ossl-1.0.35.tgz", + "integrity": "sha512-KsdlCw0hTmSa4bos7BzEa7Ag9qsDgFAMi/X+Wq+OMpKjjEPZ+JQZKmuU2leiI4dXC6i8RpdGTRFRiw9bvxk8/w==", + "optional": true, + "requires": { + "mkdirp": "0.5.1", + "nan": "2.9.2", + "tslib": "1.9.0", + "webcrypto-core": "0.1.19" + } + }, "nodeify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/nodeify/-/nodeify-1.0.1.tgz", @@ -7596,6 +7334,22 @@ "sort-keys": "1.1.2" } }, + "npm-bundled": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.3.tgz", + "integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==", + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.10.tgz", + "integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==", + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -7604,6 +7358,18 @@ "path-key": "2.0.1" } }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, "num2fraction": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", @@ -7814,7 +7580,7 @@ "os-locale": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "integrity": "sha1-QrwpAKa1uL0XN2yOiCtlr8zyS/I=", "requires": { "execa": "0.7.0", "lcid": "1.0.0", @@ -7826,6 +7592,16 @@ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, "p-cancelable": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", @@ -7836,6 +7612,11 @@ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, + "p-iteration": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/p-iteration/-/p-iteration-1.1.7.tgz", + "integrity": "sha512-VsYvUPjm2edbKkX4QzlASC1qB2e4Z6IE9WPaRVHKwCtobmB6vfUcU9eBOwj1k5uMNi8O6w89QfsDatO5ePSjQg==" + }, "p-limit": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", @@ -7868,7 +7649,7 @@ "pako": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==" + "integrity": "sha1-AQEhG6pwxLykoPY/Igbpe3368lg=" }, "parse-asn1": { "version": "5.1.0", @@ -8858,6 +8639,26 @@ "unpipe": "1.0.0" } }, + "rc": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.7.tgz", + "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", + "optional": true, + "requires": { + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "optional": true + } + } + }, "read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", @@ -10214,8 +10015,7 @@ "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "style-loader": { "version": "0.19.1", @@ -11523,13 +11323,22 @@ } } }, + "webcrypto-core": { + "version": "0.1.19", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-0.1.19.tgz", + "integrity": "sha512-RyaWaYYwFUeWVB1ny8Oj53UQJppNLyz+RWFv0IPP8W6l95kFS+jHS+4vH42o3VJaiom5EIogwmngY57Bwy5DDQ==", + "optional": true, + "requires": { + "tslib": "1.9.0" + } + }, "webcrypto-shim": { "version": "github:dignifiedquire/webcrypto-shim#190bc9ec341375df6025b17ae12ddb2428ea49c8" }, "webpack": { "version": "3.11.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.11.0.tgz", - "integrity": "sha512-3kOFejWqj5ISpJk4Qj/V7w98h9Vl52wak3CLiw/cDOfbVTq7FeoZ0SdoHHY9PYlHr50ZS42OfvzE2vB4nncKQg==", + "integrity": "sha1-d9pFGx17SxF62vQaGpO1dC8k2JQ=", "requires": { "acorn": "5.5.3", "acorn-dynamic-import": "2.0.2", @@ -11597,7 +11406,7 @@ "webpack-sources": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", - "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "integrity": "sha1-oQHrrlnWUHNU1x2AE5UKOot6WlQ=", "requires": { "source-list-map": "2.0.0", "source-map": "0.6.1" @@ -11606,7 +11415,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" } } }, @@ -11642,6 +11451,28 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "optional": true, + "requires": { + "string-width": "1.0.2" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "optional": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, "window-size": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-1.1.0.tgz", diff --git a/package.json b/package.json index c050b697f..fd673bcc6 100644 --- a/package.json +++ b/package.json @@ -54,6 +54,7 @@ "live-plugin-manager": "https://github.com/iurimatias/live-plugin-manager.git", "merge": "^1.2.0", "os-locale": "^2.1.0", + "p-iteration": "^1.1.7", "parse-json": "^4.0.0", "promptly": "^2.1.0", "propose": "0.0.5", diff --git a/templates/boilerplate/config/storage.json b/templates/boilerplate/config/storage.json index f1041e849..da1aa6b74 100644 --- a/templates/boilerplate/config/storage.json +++ b/templates/boilerplate/config/storage.json @@ -4,14 +4,21 @@ "ipfs_bin": "ipfs", "provider": "ipfs", "available_providers": ["ipfs"], - "host": "localhost", - "port": 5001 + "upload": { + "host": "localhost", + "port": 5001 + }, + "dappConnection": [ + {"provider": "ipfs", "host": "localhost", "port": 5001, "getUrl": "http://localhost:8080/ipfs/"} + ] }, "development": { "enabled": true, "provider": "ipfs", - "host": "localhost", - "port": 5001, - "getUrl": "http://localhost:8080/ipfs/" + "upload": { + "host": "localhost", + "port": 5001, + "getUrl": "http://localhost:8080/ipfs/" + } } } diff --git a/templates/boilerplate/embark.json b/templates/boilerplate/embark.json index 40c103a53..d0bfeb7ac 100644 --- a/templates/boilerplate/embark.json +++ b/templates/boilerplate/embark.json @@ -11,7 +11,8 @@ "versions": { "web3": "1.0.0-beta", "solc": "0.4.23", - "ipfs-api": "17.2.4" + "ipfs-api": "17.2.4", + "p-iteration": "1.1.7" }, "plugins": {} } diff --git a/templates/demo/config/storage.json b/templates/demo/config/storage.json index f1041e849..da1aa6b74 100644 --- a/templates/demo/config/storage.json +++ b/templates/demo/config/storage.json @@ -4,14 +4,21 @@ "ipfs_bin": "ipfs", "provider": "ipfs", "available_providers": ["ipfs"], - "host": "localhost", - "port": 5001 + "upload": { + "host": "localhost", + "port": 5001 + }, + "dappConnection": [ + {"provider": "ipfs", "host": "localhost", "port": 5001, "getUrl": "http://localhost:8080/ipfs/"} + ] }, "development": { "enabled": true, "provider": "ipfs", - "host": "localhost", - "port": 5001, - "getUrl": "http://localhost:8080/ipfs/" + "upload": { + "host": "localhost", + "port": 5001, + "getUrl": "http://localhost:8080/ipfs/" + } } } diff --git a/templates/demo/embark.json b/templates/demo/embark.json index 7bd3d48a7..05855ace1 100644 --- a/templates/demo/embark.json +++ b/templates/demo/embark.json @@ -10,7 +10,8 @@ "versions": { "web3": "1.0.0-beta", "solc": "0.4.23", - "ipfs-api": "17.2.4" + "ipfs-api": "17.2.4", + "p-iteration": "1.1.7" }, "plugins": { } diff --git a/templates/demo/test/simple_storage_spec.js b/templates/demo/test/simple_storage_spec.js index 53476a5bf..25855d70c 100644 --- a/templates/demo/test/simple_storage_spec.js +++ b/templates/demo/test/simple_storage_spec.js @@ -17,7 +17,7 @@ describe("SimpleStorage", function() { it("set storage value", async function() { await SimpleStorage.methods.set(150).send(); - let result = SimpleStorage.methods.get().call(); + let result = await SimpleStorage.methods.get().call(); assert.equal(result, 150); }); diff --git a/test_apps/test_app/config/storage.json b/test_apps/test_app/config/storage.json index a226dcb31..139121561 100644 --- a/test_apps/test_app/config/storage.json +++ b/test_apps/test_app/config/storage.json @@ -1,25 +1,39 @@ { "default": { "enabled": true, - "available_providers": ["ipfs", "swarm"], "ipfs_bin": "ipfs", - "provider": "ipfs", - "host": "localhost", - "port": 5001 + + "available_providers": ["ipfs", "swarm"], + + "upload": { + "provider": "ipfs", + "host": "localhost", + "port": 5001 + }, + + "dappConnection": [ + "$BZZ", + {"provider": "swarm", "host": "localhost", "port": 8500, "getUrl": "http://localhost:8500/bzzr:/"}, + {"provider": "ipfs", "host": "localhost", "port": 5001, "getUrl": "http://localhost:8080/ipfs/"} + ] }, "development": { "enabled": true, - "provider": "swarm", - "host": "swarm-gateways.net", - "port": false, - "getUrl": "http://swarm-gateways.net/bzzr:/" + "upload": { + "provider": "swarm", + "host": "localhost", + "port": 8500, + "getUrl": "http://localhost:8500/bzzr:/" + } }, "livenet": { "enabled": true, - "provider": "ipfs", - "host": "ipfs.infura.io", - "protocol": "https", - "port": false, - "getUrl": "https://ipfs.infura.io/ipfs/" + "upload":{ + "provider": "ipfs", + "host": "ipfs.infura.io", + "protocol": "https", + "port": false, + "getUrl": "https://ipfs.infura.io/ipfs/" + } } -} +} \ No newline at end of file diff --git a/test_apps/test_app/embark.json b/test_apps/test_app/embark.json index 66dfb0066..1ae6c1629 100644 --- a/test_apps/test_app/embark.json +++ b/test_apps/test_app/embark.json @@ -17,7 +17,8 @@ "versions": { "solc": "0.4.18", "web3": "1.0.0-beta.34", - "ipfs-api": "17.2.7" + "ipfs-api": "17.2.7", + "p-iteration": "1.1.7" }, "plugins": { "embark-service": {}