diff --git a/.eslintrc.json b/.eslintrc.json index ce639c6c6..4723ecbff 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,6 +9,9 @@ "sourceType": "module", "ecmaVersion": 2017 }, + "globals": { + "__": true + }, "rules": { "accessor-pairs": "error", "array-bracket-newline": "error", diff --git a/.travis.yml b/.travis.yml index 1019d91d8..b9912bde4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: node_js node_js: - - "7" + - "8" addons: code_climate: repo_token: 7454b1a666015e244c384d19f48c34e35d1ae58c3aa428ec542f10bbcb848358 diff --git a/js/embark.js b/js/embark.js index 912ab4157..90cab289f 100644 --- a/js/embark.js +++ b/js/embark.js @@ -1,170 +1,235 @@ -var EmbarkJS = {}; +var EmbarkJS = { + onReady: function (cb) { + if (typeof (__embarkContext) === 'undefined') { + return cb(); + } + return __embarkContext.execWhenReady(cb); + } +}; -EmbarkJS.isNewWeb3 = function() { - var _web3 = new Web3(); +EmbarkJS.isNewWeb3 = function (web3Obj) { + var _web3 = web3Obj || (new Web3()); if (typeof(_web3.version) === "string") { return true; } return parseInt(_web3.version.api.split('.')[0], 10) >= 1; }; -EmbarkJS.Contract = function(options) { - var self = this; - var i, abiElement; - var ContractClass; +EmbarkJS.Contract = function (options) { + var self = this; + var i, abiElement; + var ContractClass; - this.abi = options.abi; - this.address = options.address; - this.code = '0x' + options.code; - //this.web3 = options.web3 || web3; - this.web3 = options.web3 || window.web3; + this.abi = options.abi; + this.address = options.address; + this.gas = options.gas; + this.code = '0x' + options.code; + //this.web3 = options.web3 || web3; + this.web3 = options.web3; + if (!this.web3 && typeof (web3) !== 'undefined') { + this.web3 = web3; + } else if (!this.web3) { + this.web3 = window.web3; + } - if (EmbarkJS.isNewWeb3()) { - // TODO: - // add default **from** address - // add gasPrice - ContractClass = new this.web3.eth.Contract(this.abi, this.address); - ContractClass.setProvider(this.web3.currentProvider); - ContractClass.options.data = this.code; + if (EmbarkJS.isNewWeb3(this.web3)) { + ContractClass = new this.web3.eth.Contract(this.abi, this.address); + ContractClass.setProvider(this.web3.currentProvider); + ContractClass.options.data = this.code; + ContractClass.options.from = this.from || this.web3.eth.defaultAccount; + ContractClass.abi = ContractClass.options.abi; + ContractClass.address = this.address; + ContractClass.gas = this.gas; - return ContractClass; - } else { - ContractClass = this.web3.eth.contract(this.abi); + let originalMethods = Object.keys(ContractClass); - this.eventList = []; - - if (this.abi) { - for (i = 0; i < this.abi.length; i++) { - abiElement = this.abi[i]; - if (abiElement.type === 'event') { - this.eventList.push(abiElement.name); - } - } + ContractClass._jsonInterface.forEach((abi) => { + if (originalMethods.indexOf(abi.name) >= 0) { + console.log(abi.name + " is a reserved word and cannot be used as a contract method, property or event"); + return; } - var messageEvents = function() { - this.cb = function() {}; + if (!abi.inputs) { + return; + } + + let numExpectedInputs = abi.inputs.length; + + if (abi.type === 'function' && abi.constant) { + ContractClass[abi.name] = function () { + let options = {}, cb = null, args = Array.from(arguments || []).slice(0, numExpectedInputs); + if (typeof (arguments[numExpectedInputs]) === 'function') { + cb = arguments[numExpectedInputs]; + } else if (typeof (arguments[numExpectedInputs]) === 'object') { + options = arguments[numExpectedInputs]; + cb = arguments[numExpectedInputs + 1]; + } + + let ref = ContractClass.methods[abi.name]; + let call = ref.apply(ref, ...arguments).call; + return call.apply(call, []); + }; + } else if (abi.type === 'function') { + ContractClass[abi.name] = function () { + let options = {}, cb = null, args = Array.from(arguments || []).slice(0, numExpectedInputs); + if (typeof (arguments[numExpectedInputs]) === 'function') { + cb = arguments[numExpectedInputs]; + } else if (typeof (arguments[numExpectedInputs]) === 'object') { + options = arguments[numExpectedInputs]; + cb = arguments[numExpectedInputs + 1]; + } + + let ref = ContractClass.methods[abi.name]; + let send = ref.apply(ref, args).send; + return send.apply(send, [options, cb]); + }; + } else if (abi.type === 'event') { + ContractClass[abi.name] = function (options, cb) { + let ref = ContractClass.events[abi.name]; + return ref.apply(ref, [options, cb]); + }; + } + }); + + return ContractClass; + } else { + ContractClass = this.web3.eth.contract(this.abi); + + this.eventList = []; + + if (this.abi) { + for (i = 0; i < this.abi.length; i++) { + abiElement = this.abi[i]; + if (abiElement.type === 'event') { + this.eventList.push(abiElement.name); + } + } + } + + var messageEvents = function () { + this.cb = function () { }; + }; - messageEvents.prototype.then = function(cb) { - this.cb = cb; - }; + messageEvents.prototype.then = function (cb) { + this.cb = cb; + }; - messageEvents.prototype.error = function(err) { - return err; - }; + messageEvents.prototype.error = function (err) { + return err; + }; - this._originalContractObject = ContractClass.at(this.address); - this._methods = Object.getOwnPropertyNames(this._originalContractObject).filter(function(p) { - // TODO: check for forbidden properties - if (self.eventList.indexOf(p) >= 0) { + this._originalContractObject = ContractClass.at(this.address); + this._methods = Object.getOwnPropertyNames(this._originalContractObject).filter(function (p) { + // TODO: check for forbidden properties + if (self.eventList.indexOf(p) >= 0) { - self[p] = function() { - var promise = new messageEvents(); - var args = Array.prototype.slice.call(arguments); - args.push(function(err, result) { + self[p] = function () { + var promise = new messageEvents(); + var args = Array.prototype.slice.call(arguments); + args.push(function (err, result) { + if (err) { + promise.error(err); + } else { + promise.cb(result); + } + }); + + self._originalContractObject[p].apply(self._originalContractObject[p], args); + return promise; + }; + return true; + } else if (typeof self._originalContractObject[p] === 'function') { + self[p] = function (_args) { + var args = Array.prototype.slice.call(arguments); + var fn = self._originalContractObject[p]; + var props = self.abi.find((x) => x.name == p); + + var promise = new Promise(function (resolve, reject) { + args.push(function (err, transaction) { + promise.tx = transaction; if (err) { - promise.error(err); + return reject(err); + } + + var getConfirmation = function () { + self.web3.eth.getTransactionReceipt(transaction, function (err, receipt) { + if (err) { + return reject(err); + } + + if (receipt !== null) { + return resolve(receipt); + } + + setTimeout(getConfirmation, 1000); + }); + }; + + if (typeof transaction !== "string" || props.constant) { + resolve(transaction); } else { - promise.cb(result); + getConfirmation(); } }); - self._originalContractObject[p].apply(self._originalContractObject[p], args); - return promise; - }; - return true; - } else if (typeof self._originalContractObject[p] === 'function') { - self[p] = function(_args) { - var args = Array.prototype.slice.call(arguments); - var fn = self._originalContractObject[p]; - var props = self.abi.find((x) => x.name == p); + fn.apply(fn, args); + }); - var promise = new Promise(function(resolve, reject) { - args.push(function(err, transaction) { - promise.tx = transaction; - if (err) { - return reject(err); - } - - var getConfirmation = function() { - self.web3.eth.getTransactionReceipt(transaction, function(err, receipt) { - if (err) { - return reject(err); - } - - if (receipt !== null) { - return resolve(receipt); - } - - setTimeout(getConfirmation, 1000); - }); - }; - - if (typeof(transaction) !== "string" || props.constant) { - resolve(transaction); - } else { - getConfirmation(); - } - }); - - fn.apply(fn, args); - }); - - return promise; - }; - return true; - } - return false; - }); - } + return promise; + }; + return true; + } + return false; + }); + } }; -EmbarkJS.Contract.prototype.deploy = function(args, _options) { - var self = this; - var contractParams; - var options = _options || {}; +EmbarkJS.Contract.prototype.deploy = function (args, _options) { + var self = this; + var contractParams; + var options = _options || {}; - contractParams = args || []; + contractParams = args || []; - contractParams.push({ - from: this.web3.eth.accounts[0], - data: this.code, - gas: options.gas || 800000 + contractParams.push({ + from: this.web3.eth.accounts[0], + data: this.code, + gas: options.gas || 800000 + }); + + var contractObject = this.web3.eth.contract(this.abi); + + var promise = new Promise(function (resolve, reject) { + contractParams.push(function (err, transaction) { + if (err) { + reject(err); + } else if (transaction.address !== undefined) { + resolve(new EmbarkJS.Contract({ + abi: self.abi, + code: self.code, + address: transaction.address + })); + } }); - var contractObject = this.web3.eth.contract(this.abi); - - var promise = new Promise(function(resolve, reject) { - contractParams.push(function(err, transaction) { - if (err) { - reject(err); - } else if (transaction.address !== undefined) { - resolve(new EmbarkJS.Contract({ - abi: self.abi, - code: self.code, - address: transaction.address - })); - } - }); - - // returns promise - // deploys contract - // wraps it around EmbarkJS.Contract - contractObject["new"].apply(contractObject, contractParams); - }); + // returns promise + // deploys contract + // wraps it around EmbarkJS.Contract + contractObject["new"].apply(contractObject, contractParams); + }); - return promise; + return promise; }; EmbarkJS.Contract.prototype.new = EmbarkJS.Contract.prototype.deploy; -EmbarkJS.Contract.prototype.at = function(address) { - return new EmbarkJS.Contract({ abi: this.abi, code: this.code, address: address }); +EmbarkJS.Contract.prototype.at = function (address) { + return new EmbarkJS.Contract({abi: this.abi, code: this.code, address: address}); }; -EmbarkJS.Contract.prototype.send = function(value, unit, _options) { +EmbarkJS.Contract.prototype.send = function (value, unit, _options) { var options, wei; if (typeof unit === 'object') { options = unit; @@ -184,51 +249,54 @@ EmbarkJS.Storage = {}; EmbarkJS.Storage.Providers = {}; -EmbarkJS.Storage.saveText = function(text) { +EmbarkJS.Storage.saveText = function (text) { if (!this.currentStorage) { throw new Error('Storage provider not set; e.g EmbarkJS.Storage.setProvider("ipfs")'); } return this.currentStorage.saveText(text); }; -EmbarkJS.Storage.get = function(hash) { +EmbarkJS.Storage.get = function (hash) { if (!this.currentStorage) { throw new Error('Storage provider not set; e.g EmbarkJS.Storage.setProvider("ipfs")'); } return this.currentStorage.get(hash); }; -EmbarkJS.Storage.uploadFile = function(inputSelector) { +EmbarkJS.Storage.uploadFile = function (inputSelector) { if (!this.currentStorage) { throw new Error('Storage provider not set; e.g EmbarkJS.Storage.setProvider("ipfs")'); } return this.currentStorage.uploadFile(inputSelector); }; -EmbarkJS.Storage.getUrl = function(hash) { +EmbarkJS.Storage.getUrl = function (hash) { if (!this.currentStorage) { throw new Error('Storage provider not set; e.g EmbarkJS.Storage.setProvider("ipfs")'); } return this.currentStorage.getUrl(hash); }; -EmbarkJS.Storage.registerProvider = function(providerName, obj) { +EmbarkJS.Storage.registerProvider = function (providerName, obj) { EmbarkJS.Storage.Providers[providerName] = obj; }; -EmbarkJS.Storage.setProvider = function(provider, options) { +EmbarkJS.Storage.setProvider = function (provider, options) { let providerObj = this.Providers[provider]; if (!providerObj) { throw new Error('Unknown storage provider'); - } + } this.currentStorage = providerObj; return providerObj.setProvider(options); }; -EmbarkJS.Storage.isAvailable = function(){ +EmbarkJS.Storage.isAvailable = function () { + if (!this.currentStorage) { + throw new Error('Storage provider not set; e.g EmbarkJS.Storage.setProvider("ipfs")'); + } return this.currentStorage.isAvailable(); }; @@ -236,11 +304,11 @@ EmbarkJS.Messages = {}; EmbarkJS.Messages.Providers = {}; -EmbarkJS.Messages.registerProvider = function(providerName, obj) { +EmbarkJS.Messages.registerProvider = function (providerName, obj) { EmbarkJS.Messages.Providers[providerName] = obj; }; -EmbarkJS.Messages.setProvider = function(provider, options) { +EmbarkJS.Messages.setProvider = function (provider, options) { let providerObj = this.Providers[provider]; if (!providerObj) { @@ -252,30 +320,75 @@ EmbarkJS.Messages.setProvider = function(provider, options) { return providerObj.setProvider(options); }; -EmbarkJS.Messages.isAvailable = function(){ +EmbarkJS.Messages.isAvailable = function () { return this.currentMessages.isAvailable(); }; -EmbarkJS.Messages.sendMessage = function(options) { +EmbarkJS.Messages.sendMessage = function (options) { if (!this.currentMessages) { throw new Error('Messages provider not set; e.g EmbarkJS.Messages.setProvider("whisper")'); } return this.currentMessages.sendMessage(options); }; -EmbarkJS.Messages.listenTo = function(options, callback) { +EmbarkJS.Messages.listenTo = function (options, callback) { if (!this.currentMessages) { throw new Error('Messages provider not set; e.g EmbarkJS.Messages.setProvider("whisper")'); } return this.currentMessages.listenTo(options, callback); }; +EmbarkJS.Names = {}; + +EmbarkJS.Names.Providers = {}; + +EmbarkJS.Names.registerProvider = function (providerName, obj) { + EmbarkJS.Names.Providers[providerName] = obj; +}; + +EmbarkJS.Names.setProvider = function (provider, options) { + let providerObj = this.Providers[provider]; + + if (!providerObj) { + throw new Error('Unknown name system provider'); + } + + this.currentNameSystems = providerObj; + + return providerObj.setProvider(options); +}; + +// resolve resolves a name into an identifier of some kind +EmbarkJS.Names.resolve = function (name) { + if (!this.currentNameSystems) { + throw new Error('Name system provider not set; e.g EmbarkJS.Names.setProvider("ens")'); + } + return this.currentNameSystems.resolve(name); +}; + +// the reverse of resolve, resolves using an identifier to get to a name +EmbarkJS.Names.lookup = function (identifier) { + if (!this.currentNameSystems) { + throw new Error('Name system provider not set; e.g EmbarkJS.Names.setProvider("ens")'); + } + return this.currentNameSystems.lookup(identifier); +}; + +// To Implement + +/* +// register a name +EmbarkJS.Names.register = function(name, options) { + +} +*/ + EmbarkJS.Utils = { - fromAscii: function(str) { + fromAscii: function (str) { var _web3 = new Web3(); return _web3.utils ? _web3.utils.fromAscii(str) : _web3.fromAscii(str); }, - toAscii: function(str) { + toAscii: function (str) { var _web3 = new Web3(); return _web3.utils.toAscii(str); } diff --git a/js/embark_node.js b/js/embark_node.js new file mode 100644 index 000000000..f93916b22 --- /dev/null +++ b/js/embark_node.js @@ -0,0 +1,396 @@ +var EmbarkJS = { + onReady: function(cb) { + if (typeof (__embarkContext) === 'undefined') { + return cb(); + } + return __embarkContext.execWhenReady(cb); + } +}; + +EmbarkJS.isNewWeb3 = function(web3Obj) { + var _web3 = web3Obj || (new Web3()); + if (typeof(_web3.version) === "string") { + return true; + } + return parseInt(_web3.version.api.split('.')[0], 10) >= 1; +}; + +EmbarkJS.Contract = function(options) { + var self = this; + var i, abiElement; + var ContractClass; + + this.abi = options.abi; + this.address = options.address; + this.gas = options.gas; + this.code = '0x' + options.code; + //this.web3 = options.web3 || web3; + this.web3 = options.web3; + if (!this.web3 && typeof (web3) !== 'undefined') { + this.web3 = web3; + } else if (!this.web3) { + this.web3 = window.web3; + } + + if (EmbarkJS.isNewWeb3(this.web3)) { + ContractClass = new this.web3.eth.Contract(this.abi, this.address); + ContractClass.setProvider(this.web3.currentProvider); + ContractClass.options.data = this.code; + ContractClass.options.from = this.from || this.web3.eth.defaultAccount; + ContractClass.abi = ContractClass.options.abi; + ContractClass.address = this.address; + ContractClass.gas = this.gas; + + let originalMethods = Object.keys(ContractClass); + + ContractClass._jsonInterface.forEach((abi) => { + if (originalMethods.indexOf(abi.name) >= 0) { + console.log(abi.name + " is a reserved word and cannot be used as a contract method, property or event"); + return; + } + + if (!abi.inputs) { + return; + } + + let numExpectedInputs = abi.inputs.length; + + if (abi.type === 'function' && abi.constant) { + ContractClass[abi.name] = function() { + let options = {}, cb = null, args = Array.from(arguments || []).slice(0, numExpectedInputs); + if (typeof (arguments[numExpectedInputs]) === 'function') { + cb = arguments[numExpectedInputs]; + } else if (typeof (arguments[numExpectedInputs]) === 'object') { + options = arguments[numExpectedInputs]; + cb = arguments[numExpectedInputs + 1]; + } + + let ref = ContractClass.methods[abi.name]; + let call = ref.apply(ref, ...arguments).call; + return call.apply(call, []); + }; + } else if (abi.type === 'function') { + ContractClass[abi.name] = function() { + let options = {}, cb = null, args = Array.from(arguments || []).slice(0, numExpectedInputs); + if (typeof (arguments[numExpectedInputs]) === 'function') { + cb = arguments[numExpectedInputs]; + } else if (typeof (arguments[numExpectedInputs]) === 'object') { + options = arguments[numExpectedInputs]; + cb = arguments[numExpectedInputs + 1]; + } + + let ref = ContractClass.methods[abi.name]; + let send = ref.apply(ref, args).send; + return send.apply(send, [options, cb]); + }; + } else if (abi.type === 'event') { + ContractClass[abi.name] = function(options, cb) { + let ref = ContractClass.events[abi.name]; + return ref.apply(ref, [options, cb]); + } + } + }); + + return ContractClass; + } else { + ContractClass = this.web3.eth.contract(this.abi); + + this.eventList = []; + + if (this.abi) { + for (i = 0; i < this.abi.length; i++) { + abiElement = this.abi[i]; + if (abiElement.type === 'event') { + this.eventList.push(abiElement.name); + } + } + } + + var messageEvents = function() { + this.cb = function() {}; + }; + + messageEvents.prototype.then = function(cb) { + this.cb = cb; + }; + + messageEvents.prototype.error = function(err) { + return err; + }; + + this._originalContractObject = ContractClass.at(this.address); + this._methods = Object.getOwnPropertyNames(this._originalContractObject).filter(function(p) { + // TODO: check for forbidden properties + if (self.eventList.indexOf(p) >= 0) { + + self[p] = function() { + var promise = new messageEvents(); + var args = Array.prototype.slice.call(arguments); + args.push(function(err, result) { + if (err) { + promise.error(err); + } else { + promise.cb(result); + } + }); + + self._originalContractObject[p].apply(self._originalContractObject[p], args); + return promise; + }; + return true; + } else if (typeof self._originalContractObject[p] === 'function') { + self[p] = function(_args) { + var args = Array.prototype.slice.call(arguments); + var fn = self._originalContractObject[p]; + var props = self.abi.find((x) => x.name == p); + + var promise = new Promise(function(resolve, reject) { + args.push(function(err, transaction) { + promise.tx = transaction; + if (err) { + return reject(err); + } + + var getConfirmation = function() { + self.web3.eth.getTransactionReceipt(transaction, function(err, receipt) { + if (err) { + return reject(err); + } + + if (receipt !== null) { + return resolve(receipt); + } + + setTimeout(getConfirmation, 1000); + }); + }; + + if (typeof(transaction) !== "string" || props.constant) { + resolve(transaction); + } else { + getConfirmation(); + } + }); + + fn.apply(fn, args); + }); + + return promise; + }; + return true; + } + return false; + }); + } +}; + +EmbarkJS.Contract.prototype.deploy = function(args, _options) { + var self = this; + var contractParams; + var options = _options || {}; + + contractParams = args || []; + + contractParams.push({ + from: this.web3.eth.accounts[0], + data: this.code, + gas: options.gas || 800000 + }); + + var contractObject = this.web3.eth.contract(this.abi); + + var promise = new Promise(function(resolve, reject) { + contractParams.push(function(err, transaction) { + if (err) { + reject(err); + } else if (transaction.address !== undefined) { + resolve(new EmbarkJS.Contract({ + abi: self.abi, + code: self.code, + address: transaction.address + })); + } + }); + + // returns promise + // deploys contract + // wraps it around EmbarkJS.Contract + contractObject["new"].apply(contractObject, contractParams); + }); + + + return promise; +}; + +EmbarkJS.Contract.prototype.new = EmbarkJS.Contract.prototype.deploy; + +EmbarkJS.Contract.prototype.at = function(address) { + return new EmbarkJS.Contract({ abi: this.abi, code: this.code, address: address }); +}; + +EmbarkJS.Contract.prototype.send = function(value, unit, _options) { + var options, wei; + if (typeof unit === 'object') { + options = unit; + wei = value; + } else { + options = _options || {}; + wei = this.web3.toWei(value, unit); + } + + options.to = this.address; + options.value = wei; + + this.web3.eth.sendTransaction(options); +}; + +EmbarkJS.Storage = {}; + +EmbarkJS.Storage.Providers = {}; + +EmbarkJS.Storage.saveText = function(text) { + if (!this.currentStorage) { + throw new Error('Storage provider not set; e.g EmbarkJS.Storage.setProvider("ipfs")'); + } + return this.currentStorage.saveText(text); +}; + +EmbarkJS.Storage.get = function(hash) { + if (!this.currentStorage) { + throw new Error('Storage provider not set; e.g EmbarkJS.Storage.setProvider("ipfs")'); + } + return this.currentStorage.get(hash); +}; + +EmbarkJS.Storage.uploadFile = function(inputSelector) { + if (!this.currentStorage) { + throw new Error('Storage provider not set; e.g EmbarkJS.Storage.setProvider("ipfs")'); + } + return this.currentStorage.uploadFile(inputSelector); +}; + +EmbarkJS.Storage.getUrl = function(hash) { + if (!this.currentStorage) { + throw new Error('Storage provider not set; e.g EmbarkJS.Storage.setProvider("ipfs")'); + } + return this.currentStorage.getUrl(hash); +}; + +EmbarkJS.Storage.registerProvider = function(providerName, obj) { + EmbarkJS.Storage.Providers[providerName] = obj; +}; + +EmbarkJS.Storage.setProvider = function(provider, options) { + let providerObj = this.Providers[provider]; + + if (!providerObj) { + throw new Error('Unknown storage provider'); + } + + this.currentStorage = providerObj; + + return providerObj.setProvider(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(); +}; + +EmbarkJS.Messages = {}; + +EmbarkJS.Messages.Providers = {}; + +EmbarkJS.Messages.registerProvider = function(providerName, obj) { + EmbarkJS.Messages.Providers[providerName] = obj; +}; + +EmbarkJS.Messages.setProvider = function(provider, options) { + let providerObj = this.Providers[provider]; + + if (!providerObj) { + throw new Error('Unknown messages provider'); + } + + this.currentMessages = providerObj; + + 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")'); + } + return this.currentMessages.sendMessage(options); +}; + +EmbarkJS.Messages.listenTo = function(options, callback) { + if (!this.currentMessages) { + throw new Error('Messages provider not set; e.g EmbarkJS.Messages.setProvider("whisper")'); + } + return this.currentMessages.listenTo(options, callback); +}; + +EmbarkJS.Names = {}; + +EmbarkJS.Names.Providers = {}; + +EmbarkJS.Names.registerProvider = function(providerName, obj) { + EmbarkJS.Names.Providers[providerName] = obj; +} + +EmbarkJS.Names.setProvider = function(provider, options) { + let providerObj = this.Providers[provider]; + + if (!providerObj) { + throw new Error('Unknown name system provider'); + } + + this.currentNameSystems = providerObj; + + return providerObj.setProvider(options); +}; + +// resolve resolves a name into an identifier of some kind +EmbarkJS.Names.resolve = function(name) { + if (!this.currentNameSystems) { + throw new Error('Name system provider not set; e.g EmbarkJS.Names.setProvider("ens")'); + } + return this.currentNameSystems.resolve(name); +} + +// the reverse of resolve, resolves using an identifier to get to a name +EmbarkJS.Names.lookup = function(identifier) { + if (!this.currentNameSystems) { + throw new Error('Name system provider not set; e.g EmbarkJS.Names.setProvider("ens")'); + } + return this.currentNameSystems.lookup(identifier); +} + +// To Implement + +/* +// register a name +EmbarkJS.Names.register = function(name, options) { + +} +*/ + +EmbarkJS.Utils = { + fromAscii: function(str) { + var _web3 = new Web3(); + return _web3.utils ? _web3.utils.fromAscii(str) : _web3.fromAscii(str); + }, + toAscii: function(str) { + var _web3 = new Web3(); + return _web3.utils.toAscii(str); + } +}; + +module.exports = EmbarkJS; diff --git a/js/embarkjs/orbit.js b/js/embarkjs/orbit.js deleted file mode 100644 index 0ba8e156b..000000000 --- a/js/embarkjs/orbit.js +++ /dev/null @@ -1,95 +0,0 @@ -EmbarkJS.Messages.Orbit = {}; - -EmbarkJS.Messages.Orbit.setProvider = function(options) { - this.providerName = 'orbit'; - this.currentMessages = EmbarkJS.Messages.Orbit; - if (options === undefined) { - ipfs = HaadIpfsApi('localhost', '5001'); - } else { - ipfs = HaadIpfsApi(options.host, options.port); - } - this.currentMessages.orbit = new Orbit(ipfs); - if (typeof(web3) === "undefined") { - this.currentMessages.orbit.connect(Math.random().toString(36).substring(2)); - } else { - this.currentMessages.orbit.connect(web3.eth.accounts[0]); - } -}; - -EmbarkJS.Messages.Orbit.sendMessage = function(options) { - var topics = options.topic || options.topics; - var data = options.data || options.payload; - - if (topics === undefined) { - throw new Error("missing option: topic"); - } - - if (data === undefined) { - throw new Error("missing option: data"); - } - - if (typeof topics === 'string') { - topics = topics; - } else { - // TODO: better to just send to different channels instead - topics = topics.join(','); - } - - this.orbit.join(topics); - - var payload = JSON.stringify(data); - - this.orbit.send(topics, data); -}; - -EmbarkJS.Messages.Orbit.listenTo = function(options) { - var self = this; - var topics = options.topic || options.topics; - - if (typeof topics === 'string') { - topics = topics; - } else { - topics = topics.join(','); - } - - this.orbit.join(topics); - - var messageEvents = function() { - this.cb = function() {}; - }; - - messageEvents.prototype.then = function(cb) { - this.cb = cb; - }; - - messageEvents.prototype.error = function(err) { - return err; - }; - - var promise = new messageEvents(); - - this.orbit.events.on('message', (channel, message) => { - // TODO: looks like sometimes it's receving messages from all topics - if (topics !== channel) return; - self.orbit.getPost(message.payload.value, true).then((post) => { - var data = { - topic: channel, - data: post.content, - from: post.meta.from.name, - time: (new Date(post.meta.ts)) - }; - promise.cb(post.content, data, post); - }); - }); - - 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/cmd.js b/lib/cmd.js index ebc82b249..2f09eb5dd 100644 --- a/lib/cmd.js +++ b/lib/cmd.js @@ -1,7 +1,6 @@ const program = require('commander'); -const promptly = require('promptly'); -const utils = require('./utils/utils.js'); const Embark = require('../lib/index'); +const i18n = require('./i18n/i18n.js'); let embark = new Embark; class Cmd { @@ -37,22 +36,25 @@ class Cmd { try { if (value.match(/^[a-zA-Z\s-]+$/)) return value; } catch (e) { - throw new Error('Name must be only letters, spaces, or dashes'); + throw new Error(__('Name must be only letters, spaces, or dashes')); } }; program .command('new [name]') - .description('new application') - .option('--simple', 'create a barebones project meant only for contract development') + .description(__('New Application')) + .option('--simple', __('create a barebones project meant only for contract development')) + .option('--locale [locale]', __('language to use (default: en)')) .action(function (name, options) { + i18n.setOrDetectLocale(options.locale); if (name === undefined) { - return promptly.prompt("Name your app (default is embarkDApp):", { + const promptly = require('promptly'); + return promptly.prompt(__("Name your app (default is %s):", 'embarkDapp'), { default: "embarkDApp", validator: validateName }, function (err, inputvalue) { if (err) { - console.error('Invalid name:', err.message); + console.error(__('Invalid name') + ':', err.message); // Manually call retry // The passed error has a retry method to easily prompt again. err.retry(); @@ -78,8 +80,10 @@ class Cmd { demo() { program .command('demo') - .description('create a working dapp with a SimpleStorage contract') - .action(function () { + .option('--locale [locale]', __('language to use (default: en)')) + .description(__('create a working dapp with a SimpleStorage contract')) + .action(function (options) { + i18n.setOrDetectLocale(options.locale); embark.generateTemplate('demo', './', 'embark_demo'); }); } @@ -87,13 +91,19 @@ class Cmd { build() { program .command('build [environment]') - .option('--logfile [logfile]', 'filename to output logs (default: none)') - .option('--loglevel [loglevel]', 'level of logging to display ["error", "warn", "info", "debug", "trace"]', /^(error|warn|info|debug|trace)$/i, 'debug') - .description('deploy and build dapp at dist/ (default: development)') + .option('--contracts', 'only compile contracts into Embark wrappers') + .option('--logfile [logfile]', __('filename to output logs (default: none)')) + .option('-c, --client [client]', __('Use a specific ethereum client or simulator (supported: %s)', 'geth, testrpc')) + .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)')) + .description(__('deploy and build dapp at ') + 'dist/ (default: development)') .action(function (env, _options) { + i18n.setOrDetectLocale(_options.locale); _options.env = env || 'development'; _options.logFile = _options.logfile; // fix casing _options.logLevel = _options.loglevel; // fix casing + _options.onlyCompile = _options.contracts; + _options.client = _options.client || 'geth'; embark.build(_options); }); } @@ -101,19 +111,24 @@ class Cmd { run() { program .command('run [environment]') - .option('-p, --port [port]', 'port to run the dev webserver (default: 8000)') - .option('-b, --host [host]', 'host to run the dev webserver (default: localhost)') - .option('--noserver', 'disable the development webserver') - .option('--nodashboard', 'simple mode, disables the dashboard') - .option('--no-color', 'no colors in case it\'s needed for compatbility purposes') - .option('--logfile [logfile]', 'filename to output logs (default: none)') - .option('--loglevel [loglevel]', 'level of logging to display ["error", "warn", "info", "debug", "trace"]', /^(error|warn|info|debug|trace)$/i, 'debug') - .description('run dapp (default: development)') + .option('-p, --port [port]', __('port to run the dev webserver (default: %s)', '8000')) + .option('-c, --client [client]', __('Use a specific ethereum client or simulator (supported: %s)', 'geth, testrpc')) + .option('-b, --host [host]', __('host to run the dev webserver (default: %s)', 'localhost')) + .option('--noserver', __('disable the development webserver')) + .option('--nodashboard', __('simple mode, disables the dashboard')) + .option('--no-color', __('no colors in case it\'s needed for compatbility purposes')) + .option('--logfile [logfile]', __('filename to output logs (default: %s)', 'none')) + .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)')) + .description(__('run dapp (default: %s)', 'development')) .action(function (env, options) { + i18n.setOrDetectLocale(options.locale); embark.run({ env: env || 'development', serverPort: options.port, serverHost: options.host, + client: options.client || 'geth', + locale: options.locale, runWebserver: !options.noserver, useDashboard: !options.nodashboard, logFile: options.logfile, @@ -125,9 +140,11 @@ class Cmd { blockchain() { program .command('blockchain [environment]') - .option('-c, --client [client]', 'Use a specific ethereum client or simulator (supported: geth, testrpc)') - .description('run blockchain server (default: development)') + .option('-c, --client [client]', __('Use a specific ethereum client or simulator (supported: %s)', 'geth, testrpc')) + .option('--locale [locale]', __('language to use (default: en)')) + .description(__('run blockchain server (default: %s)', 'development')) .action(function (env, options) { + i18n.setOrDetectLocale(options.locale); embark.initConfig(env || 'development', { embarkConfig: 'embark.json', interceptLogs: false @@ -139,15 +156,17 @@ class Cmd { simulator() { program .command('simulator [environment]') - .description('run a fast ethereum rpc simulator') - .option('--testrpc', 'use testrpc as the rpc simulator [default]') - .option('-p, --port [port]', 'port to run the rpc simulator (default: 8545)') - .option('-h, --host [host]', 'host to run the rpc simulator (default: localhost)') - .option('-a, --accounts [numAccounts]', 'number of accounts (default: 10)') - .option('-e, --defaultBalanceEther [balance]', 'Amount of ether to assign each test account (default: 100)') - .option('-l, --gasLimit [gasLimit]', 'custom gas limit (default: 8000000)') + .description(__('run a fast ethereum rpc simulator')) + .option('--testrpc', __('use testrpc as the rpc simulator [%s]', 'default')) + .option('-p, --port [port]', __('port to run the rpc simulator (default: %s)', '8545')) + .option('-h, --host [host]', __('host to run the rpc simulator (default: %s)', 'localhost')) + .option('-a, --accounts [numAccounts]', __('number of accounts (default: %s)', '10')) + .option('-e, --defaultBalanceEther [balance]', __('Amount of ether to assign each test account (default: %s)', '100')) + .option('-l, --gasLimit [gasLimit]', __('custom gas limit (default: %s)', '8000000')) + .option('--locale [locale]', __('language to use (default: en)')) .action(function (env, options) { + i18n.setOrDetectLocale(options.locale); embark.initConfig(env || 'development', { embarkConfig: 'embark.json', interceptLogs: false @@ -165,37 +184,53 @@ class Cmd { test() { program .command('test [file]') - .description('run tests') - .action(function (file) { - embark.initConfig('development', { - embarkConfig: 'embark.json', interceptLogs: false - }); - embark.runTests(file); + .option('--locale [locale]', __('language to use (default: en)')) + .option('--loglevel [loglevel]', __('level of logging to display') + ' ["error", "warn", "info", "debug", "trace"]', /^(error|warn|info|debug|trace)$/i, 'warn') + .description(__('run tests')) + .action(function (file, options) { + i18n.setOrDetectLocale(options.locale); + embark.runTests({file, loglevel: options.loglevel}); }); } upload() { program - .command('upload [environment]') - .option('--logfile [logfile]', 'filename to output logs (default: none)') - .option('--loglevel [loglevel]', 'level of logging to display ["error", "warn", "info", "debug", "trace"]', /^(error|warn|info|debug|trace)$/i, 'debug') - .description('Upload your dapp to a decentralized storage (e.g embark upload ipfs).') - .action(function (platform, env, _options) { + .command('upload [environment]') + .option('--logfile [logfile]', __('filename to output logs (default: %s)', 'none')) + .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') + '.') + .action(function (env, _options) { + i18n.setOrDetectLocale(_options.locale); + if (env === "ipfs" || env === "swarm") { + console.warn(("did you mean " + "embark upload".bold + " ?").underline); + console.warn("In embark 3.1 forwards, the correct command is embark upload and the provider is configured in config/storage.js"); + } _options.env = env || 'development'; _options.logFile = _options.logfile; // fix casing _options.logLevel = _options.loglevel; // fix casing - embark.upload(platform, _options); + _options.client = _options.client || 'geth'; + embark.upload(_options); }); } graph() { program .command('graph [environment]') - .description('generates documentation based on the smart contracts configured') + .option('--skip-undeployed', __('Graph will not include undeployed contracts')) + .option('--skip-functions', __('Graph will not include functions')) + .option('--skip-events', __('Graph will not include events')) + .option('--locale [locale]', __('language to use (default: en)')) + .description(__('generates documentation based on the smart contracts configured')) .action(function (env, options) { + i18n.setOrDetectLocale(options.locale); embark.graph({ env: env || 'development', - logFile: options.logfile + logFile: options.logfile, + skipUndeployed: options.skipUndeployed, + skipFunctions: options.skipFunctions, + skipEvents: options.skipEvents }); }); } @@ -203,8 +238,10 @@ class Cmd { reset() { program .command('reset') - .description('resets embarks state on this dapp including clearing cache') - .action(function () { + .option('--locale [locale]', __('language to use (default: en)')) + .description(__('resets embarks state on this dapp including clearing cache')) + .action(function (options) { + i18n.setOrDetectLocale(options.locale); embark.initConfig('development', { embarkConfig: 'embark.json', interceptLogs: false }); @@ -215,7 +252,7 @@ class Cmd { versionCmd() { program .command('version') - .description('output the version number') + .description(__('output the version number')) .action(function () { console.log(embark.version); process.exit(0); @@ -225,17 +262,17 @@ class Cmd { otherCommands() { program .action(function (cmd) { - console.log('unknown command "%s"'.red, cmd); + console.log((__('unknown command') + ' "%s"').red, cmd); + let utils = require('./utils/utils.js'); let dictionary = ['new', 'demo', 'build', 'run', 'blockchain', 'simulator', 'test', 'upload', 'version']; let suggestion = utils.proposeAlternative(cmd, dictionary); if (suggestion) { - console.log('did you mean "%s"?'.green, suggestion); + console.log((__('did you mean') + ' "%s"?').green, suggestion); } console.log("type embark --help to see the available commands"); process.exit(0); }); } - } diff --git a/lib/cmds/blockchain/blockchain.js b/lib/cmds/blockchain/blockchain.js index 8726d2b4c..f2e9cf99b 100644 --- a/lib/cmds/blockchain/blockchain.js +++ b/lib/cmds/blockchain/blockchain.js @@ -1,17 +1,22 @@ -var shelljs = require('shelljs'); +const async = require('async'); +const child_process = require('child_process'); +const _ = require('underscore'); -var fs = require('../../core/fs.js'); +const fs = require('../../core/fs.js'); +const constants = require('../../constants.json'); -var GethCommands = require('./geth_commands.js'); +const GethCommands = require('./geth_commands.js'); -/*eslint complexity: ["error", 35]*/ +/*eslint complexity: ["error", 36]*/ var Blockchain = function(options) { this.blockchainConfig = options.blockchainConfig; this.env = options.env || 'development'; this.client = options.client; + this.isDev = options.isDev; + this.onReadyCallback = options.onReadyCallback; if ((this.blockchainConfig === {} || JSON.stringify(this.blockchainConfig) === '{"enabled":true}') && this.env !== 'development') { - console.log("===> warning: running default config on a non-development environment"); + console.log("===> " + __("warning: running default config on a non-development environment")); } this.config = { @@ -31,18 +36,20 @@ var Blockchain = function(options) { whisper: (this.blockchainConfig.whisper === undefined) || this.blockchainConfig.whisper, maxpeers: ((this.blockchainConfig.maxpeers === 0) ? 0 : (this.blockchainConfig.maxpeers || 25)), bootnodes: this.blockchainConfig.bootnodes || "", - rpcApi: (this.blockchainConfig.rpcApi || ['eth', 'web3', 'net']), + rpcApi: (this.blockchainConfig.rpcApi || ['eth', 'web3', 'net', 'debug']), wsRPC: (this.blockchainConfig.wsRPC === undefined) || this.blockchainConfig.wsRPC, wsHost: this.blockchainConfig.wsHost || 'localhost', wsPort: this.blockchainConfig.wsPort || 8546, wsOrigins: this.blockchainConfig.wsOrigins || false, - wsApi: (this.blockchainConfig.wsApi || ['eth', 'web3', 'net', 'shh']), + wsApi: (this.blockchainConfig.wsApi || ['eth', 'web3', 'net', 'shh', 'debug']), vmdebug: this.blockchainConfig.vmdebug || false, targetGasLimit: this.blockchainConfig.targetGasLimit || false, - light: this.blockchainConfig.light || false, - fast: this.blockchainConfig.fast || false + syncMode: this.blockchainConfig.syncMode, + verbosity: this.blockchainConfig.verbosity }; + this.setupProxy(); + if (this.blockchainConfig === {} || JSON.stringify(this.blockchainConfig) === '{"enabled":true}') { this.config.account = {}; this.config.account.password = fs.embarkPath("templates/boilerplate/config/development/password"); @@ -50,90 +57,205 @@ var Blockchain = function(options) { this.config.datadir = fs.embarkPath(".embark/development/datadir"); } - if (this.blockchainConfig.isDev) { - this.isDev = true; - } else if (this.blockchainConfig.isDev === false) { - this.isDev = false; - } else { - this.isDev = this.env === 'development'; + const spaceMessage = 'The path for %s in blockchain config contains spaces, please remove them'; + if (this.config.datadir && this.config.datadir.indexOf(' ') > 0) { + console.error(__(spaceMessage, 'datadir')); + process.exit(); + } + if (this.config.account.password && this.config.account.password.indexOf(' ') > 0) { + console.error(__(spaceMessage, 'account.password')); + process.exit(); + } + if (this.config.genesisBlock && this.config.genesisBlock.indexOf(' ') > 0) { + console.error(__(spaceMessage, 'genesisBlock')); + process.exit(); } this.client = new options.client({config: this.config, env: this.env, isDev: this.isDev}); }; -Blockchain.prototype.runCommand = function(cmd, options) { - console.log(("running: " + cmd.underline).green); - return shelljs.exec(cmd, options, (err, stdout, _stderr) => { - if (err && this.env === 'development' && stdout.indexOf('Failed to unlock developer account') > 0) { - console.warn('\nDevelopment blockchain has changed to use the --dev option.'.yellow); - console.warn('You can reset your workspace to fix the problem with'.yellow + ' embark reset'.cyan); - console.warn('Otherwise, you can change your data directory in blockchain.json (datadir)'.yellow); - } - }); +Blockchain.prototype.setupProxy = function() { + this.config.proxy = true; + if (this.blockchainConfig.proxy === false) { + this.config.proxy = false; + return; + } + + const proxy = require('../../core/proxy'); + const Ipc = require('../../core/ipc'); + + let ipcObject = new Ipc({ipcRole: 'client'}); + + proxy.serve(ipcObject, this.config.rpcHost, this.config.rpcPort, false); + proxy.serve(ipcObject, this.config.wsHost, this.config.wsPort, true); + this.config.rpcPort += constants.blockchain.servicePortOnProxy; + this.config.wsPort += constants.blockchain.servicePortOnProxy; +}; + +Blockchain.prototype.runCommand = function(cmd, options, callback) { + console.log(__("running: %s", cmd.underline).green); + if (this.blockchainConfig.silent) { + options.silent = true; + } + return child_process.exec(cmd, options, callback); }; Blockchain.prototype.run = function() { var self = this; console.log("===============================================================================".magenta); console.log("===============================================================================".magenta); - console.log(("Embark Blockchain Using: " + this.client.name.underline).magenta); + console.log(__("Embark Blockchain Using: %s", this.client.name.underline).magenta); console.log("===============================================================================".magenta); console.log("===============================================================================".magenta); - if (!this.isClientInstalled()) { - console.log(("could not find " + this.config.geth_bin + " command; is " + this.client.name + " installed or in the PATH?").green); - return; - } + + this.checkPathLength(); let address = ''; - if (!this.isDev) { - address = this.initChainAndGetAddress(); - } - this.client.mainCommand(address, function(cmd) { - self.runCommand(cmd, {async: true}); + async.waterfall([ + function checkInstallation(next) { + self.isClientInstalled((err) => { + if (err) { + console.log(__("could not find {{geth_bin}} command; is {{client_name}} installed or in the PATH?", {geth_bin: this.config.geth_bin, client_name: this.client.name}).green); + return next(err); + } + next(); + }); + }, + function init(next) { + if (!self.isDev) { + return self.initChainAndGetAddress((err, addr) => { + address = addr; + next(err); + }); + } + next(); + }, + function getMainCommand(next) { + self.client.mainCommand(address, function(cmd, args) { + next(null, cmd, args); + }, true); + } + ], function (err, cmd, args) { + if (err) { + console.error(err); + return; + } + args = _.compact(args); + + let full_cmd = cmd + " " + args.join(' '); + console.log(__("running: %s", full_cmd.underline).green); + self.child = child_process.spawn(cmd, args, {cwd: process.cwd()}); + + self.child.on('error', (err) => { + err = err.toString(); + console.error('Blockchain error: ', err); + if (self.env === 'development' && err.indexOf('Failed to unlock') > 0) { + console.error('\n' + __('Development blockchain has changed to use the --dev option.').yellow); + console.error(__('You can reset your workspace to fix the problem with').yellow + ' embark reset'.cyan); + console.error(__('Otherwise, you can change your data directory in blockchain.json (datadir)').yellow); + } + }); + self.child.stdout.on('data', (data) => { + console.log(`Geth error: ${data}`); + }); + // Geth logs appear in stderr somehow + self.child.stderr.on('data', (data) => { + data = data.toString(); + if (self.onReadyCallback && !self.readyCalled && data.indexOf('WebSocket endpoint opened') > -1) { + self.readyCalled = true; + self.onReadyCallback(); + } + console.log('Geth: ' + data); + }); + self.child.on('exit', (code) => { + if (code) { + console.error('Geth exited with error code ' + code); + } + }); }); }; -Blockchain.prototype.isClientInstalled = function() { - let versionCmd = this.client.determineVersion(); - let result = this.runCommand(versionCmd); - - if (result.output === undefined || result.output.indexOf("not found") >= 0) { - return false; +Blockchain.prototype.kill = function() { + if (this.child) { + this.child.kill(); } - return true; }; -Blockchain.prototype.initChainAndGetAddress = function() { - var address = null, result; +Blockchain.prototype.checkPathLength = function() { + let dappPath = fs.dappPath(''); + if (dappPath.length > 66) { + // console.error is captured and sent to the console output regardless of silent setting + console.error("===============================================================================".yellow); + console.error("===========> ".yellow + __('WARNING! DApp path length is too long: ').yellow + dappPath.yellow); + console.error("===========> ".yellow + __('This is known to cause issues with starting geth, please consider reducing your DApp path\'s length to 66 characters or less.').yellow); + console.error("===============================================================================".yellow); + } +}; + +Blockchain.prototype.isClientInstalled = function(callback) { + let versionCmd = this.client.determineVersionCommand(); + this.runCommand(versionCmd, {}, (err, stdout, stderr) => { + if (err || stderr || !stdout || stdout.indexOf("not found") >= 0) { + return callback('Geth not found'); + } + callback(); + }); +}; + +Blockchain.prototype.initChainAndGetAddress = function(callback) { + const self = this; + let address = null; // ensure datadir exists, bypassing the interactive liabilities prompt. - this.datadir = '.embark/' + this.env + '/datadir'; - fs.mkdirpSync(this.datadir); + self.datadir = '.embark/' + self.env + '/datadir'; - // copy mining script - fs.copySync(fs.embarkPath("js"), ".embark/" + this.env + "/js", {overwrite: true}); - - // check if an account already exists, create one if not, return address - result = this.runCommand(this.client.listAccountsCommand()); - if (result.output === undefined || result.output.match(/{(\w+)}/) === null || result.output.indexOf("Fatal") >= 0) { - console.log("no accounts found".green); - if (this.config.genesisBlock) { - console.log("initializing genesis block".green); - result = this.runCommand(this.client.initGenesisCommmand()); + async.waterfall([ + function makeDir(next) { + fs.mkdirp(self.datadir, (err, _result) => { + next(err); + }); + }, + function copy(next) { + // copy mining script + fs.copy(fs.embarkPath("js"), ".embark/" + self.env + "/js", {overwrite: true}, next); + }, + function listAccounts(next) { + self.runCommand(self.client.listAccountsCommand(), {}, (err, stdout, stderr) => { + if (err || stderr || stdout === undefined || stdout.match(/{(\w+)}/) === null || stdout.indexOf("Fatal") >= 0) { + console.log(__("no accounts found").green); + return next(); + } + console.log(__("already initialized").green); + address = stdout.match(/{(\w+)}/)[1]; + next(); + }); + }, + function genesisBlock(next) { + if (!self.config.genesisBlock) { + return next(); + } + console.log(__("initializing genesis block").green); + self.runCommand(self.client.initGenesisCommmand(), {}, (err, _stdout, _stderr) => { + next(err); + }); + }, + function newAccount(next) { + self.runCommand(self.client.newAccountCommand(), {}, (err, stdout, _stderr) => { + if (err) { + return next(err); + } + address = stdout.match(/{(\w+)}/)[1]; + next(); + }); } - - result = this.runCommand(this.client.newAccountCommand()); - address = result.output.match(/{(\w+)}/)[1]; - } else { - console.log("already initialized".green); - address = result.output.match(/{(\w+)}/)[1]; - } - - return address; + ], (err) => { + callback(err, address); + }); }; -var BlockchainClient = function(blockchainConfig, client, env) { +var BlockchainClient = function(blockchainConfig, client, env, isDev, onReadyCallback) { + // TODO add other clients at some point if (client === 'geth') { - return new Blockchain({blockchainConfig: blockchainConfig, client: GethCommands, env: env}); + return new Blockchain({blockchainConfig, client: GethCommands, env, isDev, onReadyCallback}); } else { throw new Error('unknown client'); } diff --git a/lib/cmds/blockchain/blockchainProcess.js b/lib/cmds/blockchain/blockchainProcess.js new file mode 100644 index 000000000..e9d3724fd --- /dev/null +++ b/lib/cmds/blockchain/blockchainProcess.js @@ -0,0 +1,47 @@ +const ProcessWrapper = require('../../process/processWrapper'); +const BlockchainClient = require('./blockchain'); +const i18n = require('../../i18n/i18n.js'); +const constants = require('../../constants'); + +let blockchainProcess; + +class BlockchainProcess extends ProcessWrapper { + constructor(options) { + super(); + this.blockchainConfig = options.blockchainConfig; + this.client = options.client; + this.env = options.env; + this.isDev = options.isDev; + + i18n.setOrDetectLocale(options.locale); + + this.blockchainConfig.silent = true; + this.blockchain = BlockchainClient( + this.blockchainConfig, + this.client, + this.env, + this.isDev, + this.blockchainReady.bind(this) + ); + + this.blockchain.run(); + } + + blockchainReady() { + blockchainProcess.send({result: constants.blockchain.blockchainReady}); + } + + kill() { + this.blockchain.kill(); + } +} + +process.on('message', (msg) => { + if (msg === 'exit') { + return blockchainProcess.kill(); + } + if (msg.action === constants.blockchain.init) { + blockchainProcess = new BlockchainProcess(msg.options); + return blockchainProcess.send({result: constants.blockchain.initiated}); + } +}); diff --git a/lib/cmds/blockchain/geth_commands.js b/lib/cmds/blockchain/geth_commands.js index 84d28dcf0..e6ef57188 100644 --- a/lib/cmds/blockchain/geth_commands.js +++ b/lib/cmds/blockchain/geth_commands.js @@ -1,4 +1,4 @@ -let async = require('async'); +const async = require('async'); // TODO: make all of this async class GethCommands { @@ -12,82 +12,82 @@ class GethCommands { commonOptions() { let config = this.config; - let cmd = ""; + let cmd = []; - cmd += this.determineNetworkType(config); + cmd.push(this.determineNetworkType(config)); if (config.datadir) { - cmd += "--datadir=\"" + config.datadir + "\" "; + cmd.push(`--datadir=${config.datadir}`); } - if (config.light) { - cmd += "--light "; - } - - if (config.fast) { - cmd += "--fast "; + if (config.syncMode) { + cmd.push("--syncmode=" + config.syncMode); } if (config.account && config.account.password) { - cmd += "--password " + config.account.password + " "; + cmd.push(`--password=${config.account.password}`); + } + + if (Number.isInteger(config.verbosity) && config.verbosity >=0 && config.verbosity <= 5) { + cmd.push("--verbosity=" + config.verbosity); } return cmd; } - determineVersion() { + determineVersionCommand() { return this.geth_bin + " version"; } determineNetworkType(config) { - let cmd = ""; + let cmd; if (config.networkType === 'testnet') { - cmd += "--testnet "; - } else if (config.networkType === 'olympic') { - cmd += "--olympic "; + cmd = "--testnet"; + } else if (config.networkType === 'rinkeby') { + cmd = "--rinkeby"; } else if (config.networkType === 'custom') { - cmd += "--networkid " + config.networkId + " "; + cmd = "--networkid=" + config.networkId; } return cmd; } initGenesisCommmand() { let config = this.config; - let cmd = this.geth_bin + " " + this.commonOptions(); + let cmd = this.geth_bin + " " + this.commonOptions().join(' '); if (config.genesisBlock) { - cmd += "init \"" + config.genesisBlock + "\" "; + cmd += " init \"" + config.genesisBlock + "\" "; } return cmd; } newAccountCommand() { - return this.geth_bin + " " + this.commonOptions() + "account new "; + return this.geth_bin + " " + this.commonOptions().join(' ') + " account new "; } listAccountsCommand() { - return this.geth_bin + " " + this.commonOptions() + "account list "; + return this.geth_bin + " " + this.commonOptions().join(' ') + " account list "; } determineRpcOptions(config) { - let cmd = ""; + let cmd = []; - cmd += "--port " + config.port + " "; - cmd += "--rpc "; - cmd += "--rpcport " + config.rpcPort + " "; - cmd += "--rpcaddr " + config.rpcHost + " "; + cmd.push("--port=" + config.port); + cmd.push("--rpc"); + cmd.push("--rpcport=" + config.rpcPort); + cmd.push("--rpcaddr=" + config.rpcHost); if (config.rpcCorsDomain) { if (config.rpcCorsDomain === '*') { console.log('=================================='); - console.log('rpcCorsDomain set to *'); - console.log('make sure you know what you are doing'); + console.log(__('rpcCorsDomain set to *')); + console.log(__('make sure you know what you are doing')); console.log('=================================='); } - cmd += "--rpccorsdomain=\"" + config.rpcCorsDomain + "\" "; + cmd.push("--rpccorsdomain=" + config.rpcCorsDomain); } else { console.log('=================================='); - console.log('warning: cors is not set'); + console.log(__('warning: cors is not set')); console.log('=================================='); } @@ -95,23 +95,23 @@ class GethCommands { } determineWsOptions(config) { - let cmd = ""; + let cmd = []; if (config.wsRPC) { - cmd += "--ws "; - cmd += "--wsport " + config.wsPort + " "; - cmd += "--wsaddr " + config.wsHost + " "; + cmd.push("--ws"); + cmd.push("--wsport=" + config.wsPort); + cmd.push("--wsaddr=" + config.wsHost); if (config.wsOrigins) { if (config.wsOrigins === '*') { console.log('=================================='); - console.log('wsOrigins set to *'); - console.log('make sure you know what you are doing'); + console.log(__('wsOrigins set to *')); + console.log(__('make sure you know what you are doing')); console.log('=================================='); } - cmd += "--wsorigins \"" + config.wsOrigins + "\" "; + cmd.push("--wsorigins=" + config.wsOrigins); } else { console.log('=================================='); - console.log('warning: wsOrigins is not set'); + console.log(__('warning: wsOrigins is not set')); console.log('=================================='); } } @@ -122,47 +122,57 @@ class GethCommands { mainCommand(address, done) { let self = this; let config = this.config; - let rpc_api = (this.config.rpcApi || ['eth', 'web3', 'net']); - let ws_api = (this.config.wsApi || ['eth', 'web3', 'net']); + let rpc_api = (this.config.rpcApi || ['eth', 'web3', 'net', 'debug']); + let ws_api = (this.config.wsApi || ['eth', 'web3', 'net', 'debug']); + + let args = []; async.series([ function commonOptions(callback) { let cmd = self.commonOptions(); + args = args.concat(cmd); callback(null, cmd); }, function rpcOptions(callback) { let cmd = self.determineRpcOptions(self.config); + args = args.concat(cmd); callback(null, cmd); }, function wsOptions(callback) { let cmd = self.determineWsOptions(self.config); + args = args.concat(cmd); callback(null, cmd); }, function dontGetPeers(callback) { if (config.nodiscover) { + args.push("--nodiscover"); return callback(null, "--nodiscover"); } callback(null, ""); }, function vmDebug(callback) { if (config.vmdebug) { + args.push("--vmdebug"); return callback(null, "--vmdebug"); } callback(null, ""); }, function maxPeers(callback) { - let cmd = "--maxpeers " + config.maxpeers; + let cmd = "--maxpeers=" + config.maxpeers; + args.push(cmd); callback(null, cmd); }, function mining(callback) { if (config.mineWhenNeeded || config.mine) { - return callback(null, "--mine "); + args.push("--mine"); + return callback(null, "--mine"); } callback(""); }, function bootnodes(callback) { if (config.bootnodes && config.bootnodes !== "" && config.bootnodes !== []) { - return callback(null, "--bootnodes " + config.bootnodes); + args.push("--bootnodes=" + config.bootnodes); + return callback(null, "--bootnodes=" + config.bootnodes); } callback(""); }, @@ -172,15 +182,18 @@ class GethCommands { if (ws_api.indexOf('shh') === -1) { ws_api.push('shh'); } + args.push("--shh"); return callback(null, "--shh "); } callback(""); }, function rpcApi(callback) { - callback(null, '--rpcapi "' + rpc_api.join(',') + '"'); + args.push('--rpcapi=' + rpc_api.join(',')); + callback(null, '--rpcapi=' + rpc_api.join(',')); }, function wsApi(callback) { - callback(null, '--wsapi "' + ws_api.join(',') + '"'); + args.push('--wsapi=' + ws_api.join(',')); + callback(null, '--wsapi=' + ws_api.join(',')); }, function accountToUnlock(callback) { let accountAddress = ""; @@ -190,33 +203,37 @@ class GethCommands { accountAddress = address; } if (accountAddress && !self.isDev) { + args.push("--unlock=" + accountAddress); return callback(null, "--unlock=" + accountAddress); } callback(null, ""); }, function gasLimit(callback) { if (config.targetGasLimit) { - return callback(null, "--targetgaslimit " + config.targetGasLimit); + args.push("--targetgaslimit=" + config.targetGasLimit); + return callback(null, "--targetgaslimit=" + config.targetGasLimit); } callback(null, ""); }, function mineWhenNeeded(callback) { if (config.mineWhenNeeded && !self.isDev) { + args.push("js .embark/" + self.env + "/js/mine.js"); return callback(null, "js .embark/" + self.env + "/js/mine.js"); } callback(null, ""); }, function isDev(callback) { if (self.isDev) { + args.push('--dev'); return callback(null, '--dev'); } callback(null, ''); } - ], function (err, results) { + ], function (err) { if (err) { throw new Error(err.message); } - done(self.geth_bin + " " + results.join(" ")); + return done(self.geth_bin, args); }); } } diff --git a/lib/cmds/graph.js b/lib/cmds/graph.js index 7621fe655..8ae2eda57 100644 --- a/lib/cmds/graph.js +++ b/lib/cmds/graph.js @@ -6,15 +6,16 @@ class GraphGenerator { this.engine = engine; } - generate() { + generate(options) { let id = 0; let contractString = ""; let relationshipString = ""; let idMapping = {}; let contractInheritance = {}; - for (let contract in this.engine.contractsManager.contracts) { + if(options.skipUndeployed && !this.engine.contractsManager.contracts[contract].deploy) continue; + id++; idMapping[contract] = id; @@ -30,23 +31,27 @@ class GraphGenerator { contractLabel += ": " + this.engine.contractsManager.contracts[contract].instanceOf; tooltip += " instance of " + this.engine.contractsManager.contracts[contract].instanceOf; } else { - contractLabel += "|"; + if(!(options.skipFunctions === true && options.skipEvents === true)) contractLabel += "|"; for(let i = 0; i < this.engine.contractsManager.contracts[contract].abiDefinition.length; i++){ - switch(this.engine.contractsManager.contracts[contract].abiDefinition[i].type){ + let abiDef = this.engine.contractsManager.contracts[contract].abiDefinition[i]; + if(abiDef.type == 'event' && options.skipEvents) continue; + if(['constructor', 'fallback'].indexOf(abiDef.type) > -1 && options.skipFunctions) continue; + + switch(abiDef.type){ case 'fallback': contractLabel += "«fallback»()\\l"; break; - case 'constructor': + case 'constructor': contractLabel += "«constructor»("; - this.engine.contractsManager.contracts[contract].abiDefinition[i].inputs.forEach(function(elem, index){ + abiDef.inputs.forEach(function(elem, index){ contractLabel += (index == 0 ? "" : ", ") + elem.type; }); contractLabel += ")\\l"; break; - case 'event': - contractLabel += "«event»" + this.engine.contractsManager.contracts[contract].abiDefinition[i].name + "("; - this.engine.contractsManager.contracts[contract].abiDefinition[i].inputs.forEach(function(elem, index){ + case 'event': + contractLabel += "«event»" + abiDef.name + "("; + abiDef.inputs.forEach(function(elem, index){ contractLabel += (index == 0 ? "" : ", ") + elem.type; }); contractLabel += ")\\l"; @@ -56,7 +61,7 @@ class GraphGenerator { } let fHashes = this.engine.contractsManager.contracts[contract].functionHashes; - if(fHashes != {} && fHashes != undefined){ + if(fHashes != {} && fHashes != undefined && !options.skipFunctions){ for(let method in this.engine.contractsManager.contracts[contract].functionHashes){ contractLabel += method + '\\l'; } @@ -73,20 +78,23 @@ class GraphGenerator { } - for (let c in this.engine.contractsManager.contractDependencies){ + for (let c in this.engine.contractsManager.contractDependencies){ let contractDependencies = Array.from(new Set(this.engine.contractsManager.contractDependencies[c])); - contractDependencies.forEach(function(d){ + contractDependencies.forEach((d) => { if(idMapping[c] !== undefined && idMapping[d] !== undefined){ - relationshipString += `${idMapping[d]}->${idMapping[c]}[constraint=true, arrowtail=diamond, tooltip="${c} uses ${d}"]\n`; + if(options.skipUndeployed && this.engine.contractsManager.contracts[c].deploy && this.engine.contractsManager.contracts[d].deploy){ + relationshipString += `${idMapping[d]}->${idMapping[c]}[constraint=true, arrowtail=diamond, tooltip="${c} uses ${d}"]\n`; + } } }); } for (let c in contractInheritance){ + if(options.skipUndeployed && !this.engine.contractsManager.contracts[contractInheritance[c]].deploy) continue; + relationshipString += `${idMapping[contractInheritance[c]]}->${idMapping[c]}[tooltip="${c} instance of ${contractInheritance[c]}"]\n`; } - let dot = ` digraph Contracts { node[shape=record,style=filled] diff --git a/lib/cmds/reset.js b/lib/cmds/reset.js index c2b14756d..557e7b67f 100644 --- a/lib/cmds/reset.js +++ b/lib/cmds/reset.js @@ -4,5 +4,5 @@ module.exports = function() { fs.removeSync('./chains.json'); fs.removeSync('.embark/'); fs.removeSync('dist/'); - console.log("reset done!".green); + console.log(__("reset done!").green); }; diff --git a/lib/cmds/simulator.js b/lib/cmds/simulator.js index 6366290d9..638020e39 100644 --- a/lib/cmds/simulator.js +++ b/lib/cmds/simulator.js @@ -1,4 +1,7 @@ let shelljs = require('shelljs'); +let proxy = require('../core/proxy'); +const Ipc = require('../core/ipc'); +const constants = require('../constants.json'); class Simulator { constructor(options) { @@ -12,13 +15,17 @@ class Simulator { 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'); + this.logger.warn(__('%s is not installed on your machine', 'Ganache CLI (TestRPC)')); + this.logger.info(__('You can install it by running: %s', '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')); + let useProxy = this.blockchainConfig.proxy || false; + let host = (options.host || this.blockchainConfig.rpcHost || 'localhost'); + let port = (options.port || this.blockchainConfig.rpcPort || 8545); + + cmds.push("-p " + (port + (useProxy ? constants.blockchain.servicePortOnProxy : 0))); + cmds.push("-h " + host); cmds.push("-a " + (options.numAccounts || 10)); cmds.push("-e " + (options.defaultBalance || 100)); cmds.push("-l " + (options.gasLimit || 8000000)); @@ -36,7 +43,14 @@ class Simulator { } const program = ganache ? 'ganache-cli' : 'testrpc'; + shelljs.exec(`${program} ${cmds.join(' ')}`, {async : true}); + + if(useProxy){ + let ipcObject = new Ipc({ipcRole: 'client'}); + proxy.serve(ipcObject, host, port, false); + } + } } diff --git a/lib/cmds/template_generator.js b/lib/cmds/template_generator.js index 3bb8c4a34..8597fcc02 100644 --- a/lib/cmds/template_generator.js +++ b/lib/cmds/template_generator.js @@ -8,7 +8,7 @@ class TemplateGenerator { generate(destinationFolder, name) { let templatePath = fs.embarkPath(utils.joinPath('templates', this.templateName)); - console.log('Initializing Embark Template....'.green); + console.log(__('Initializing Embark Template....').green); let fspath = utils.joinPath(destinationFolder, name); fs.copySync(templatePath, fspath); @@ -16,21 +16,19 @@ class TemplateGenerator { utils.sed('package.json', '%APP_NAME%', name); if (name === 'embark_demo') { - console.log('Installing packages...'.green); + console.log(__('Installing packages...').green); utils.runCmd('npm install'); } - console.log('Init complete'.green); - console.log('\nApp ready at '.green + fspath); + console.log(__('Init complete').green); + console.log('\n' + __('App ready at ').green + fspath); if (name === 'embark_demo') { console.log('-------------------'.yellow); - console.log('Next steps:'.green); + console.log(__('Next steps:').green); console.log(('-> ' + ('cd ' + fspath).bold.cyan).green); - console.log('-> '.green + 'embark blockchain'.bold.cyan + ' or '.green + 'embark simulator'.bold.cyan); - console.log('open another console in the same directory and run'.green); console.log('-> '.green + 'embark run'.bold.cyan); - console.log('For more info go to http://embark.status.im'.green); + console.log(__('For more info go to http://embark.status.im').green); } } } diff --git a/lib/coderunner/codeRunner.js b/lib/coderunner/codeRunner.js new file mode 100644 index 000000000..a7c3e153b --- /dev/null +++ b/lib/coderunner/codeRunner.js @@ -0,0 +1,32 @@ +// still needs to be run on a separate file due to the global context +var RunCode = require('./runCode.js'); + +class CodeRunner { + constructor(options) { + this.plugins = options.plugins; + this.logger = options.logger; + this.events = options.events; + + // necessary to init the context + RunCode.initContext(); + + this.events.on("runcode:register", (varName, code) => { + RunCode.registerVar(varName, code); + }); + + this.events.setCommandHandler('runcode:eval', (code, cb) => { + if (!cb) { + cb = function() {}; + } + try { + let result = RunCode.doEval(code); + cb(null, result); + } catch (e) { + cb(e); + } + + }); + } +} + +module.exports = CodeRunner; diff --git a/lib/core/runCode.js b/lib/coderunner/runCode.js similarity index 61% rename from lib/core/runCode.js rename to lib/coderunner/runCode.js index 582238b88..9560eec1f 100644 --- a/lib/core/runCode.js +++ b/lib/coderunner/runCode.js @@ -1,18 +1,16 @@ /*eslint no-unused-vars: off*/ -let Web3 = require('web3'); -let web3; -let __mainContext; +let __mainContext = this; + +function initContext() { + doEval("__mainContext = this"); +} // ====================== // the eval is used for evaluating some of the contact calls for different purposes // this should be at least moved to a different process and scope // for now it is defined here // ====================== -function doEval(code, _web3) { - if (_web3) { - web3 = _web3; - } - +function doEval(code) { try { // TODO: add trace log here return eval(code); @@ -21,6 +19,12 @@ function doEval(code, _web3) { } } +function registerVar(varName, code) { + __mainContext[varName] = code; +} + module.exports = { - doEval: doEval + doEval: doEval, + registerVar: registerVar, + initContext: initContext }; diff --git a/lib/constants.json b/lib/constants.json index 06d6a28c2..d8a0759be 100644 --- a/lib/constants.json +++ b/lib/constants.json @@ -15,5 +15,31 @@ "events": { "contractFilesChanged": "contractFilesChanged", "contractConfigChanged": "contractConfigChanged" + }, + "process": { + "processLaunchRequest": "process:launch-request", + "processLaunchComplete": "process:launch-complete", + "log": "log", + "events": { + "on": "on", + "request": "request", + "response": "response" + } + }, + "pipeline": { + "init": "init", + "build": "build", + "initiated": "initiated", + "built": "built" + }, + "blockchain": { + "blockchainReady": "blockchainReady", + "init": "init", + "initiated": "initiated", + "servicePortOnProxy": 10 + }, + "storage": { + "init": "init", + "initiated": "initiated" } } diff --git a/lib/contracts/accountParser.js b/lib/contracts/accountParser.js new file mode 100644 index 000000000..f407cf54b --- /dev/null +++ b/lib/contracts/accountParser.js @@ -0,0 +1,95 @@ +const bip39 = require("bip39"); +const hdkey = require('ethereumjs-wallet/hdkey'); +const fs = require('../core/fs'); + +class AccountParser { + static parseAccountsConfig(accountsConfig, web3, logger) { + let accounts = []; + if (accountsConfig && accountsConfig.length) { + accountsConfig.forEach(accountConfig => { + const account = AccountParser.getAccount(accountConfig, web3, logger); + if (!account) { + return; + } + if (Array.isArray(account)) { + accounts = accounts.concat(account); + return; + } + accounts.push(account); + }); + } + return accounts; + } + + static getHexBalance(balanceString, web3) { + if (!balanceString) { + return 0xFFFFFFFFFFFFFFFFFF; + } + if (web3.utils.isHexStrict(balanceString)) { + return balanceString; + } + const match = balanceString.match(/([0-9]+) ?([a-zA-Z]*)/); + if (!match) { + throw new Error(__('Unrecognized balance string "%s"', balanceString)); + } + if (!match[2]) { + return web3.utils.toHex(parseInt(match[1], 10)); + } + + return web3.utils.toHex(web3.utils.toWei(match[1], match[2])); + } + + static getAccount(accountConfig, web3, logger) { + if (!logger) { + logger = console; + } + let hexBalance = null; + if (accountConfig.balance) { + hexBalance = AccountParser.getHexBalance(accountConfig.balance, web3); + } + if (accountConfig.privateKey) { + if (!accountConfig.privateKey.startsWith('0x')) { + accountConfig.privateKey = '0x' + accountConfig.privateKey; + } + if (!web3.utils.isHexStrict(accountConfig.privateKey)) { + logger.warn(`Private key ending with ${accountConfig.privateKey.substr(accountConfig.privateKey.length - 5)} is not a HEX string`); + return null; + } + return Object.assign(web3.eth.accounts.privateKeyToAccount(accountConfig.privateKey), {hexBalance}); + } + if (accountConfig.privateKeyFile) { + let fileContent = fs.readFileSync(fs.dappPath(accountConfig.privateKeyFile)).toString(); + fileContent = fileContent.trim().split(/[,;]/); + return fileContent.map((key, index) => { + if (!key.startsWith('0x')) { + key = '0x' + key; + } + if (!web3.utils.isHexStrict(key)) { + logger.warn(`Private key is not a HEX string in file ${accountConfig.privateKeyFile} at index ${index}`); + return null; + } + return Object.assign(web3.eth.accounts.privateKeyToAccount(key), {hexBalance}); + }); + } + if (accountConfig.mnemonic) { + const hdwallet = hdkey.fromMasterSeed(bip39.mnemonicToSeed(accountConfig.mnemonic.trim())); + + const addressIndex = accountConfig.addressIndex || 0; + const numAddresses = accountConfig.numAddresses || 1; + const wallet_hdpath = accountConfig.hdpath || "m/44'/60'/0'/0/"; + + const accounts = []; + for (let i = addressIndex; i < addressIndex + numAddresses; i++) { + const wallet = hdwallet.derivePath(wallet_hdpath + i).getWallet(); + accounts.push(Object.assign(web3.eth.accounts.privateKeyToAccount('0x' + wallet.getPrivateKey().toString('hex')), {hexBalance})); + } + return accounts; + } + logger.warn('Unsupported account configuration: ' + JSON.stringify(accountConfig)); + logger.warn('Try using one of those: ' + + '{ "privateKey": "your-private-key", "privateKeyFile": "path/to/file/containing/key", "mnemonic": "12 word mnemonic" }'); + return null; + } +} + +module.exports = AccountParser; diff --git a/lib/contracts/blockchain.js b/lib/contracts/blockchain.js new file mode 100644 index 000000000..6ae0c9c76 --- /dev/null +++ b/lib/contracts/blockchain.js @@ -0,0 +1,293 @@ +const Web3 = require('web3'); +const async = require('async'); +const Provider = require('./provider.js'); +const BlockchainProcessLauncher = require('../processes/blockchainProcessLauncher'); +const utils = require('../utils/utils'); +const constants = require('../constants'); + +const WEB3_READY = 'web3Ready'; + +class Blockchain { + constructor(options) { + this.plugins = options.plugins; + this.logger = options.logger; + this.events = options.events; + this.contractsConfig = options.contractsConfig; + this.blockchainConfig = options.blockchainConfig; + this.web3 = options.web3; + this.locale = options.locale; + this.isDev = options.isDev; + this.web3Endpoint = ''; + this.isWeb3Ready = false; + this.web3StartedInProcess = false; + + if (!this.web3) { + this.initWeb3(); + } else { + this.isWeb3Ready = true; + } + this.registerServiceCheck(); + this.registerRequests(); + this.registerWeb3Object(); + } + + initWeb3(cb) { + if (!cb) { + cb = function(){}; + } + if (this.isWeb3Ready) { + return cb(); + } + const self = this; + this.web3 = new Web3(); + + if (this.contractsConfig.deployment.type !== "rpc" && this.contractsConfig.deployment.type !== "ws") { + const message = __("contracts config error: unknown deployment type %s", this.contractsConfig.deployment.type); + this.logger.error(message); + return cb(message); + } + + const protocol = (this.contractsConfig.deployment.type === "rpc") ? this.contractsConfig.deployment.protocol : 'ws'; + let provider; + this.web3Endpoint = utils.buildUrl(protocol, this.contractsConfig.deployment.host, this.contractsConfig.deployment.port);//`${protocol}://${this.contractsConfig.deployment.host}:${this.contractsConfig.deployment.port}`; + + const providerOptions = { + web3: this.web3, + accountsConfig: this.contractsConfig.deployment.accounts, + blockchainConfig: this.blockchainConfig, + logger: this.logger, + isDev: this.isDev, + type: this.contractsConfig.deployment.type, + web3Endpoint: self.web3Endpoint + }; + provider = new Provider(providerOptions); + + async.waterfall([ + function checkNode(next) { + self.assertNodeConnection(true, (err) => { + if (err && self.web3StartedInProcess) { + // Already started blockchain in another node, we really have a node problem + self.logger.error(__('Unable to start the blockchain process. Is Geth installed?').red); + return next(err); + } + if (!err) { + self.isWeb3Ready = true; + self.events.emit(WEB3_READY); + return next(); + } + self.web3StartedInProcess = true; + self.startBlockchainNode(() => { + // Need to re-initialize web3 to connect to the new blockchain node + provider.stop(); + self.initWeb3(cb); + }); + }); + }, + function startProvider(next) { + provider.startWeb3Provider(next); + }, + function fundAccountsIfNeeded(next) { + provider.fundAccounts(next); + } + ], (err) => { + self.registerWeb3Object(); + cb(err); + }); + } + + onReady(callback) { + if (this.isWeb3Ready) { + return callback(); + } + + this.events.once(WEB3_READY, () => { + callback(); + }); + } + + startBlockchainNode(callback) { + const self = this; + let blockchainProcess = new BlockchainProcessLauncher({ + events: self.events, + logger: self.logger, + normalizeInput: utils.normalizeInput, + blockchainConfig: self.blockchainConfig, + locale: self.locale, + isDev: self.isDev + }); + + blockchainProcess.startBlockchainNode(); + self.events.once(constants.blockchain.blockchainReady, () => { + callback(); + }); + } + + registerServiceCheck() { + const self = this; + const NO_NODE = 'noNode'; + + this.events.request("services:register", 'Ethereum', function (cb) { + async.waterfall([ + function checkNodeConnection(next) { + self.assertNodeConnection(true, (err) => { + if (err) { + return next(NO_NODE, {name: "No Blockchain node found", status: 'off'}); + } + next(); + }); + }, + function checkVersion(next) { + // TODO: web3_clientVersion method is currently not implemented in web3.js 1.0 + self.web3._requestManager.send({method: 'web3_clientVersion', params: []}, (err, version) => { + if (err) { + return next(null, {name: "Ethereum node (version unknown)", status: 'on'}); + } + if (version.indexOf("/") < 0) { + return next(null, {name: version, status: 'on'}); + } + let nodeName = version.split("/")[0]; + let versionNumber = version.split("/")[1].split("-")[0]; + let name = nodeName + " " + versionNumber + " (Ethereum)"; + + return next(null, {name: name, status: 'on'}); + }); + } + ], (err, statusObj) => { + if (err && err !== NO_NODE) { + return cb(err); + } + cb(statusObj); + }); + }, 5000, 'off'); + } + + registerRequests() { + const self = this; + + this.events.setCommandHandler("blockchain:defaultAccount:get", function(cb) { + cb(self.defaultAccount); + }); + + this.events.setCommandHandler("blockchain:defaultAccount:set", function(account, cb) { + self.setDefaultAccount(account); + cb(); + }); + + this.events.setCommandHandler("blockchain:block:byNumber", function(blockNumber, cb) { + self.getBlock(blockNumber, cb); + }); + + this.events.setCommandHandler("blockchain:gasPrice", function(cb) { + self.getGasPrice(cb); + }); + + } + + defaultAccount() { + return this.web3.eth.defaultAccount; + } + + setDefaultAccount(account) { + this.web3.eth.defaultAccount = account; + } + + getAccounts(cb) { + this.web3.eth.getAccounts(cb); + } + + getCode(address, cb) { + this.web3.eth.getCode(address, cb); + } + + getBlock(blockNumber, cb) { + this.web3.eth.getBlock(blockNumber, cb); + } + + getGasPrice(cb) { + this.web3.eth.getGasPrice(cb); + } + + ContractObject(params) { + return new this.web3.eth.Contract(params.abi); + } + + deployContractObject(contractObject, params) { + return contractObject.deploy({arguments: params.arguments, data: params.data}); + } + + estimateDeployContractGas(deployObject, cb) { + return deployObject.estimateGas().then((gasValue) => { + cb(null, gasValue); + }).catch(cb); + } + + deployContractFromObject(deployContractObject, params, cb) { + deployContractObject.send({ + from: params.from, gas: params.gas, gasPrice: params.gasPrice + }).on('receipt', function(receipt) { + if (receipt.contractAddress !== undefined) { + cb(null, receipt); + } + }).on('error', cb); + } + + assertNodeConnection(noLogs, cb) { + if (typeof noLogs === 'function') { + cb = noLogs; + noLogs = false; + } + const NO_NODE_ERROR = Error("error connecting to blockchain node"); + const self = this; + + async.waterfall([ + function checkInstance(next) { + if (!self.web3) { + return next(Error("no web3 instance found")); + } + next(); + }, + function checkProvider(next) { + if (self.web3.currentProvider === undefined) { + return next(NO_NODE_ERROR); + } + next(); + }, + function pingEndpoint(next) { + if (!self.contractsConfig || !self.contractsConfig.deployment || !self.contractsConfig.deployment.host) { + return next(); + } + const {host, port, type, protocol} = self.contractsConfig.deployment; + utils.pingEndpoint(host, port, type, protocol, self.blockchainConfig.wsOrigins.split(',')[0], next); + } + ], function (err) { + if (!noLogs && err === NO_NODE_ERROR) { + self.logger.error(("Couldn't connect to an Ethereum node are you sure it's on?").red); + self.logger.info("make sure you have an Ethereum node or simulator running. e.g 'embark blockchain'".magenta); + } + cb(err); + }); + } + + determineDefaultAccount(cb) { + const self = this; + self.getAccounts(function (err, accounts) { + if (err) { + self.logger.error(err); + return cb(new Error(err)); + } + let accountConfig = self.blockchainConfig.account; + let selectedAccount = accountConfig && accountConfig.address; + self.setDefaultAccount(selectedAccount || accounts[0]); + cb(); + }); + } + + registerWeb3Object() { + // doesn't feel quite right, should be a cmd or plugin method + // can just be a command without a callback + this.events.emit("runcode:register", "web3", this.web3); + } +} + +module.exports = Blockchain; + diff --git a/lib/contracts/code_generator.js b/lib/contracts/code_generator.js index 6b8306aec..ef9fb6514 100644 --- a/lib/contracts/code_generator.js +++ b/lib/contracts/code_generator.js @@ -1,5 +1,6 @@ let async = require('async'); let fs = require('../core/fs.js'); +const utils = require('../utils/utils.js'); require('ejs'); const Templates = { @@ -13,7 +14,8 @@ const Templates = { define_web3_simple: require('./code_templates/define-web3-simple.js.ejs'), web3_connector: require('./code_templates/web3-connector.js.ejs'), do_when_loaded: require('./code_templates/do-when-loaded.js.ejs'), - exec_when_env_loaded: require('./code_templates/exec-when-env-loaded.js.ejs') + exec_when_env_loaded: require('./code_templates/exec-when-env-loaded.js.ejs'), + embark_building_placeholder: require('./code_templates/embark-building-placeholder.html.ejs') }; class CodeGenerator { @@ -24,7 +26,8 @@ class CodeGenerator { this.contractsConfig = options.contractsConfig || {}; this.storageConfig = options.storageConfig || {}; this.communicationConfig = options.communicationConfig || {}; - this.contractsManager = options.contractsManager; + this.namesystemConfig = options.namesystemConfig || {}; + this.env = options.env || 'development'; this.plugins = options.plugins; this.events = options.events; } @@ -32,68 +35,61 @@ class CodeGenerator { listenToCommands() { let self = this; - this.events.setCommandHandlerOnce('provider-code', function(cb) { + this.events.setCommandHandler('provider-code', function(cb) { let providerCode = self.generateProvider(false); cb(providerCode); }); - // deprecated events; to remove in embark 2.7.0 - this.events.setCommandHandlerOnce('abi-vanila', function(cb) { - let vanillaABI = self.generateABI({useEmbarkJS: false}); - let contractsJSON = self.generateContractsJSON(); - - cb(vanillaABI, contractsJSON); - }); - - this.events.setCommandHandlerOnce('abi', function(cb) { - let embarkJSABI = self.generateABI({useEmbarkJS: true}); - let contractsJSON = self.generateContractsJSON(); - - cb(embarkJSABI, contractsJSON); - }); - - this.events.setCommandHandlerOnce('abi-contracts-vanila', function(cb) { - let vanillaContractsABI = self.generateContracts(false, true, false); - let contractsJSON = self.generateContractsJSON(); - - cb(vanillaContractsABI, contractsJSON); - }); - - this.events.setCommandHandlerOnce('abi-vanila-deployment', function(cb) { - let vanillaABI = self.generateABI({useEmbarkJS: false, deployment: true}); - let contractsJSON = self.generateContractsJSON(); - - cb(vanillaABI, contractsJSON); - }); - // new events - this.events.setCommandHandlerOnce('code-vanila', function(cb) { - let vanillaABI = self.generateABI({useEmbarkJS: false}); - let contractsJSON = self.generateContractsJSON(); - - cb(vanillaABI, contractsJSON); + this.events.setCommandHandler('code-vanila', function(cb) { + self.events.request("contracts:list", (_err, contractsList) => { + let vanillaABI = self.generateABI(contractsList, {useEmbarkJS: false}); + let contractsJSON = self.generateContractsJSON(contractsList); + cb(vanillaABI, contractsJSON); + }); }); - this.events.setCommandHandlerOnce('code', function(cb) { - let embarkJSABI = self.generateABI({useEmbarkJS: true}); - let contractsJSON = self.generateContractsJSON(); - - cb(embarkJSABI, contractsJSON); + this.events.setCommandHandler('code', function(cb) { + self.events.request("contracts:list", (_err, contractsList) => { + let embarkJSABI = self.generateABI(contractsList, {useEmbarkJS: true}); + let contractsJSON = self.generateContractsJSON(contractsList); + cb(embarkJSABI, contractsJSON); + }); }); - this.events.setCommandHandlerOnce('code-contracts-vanila', function(cb) { - let vanillaContractsABI = self.generateContracts(false, true, false); - let contractsJSON = self.generateContractsJSON(); - - cb(vanillaContractsABI, contractsJSON); + this.events.setCommandHandler('code-contracts-vanila', function(cb) { + self.events.request("contracts:list", (_err, contractsList) => { + let vanillaContractsABI = self.generateContracts(contractsList, false, true, false); + let contractsJSON = self.generateContractsJSON(contractsList); + cb(vanillaContractsABI, contractsJSON); + }); }); - this.events.setCommandHandlerOnce('code-vanila-deployment', function(cb) { - let vanillaABI = self.generateABI({useEmbarkJS: false, deployment: true}); - let contractsJSON = self.generateContractsJSON(); + this.events.setCommandHandler('code-vanila-deployment', function(cb) { + self.events.request("contracts:list", (_err, contractsList) => { + let vanillaABI = self.generateABI(contractsList, {useEmbarkJS: false, deployment: true}); + let contractsJSON = self.generateContractsJSON(contractsList); + cb(vanillaABI, contractsJSON); + }); + }); - cb(vanillaABI, contractsJSON); + this.events.setCommandHandler('code-generator:web3js', function(cb) { + self.buildWeb3JS(cb); + }); + + self.events.setCommandHandler('code-generator:contract', (contractName, cb) => { + self.events.request('contracts:contract', contractName, (contract) => { + self.buildContractJS(contractName, self.generateContractJSON(contract, contract), cb); + }); + }); + + self.events.setCommandHandler('code-generator:contract:vanilla', (contract, gasLimit, cb) => { + cb(self.generateContractCode(contract, gasLimit)); + }); + + this.events.setCommandHandler('embark-building-placeholder', (cb) => { + self.buildPlaceholderPage(cb); }); } @@ -138,7 +134,11 @@ class CodeGenerator { web3Load = Templates.define_web3_simple({url: connection, done: 'done();'}); } else { let connectionList = "[" + this.contractsConfig.dappConnection.map((x) => '"' + x + '"').join(',') + "]"; - web3Load = Templates.web3_connector({connectionList: connectionList, done: 'done();'}); + if (self.env === 'development') { + web3Load = Templates.web3_connector({connectionList: connectionList, done: 'done();', warnAboutMetamask: true}); + } else { + web3Load = Templates.web3_connector({connectionList: connectionList, done: 'done();', warnAboutMetamask: true}); + } } result += Templates.do_when_loaded({block: web3Load}); @@ -147,16 +147,15 @@ class CodeGenerator { return result; } - generateContracts(useEmbarkJS, isDeployment, useLoader) { + generateContracts(contractsList, useEmbarkJS, isDeployment, useLoader) { let self = this; let result = "\n"; let contractsPlugins; if (useLoader === false) { - for (let className in this.contractsManager.contracts) { - let contract = this.contractsManager.contracts[className]; + for (let contract of contractsList) { let abi = JSON.stringify(contract.abiDefinition); - result += Templates.vanilla_contract({className: className, abi: abi, contract: contract, gasLimit: 6000000}); + result += Templates.vanilla_contract({className: contract.className, abi: abi, contract: contract, gasLimit: 6000000}); } return result; } @@ -171,12 +170,10 @@ class CodeGenerator { if (this.plugins && contractsPlugins.length > 0) { contractsPlugins.forEach(function (plugin) { - result += plugin.generateContracts({contracts: self.contractsManager.contracts}); + result += plugin.generateContracts({contracts: contractsList}); }); } else { - for (let className in this.contractsManager.contracts) { - let contract = this.contractsManager.contracts[className]; - + for (let contract of contractsList) { let abi = JSON.stringify(contract.abiDefinition); let gasEstimates = JSON.stringify(contract.gasEstimates); @@ -184,9 +181,9 @@ class CodeGenerator { if (useEmbarkJS) { let contractAddress = contract.deployedAddress ? ("'" + contract.deployedAddress + "'") : "undefined"; - block += Templates.embarkjs_contract({className: className, abi: abi, contract: contract, contractAddress: contractAddress, gasEstimates: gasEstimates}); + block += Templates.embarkjs_contract({className: contract.className, abi: abi, contract: contract, contractAddress: contractAddress, gasEstimates: gasEstimates}); } else { - block += Templates.vanilla_contract({className: className, abi: abi, contract: contract, gasLimit: (isDeployment ? 6000000 : false)}); + block += Templates.vanilla_contract({className: contract.className, abi: abi, contract: contract, gasLimit: (isDeployment ? 6000000 : false)}); } result += Templates.exec_when_ready({block: block}); @@ -204,6 +201,17 @@ class CodeGenerator { return block; } + generateNamesInitialization(useEmbarkJS) { + if (!useEmbarkJS || this.namesystemConfig === {}) return ""; + + let result = "\n"; + result += Templates.define_when_env_loaded(); + result += this._getInitCode('names', this.namesystemConfig); + + return result; + } + + generateStorageInitialization(useEmbarkJS) { if (!useEmbarkJS || this.storageConfig === {}) return ""; @@ -239,35 +247,39 @@ class CodeGenerator { return result; } - generateABI(options) { + generateABI(contractsList, options) { let result = ""; result += this.generateProvider(options.deployment); - result += this.generateContracts(options.useEmbarkJS, options.deployment, true); + result += this.generateContracts(contractsList, options.useEmbarkJS, options.deployment, true); result += this.generateStorageInitialization(options.useEmbarkJS); result += this.generateCommunicationInitialization(options.useEmbarkJS); + result += this.generateNamesInitialization(options.useEmbarkJS); return result; } - generateContractsJSON() { + generateContractJSON(className, contract) { + let contractJSON = {}; + + contractJSON.contract_name = className; + contractJSON.address = contract.deployedAddress; + contractJSON.code = contract.code; + contractJSON.runtime_bytecode = contract.runtimeBytecode; + contractJSON.real_runtime_bytecode = contract.realRuntimeBytecode; + contractJSON.swarm_hash = contract.swarmHash; + contractJSON.gas_estimates = contract.gasEstimates; + contractJSON.function_hashes = contract.functionHashes; + contractJSON.abi = contract.abiDefinition; + + return contractJSON; + } + + generateContractsJSON(contractsList) { let contracts = {}; - for (let className in this.contractsManager.contracts) { - let contract = this.contractsManager.contracts[className]; - let contractJSON = {}; - - contractJSON.contract_name = className; - contractJSON.address = contract.deployedAddress; - contractJSON.code = contract.code; - contractJSON.runtime_bytecode = contract.runtimeBytecode; - contractJSON.real_runtime_bytecode = contract.realRuntimeBytecode; - contractJSON.swarm_hash = contract.swarmHash; - contractJSON.gas_estimates = contract.gasEstimates; - contractJSON.function_hashes = contract.functionHashes; - contractJSON.abi = contract.abiDefinition; - - contracts[className] = contractJSON; + for (let contract of contractsList) { + contracts[contract.className] = this.generateContractJSON(contract.className, contract); } return contracts; @@ -303,10 +315,9 @@ class CodeGenerator { code += plugin.embarkjs_code.join('\n'); } - //code += "\n" + fs.readFileSync(fs.embarkPath('js/embarkjs/orbit.js')).toString(); - code += self.generateCommunicationInitialization(true); code += self.generateStorageInitialization(true); + code += self.generateNamesInitialization(true); next(); }, function writeFile(next) { @@ -318,6 +329,63 @@ class CodeGenerator { cb(); }); } + + buildContractJS(contractName, contractJSON, cb) { + let contractCode = ""; + contractCode += "import web3 from 'Embark/web3';\n"; + contractCode += "import EmbarkJS from 'Embark/EmbarkJS';\n"; + contractCode += "let " + contractName + "JSONConfig = " + JSON.stringify(contractJSON) + ";\n"; + contractCode += "let " + contractName + " = new EmbarkJS.Contract(" + contractName + "JSONConfig);\n"; + + contractCode += "\n__embarkContext.execWhenReady(function() {\n"; + contractCode += "\n" + contractName + ".setProvider(web3.currentProvider);\n"; + contractCode += "\n" + contractName + ".options.from = web3.eth.defaultAccount;\n"; + contractCode += "\n});\n"; + + contractCode += "export default " + contractName + ";\n"; + cb(contractCode); + } + + buildWeb3JS(cb) { + const self = this; + let code = ""; + + async.waterfall([ + function getWeb3Location(next) { + self.events.request("version:get:web3", function(web3Version) { + if (web3Version === "1.0.0-beta") { + return next(null, utils.joinPath(fs.embarkPath("js/web3-1.0.min.js"))); + } else { + self.events.request("version:getPackageLocation", "web3", web3Version, function(err, location) { + return next(null, fs.dappPath(location)); + }); + } + }); + }, + function getImports(web3Location, next) { + web3Location = web3Location.replace(/\\/g, '/'); // Import paths must always have forward slashes + code += "\nimport Web3 from '" + web3Location + "';\n"; + + code += "\n if (typeof web3 !== 'undefined') {"; + code += "\n } else {"; + code += "\n var web3 = new Web3();\n"; + code += "\n }"; + + let providerCode = self.generateProvider(false); + code += providerCode; + code += "\nglobal.__embarkContext = __mainContext.__loadManagerInstance;\n"; + code += "\nwindow.web3 = web3;\n"; + code += "\nexport default web3;\n"; + next(null, code); + } + ], cb); + } + + buildPlaceholderPage(cb) { + let html = Templates.embark_building_placeholder({buildingMsg: __('Embark is building, please wait...')}); + cb(html); + } + } module.exports = CodeGenerator; diff --git a/lib/contracts/code_templates/embark-building-placeholder.html.ejs b/lib/contracts/code_templates/embark-building-placeholder.html.ejs new file mode 100644 index 000000000..b81d85b6a --- /dev/null +++ b/lib/contracts/code_templates/embark-building-placeholder.html.ejs @@ -0,0 +1,28 @@ + + + + <%- buildingMsg %> + + + + +
+
+
+
+
+
+ + + + + + + + + +

<%- buildingMsg %>

+ + \ No newline at end of file diff --git a/lib/contracts/code_templates/web3-connector.js.ejs b/lib/contracts/code_templates/web3-connector.js.ejs index be3e33519..f44368db3 100644 --- a/lib/contracts/code_templates/web3-connector.js.ejs +++ b/lib/contracts/code_templates/web3-connector.js.ejs @@ -26,6 +26,11 @@ __reduce(<%- connectionList %>,function(prev, value, next) { }, function(err, _result) { __getAccounts(function(err, accounts) { web3.eth.defaultAccount = accounts[0]; + <% if (warnAboutMetamask) { %> + if (web3.eth.currentProvider.isMetaMask) { + console.log("Note: Embark has detected you are in the development environment and using Metamask, please make sure Metamask is connected to your local node"); + } + <% } %> <%- done %> }); }); diff --git a/lib/contracts/compiler.js b/lib/contracts/compiler.js index 5b397ed1f..e6c4fc23e 100644 --- a/lib/contracts/compiler.js +++ b/lib/contracts/compiler.js @@ -43,7 +43,7 @@ class Compiler { function (err) { contractFiles.forEach(file => { if (!file.compiled) { - self.logger.warn(`${file.filename} doesn't have a compatible contract compiler. Maybe a plugin exists for it.`); + self.logger.warn(__("%s doesn't have a compatible contract compiler. Maybe a plugin exists for it.", file.filename)); } }); diff --git a/lib/contracts/contract_deployer.js b/lib/contracts/contract_deployer.js new file mode 100644 index 000000000..3385d642a --- /dev/null +++ b/lib/contracts/contract_deployer.js @@ -0,0 +1,263 @@ +let async = require('async'); +//require("../utils/debug_util.js")(__filename, async); +let utils = require('../utils/utils.js'); + +class ContractDeployer { + constructor(options) { + const self = this; + + this.blockchain = options.blockchain; + this.logger = options.logger; + this.events = options.events; + this.plugins = options.plugins; + this.gasLimit = options.gasLimit; + + self.events.setCommandHandler('deploy:contract', (contract, cb) => { + self.checkAndDeployContract(contract, null, cb); + }); + } + + // TODO: determining the arguments could also be in a module since it's not + // part of ta 'normal' contract deployment + determineArguments(suppliedArgs, contract, callback) { + const self = this; + + let args = suppliedArgs; + if (!Array.isArray(args)) { + args = []; + let abi = contract.abiDefinition.find((abi) => abi.type === 'constructor'); + + for (let input of abi.inputs) { + let inputValue = suppliedArgs[input.name]; + if (!inputValue) { + this.logger.error(__("{{inputName}} has not been defined for {{className}} constructor", {inputName: input.name, className: contract.className})); + } + args.push(inputValue || ""); + } + } + + async.map(args, (arg, nextEachCb) => { + if (arg[0] === "$") { + let contractName = arg.substr(1); + self.events.request('contracts:contract', contractName, (referedContract) => { + nextEachCb(null, referedContract.deployedAddress); + }); + } else if (Array.isArray(arg)) { + async.map(arg, (sub_arg, nextSubEachCb) => { + if (sub_arg[0] === "$") { + let contractName = sub_arg.substr(1); + + self.events.request('contracts:contract', contractName, (referedContract) => { + nextSubEachCb(null, referedContract.deployedAddress); + }); + } else { + nextSubEachCb(null, sub_arg); + } + }, (err, subRealArgs) => { + nextEachCb(null, subRealArgs); + }); + } else { + nextEachCb(null, arg); + } + }, callback); + } + + checkAndDeployContract(contract, params, callback) { + let self = this; + contract.error = false; + + if (contract.deploy === false) { + self.events.emit("deploy:contract:undeployed", contract); + return callback(); + } + + async.waterfall([ + function _determineArguments(next) { + self.determineArguments(params || contract.args, contract, (err, realArgs) => { + if (err) { + return next(err); + } + contract.realArgs = realArgs; + next(); + }); + }, + function deployIt(next) { + if (contract.address !== undefined) { + try { + utils.toChecksumAddress(contract.address); + } catch(e) { + self.logger.error(__("error deploying %s", contract.className)); + self.logger.error(e.message); + contract.error = e.message; + self.events.emit("deploy:contract:error", contract); + return next(e.message); + } + contract.deployedAddress = contract.address; + self.logger.info(contract.className.bold.cyan + __(" already deployed at ").green + contract.address.bold.cyan); + self.events.emit("deploy:contract:deployed", contract); + return next(); + } + + // TODO find a better way to do that + if (process.env.isTest) { + return self.deployContract(contract, next); + } + // TODO: this should be a plugin API instead, if not existing, it should by default deploy the contract + self.events.request("deploy:contract:shouldDeploy", contract, function(trackedContract) { + if (!trackedContract) { + return self.deployContract(contract, next); + } + + self.blockchain.getCode(trackedContract.address, function(_getCodeErr, codeInChain) { + if (codeInChain !== "0x") { + self.contractAlreadyDeployed(contract, trackedContract, next); + } else { + self.deployContract(contract, next); + } + }); + }); + } + ], callback); + } + + contractAlreadyDeployed(contract, trackedContract, callback) { + const self = this; + self.logger.info(contract.className.bold.cyan + __(" already deployed at ").green + trackedContract.address.bold.cyan); + contract.deployedAddress = trackedContract.address; + self.events.emit("deploy:contract:deployed", contract); + + // TODO: can be moved into a afterDeploy event + // just need to figure out the gasLimit coupling issue + self.events.request('code-generator:contract:vanilla', contract, contract._gasLimit, (contractCode) => { + self.events.request('runcode:eval', contractCode); + return callback(); + }); + } + + deployContract(contract, callback) { + let self = this; + let accounts = []; + let contractParams = (contract.realArgs || contract.args).slice(); + let contractCode = contract.code; + let deploymentAccount = self.blockchain.defaultAccount(); + let deployObject; + + async.waterfall([ + // TODO: can potentially go to a beforeDeploy plugin + function getAccounts(next) { + self.blockchain.getAccounts(function (err, _accounts) { + if (err) { + return next(new Error(err)); + } + accounts = _accounts; + + // applying deployer account configuration, if any + if (typeof contract.fromIndex == 'number') { + deploymentAccount = accounts[contract.fromIndex]; + if (deploymentAccount === undefined) { + return next(__("error deploying") + " " + contract.className + ": " + __("no account found at index") + " " + contract.fromIndex + __(" check the config")); + } + } + if (typeof contract.from == 'string' && typeof contract.fromIndex != 'undefined') { + self.logger.warn(__('Both "from" and "fromIndex" are defined for contract') + ' "' + contract.className + '". ' + __('Using "from" as deployer account.')); + } + if (typeof contract.from == 'string') { + deploymentAccount = contract.from; + } + + deploymentAccount = deploymentAccount || accounts[0]; + next(); + }); + }, + function doLinking(next) { + self.events.request('contracts:list', (_err, contracts) => { + for (let contractObj of contracts) { + let filename = contractObj.filename; + let deployedAddress = contractObj.deployedAddress; + if (deployedAddress) { + deployedAddress = deployedAddress.substr(2); + } + let linkReference = '__' + filename + ":" + contractObj.className; + if (contractCode.indexOf(linkReference) < 0) { + continue; + } + if (linkReference.length > 40) { + return next(new Error(__("{{linkReference}} is too long, try reducing the path of the contract ({{filename}}) and/or its name {{contractName}}", {linkReference: linkReference, filename: filename, contractName: contractObj.className}))); + } + let toReplace = linkReference + "_".repeat(40 - linkReference.length); + if (deployedAddress === undefined) { + let libraryName = contractObj.className; + return next(new Error(__("{{contractName}} needs {{libraryName}} but an address was not found, did you deploy it or configured an address?", {contractName: contract.className, libraryName: libraryName}))); + } + contractCode = contractCode.replace(new RegExp(toReplace, "g"), deployedAddress); + } + // saving code changes back to contract object + contract.code = contractCode; + next(); + }); + }, + function applyBeforeDeploy(next) { + self.plugins.emitAndRunActionsForEvent('deploy:contract:beforeDeploy', {contract: contract}, next); + }, + function createDeployObject(next) { + let contractObject = self.blockchain.ContractObject({abi: contract.abiDefinition}); + + try { + const dataCode = contractCode.startsWith('0x') ? contractCode : "0x" + contractCode; + deployObject = self.blockchain.deployContractObject(contractObject, {arguments: contractParams, data: dataCode}); + } catch(e) { + if (e.message.indexOf('Invalid number of parameters for "undefined"') >= 0) { + return next(new Error(__("attempted to deploy %s without specifying parameters", contract.className))); + } else { + return next(new Error(e)); + } + } + next(); + }, + function estimateCorrectGas(next) { + if (contract.gas === 'auto') { + return self.blockchain.estimateDeployContractGas(deployObject, (err, gasValue) => { + if (err) { + return next(err); + } + contract.gas = gasValue; + next(); + }); + } + next(); + }, + function deployTheContract(next) { + self.logger.info(__("deploying") + " " + contract.className.bold.cyan + " " + __("with").green + " " + contract.gas + " " + __("gas").green); + + self.blockchain.deployContractFromObject(deployObject, { + from: deploymentAccount, + gas: contract.gas, + gasPrice: contract.gasPrice + }, function(error, receipt) { + if (error) { + contract.error = error.message; + self.events.emit("deploy:contract:error", contract); + return next(new Error("error deploying =" + contract.className + "= due to error: " + error.message)); + } + self.logger.info(contract.className.bold.cyan + " " + __("deployed at").green + " " + receipt.contractAddress.bold.cyan); + contract.deployedAddress = receipt.contractAddress; + contract.transactionHash = receipt.transactionHash; + self.events.emit("deploy:contract:receipt", receipt); + self.events.emit("deploy:contract:deployed", contract); + + // TODO: can be moved into a afterDeploy event + // just need to figure out the gasLimit coupling issue + self.events.request('code-generator:contract:vanilla', contract, contract._gasLimit, (contractCode) => { + self.events.request('runcode:eval', contractCode); + self.plugins.runActionsForEvent('deploy:contract:deployed', {contract: contract}, () => { + return next(null, receipt); + }); + }); + }); + } + ], callback); + } + +} + +module.exports = ContractDeployer; diff --git a/lib/contracts/contracts.js b/lib/contracts/contracts.js index 10f567085..f53d5fd53 100644 --- a/lib/contracts/contracts.js +++ b/lib/contracts/contracts.js @@ -1,16 +1,16 @@ let toposort = require('toposort'); let async = require('async'); +const cloneDeep = require('clone-deep'); -let Compiler = require('./compiler.js'); let utils = require('../utils/utils.js'); -const constants = require('../constants'); // TODO: create a contract object class ContractsManager { constructor(options) { + const self = this; this.contractFiles = options.contractFiles; - this.contractsConfig = options.contractsConfig; + this.contractsConfig = cloneDeep(options.contractsConfig || {}); this.contracts = {}; this.logger = options.logger; this.plugins = options.plugins; @@ -18,26 +18,66 @@ class ContractsManager { this.gasLimit = options.gasLimit; this.deployOnlyOnConfig = false; this.events = options.events; + this.compileError = false; - this.events.on(constants.events.contractFilesChanged, (newContractFiles) => { - this.contractFiles = newContractFiles; + self.events.setCommandHandler('contracts:list', (cb) => { + cb(self.compileError, self.listContracts()); }); - this.events.on(constants.events.contractConfigChanged, (newContracts) => { - this.contractsConfig = newContracts; + + self.events.setCommandHandler("contracts:contract", (contractName, cb) => { + cb(self.getContract(contractName)); }); + + self.events.setCommandHandler("contracts:build", (configOnly, cb) => { + self.deployOnlyOnConfig = configOnly; // temporary, should refactor + self.build((err) => { + cb(err); + }); + }); + + self.events.on("deploy:contract:error", (_contract) => { + self.events.emit('contractsState', self.contractsState()); + }); + + self.events.on("deploy:contract:deployed", (_contract) => { + self.events.emit('contractsState', self.contractsState()); + }); + + self.events.on("deploy:contract:undeployed", (_contract) => { + self.events.emit('contractsState', self.contractsState()); + }); + } build(done) { let self = this; + self.contracts = {}; async.waterfall([ + function loadContractFiles(callback) { + self.events.request("config:contractsFiles", (contractsFiles) => { + self.contractsFiles = contractsFiles; + callback(); + }); + }, + function loadContractConfigs(callback) { + self.events.request("config:contractsConfig", (contractsConfig) => { + self.contractsConfig = cloneDeep(contractsConfig); + callback(); + }); + }, function compileContracts(callback) { - let compiler = new Compiler({plugins: self.plugins, logger: self.logger}); - compiler.compile_contracts(self.contractFiles, function (err, compiledObject) { + self.events.emit("status", __("Compiling...")); + if (process.env.isTest && self.compiledContracts && Object.keys(self.compiledContracts).length) { + // Only compile once for tests + return callback(); + } + self.events.request("compiler:contracts", self.contractFiles, function (err, compiledObject) { self.compiledContracts = compiledObject; callback(err); }); }, function prepareContractsFromConfig(callback) { + self.events.emit("status", __("Building...")); let className, contract; for (className in self.contractsConfig.contracts) { contract = self.contractsConfig.contracts[className]; @@ -49,7 +89,13 @@ class ContractsManager { } callback(); }, - function prepareContractsFromCompilation(callback) { + function getGasPriceForNetwork(callback) { + if (self.contractsConfig.gasPrice) { + return callback(null, self.contractsConfig.gasPrice); + } + self.events.request("blockchain:gasPrice", callback); + }, + function prepareContractsFromCompilation(gasPrice, callback) { let className, compiledContract, contractConfig, contract; for (className in self.compiledContracts) { compiledContract = self.compiledContracts[className]; @@ -68,7 +114,7 @@ class ContractsManager { contract.gas = (contractConfig && contractConfig.gas) || self.contractsConfig.gas || 'auto'; - contract.gasPrice = contract.gasPrice || self.contractsConfig.gasPrice; + contract.gasPrice = contract.gasPrice || gasPrice; contract.type = 'file'; contract.className = className; @@ -86,7 +132,7 @@ class ContractsManager { } if (contract.code === "") { - self.logger.info("assuming " + className + " to be an interface"); + self.logger.info(__("assuming %s to be an interface", className)); contract.deploy = false; } } @@ -108,15 +154,15 @@ class ContractsManager { parentContract = self.contracts[parentContractName]; if (parentContract === className) { - self.logger.error(className + ": instanceOf is set to itself"); + self.logger.error(__("%s : instanceOf is set to itself", className)); continue; } if (parentContract === undefined) { - self.logger.error(className + ": couldn't find instanceOf contract " + parentContractName); + self.logger.error(__("{{className}}: couldn't find instanceOf contract {{parentContractName}}", {className: className, parentContractName: parentContractName})); let suggestion = utils.proposeAlternative(parentContractName, dictionary, [className, parentContractName]); if (suggestion) { - self.logger.warn('did you mean "' + suggestion + '"?'); + self.logger.warn(__('did you mean "%s"?', suggestion)); } continue; } @@ -126,7 +172,7 @@ class ContractsManager { } if (contract.code !== undefined) { - self.logger.error(className + " has code associated to it but it's configured as an instanceOf " + parentContractName); + self.logger.error(__("{{className}} has code associated to it but it's configured as an instanceOf {{parentContractName}}", {className: className, parentContractName: parentContractName})); } contract.code = parentContract.code; @@ -149,10 +195,10 @@ class ContractsManager { contract = self.contracts[className]; if (contract.code === undefined) { - self.logger.error(className + " has no code associated"); + self.logger.error(__("%s has no code associated", className)); let suggestion = utils.proposeAlternative(className, dictionary, [className]); if (suggestion) { - self.logger.warn('did you mean "' + suggestion + '"?'); + self.logger.warn(__('did you mean "%s"?', suggestion)); } delete self.contracts[className]; } @@ -191,12 +237,14 @@ class ContractsManager { if (arg[0] === "$") { self.contractDependencies[className] = self.contractDependencies[className] || []; self.contractDependencies[className].push(arg.substr(1)); + self.checkDependency(className, arg.substr(1)); } if (Array.isArray(arg)) { for (let sub_arg of arg) { if (sub_arg[0] === "$") { self.contractDependencies[className] = self.contractDependencies[className] || []; self.contractDependencies[className].push(sub_arg.substr(1)); + self.checkDependency(className, sub_arg.substr(1)); } } } @@ -216,13 +264,32 @@ class ContractsManager { } ], function (err, _result) { if (err) { - self.logger.error("Error Compiling/Building contracts: " + err); + self.compileError = true; + self.events.emit("status", __("Compile/Build error")); + self.logger.error(__("Error Compiling/Building contracts: ") + err); + }else{ + self.compileError = false; } self.logger.trace("finished".underline); done(err, self); }); } + checkDependency(className, dependencyName) { + if (!this.contractDependencies[className]) { + return; + } + if (!this.contracts[dependencyName]) { + this.logger.warn(__('{{className}} has a dependency on {{dependencyName}}', {className, dependencyName}) + + __(', but it is not present in the contracts')); + return; + } + if (!this.contracts[dependencyName].deploy) { + this.logger.warn(__('{{className}} has a dependency on {{dependencyName}}', {className, dependencyName}) + + __(', but it is not set to deploy. It could be an interface.')); + } + } + getContract(className) { return this.contracts[className]; } @@ -242,9 +309,9 @@ class ContractsManager { try { orderedDependencies = toposort(converted_dependencies.filter((x) => x[0] != x[1])).reverse(); } catch(e) { - this.logger.error(("Error: " + e.message).red); - this.logger.error("there are two or more contracts that depend on each other in a cyclic manner".bold.red); - this.logger.error("Embark couldn't determine which one to deploy first".red); + this.logger.error((__("Error: ") + e.message).red); + this.logger.error(__("there are two or more contracts that depend on each other in a cyclic manner").bold.red); + this.logger.error(__("Embark couldn't determine which one to deploy first").red); throw new Error("CyclicDependencyError"); //process.exit(0); } @@ -279,7 +346,7 @@ class ContractsManager { if (contract.deploy === false) { contractData = [ className.green, - 'Interface or set to not deploy'.green, + __('Interface or set to not deploy').green, "\t\tn/a".green ]; } else if (contract.error) { @@ -292,7 +359,7 @@ class ContractsManager { contractData = [ className.green, (contract.deployedAddress || '...').green, - ((contract.deployedAddress !== undefined) ? "\t\tDeployed".green : "\t\tPending".magenta) + ((contract.deployedAddress !== undefined) ? ("\t\t" + __("Deployed")).green : ("\t\t" + __("Pending")).magenta) ]; } diff --git a/lib/contracts/deploy.js b/lib/contracts/deploy.js deleted file mode 100644 index 1551331c5..000000000 --- a/lib/contracts/deploy.js +++ /dev/null @@ -1,381 +0,0 @@ -let async = require('async'); -//require("../utils/debug_util.js")(__filename, async); - -let RunCode = require('../core/runCode.js'); - -let DeployTracker = require('./deploy_tracker.js'); -let CodeGenerator = require('./code_generator.js'); - -class Deploy { - constructor(options) { - this.web3 = options.web3; - this.contractsManager = options.contractsManager; - this.logger = options.logger; - this.events = options.events; - this.env = options.env; - this.chainConfig = options.chainConfig; - this.plugins = options.plugins; - this.gasLimit = options.gasLimit; - } - - initTracker(cb) { - this.deployTracker = new DeployTracker({ - logger: this.logger, chainConfig: this.chainConfig, web3: this.web3, env: this.env - }, cb); - } - - determineArguments(suppliedArgs, contract) { - let realArgs = [], l, arg, contractName, referedContract; - - let args = suppliedArgs; - - if (!Array.isArray(args)) { - args = []; - let abi = contract.abiDefinition.find((abi) => abi.type === 'constructor'); - - for (let input of abi.inputs) { - let inputValue = suppliedArgs[input.name]; - if (!inputValue) { - this.logger.error(input.name + " has not been defined for " + contract.className + " constructor"); - } - args.push(inputValue || ""); - } - } - - for (l = 0; l < args.length; l++) { - arg = args[l]; - if (arg[0] === "$") { - contractName = arg.substr(1); - referedContract = this.contractsManager.getContract(contractName); - realArgs.push(referedContract.deployedAddress); - } else if (Array.isArray(arg)) { - let subRealArgs = []; - for (let sub_arg of arg) { - if (sub_arg[0] === "$") { - contractName = sub_arg.substr(1); - referedContract = this.contractsManager.getContract(contractName); - subRealArgs.push(referedContract.deployedAddress); - } else { - subRealArgs.push(sub_arg); - } - } - realArgs.push(subRealArgs); - } else { - realArgs.push(arg); - } - } - - return realArgs; - } - - checkAndDeployContract(contract, params, callback) { - let self = this; - let realArgs; - contract.error = false; - - if (contract.deploy === false) { - self.events.emit('contractsState', self.contractsManager.contractsState()); - return callback(); - } - - realArgs = self.determineArguments(params || contract.args, contract); - - if (contract.address !== undefined) { - try { - this.web3.utils.toChecksumAddress(contract.address); - } catch(e) { - self.logger.error("error deploying " + contract.className); - self.logger.error(e.message); - contract.error = e.message; - self.events.emit('contractsState', self.contractsManager.contractsState()); - return callback(e.message); - } - contract.deployedAddress = contract.address; - self.logger.info(contract.className.bold.cyan + " already deployed at ".green + contract.address.bold.cyan); - if (this.deployTracker) { - self.deployTracker.trackContract(contract.className, contract.realRuntimeBytecode, realArgs, contract.address); - self.deployTracker.save(); - } - self.events.emit('contractsState', self.contractsManager.contractsState()); - return callback(); - } - - if (!this.deployTracker) { - return self.contractToDeploy(contract, params, callback); - } - - let trackedContract = self.deployTracker.getContract(contract.className, contract.realRuntimeBytecode, realArgs); - if (!trackedContract) { - return self.contractToDeploy(contract, params, callback); - } - - this.web3.eth.getCode(trackedContract.address, function(_getCodeErr, codeInChain) { - if (codeInChain !== "0x") { - self.contractAlreadyDeployed(contract, trackedContract, callback); - } else { - self.contractToDeploy(contract, params, callback); - } - }); - } - - contractAlreadyDeployed(contract, trackedContract, callback) { - const self = this; - self.logger.info(contract.className.bold.cyan + " already deployed at ".green + trackedContract.address.bold.cyan); - contract.deployedAddress = trackedContract.address; - self.events.emit('contractsState', self.contractsManager.contractsState()); - - // always run contractCode so other functionality like 'afterDeploy' can also work - let codeGenerator = new CodeGenerator({contractsManager: self.contractsManager}); - let contractCode = codeGenerator.generateContractCode(contract, self.gasLimit); - RunCode.doEval(contractCode, self.web3); - - return callback(); - } - - contractToDeploy(contract, params, callback) { - const self = this; - let realArgs = self.determineArguments(params || contract.args, contract); - - this.deployContract(contract, realArgs, function (err, address) { - if (err) { - return callback(new Error(err)); - } - self.deployTracker.trackContract(contract.className, contract.realRuntimeBytecode, realArgs, address); - self.deployTracker.save(); - self.events.emit('contractsState', self.contractsManager.contractsState()); - - // always run contractCode so other functionality like 'afterDeploy' can also work - let codeGenerator = new CodeGenerator({contractsManager: self.contractsManager}); - let contractCode = codeGenerator.generateContractCode(contract, self.gasLimit); - RunCode.doEval(contractCode, self.web3); - - if (contract.onDeploy !== undefined) { - self.logger.info('executing onDeploy commands'); - - let contractCode = codeGenerator.generateContractCode(contract, self.gasLimit); - RunCode.doEval(contractCode, self.web3); - - let withErrors = false; - let regex = /\$\w+/g; - let onDeployCode = contract.onDeploy.map((cmd) => { - let realCmd = cmd.replace(regex, (match) => { - let referedContractName = match.slice(1); - let referedContract = self.contractsManager.getContract(referedContractName); - if (!referedContract) { - self.logger.error('error executing onDeploy for ' + contract.className); - self.logger.error(referedContractName + ' does not exist'); - self.logger.error("error running onDeploy: " + cmd); - withErrors = true; - return; - } - if (referedContract && referedContract.deploy === false) { - self.logger.error('error executing onDeploy for ' + contract.className); - self.logger.error(referedContractName + " exists but has been set to not deploy"); - self.logger.error("error running onDeploy: " + cmd); - withErrors = true; - return; - } - if (referedContract && !referedContract.deployedAddress) { - self.logger.error('error executing onDeploy for ' + contract.className); - self.logger.error("couldn't find a valid address for " + referedContractName + ". has it been deployed?"); - self.logger.error("error running onDeploy: " + cmd); - withErrors = true; - return; - } - return referedContract.deployedAddress; - }); - return realCmd; - }); - - if (withErrors) { - contract.error = "onDeployCmdError"; - return callback(new Error("error running onDeploy")); - } - - // TODO: convert to for to avoid repeated callback - for(let cmd of onDeployCode) { - self.logger.info("executing: " + cmd); - try { - RunCode.doEval(cmd, self.web3); - } catch(e) { - if (e.message.indexOf("invalid opcode") >= 0) { - self.logger.error('the transaction was rejected; this usually happens due to a throw or a require, it can also happen due to an invalid operation'); - } - return callback(new Error(e)); - } - } - } - - callback(); - }); - } - - deployContract(contract, params, callback) { - let self = this; - let accounts = []; - let contractParams = (params || contract.args).slice(); - let contractCode = contract.code; - let deploymentAccount = self.web3.eth.defaultAccount; - let deployObject; - - async.waterfall([ - function getAccounts(next) { - self.web3.eth.getAccounts(function (err, _accounts) { - if (err) { - return next(new Error(err)); - } - accounts = _accounts; - - // applying deployer account configuration, if any - if (typeof contract.fromIndex == 'number') { - deploymentAccount = accounts[contract.fromIndex]; - if (deploymentAccount === undefined) { - return next("error deploying " + contract.className + ": no account found at index " + contract.fromIndex + " check the config"); - } - } - if (typeof contract.from == 'string' && typeof contract.fromIndex != 'undefined') { - self.logger.warn('Both "from" and "fromIndex" are defined for contract "'+contract.className+'". Using "from" as deployer account.'); - } - if (typeof contract.from == 'string') { - deploymentAccount = contract.from; - } - - deploymentAccount = deploymentAccount || accounts[0]; - next(); - }); - }, - function doLinking(next) { - // Applying linked contracts - let contractsList = self.contractsManager.listContracts(); - for (let contractObj of contractsList) { - let filename = contractObj.filename; - let deployedAddress = contractObj.deployedAddress; - if (deployedAddress) { - deployedAddress = deployedAddress.substr(2); - } - let linkReference = '__' + filename + ":" + contractObj.className; - if (contractCode.indexOf(linkReference) < 0) { - continue; - } - if (linkReference.length > 40) { - return next(new Error(linkReference + " is too long, try reducing the path of the contract (" + filename + ") and/or its name " + contractObj.className)); - } - let toReplace = linkReference + "_".repeat(40 - linkReference.length); - if (deployedAddress === undefined) { - let libraryName = contractObj.className; - return next(new Error(contract.className + " needs " + libraryName + " but an address was not found, did you deploy it or configured an address?")); - } - contractCode = contractCode.replace(new RegExp(toReplace, "g"), deployedAddress); - } - // saving code changes back to contract object - contract.code = contractCode; - next(); - }, - function applyBeforeDeploy(next) { - let beforeDeployPlugins = self.plugins.getPluginsFor('beforeDeploy'); - - //self.logger.info("applying beforeDeploy plugins...", beforeDeployPlugins.length); - async.eachSeries(beforeDeployPlugins, (plugin, eachPluginCb) => { - self.logger.info("running beforeDeploy plugin " + plugin.name + " ."); - - // 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: beforeDeployCb - }, beforeDeployCb); - }, () => { - //self.logger.info('All beforeDeploy handlers of the plugin has processed.'); - eachPluginCb(); - }); - }, () => { - //self.logger.info('All beforeDeploy plugins has been processed.'); - contractCode = contract.code; - next(); - }); - }, - function createDeployObject(next) { - let contractObject = new self.web3.eth.Contract(contract.abiDefinition); - - try { - const dataCode = contractCode.startsWith('0x') ? contractCode : "0x" + contractCode; - deployObject = contractObject.deploy({arguments: contractParams, data: dataCode}); - } catch(e) { - if (e.message.indexOf('Invalid number of parameters for "undefined"') >= 0) { - return next(new Error("attempted to deploy " + contract.className + " without specifying parameters")); - } else { - return next(new Error(e)); - } - } - next(); - }, - function estimateCorrectGas(next) { - if (contract.gas === 'auto') { - return deployObject.estimateGas().then((gasValue) => { - contract.gas = gasValue; - next(); - }).catch(next); - } - next(); - }, - function deployTheContract(next) { - self.logger.info("deploying " + contract.className.bold.cyan + " with ".green + contract.gas + " gas".green); - - deployObject.send({ - from: deploymentAccount, - gas: contract.gas, - gasPrice: contract.gasPrice - }).on('receipt', function(receipt) { - if (receipt.contractAddress !== undefined) { - self.logger.info(contract.className.bold.cyan + " deployed at ".green + receipt.contractAddress.bold.cyan); - contract.deployedAddress = receipt.contractAddress; - contract.transactionHash = receipt.transactionHash; - self.events.emit('contractsState', self.contractsManager.contractsState()); - return next(null, receipt.contractAddress); - } - self.events.emit('contractsState', self.contractsManager.contractsState()); - }).on('error', function(error) { - self.events.emit('contractsState', self.contractsManager.contractsState()); - return next(new Error("error deploying =" + contract.className + "= due to error: " + error.message)); - }); - } - ], callback); - } - - deployAll(done) { - let self = this; - this.logger.info("deploying contracts"); - let contracts = this.contractsManager.listContracts(); - - async.eachOfSeries(contracts, - function (contract, key, callback) { - self.logger.trace(arguments); - self.checkAndDeployContract(contract, null, callback); - }, - function (err, _results) { - if (err) { - self.logger.error("error deploying contracts"); - 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); - } - ); - - } -} - -module.exports = Deploy; diff --git a/lib/contracts/deploy_manager.js b/lib/contracts/deploy_manager.js index d309863ed..7f63a4d43 100644 --- a/lib/contracts/deploy_manager.js +++ b/lib/contracts/deploy_manager.js @@ -1,161 +1,117 @@ let async = require('async'); -//require("../utils/debug_util.js")(__filename, async); -let Deploy = require('./deploy.js'); -let RunCode = require('../core/runCode.js'); class DeployManager { constructor(options) { + const self = this; this.config = options.config; this.logger = options.logger; this.blockchainConfig = this.config.blockchainConfig; this.events = options.events; this.plugins = options.plugins; - this.web3 = options.web3; - this.chainConfig = (options.trackContracts !== false) ? this.config.chainTracker : false; - this.contractsManager = options.contractsManager; + this.blockchain = options.blockchain; this.gasLimit = false; this.fatalErrors = false; this.deployOnlyOnConfig = false; this.onlyCompile = options.onlyCompile !== undefined ? options.onlyCompile : false; + + this.events.setCommandHandler('deploy:contracts', (cb) => { + self.deployContracts(cb); + }); + } + + deployAll(done) { + let self = this; + + self.events.request('contracts:list', (err, contracts) => { + if (err) { + return done(err); + } + + self.logger.info(__("deploying contracts")); + self.events.emit("deploy:beforeAll"); + + async.eachOfSeries(contracts, + function (contract, key, callback) { + contract._gasLimit = self.gasLimit; + self.events.request('deploy:contract', contract, (err) => { + callback(err); + }); + }, + function (err, _results) { + if (err) { + self.logger.error(__("error deploying contracts")); + 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")); + done(err); + } + ); + }); } deployContracts(done) { let self = this; if (self.blockchainConfig === {} || self.blockchainConfig.enabled === false) { - self.logger.info("Blockchain component is disabled in the config".underline); + self.logger.info(__("Blockchain component is disabled in the config").underline); this.events.emit('blockchainDisabled', {}); return done(); } async.waterfall([ function buildContracts(callback) { - self.contractsManager.deployOnlyOnConfig = self.deployOnlyOnConfig; // temporary, should refactor - self.contractsManager.build(callback); + self.events.request("contracts:build", self.deployOnlyOnConfig, (err) => { + callback(err); + }); }, - function checkCompileOnly(contractsManager, callback){ + + // TODO: shouldn't be necessary + function checkCompileOnly(callback){ if(self.onlyCompile){ - self.events.emit('contractsDeployed', contractsManager); + self.events.emit('contractsDeployed'); return done(); } - return callback(null, contractsManager); + return callback(); }, - function checkWeb3IsConnected(contractsManager, callback) { - if (!self.web3) { - return callback(Error("no web3 instance found")); - } - if (self.web3.currentProvider === undefined) { - self.logger.error(("Couldn't connect to an Ethereum node are you sure it's on?").red); - self.logger.info("make sure you have an Ethereum node or simulator running. e.g 'embark blockchain'".magenta); - return callback(Error("error connecting to blockchain node")); - } - - self.web3.eth.getAccounts(function(err, _accounts) { - if (err) { - self.logger.error(("Couldn't connect to an Ethereum node are you sure it's on?").red); - self.logger.info("make sure you have an Ethereum node or simulator running. e.g 'embark blockchain'".magenta); - return callback(Error("error connecting to blockchain node")); - } - return callback(null, contractsManager, self.web3); - }); - }, - function setDefaultAccount(contractsManager, web3, callback) { - web3.eth.getAccounts(function (err, accounts) { - if (err) { - self.logger.error(err); - return callback(new Error(err)); - } - let accountConfig = self.config.blockchainConfig.account; - let selectedAccount = accountConfig && accountConfig.address; - web3.eth.defaultAccount = (selectedAccount || accounts[0]); - callback(null, contractsManager, web3); - }); - }, - function deployAllContracts(contractsManager, web3, callback) { - let deploy = new Deploy({ - web3: web3, - contractsManager: contractsManager, - logger: self.logger, - events: self.events, - chainConfig: self.chainConfig, - env: self.config.env, - plugins: self.plugins, - gasLimit: self.gasLimit - }); - - deploy.initTracker(function() { - deploy.deployAll(function (err) { - if (!err) { - self.events.emit('contractsDeployed', contractsManager); - } - if (err && self.fatalErrors) { - return callback(err); - } - callback(null, contractsManager, web3); + // TODO: could be implemented as an event (beforeDeployAll) + function checkIsConnectedToBlockchain(callback) { + self.blockchain.onReady(() => { + self.blockchain.assertNodeConnection((err) => { + callback(err); }); }); }, - function runAfterDeployCommands(contractsManager, web3, callback) { - let afterDeployCmds = self.config.contractsConfig.afterDeploy || []; - let withErrors = false; - let regex = /\$\w+/g; - let onDeployCode = afterDeployCmds.map((cmd) => { - let realCmd = cmd.replace(regex, (match) => { - let referedContractName = match.slice(1); - let referedContract = contractsManager.getContract(referedContractName); - if (!referedContract) { - self.logger.error(referedContractName + ' does not exist'); - self.logger.error("error running afterDeploy: " + cmd); - withErrors = true; - return; - } - if (referedContract && referedContract.deploy === false) { - self.logger.error(referedContractName + " exists but has been set to not deploy"); - self.logger.error("error running afterDeploy: " + cmd); - withErrors = true; - return; - } - if (referedContract && !referedContract.deployedAddress) { - self.logger.error("couldn't find a valid address for " + referedContractName + ". has it been deployed?"); - self.logger.error("error running afterDeploy: " + cmd); - withErrors = true; - return; - } - return referedContract.deployedAddress; - }); - return realCmd; + // TODO: this can be done on the fly or as part of the initialization + function determineDefaultAccount(callback) { + self.blockchain.determineDefaultAccount((err) => { + callback(err); }); + }, - if (withErrors) { - return callback(new Error("error running afterDeploy")); - } - - async.each(onDeployCode, (cmd, eachCb) => { - self.logger.info("executing: " + cmd); - try { - RunCode.doEval(cmd, web3); - } catch(e) { - if (e.message.indexOf("invalid opcode") >= 0) { - self.logger.error('the transaction was rejected; this usually happens due to a throw or a require, it can also happen due to an invalid operation'); - } - return eachCb(new Error(e)); + function deployAllContracts(callback) { + self.deployAll(function (err) { + if (!err) { + self.events.emit('contractsDeployed'); } - eachCb(); - }, (err) => { - callback(err, contractsManager); + if (err && self.fatalErrors) { + return callback(err); + } + callback(); }); - - - } - ], function (err, result) { - if (err) { - done(err, null); - } else { - done(null, result); + }, + function runAfterDeploy(callback) { + self.plugins.emitAndRunActionsForEvent('contracts:deploy:afterAll', callback); } + ], function (err, _result) { + done(err); }); } diff --git a/lib/contracts/deploy_tracker.js b/lib/contracts/deploy_tracker.js deleted file mode 100644 index 2497b2dcb..000000000 --- a/lib/contracts/deploy_tracker.js +++ /dev/null @@ -1,64 +0,0 @@ -let fs = require('../core/fs.js'); - -class DeployTracker { - constructor(options, cb) { - const self = this; - this.logger = options.logger; - this.env = options.env; - this.chainConfig = options.chainConfig; - this.web3 = options.web3; - - if (this.chainConfig === false) { - this.currentChain = {contracts: []}; - return cb(); - } - - this.web3.eth.getBlock(0, function(err, block) { - let chainId = block.hash; - - if (self.chainConfig[chainId] === undefined) { - self.chainConfig[chainId] = {contracts: {}}; - } - - self.currentChain = self.chainConfig[chainId]; - - self.currentChain.name = self.env; - cb(); - }); - - // TODO: add other params - //this.currentChain.networkId = ""; - //this.currentChain.networkType = "custom" - } - - loadConfig(config) { - this.chainConfig = config; - return this; - } - - trackContract(contractName, code, args, address) { - this.currentChain.contracts[this.web3.utils.sha3(code + contractName + args.join(','))] = { - name: contractName, - address: address - }; - } - - getContract(contractName, code, args) { - let contract = this.currentChain.contracts[this.web3.utils.sha3(code + contractName + args.join(','))]; - if (contract && contract.address === undefined) { - return false; - } - return contract; - } - - // TODO: abstract this - // chainConfig can be an abstract PersistentObject - save() { - if (this.chainConfig === false) { - return; - } - fs.writeJSONSync("./chains.json", this.chainConfig, {spaces: 2}); - } -} - -module.exports = DeployTracker; diff --git a/lib/contracts/fundAccount.js b/lib/contracts/fundAccount.js new file mode 100644 index 000000000..35470b547 --- /dev/null +++ b/lib/contracts/fundAccount.js @@ -0,0 +1,76 @@ +const async = require('async'); +const TARGET = 0x7FFFFFFFFFFFFFFF; +const ALREADY_FUNDED = 'alreadyFunded'; + +function fundAccount(web3, accountAddress, hexBalance, callback) { + if (!hexBalance) { + hexBalance = TARGET; + } + const targetBalance = (typeof hexBalance === 'string') ? parseInt(hexBalance, 16) : hexBalance; + let accountBalance; + let coinbaseAddress; + let lastNonce; + let gasPrice; + + async.waterfall([ + function getAccountBalance(next) { + web3.eth.getBalance(accountAddress, (err, balance) => { + if (err) { + return next(err); + } + if (balance >= targetBalance) { + return next(ALREADY_FUNDED); + } + accountBalance = balance; + next(); + }); + }, + function getNeededParams(next) { + async.parallel([ + function getCoinbaseAddress(paraCb) { + web3.eth.getCoinbase() + .then((address) => { + coinbaseAddress = address; + paraCb(); + }).catch(paraCb); + }, + function getGasPrice(paraCb) { + web3.eth.getGasPrice((err, price) => { + if (err) { + return paraCb(err); + } + gasPrice = price; + paraCb(); + }); + } + ], (err, _result) => { + next(err); + }); + }, + function getNonce(next) { + web3.eth.getTransactionCount(coinbaseAddress, (err, nonce) => { + if (err) { + return next(err); + } + lastNonce = nonce; + next(); + }); + }, + function sendTransaction(next) { + web3.eth.sendTransaction({ + from: coinbaseAddress, + to: accountAddress, + value: targetBalance - accountBalance, + gasPrice: gasPrice, + nonce: lastNonce + }, next); + } + ], (err) => { + if (err && err !== ALREADY_FUNDED) { + return callback(err); + } + callback(); + }); +} + +module.exports = fundAccount; diff --git a/lib/contracts/provider.js b/lib/contracts/provider.js new file mode 100644 index 000000000..59e128fbb --- /dev/null +++ b/lib/contracts/provider.js @@ -0,0 +1,113 @@ +const ProviderEngine = require('embark-web3-provider-engine'); +const RpcSubprovider = require('embark-web3-provider-engine/subproviders/rpc'); +const WsSubprovider = require('embark-web3-provider-engine/subproviders/websocket'); +const async = require('async'); +const AccountParser = require('./accountParser'); +const fundAccount = require('./fundAccount'); + +const NO_ACCOUNTS = 'noAccounts'; + +class Provider { + constructor(options) { + this.web3 = options.web3; + this.accountsConfig = options.accountsConfig; + this.blockchainConfig = options.blockchainConfig; + this.type = options.type; + this.web3Endpoint = options.web3Endpoint; + this.logger = options.logger; + this.isDev = options.isDev; + this.engine = new ProviderEngine(); + this.asyncMethods = {}; + } + + startWeb3Provider(callback) { + const self = this; + + if (this.type === 'rpc') { + self.engine.addProvider(new RpcSubprovider({ + rpcUrl: self.web3Endpoint + })); + } else if (this.type === 'ws') { + self.engine.addProvider(new WsSubprovider({ + rpcUrl: self.web3Endpoint, + origin: this.blockchainConfig.wsOrigins.split(',')[0] + })); + } else { + return callback(__("contracts config error: unknown deployment type %s", this.type)); + } + + + // network connectivity error + self.engine.on('error', (err) => { + // report connectivity errors + self.logger.error(err.stack); + }); + + self.engine.start(); + self.web3.setProvider(self); + + self.accounts = AccountParser.parseAccountsConfig(self.accountsConfig, self.web3, self.logger); + self.addresses = []; + async.waterfall([ + function populateWeb3Wallet(next) { + if (!self.accounts.length) { + return next(NO_ACCOUNTS); + } + self.accounts.forEach(account => { + self.addresses.push(account.address); + self.web3.eth.accounts.wallet.add(account); + }); + self.asyncMethods = { + eth_accounts: self.eth_accounts.bind(self) + }; + next(); + } + ], function (err) { + if (err && err !== NO_ACCOUNTS) { + self.logger.error((err)); + } + callback(); + }); + } + + fundAccounts(callback) { + const self = this; + if (!self.accounts.length) { + return callback(); + } + if (!self.isDev) { + return callback(); + } + async.each(self.accounts, (account, eachCb) => { + fundAccount(self.web3, account.address, account.hexBalance, eachCb); + }, callback); + } + + stop() { + this.engine.stop(); + } + + eth_accounts(payload, cb) { + return cb(null, this.addresses); + } + + sendAsync(payload, callback) { + let method = this.asyncMethods[payload.method]; + if (method) { + return method.call(method, payload, (err, result) => { + if (err) { + return callback(err); + } + let response = {'id': payload.id, 'jsonrpc': '2.0', 'result': result}; + callback(null, response); + }); + } + this.engine.sendAsync.apply(this.engine, arguments); + } + + send() { + return this.engine.send.apply(this.engine, arguments); + } +} + +module.exports = Provider; diff --git a/lib/core/config.js b/lib/core/config.js index 43e7160af..608d1f580 100644 --- a/lib/core/config.js +++ b/lib/core/config.js @@ -7,6 +7,7 @@ const deepEqual = require('deep-equal'); const constants = require('../constants'); var Config = function(options) { + const self = this; this.env = options.env; this.blockchainConfig = {}; this.contractsConfig = {}; @@ -22,6 +23,21 @@ var Config = function(options) { this.events = options.events; this.embarkConfig = {}; this.context = options.context || [constants.contexts.any]; + + self.events.setCommandHandler("config:contractsConfig", (cb) => { + cb(self.contractsConfig); + }); + + self.events.setCommandHandler("config:contractsFiles", (cb) => { + cb(self.contractsFiles); + }); + + // TODO: refactor this so reading the file can be done with a normal resolver or something that takes advantage of the plugin api + self.events.setCommandHandler("config:contractsFiles:add", (filename) => { + self.contractsFiles.push(new File({filename: filename, type: File.types.custom, path: filename, resolver: function(callback) { + callback(fs.readFileSync(filename).toString()); + }})); + }); }; Config.prototype.loadConfigFiles = function(options) { @@ -31,20 +47,21 @@ Config.prototype.loadConfigFiles = function(options) { } if (!fs.existsSync(options.embarkConfig)){ - this.logger.error('Cannot find file ' + options.embarkConfig + '. Please ensure you are running this command inside the Dapp folder'); + this.logger.error(__('Cannot find file %s Please ensure you are running this command inside the Dapp folder', options.embarkConfig)); process.exit(1); } this.embarkConfig = fs.readJSONSync(options.embarkConfig); this.embarkConfig.plugins = this.embarkConfig.plugins || {}; - this.plugins = new Plugins({plugins: this.embarkConfig.plugins, logger: this.logger, interceptLogs: interceptLogs, events: this.events, config: this, context: this.context}); + this.plugins = new Plugins({plugins: this.embarkConfig.plugins, logger: this.logger, interceptLogs: interceptLogs, events: this.events, config: this, context: this.context, env: this.env}); this.plugins.loadPlugins(); this.loadEmbarkConfigFile(); this.loadBlockchainConfigFile(); this.loadStorageConfigFile(); this.loadCommunicationConfigFile(); + this.loadNameSystemConfigFile(); this.loadContractsConfigFile(); this.loadPipelineConfigFile(); @@ -54,6 +71,8 @@ Config.prototype.loadConfigFiles = function(options) { this.loadWebServerConfigFile(); this.loadChainTrackerFile(); this.loadPluginContractFiles(); + + this._updateBlockchainCors(); }; Config.prototype.reloadConfig = function() { @@ -61,11 +80,43 @@ Config.prototype.reloadConfig = function() { this.loadBlockchainConfigFile(); this.loadStorageConfigFile(); this.loadCommunicationConfigFile(); + this.loadNameSystemConfigFile(); this.loadContractsConfigFile(); this.loadPipelineConfigFile(); this.loadContractsConfigFile(); this.loadExternalContractsFiles(); this.loadChainTrackerFile(); + + this._updateBlockchainCors(); +}; + +Config.prototype._updateBlockchainCors = function(){ + let blockchainConfig = this.blockchainConfig; + let storageConfig = this.storageConfig; + let webServerConfig = this.webServerConfig; + let corsParts = []; + + if(webServerConfig && webServerConfig.enabled) { + if(webServerConfig.host) corsParts.push(utils.buildUrlFromConfig(webServerConfig)); + } + if(storageConfig && storageConfig.enabled) { + // 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; }; Config.prototype._mergeConfig = function(configFilePath, defaultConfig, env, enabledByDefault) { @@ -75,15 +126,22 @@ Config.prototype._mergeConfig = function(configFilePath, defaultConfig, env, ena return configToReturn; } - if (!fs.existsSync(configFilePath)) { + // due to embark.json; TODO: refactor this + configFilePath = configFilePath.replace('.json','').replace('.js', ''); + if (!fs.existsSync(configFilePath + '.js') && !fs.existsSync(configFilePath + '.json')) { // TODO: remove this if if (this.logger) { - this.logger.warn("no config file found at " + configFilePath + ". using default config"); + this.logger.warn(__("no config file found at %s using default config", configFilePath)); } return defaultConfig['default'] || {}; } - let config = fs.readJSONSync(configFilePath); + let config; + if (fs.existsSync(configFilePath + '.js')) { + config = require(fs.dappPath(configFilePath + '.js')); + } else { + config = fs.readJSONSync(configFilePath + '.json'); + } let configObject = utils.recursiveMerge(defaultConfig, config); if (env) { @@ -109,7 +167,7 @@ Config.prototype.loadBlockchainConfigFile = function() { } }; - let configFilePath = this._getFileOrOject(this.configDir, 'blockchain.json', 'blockchain'); + let configFilePath = this._getFileOrOject(this.configDir, 'blockchain', 'blockchain'); this.blockchainConfig = this._mergeConfig(configFilePath, configObject, this.env, true); }; @@ -142,7 +200,7 @@ Config.prototype.loadContractsConfigFile = function() { configObject = utils.recursiveMerge(configObject, pluginConfig); }); - let configFilePath = this._getFileOrOject(this.configDir, 'contracts.json', 'contracts'); + let configFilePath = this._getFileOrOject(this.configDir, 'contracts', 'contracts'); const newContractsConfig = this._mergeConfig(configFilePath, configObject, this.env); @@ -162,7 +220,7 @@ Config.prototype.loadExternalContractsFiles = function() { if (contract.file.startsWith('http') || contract.file.startsWith('git')) { const fileObj = utils.getExternalContractUrl(contract.file); if (!fileObj) { - return this.logger.error("HTTP contract file not found: " + contract.file); + return this.logger.error(__("HTTP contract file not found") + ": " + contract.file); } const localFile = fileObj.filePath; this.contractsFiles.push(new File({filename: localFile, type: File.types.http, basedir: '', path: fileObj.url})); @@ -171,13 +229,13 @@ Config.prototype.loadExternalContractsFiles = function() { } else if (fs.existsSync(path.join('./node_modules/', contract.file))) { this.contractsFiles.push(new File({filename: path.join('./node_modules/', contract.file), type: File.types.dapp_file, basedir: '', path: path.join('./node_modules/', contract.file)})); } else { - this.logger.error("contract file not found: " + contract.file); + this.logger.error(__("contract file not found") + ": " + contract.file); } } }; 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": { @@ -185,32 +243,50 @@ 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/"}] } }; - let configFilePath = this._getFileOrOject(this.configDir, 'storage.json', 'storage'); + let configFilePath = this._getFileOrOject(this.configDir, 'storage', 'storage'); this.storageConfig = this._mergeConfig(configFilePath, configObject, this.env); }; +Config.prototype.loadNameSystemConfigFile = function() { + // todo: spec out names for registration in the file itself for a dev chain + var configObject = { + "default": { + "available_providers": ["ens"], + "provider": "ens", + "enabled": true + } + }; + + let configFilePath = this._getFileOrOject(this.configDir, 'namesystem', 'namesystem'); + + this.namesystemConfig = this._mergeConfig(configFilePath, configObject, this.env); +}; + Config.prototype.loadCommunicationConfigFile = function() { var configObject = { "default": { "enabled": true, "provider": "whisper", - "available_providers": ["whisper", "orbit"], + "available_providers": ["whisper"], "connection": { "host": "localhost", "port": 8546, "type": "ws" } } }; - let configFilePath = this._getFileOrOject(this.configDir, 'communication.json', 'communication'); + let configFilePath = this._getFileOrOject(this.configDir, 'communication', 'communication'); this.communicationConfig = this._mergeConfig(configFilePath, configObject, this.env); }; @@ -220,7 +296,7 @@ Config.prototype.loadWebServerConfigFile = function() { "enabled": true, "host": "localhost", "port": 8000 }; - let configFilePath = this._getFileOrOject(this.configDir, 'webserver.json', 'webserver'); + let configFilePath = this._getFileOrOject(this.configDir, 'webserver', 'webserver'); this.webServerConfig = this._mergeConfig(configFilePath, configObject, false); }; @@ -253,7 +329,7 @@ Config.prototype.loadPipelineConfigFile = function() { Config.prototype.loadChainTrackerFile = function() { if (!fs.existsSync(this.chainsFile)) { - this.logger.info(this.chainsFile + ' file not found, creating it...'); + this.logger.info(this.chainsFile + ' ' + __('file not found, creating it...')); fs.writeJSONSync(this.chainsFile, {}); } @@ -307,6 +383,7 @@ Config.prototype.loadFiles = function(files) { return readFiles; }; +// NOTE: this doesn't work for internal modules Config.prototype.loadPluginContractFiles = function() { var self = this; diff --git a/lib/core/engine.js b/lib/core/engine.js index e7aa45bad..6e9faf33f 100644 --- a/lib/core/engine.js +++ b/lib/core/engine.js @@ -1,18 +1,14 @@ -let Web3 = require('web3'); -let Events = require('./events.js'); -let Logger = require('./logger.js'); -let Config = require('./config.js'); -let ContractsManager = require('../contracts/contracts.js'); -let DeployManager = require('../contracts/deploy_manager.js'); -let CodeGenerator = require('../contracts/code_generator.js'); -let ServicesMonitor = require('./services_monitor.js'); -let Pipeline = require('../pipeline/pipeline.js'); -let Watch = require('../pipeline/watch.js'); -let LibraryManager = require('../versions/library_manager.js'); +const async = require('async'); + +const utils = require('../utils/utils'); +const IPC = require('./ipc'); class Engine { constructor(options) { this.env = options.env; + this.isDev = options.isDev; + this.client = options.client; + this.locale = options.locale; this.embarkConfig = options.embarkConfig; this.interceptLogs = options.interceptLogs; this.version = options.version; @@ -20,10 +16,14 @@ class Engine { this.logLevel = options.logLevel; this.events = options.events; this.context = options.context; + this.useDashboard = options.useDashboard; } init(_options) { - let self = this; + const Events = require('./events.js'); + const Logger = require('./logger.js'); + const Config = require('./config.js'); + let options = _options || {}; this.events = options.events || this.events || new Events(); this.logger = options.logger || new Logger({logLevel: options.logLevel || this.logLevel || 'debug', events: this.events, logFile: this.logFile}); @@ -31,11 +31,6 @@ class Engine { this.config.loadConfigFiles({embarkConfig: this.embarkConfig, interceptLogs: this.interceptLogs}); this.plugins = this.config.plugins; - this.servicesMonitor = new ServicesMonitor({events: this.events, logger: this.logger}); - this.servicesMonitor.addCheck('embarkVersion', function (cb) { - return cb({name: 'Embark ' + self.version, status: 'on'}); - }, 0); - if (this.interceptLogs || this.interceptLogs === undefined) { this.doInterceptLogs(); } @@ -46,77 +41,46 @@ class Engine { 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)); + self.logger.info(utils.normalizeInput(arguments)); }; context.console.warn = function() { - self.logger.warn(normalizeInput(arguments)); + self.logger.warn(utils.normalizeInput(arguments)); }; context.console.info = function() { - self.logger.info(normalizeInput(arguments)); + self.logger.info(utils.normalizeInput(arguments)); }; context.console.debug = function() { // TODO: ue JSON.stringify - self.logger.debug(normalizeInput(arguments)); + self.logger.debug(utils.normalizeInput(arguments)); }; context.console.trace = function() { - self.logger.trace(normalizeInput(arguments)); + self.logger.trace(utils.normalizeInput(arguments)); }; context.console.dir = function() { - self.logger.dir(normalizeInput(arguments)); + self.logger.dir(utils.normalizeInput(arguments)); }; } - startMonitor() { - let self = this; - if (this.plugins) { - // -------- - // TODO: this only works for services done on startup - // -------- - let servicePlugins = this.plugins.getPluginsFor('serviceChecks'); - servicePlugins.forEach(function (plugin) { - plugin.serviceChecks.forEach(function (pluginCheck) { - self.servicesMonitor.addCheck(pluginCheck.checkName, pluginCheck.checkFn, pluginCheck.time); - }); - }); - } - this.servicesMonitor.startMonitor(); - } - registerModule(moduleName, options) { - this.plugins.loadInternalPlugin(moduleName, options); + this.plugins.loadInternalPlugin(moduleName, options || {}); } startService(serviceName, _options) { let options = _options || {}; let services = { + "serviceMonitor": this.serviceMonitor, "pipeline": this.pipelineService, + "codeRunner": this.codeRunnerService, "codeGenerator": this.codeGeneratorService, "deployment": this.deploymentService, "fileWatcher": this.fileWatchService, "webServer": this.webServerService, - "ipfs": this.ipfsService, + "namingSystem": this.namingSystem, "web3": this.web3Service, "libraryManager": this.libraryManagerService, - "swarm": this.swarmService + "storage": this.storageService }; let service = services[serviceName]; @@ -131,9 +95,10 @@ class Engine { } pipelineService(_options) { - let self = this; + const self = this; this.events.emit("status", "Building Assets"); - let pipeline = new Pipeline({ + const Pipeline = require('../pipeline/pipeline.js'); + const pipeline = new Pipeline({ buildDir: this.config.buildDir, contractsFiles: this.config.contractsFiles, assetFiles: this.config.assetFiles, @@ -143,51 +108,93 @@ class Engine { }); this.events.on('code-generator-ready', function () { self.events.request('code', function (abi, contractsJSON) { - self.currentAbi = abi; - self.contractsJSON = contractsJSON; - pipeline.build(abi, contractsJSON, null, function() { - if (self.watch) { - self.watch.restart(); // Necessary because changing a file while it is writing can stop it from being watched - } + pipeline.build(abi, contractsJSON, null, () => { self.events.emit('outputDone'); }); }); }); } + serviceMonitor() { + const self = this; + const ServicesMonitor = require('./services_monitor.js'); + this.servicesMonitor = new ServicesMonitor({events: this.events, logger: this.logger, plugins: this.plugins}); + this.servicesMonitor.addCheck('embarkVersion', function (cb) { + return cb({name: 'Embark ' + self.version, status: 'on'}); + }, 0); + this.servicesMonitor.startMonitor(); + } + + namingSystem(_options) { + this.registerModule('ens'); + } + + codeRunnerService(_options) { + const CodeRunner = require('../coderunner/codeRunner.js'); + this.codeRunner = new CodeRunner({ + plugins: this.plugins, + events: this.events, + logger: this.logger + }); + } + codeGeneratorService(_options) { let self = this; - let generateCode = function (contractsManager) { - let codeGenerator = new CodeGenerator({ - blockchainConfig: self.config.blockchainConfig, - contractsConfig: self.config.contractsConfig, - contractsManager: contractsManager, - plugins: self.plugins, - storageConfig: self.config.storageConfig, - communicationConfig: self.config.communicationConfig, - events: self.events - }); - codeGenerator.listenToCommands(); - codeGenerator.buildEmbarkJS(function() { + const CodeGenerator = require('../contracts/code_generator.js'); + this.codeGenerator = new CodeGenerator({ + blockchainConfig: self.config.blockchainConfig, + contractsConfig: self.config.contractsConfig, + plugins: self.plugins, + storageConfig: self.config.storageConfig, + namesystemConfig: self.config.namesystemConfig, + communicationConfig: self.config.communicationConfig, + events: self.events, + env: self.env + }); + this.codeGenerator.listenToCommands(); + + const generateCode = function () { + self.codeGenerator.buildEmbarkJS(function() { self.events.emit('code-generator-ready'); }); }; - this.events.on('contractsDeployed', generateCode); - this.events.on('blockchainDisabled', generateCode); - this.events.on('asset-changed', generateCode); + const cargo = async.cargo((_tasks, callback) => { + generateCode(); + self.events.once('outputDone', callback); + }); + const addToCargo = function () { + cargo.push({}); + }; + + this.events.on('contractsDeployed', addToCargo); + this.events.on('blockchainDisabled', addToCargo); + this.events.on('asset-changed', addToCargo); } deploymentService(options) { let self = this; - this.registerModule('solidity', { - contractDirectories: self.config.contractDirectories - }); - this.registerModule('vyper', { - contractDirectories: self.config.contractDirectories + const Compiler = require('../contracts/compiler.js'); + let compiler = new Compiler({plugins: self.plugins, logger: self.logger}); + this.events.setCommandHandler("compiler:contracts", function(contractFiles, cb) { + compiler.compile_contracts(contractFiles, cb); }); + this.ipc = new IPC({logger: this.logger, ipcRole: options.ipcRole}); + if (this.ipc.isServer()) { + this.ipc.serve(); + } + + this.registerModule('solidity', {ipc: this.ipc, useDashboard: this.useDashboard}); + this.registerModule('vyper'); + this.registerModule('profiler'); + this.registerModule('fuzzer'); + this.registerModule('deploytracker'); + this.registerModule('specialconfigs'); + this.registerModule('console_listener', {ipc: this.ipc}); + + const ContractsManager = require('../contracts/contracts.js'); this.contractsManager = new ContractsManager({ contractFiles: this.config.contractsFiles, contractsConfig: this.config.contractsConfig, @@ -197,110 +204,90 @@ class Engine { events: this.events }); + const DeployManager = require('../contracts/deploy_manager.js'); this.deployManager = new DeployManager({ - web3: options.web3 || self.web3, - trackContracts: options.trackContracts, + blockchain: this.blockchain, config: this.config, logger: this.logger, plugins: this.plugins, events: this.events, - contractsManager: this.contractsManager, onlyCompile: options.onlyCompile }); + const ContractDeployer = require('../contracts/contract_deployer.js'); + this.contractDeployer = new ContractDeployer({ + blockchain: this.blockchain, + logger: this.logger, + events: this.events, + plugins: this.plugins + }); + 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') { - self.config.reloadConfig(); - self.deployManager.deployContracts(function () { - }); - } + clearTimeout(self.fileTimeout); + self.fileTimeout = setTimeout(() => { + // TODO: still need to redeploy contracts because the original contracts + // config is being corrupted + if (fileType === 'asset') { + // Throttle file changes so we re-write only once for all files + self.events.emit('asset-changed', self.contractsManager); + } + // TODO: for now need to deploy on asset changes as well + // because the contractsManager config is corrupted after a deploy + if (fileType === 'contract' || fileType === 'config') { + self.config.reloadConfig(); + + self.events.request('deploy:contracts', () => {}); + } + }, 50); }); } fileWatchService(_options) { this.events.emit("status", "Watching for changes"); + const Watch = require('../pipeline/watch.js'); this.watch = new Watch({logger: this.logger, events: this.events}); this.watch.start(); } webServerService() { - this.registerModule('webserver', { - addCheck: this.servicesMonitor.addCheck.bind(this.servicesMonitor) - }); + this.registerModule('webserver'); } - ipfsService(_options) { - this.registerModule('ipfs', { - addCheck: this.servicesMonitor.addCheck.bind(this.servicesMonitor), + storageService(_options) { + this.registerModule('storage', { 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), - storageConfig: this.config.storageConfig, - bzz: _options.bzz + port: _options.port, + servicesMonitor: this.servicesMonitor, + events: this.events, + logger: this.logger, + context: this.context }); } web3Service(options) { - let self = this; - this.web3 = options.web3; - if (this.web3 === undefined) { - this.web3 = new Web3(); - if (this.config.contractsConfig.deployment.type === "rpc") { - let web3Endpoint = 'http://' + this.config.contractsConfig.deployment.host + ':' + this.config.contractsConfig.deployment.port; - this.web3.setProvider(new this.web3.providers.HttpProvider(web3Endpoint)); - } else { - throw new Error("contracts config error: unknown deployment type " + this.config.contractsConfig.deployment.type); - } - } - - self.servicesMonitor.addCheck('Ethereum', function (cb) { - if (self.web3.currentProvider === undefined) { - return cb({name: "No Blockchain node found", status: 'off'}); - } - - self.web3.eth.getAccounts(function(err, _accounts) { - if (err) { - return cb({name: "No Blockchain node found", status: 'off'}); - } - - // TODO: web3_clientVersion method is currently not implemented in web3.js 1.0 - self.web3._requestManager.send({method: 'web3_clientVersion', params: []}, (err, version) => { - if (err) { - return cb({name: "Ethereum node (version unknown)", status: 'on'}); - } - if (version.indexOf("/") < 0) { - return cb({name: version, status: 'on'}); - } - let nodeName = version.split("/")[0]; - let versionNumber = version.split("/")[1].split("-")[0]; - let name = nodeName + " " + versionNumber + " (Ethereum)"; - - return cb({name: name, status: 'on'}); - }); - }); + const Blockchain = require('../contracts/blockchain.js'); + this.blockchain = new Blockchain({ + contractsConfig: this.config.contractsConfig, + blockchainConfig: this.config.blockchainConfig, + events: this.events, + logger: this.logger, + isDev: this.isDev, + locale: this.locale, + web3: options.web3 }); this.registerModule('whisper', { - addCheck: this.servicesMonitor.addCheck.bind(this.servicesMonitor), - communicationConfig: this.config.communicationConfig, - web3: this.web3 + // TODO: this should not be needed and should be deducted from the config instead + // the eth provider is not necessary the same as the whisper one + web3: this.blockchain.web3 }); } libraryManagerService(_options) { + const LibraryManager = require('../versions/library_manager.js'); this.libraryManager = new LibraryManager({ plugins: this.plugins, config: this.config diff --git a/lib/core/events.js b/lib/core/events.js index c561f0008..42f6958a5 100644 --- a/lib/core/events.js +++ b/lib/core/events.js @@ -1,9 +1,9 @@ var EventEmitter = require('events'); function warnIfLegacy(eventName) { - const legacyEvents = ['abi-vanila', 'abi', 'abi-contracts-vanila', 'abi-vanila-deployment']; + const legacyEvents = []; if (legacyEvents.indexOf(eventName) >= 0) { - console.info("this event is deprecated and will be removed in future versions: " + eventName); + console.info(__("this event is deprecated and will be removed in future versions %s", eventName)); } } @@ -14,6 +14,7 @@ function log(eventType, eventName) { //console.log(eventType, eventName); } +EventEmitter.prototype._maxListeners = 300; const _on = EventEmitter.prototype.on; const _setHandler = EventEmitter.prototype.setHandler; @@ -39,10 +40,13 @@ EventEmitter.prototype.request = function() { }; EventEmitter.prototype.setCommandHandler = function(requestName, cb) { - log("setting command handler for: ", requestName); - return this.on('request:' + requestName, function(_cb) { + log("setting command handler for: " + requestName); + let listener = function(_cb) { cb.call(this, ...arguments); - }); + }; + // unlike events, commands can only have 1 handler + this.removeAllListeners('request:' + requestName); + return this.on('request:' + requestName, listener); }; EventEmitter.prototype.setCommandHandlerOnce = function(requestName, cb) { diff --git a/lib/core/file.js b/lib/core/file.js index 62cd859ee..bc97ddaac 100644 --- a/lib/core/file.js +++ b/lib/core/file.js @@ -73,15 +73,25 @@ class File { }); }, function downloadTheFile(next) { + let alreadyCalledBack = false; + function doCallback(err) { + if (alreadyCalledBack) { + return; + } + alreadyCalledBack = true; + next(err); + } request(url) .on('response', function (response) { if (response.statusCode !== 200) { - next('Getting file returned code ' + response.statusCode); + doCallback('Getting file returned code ' + response.statusCode); } }) - .on('error', next) + .on('error', doCallback) .pipe(fs.createWriteStream(filename)) - .on('finish', next); + .on('finish', () => { + doCallback(); + }); }, function readFile(next) { fs.readFile(filename, next); @@ -93,7 +103,7 @@ class File { } ], (err, content) => { if (err) { - console.error('Error while downloading the file', err); + console.error(__('Error while downloading the file'), err); return callback(''); } callback(content.toString()); diff --git a/lib/core/fs.js b/lib/core/fs.js index d196d99c8..6dbc12285 100644 --- a/lib/core/fs.js +++ b/lib/core/fs.js @@ -11,14 +11,26 @@ function mkdirp() { return fs.mkdirp.apply(fs.mkdirp, arguments); } +function copy() { + return fs.copy.apply(fs.copy, arguments); +} + function copySync() { return fs.copySync.apply(fs.copySync, arguments); } +function move(){ + return fs.move.apply(fs.move, arguments); +} + function appendFileSync() { return fs.appendFileSync.apply(fs.writeFileSync, arguments); } +function writeFile() { + return fs.writeFile.apply(fs.writeFileSync, arguments); +} + function writeFileSync() { return fs.writeFileSync.apply(fs.writeFileSync, arguments); } @@ -45,10 +57,18 @@ function writeJSONSync() { return fs.writeJSONSync.apply(fs.writeJSONSync, arguments); } +function writeJson() { + return fs.writeJson.apply(fs.writeJson, arguments); +} + function existsSync() { return fs.existsSync.apply(fs.existsSync, arguments); } +function access() { + return fs.access.apply(fs.access, arguments); +} + function removeSync() { return fs.removeSync.apply(fs.removeSync, arguments); } @@ -67,18 +87,23 @@ function createWriteStream() { } module.exports = { - mkdirpSync: mkdirpSync, + mkdirpSync, mkdirp, - copySync: copySync, + copy, + copySync, + move, readFile, - readFileSync: readFileSync, - appendFileSync: appendFileSync, - writeFileSync: writeFileSync, - readJSONSync: readJSONSync, - writeJSONSync: writeJSONSync, - existsSync: existsSync, - removeSync: removeSync, - embarkPath: embarkPath, - dappPath: dappPath, + readFileSync, + appendFileSync, + writeFile, + writeFileSync, + readJSONSync, + writeJson, + writeJSONSync, + access, + existsSync, + removeSync, + embarkPath, + dappPath, createWriteStream }; diff --git a/lib/core/ipc.js b/lib/core/ipc.js new file mode 100644 index 000000000..e84e88abc --- /dev/null +++ b/lib/core/ipc.js @@ -0,0 +1,90 @@ +let fs = require('./fs.js'); +let ipc = require('node-ipc'); + +class IPC { + + constructor(options) { + this.logger = options.logger; + this.socketPath = options.socketPath || fs.dappPath(".embark/embark.ipc"); + this.ipcRole = options.ipcRole || "server"; + ipc.config.silent = true; + this.connected = false; + } + + connect(done) { + const self = this; + function connecting(_socket) { + let connectedBefore = false, alreadyDisconnected = false; + ipc.of['embark'].on('connect',function() { + connectedBefore = true; + if (!alreadyDisconnected) { + self.connected = true; + done(); + } + }); + ipc.of['embark'].on('disconnect',function() { + self.connected = false; + ipc.disconnect('embark'); + + // we only want to trigger the error callback the first time + if (!connectedBefore && !alreadyDisconnected) { + alreadyDisconnected = true; + done(new Error("no connection found")); + } + }); + } + + ipc.connectTo('embark', this.socketPath, connecting); + } + + serve() { + ipc.serve(this.socketPath, () => {}); + ipc.server.start(); + + this.logger.info(`pid ${process.pid} listening on ${this.socketPath}`); + } + + on(action, done) { + const self = this; + ipc.server.on('message', function(data, socket) { + if (data.action !== action) { + return; + } + let reply = function(replyData) { + self.reply(socket, 'compile', replyData); + }; + done(data.message, reply, socket); + }); + } + + reply(client, action, data) { + ipc.server.emit(client, 'message', {action: action, message: data}); + } + + once(action, cb) { + ipc.of['embark'].once('message', function(msg) { + if (msg.action !== action) { + return; + } + cb(msg.message); + }); + } + + request(action, data, cb) { + if (cb) { + this.once(action, cb); + } + ipc.of['embark'].emit('message', {action: action, message: data}); + } + + isClient() { + return this.ipcRole === 'client'; + } + + isServer() { + return this.ipcRole === 'server'; + } + +} + +module.exports = IPC; diff --git a/lib/core/plugin.js b/lib/core/plugin.js index 00abe240c..991c8ceca 100644 --- a/lib/core/plugin.js +++ b/lib/core/plugin.js @@ -1,6 +1,7 @@ const fs = require('./fs.js'); const utils = require('../utils/utils.js'); const constants = require('../constants'); +const _ = require('underscore'); // TODO: pass other params like blockchainConfig, contract files, etc.. var Plugin = function(options) { @@ -25,9 +26,13 @@ var Plugin = function(options) { this.imports = []; this.embarkjs_code = []; this.embarkjs_init_code = {}; + this.afterContractsDeployActions = []; + this.onDeployActions = []; + this.eventActions = {}; this.logger = options.logger; this.events = options.events; this.config = options.config; + this.env = options.env; this.loaded = false; this.currentContext = options.context; this.acceptedContext = options.pluginConfig.context || [constants.contexts.any]; @@ -55,8 +60,7 @@ Plugin.prototype.hasContext = function(context) { Plugin.prototype.loadPlugin = function() { if (!this.isContextValid()) { - console.log(this.acceptedContext); - this.logger.warn(`Plugin ${this.name} can only be loaded in the context of "${this.acceptedContext.join(', ')}"`); + this.logger.warn(__('Plugin {{name}} can only be loaded in the context of "{{contextes}}"', {name: this.name, contextes: this.acceptedContext.join(', ')})); return false; } this.loaded = true; @@ -115,50 +119,53 @@ Plugin.prototype.interceptLogs = function(context) { // TODO: add deploy provider Plugin.prototype.registerClientWeb3Provider = function(cb) { this.clientWeb3Providers.push(cb); - this.pluginTypes.push('clientWeb3Provider'); -}; - -Plugin.prototype.registerBeforeDeploy = function(cb) { - this.beforeDeploy.push(cb); - this.pluginTypes.push('beforeDeploy'); + this.addPluginType('clientWeb3Provider'); }; Plugin.prototype.registerContractsGeneration = function(cb) { this.contractsGenerators.push(cb); - this.pluginTypes.push('contractGeneration'); + this.addPluginType('contractGeneration'); }; Plugin.prototype.registerPipeline = function(matcthingFiles, cb) { // TODO: generate error for more than one pipeline per plugin this.pipeline.push({matcthingFiles: matcthingFiles, cb: cb}); - this.pluginTypes.push('pipeline'); + this.addPluginType('pipeline'); }; Plugin.prototype.addFileToPipeline = function(file, intendedPath, options) { this.pipelineFiles.push({file: file, intendedPath: intendedPath, options: options}); - this.pluginTypes.push('pipelineFiles'); + this.addPluginType('pipelineFiles'); }; Plugin.prototype.addContractFile = function(file) { + if (this.isInternal) { + throw new Error("this API cannot work for internal modules. please use an event command instead: config:contractsFiles:add"); + } this.contractsFiles.push(file); - this.pluginTypes.push('contractFiles'); + this.addPluginType('contractFiles'); }; Plugin.prototype.registerConsoleCommand = function(cb) { this.console.push(cb); - this.pluginTypes.push('console'); + this.addPluginType('console'); }; // TODO: this only works for services done on startup Plugin.prototype.registerServiceCheck = function(checkName, checkFn, time) { this.serviceChecks.push({checkName: checkName, checkFn: checkFn, time: time}); - this.pluginTypes.push('serviceChecks'); + this.addPluginType('serviceChecks'); }; Plugin.prototype.has = function(pluginType) { return this.pluginTypes.indexOf(pluginType) >= 0; }; +Plugin.prototype.addPluginType = function(pluginType) { + this.pluginTypes.push(pluginType); + this.pluginTypes = _.uniq(this.pluginTypes); +}; + Plugin.prototype.generateProvider = function(args) { return this.clientWeb3Providers.map(function(cb) { return cb.call(this, args); @@ -173,33 +180,41 @@ Plugin.prototype.generateContracts = function(args) { Plugin.prototype.registerContractConfiguration = function(config) { this.contractsConfigs.push(config); - this.pluginTypes.push('contractsConfig'); + this.addPluginType('contractsConfig'); }; Plugin.prototype.registerCompiler = function(extension, cb) { this.compilers.push({extension: extension, cb: cb}); - this.pluginTypes.push('compilers'); + this.addPluginType('compilers'); }; Plugin.prototype.registerUploadCommand = function(cmd, cb) { this.uploadCmds.push({cmd: cmd, cb: cb}); - this.pluginTypes.push('uploadCmds'); + this.addPluginType('uploadCmds'); }; Plugin.prototype.addCodeToEmbarkJS = function(code) { this.embarkjs_code.push(code); - this.pluginTypes.push('embarkjsCode'); + this.addPluginType('embarkjsCode'); }; Plugin.prototype.addProviderInit = function(providerType, code, initCondition) { this.embarkjs_init_code[providerType] = this.embarkjs_init_code[providerType] || []; this.embarkjs_init_code[providerType].push([code, initCondition]); - this.pluginTypes.push('initCode'); + this.addPluginType('initCode'); }; Plugin.prototype.registerImportFile = function(importName, importLocation) { this.imports.push([importName, importLocation]); - this.pluginTypes.push('imports'); + this.addPluginType('imports'); +}; + +Plugin.prototype.registerActionForEvent = function(eventName, cb) { + if (!this.eventActions[eventName]) { + this.eventActions[eventName] = []; + } + this.eventActions[eventName].push(cb); + this.addPluginType('eventActions'); }; Plugin.prototype.runFilePipeline = function() { diff --git a/lib/core/plugins.js b/lib/core/plugins.js index f12f421f1..bbf717c26 100644 --- a/lib/core/plugins.js +++ b/lib/core/plugins.js @@ -1,5 +1,7 @@ +const async = require('async'); var Plugin = require('./plugin.js'); var utils = require('../utils/utils.js'); +var fs = require('../core/fs.js'); var Plugins = function(options) { this.pluginList = options.plugins || []; @@ -10,6 +12,7 @@ var Plugins = function(options) { this.events = options.events; this.config = options.config; this.context = options.context; + this.env = options.env; }; Plugins.prototype.loadPlugins = function() { @@ -51,20 +54,21 @@ Plugins.prototype.createPlugin = function(pluginName, pluginConfig) { }; Plugins.prototype.loadInternalPlugin = function(pluginName, pluginConfig) { - var pluginPath = utils.joinPath('../modules/', pluginName, 'index.js'); + var pluginPath = fs.embarkPath('lib/modules/' + pluginName); var plugin = require(pluginPath); var pluginWrapper = new Plugin({ name: pluginName, pluginModule: plugin, - pluginConfig: pluginConfig, + pluginConfig: pluginConfig || {}, logger: this.logger, pluginPath: pluginPath, interceptLogs: this.interceptLogs, events: this.events, config: this.config, isInternal: true, - context: this.context + context: this.context, + env: this.env }); pluginWrapper.loadInternalPlugin(); this.plugins.push(pluginWrapper); @@ -96,18 +100,60 @@ Plugins.prototype.getPluginsFor = function(pluginType) { }); }; -Plugins.prototype.getPluginsProperty = function(pluginType, property) { +Plugins.prototype.getPluginsProperty = function(pluginType, property, sub_property) { let matchingPlugins = this.plugins.filter(function(plugin) { return plugin.has(pluginType); }); + // Sort internal plugins first + matchingPlugins.sort((a, b) => { + if (a.isInternal) { + return -1; + } + if (b.isInternal) { + return 1; + } + return 0; + }); + let matchingProperties = matchingPlugins.map((plugin) => { + if (sub_property) { + return plugin[property][sub_property]; + } return plugin[property]; }); + // Remove empty properties + matchingProperties = matchingProperties.filter((property) => property); + //return flattened list if (matchingProperties.length === 0) return []; - return matchingProperties.reduce((a,b) => { return a.concat(b); }); + return matchingProperties.reduce((a,b) => { return a.concat(b); }) || []; +}; + +Plugins.prototype.runActionsForEvent = function(eventName, args, cb) { + if (typeof (args) === 'function') { + cb = args; + } + let actionPlugins = this.getPluginsProperty('eventActions', 'eventActions', eventName); + + if (actionPlugins.length === 0) { + return cb(); + } + + async.eachLimit(actionPlugins, 1, function(plugin, nextEach) { + if (typeof (args) === 'function') { + plugin.call(plugin, nextEach); + } else { + //plugin.call(plugin, ...args, nextEach); + plugin.call(plugin, args, nextEach); + } + }, cb); +}; + +Plugins.prototype.emitAndRunActionsForEvent = function(eventName, args, cb) { + this.events.emit(eventName); + return this.runActionsForEvent(eventName, args, cb); }; module.exports = Plugins; diff --git a/lib/core/proxy.js b/lib/core/proxy.js new file mode 100644 index 000000000..4a2a6bd4f --- /dev/null +++ b/lib/core/proxy.js @@ -0,0 +1,125 @@ +const httpProxy = require('http-proxy'); +const http = require('http'); +const constants = require('../constants.json'); + +let commList = {}; +let transactions = {}; +let receipts = {}; + +const parseRequest = function(reqBody){ + let jsonO; + try { + jsonO = JSON.parse(reqBody); + } catch(e){ + return; // Request is not a json. Do nothing + } + if(jsonO.method === "eth_sendTransaction"){ + commList[jsonO.id] = { + type: 'contract-log', + address: jsonO.params[0].to, + data: jsonO.params[0].data + }; + } else if(jsonO.method === "eth_getTransactionReceipt"){ + if(transactions[jsonO.params[0]]){ + transactions[jsonO.params[0]].receiptId = jsonO.id; + receipts[jsonO.id] = transactions[jsonO.params[0]].commListId; + } + } +}; + +const parseResponse = function(ipc, resBody){ + let jsonO; + try { + jsonO = JSON.parse(resBody); + } catch(e) { + return; // Response is not a json. Do nothing + } + + if(commList[jsonO.id]){ + commList[jsonO.id].transactionHash = jsonO.result; + transactions[jsonO.result] = {commListId: jsonO.id}; + } else if(receipts[jsonO.id] && jsonO.result && jsonO.result.blockNumber){ + commList[receipts[jsonO.id]].blockNumber = jsonO.result.blockNumber; + commList[receipts[jsonO.id]].gasUsed = jsonO.result.gasUsed; + commList[receipts[jsonO.id]].status = jsonO.result.status; + + if(ipc.connected && !ipc.connecting){ + ipc.request('log', commList[receipts[jsonO.id]]); + } else { + ipc.connecting = true; + ipc.connect(() => { + ipc.connecting = false; + }); + } + + delete transactions[commList[receipts[jsonO.id]].transactionHash]; + delete receipts[jsonO.id]; + delete commList[jsonO.id]; + } +}; + +exports.serve = function(ipc, host, port, ws){ + let proxy = httpProxy.createProxyServer({ + target: { + host, + port: port + constants.blockchain.servicePortOnProxy + }, + ws: ws + }); + + proxy.on('error', function () { + console.log(__("Error forwarding requests to blockchain/simulator")); + process.exit(); + }); + + proxy.on('proxyRes', (proxyRes) => { + let resBody = []; + proxyRes.on('data', (b) => resBody.push(b)); + proxyRes.on('end', function () { + resBody = Buffer.concat(resBody).toString(); + if(resBody){ + parseResponse(ipc, resBody); + } + }); + }); + + let server = http.createServer((req, res) => { + let reqBody = []; + req.on('data', (b) => { reqBody.push(b); }) + .on('end', () => { + reqBody = Buffer.concat(reqBody).toString(); + if(reqBody){ + parseRequest(reqBody); + } + }); + + if(!ws){ + proxy.web(req, res); + } + }); + + if(ws){ + const WsParser = require('simples/lib/parsers/ws'); // npm install simples + + server.on('upgrade', function (req, socket, head) { + proxy.ws(req, socket, head); + }); + + proxy.on('open', (proxySocket) => { + proxySocket.on('data', (data) => { + parseResponse(ipc, data.toString().substr(data.indexOf("{"))); + }); + }); + + proxy.on('proxyReqWs', (proxyReq, req, socket) => { + var parser = new WsParser(0, false); + socket.pipe(parser); + parser.on('frame', function (frame) { + parseRequest(frame.data); + }); + + }); + } + + server.listen(port); +}; diff --git a/lib/core/services_monitor.js b/lib/core/services_monitor.js index 9b830568e..046a7feb1 100644 --- a/lib/core/services_monitor.js +++ b/lib/core/services_monitor.js @@ -2,12 +2,18 @@ let async = require('../utils/async_extend.js'); class ServicesMonitor { constructor(options) { + const self = this; this.events = options.events; this.logger = options.logger; + this.plugins = options.plugins; this.checkList = {}; this.checkTimers = {}; this.checkState = {}; this.working = false; + + self.events.setCommandHandler("services:register", (checkName, checkFn, time, initialStatus) => { + self.addCheck(checkName, checkFn, time, initialStatus); + }); } } @@ -44,9 +50,9 @@ ServicesMonitor.prototype.initCheck = function (checkName) { }); }; -ServicesMonitor.prototype.addCheck = function (checkName, checkFn, time) { +ServicesMonitor.prototype.addCheck = function (checkName, checkFn, time, initialState) { this.logger.trace('add check: ' + checkName); - this.checkList[checkName] = {fn: checkFn, interval: time || 5000}; + this.checkList[checkName] = {fn: checkFn, interval: time || 5000, status: initialState}; if (this.working) { this.initCheck(checkName); @@ -65,12 +71,17 @@ ServicesMonitor.prototype.startMonitor = function () { this.working = true; this.logger.trace('startMonitor'); + let servicePlugins = this.plugins.getPluginsProperty('serviceChecks', 'serviceChecks'); + servicePlugins.forEach(function (pluginCheck) { + self.addCheck(pluginCheck.checkName, pluginCheck.checkFn, pluginCheck.time); + }); + async.eachObject(this.checkList, function (checkName, check, callback) { self.initCheck(checkName); callback(); }, function (err) { if (err) { - self.logger.error("error running service check"); + self.logger.error(__("error running service check")); self.logger.error(err.message); } }); diff --git a/lib/dashboard/console.js b/lib/dashboard/console.js index 907e9844b..c77d2b2fa 100644 --- a/lib/dashboard/console.js +++ b/lib/dashboard/console.js @@ -1,5 +1,4 @@ let utils = require('../utils/utils.js'); -let RunCode = require('../core/runCode.js'); class Console { constructor(options) { @@ -10,25 +9,26 @@ class Console { } runCode(code) { - RunCode.doEval(code); + this.events.request('runcode:eval', code); } processEmbarkCmd (cmd) { - if (cmd === 'help') { + if (cmd === 'help' || cmd === __('help')) { let helpText = [ - 'Welcome to Embark ' + this.version, + __('Welcome to Embark') + ' ' + this.version, '', - 'possible commands are:', - 'versions - display versions in use for libraries and tools like web3 and solc', + __('possible commands are:'), + 'versions - ' + __('display versions in use for libraries and tools like web3 and solc'), // TODO: only if the blockchain is actually active! // will need to pass te current embark state here - 'web3 - instantiated web3.js object configured to the current environment', - 'quit - to immediatly exit (alias: exit)', + 'ipfs - ' + __('instantiated js-ipfs object configured to the current environment (available if ipfs is enabled)'), + 'web3 - ' + __('instantiated web3.js object configured to the current environment'), + 'quit - ' + __('to immediatly exit (alias: exit)'), '', - 'The web3 object and the interfaces for the deployed contracts and their methods are also available' + __('The web3 object and the interfaces for the deployed contracts and their methods are also available') ]; return helpText.join('\n'); - } else if (['quit', 'exit', 'sair', 'sortir'].indexOf(cmd) >= 0) { + } else if (['quit', 'exit', 'sair', 'sortir', __('quit')].indexOf(cmd) >= 0) { utils.exit(); } return false; @@ -38,7 +38,7 @@ class Console { var pluginCmds = this.plugins.getPluginsProperty('console', 'console'); for (let pluginCmd of pluginCmds) { let pluginOutput = pluginCmd.call(this, cmd, {}); - if (pluginOutput !== false && pluginOutput !== 'false') return callback(pluginOutput); + if (pluginOutput !== false && pluginOutput !== 'false' && pluginOutput !== undefined) return callback(pluginOutput); } let output = this.processEmbarkCmd(cmd); @@ -47,12 +47,13 @@ class Console { } try { - let result = RunCode.doEval(cmd); - return callback(result); + this.events.request('runcode:eval', cmd, (err, result) => { + callback(result); + }); } catch (e) { if (e.message.indexOf('not defined') > 0) { - return callback(("error: " + e.message).red + ("\nType " + "help".bold + " to see the list of available commands").cyan); + return callback(("error: " + e.message).red + ("\n" + __("Type") + " " + "help".bold + " " + __("to see the list of available commands")).cyan); } else { return callback(e.message); } diff --git a/lib/dashboard/dashboard.js b/lib/dashboard/dashboard.js index 2ce994fb0..bc8c0c2a3 100644 --- a/lib/dashboard/dashboard.js +++ b/lib/dashboard/dashboard.js @@ -1,4 +1,5 @@ let async = require('async'); +let windowSize = require('window-size'); let Monitor = require('./monitor.js'); let Console = require('./console.js'); @@ -11,6 +12,16 @@ class Dashboard { this.version = options.version; this.env = options.env; this.contractsConfig = options.contractsConfig; + + this.events.on('firstDeploymentDone', this.checkWindowSize.bind(this)); + this.events.on('outputDone', this.checkWindowSize.bind(this)); + } + + checkWindowSize() { + let size = windowSize.get(); + if (size.height < 40 || size.width < 118) { + this.logger.warn(__("tip: you can resize the terminal or disable the dashboard with") + " embark run --nodashboard".bold.underline); + } } start(done) { @@ -38,7 +49,7 @@ class Dashboard { self.events.setCommandHandler("console:command", monitor.executeCmd.bind(monitor)); self.logger.info('========================'.bold.green); - self.logger.info(('Welcome to Embark ' + self.version).yellow.bold); + self.logger.info((__('Welcome to Embark') + ' ' + self.version).yellow.bold); self.logger.info('========================'.bold.green); // TODO: do this after monitor is rendered diff --git a/lib/dashboard/monitor.js b/lib/dashboard/monitor.js index 2b98967ae..8d389252a 100644 --- a/lib/dashboard/monitor.js +++ b/lib/dashboard/monitor.js @@ -1,4 +1,4 @@ -let blessed = require("blessed"); +let blessed = require("neo-blessed"); let CommandHistory = require('./command_history.js'); class Dashboard { @@ -67,7 +67,7 @@ class Dashboard { setContracts(contracts) { let data = []; - data.push(["Contract Name", "Address", "Status"]); + data.push([__("Contract Name"), __("Address"), __("Status")]); contracts.forEach(function (row) { data.push(row); @@ -84,7 +84,7 @@ class Dashboard { layoutLog() { this.log = blessed.box({ - label: "Logs", + label: __("Logs"), padding: 1, width: "100%", height: "55%", @@ -123,7 +123,7 @@ class Dashboard { layoutModules() { this.modules = blessed.box({ - label: "Contracts", + label: __("Contracts"), tags: true, padding: 1, width: "75%", @@ -166,7 +166,7 @@ class Dashboard { layoutAssets() { this.assets = blessed.box({ - label: "Asset Pipeline", + label: __("Asset Pipeline"), tags: true, padding: 1, width: "50%", @@ -217,7 +217,7 @@ class Dashboard { this.status = blessed.box({ parent: this.wrapper, - label: "Environment", + label: __("Environment"), tags: true, padding: { left: 1 @@ -238,7 +238,7 @@ class Dashboard { this.operations = blessed.box({ parent: this.wrapper, - label: "Status", + label: __("Status"), tags: true, padding: { left: 1 @@ -259,7 +259,7 @@ class Dashboard { this.progress = blessed.box({ parent: this.wrapper, - label: "Available Services", + label: __("Available Services"), tags: true, padding: this.minimal ? { left: 1 @@ -270,6 +270,12 @@ class Dashboard { border: { type: "line" }, + scrollable: true, + alwaysScroll: true, + scrollbar: { + ch: " ", + inverse: true + }, style: { fg: -1, border: { @@ -283,7 +289,7 @@ class Dashboard { layoutCmd() { this.consoleBox = blessed.box({ - label: 'Console', + label: __('Console'), tags: true, padding: 0, width: '100%', @@ -324,6 +330,7 @@ class Dashboard { let self = this; this.input.key(["C-c"], function () { + self.events.emit('exit'); process.exit(0); }); diff --git a/lib/i18n/i18n.js b/lib/i18n/i18n.js new file mode 100644 index 000000000..ebe6562cb --- /dev/null +++ b/lib/i18n/i18n.js @@ -0,0 +1,42 @@ +const i18n = require('i18n'); +const osLocale = require('os-locale'); +const path = require('path'); + +const supported_languages = ['en', 'pt', 'fr']; + +i18n.configure({ + locales: supported_languages, + register: global, + updateFiles: false, + directory: path.join(__dirname, 'locales') +}); + +function isSupported(locale) { + return (supported_languages.indexOf(locale.substr(0, 2)) >= 0); +} + +function setLocale(locale) { + i18n.setLocale(locale.substr(0, 2)); +} + +function setDefaultLocale() { + osLocale().then(setLocale).catch(); +} + +function setOrDetectLocale(locale) { + if (locale && !isSupported(locale)) { + console.log("===== locale " + locale + " not supported ====="); + } + if (locale) { + return i18n.setLocale(locale.substr(0, 2)); + } + setDefaultLocale(); +} + +setDefaultLocale(); + +module.exports = { + i18n: i18n, + setOrDetectLocale: setOrDetectLocale +}; + diff --git a/lib/i18n/locales/en.json b/lib/i18n/locales/en.json new file mode 100644 index 000000000..bf20868dd --- /dev/null +++ b/lib/i18n/locales/en.json @@ -0,0 +1,170 @@ +{ + "new_application": "new_application", + "Contract Name": "Contract Name", + "New Application": "New Application", + "create a barebones project meant only for contract development": "create a barebones project meant only for contract development", + "create a working dapp with a SimpleStorage contract": "create a working dapp with a SimpleStorage contract", + "filename to output logs (default: none)": "filename to output logs (default: none)", + "level of logging to display": "level of logging to display", + "deploy and build dapp at ": "deploy and build dapp at ", + "port to run the dev webserver (default: %s)": "port to run the dev webserver (default: %s)", + "host to run the dev webserver (default: %s)": "host to run the dev webserver (default: %s)", + "disable the development webserver": "disable the development webserver", + "simple mode, disables the dashboard": "simple mode, disables the dashboard", + "no colors in case it's needed for compatbility purposes": "no colors in case it's needed for compatbility purposes", + "filename to output logs (default: %s)": "filename to output logs (default: %s)", + "run dapp (default: %s)": "run dapp (default: %s)", + "Use a specific ethereum client or simulator (supported: %s)": "Use a specific ethereum client or simulator (supported: %s)", + "run blockchain server (default: %s)": "run blockchain server (default: %s)", + "run a fast ethereum rpc simulator": "run a fast ethereum rpc simulator", + "use testrpc as the rpc simulator [%s]": "use testrpc as the rpc simulator [%s]", + "port to run the rpc simulator (default: %s)": "port to run the rpc simulator (default: %s)", + "host to run the rpc simulator (default: %s)": "host to run the rpc simulator (default: %s)", + "number of accounts (default: %s)": "number of accounts (default: %s)", + "Amount of ether to assign each test account (default: %s)": "Amount of ether to assign each test account (default: %s)", + "custom gas limit (default: %s)": "custom gas limit (default: %s)", + "run tests": "run tests", + "resets embarks state on this dapp including clearing cache": "resets embarks state on this dapp including clearing cache", + "generates documentation based on the smart contracts configured": "generates documentation based on the smart contracts configured", + "Upload your dapp to a decentralized storage": "Upload your dapp to a decentralized storage", + "output the version number": "output the version number", + "Logs": "Logs", + "Environment": "Environment", + "Status": "Status", + "Available Services": "Available Services", + "Contracts": "Contracts", + "Console": "Console", + "Welcome to Embark": "Welcome to Embark", + "dashboard start": "dashboard start", + "loaded plugins": "loaded plugins", + "loading solc compiler": "loading solc compiler", + "compiling solidity contracts": "compiling solidity contracts", + "%s doesn't have a compatible contract compiler. Maybe a plugin exists for it.": "%s doesn't have a compatible contract compiler. Maybe a plugin exists for it.", + "assuming %s to be an interface": "assuming %s to be an interface", + "{{className}}: couldn't find instanceOf contract {{parentContractName}}": "{{className}}: couldn't find instanceOf contract {{parentContractName}}", + "did you mean \"%s\"?": "did you mean \"%s\"?", + "%s has no code associated": "%s has no code associated", + "deploying contracts": "deploying contracts", + " already deployed at ": " already deployed at ", + "Pending": "Pending", + "Interface or set to not deploy": "Interface or set to not deploy", + "Deployed": "Deployed", + "Address": "Address", + "running beforeDeploy plugin %s .": "running beforeDeploy plugin %s .", + "deploying": "deploying", + "with": "with", + "gas": "gas", + "error deploying": "error deploying", + "due to error": "due to error", + "error deploying contracts": "error deploying contracts", + "finished deploying contracts": "finished deploying contracts", + "error running afterDeploy: ": "error running afterDeploy: ", + "ready to watch file changes": "ready to watch file changes", + "Starting Server": "Starting Server", + "webserver available at": "webserver available at", + "Webserver": "Webserver", + "versions": "versions", + "possible commands are:": "possible commands are:", + "display versions in use for libraries and tools like web3 and solc": "display versions in use for libraries and tools like web3 and solc", + "instantiated web3.js object configured to the current environment": "instantiated web3.js object configured to the current environment", + "to immediatly exit (alias: exit)": "to immediatly exit (alias: exit)", + "The web3 object and the interfaces for the deployed contracts and their methods are also available": "The web3 object and the interfaces for the deployed contracts and their methods are also available", + "versions in use": "versions in use", + "language to use (default: en)": "language to use (default: en)", + "executing": "executing", + "writing file": "writing file", + "errors found while generating": "errors found while generating", + "Looking for documentation? You can find it at": "Looking for documentation? You can find it at", + "Ready": "Ready", + "Graph will not include undeployed contracts": "Graph will not include undeployed contracts", + "Graph will not include functions": "Graph will not include functions", + "Graph will not include events": "Graph will not include events", + "Embark Blockchain Using: %s": "Embark Blockchain Using: %s", + "running: %s": "running: %s", + "Initializing Embark Template....": "Initializing Embark Template....", + "Init complete": "Init complete", + "App ready at ": "App ready at ", + "already initialized": "already initialized", + "deployed at": "deployed at", + "executing onDeploy commands": "executing onDeploy commands", + "executing: ": "executing: ", + "no config file found at %s using default config": "no config file found at %s using default config", + "Development blockchain has changed to use the --dev option.": "Development blockchain has changed to use the --dev option.", + "You can reset your workspace to fix the problem with": "You can reset your workspace to fix the problem with", + "Otherwise, you can change your data directory in blockchain.json (datadir)": "Otherwise, you can change your data directory in blockchain.json (datadir)", + "tip: you can resize the terminal or disable the dashboard with": "tip: you can resize the terminal or disable the dashboard with", + "help": "help", + "quit": "quit", + "Error Compiling/Building contracts: ": "Error Compiling/Building contracts: ", + "file not found, creating it...": "file not found, creating it...", + "{{className}} has code associated to it but it's configured as an instanceOf {{parentContractName}}": "{{className}} has code associated to it but it's configured as an instanceOf {{parentContractName}}", + "downloading {{packageName}} {{version}}....": "downloading {{packageName}} {{version}}....", + "Swarm node is offline...": "Swarm node is offline...", + "Swarm node detected...": "Swarm node detected...", + "Cannot find file %s Please ensure you are running this command inside the Dapp folder": "Cannot find file %s Please ensure you are running this command inside the Dapp folder", + "compiling Vyper contracts": "compiling Vyper contracts", + "Vyper exited with error code ": "Vyper exited with error code ", + "attempted to deploy %s without specifying parameters": "attempted to deploy %s without specifying parameters", + "Ethereum node (version unknown)": "Ethereum node (version unknown)", + "No Blockchain node found": "No Blockchain node found", + "Couldn't connect to an Ethereum node are you sure it's on?": "Couldn't connect to an Ethereum node are you sure it's on?", + "make sure you have an Ethereum node or simulator running. e.g '%s'": "make sure you have an Ethereum node or simulator running. e.g '%s'", + "Embark is building, please wait...": "Embark is building, please wait...", + "finished building DApp and deploying to": "finished building DApp and deploying to", + "Type": "Type", + "to see the list of available commands": "to see the list of available commands", + "instantiated js-ipfs object configured to the current environment (available if ipfs is enabled)": "instantiated js-ipfs object configured to the current environment (available if ipfs is enabled)", + "reset done!": "reset done!", + "finished building": "finished building", + "finished deploying": "finished deploying", + "adding %s to ipfs": "adding %s to ipfs", + "DApp available at": "DApp available at", + "successfully uploaded to ipfs": "successfully uploaded to ipfs", + "Starting Blockchain node in another process": "Starting Blockchain node in another process", + "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?", + "Error while downloading the file": "Error while downloading the file", + "Error while loading the content of ": "Error while loading the content of ", + "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", + "Starting ipfs process": "Starting ipfs process", + "ipfs process started": "ipfs process started", + "Starting swarm process": "Starting swarm process", + "unknown command": "unknown command", + "Simulator not found; Please install it with \"%s\"": "Simulator not found; Please install it with \"%s\"", + "IMPORTANT: if you using a NodeJS version older than 6.9.1 then you need to install an older version of testrpc \"%s\"": "IMPORTANT: if you using a NodeJS version older than 6.9.1 then you need to install an older version of testrpc \"%s\"", + "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", + "IPFS node detected": "IPFS node detected", + "Ethereum node detected": "Ethereum node detected", + "Starting swarm process": "Starting swarm process", + "Deployment Done": "Deployment Done", + "Name your app (default is %s):": "Name your app (default is %s):" +} diff --git a/lib/i18n/locales/es.json b/lib/i18n/locales/es.json new file mode 100644 index 000000000..59910a4cb --- /dev/null +++ b/lib/i18n/locales/es.json @@ -0,0 +1,188 @@ +{ + "New Application": "Nueva Aplicación", + "Contract Name": "Nombre del Contrato", + "Address": "Dirección", + "Status": "Estado", + "Embark Blockchain Using: %s": "Embark Blockchain esta usando el comando: %s", + "running: %s": "ejecutando: %s", + "already initialized": "ya esta inicializado", + "create a barebones project meant only for contract development": "crear un proyecto vacio destinado solo para el desarrollo de contratos", + "loading solc compiler": "cargando el compilador solc", + "Welcome to Embark": "Bienvenido a Embark", + "possible commands are:": "los comandos posibles son:", + "display versions in use for libraries and tools like web3 and solc": "mostrar versiones en uso para bibliotecas y herramientas como web3 y solc", + "instantiated web3.js object configured to the current environment": "objeto web3.js instanciado configurado para el entorno actual", + "to immediatly exit (alias: exit)": "para salir inmediatamente (alias: exit)", + "The web3 object and the interfaces for the deployed contracts and their methods are also available": "El objeto web3 y las interfaces para los contratos publicados y sus métodos también están disponibles", + "create a working dapp with a SimpleStorage contract": "Crear una dapp funcional con un contrato SimpleStorage", + "filename to output logs (default: none)": "fichero/archivo para salida de los logs (predefinido: none)", + "level of logging to display": "nivel de log para mostrar", + "deploy and build dapp at ": "Publica los contractos y construye la aplicación en ", + "port to run the dev webserver (default: %s)": "puerto para correr el servidor web para desarrollo (default: %s)", + "host to run the dev webserver (default: %s)": "host para correr el servidor web para desarrollo (default: %s)", + "disable the development webserver": "desactiva el servidor web para desarrollo", + "simple mode, disables the dashboard": "modo simple, desactiva el dashboard", + "no colors in case it's needed for compatbility purposes": "Sin colores, en caso de ser necessario para compatibilidad con la terminal", + "filename to output logs (default: %s)": "fichero/archivo para los logs (predefinido: %s)", + "run dapp (default: %s)": "ejecutar la dapp (applicación decentralizada) (predefinido: %s)", + "Use a specific ethereum client or simulator (supported: %s)": "Usa un cliente o un simulador de ethereum específico (soportado: %s)", + "run blockchain server (default: %s)": "ejecuta un nodo de blockchain (predefinido: %s)", + "run a fast ethereum rpc simulator": "ejecuta un simulador RPC de ethereum", + "use testrpc as the rpc simulator [%s]": "usa testrpc como simulator de rpc [%s]", + "port to run the rpc simulator (default: %s)": "puerto para ejecutar un simulador de rpc (predefinido: %s)", + "host to run the rpc simulator (default: %s)": "host para ejecutar un servidor de rpc (predefinido: %s)", + "number of accounts (default: %s)": "número de cuentas (predefinido: %s)", + "Amount of ether to assign each test account (default: %s)": "Cantidad de éter para asignar a cada cuenta de prueba (predefinido: %s)", + "custom gas limit (default: %s)": "límite de gas (predefinido: %s)", + "run tests": "ejecutar las pruebas", + "resets embarks state on this dapp including clearing cache": "restablece el estado de Embark en esta dapp, incluida la eliminación de la memoria caché", + "generates documentation based on the smart contracts configured": "genera documentación basada en los contratos inteligentes configurados", + "Upload your dapp to a decentralized storage": "Suba su dapp a un almacenamiento descentralizado", + "output the version number": "mostrar el número de versión", + "Logs": "Logs", + "Environment": "Ambiente", + "Available Services": "Servicios Disponibles", + "Contracts": "Contratos", + "Console": "Consola", + "dashboard start": "inicia el panel de control", + "loaded plugins": "plugins cargados", + "compiling solidity contracts": "Compilando contratos Solidity", + "%s doesn't have a compatible contract compiler. Maybe a plugin exists for it.": "%s no tiene un compilador de contrato compatible. Tal vez existe un plugin para ello.", + "assuming %s to be an interface": "suponiendo que %s sea una interfaz", + "{{className}}: couldn't find instanceOf contract {{parentContractName}}": "{{className}}: no se pudo encontrar la instancia (instanceOf) del contrato {{parentContractName}}", + "did you mean \"%s\"?": "querías decir \"%s\"?", + "%s has no code associated": "%s no tiene código asociado", + "deploying contracts": "publicando contratos", + "running beforeDeploy plugin %s .": "ejecutanto plugin beforeDeploy %s .", + "deploying": "publicando", + "with": "con", + "gas": "gas", + "Pending": "Pendiente", + "Interface or set to not deploy": "Interfaz o configurado para no publicar", + "error deploying": "error publicando", + "due to error": "debido a error", + "error deploying contracts": "error publicando contratos", + "finished deploying contracts": "publicación de contratos concluida", + "error running afterDeploy: ": "error ejecutando afterDeploy: ", + "ready to watch file changes": "listo para monitorear alteraciones en ficheros/archivos", + "Starting Server": "iniciando el servidor", + "webserver available at": "servidor web disponible en", + "Webserver": "Servidor Web", + " already deployed at ": " ya publicado en ", + "Deployed": "Publicado", + "Name must be only letters, spaces, or dashes": "El nombre debe ser solo letras, espacios o guiones", + "Name your app (default is %s)": "Nombre su aplicación (el valor predeterminado es %s)", + "Invalid name": "Nombre inválido", + "unknown command": "comando desconocido", + "did you mean": "querías decir", + "warning: running default config on a non-development environment": "aviso: ejecutando la configuración predefinida en un ambiente de no-desarrollo", + "could not find {{geth_bin}} command; is {{client_name}} installed or in the PATH?": "no se pudo encontrar el comando {{geth_bin}}; ¿Está {{client_name}} instalado o en la RUTA?", + "no accounts found": "no se encontraron cuentas", + "initializing genesis block": "inicializando bloque genesis", + "rpcCorsDomain set to *": "rpcCorsDomain definido como *", + "make sure you know what you are doing": "asegúrate de saber lo que estás haciendo", + "warning: cors is not set": "aviso: cors no está definido", + "wsOrigins set to *": "wsOrigins definido como *", + "warning: wsOrigins is not set": "aviso: wsOrigins no está definido", + "reset done!": "reset listo!", + "%s is not installed on your machine": "%s no está instalado en su máquina", + "You can install it by running: %s": "Puede instalarlo ejecutando: %s", + "Initializing Embark Template....": "Inicializando la plantilla de Embark....", + "Installing packages...": "Instalando paquetes...", + "Init complete": "Init completo", + "App ready at ": "Aplicación lista en ", + "Next steps:": "Próximos pasos:", + "open another console in the same directory and run": "abrir otra consola en el mismo directorio y ejecutar", + "For more info go to http://embark.status.im": "Para más información ve a http://embark.status.im", + "%s : instanceOf is set to itself": "%s : instanceOf se establece a sí mismo", + "{{className}} has code associated to it but it's configured as an instanceOf {{parentContractName}}": "{{className}} tiene un código asociado pero está configurado como una instancia de {{parentContractName}}", + "Error Compiling/Building contracts: ": "Error Compilando/Construyendo los contractos: ", + "Error: ": "Error: ", + "there are two or more contracts that depend on each other in a cyclic manner": "hay dos o más contratos que dependen el uno del otro de forma cíclica", + "Embark couldn't determine which one to deploy first": "Embark no pudo determinar cual publicar primero", + "{{inputName}} has not been defined for {{className}} constructor": "{{inputName}} no ha sido definido para el constructor de {{className}}", + "error deploying %s": "error publicando %s", + "executing onDeploy commands": "ejecutando comandos onDeploy", + "error executing onDeploy for ": "error ejecutando onDeploy para ", + " does not exist": " no existe", + "error running onDeploy: ": "error ejecutando onDeploy: ", + " exists but has been set to not deploy": " existe, pero se ha configurado para no implementar", + "couldn't find a valid address for %s has it been deployed?": "no pudo encontrar una dirección válida para %s ¿ha sido publicado?", + "executing: ": "ejecutando: ", + "the transaction was rejected; this usually happens due to a throw or a require": "la transacción fue rechazada; esto generalmente sucede debido a un throw o a un require", + "no account found at index": "no se encontró una cuenta en index", + " check the config": " verifique la configuración", + "Both \"from\" and \"fromIndex\" are defined for contract": "Ambos \"from\" y \"fromIndex\" están definidos para el contracto", + "Using \"from\" as deployer account.": "Usando \"from\" como cuenta de implementación.", + "{{linkReference}} is too long": "{{linkReference}} es muy largo", + "{{contractName}} needs {{libraryName}} but an address was not found, did you deploy it or configured an address?": "{{contractName}} necesita {{libraryName}} pero no se encontró una dirección, ¿la implementó o configuró una dirección?", + "attempted to deploy %s without specifying parameters": "intentado publicar %s sin especificar parámetros", + "deployed at": "publicado en", + "no contracts found": "no hay contractos encontrados", + "Blockchain component is disabled in the config": "El componente Blockchain está deshabilitado en la configuración", + "Couldn't connect to an Ethereum node are you sure it's on?": "No se pudo conectar a un nodo Ethereum, ¿está seguro de que está activado?", + "make sure you have an Ethereum node or simulator running. e.g '%s'": "asegurese de tener un nodo o simulador Ethereum en funcionamiento. e.g '%s'", + "executing": "ejecutando", + "the transaction was rejected; this usually happens due to a throw or a require, it can also happen due to an invalid operation": "la transacción fue rechazada; esto generalmente ocurre debido a un throw o un require, también puede ocurrir debido a una operación no válida", + "Cannot find file %s Please ensure you are running this command inside the Dapp folder": "No se puede encontrar el archivo %s Asegúrese de que está ejecutando este comando dentro de la carpeta de la DApp", + "no config file found at %s using default config": "archivo de configuración no encontrado en %s utilizado la configuración predefinida", + "HTTP contract file not found": "archivo de contracto HTTP no encontrado", + "contract file not found": "archivo de contracto no encontrado", + "file not found, creating it...": "archivo no encontrado, creándolo ...", + "No Blockchain node found": "No se encontró ningún nodo de Blockchain", + "Ethereum node (version unknown)": "Nodo Ethereum (versión desconocida)", + "this event is deprecated and will be removed in future versions %s": "este evento está en desuso y se eliminará en futuras versiones %s", + "Error while downloading the file": "Error descargando el archivo", + "Plugin {{name}} can only be loaded in the context of \"{{contextes}}\"": "El complemento {{name}} solo se puede cargar en el contexto de \"{{contextes}} \"", + "error running service check": "error al ejecutar la comprobación del servicio", + "help": "ayuda", + "quit": "salir", + "Type": "Tipo", + "to see the list of available commands": "para ver la lista de comandos disponibles", + "Asset Pipeline": "Asset Pipeline", + "Ethereum node detected": "Nodo Ethereum detectado", + "Deployment Done": "Publicación completada", + "Looking for documentation? You can find it at": "¿Buscando documentación? puede encontrarla en", + "Ready": "Listo", + "tip: you can resize the terminal or disable the dashboard with": "consejo: puede redimensionar la terminal o desactivar el tablero con", + "finished building": "construcción completada", + "Done": "Hecho", + "Cannot upload: {{platform}} node is not running on {{url}}.": "No se puede cargar: el nodo {{platform}} no se está ejecutando en {{url}}.", + "try \"{{ipfs}}\" or \"{{swarm}}\"": "intente \"{{ipfs}}\" o \"{{swarm}}\"", + "finished deploying": "publicación completada", + "finished building DApp and deploying to": "construcción de la DApp completada y publicada en", + "IPFS node detected": "Nodo de IPFS detectado", + "IPFS node is offline": "Nodo de IPFS no está en línea", + "not found or not in the path. Guessing %s for path": "no encontrado o no se encuentra en la ruta. Estimando %s para la ruta", + "adding %s to ipfs": "añadiendo %s a ipfs", + "DApp available at": "DApp disponible en", + "error uploading to ipfs": "error cargando a ipfs", + "successfully uploaded to ipfs": "cargado con éxito a ipfs", + "Error while loading the content of ": "Error al cargar el contenido de ", + "error compiling for unknown reasons": "error compilando por razones desconocidas", + "error compiling. There are sources available but no code could be compiled, likely due to fatal errors in the solidity code": "error compilando. Hay fuentes disponibles pero no se pudo compilar ningún código, probablemente debido a errores fatales en el código solidity", + "Swarm node detected...": "nodo Swarm detectado...", + "Swarm node is offline...": "el nodo de Swarm no se encuentra en línea...", + "deploying to swarm!": "publicando en swarm!", + "adding %s to swarm": "añadiendo %s a swarm", + "error uploading to swarm": "error cargando a swarm", + "successfully uploaded to swarm": "cargado exitosamente a swarm", + "Vyper exited with error code ": "Vyper salió con el código de error ", + "Execution returned no result": "La ejecución no devolvió resultados", + "compiling Vyper contracts": "compilando contractos Vyper", + "Webserver is offline": "el servidor web no se encuentra en línea", + "stopping webserver": "deteniendo el servidor web", + "a webserver is already running at": "un servidor web ya se está ejecutando en", + "no webserver is currently running": "ningún servidor web se está ejecutando actualmente", + "couldn't find file": "el archivo no pudo ser encontrado", + "errors found while generating": "errores encontrados al generar", + "writing file": "escribiendo archivo", + "Simulator not found; Please install it with \"%s\"": "Simulador no encontrado; Por favor instalarlo con \"%s\"", + "Tried to load testrpc but an error occurred. This is a problem with testrpc": "Intenté cargar testrpc pero ocurrió un error. Este es un problema con testrpc", + "IMPORTANT: if you using a NodeJS version older than 6.9.1 then you need to install an older version of testrpc \"%s\". Alternatively install node 6.9.1 and the testrpc 3.0": "IMPORTANTE: si usa una versión de NodeJS anterior a la 6.9.1, entonces necesita instalar una versión anterior de testrpc \"%s\". Alternativamente, instale el Node 6.9.1 y el testrpc 3.0", + "terminating due to error": "terminando debido a un error", + "There a a space in the version of {{versionKey}}. We corrected it for you ({{correction})": "Hay un espacio en la versión de {{versionKey}}. Lo corregimos por ti ({{correction})", + "versions": "versiones", + "versions in use": "versiones en uso", + "downloading {{packageName}} {{version}}....": "descargando {{packageName}} {{version}}...." +} \ No newline at end of file diff --git a/lib/i18n/locales/fr.json b/lib/i18n/locales/fr.json new file mode 100644 index 000000000..994badd0f --- /dev/null +++ b/lib/i18n/locales/fr.json @@ -0,0 +1,188 @@ +{ + "New Application": "Nouvelle Application", + "Contract Name": "Contrat", + "Address": "Addresse", + "Status": "Etat", + "Embark Blockchain Using: %s": "Embark Blockchain utilise: %s", + "running: %s": "en cours d'exécution: %s", + "already initialized": "Déjà initialisé", + "create a barebones project meant only for contract development": "créer un projet destiné uniquement au développement de contrats", + "loading solc compiler": "chargement du compilateur solc", + "Welcome to Embark": "Bienvenue sur Embark", + "possible commands are:": "les commandes possibles sont:", + "display versions in use for libraries and tools like web3 and solc": "liste des versions utilisées pour les bibliothèques et les outils comme web3 et solc", + "instantiated web3.js object configured to the current environment": "objet web3.js instancié configuré pour l'environnement actuel", + "to immediatly exit (alias: exit)": "quitter immédiatement (alias: exit)", + "The web3 object and the interfaces for the deployed contracts and their methods are also available": "L'objet web3 et les interfaces avec les contrats déployés et leurs méthodes sont également disponibles", + "create a working dapp with a SimpleStorage contract": "créer une dapp fonctionnelle avec un SimpleStorage contrat", + "filename to output logs (default: none)": "nom de fichier pour les journaux de sortie (par défaut: aucun)", + "level of logging to display": "niveau de journalisation à afficher", + "deploy and build dapp at ": "Publiez et créez la dapp dans ", + "port to run the dev webserver (default: %s)": "port pour exécuter le serveur de développement Web (par défaut:% s)", + "host to run the dev webserver (default: %s)": "hôte pour exécuter le serveur de développement Web (par défaut:% s)", + "disable the development webserver": "désactiver le serveur de développement Web", + "simple mode, disables the dashboard": "mode simple, désactive le tableau de bord", + "no colors in case it's needed for compatbility purposes": "pas de couleur au cas où cela serait nécessaire à des fins de compatibilité", + "filename to output logs (default: %s)": "nom de fichier pour les journaux de sortie (par défaut: %s)", + "run dapp (default: %s)": "lancer la dapp (par défaut: %s)", + "Use a specific ethereum client or simulator (supported: %s)": "Utiliser un client ou simulateur ethereum spécifique (supporté:% s)", + "run blockchain server (default: %s)": "exécuter le serveur blockchain (par défaut: %s)", + "run a fast ethereum rpc simulator": "exécuter un simulateur ethereum RPC rapide", + "use testrpc as the rpc simulator [%s]": "utiliser testrpc comme simulateur RPC [%s]", + "port to run the rpc simulator (default: %s)": "port pour exécuter le simulateur RPC (par défaut: %s)", + "host to run the rpc simulator (default: %s)": "hôte pour exécuter le simulateur RPC (par défaut: %s)", + "number of accounts (default: %s)": "nombre de comptes (par défaut: %s)", + "Amount of ether to assign each test account (default: %s)": "Quantité d'éther à affecter à chaque compte de test (par défaut: %s)", + "custom gas limit (default: %s)": "limite de gaz personnalisée (par défaut: %s)", + "run tests": "Exécuter les tests", + "resets embarks state on this dapp including clearing cache": "réinitialise l'état d'Embark dans cette dapp, y compris le cache", + "generates documentation based on the smart contracts configured": "génère la documentation basée sur les contrats configurés", + "Upload your dapp to a decentralized storage": "Téléchargez votre dapp dans un stockage décentralisé", + "output the version number": "afficher le numéro de version", + "Logs": "Journaux", + "Environment": "Environnement", + "Available Services": "Services disponibles", + "Contracts": "Contrats", + "Console": "Console", + "dashboard start": "démarrer le tableau de bord", + "loaded plugins": "plugins chargés", + "compiling solidity contracts": "compilation des contrats Solidity", + "%s doesn't have a compatible contract compiler. Maybe a plugin exists for it.": "%s n'a pas de compilateur de contrat compatible, il existe peut-être un plugin.", + "assuming %s to be an interface": "En supposant que %s soit une interface", + "{{className}}: couldn't find instanceOf contract {{parentContractName}}": "{{className}}: impossible de trouver un instance du contrat {{parentContractName}}", + "did you mean \"%s\"?": "Voulez-vous dire \"%s\"?", + "%s has no code associated": "%s n'a aucun code associé", + "deploying contracts": "déploiement des contrats", + "running beforeDeploy plugin %s .": "En cours d'exécution du plugin beforeDeploy %s .", + "deploying": "En cours de déploiement", + "with": "avec", + "gas": "gaz", + "Pending": "en attente", + "Interface or set to not deploy": "Interface ou configuré pour ne pas déployer", + "error deploying": "erreur de déploiement", + "due to error": "en raison d'une erreur", + "error deploying contracts": "erreur lors du déploiement de contrats", + "finished deploying contracts": "fini de déployer les contrats", + "error running afterDeploy: ": "erreur d'exécution AfterDeploy: ", + "ready to watch file changes": "Prêt à monitorer les changements de fichiers", + "Starting Server": "Démarrage du serveur", + "webserver available at": "serveur Web disponible à", + "Webserver": "Serveur Web", + " already deployed at ": " déjà déployé à ", + "Deployed": "Déployé", + "Name must be only letters, spaces, or dashes": "Le nom ne doit être que des lettres, des espaces ou des tirets", + "Name your app (default is %s)": "Nommez votre application (par défaut: %s)", + "Invalid name": "Nom incorrect", + "unknown command": "commande inconnue", + "did you mean": "vouliez-vous dire", + "warning: running default config on a non-development environment": "avertissement: exécution de la configuration par défaut sur un environnement de non-développement", + "could not find {{geth_bin}} command; is {{client_name}} installed or in the PATH?": "Impossible de trouver la commande {{geth_bin}}, est-ce que {{client_name}} est installé ou dans le PATH?", + "no accounts found": "Aucun compte trouvé", + "initializing genesis block": "initialisation du bloc de genèse", + "rpcCorsDomain set to *": "rpcCorsDomain défini sur *", + "make sure you know what you are doing": "Assurez-vous de savoir ce que vous faites", + "warning: cors is not set": "avertissement: cors n'est pas défini", + "wsOrigins set to *": "wsOrigins défini sur *", + "warning: wsOrigins is not set": "avertissement: wsOrigins n'est pas défini", + "reset done!": "réinitialisation terminée!", + "%s is not installed on your machine": "%s n'est pas installé sur votre machine", + "You can install it by running: %s": "Vous pouvez l'installer en exécutant: %s", + "Initializing Embark Template....": "Initialisation du modèle Embark....", + "Installing packages...": "Installation des paquets...", + "Init complete": "Initialisation terminée", + "App ready at ": "Application prête à ", + "Next steps:": "Prochaines étapes:", + "open another console in the same directory and run": "ouvrir une autre console dans le même répertoire et exécutez", + "For more info go to http://embark.status.im": "Pour plus d'informations, rendez-vous sur http://embark.status.im", + "%s : instanceOf is set to itself": "%s : instanceOf est défini sur lui-même", + "{{className}} has code associated to it but it's configured as an instanceOf {{parentContractName}}": "{{className}} a du code associé, mais il est configuré comme une instanceOf {{parentContractName}}", + "Error Compiling/Building contracts: ": "Erreur lors de la compilation/construction des contrats: ", + "Error: ": "Erreur: ", + "there are two or more contracts that depend on each other in a cyclic manner": "il y a deux ou plusieurs contrats qui dépendent l'un de l'autre de manière cyclique", + "Embark couldn't determine which one to deploy first": "Embark n'a pas pu déterminer lequel déployer en premier", + "{{inputName}} has not been defined for {{className}} constructor": "{{inputName}} n'a pas été défini pour le constructeur {{className}}", + "error deploying %s": "erreur de déploiement de %s", + "executing onDeploy commands": "Exécution des commandes onDeploy", + "error executing onDeploy for ": "erreur d'exécution onDeploy pour ", + " does not exist": " n'existe pas", + "error running onDeploy: ": "erreur d'exécution onDeploy: ", + " exists but has been set to not deploy": " existe, mais a été configuré pour ne pas se déployer", + "couldn't find a valid address for %s has it been deployed?": "impossible de trouver une adresse valide pour %s. A-t-il été déployé?", + "executing: ": "en cours d'exécution: ", + "the transaction was rejected; this usually happens due to a throw or a require": "la transaction a été rejetée, cela arrive généralement en raison d'un 'throw' ou d'un 'require'", + "no account found at index": "aucun compte trouvé à l'index", + " check the config": " vérifier la configuration", + "Both \"from\" and \"fromIndex\" are defined for contract": "\"from\" et \"fromIndex\" sont définis pour le contrat", + "Using \"from\" as deployer account.": "Embark utilise \"from\" comme compte de déploiement.", + "{{linkReference}} is too long": "{{linkReference}} est trop long", + "{{contractName}} needs {{libraryName}} but an address was not found, did you deploy it or configured an address?": "{{contractName}} a besoin de {{libraryName}} mais une adresse n'a pas été trouvée, l'avez-vous déployée ou avez-vous configuré une adresse?", + "attempted to deploy %s without specifying parameters": "a tenté de déployer %s sans spécifier de paramètres", + "deployed at": "déployé à", + "no contracts found": "aucun contrat trouvé", + "Blockchain component is disabled in the config": "Le composant Blockchain est désactivé dans la configuration", + "Couldn't connect to an Ethereum node are you sure it's on?": "Impossible de se connecter à un noeud Ethereum. Êtes-vous sûr qu'il est activé?", + "make sure you have an Ethereum node or simulator running. e.g '%s'": "Assurez-vous que vous avez un noeud Ethereum ou un simulateur en cours d'exécution, par exemple '%s'", + "executing": "en cours d'exécution", + "the transaction was rejected; this usually happens due to a throw or a require, it can also happen due to an invalid operation": "la transaction a été rejetée, cela arrive généralement en raison d'un 'throw' ou d'un 'require', cela peut aussi arriver en raison d'une opération invalide", + "Cannot find file %s Please ensure you are running this command inside the Dapp folder": "Impossible de trouver le fichier %s Veuillez vous assurer que vous exécutez cette commande dans le dossier Dapp", + "no config file found at %s using default config": "Aucun fichier de configuration trouvé sur %s en utilisant la configuration par défaut", + "HTTP contract file not found": "Fichier de contrat HTTP introuvable", + "contract file not found": "Fichier de contrat non trouvé", + "file not found, creating it...": "fichier introuvable, en cours de création...", + "No Blockchain node found": "Pas de noeud Blockchain trouvé", + "Ethereum node (version unknown)": "Nœud Ethereum (version inconnue)", + "this event is deprecated and will be removed in future versions %s": "cet événement est obsolète et sera supprimé dans les futures versions %s", + "Error while downloading the file": "Erreur lors du téléchargement du fichier", + "Plugin {{name}} can only be loaded in the context of \"{{contextes}}\"": "Le plugin {{name}} ne peut être chargé que dans le contexte de \"{{contextes}}\"", + "error running service check": "erreur lors de l'exécution du service de contrôle", + "help": "aide", + "quit": "quitter", + "Type": "Type", + "to see the list of available commands": "pour voir la liste des commandes disponibles", + "Asset Pipeline": "Asset Pipeline", + "Ethereum node detected": "Nœud Ethereum détecté", + "Deployment Done": "Déploiement effectué", + "Looking for documentation? You can find it at": "Vous cherchez de la documentation? Vous pouvez la trouver à", + "Ready": "Prêt", + "tip: you can resize the terminal or disable the dashboard with": "astuce: vous pouvez redimensionner le terminal ou désactiver le tableau de bord avec", + "finished building": "construction terminé", + "Done": "Terminé", + "Cannot upload: {{platform}} node is not running on {{url}}.": "Impossible de télécharger: le noeud {{platform}} ne fonctionne pas sur {{url}}.", + "try \"{{ipfs}}\" or \"{{swarm}}\"": "essayez \"{{ipfs}}\" ou \"{{swarm}}\"", + "finished deploying": "déploiement terminé", + "finished building DApp and deploying to": "construction de la DApp terminé et déploiement à", + "IPFS node detected": "Noeud IPFS détecté", + "IPFS node is offline": "Le noeud IPFS est hors ligne", + "not found or not in the path. Guessing %s for path": "introuvable ou pas dans le PATH. Embark devine %s pour le chemin.", + "adding %s to ipfs": "en cours d'ajout %s à ipfs", + "DApp available at": "DApp disponible à", + "error uploading to ipfs": "Erreur de téléchargement sur ipfs", + "successfully uploaded to ipfs": "Téléchargé avec succès sur ipfs", + "Error while loading the content of ": "Erreur lors du chargement du contenu de ", + "error compiling for unknown reasons": "erreur de compilation pour des raisons inconnues", + "error compiling. There are sources available but no code could be compiled, likely due to fatal errors in the solidity code": "erreur de compilation.Il existe des sources disponibles, mais aucun code n'a pu être compilé, probablement en raison d'erreurs fatales dans le code de solidity", + "Swarm node detected...": "Noeud Swarm détecté...", + "Swarm node is offline...": "Le nœud Swarm est hors ligne ...", + "deploying to swarm!": "déploiement de swarm!", + "adding %s to swarm": "Ajout de %s à swarm", + "error uploading to swarm": "Erreur de téléchargement dans le swarm", + "successfully uploaded to swarm": "téléchargé avec succès dans le swarm", + "Vyper exited with error code ": "Vyper a quitté avec le code d'erreur ", + "Execution returned no result": "L'exécution n'a renvoyé aucun résultat", + "compiling Vyper contracts": "compilation des contrats Vyper", + "Webserver is offline": "Le serveur Web est hors ligne", + "stopping webserver": "Serveur web en cours d'arrêt", + "a webserver is already running at": "un serveur web est déjà en cours d'exécution à", + "no webserver is currently running": "Aucun serveur Web n'est en cours d'exécution", + "couldn't find file": "Impossible de trouver le fichier", + "errors found while generating": "erreurs trouvées lors de la génération", + "writing file": "écriture du fichier", + "Simulator not found; Please install it with \"%s\"": "Simulateur introuvable, veuillez l'installer avec \"%s\"", + "Tried to load testrpc but an error occurred. This is a problem with testrpc": "Nous avons essayé de charger testrpc, mais une erreur s'est produite. Ceci est un problème avec testrpc", + "IMPORTANT: if you using a NodeJS version older than 6.9.1 then you need to install an older version of testrpc \"%s\". Alternatively install node 6.9.1 and the testrpc 3.0": "IMPORTANT: si vous utilisez une version NodeJS antérieure à la version 6.9.1, vous devez installer une ancienne version de testrpc \"%s\". Ou bien installer Node 6.9.1 et le testrpc 3.0", + "terminating due to error": "en cours de terminaison en raison d'une erreur", + "There a a space in the version of {{versionKey}}. We corrected it for you ({{correction})": "Il y a un espace dans la version de {{versionKey}}. Nous l'avons corrigé pour vous ({{correction})", + "versions": "versions", + "versions in use": "versions en cours d'utilisation", + "downloading {{packageName}} {{version}}....": "téléchargement {{packageName}} {{version}}...." +} diff --git a/lib/i18n/locales/pt.json b/lib/i18n/locales/pt.json new file mode 100644 index 000000000..dd0143d83 --- /dev/null +++ b/lib/i18n/locales/pt.json @@ -0,0 +1,188 @@ +{ + "New Application": "Nova Aplicacao", + "Contract Name": "Contracto", + "Address": "Endereço", + "Status": "Estado", + "Embark Blockchain Using: %s": "Embark Blockchain esta usando o commando: %s", + "running: %s": "executando: %s", + "already initialized": "ja esta inicializado", + "create a barebones project meant only for contract development": "criar um projeto vazio destinado apenas ao desenvolvimento de contratos", + "loading solc compiler": "carregando o compilador solc", + "Welcome to Embark": "Bem-vindo ao Embark", + "possible commands are:": "comandos possíveis são:", + "display versions in use for libraries and tools like web3 and solc": "lista versões em uso para bibliotecas e ferramentas como web3 e solc", + "instantiated web3.js object configured to the current environment": "objeto web3.js instanciado configurado para o ambiente atual", + "to immediatly exit (alias: exit)": "para sair imediatamente (alias: exit)", + "The web3 object and the interfaces for the deployed contracts and their methods are also available": "O objeto web3 e as interfaces para os contratos implantados e seus métodos também estão disponíveis", + "create a working dapp with a SimpleStorage contract": "Cria uma dapp funcional com o contrato SimpleStorage", + "filename to output logs (default: none)": "ficheiro/arquivo para saída dos logs (predefinido: none)", + "level of logging to display": "nivel do log", + "deploy and build dapp at ": "Publica os contractos e constroi a applicacao em ", + "port to run the dev webserver (default: %s)": "porta para correr o servidor web para desenvolvimento (default: %s)", + "host to run the dev webserver (default: %s)": "host para correr o servidor web para desenvolvimento (default: %s)", + "disable the development webserver": "disativa o servidor web para desenvolvimento", + "simple mode, disables the dashboard": "modo simples, disativa o dashboard", + "no colors in case it's needed for compatbility purposes": "sem cores, em caso seja necessario para compabitilidade com a terminal", + "filename to output logs (default: %s)": "ficheiro/arquivo para os logs (predefinido: %s)", + "run dapp (default: %s)": "executa a dapp (applicacao decentralizada) (predefinido: %s)", + "Use a specific ethereum client or simulator (supported: %s)": "Usa um cliente ou simulador de ethereum específico (supportado: %s)", + "run blockchain server (default: %s)": "executa un node de blockchain (predefinido: %s)", + "run a fast ethereum rpc simulator": "executa um simulador RPC de ethereum", + "use testrpc as the rpc simulator [%s]": "usa testrpc como simulator de rpc [%s]", + "port to run the rpc simulator (default: %s)": "porta para executar simulador de rpc (predefinido: %s)", + "host to run the rpc simulator (default: %s)": "host para executar servidor de rpc (predefinido: %s)", + "number of accounts (default: %s)": "numero de contas (predefinido: %s)", + "Amount of ether to assign each test account (default: %s)": "Quantidade de éter para atribuir cada conta de teste (predefinido: %s)", + "custom gas limit (default: %s)": "limite de gás (predefinido: %s)", + "run tests": "executar os testes", + "resets embarks state on this dapp including clearing cache": "recomenca o estado do Embark nesta appliacao, incluindo a cache", + "generates documentation based on the smart contracts configured": "gera documentação baseada nos contratos configurados", + "Upload your dapp to a decentralized storage": "Carrega a appliacao para armazenamento descentralizado", + "output the version number": "produz a versão actual", + "Logs": "Logs", + "Environment": "Ambiente", + "Available Services": "Serviços Disponíveis", + "Contracts": "Contratos", + "Console": "Consola", + "dashboard start": "inicia o painel de controle", + "loaded plugins": "plugins carregados", + "compiling solidity contracts": "Compilando contratos Solidity", + "%s doesn't have a compatible contract compiler. Maybe a plugin exists for it.": "%s não tem um compilador de contrato compatível. Talvez exista um plugin para isso.", + "assuming %s to be an interface": "assumindo que %s é uma interface", + "{{className}}: couldn't find instanceOf contract {{parentContractName}}": "{{className}}: não foi possível encontrar instancia de (instanceOf) do contrato {{parentContractName}}", + "did you mean \"%s\"?": "você quis dizer \"%s\"?", + "%s has no code associated": "%s não tem código associado", + "deploying contracts": "publicando contratos", + "running beforeDeploy plugin %s .": "executando plugin beforeDeploy %s .", + "deploying": "publicando", + "with": "com", + "gas": "gas", + "Pending": "Pendente", + "Interface or set to not deploy": "Interface ou configurado para não ser publicado", + "error deploying": "erro de publicação", + "due to error": "devido a erro", + "error deploying contracts": "erro publicando contratos", + "finished deploying contracts": "publicação de contratos concluida", + "error running afterDeploy: ": "erro executado afterDeploy: ", + "ready to watch file changes": "pronto para monitorar alterações em ficheiros/arquivos", + "Starting Server": "iniciando o servidor", + "webserver available at": "servidor web disponivel em", + "Webserver": "Servidor Web", + " already deployed at ": " já publicado em ", + "Deployed": "Publicado", + "Name must be only letters, spaces, or dashes": "O nome deve ser apenas letras, espaços ou traços", + "Name your app (default is %s)": "Nome da aplicacao (predefinido is %s)", + "Invalid name": "Nome inválido", + "unknown command": "comando desconhecido", + "did you mean": "você quis dizer", + "warning: running default config on a non-development environment": "aviso: executando a configuração padrão em um ambiente de não desenvolvimento", + "could not find {{geth_bin}} command; is {{client_name}} installed or in the PATH?": "não foi possível encontrar o comando {{geth_bin}}; o {{client_name}} instalado ou no PATH?", + "no accounts found": "nenhuma conta encontrada", + "initializing genesis block": "inicializando o bloco de gênese", + "rpcCorsDomain set to *": "rpcCorsDomain definido como *", + "make sure you know what you are doing": "certifique-se de saber o que está fazendo", + "warning: cors is not set": "aviso: cors não está definido", + "wsOrigins set to *": "wsOrigins definido como *", + "warning: wsOrigins is not set": "aviso: wsOrigins não está definido", + "reset done!": "reset feito!", + "%s is not installed on your machine": "%s não está instalado na sua máquina", + "You can install it by running: %s": "Você pode instalá-lo executando: %s", + "Initializing Embark Template....": "Inicializando Embark Template....", + "Installing packages...": "Instalando pacotes...", + "Init complete": "Init complete", + "App ready at ": "App ready at ", + "Next steps:": "Next steps:", + "open another console in the same directory and run": "open another console in the same directory and run", + "For more info go to http://embark.status.im": "For more info go to http://embark.status.im", + "%s : instanceOf is set to itself": "%s : instanceOf is set to itself", + "{{className}} has code associated to it but it's configured as an instanceOf {{parentContractName}}": "{{className}} has code associated to it but it's configured as an instanceOf {{parentContractName}}", + "Error Compiling/Building contracts: ": "Error Compiling/Building contracts: ", + "Error: ": "Error: ", + "there are two or more contracts that depend on each other in a cyclic manner": "there are two or more contracts that depend on each other in a cyclic manner", + "Embark couldn't determine which one to deploy first": "Embark couldn't determine which one to deploy first", + "{{inputName}} has not been defined for {{className}} constructor": "{{inputName}} has not been defined for {{className}} constructor", + "error deploying %s": "error deploying %s", + "executing onDeploy commands": "executing onDeploy commands", + "error executing onDeploy for ": "error executing onDeploy for ", + " does not exist": " does not exist", + "error running onDeploy: ": "error running onDeploy: ", + " exists but has been set to not deploy": " exists but has been set to not deploy", + "couldn't find a valid address for %s has it been deployed?": "couldn't find a valid address for %s has it been deployed?", + "executing: ": "executing: ", + "the transaction was rejected; this usually happens due to a throw or a require": "the transaction was rejected; this usually happens due to a throw or a require", + "no account found at index": "no account found at index", + " check the config": " check the config", + "Both \"from\" and \"fromIndex\" are defined for contract": "Both \"from\" and \"fromIndex\" are defined for contract", + "Using \"from\" as deployer account.": "Using \"from\" as deployer account.", + "{{linkReference}} is too long": "{{linkReference}} is too long", + "{{contractName}} needs {{libraryName}} but an address was not found, did you deploy it or configured an address?": "{{contractName}} needs {{libraryName}} but an address was not found, did you deploy it or configured an address?", + "attempted to deploy %s without specifying parameters": "attempted to deploy %s without specifying parameters", + "deployed at": "deployed at", + "no contracts found": "no contracts found", + "Blockchain component is disabled in the config": "Blockchain component is disabled in the config", + "Couldn't connect to an Ethereum node are you sure it's on?": "Couldn't connect to an Ethereum node are you sure it's on?", + "make sure you have an Ethereum node or simulator running. e.g '%s'": "make sure you have an Ethereum node or simulator running. e.g '%s'", + "executing": "executing", + "the transaction was rejected; this usually happens due to a throw or a require, it can also happen due to an invalid operation": "the transaction was rejected; this usually happens due to a throw or a require, it can also happen due to an invalid operation", + "Cannot find file %s Please ensure you are running this command inside the Dapp folder": "Cannot find file %s Please ensure you are running this command inside the Dapp folder", + "no config file found at %s using default config": "no config file found at %s using default config", + "HTTP contract file not found": "HTTP contract file not found", + "contract file not found": "contract file not found", + "file not found, creating it...": "file not found, creating it...", + "No Blockchain node found": "No Blockchain node found", + "Ethereum node (version unknown)": "Ethereum node (version unknown)", + "this event is deprecated and will be removed in future versions %s": "this event is deprecated and will be removed in future versions %s", + "Error while downloading the file": "Error while downloading the file", + "Plugin {{name}} can only be loaded in the context of \"{{contextes}}\"": "Plugin {{name}} can only be loaded in the context of \"{{contextes}}\"", + "error running service check": "error running service check", + "help": "ajuda", + "quit": "sair", + "Type": "Type", + "to see the list of available commands": "to see the list of available commands", + "Asset Pipeline": "Asset Pipeline", + "Ethereum node detected": "Ethereum node detected", + "Deployment Done": "Deployment Done", + "Looking for documentation? You can find it at": "A procura de Documentacao? pode encontra-la em", + "Ready": "Ready", + "tip: you can resize the terminal or disable the dashboard with": "tip: you can resize the terminal or disable the dashboard with", + "finished building": "finished building", + "Done": "Done", + "Cannot upload: {{platform}} node is not running on {{url}}.": "Cannot upload: {{platform}} node is not running on {{url}}.", + "try \"{{ipfs}}\" or \"{{swarm}}\"": "try \"{{ipfs}}\" or \"{{swarm}}\"", + "finished deploying": "finished deploying", + "finished building DApp and deploying to": "finished building DApp and deploying to", + "IPFS node detected": "IPFS node detected", + "IPFS node is offline": "IPFS node is offline", + "not found or not in the path. Guessing %s for path": "not found or not in the path. Guessing %s for path", + "adding %s to ipfs": "adding %s to ipfs", + "DApp available at": "DApp available at", + "error uploading to ipfs": "error uploading to ipfs", + "successfully uploaded to ipfs": "successfully uploaded to ipfs", + "Error while loading the content of ": "Error while loading the content of ", + "error compiling for unknown reasons": "error compiling for unknown reasons", + "error compiling. There are sources available but no code could be compiled, likely due to fatal errors in the solidity code": "error compiling. There are sources available but no code could be compiled, likely due to fatal errors in the solidity code", + "Swarm node detected...": "Swarm node detected...", + "Swarm node is offline...": "Swarm node is offline...", + "deploying to swarm!": "deploying to swarm!", + "adding %s to swarm": "adding %s to swarm", + "error uploading to swarm": "error uploading to swarm", + "successfully uploaded to swarm": "successfully uploaded to swarm", + "Vyper exited with error code ": "Vyper exited with error code ", + "Execution returned no result": "Execution returned no result", + "compiling Vyper contracts": "compiling Vyper contracts", + "Webserver is offline": "Webserver is offline", + "stopping webserver": "stopping webserver", + "a webserver is already running at": "a webserver is already running at", + "no webserver is currently running": "no webserver is currently running", + "couldn't find file": "couldn't find file", + "errors found while generating": "errors found while generating", + "writing file": "escrevendo ficheiro", + "Simulator not found; Please install it with \"%s\"": "Simulator not found; Please install it with \"%s\"", + "Tried to load testrpc but an error occurred. This is a problem with testrpc": "Tried to load testrpc but an error occurred. This is a problem with testrpc", + "IMPORTANT: if you using a NodeJS version older than 6.9.1 then you need to install an older version of testrpc \"%s\". Alternatively install node 6.9.1 and the testrpc 3.0": "IMPORTANT: if you using a NodeJS version older than 6.9.1 then you need to install an older version of testrpc \"%s\". Alternatively install node 6.9.1 and the testrpc 3.0", + "terminating due to error": "terminating due to error", + "There a a space in the version of {{versionKey}}. We corrected it for you ({{correction})": "There a a space in the version of {{versionKey}}. We corrected it for you ({{correction})", + "versions": "versions", + "versions in use": "versions in use", + "downloading {{packageName}} {{version}}....": "downloading {{packageName}} {{version}}...." +} diff --git a/lib/index.js b/lib/index.js index 9e5a485fb..858292ca0 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,26 +1,22 @@ let async = require('async'); const constants = require('./constants'); -const _ = require('underscore'); -// require("./utils/debug_util.js")(__filename, async); require('colors'); // Override process.chdir so that we have a partial-implementation PWD for Windows const realChdir = process.chdir; process.chdir = (...args) => { - if (!process.env.PWD) { - process.env.PWD = process.cwd(); - } - realChdir(...args); + if (!process.env.PWD) { + process.env.PWD = process.cwd(); + } + realChdir(...args); }; -let Engine = require('./core/engine.js'); - let version = require('../package.json').version; class Embark { - constructor (options) { + constructor(options) { this.version = version; this.options = options || {}; } @@ -38,27 +34,27 @@ class Embark { this.plugins = this.config.plugins; } + isDev(env) { + if (this.config && this.config.blockchainConfig && this.config.blockchainConfig.isDev) { + return true; + } else if (this.config && this.config.blockchainConfig && this.config.blockchainConfig.isDev === false) { + return false; + } + return (env === 'development'); + } + blockchain(env, client) { this.context = [constants.contexts.blockchain]; - 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(); + return require('./cmds/blockchain/blockchain.js')(this.config.blockchainConfig, client, env, this.isDev(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, logger: this.logger}); + let simulator = new Simulator({ + blockchainConfig: this.config.blockchainConfig, + logger: this.logger + }); simulator.run(options); } @@ -73,21 +69,25 @@ class Embark { let self = this; self.context = options.context || [constants.contexts.run, constants.contexts.build]; let Dashboard = require('./dashboard/dashboard.js'); - let windowSize = require('window-size'); - let engine = new Engine({ + const Engine = require('./core/engine.js'); + const engine = new Engine({ env: options.env, + client: options.client, + locale: options.locale, + isDev: this.isDev(options.env), version: this.version, embarkConfig: options.embarkConfig || 'embark.json', logFile: options.logFile, logLevel: options.logLevel, - context: self.context + context: self.context, + useDashboard: options.useDashboard }); engine.init(); if (!options.useDashboard) { engine.logger.info('========================'.bold.green); - engine.logger.info(('Welcome to Embark ' + this.version).yellow.bold); + engine.logger.info((__('Welcome to Embark') + ' ' + this.version).yellow.bold); engine.logger.info('========================'.bold.green); } @@ -106,48 +106,51 @@ class Embark { contractsConfig: engine.config.contractsConfig }); dashboard.start(function () { - engine.logger.info('dashboard start'); + engine.logger.info(__('dashboard start')); callback(); }); }, function (callback) { let pluginList = engine.plugins.listPlugins(); if (pluginList.length > 0) { - engine.logger.info("loaded plugins: " + pluginList.join(", ")); + engine.logger.info(__("loaded plugins") + ": " + pluginList.join(", ")); } - engine.startMonitor(); + engine.startService("serviceMonitor"); engine.startService("libraryManager"); + engine.startService("codeRunner"); engine.startService("web3"); engine.startService("pipeline"); - engine.startService("codeGenerator"); engine.startService("deployment"); - engine.startService(engine.config.storageConfig.provider, {bzz: engine.web3.bzz}); + engine.startService("storage"); + engine.startService("codeGenerator"); + engine.startService("namingSystem"); engine.events.on('check:backOnline:Ethereum', function () { - engine.logger.info('Ethereum node detected..'); + engine.logger.info(__('Ethereum node detected') + '..'); engine.config.reloadConfig(); - engine.deployManager.deployContracts(function () { - engine.logger.info('Deployment Done'); + engine.events.request('deploy:contracts', function (err) { + if (err) { + return; + } + engine.logger.info(__('Deployment Done')); }); }); 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.logger.info((__("Looking for documentation? You can find it at") + " ").cyan + "http://embark.status.im/docs/".green.underline + ".".cyan); + engine.logger.info(__("Ready").underline); + engine.events.emit("status", __("Ready").green); }); - engine.deployManager.deployContracts(function (err) { - engine.startService("fileWatcher"); - if (options.runWebserver) { - engine.startService("webServer", { - host: options.serverHost, - port: options.serverPort - }); - } - callback(err); - }); + if (options.runWebserver) { + engine.startService("webServer", { + host: options.serverHost, + port: options.serverPort + }); + } + engine.startService("fileWatcher"); + callback(); } ], function (err, _result) { if (err) { @@ -155,11 +158,6 @@ class Embark { engine.logger.info(err.stack); } else { engine.events.emit('firstDeploymentDone'); - - let size = windowSize.get(); - if (size.height < 40 || size.width < 118) { - engine.logger.warn("tip: you can resize the terminal or disable the dashboard with " + "embark run --nodashboard".bold.underline); - } } }); } @@ -167,8 +165,12 @@ class Embark { build(options) { this.context = options.context || [constants.contexts.build]; - let engine = new Engine({ + const Engine = require('./core/engine.js'); + const engine = new Engine({ env: options.env, + client: options.client, + locale: options.locale, + isDev: this.isDev(options.env), version: this.version, embarkConfig: 'embark.json', interceptLogs: false, @@ -186,20 +188,20 @@ class Embark { function startServices(callback) { let pluginList = engine.plugins.listPlugins(); if (pluginList.length > 0) { - engine.logger.info("loaded plugins: " + pluginList.join(", ")); + engine.logger.info(__("loaded plugins") + ": " + pluginList.join(", ")); } engine.startService("libraryManager"); + engine.startService("codeRunner"); engine.startService("web3"); engine.startService("pipeline"); + engine.startService("deployment", {onlyCompile: options.onlyCompile}); + engine.startService("storage"); engine.startService("codeGenerator"); - engine.startService("deployment"); - engine.startService("ipfs"); - engine.startService("swarm", {bzz: engine.web3.bzz}); callback(); }, function deploy(callback) { - engine.deployManager.deployContracts(function (err) { + engine.events.request('deploy:contracts', function (err) { callback(err); }); }, @@ -215,26 +217,21 @@ class Embark { engine.logger.error(err.message); engine.logger.debug(err.stack); } else { - engine.logger.info("Finished building".underline); + engine.logger.info(__("finished building").underline); } // needed due to child processes process.exit(); }); } - initTests(options) { - this.context = options.context || [constants.contexts.test]; - let Test = require('./tests/test.js'); - options.context = this.context; - return new Test(options); - } - graph(options) { this.context = options.context || [constants.contexts.graph]; options.onlyCompile = true; - - let engine = new Engine({ + + const Engine = require('./core/engine.js'); + const engine = new Engine({ env: options.env, + isDev: this.isDev(options.env), version: this.version, embarkConfig: options.embarkConfig || 'embark.json', logFile: options.logFile, @@ -242,26 +239,23 @@ class Embark { }); engine.init(); - - async.parallel([ - + async.waterfall([ function (callback) { let pluginList = engine.plugins.listPlugins(); if (pluginList.length > 0) { - engine.logger.info("loaded plugins: " + pluginList.join(", ")); + engine.logger.info(__("loaded plugins") + ": " + pluginList.join(", ")); } - engine.startMonitor(); + engine.startService("serviceMonitor"); engine.startService("libraryManager"); engine.startService("pipeline"); - engine.startService("codeGenerator"); engine.startService("deployment", {onlyCompile: true}); + engine.startService("web3"); + engine.startService("codeGenerator"); - engine.deployManager.deployContracts(function (err) { - callback(err); - }); + engine.events.request('deploy:contracts', callback); } - ], function (err, _result) { + ], (err) => { if (err) { engine.logger.error(err.message); engine.logger.info(err.stack); @@ -269,11 +263,11 @@ class Embark { const GraphGenerator = require('./cmds/graph.js'); let graphGen = new GraphGenerator(engine); - graphGen.generate(); + graphGen.generate(options); - engine.logger.info("Done".underline); - process.exit(); + engine.logger.info(__("Done. %s generated", "./diagram.svg").underline); } + process.exit(); }); } @@ -284,12 +278,15 @@ class Embark { resetCmd(); } - upload(platform, options) { - + upload(options) { this.context = options.context || [constants.contexts.upload, constants.contexts.build]; - let engine = new Engine({ + const Engine = require('./core/engine.js'); + const engine = new Engine({ env: options.env, + client: options.client, + locale: options.locale, + isDev: this.isDev(options.env), version: this.version, embarkConfig: 'embark.json', interceptLogs: false, @@ -298,51 +295,37 @@ 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.upload.provider; + let cmdPlugin; async.waterfall([ - + function startServices(callback) { - + + engine.startService("serviceMonitor"); engine.startService("libraryManager"); + engine.startService("codeRunner"); engine.startService("web3"); engine.startService("pipeline"); - engine.startService("codeGenerator"); engine.startService("deployment"); - engine.startService(platform.toLowerCase(), {bzz: engine.web3.bzz}); - engine.startMonitor(); + engine.startService("storage"); + engine.startService("codeGenerator"); 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') { - 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){ + function setupStoragePlugin(callback) { let pluginList = engine.plugins.listPlugins(); if (pluginList.length > 0) { - engine.logger.info("loaded plugins: " + pluginList.join(", ")); + engine.logger.info(__("loaded plugins") + ": " + pluginList.join(", ")); } - + // check use has input existing storage plugin let cmdPlugins = engine.plugins.getPluginsFor('uploadCmds'); - + if (cmdPlugins.length > 0) { cmdPlugin = cmdPlugins.find((pluginCmd) => { return pluginCmd.uploadCmds.some(uploadCmd => { @@ -351,25 +334,23 @@ class Embark { }); } if (!cmdPlugin) { - engine.logger.info('try "embark upload ipfs" or "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(); }, function deploy(callback) { - // 2. upload to storage (outputDone event triggered after webpack finished) engine.events.on('outputDone', function () { cmdPlugin.uploadCmds[0].cb() - .then((success) => { - callback(null, success); - }) - .catch(callback); + .then((success) => { + callback(null, success); + }) + .catch(callback); }); - // 1. build the contracts and dapp webpack - engine.deployManager.deployContracts(function (err) { - engine.logger.info("finished deploying".underline); - if(err){ - callback(err); + + engine.events.request('deploy:contracts', function (err) { + engine.logger.info(__("finished deploying").underline); + if (err) { + callback(err); } }); } @@ -378,7 +359,7 @@ class Embark { engine.logger.error(err.message); engine.logger.debug(err.stack); } else { - engine.logger.info(`finished building DApp and deploying to ${platform}`.underline); + engine.logger.info((__("finished building DApp and deploying to") + " " + platform).underline); } // needed due to child processes @@ -386,19 +367,11 @@ class Embark { }); } - runTests(file) { + runTests(options) { this.context = [constants.contexts.test]; let RunTests = require('./tests/run_tests.js'); - RunTests.run(file); + RunTests.run(options); } - } -// temporary until next refactor -Embark.initTests = function(options) { - let Test = require('./tests/test.js'); - options.context = [constants.contexts.test]; - return new Test(options); -}; - module.exports = Embark; diff --git a/lib/modules/console_listener/index.js b/lib/modules/console_listener/index.js new file mode 100644 index 000000000..210b6ae2a --- /dev/null +++ b/lib/modules/console_listener/index.js @@ -0,0 +1,92 @@ +const utils = require('../../utils/utils.js'); + +class ConsoleListener { + constructor(embark, options) { + this.logger = embark.logger; + this.ipc = options.ipc; + this.events = embark.events; + this.addressToContract = []; + this.contractsConfig = embark.config.contractsConfig; + this.contractsDeployed = false; + this._listenForLogRequests(); + + this.events.on("contractsDeployed", () => { + this.contractsDeployed = true; + this._updateContractList(); + }); + } + + _updateContractList(){ + this.events.request("contracts:list", (_err, contractsList) => { + if(_err) { + this.logger.error(__("no contracts found")); + return; + } + contractsList.forEach(contract => { + if(!contract.deployedAddress) return; + + let address = contract.deployedAddress.toLowerCase(); + if(!this.addressToContract[address]){ + let funcSignatures = {}; + contract.abiDefinition + .filter(func => func.type == "function") + .map(func => { + const name = func.name + + '(' + + (func.inputs ? func.inputs.map(input => input.type).join(',') : '') + + ')'; + funcSignatures[utils.sha3(name).substring(0, 10)] = { + name, + abi: func, + functionName: func.name + }; + }); + + this.addressToContract[address] = { + name: contract.className, + functions: funcSignatures + }; + } + }); + }); + } + + _listenForLogRequests(){ + if(this.ipc.ipcRole !== 'server') return; + this.ipc.on('log', (request) => { + if(request.type == 'contract-log'){ + if(!this.contractsDeployed) return; + + let {address, data, transactionHash, blockNumber, gasUsed, status} = request; + if(!this.addressToContract[address]){ + this._updateContractList(); + } + if(!this.addressToContract[address]) return; + + + const name = this.addressToContract[address].name; + const func = this.addressToContract[address].functions[data.substring(0, 10)]; + const functionName = func.functionName; + + const decodedParameters = utils.decodeParams(func.abi.inputs, data.substring(10)); + let paramString = ""; + if(func.abi.inputs){ + func.abi.inputs.forEach((input) => { + let quote = input.type.indexOf("int") == -1 ? '"' : ''; + paramString += quote + decodedParameters[input.name] + quote + ", "; + }); + paramString = paramString.substring(0, paramString.length - 2); + } + + gasUsed = utils.hexToNumber(gasUsed); + blockNumber = utils.hexToNumber(blockNumber); + + this.logger.info(`Blockchain>`.underline + ` ${name}.${functionName}(${paramString})`.bold + ` | ${transactionHash} | gas:${gasUsed} | blk:${blockNumber} | status:${status}`); + } else { + this.logger.info(JSON.stringify(request)); + } + }); + } +} + +module.exports = ConsoleListener; diff --git a/lib/modules/deploytracker/index.js b/lib/modules/deploytracker/index.js new file mode 100644 index 000000000..1d37f531c --- /dev/null +++ b/lib/modules/deploytracker/index.js @@ -0,0 +1,89 @@ +let utils = require('../../utils/utils.js'); +let fs = require('../../core/fs.js'); + +class DeployTracker { + + constructor(embark, options) { + this.logger = embark.logger; + this.events = embark.events; + + // TODO: unclear where it comes from + this.env = options.env; + //this.chainConfig = options.chainConfig; + this.chainConfig = embark.config.chainTracker; + this.registerEvents(); + } + + registerEvents() { + const self = this; + + this.events.on("deploy:beforeAll", this.setCurrentChain.bind(this)); + + this.events.on("deploy:contract:deployed", (contract) => { + self.trackContract(contract.className, contract.realRuntimeBytecode, contract.realArgs, contract.deployedAddress); + self.save(); + }); + + this.events.setCommandHandler("deploy:contract:shouldDeploy", (contract, cb) => { + let trackedContract = self.getContract(contract.className, contract.realRuntimeBytecode, contract.realArgs); + cb(trackedContract); + }); + } + + // TODO: just an event might not be enought to the async nature + // it needs to be a plugin api before deploy, that makes the deployment wait + setCurrentChain() { + const self = this; + if (this.chainConfig === false) { + this.currentChain = {contracts: []}; + //return cb(); + } + + this.events.request("blockchain:block:byNumber", 0, function(_err, block) { + let chainId = block.hash; + + if (self.chainConfig[chainId] === undefined) { + self.chainConfig[chainId] = {contracts: {}}; + } + + self.currentChain = self.chainConfig[chainId]; + + self.currentChain.name = self.env; + //cb(); + }); + } + + loadConfig(config) { + this.chainConfig = config; + return this; + } + + trackContract(contractName, code, args, address) { + if (!this.currentChain) return false; + this.currentChain.contracts[utils.sha3(code + contractName + args.join(','))] = { + name: contractName, + address: address + }; + } + + getContract(contractName, code, args) { + if (!this.currentChain) return false; + let contract = this.currentChain.contracts[utils.sha3(code + contractName + args.join(','))]; + if (contract && contract.address === undefined) { + return false; + } + return contract; + } + + // TODO: abstract this + // chainConfig can be an abstract PersistentObject + save() { + if (this.chainConfig === false) { + return; + } + fs.writeJSONSync("./chains.json", this.chainConfig, {spaces: 2}); + } + +} + +module.exports = DeployTracker; diff --git a/lib/modules/ens/embarkjs.js b/lib/modules/ens/embarkjs.js new file mode 100644 index 000000000..1f37856cf --- /dev/null +++ b/lib/modules/ens/embarkjs.js @@ -0,0 +1,304 @@ +import namehash from 'eth-ens-namehash'; + +/*global web3*/ +let __embarkENS = {}; + +// registry interface for later +__embarkENS.registryInterface = [ + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "resolver", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "owner", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "resolver", + "type": "address" + } + ], + "name": "setResolver", + "outputs": [], + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "label", + "type": "bytes32" + }, + { + "name": "owner", + "type": "address" + } + ], + "name": "setSubnodeOwner", + "outputs": [], + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "owner", + "type": "address" + } + ], + "name": "setOwner", + "outputs": [], + "type": "function" + } +]; + +__embarkENS.resolverInterface = [ + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "addr", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "content", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + } + ], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "kind", + "type": "bytes32" + } + ], + "name": "has", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "addr", + "type": "address" + } + ], + "name": "setAddr", + "outputs": [], + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "hash", + "type": "bytes32" + } + ], + "name": "setContent", + "outputs": [], + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "name", + "type": "string" + } + ], + "name": "setName", + "outputs": [], + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "node", + "type": "bytes32" + }, + { + "name": "contentType", + "type": "uint256" + } + ], + "name": "ABI", + "outputs": [ + { + "name": "", + "type": "uint256" + }, + { + "name": "", + "type": "bytes" + } + ], + "payable": false, + "type": "function" + } +]; + +__embarkENS.registryAddresses = { + // Mainnet + "1": "0x314159265dd8dbb310642f98f50c066173c1259b", + // Ropsten + "3": "0x112234455c3a32fd11230c42e7bccd4a84e02010", + // Rinkeby + "4": "0xe7410170f87102DF0055eB195163A03B7F2Bff4A" +}; + +__embarkENS.setProvider = function () { + const self = this; + // get network id and then assign ENS contract based on that + let registryAddresses = this.registryAddresses; + this.ens = null; + web3.eth.net.getId().then(id => { + if (registryAddresses[id] !== undefined) { + self.ens = new web3.eth.Contract(self.registryInterface, registryAddresses[id]); + } + // todo: deploy at this point + }).catch(e => { + if (e.message.indexOf('Provider not set or invalid') > -1) { + console.warn('ENS is not available in this chain'); + return; + } + console.error(e); + }); +}; + +__embarkENS.resolve = function(name) { + const self = this; + + if (self.ens === undefined) return; + + let node = namehash.hash(name); + + return self.ens.methods.resolver(node).call().then((resolverAddress) => { + let resolverContract = new web3.eth.Contract(self.resolverInterface, resolverAddress); + return resolverContract.methods.addr(node).call(); + }).then((addr) => { + return addr; + }).catch(err => err); +}; + +__embarkENS.lookup = function(address) { + const self = this; + + if (self.ens === undefined) return; + + if (address.startsWith("0x")) address = address.slice(2); + + let node = namehash.hash(address.toLowerCase() + ".addr.reverse"); + + return self.ens.methods.resolver(node).call().then((resolverAddress) => { + let resolverContract = new web3.eth.Contract(self.resolverInterface, resolverAddress); + return resolverContract.methods.name(node).call(); + }).then((name) => { + if (name === "" || name === undefined) throw Error("ENS name not found"); + return name; + }).catch(err => err); +}; diff --git a/lib/modules/ens/index.js b/lib/modules/ens/index.js new file mode 100644 index 000000000..0b0c66569 --- /dev/null +++ b/lib/modules/ens/index.js @@ -0,0 +1,55 @@ +const fs = require('../../core/fs.js'); +const utils = require('../../utils/utils.js'); + +class ENS { + constructor(embark, _options) { + this.logger = embark.logger; + this.events = embark.events; + this.namesConfig = embark.config.namesystemConfig; + this.embark = embark; + + this.addENSToEmbarkJS(); + this.addSetProvider(); + } + + addENSToEmbarkJS() { + const self = this; + // TODO: make this a shouldAdd condition + if (this.namesConfig === {}) { + return; + } + + if ((this.namesConfig.available_providers.indexOf('ens') < 0) && (this.namesConfig.provider !== 'ens' || this.namesConfig.enabled !== true)) { + return; + } + + self.events.request("version:get:eth-ens-namehash", function(EnsNamehashVersion) { + let currentEnsNamehashVersion = require('../../../package.json').dependencies["eth-ens-namehash"]; + if (EnsNamehashVersion !== currentEnsNamehashVersion) { + self.events.request("version:getPackageLocation", "eth-ens-namehash", EnsNamehashVersion, function(err, location) { + self.embark.registerImportFile("eth-ens-namehash", fs.dappPath(location)); + }); + } + }); + + let code = ""; + code += "\n" + fs.readFileSync(utils.joinPath(__dirname, 'embarkjs.js')).toString(); + code += "\nEmbarkJS.Names.registerProvider('ens', __embarkENS);"; + + this.embark.addCodeToEmbarkJS(code); + } + + addSetProvider() { + let config = JSON.stringify({}); + + let code = "\nEmbarkJS.Names.setProvider('ens'," + config + ");"; + + let shouldInit = (namesConfig) => { + return (namesConfig.provider === 'ens' && namesConfig.enabled === true); + }; + + this.embark.addProviderInit('names', code, shouldInit); + } +} + +module.exports = ENS; diff --git a/lib/modules/fuzzer/index.js b/lib/modules/fuzzer/index.js new file mode 100644 index 000000000..02defe933 --- /dev/null +++ b/lib/modules/fuzzer/index.js @@ -0,0 +1,113 @@ +const utils = require('web3-utils'); +const _ = require('underscore'); + +// generates random inputs based on the inputs of an ABI +class ContractFuzzer { + constructor(embark) { + this.embark = embark; + this.logger = embark.logger; + this.events = embark.events; + + this.registerConsoleCommand(); + } + + // main function to call, takes in iteration number and a contract and returns a map object + // composed of method names -> fuzzed inputs. + generateFuzz(iterations, contract) { + const self = this; + let fuzzMap = {}; + contract.abiDefinition.filter((x) => x.inputs && x.inputs.length != 0 && x.type != "event").forEach((abiMethod) => { + let name = abiMethod.type === "constructor" ? "constructor" : abiMethod.name; + let inputTypes = abiMethod.inputs.map(input => input.type); + fuzzMap[name] = {}; + for (let i = 0; i < iterations; i++) { + fuzzMap[name][i] = inputTypes.map(input => this.getTypeFuzz(input)); + self.logger.trace(name); + self.logger.trace("iteration: " + i + "\n" + fuzzMap[name][i]); + } + }); + self.logger.trace('\n'); + return fuzzMap; + } + + getTypeFuzz(typeString) { + const self = this; + // Group 0: uint256[3] + // Group 1: uint256 + // Group 2: uint + // Group 3: 256 + // Group 4: [3] + // Group 5: 3 + let regexObj = typeString.match(/((bool|int|uint|bytes|string|address)([0-9]*)?)(\[([0-9]*)\])*$/); + let type = regexObj[1]; + let kind = regexObj[2]; + let size = regexObj[3]; + let array = regexObj[4]; + let arraySize = regexObj[5]; + switch(true) { + case array !== undefined: { + // if it's a dynamic array pick a number between 1 and 256 for length of array + let length = arraySize === undefined || arraySize === null || arraySize === '' ? Math.floor((Math.random() * 256) + 1) : arraySize; + return self.generateArrayOfType(length, type); + } + case kind == "bool": + return self.generateRandomBool(); + case kind == "uint" || kind == "int": + return self.generateRandomInt(size); + case kind === "bytes" && size !== undefined: + return self.generateRandomStaticBytes(size); + case kind === "string" || kind === "bytes": + return self.generateRandomDynamicType(); + case kind === "address": + return self.generateRandomAddress(); + default: + throw new Error("Couldn't find proper ethereum abi type"); + } + } + + generateRandomBool() { + return _.sample([true, false]); + } + + generateArrayOfType(length, type) { + var arr = []; + for (var i = 0; i < length; i++) arr.push(this.getTypeFuzz(type)); + return arr; + } + + generateRandomDynamicType() { + return Math.random().toString(36).slice(2); + } + + generateRandomStaticBytes(size) { + return utils.randomHex(size); + } + + generateRandomInt(size) { + return utils.toBN(utils.randomHex(size / 8)); + } + + generateRandomAddress() { + return utils.randomHex(20); + } + + registerConsoleCommand() { + const self = this; + self.embark.registerConsoleCommand((cmd, _options) => { + let splitCmd = cmd.split(' '); + let cmdName = splitCmd[0]; + let contractName = splitCmd[1]; + let iterations = splitCmd[2] === undefined ? 1 : splitCmd[2]; + if (cmdName === 'fuzz') { + self.events.request('contracts:contract', contractName, (contract) => { + self.logger.info("-- fuzzed vals for " + contractName); + this.generateFuzz(iterations, contract); + }); + return ""; + } + return false; + }); + } +} + +module.exports = ContractFuzzer; diff --git a/lib/modules/gasEstimator/index.js b/lib/modules/gasEstimator/index.js new file mode 100644 index 000000000..8cde13193 --- /dev/null +++ b/lib/modules/gasEstimator/index.js @@ -0,0 +1,72 @@ +/*global web3*/ +const async = require('async'); +const _ = require('underscore'); +const ContractFuzzer = require('../fuzzer'); + +class GasEstimator { + constructor(embark) { + this.embark = embark; + this.logger = embark.logger; + this.events = embark.events; + this.fuzzer = new ContractFuzzer(embark); + } + + estimateGas(contractName, cb) { + const self = this; + let gasMap = {}; + self.events.request('contracts:contract', contractName, (contract) => { + let fuzzMap = self.fuzzer.generateFuzz(3, contract); + let contractObj = new web3.eth.Contract(contract.abiDefinition, contract.deployedAddress); + async.each(contract.abiDefinition.filter((x) => x.type !== "event"), + (abiMethod, gasCb) => { + let name = abiMethod.name; + if (abiMethod.type === "constructor") { + // already provided for us + gasMap['constructor'] = contract.gasEstimates.creation.totalCost.toString(); + return gasCb(null, name, abiMethod.type); + } else if (abiMethod.type == "fallback") { + gasMap['fallback'] = contract.gasEstimates.external[""].toString(); + return gasCb(null, name, abiMethod.type); + } else if ( + (abiMethod.inputs === null || abiMethod.inputs === undefined || abiMethod.inputs.length === 0) + ) { + // just run it and register it + contractObj.methods[name] + .apply(contractObj.methods[name], []) + .estimateGas((err, gasAmount) => { + if (err) return gasCb(err, name, abiMethod.type); + gasMap[name] = gasAmount; + return gasCb(null, name, abiMethod.type); + }); + } else { + // async concatenate all the fuzz values and their gas cost outputs and check for equality + async.concat(fuzzMap[name], (values, getVarianceCb) => { + contractObj.methods[name].apply(contractObj.methods[name], values) + .estimateGas((err, gasAmount) => { + getVarianceCb(err, gasAmount); + }); + }, (err, variance) => { + if (err) { + return gasCb(err, name, abiMethod.type); + } else if (_.isEqual(variance[0], variance[1]) && _.isEqual(variance[1], variance[2])) { + gasMap[name] = variance[0]; + } else { + gasMap[name] = 'infinite'; + } + return gasCb(null, name, abiMethod.type); + }); + } + }, + (err, name, type) => { + if (err) { + if (type === "constructor" || type === "fallback") name = type; + return cb(err, null, name); + } + cb(null, gasMap, null); + } + ); + }); + } +} + +module.exports = GasEstimator; 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 e433be6d3..2e37f67f8 100644 --- a/lib/modules/ipfs/index.js +++ b/lib/modules/ipfs/index.js @@ -1,6 +1,8 @@ -let UploadIPFS = require('./upload.js'); -let utils = require('../../utils/utils.js'); -let fs = require('../../core/fs.js'); +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 { @@ -8,22 +10,17 @@ class IPFS { 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.storageConfig = embark.config.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.embark = embark; - - this.commandlineDeploy(); - this.setServiceCheck(); - this.addIPFSToEmbarkJS(); - this.addSetProvider(); } commandlineDeploy() { let upload_ipfs = new UploadIPFS({ buildDir: this.buildDir || 'dist/', - storageConfig: this.storageConfig, + storageConfig: this.storageConfig.upload, configIpfsBin: this.storageConfig.ipfs_bin || "ipfs" }); @@ -38,45 +35,49 @@ 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; } self.events.on('check:backOnline:IPFS', function () { - self.logger.info('IPFS node detected..'); + self.logger.info(__('IPFS node detected') + '..'); }); self.events.on('check:wentOffline:IPFS', function () { - self.logger.info('IPFS node is offline..'); + self.logger.info(__('IPFS node is offline') + '..'); }); - if (!self.addCheck) { - return; - } - - self.addCheck('IPFS', function (cb) { - self.logger.trace("Checking IPFS version..."); - utils.httpGetJson('http://' + self.host + ':' + self.port + '/api/v0/version', function (err, body) { + self.events.request("services:register", 'IPFS', function (cb) { + let url = (self.protocol || 'http') + '://' + self.host + ':' + self.port + '/api/v0/version'; + self.logger.trace(`Checking IPFS version on ${url}...`); + 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); + self.logger.trace("IPFS unavailable"); return cb({name: "IPFS ", status: 'off'}); } if (body.Version) { + self.logger.trace("IPFS available"); return cb({name: ("IPFS " + body.Version), status: 'on'}); } + self.logger.trace("IPFS available"); 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; } @@ -89,6 +90,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);"; @@ -96,21 +106,11 @@ 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); + addObjectToConsole() { + let ipfs = IpfsApi(this.host, this.port); + this.events.emit("runcode:register", "ipfs", ipfs); } + } module.exports = IPFS; diff --git a/lib/modules/ipfs/upload.js b/lib/modules/ipfs/upload.js index 36c65e407..8837ffde5 100644 --- a/lib/modules/ipfs/upload.js +++ b/lib/modules/ipfs/upload.js @@ -20,7 +20,7 @@ class IPFS { let ipfs_bin = shelljs.which(self.configIpfsBin); if (ipfs_bin === 'ipfs not found' || !ipfs_bin) { - console.log(('=== WARNING: ' + self.configIpfsBin + ' not found or not in the path. Guessing ~/go/bin/ipfs for path').yellow); + console.log(('=== WARNING: ' + self.configIpfsBin + ' ' + __('not found or not in the path. Guessing %s for path', '~/go/bin/ipfs')).yellow); ipfs_bin = "~/go/bin/ipfs"; } @@ -28,7 +28,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.log(("=== " + __("adding %s to ipfs", self.buildDir)).green); 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); @@ -43,18 +43,18 @@ class IPFS { callback(null, dir_hash); }, 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://localhost:8080/ipfs/" + dir_hash + "/").green); + console.log(("=== " + __("DApp available at") + " http://ipfs.infura.io/ipfs/" + dir_hash + "/").green); callback(); } ], function (err, _result) { if (err) { - console.log("error uploading to ipfs".red); + console.log(__("error uploading to ipfs").red); console.log(err); reject(err); } - else resolve('successfully uploaded to ipfs'); + else resolve(__('successfully uploaded to ipfs')); }); }); } diff --git a/lib/modules/profiler/index.js b/lib/modules/profiler/index.js new file mode 100644 index 000000000..dd34719ef --- /dev/null +++ b/lib/modules/profiler/index.js @@ -0,0 +1,72 @@ +const asciiTable = require('ascii-table'); +const GasEstimator = require('../gasEstimator'); + +class Profiler { + constructor(embark) { + this.embark = embark; + this.logger = embark.logger; + this.events = embark.events; + this.gasEstimator = new GasEstimator(embark); + + this.registerConsoleCommand(); + } + + profile(contractName, contract) { + const self = this; + let table = new asciiTable(contractName); + table.setHeading('Function', 'Payable', 'Mutability', 'Inputs', 'Outputs', 'Gas Estimates'); + self.gasEstimator.estimateGas(contractName, function(err, gastimates, name) { + if (err) { + self.logger.error('error found in method: ', name); + self.logger.error(JSON.stringify(err)); + return; + } + contract.abiDefinition.forEach((abiMethod) => { + switch(abiMethod.type) { + case "constructor": + table.addRow("constructor", abiMethod.payable, abiMethod.stateMutability, self.formatParams(abiMethod.inputs), self.formatParams(abiMethod.outputs), gastimates['constructor']); + break; + case "fallback": + table.addRow("fallback", abiMethod.payable, abiMethod.stateMutability, self.formatParams(abiMethod.inputs), self.formatParams(abiMethod.outputs), gastimates['fallback']); + break; + default: + table.addRow(abiMethod.name, abiMethod.payable, abiMethod.stateMutability, self.formatParams(abiMethod.inputs), self.formatParams(abiMethod.outputs), gastimates[abiMethod.name]); + } + }); + self.logger.info(table.toString()); + }); + } + + formatParams(params) { + if (!params || !params.length) { + return "()"; + } + let paramString = "("; + let mappedParams = params.map(param => param.type); + paramString += mappedParams.join(','); + paramString += ")"; + return paramString; + } + + registerConsoleCommand() { + const self = this; + self.embark.registerConsoleCommand((cmd, _options) => { + let cmdName = cmd.split(' ')[0]; + let contractName = cmd.split(' ')[1]; + if (cmdName === 'profile') { + self.events.request('contracts:contract', contractName, (contract) => { + if (!contract.deployedAddress) { + self.logger.info("-- couldn't profile " + contractName + " - it's not deployed or could be an interface"); + return ""; + } + self.logger.info("-- profile for " + contractName); + this.profile(contractName, contract); + }); + return ""; + } + return false; + }); + } +} + +module.exports = Profiler; diff --git a/lib/modules/solidity/index.js b/lib/modules/solidity/index.js index 066c22c88..c70d51c10 100644 --- a/lib/modules/solidity/index.js +++ b/lib/modules/solidity/index.js @@ -6,7 +6,11 @@ class Solidity { constructor(embark, options) { this.logger = embark.logger; this.events = embark.events; - this.contractDirectories = options.contractDirectories; + this.ipc = options.ipc; + this.contractDirectories = embark.config.contractDirectories; + this.solcAlreadyLoaded = false; + this.solcW = null; + this.useDashboard = options.useDashboard; embark.registerCompiler(".sol", this.compile_solidity.bind(this)); } @@ -17,7 +21,6 @@ class Solidity { } let self = this; let input = {}; - let solcW; async.waterfall([ function prepareInput(callback) { async.each(contractFiles, @@ -31,7 +34,7 @@ class Solidity { file.content(function(fileContent) { if (!fileContent) { - self.logger.error('Error while loading the content of ' + filename); + self.logger.error(__('Error while loading the content of ') + filename); return fileCb(); } input[filename] = {content: fileContent.replace(/\r\n/g, '\n')}; @@ -44,19 +47,19 @@ class Solidity { ); }, function loadCompiler(callback) { - // TODO: there ino need to load this twice - solcW = new SolcW({logger: self.logger, events: self.events}); - if (solcW.isCompilerLoaded()) { + if (self.solcAlreadyLoaded) { return callback(); } + self.solcW = new SolcW({logger: self.logger, events: self.events, ipc: self.ipc, useDashboard: self.useDashboard}); - self.logger.info("loading solc compiler.."); - solcW.load_compiler(function (err) { + self.logger.info(__("loading solc compiler") + ".."); + self.solcW.load_compiler(function (err) { + self.solcAlreadyLoaded = true; callback(err); }); }, function compileContracts(callback) { - self.logger.info("compiling solidity contracts..."); + self.logger.info(__("compiling solidity contracts") + "..."); let jsonObj = { language: 'Solidity', sources: input, @@ -73,7 +76,10 @@ class Solidity { } }; - solcW.compile(jsonObj, function (output) { + self.solcW.compile(jsonObj, function (err, output) { + if(err){ + return callback(err); + } if (output.errors) { for (let i=0; i 0) { - return callback(new Error("error compiling. There are sources available but no code could be compiled, likely due to fatal errors in the solidity code").message); + return callback(new Error(__("error compiling. There are sources available but no code could be compiled, likely due to fatal errors in the solidity code")).message); } let compiled_object = {}; diff --git a/lib/modules/solidity/solcP.js b/lib/modules/solidity/solcP.js index 2beb3305e..934cbad76 100644 --- a/lib/modules/solidity/solcP.js +++ b/lib/modules/solidity/solcP.js @@ -1,41 +1,91 @@ -let solc; - const fs = require('fs-extra'); const path = require('path'); const constants = require('../../constants'); const Utils = require('../../utils/utils'); +const ProcessWrapper = require('../../process/processWrapper'); +const PluginManager = require('live-plugin-manager-git-fix').PluginManager; +const NpmTimer = require('../../versions/npmTimer'); -function findImports(filename) { - if (filename.startsWith('http') || filename.startsWith('git')) { - const fileObj = Utils.getExternalContractUrl(filename); - filename = fileObj.filePath; + +class SolcProcess extends ProcessWrapper { + + constructor(options){ + super(); + this._logger = options.logger; + this._showSpinner = options.showSpinner === true; } - if (fs.existsSync(filename)) { - return {contents: fs.readFileSync(filename).toString()}; + + findImports(filename) { + if (filename.startsWith('http') || filename.startsWith('git')) { + const fileObj = Utils.getExternalContractUrl(filename); + filename = fileObj.filePath; + } + if (fs.existsSync(filename)) { + return {contents: fs.readFileSync(filename).toString()}; + } + if (fs.existsSync(path.join('./node_modules/', filename))) { + return {contents: fs.readFileSync(path.join('./node_modules/', filename)).toString()}; + } + if (fs.existsSync(path.join(constants.httpContractsDirectory, filename))) { + return {contents: fs.readFileSync(path.join(constants.httpContractsDirectory, filename)).toString()}; + } + return {error: 'File not found'}; } - if (fs.existsSync(path.join('./node_modules/', filename))) { - return {contents: fs.readFileSync(path.join('./node_modules/', filename)).toString()}; + + installAndLoadCompiler(solcVersion, packagePath){ + let self = this; + return new Promise((resolve, reject) => { + let manager = new PluginManager({pluginsPath: packagePath}); + let timer; + if (!fs.existsSync(packagePath)) { + timer = new NpmTimer({logger: self._logger, packageName: 'solc', version: solcVersion, showSpinner: self._showSpinner}); + } + + if(timer) timer.start(); + manager.install('solc', solcVersion).then(() => { + self.solc = manager.require('solc'); + if(timer) timer.end(); + resolve(); + }).catch(reject); + + }); } - if (fs.existsSync(path.join(constants.httpContractsDirectory, filename))) { - return {contents: fs.readFileSync(path.join('./.embark/contracts', filename)).toString()}; + + compile(jsonObj, cb) { + // TODO: only available in 0.4.11; need to make versions warn about this + try { + let output = this.solc.compileStandardWrapper(JSON.stringify(jsonObj), this.findImports); + cb(null, output); + } catch (err) { + cb(err.message); + } } - return {error: 'File not found'}; + + } -process.on('message', function (msg) { - if (msg.action === 'loadCompiler') { - solc = require(msg.solcLocation); - process.send({result: "loadedCompiler"}); +let solcProcess; +process.on('message', (msg) => { + if (msg.action === "init") { + solcProcess = new SolcProcess(msg.options); + return process.send({result: "initiated"}); } - if (msg.action === 'compile') { - // TODO: only available in 0.4.11; need to make versions warn about this - let output = solc.compileStandardWrapper(JSON.stringify(msg.jsonObj), findImports); - process.send({result: "compilation", output: output}); + else if (msg.action === 'loadCompiler') { + solcProcess.solc = require('solc'); + return process.send({result: "loadedCompiler"}); + } + + else if (msg.action == 'installAndLoadCompiler') { + solcProcess.installAndLoadCompiler(msg.solcVersion, msg.packagePath).then(() => { + return process.send({result: "loadedCompiler"}); + }); + } + + else if (msg.action === 'compile') { + solcProcess.compile(msg.jsonObj, (err, output) => { + process.send({result: "compilation-" + msg.id, err: err, output: output}); + }); } }); -process.on('exit', function () { - process.exit(0); -}); - diff --git a/lib/modules/solidity/solcW.js b/lib/modules/solidity/solcW.js index 70a434336..a551ab654 100644 --- a/lib/modules/solidity/solcW.js +++ b/lib/modules/solidity/solcW.js @@ -1,58 +1,91 @@ let utils = require('../../utils/utils.js'); let fs = require('../../core/fs.js'); -let solcProcess; -let compilerLoaded = false; let currentSolcVersion = require('../../../package.json').dependencies.solc; +const ProcessLauncher = require('../../process/processLauncher'); +const uuid = require('uuid/v1'); class SolcW { constructor(options) { this.logger = options.logger; this.events = options.events; + this.ipc = options.ipc; + this.compilerLoaded = false; + this.solcProcess = null; + this.useDashboard = options.useDashboard; } load_compiler(done) { const self = this; - if (compilerLoaded) { - done(); + if (!self.ipc.isClient()) { + return self.load_compiler_internally(done); } - solcProcess = require('child_process').fork(utils.joinPath(__dirname, '/solcP.js')); - solcProcess.once('message', function (msg) { - if (msg.result !== 'loadedCompiler') { - return; + + self.ipc.connect((err) => { + if (err) { + return self.load_compiler_internally(done); } - compilerLoaded = true; + self.compilerLoaded = true; done(); }); + } - this.events.request("version:get:solc", function(solcVersion) { - if (solcVersion === currentSolcVersion) { - solcProcess.send({action: 'loadCompiler', solcLocation: 'solc'}); - } else { - self.events.request("version:getPackageLocation", "solc", solcVersion, function(err, location) { + load_compiler_internally(done) { + const self = this; + if (this.compilerLoaded) { + return done(); + } + this.solcProcess = new ProcessLauncher({ + modulePath: utils.joinPath(__dirname, 'solcP.js'), + logger: self.logger, + events: self.events + }); + + this.solcProcess.once("result", "initiated", () => { + this.events.request("version:get:solc", function(solcVersion) { + if (solcVersion === currentSolcVersion) { + return self.solcProcess.send({action: 'loadCompiler', requirePath: 'solc'}); + } + self.events.request("version:getPackagePath", "solc", solcVersion, function(err, path) { if (err) { return done(err); } - let requirePath = fs.dappPath(location); - solcProcess.send({action: 'loadCompiler', solcLocation: requirePath}); + let requirePath = fs.dappPath(path); + self.solcProcess.send({action: 'installAndLoadCompiler', solcVersion: solcVersion, packagePath: requirePath}); }); - - } + }); }); + + this.solcProcess.once("result", "loadedCompiler", () => { + self.compilerLoaded = true; + done(); + }); + this.solcProcess.send({action: "init", options: {logger: self.logger, showSpinner: !self.useDashboard}}); + + if (this.ipc.isServer()) { + this.ipc.on('compile', self.compile.bind(this)); + } } isCompilerLoaded() { - return (compilerLoaded === true); + return (this.compilerLoaded === true); } compile(jsonObj, done) { - solcProcess.once('message', function (msg) { - if (msg.result !== 'compilation') { - return; + const id = uuid(); + + if (this.ipc.isClient() && this.ipc.connected) { + return this.ipc.request('compile', jsonObj, done); + } + + this.solcProcess.once('result', 'compilation-' + id, (msg) => { + if(msg.err) { + return done(msg.err); } - done(JSON.parse(msg.output)); + done(null, JSON.parse(msg.output)); }); - solcProcess.send({action: 'compile', jsonObj: jsonObj}); + + this.solcProcess.send({action: 'compile', jsonObj: jsonObj, id}); } } diff --git a/lib/modules/specialconfigs/index.js b/lib/modules/specialconfigs/index.js new file mode 100644 index 000000000..0f6dcb91c --- /dev/null +++ b/lib/modules/specialconfigs/index.js @@ -0,0 +1,107 @@ +const stringReplaceAsync = require('string-replace-async'); +const async = require('async'); + +class SpecialConfigs { + + constructor(embark, options) { + this.logger = embark.logger; + this.events = embark.events; + this.buildDir = options.buildDir; + this.embark = embark; + this.contractsConfig = embark.config.contractsConfig; + + this.registerAfterDeployAction(); + this.registerOnDeployAction(); + } + + replaceWithAddresses(cmd, cb) { + const self = this; + let regex = /\$\w+/g; + stringReplaceAsync.seq(cmd, regex, (match) => { + return (new Promise((resolve, reject) => { + let referedContractName = match.slice(1); + self.events.request('contracts:contract', referedContractName, (referedContract) => { + if (!referedContract) { + self.logger.error(referedContractName + ' does not exist'); + self.logger.error("error running cmd: " + cmd); + return reject(new Error("ReferedContractDoesNotExist")); + } + if (referedContract && referedContract.deploy === false) { + self.logger.error(referedContractName + " exists but has been set to not deploy"); + self.logger.error("error running cmd: " + cmd); + return reject(new Error("ReferedContracSetToNotdeploy")); + } + if (referedContract && !referedContract.deployedAddress) { + self.logger.error("couldn't find a valid address for " + referedContractName + ". has it been deployed?"); + self.logger.error("error running cmd: " + cmd); + return reject(new Error("ReferedContractAddressNotFound")); + } + return resolve(referedContract.deployedAddress); + }); + })); + }).then((result) => { + cb(null, result); + }).catch(cb); + } + + registerAfterDeployAction() { + const self = this; + + this.embark.registerActionForEvent("contracts:deploy:afterAll", (cb) => { + let afterDeployCmds = self.contractsConfig.afterDeploy || []; + + async.mapLimit(afterDeployCmds, 1, (cmd, nextMapCb) => { + self.replaceWithAddresses(cmd, nextMapCb); + }, (err, onDeployCode) => { + if (err) { + self.logger.trace(err); + return cb(new Error("error running afterDeploy")); + } + + self.runOnDeployCode(onDeployCode, cb); + }); + }); + } + + runOnDeployCode(onDeployCode, callback) { + const self = this; + async.each(onDeployCode, (cmd, eachCb) => { + self.logger.info("==== executing: " + cmd); + self.events.request('runcode:eval', cmd, (err) => { + if (err && err.message.indexOf("invalid opcode") >= 0) { + self.logger.error('the transaction was rejected; this usually happens due to a throw or a require, it can also happen due to an invalid operation'); + } + eachCb(err); + }); + }, callback); + } + + registerOnDeployAction() { + const self = this; + + this.embark.registerActionForEvent("deploy:contract:deployed", (params, cb) => { + let contract = params.contract; + + if (!contract.onDeploy) { + return cb(); + } + + self.logger.info(__('executing onDeploy commands')); + + let onDeployCmds = contract.onDeploy; + + async.mapLimit(onDeployCmds, 1, (cmd, nextMapCb) => { + self.replaceWithAddresses(cmd, nextMapCb); + }, (err, onDeployCode) => { + if (err) { + return cb(new Error("error running onDeploy for " + contract.className.cyan)); + } + + self.runOnDeployCode(onDeployCode, cb); + }); + }); + } + +} + +module.exports = SpecialConfigs; 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..fbcb5d9da --- /dev/null +++ b/lib/modules/storage/index.js @@ -0,0 +1,224 @@ + +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) { + 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); + } + + checkStorageService(platform, url, callback) { + const self = this; + + // start the upload storage node + self._checkStorageEndpoint(platform, function (err) { + if (!err) { + return callback(null); + } + self._startStorageNode(platform, (err) => { + if (err) { + return callback(err); + } + // Check endpoint again to see if really did start + self._checkStorageEndpoint(platform, (err) => { + if (err) { + return callback(err); + } + callback(null); + }); + }); + }); + } + + startStorageProcesses(){ + let platform = this._storageConfig.upload.provider; + let self = this; + let withErrors = false; + + async.waterfall([ + function _checkStorageService(callback){ + self.checkStorageService(platform, utils.buildUrlFromConfig(self._storageConfig.upload), (err) => { + // log error and continue + if(err){ + self._logger.error(err); + withErrors = true; + } + callback(null); + }); + }, + function checkDappConnectionStorageService(callback){ + // start any dappConnection storage nodes + async.each(self._validDappProviders, function(dappConn, cb) { + if(!dappConn.provider || dappConn.provider === platform) { + return cb(null); + } // don't start the process we've just started above + + self.checkStorageService(dappConn.provider, utils.buildUrlFromConfig(dappConn), (err) => { + // log error and continue + if(err){ + self._logger.error(err); + withErrors = true; + } + cb(null); + }); + }, callback); + } + ], function (){ + let strComplete = __('Finished starting all storage providers'); + if(withErrors){ + strComplete += ', ' + __('with errors.'); + return self._logger.warn(strComplete); + } + self._logger.info(strComplete + '.'); + }); + } +} + +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 07660f4b3..cc44791cc 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,37 +10,29 @@ class Swarm { this.logger = embark.logger; this.events = embark.events; this.buildDir = options.buildDir; - this.storageConfig = options.storageConfig; + this.storageConfig = embark.config.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(); - } + this.providerUrl = utils.buildUrl(options.protocol || options.storageConfig.upload.protocol, options.host || options.storageConfig.upload.host, options.port || options.storageConfig.upload.port); - initSwarmProvider(){ - if(!this.bzz.currentProvider) { - this.bzz.setProvider(`http://${this.host}:${this.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 }); this.embark.registerUploadCommand('swarm', this.upload_swarm.deploy.bind(this.upload_swarm)); } - setServiceCheck() { let self = this; @@ -47,26 +41,22 @@ 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; } this.events.on('check:backOnline:Swarm', function () { - self.logger.info('Swarm node detected...'); + self.logger.info(__('Swarm node detected...')); }); this.events.on('check:wentOffline:Swarm', function () { - self.logger.info('Swarm node is offline...'); + 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.events.request("services:register", 'Swarm', function(cb){ + self.logger.trace(`Checking Swarm availability on ${self.bzz.currentProvider}...`); self.bzz.isAvailable().then(result => { + self.logger.trace("Swarm " + (result ? '':'un') + "available"); return cb({name: "Swarm ", status: result ? 'on':'off'}); }).catch(err => { self.logger.trace("Check Swarm availability error: " + err); @@ -75,38 +65,35 @@ 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) { + if(err){ + return self.logger.error("Error getting package location for p-iteration: " + err); + } + 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 fbe64924a..995cafb90 100644 --- a/lib/modules/swarm/upload.js +++ b/lib/modules/swarm/upload.js @@ -7,16 +7,17 @@ class Swarm { this.buildDir = options.buildDir || 'dist/'; this.bzz = options.bzz; this.storageConfig = options.storageConfig; + this.getUrl = options.getUrl; } deploy() { return new Promise((resolve, reject) => { - console.log("deploying to swarm!"); + console.log(__("deploying to swarm!")); let self = this; let bzz = this.bzz; async.waterfall([ function runCommand(callback) { - console.log(("=== adding " + self.buildDir + " to swarm").green); + console.log(("=== " + __("adding %s to swarm", self.buildDir)).green); bzz.upload({ path: self.buildDir, // path to data / file / directory kind: "directory", // could also be "file" or "data" @@ -31,17 +32,18 @@ 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(); } ], function (err, _result) { if (err) { - console.log("error uploading to swarm".red); + console.log(__("error uploading to swarm").red); console.log(err); return reject(err); } - resolve('successfully uploaded to swarm'); + resolve(__('successfully uploaded to swarm')); }); }); } diff --git a/lib/modules/vyper/index.js b/lib/modules/vyper/index.js index 72683ef9f..6e11d0b33 100644 --- a/lib/modules/vyper/index.js +++ b/lib/modules/vyper/index.js @@ -4,10 +4,10 @@ const path = require('path'); class Vyper { - constructor(embark, options) { + constructor(embark, _options) { this.logger = embark.logger; this.events = embark.events; - this.contractDirectories = options.contractDirectories; + this.contractDirectories = embark.config.contractDirectories; // FIXME: Use array of extensions instead of duplicatiing embark.registerCompiler(".py", this.compile_vyper.bind(this)); @@ -21,10 +21,10 @@ class Vyper { return callback(stderr); } if (code !== 0) { - return callback(`Vyper exited with error code ${code}`); + return callback(__('Vyper exited with error code ') + code); } if (!stdout) { - return callback('Execution returned no result'); + return callback(__('Execution returned no result')); } callback(null, stdout.replace(/\n/g, '')); }); @@ -35,7 +35,15 @@ class Vyper { if (!contractFiles || !contractFiles.length) { return cb(); } - self.logger.info("compiling Vyper contracts..."); + + const vyper = shelljs.which('vyper'); + if (!vyper) { + self.logger.warn(__('%s is not installed on your machine', 'Vyper')); + self.logger.info(__('You can install it by visiting: %s', 'https://vyper.readthedocs.io/en/latest/installing-vyper.html')); + return cb(); + } + self.logger.info(__("compiling Vyper contracts") + "..."); + const compiled_object = {}; async.each(contractFiles, function (file, fileCb) { diff --git a/lib/modules/webserver/index.js b/lib/modules/webserver/index.js index e3a313fec..a13fb1b7a 100644 --- a/lib/modules/webserver/index.js +++ b/lib/modules/webserver/index.js @@ -7,7 +7,6 @@ class WebServer { this.embark = embark; this.logger = embark.logger; this.events = embark.events; - this.addCheck = options.addCheck; this.webServerConfig = embark.config.webServerConfig; if (!this.webServerConfig.enabled) { return; @@ -16,7 +15,7 @@ class WebServer { this.host = options.host || this.webServerConfig.host; this.port = options.port || this.webServerConfig.port; - this.events.emit("status", "Starting Server"); + this.events.emit("status", __("Starting Server")); this.server = new Server({logger: this.logger, host: this.host, port: this.port}); this.setServiceCheck(); @@ -29,17 +28,16 @@ class WebServer { setServiceCheck() { let url = 'http://' + this.host + ':' + this.port; - //embark.registerServiceCheck('WebserverService', function (cb) { - this.addCheck('Webserver', function (cb) { + this.events.request("services:register", 'Webserver', function (cb) { utils.checkIsAvailable(url, function (available) { - let devServer = 'Webserver (' + url + ')'; + let devServer = __('Webserver') + ' (' + url + ')'; let serverStatus = (available ? 'on' : 'off'); return cb({name: devServer, status: serverStatus}); }); }); this.events.on('check:wentOffline:Webserver', () => { - this.logger.info("Webserver is offline"); + this.logger.info(__("Webserver is offline")); }); } @@ -57,7 +55,7 @@ class WebServer { } if (cmd === 'webserver stop') { self.events.request("stop-webserver"); - return "stopping webserver..."; + return __("stopping webserver") + "..."; } return false; }); diff --git a/lib/modules/webserver/server.js b/lib/modules/webserver/server.js index 99c824ac9..9f1c64edb 100644 --- a/lib/modules/webserver/server.js +++ b/lib/modules/webserver/server.js @@ -13,7 +13,7 @@ class Server { start(callback) { if (this.server && this.server.listening) { - this.logger.warn("a webserver is already running at " + ("http://" + this.hostname + ":" + this.port).bold.underline.green); + this.logger.warn(__("a webserver is already running at") + " " + ("http://" + this.hostname + ":" + this.port).bold.underline.green); if (callback) { callback(); } @@ -25,7 +25,7 @@ class Server { serve(req, res, finalhandler(req, res)); }).withShutdown(); - this.logger.info("webserver available at " + ("http://" + this.hostname + ":" + this.port).bold.underline.green); + this.logger.info(__("webserver available at") + " " + ("http://" + this.hostname + ":" + this.port).bold.underline.green); this.server.listen(this.port, this.hostname); if (callback) { callback(); @@ -34,7 +34,7 @@ class Server { stop(callback) { if (!this.server || !this.server.listening) { - this.logger.warn("no webserver is currently running"); + this.logger.warn(__("no webserver is currently running")); if (callback) { callback(); } diff --git a/lib/modules/whisper/index.js b/lib/modules/whisper/index.js index 4546dd24a..a92fb7c65 100644 --- a/lib/modules/whisper/index.js +++ b/lib/modules/whisper/index.js @@ -1,24 +1,34 @@ let utils = require('../../utils/utils.js'); let fs = require('../../core/fs.js'); +let Web3 = require('web3'); class Whisper { - constructor(embark, options) { + constructor(embark, _options) { this.logger = embark.logger; this.events = embark.events; - this.communicationConfig = options.communicationConfig; - this.addCheck = options.addCheck; - this.web3 = options.web3; + this.communicationConfig = embark.config.communicationConfig; + this.web3 = new Web3(); this.embark = embark; + this.connectToProvider(); this.setServiceCheck(); this.addWhisperToEmbarkJS(); this.addSetProvider(); } + connectToProvider() { + let {host, port} = this.communicationConfig.connection; + let web3Endpoint = 'ws://' + host + ':' + port; + this.web3.setProvider(new Web3.providers.WebsocketProvider(web3Endpoint, {headers: {Origin: "http://localhost:8000"}})); + } + setServiceCheck() { const self = this; - self.addCheck('Whisper', function (cb) { + self.events.request("services:register", 'Whisper', function (cb) { + if (!self.web3.currentProvider || self.web3.currentProvider.connection.readyState !== 1) { + return self.connectToProvider(); + } self.web3.shh.getVersion(function (err, version) { if (err || version == "2") { return cb({name: 'Whisper', status: 'off'}); diff --git a/lib/pipeline/pipeline.js b/lib/pipeline/pipeline.js index f9530d09a..7d7a0e544 100644 --- a/lib/pipeline/pipeline.js +++ b/lib/pipeline/pipeline.js @@ -1,7 +1,9 @@ -let fs = require('../core/fs.js'); -let async = require('async'); -var utils = require('../utils/utils.js'); -const webpack = require("webpack"); +const fs = require('../core/fs.js'); +const async = require('async'); +const ProcessLauncher = require('../process/processLauncher'); +const utils = require('../utils/utils.js'); +const constants = require('../constants'); + require("babel-preset-react"); require("babel-preset-es2015"); @@ -17,153 +19,183 @@ class Pipeline { this.events = options.events; this.logger = options.logger; this.plugins = options.plugins; + this.pipelinePlugins = this.plugins.getPluginsFor('pipeline'); } build(abi, contractsJSON, path, callback) { let self = this; + const importsList = {}; + let placeholderPage; - this.buildContracts(contractsJSON); + async.waterfall([ + function createPlaceholderPage(next){ + self.events.request('embark-building-placeholder', (html) => { + fs.mkdirpSync(self.buildDir); // create dist/ folder if not already exists + fs.writeFile(self.buildDir + 'index.html', html, next); + }); + }, + function buildTheContracts(next) { + self.buildContracts(next); + }, + function buildWeb3(next) { + self.buildWeb3JS(next); + }, + function createImportList(next) { + importsList["Embark/EmbarkJS"] = fs.dappPath(".embark", 'embark.js'); + importsList["Embark/web3"] = fs.dappPath(".embark", 'web3_instance.js'); + importsList["Embark/contracts"] = fs.dappPath(".embark/contracts", ''); - self.buildWeb3JS(function() { - - let importsList = {}; - - importsList["Embark/EmbarkJS"] = fs.dappPath(".embark", 'embark.js'); - importsList["Embark/web3"] = fs.dappPath(".embark", 'web3_instance.js'); - - self.plugins.getPluginsProperty('imports', 'imports').forEach(function (importObject) { + self.plugins.getPluginsProperty('imports', 'imports').forEach(function (importObject) { let [importName, importLocation] = importObject; importsList[importName] = importLocation; - }); - - for (let contractName in contractsJSON) { - let contractCode = self.buildContractJS(contractName); - let filePath = fs.dappPath(".embark", contractName + '.js'); - fs.writeFileSync(filePath, contractCode); - importsList["Embark/contracts/" + contractName] = filePath; - } - - // limit:1 due to issues when downloading required files such as web3.js - async.eachOfLimit(self.assetFiles, 1, function (files, targetFile, cb) { - // limit:1 due to issues when downloading required files such as web3.js - async.mapLimit(files, 1, - function(file, fileCb) { - self.logger.trace("reading " + file.filename); - - if (file.filename.indexOf('.js') >= 0) { - - let realCwd; - - async.waterfall([ - - function findImports(next) { - self.webpackRun(file.filename, {}, false, importsList, false, next); - }, - - function changeCwd(next) { - realCwd = utils.pwd(); - process.chdir(fs.embarkPath('')); - next(); - }, - - //function findImportsPhase2(next) { - // console.log("====> findImports_2"); - // self.webpackRun(file.filename, { - // externals: function(context, request, callback) { - // if (request === utils.joinPath(fs.dappPath(), file.filename)) { - // callback(); - // } else { - // //if (request.indexOf('Embark/contracts/') === 0) { - // // let contractName = request.split('/')[2]; - // // let contractCode = self.buildContractJS(contractName); - // // let filePath = utils.joinPath(fs.dappPath(), ".embark", contractName + '.js'); - // // fs.writeFileSync(filePath, contractCode); - // // importsList[request] = filePath; - // //} - // callback(null, "amd " + Math.random()); - // } - // } - // }, true, importsList, next); - //}, - - function runWebpack(next) { - self.webpackRun(file.filename, {}, true, importsList, true, next); - }, - - function changeCwdBack(next) { - process.chdir(realCwd); - next(); - } - - ], function(err, _result) { - if (err) { - process.chdir(realCwd); - self.logger.error(err); - return fileCb(err); - } - if (!fs.existsSync('./.embark/' + file.filename)) { - self.logger.error("couldn't find file: " + file.filename); - return fileCb("couldn't find file: " + file.filename); - } - let fileContent = fs.readFileSync('./.embark/' + file.filename).toString(); - self.runPlugins(file, fileContent, fileCb); - }); - } else { - file.content(function(fileContent) { - self.runPlugins(file, fileContent, fileCb); - }); - } - }, - function (err, contentFiles) { - if (err) { - self.logger.warn('errors found while generating ' + targetFile); - } - let dir = targetFile.split('/').slice(0, -1).join('/'); - self.logger.trace("creating dir " + self.buildDir + dir); - fs.mkdirpSync(self.buildDir + dir); - - // if it's a directory - if (targetFile.slice(-1) === '/' || targetFile.indexOf('.') === -1) { - let targetDir = targetFile; - - if (targetDir.slice(-1) !== '/') { - targetDir = targetDir + '/'; - } - - contentFiles.map(function (file) { - let filename = file.filename.replace(file.basedir + '/', ''); - self.logger.info("writing file " + (self.buildDir + targetDir + filename).bold.dim); - - fs.copySync(file.path, self.buildDir + targetDir + filename, {overwrite: true}); - }); - } else { - let content = contentFiles.map(function (file) { - if (file === undefined) { - return ""; - } - return file.content; - }).join("\n"); - - self.logger.info("writing file " + (self.buildDir + targetFile).bold.dim); - fs.writeFileSync(self.buildDir + targetFile, content); - } - cb(); - } - ); - }, - function (_err, _results) { - callback(); }); - }); + + next(); + }, + function writeContracts(next) { + self.events.request('contracts:list', (_err, contracts) => { + // ensure the .embark/contracts directory exists (create if not exists) + fs.mkdirp(fs.dappPath(".embark/contracts", ''), (err) => { + if(err) return next(err); + + // Create a file .embark/contracts/index.js that requires all contract files + // Used to enable alternate import syntax: + // e.g. import {Token} from 'Embark/contracts' + // e.g. import * as Contracts from 'Embark/contracts' + let importsHelperFile = fs.createWriteStream(fs.dappPath(".embark/contracts", 'index.js')); + importsHelperFile.write('module.exports = {\n'); + + async.eachOf(contracts, (contract, idx, eachCb) => { + self.events.request('code-generator:contract', contract.className, (contractCode) => { + let filePath = fs.dappPath(".embark/contracts", contract.className + '.js'); + importsList["Embark/contracts/" + contract.className] = filePath; + fs.writeFile(filePath, contractCode, eachCb); + + // add the contract to the exports list to support alternate import syntax + importsHelperFile.write(`"${contract.className}": require('./${contract.className}').default`); + if(idx < contracts.length - 1) importsHelperFile.write(',\n'); // add a comma if we have more contracts to add + }); + }, function(){ + importsHelperFile.write('\n}'); // close the module.exports = {} + importsHelperFile.close(next); // close the write stream + }); + }); + }); + }, + function assetFileWrite(next) { + async.eachOf(self.assetFiles, function (files, targetFile, cb) { + async.map(files, + function (file, fileCb) { + self.logger.trace("reading " + file.filename); + + // Not a JS file + if (file.filename.indexOf('.js') < 0) { + return file.content(function (fileContent) { + self.runPlugins(file, fileContent, fileCb); + }); + } + + // JS files + async.waterfall([ + function runWebpack(next) { + const webpackProcess = new ProcessLauncher({ + modulePath: utils.joinPath(__dirname, 'webpackProcess.js'), + logger: self.logger, + events: self.events + }); + webpackProcess.send({action: constants.pipeline.init, options: {}}); + webpackProcess.send({action: constants.pipeline.build, file, importsList}); + + webpackProcess.once('result', constants.pipeline.built, (msg) => { + webpackProcess.kill(); + return next(msg.error); + }); + }, + + function readFile(next) { + fs.readFile('./.embark/' + file.filename, (err, data) => { + if (err) { + return next(err); + } + next(null, data.toString()); + }); + }, + + function runPluginsOnContent(fileContent, next) { + self.runPlugins(file, fileContent, next); + } + + ], function (err, contentFile) { + if (err) { + self.logger.error(err); + return fileCb(err); + } + + fileCb(null, contentFile); + }); + }, + function (err, contentFiles) { + if (err) { + self.logger.error(__('errors found while generating') + ' ' + targetFile); + } + let dir = targetFile.split('/').slice(0, -1).join('/'); + self.logger.trace("creating dir " + self.buildDir + dir); + fs.mkdirpSync(self.buildDir + dir); + + // if it's a directory + if (targetFile.slice(-1) === '/' || targetFile.indexOf('.') === -1) { + let targetDir = targetFile; + + if (targetDir.slice(-1) !== '/') { + targetDir = targetDir + '/'; + } + + async.each(contentFiles, function (file, mapCb) { + let filename = file.filename.replace(file.basedir + '/', ''); + self.logger.info("writing file " + (self.buildDir + targetDir + filename).bold.dim); + + fs.copy(file.path, self.buildDir + targetDir + filename, {overwrite: true}, mapCb); + }, cb); + return; + } + + let content = contentFiles.map(function (file) { + if (file === undefined) { + return ""; + } + return file.content; + }).join("\n"); + + self.logger.info(__("writing file") + " " + (self.buildDir + targetFile).bold.dim); + if(new RegExp(/^index.html?/i).test(targetFile)){ + targetFile = targetFile.replace('index', 'index-temp'); + placeholderPage = targetFile; + } + fs.writeFile(self.buildDir + targetFile, content, cb); + } + ); + }, + next); + }, + function removePlaceholderPage(next){ + let placeholderFile = self.buildDir + placeholderPage; + fs.access(self.buildDir + placeholderPage, (err) => { + if (err) return next(); // index-temp doesn't exist, do nothing + + // rename index-temp.htm/l to index.htm/l, effectively replacing our placeholder page + // with the contents of the built index.html page + fs.move(placeholderFile, placeholderFile.replace('index-temp', 'index'), {overwrite: true}, next); + }); + } + ], callback); } runPlugins(file, fileContent, fileCb) { const self = this; - let pipelinePlugins = self.plugins.getPluginsFor('pipeline'); - if (pipelinePlugins.length <= 0) { + if (self.pipelinePlugins.length <= 0) { return fileCb(null, {content: fileContent, filename: file.filename, path: file.path, basedir: file.basedir, modified: true}); } - async.eachSeries(pipelinePlugins, + async.eachSeries(self.pipelinePlugins, function(plugin, pluginCB) { if (file.options && file.options.skipPipeline) { return pluginCB(); @@ -182,140 +214,44 @@ class Pipeline { ); } - webpackRun(filename, options, includeModules, importsList, detectErrors, callback) { - let defaultOptions = { - entry: fs.dappPath(filename), - output: { - libraryTarget: 'umd', - path: fs.dappPath('.embark'), - filename: filename + buildContracts(cb) { + const self = this; + + async.waterfall([ + function makeDirectory(next) { + fs.mkdirp(fs.dappPath(self.buildDir, 'contracts'), (err, _result) => { + next(err); + }); }, - resolve: { - alias: importsList, - modules: [ - fs.embarkPath('node_modules'), - fs.dappPath('node_modules') - ] + function getContracts(next) { + self.events.request('contracts:list', (err, contracts) => { + next(err, contracts); + }); }, - externals: function(context, request, callback) { - callback(); + function writeContractsJSON(contracts, next) { + async.each(contracts, (contract, eachCb) => { + fs.writeJson(fs.dappPath(self.buildDir, 'contracts', contract.className + ".json"), contract, {spaces: 2}, eachCb); + }, () => { next(); }); } - }; - - let webpackOptions = utils.recursiveMerge(defaultOptions, options); - - if (includeModules) { - webpackOptions.module = { - rules: [ - { - test: /\.css$/, - use: [{loader: "style-loader"}, {loader: "css-loader"}] - }, - { - test: /\.scss$/, - use: [{loader: "style-loader"}, {loader: "css-loader"}] - }, - { - test: /\.(png|woff|woff2|eot|ttf|svg)$/, - loader: 'url-loader?limit=100000' - }, - { - test: /\.js$/, - loader: "babel-loader", - exclude: /(node_modules|bower_components)/, - options: { - presets: ['babel-preset-es2016', 'babel-preset-es2017', 'babel-preset-react'].map(require.resolve), - plugins: ["babel-plugin-webpack-aliases"].map(require.resolve), - compact: false - } - } - ] - }; - } - - webpack(webpackOptions).run((_err, _stats) => { - if (!detectErrors) { - return callback(); - } - - if (_stats.hasErrors()) { - return callback(_stats.toJson().errors.join("\n")); - } - callback(); - }); - } - - buildContracts(contractsJSON) { - fs.mkdirpSync(fs.dappPath(this.buildDir, 'contracts')); - - for (let className in contractsJSON) { - let contract = contractsJSON[className]; - fs.writeJSONSync(fs.dappPath(this.buildDir, 'contracts', className + ".json"), contract, {spaces: 2}); - } - } - - buildContractJS(contractName) { - let contractJSON = fs.readFileSync(fs.dappPath(this.buildDir, 'contracts', contractName + '.json')).toString(); - - let contractCode = ""; - contractCode += "import web3 from 'Embark/web3';\n"; - contractCode += "import EmbarkJS from 'Embark/EmbarkJS';\n"; - contractCode += "let " + contractName + "JSONConfig = " + contractJSON + ";\n"; - contractCode += "let " + contractName + " = new EmbarkJS.Contract(" + contractName + "JSONConfig);\n"; - - contractCode += "\n__embarkContext.execWhenReady(function() {\n"; - contractCode += "\n" + contractName + ".setProvider(web3.currentProvider);\n"; - contractCode += "\n" + contractName + ".options.from = web3.eth.defaultAccount;\n"; - contractCode += "\n});\n"; - - contractCode += "export default " + contractName + ";\n"; - - return contractCode; + ], cb); } buildWeb3JS(cb) { const self = this; - let code = ""; - async.waterfall([ - function getWeb3Location(next) { - self.events.request("version:get:web3", function(web3Version) { - if (web3Version === "1.0.0-beta") { - return next(null, utils.joinPath(fs.embarkPath("js/web3-1.0.min.js"))); - } else { - self.events.request("version:getPackageLocation", "web3", web3Version, function(err, location) { - return next(null, fs.dappPath(location)); - }); - } + function makeDirectory(next) { + fs.mkdirp(fs.dappPath(".embark"), (err, _result) => { + next(err); }); }, - function getImports(web3Location, next) { - web3Location = web3Location.replace(/\\/g, '/'); // Import paths must always have forward slashes - code += "\nimport Web3 from '" + web3Location + "';\n"; - - code += "\n if (typeof web3 !== 'undefined') {"; - code += "\n } else {"; - code += "\n var web3 = new Web3();\n"; - code += "\n }"; - - self.events.request('provider-code', function(providerCode) { - code += providerCode; - code += "\nglobal.__embarkContext = __mainContext.__loadManagerInstance;\n"; - code += "\nwindow.web3 = web3;\n"; - code += "\nexport default web3;\n"; - next(); - }); + function getWeb3Code(next) { + self.events.request('code-generator:web3js', next); }, - function writeFile(next) { - fs.mkdirpSync(fs.dappPath(".embark")); - fs.writeFileSync(fs.dappPath(".embark", 'web3_instance.js'), code); - next(); + function writeFile(code, next) { + fs.writeFile(fs.dappPath(".embark", 'web3_instance.js'), code, next); } - ], function(_err, _result) { - cb(); - }); + ], cb); } - } module.exports = Pipeline; diff --git a/lib/pipeline/watch.js b/lib/pipeline/watch.js index 1f3fc1403..6d028ddca 100644 --- a/lib/pipeline/watch.js +++ b/lib/pipeline/watch.js @@ -27,11 +27,11 @@ class Watch { self.logger.trace('ready to watch contract changes'); }); - this.watchConfigs(function () { + this.watchConfigs(embarkConfig, function () { self.logger.trace('ready to watch config changes'); }); - this.logger.info("ready to watch file changes"); + this.logger.info(__("ready to watch file changes")); } restart() { @@ -41,10 +41,10 @@ class Watch { stop() { this.fileWatchers.forEach(fileWatcher => { - fileWatcher.close(); - fileWatcher = null; + if (fileWatcher.shouldClose) return; + if (fileWatcher.isReady) fileWatcher.close(); + fileWatcher.shouldClose = true; }); - this.fileWatchers = []; } watchAssets(embarkConfig, callback) { @@ -97,10 +97,19 @@ class Watch { ); } - watchConfigs(callback) { + watchConfigs(embarkConfig, callback) { let self = this; - this.watchFiles( - "config/**/contracts.json", + let contractsConfig; + if (typeof embarkConfig.config === 'object' || embarkConfig.config.contracts) { + contractsConfig = embarkConfig.config.contracts; + } else { + let contractsFolder = embarkConfig.config.replace(/\\/g, '/'); + if (contractsFolder.charAt(contractsFolder.length - 1) !== '/') { + contractsFolder += '/'; + } + contractsConfig = [`${contractsFolder}**/contracts.json`, `${contractsFolder}**/contracts.js`]; + } + this.watchFiles(contractsConfig, function (eventName, path) { self.logger.info(`${eventName}: ${path}`); self.events.emit('file-' + eventName, 'config', path); @@ -117,7 +126,7 @@ class Watch { this.logger.trace(files); let configWatcher = chokidar.watch(files, { - ignored: /[\/\\]\./, persistent: true, ignoreInitial: true, followSymlinks: true + ignored: /[\/\\]\.|tmp_/, persistent: true, ignoreInitial: true, followSymlinks: true }); this.fileWatchers.push(configWatcher); @@ -125,7 +134,11 @@ class Watch { .on('add', path => changeCallback('add', path)) .on('change', path => changeCallback('change', path)) .on('unlink', path => changeCallback('remove', path)) - .on('ready', doneCallback); + .once('ready', () => { + configWatcher.isReady = true; + if (configWatcher.shouldClose) configWatcher.close(); + doneCallback(); + }); } } diff --git a/lib/pipeline/webpackProcess.js b/lib/pipeline/webpackProcess.js new file mode 100644 index 000000000..ca917d3c6 --- /dev/null +++ b/lib/pipeline/webpackProcess.js @@ -0,0 +1,121 @@ +const async = require('async'); +const webpack = require('webpack'); +const utils = require('../utils/utils'); +const fs = require('../core/fs'); +const constants = require('../constants'); +const HardSourceWebpackPlugin = require('hard-source-webpack-plugin'); +const ProcessWrapper = require('../process/processWrapper'); + +let webpackProcess; + +class WebpackProcess extends ProcessWrapper { + build(file, importsList, callback) { + const self = this; + let realCwd; + + async.waterfall([ + function findImports(next) { + self.webpackRun(file.filename, {}, false, importsList, false, next); + }, + + function changeCwd(next) { + realCwd = utils.pwd(); + process.chdir(fs.embarkPath('')); + next(); + }, + + function runWebpack(next) { + self.webpackRun(file.filename, {}, true, importsList, true, next); + }, + + function changeCwdBack(next) { + process.chdir(realCwd); + next(); + } + ], (err) => { + process.chdir(realCwd); + callback(err); + }); + } + + + webpackRun(filename, options, includeModules, importsList, detectErrors, callback) { + let defaultOptions = { + entry: fs.dappPath(filename), + output: { + libraryTarget: 'umd', + path: fs.dappPath('.embark'), + filename: filename + }, + resolve: { + alias: importsList, + modules: [ + fs.embarkPath('node_modules'), + fs.dappPath('node_modules') + ] + }, + externals: function (context, request, callback) { + callback(); + }, + plugins: [new HardSourceWebpackPlugin()] + }; + + let webpackOptions = utils.recursiveMerge(defaultOptions, options); + + if (includeModules) { + webpackOptions.module = { + rules: [ + { + test: /\.css$/, + use: [{loader: "style-loader"}, {loader: "css-loader"}] + }, + { + test: /\.scss$/, + use: [{loader: "style-loader"}, {loader: "css-loader"}] + }, + { + test: /\.(png|woff|woff2|eot|ttf|svg)$/, + loader: 'url-loader?limit=100000' + }, + { + test: /\.js$/, + loader: "babel-loader", + exclude: /(node_modules|bower_components)/, + options: { + presets: ['babel-preset-es2016', 'babel-preset-es2017', 'babel-preset-react'].map(require.resolve), + plugins: ["babel-plugin-webpack-aliases"].map(require.resolve), + compact: false + } + } + ] + }; + } + + webpack(webpackOptions).run((err, stats) => { + if (err) { + console.error(err); + } + if (!detectErrors) { + return callback(); + } + + if (stats.hasErrors()) { + return callback(stats.toJson().errors.join("\n")); + } + callback(); + }); + } +} + +process.on('message', (msg) => { + if (msg.action === constants.pipeline.init) { + webpackProcess = new WebpackProcess(msg.options); + return process.send({result: constants.pipeline.initiated}); + } + + if (msg.action === constants.pipeline.build) { + return webpackProcess.build(msg.file, msg.importsList, (err) => { + process.send({result: constants.pipeline.built, error: err}); + }); + } +}); diff --git a/lib/process/eventsWrapper.js b/lib/process/eventsWrapper.js new file mode 100644 index 000000000..de1021585 --- /dev/null +++ b/lib/process/eventsWrapper.js @@ -0,0 +1,55 @@ +const uuid = require('uuid/v1'); +const constants = require('../constants'); + +class Events { + + /** + * Constructs an event wrapper for processes. + * Handles sending an event message to the parent process and waiting for its response + * No need to create an instance of eventsWrapper for your own process, just extend ProcessWrapper + * Then, you an use `this.events.[on|request]` with the usual parameters you would use + */ + constructor() { + this.subscribedEvents = {}; + this.listenToParentProcess(); + } + + listenToParentProcess() { + process.on('message', (msg) => { + if (!msg.event || msg.event !== constants.process.events.response) { + return; + } + if (!this.subscribedEvents[msg.eventId]) { + return; + } + this.subscribedEvents[msg.eventId](msg.result); + }); + } + + sendEvent() { + const eventType = arguments[0]; + const requestName = arguments[1]; + + let args = [].slice.call(arguments, 2); + const eventId = uuid(); + this.subscribedEvents[eventId] = args[args.length - 1]; + args = args.splice(0, args.length - 2); + + process.send({ + event: eventType, + requestName, + args, + eventId: eventId + }); + } + + on() { + this.sendEvent(constants.process.events.on, ...arguments); + } + + request() { + this.sendEvent(constants.process.events.request, ...arguments); + } +} + +module.exports = Events; diff --git a/lib/process/processLauncher.js b/lib/process/processLauncher.js new file mode 100644 index 000000000..9c2c1b1d1 --- /dev/null +++ b/lib/process/processLauncher.js @@ -0,0 +1,218 @@ +const child_process = require('child_process'); +const constants = require('../constants'); +const path = require('path'); +const utils = require('../utils/utils'); + +class ProcessLauncher { + + /** + * Constructor of ProcessLauncher. Forks the module and sets up the message handling + * @param {Object} options Options tp start the process + * * modulePath {String} Absolute path to the module to fork + * * logger {Object} Logger + * * events {Function} Events Emitter instance + * @return {ProcessLauncher} The ProcessLauncher instance + */ + constructor(options) { + this.name = path.basename(options.modulePath); + this.process = child_process.fork(options.modulePath); + this.logger = options.logger; + this.events = options.events; + this.silent = options.silent; + this.exitCallback = options.exitCallback; + + this.subscriptions = {}; + this._subscribeToMessages(); + } + + // Subscribes to messages from the child process and delegates to the right methods + _subscribeToMessages() { + const self = this; + this.process.on('message', (msg) => { + if (msg.result === constants.process.log) { + return self._handleLog(msg); + } + if (msg.event) { + return self._handleEvent(msg); + } + self._checkSubscriptions(msg); + }); + + this.process.on('exit', (code) => { + if (self.exitCallback) { + return self.exitCallback(code); + } + if (code) { + this.logger.info(`Child Process ${this.name} exited with code ${code}`); + } + }); + } + + // Translates logs from the child process to the logger + _handleLog(msg) { + if (this.silent && msg.type !== 'error') { + return; + } + if (this.logger[msg.type]) { + return this.logger[msg.type](utils.normalizeInput(msg.message)); + } + this.logger.debug(utils.normalizeInput(msg.message)); + } + + // Handle event calls from the child process + _handleEvent(msg) { + const self = this; + if (!self.events[msg.event]) { + self.logger.warn('Unknown event method called: ' + msg.event); + return; + } + if (!msg.args || !Array.isArray(msg.args)) { + msg.args = []; + } + // Add callback in the args + msg.args.push((result) => { + self.process.send({ + event: constants.process.events.response, + result, + eventId: msg.eventId + }); + }); + self.events[msg.event](msg.requestName, ...msg.args); + } + + // Looks at the subscriptions to see if there is a callback to call + _checkSubscriptions(msg) { + const messageKeys = Object.keys(msg); + const subscriptionsKeys = Object.keys(this.subscriptions); + let subscriptionsForKey; + let messageKey; + // Find if the message contains a key that we are subscribed to + messageKeys.some(_messageKey => { + return subscriptionsKeys.some(subscriptionKey => { + if (_messageKey === subscriptionKey) { + subscriptionsForKey = this.subscriptions[subscriptionKey]; + messageKey = _messageKey; + return true; + } + return false; + }); + }); + + if (subscriptionsForKey) { + // Find if we are subscribed to one of the values + let subsIndex = []; + const subscriptionsForValue = subscriptionsForKey.filter((sub, index) => { + if (msg[messageKey] === sub.value) { + subsIndex.push(index); + return true; + } + return false; + }); + + if (subscriptionsForValue.length) { + // We are subscribed to that message, call the callback + subscriptionsForValue.forEach((subscription, index) => { + subscription.callback(msg); + + if (subscription.once) { + // Called only once, we can remove it + subscription = null; + this.subscriptions[messageKey].splice(subsIndex[index], 1); + } + }); + } + } + } + + /** + * Subscribe to a message using a key-value pair + * @param {String} key Message key to subscribe to + * @param {String} value Value that the above key must have for the callback to be called + * @param {Function} callback callback(response) + * @return {void} + */ + on(key, value, callback) { + if (this.subscriptions[key]) { + this.subscriptions[key].push({value, callback}); + return; + } + this.subscriptions[key] = [{value, callback}]; + } + + /** + * Same as .on, but only triggers once + * @param {String} key Message key to subscribe to + * @param {String} value Value that the above key must have for the callback to be called + * @param {Function} callback callback(response) + * @return {void} + */ + once(key, value, callback) { + const obj = {value, callback, once: true}; + if (this.subscriptions[key]) { + this.subscriptions[key].push(obj); + return; + } + this.subscriptions[key] = [obj]; + } + + /** + * Unsubscribes from a previously subscribed key-value pair (or key if no value) + * @param {String} key Message key to unsubscribe + * @param {String} value [Optional] Value of the key to unsubscribe + * If there is no value, unsubscribes from all the values of that key + * @return {void} + */ + unsubscribeTo(key, value) { + if (!value) { + this.subscriptions[key] = []; + } + if (this.subscriptions[key]) { + this.subscriptions[key].filter((val, index) => { + if (val.value === value) { + this.subscriptions[key].splice(index, 1); + } + }); + } + } + + /** + * Unsubscribes from all subscriptions + * @return {void} + */ + unsubscribeToAll() { + this.subscriptions = {}; + } + + /** + * Sends a message to the child process. Same as ChildProcess.send() + * @params {Object} message Message to send + * For other parameters, see: + * https://nodejs.org/api/child_process.html#child_process_subprocess_send_message_sendhandle_options_callback + * @return {void} + */ + send() { + if (!this.process.connected) { + return false; + } + return this.process.send(...arguments); + } + + /** + * Disconnects the child process. It will exit on its own + * @return {void} + */ + disconnect() { + this.process.disconnect(); + } + + /** + * Kills the child process + * https://nodejs.org/api/child_process.html#child_process_subprocess_kill_signal + * @return {void} + */ + kill() { + this.process.kill(...arguments); + } +} + +module.exports = ProcessLauncher; diff --git a/lib/process/processWrapper.js b/lib/process/processWrapper.js new file mode 100644 index 000000000..f4eda6954 --- /dev/null +++ b/lib/process/processWrapper.js @@ -0,0 +1,93 @@ +const constants = require('../constants'); +const Events = require('./eventsWrapper'); + +// Override process.chdir so that we have a partial-implementation PWD for Windows +const realChdir = process.chdir; +process.chdir = (...args) => { + if (!process.env.PWD) { + process.env.PWD = process.cwd(); + } + realChdir(...args); +}; + +class ProcessWrapper { + + /** + * Class from which process extend. Should not be instantiated alone. + * Manages the log interception so that all console.* get sent back to the parent process + * Also creates an Events instance. To use it, just do `this.events.[on|request]` + * + * @param {Options} _options Nothing for now + */ + constructor(_options) { + this.interceptLogs(); + this.events = new Events(); + + this.pingParent(); + } + + // Ping parent to see if it is still alive. Otherwise, let's die + pingParent() { + const self = this; + self.retries = 0; + function error() { + if (self.retries > 2) { + self.kill(); + process.exit(); + } + self.retries++; + } + setInterval(() => { + try { + let result = self.send({action: 'ping'}); + if (!result) { + return error(); + } + self.retries = 0; + } catch (e) { + error(); + } + }, 2000); + } + + interceptLogs() { + const context = {}; + context.console = console; + + context.console.log = this._log.bind(this, 'log'); + context.console.warn = this._log.bind(this, 'warn'); + context.console.error = this._log.bind(this, 'error'); + context.console.info = this._log.bind(this, 'info'); + context.console.debug = this._log.bind(this, 'debug'); + context.console.trace = this._log.bind(this, 'trace'); + context.console.dir = this._log.bind(this, 'dir'); + } + + _log(type, ...messages) { + const isHardSource = messages.some(message => { + return (typeof message === 'string' && message.indexOf('hard-source') > -1); + }); + if (isHardSource) { + return; + } + this.send({result: constants.process.log, message: messages, type}); + } + + send() { + if (!process.connected) { + return false; + } + return process.send(...arguments); + } + + kill() { + // Should be implemented by derived class + console.log('Process killed'); + } +} + +process.on('exit', () => { + process.exit(0); +}); + +module.exports = ProcessWrapper; diff --git a/lib/processes/blockchainProcessLauncher.js b/lib/processes/blockchainProcessLauncher.js new file mode 100644 index 000000000..ba30dbd5f --- /dev/null +++ b/lib/processes/blockchainProcessLauncher.js @@ -0,0 +1,54 @@ +const ProcessLauncher = require('../process/processLauncher'); +const utils = require('../utils/utils.js'); +const constants = require('../constants'); + +class BlockchainProcessLauncher { + + constructor (options) { + this.events = options.events; + this.logger = options.logger; + this.normalizeInput = options.normalizeInput; + this.blockchainConfig = options.blockchainConfig; + this.locale = options.locale; + this.isDev = options.isDev; + } + + processEnded(code) { + this.logger.error(__('Blockchain process ended before the end of this process. Code: %s', code)); + } + + startBlockchainNode() { + this.logger.info(__('Starting Blockchain node in another process').cyan); + + this.blockchainProcess = new ProcessLauncher({ + modulePath: utils.joinPath(__dirname, '../cmds/blockchain/blockchainProcess.js'), + logger: this.logger, + events: this.events, + silent: this.logger.logLevel !== 'trace', + exitCallback: this.processEnded.bind(this) + }); + this.blockchainProcess.send({ + action: constants.blockchain.init, options: { + blockchainConfig: this.blockchainConfig, + //client: this.client, + // TODO: assume for now it's geth + client: 'geth', + env: this.env, + isDev: this.isDev, + locale: this.locale + } + }); + + this.blockchainProcess.once('result', constants.blockchain.blockchainReady, () => { + this.logger.info(__('Blockchain node is ready').cyan); + this.events.emit(constants.blockchain.blockchainReady); + }); + + this.events.on('exit', () => { + this.blockchainProcess.send('exit'); + }); + } + +} + +module.exports = BlockchainProcessLauncher; diff --git a/lib/processes/storageProcesses/ipfs.js b/lib/processes/storageProcesses/ipfs.js new file mode 100644 index 000000000..7d6715214 --- /dev/null +++ b/lib/processes/storageProcesses/ipfs.js @@ -0,0 +1,134 @@ +const child_process = require('child_process'); +const ProcessWrapper = require('../../process/processWrapper'); +const constants = require('../../constants'); +const StorageUtils = require('./storageUtils'); + +let ipfsProcess; // eslint-disable-line no-unused-vars + +class IPFSProcess extends ProcessWrapper { + constructor(options) { + super(); + + this.cors = options.cors; + this.command = StorageUtils.getCommand('ipfs', options); + + this.checkIPFSVersion(); + this.startIPFSDaemon(); + } + + checkIPFSVersion() { + child_process.exec(this.command + ' --version', {silent: true}, (err, stdout, _stderr) => { + if (err) { + console.error(err); + return; + } + const match = stdout.match(/[0-9]+\.[0-9]+\.[0-9]+/); + if (match[0]) { + const versions = match[0].split('.'); + if (versions[0] <= 0 && versions[1] <= 4 && versions[2] <= 14) { + console.error(`You are using IPFS version ${match[0]} which has an issue with processes.`); + console.error(`Please update to IPFS version 0.4.15 or more recent: https://github.com/ipfs/ipfs-update`); + } + } + }); + } + + _bindChildEvents(childProcess){ + const self = this; + + childProcess.on('error', (err) => { + err = err.toString(); + console.error('IPFS error: ', err); + }); + + childProcess.stderr.on('data', (data) => { + data = data.toString(); + console.log(`IPFS error: ${data}`); + // `ipfs daemon called`, but `ipfs init` had not been run yet + if(!self.initCalled && data.indexOf('no IPFS repo found') > -1) { + self.initCalled = true; + let ipfsInitChild = child_process.spawn(this.command, ['init']); + self._bindChildEvents(ipfsInitChild); + } + }); + + childProcess.stdout.on('data', (data) => { + data = data.toString(); + + // ipfs init just run, and we have a successful result + // re-run `ipfs daemon` + if(self.initCalled && !self.readyCalled && data.indexOf('peer identity:') > -1) { + self.startIPFSDaemon(); + } + else if (!self.readyCalled && data.indexOf('Daemon is ready') > -1) { + self.readyCalled = true; + + // update IPFS cors before spawning a daemon (muhaha) + let ipfsCorsCmd = `${self.command} config --json API.HTTPHeaders.Access-Control-Allow-Origin "[\\"${self.cors.join('\\", \\"')}\\"]"`; + console.trace(`Updating IPFS CORS using command: ${ipfsCorsCmd}`); + child_process.exec(ipfsCorsCmd, {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(self.command + ' 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(self.command + ' 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); + }); + childProcess.on('exit', (code) => { + if (code) { + console.error('IPFS exited with error code ' + code); + } + }); + } + + startIPFSDaemon() { + const self = this; + + // spawn the daemon (muhaha) + this.child = child_process.spawn(this.command, ['daemon']); + + self._bindChildEvents(this.child); + } + + kill() { + if (this.child) { + this.child.kill(); + } + } +} + +process.on('message', (msg) => { + if (msg === 'exit') { + return ipfsProcess.kill(); + } + if (msg.action === constants.storage.init) { + ipfsProcess = new IPFSProcess(msg.options); + } +}); diff --git a/lib/processes/storageProcesses/storageProcessesLauncher.js b/lib/processes/storageProcesses/storageProcessesLauncher.js new file mode 100644 index 000000000..2ac624a01 --- /dev/null +++ b/lib/processes/storageProcesses/storageProcessesLauncher.js @@ -0,0 +1,123 @@ +const fs = require('../../core/fs'); +const shellJs = require('shelljs'); +const utils = require('../../utils/utils'); +const ProcessLauncher = require('../../process/processLauncher'); +const constants = require('../../constants'); +const StorageUtils = require('./storageUtils'); + +class StorageProcessesLauncher { + constructor(options) { + this.logger = options.logger; + 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'); + }); + }); + } + + 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}}`, {storageName, code})); + } + + launchProcess(storageName, callback) { + const self = this; + if (self.processes[storageName]) { + return callback(__('Storage process already started')); + } + const filePath = utils.joinPath(__dirname, `./${storageName}.js`); + fs.access(filePath, (err) => { + if (err) { + return callback(__('No process file for this storage type (%s) exists. Please start the process locally.', storageName)); + } + + const program = shellJs.which(StorageUtils.getCommand(storageName, self.storageConfig)); + if (!program) { + self.logger.warn(__('{{storageName}} is not installed or your configuration is not right', {storageName}).yellow); + self.logger.info(__('You can install and get more information here: ').yellow + StorageUtils.getStorageInstallationSite(storageName).underline); + return callback(__('%s not installed', storageName)); + } + + self.logger.info(__(`Starting %s process`, storageName).cyan); + self.processes[storageName] = new ProcessLauncher({ + modulePath: filePath, + logger: self.logger, + events: self.events, + silent: self.logger.logLevel !== 'trace', + exitCallback: self.processExited.bind(this, storageName) + }); + self.processes[storageName].send({ + action: constants.blockchain.init, options: { + storageConfig: self.storageConfig, + cors: self.buildCors(storageName) + } + }); + + self.processes[storageName].on('result', constants.storage.initiated, (msg) => { + if (msg.error) { + self.processes[storageName].disconnect(); + delete self.processes[storageName]; + return callback(msg.error); + } + self.logger.info(__(`${storageName} process started`).cyan); + callback(); + }); + }); + } +} + +module.exports = StorageProcessesLauncher; diff --git a/lib/processes/storageProcesses/storageUtils.js b/lib/processes/storageProcesses/storageUtils.js new file mode 100644 index 000000000..d701d2b73 --- /dev/null +++ b/lib/processes/storageProcesses/storageUtils.js @@ -0,0 +1,25 @@ +const IPFS = 'ipfs'; +const SWARM = 'swarm'; + +class StorageUtils { + static getCommand(storageName, config) { + if (storageName === IPFS) { + return IPFS; + } + if (storageName === SWARM) { + return config.swarmPath || SWARM; + } + return null; + } + + static getStorageInstallationSite(storageName) { + if (storageName === IPFS) { + return 'https://ipfs.io/docs/install/'; + } + if (storageName === SWARM) { + return 'http://swarm-guide.readthedocs.io/en/latest/installation.html'; + } + } +} + +module.exports = StorageUtils; diff --git a/lib/processes/storageProcesses/swarm.js b/lib/processes/storageProcesses/swarm.js new file mode 100644 index 000000000..36302c17b --- /dev/null +++ b/lib/processes/storageProcesses/swarm.js @@ -0,0 +1,74 @@ +const child_process = require('child_process'); +const ProcessWrapper = require('../../process/processWrapper'); +const constants = require('../../constants'); +const fs = require('../../core/fs'); +const StorageUtils = require('./storageUtils'); + +let swarmProcess; + +class SwarmProcess extends ProcessWrapper { + constructor(options) { + super(); + this.storageConfig = options.storageConfig; + this.cors = options.cors; + this.command = StorageUtils.getCommand('swarm', this.storageConfig); + } + + startSwarmDaemon() { + const self = this; + 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'; + } + + const args = [ + `--bzzaccount=${this.storageConfig.account.address}`, + `--password=${fs.dappPath(this.storageConfig.account.password)}`, + `--corsdomain=${self.cors.join(',')}` + ]; + console.trace('Starting swarm process with arguments: ' + args.join(' ')); + this.child = child_process.spawn(this.command, args); + + this.child.on('error', (err) => { + err = err.toString(); + console.error('Swarm error: ', err); + }); + this.child.stdout.on('data', (data) => { + data = data.toString(); + console.log(`Swarm error: ${data}`); + }); + // Swarm logs appear in stderr somehow + this.child.stderr.on('data', (data) => { + data = data.toString(); + if (!self.readyCalled && data.indexOf('Swarm http proxy started') > -1) { + self.readyCalled = true; + self.send({result: constants.storage.initiated}); + } + console.log('Swarm: ' + data); + }); + this.child.on('exit', (code) => { + if (code) { + console.error('Swarm exited with error code ' + code); + } + }); + } + + kill() { + if (this.child) { + this.child.kill(); + } + } +} + +process.on('message', (msg) => { + if (msg === 'exit') { + return swarmProcess.kill(); + } + if (msg.action === constants.storage.init) { + swarmProcess = new SwarmProcess(msg.options); + const error = swarmProcess.startSwarmDaemon(); + + if (error) { + swarmProcess.send({result: constants.storage.initiated, error}); + } + } +}); diff --git a/lib/tests/run_tests.js b/lib/tests/run_tests.js index 0c41d1e7e..80d238705 100644 --- a/lib/tests/run_tests.js +++ b/lib/tests/run_tests.js @@ -1,80 +1,137 @@ -const utils = require('../utils/utils.js'); +const async = require('async'); +const fs = require('fs-extra'); +const Mocha = require('mocha'); +const path = require('path'); +const assert = require('assert'); +const Test = require('./test'); + +function getFilesFromDir(filePath, cb) { + fs.readdir(filePath, (err, files) => { + if (err) { + return cb(err); + } + const testFiles = files.filter((file) => { + // Only keep the .js files + // TODO: make this a configuration in embark.json + return file.substr(-3) === '.js'; + }).map((file) => { + return path.join(filePath, file); + }); + cb(null, testFiles); + }); +} module.exports = { - run: function(filepath) { - const Mocha = require('mocha'), - fs = require('fs-extra'), - path = require('path'); - - const mocha = new Mocha(); - - if (filepath) { - if (filepath.substr(-1) === '/') { - // Add each .js file to the mocha instance - fs.readdirSync(filepath).filter(function(file){ - // Only keep the .js files - // TODO: make this a configuration in embark.json - return file.substr(-3) === '.js'; - }).forEach(function(file){ - mocha.addFile( - path.join(filepath, file) - ); - }); - } else { - mocha.addFile(filepath); - } - } else { - var testDir = 'test/'; - - // Add each .js file to the mocha instance - fs.readdirSync(testDir).filter(function(file){ - // Only keep the .js files - // TODO: make this a configuration in embark.json - return file.substr(-3) === '.js'; - }).forEach(function(file){ - mocha.addFile( - path.join(testDir, file) - ); - }); + run: function (options) { + process.env.isTest = true; + let failures = 0; + let filePath = options.file; + const loglevel = options.loglevel || 'warn'; + if (!filePath) { + filePath = 'test/'; } - let Test = require('./test.js'); + async.waterfall([ + function checkIfDir(next) { + if (filePath.substr(-1) === '/') { + return next(null, null); + } + fs.stat(filePath, (err, stats) => { + if (err) { + return next(`File "${filePath}" doesn't exist or you don't have permission to it`.red); + } + if (stats.isDirectory()) { + return next(null, null); + } + next(null, [filePath]); + }); + }, + function getFiles(files, next) { + if (files) { + return next(null, files); + } + getFilesFromDir(filePath, (err, files) => { + if (err) { + console.error('Error while reading the directory'); + return next(err); + } + next(null, files); + }); + }, + function setupGlobalNamespace(files, next) { + // TODO put default config + const test = new Test({loglevel}); + global.embark = test; + global.assert = assert; + global.config = test.config.bind(test); - global.assert = require('assert'); + let deprecatedWarning = function () { + console.error(__('%s are not supported anymore', 'EmbarkSpec & deployAll').red); + console.info(__('You can learn about the new revamped tests here: %s', 'https://embark.status.im/docs/testing.html'.underline)); + process.exit(); + }; - let configOptions = { - gasPrice: 1 - }; - global.config = function(config) { - configOptions = utils.recursiveMerge(configOptions, config); - }; - // TODO: check how to pass the options - //global.EmbarkSpec = new Test(options); + global.deployAll = deprecatedWarning; + global.EmbarkSpec = {}; + global.EmbarkSpec.deployAll = deprecatedWarning; - // TODO: this global here might not be necessary at all - global.EmbarkSpec = new Test({}); - global.web3 = global.EmbarkSpec.web3; + // Override require to enable `require('Embark/contracts/contractName');` + const Module = require('module'); + const originalRequire = require('module').prototype.require; + Module.prototype.require = function (requireName) { + if (requireName.startsWith('Embark')) { + return test.require(...arguments); + } + return originalRequire.apply(this, arguments); + }; - global.contract = function(describeName, callback) { - return Mocha.describe(describeName, callback); - }; + // TODO: this global here might not be necessary at all + global.web3 = global.embark.web3; + + global.contract = function (describeName, callback) { + return Mocha.describe(describeName, callback); + }; + + console.info('Compiling contracts'.cyan); + test.init((err) => { + next(err, files); + }); + }, + function executeForAllFiles(files, next) { + async.eachLimit(files, 1, (file, eachCb) => { + const mocha = new Mocha(); + mocha.addFile(file); + + mocha.suite.timeout(0); + + mocha.suite.beforeAll('Wait for deploy', (done) => { + global.embark.onReady((err) => { + done(err); + }); + }); + + mocha.run(function (fails) { + failures += fails; + // Mocha prints the error already + eachCb(); + }); + }, next); + } + ], (err) => { + if (err) { + console.error(err); + process.exit(1); + } + if (failures) { + console.error(` > Total number of failures: ${failures}`.red.bold); + } else { + console.log(' > All tests passed'.green.bold); + } - // Run the tests. - let runner = mocha.run(function(failures) { // Clean contracts folder for next test run fs.remove('.embark/contracts', (_err) => { - process.on('exit', function () { - process.exit(failures); // exit with non-zero status if there were failures - }); - process.exit(); + process.exit(failures); }); }); - - runner.on('suite', function() { - global.assert = require('assert'); - global.EmbarkSpec = new Test({simulatorOptions: configOptions}); - global.web3 = global.EmbarkSpec.web3; - }); - } }; diff --git a/lib/tests/test.js b/lib/tests/test.js index 7fc4f2e4a..2cd5d7fac 100644 --- a/lib/tests/test.js +++ b/lib/tests/test.js @@ -1,108 +1,343 @@ -var async = require('async'); -//require("../utils/debug_util.js")(__filename, async); -var Web3 = require('web3'); -var Engine = require('../core/engine.js'); -var RunCode = require('../core/runCode.js'); -var TestLogger = require('./test_logger.js'); +const async = require('async'); +const Engine = require('../core/engine.js'); +const TestLogger = require('./test_logger.js'); +const Web3 = require('web3'); +const constants = require('../constants'); +const Events = require('../core/events'); +const cloneDeep = require('clone-deep'); +const AccountParser = require('../contracts/accountParser'); +const Provider = require('../contracts/provider'); +const utils = require('../utils/utils'); -var getSimulator = function() { +const EmbarkJS = require('../../js/embark_node'); + +function getSimulator() { try { - var sim = require('ethereumjs-testrpc'); - return sim; + return require('ganache-cli'); } catch (e) { + const moreInfo = 'For more information see https://github.com/trufflesuite/ganache-cli'; if (e.code === 'MODULE_NOT_FOUND') { - console.log('Simulator not found; Please install it with "npm install ethereumjs-testrpc --save"'); - console.log('IMPORTANT: if you using a NodeJS version older than 6.9.1 then you need to install an older version of testrpc "npm install ethereumjs-testrpc@2.0 --save"'); - console.log('For more information see https://github.com/ethereumjs/testrpc'); - // TODO: should throw exception instead - return process.exit(); + console.error(__('Simulator not found; Please install it with "%s"', 'npm install ganache-cli --save')); + console.error(moreInfo); + throw e; } - console.log("=============="); - console.log("Tried to load testrpc but an error occurred. This is a problem with testrpc"); - console.log('IMPORTANT: if you using a NodeJS version older than 6.9.1 then you need to install an older version of testrpc "npm install ethereumjs-testrpc@2.0 --save". Alternatively install node 6.9.1 and the testrpc 3.0'); - console.log("=============="); + console.error("=============="); + console.error(__("Tried to load Ganache CLI (testrpc), but an error occurred. This is a problem with Ganache CLI")); + console.error(moreInfo); + console.error("=============="); throw e; } -}; +} -var Test = function(options) { - this.options = options || {}; - this.simOptions = this.options.simulatorOptions || {}; +class Test { + constructor(options) { + this.options = options || {}; + this.simOptions = {}; + this.contracts = {}; + this.events = new Events(); + this.ready = true; + this.error = false; + this.builtContracts = {}; + this.compiledContracts = {}; - this.engine = new Engine({ - env: this.options.env || 'test', - // TODO: confi will need to detect if this is a obj - embarkConfig: this.options.embarkConfig || 'embark.json', - interceptLogs: false - }); - - this.engine.init({ - logger: new TestLogger({logLevel: 'debug'}) - }); - - this.web3 = new Web3(); -}; - -Test.prototype.deployAll = function(contractsConfig, cb) { - var self = this; - - if (this.simOptions.node) { - this.web3.setProvider(new this.web3.providers.HttpProvider(this.simOptions.node)); - } else { - this.sim = getSimulator(); - this.web3.setProvider(this.sim.provider(this.simOptions)); + this.web3 = new Web3(); } - async.waterfall([ - function getConfig(callback) { - let _versions_default = self.engine.config.contractsConfig.versions; - self.engine.config.contractsConfig = {contracts: contractsConfig, versions: _versions_default}; - callback(); - }, - function startServices(callback) { - //{abiType: 'contracts', embarkJS: false} - self.engine.startService("libraryManager"); - self.engine.startService("codeGenerator"); - self.engine.startService("deployment", { - web3: self.web3, - trackContracts: false - }); - callback(); - }, - function deploy(callback) { - self.engine.events.on('code-generator-ready', function () { - self.engine.events.request('code-contracts-vanila', function(vanillaABI) { - callback(null, vanillaABI); - }); - }); + initWeb3Provider(callback) { + if (this.simOptions.host) { + let {host, port, type, protocol, accounts} = this.simOptions; + if (!protocol) { + protocol = (this.simOptions.type === "rpc") ? 'http' : 'ws'; + } + const endpoint = `${protocol}://${host}:${port}`; + const providerOptions = { + web3: this.web3, + type, + accountsConfig: accounts, + blockchainConfig: this.engine.config.blockchainConfig, + logger: this.engine.logger, + isDev: false, + web3Endpoint: endpoint + }; + console.info(`Connecting to node at ${endpoint}`.cyan); + return utils.pingEndpoint(host, port, type, protocol, this.engine.config.blockchainConfig.wsOrigins.split(',')[0], (err) => { + if (err) { + console.error(`Error connecting to the node, there might be an error in ${endpoint}`.red); + return callback(err); + } + this.provider = new Provider(providerOptions); + return this.provider.startWeb3Provider(callback); + }); + } + if (this.simOptions.accounts) { + this.simOptions.accounts = this.simOptions.accounts.map((account) => { + return {balance: account.hexBalance, secretKey: account.privateKey}; + }); + } + this.sim = getSimulator(); + this.web3.setProvider(this.sim.provider(this.simOptions)); + callback(); + } + + initDeployServices() { + this.engine.startService("web3", { + web3: this.web3 + }); + this.engine.startService("deployment", { + trackContracts: false + //ipcRole: 'client' // disabled for now due to issues with ipc file + }); + } + + init(callback) { + const self = this; + + this.engine = new Engine({ + env: this.options.env || 'test', + // TODO: config will need to detect if this is a obj + embarkConfig: this.options.embarkConfig || 'embark.json', + interceptLogs: false + }); + + this.initWeb3Provider((err) => { + if (err) { + return callback(err); + } + + this.engine.init({ + logger: new TestLogger({logLevel: this.options.loglevel}) + }); + + this.versions_default = this.engine.config.contractsConfig.versions; + // Reset contract config to nothing to make sure we deploy only what we want + this.engine.config.contractsConfig = { + contracts: {}, + versions: this.versions_default + }; + + this.engine.startService("libraryManager"); + this.engine.startService("codeRunner"); + this.initDeployServices(); + this.engine.startService("codeGenerator"); + + this.engine.contractsManager.build(() => { + self.builtContracts = cloneDeep(self.engine.contractsManager.contracts); + self.compiledContracts = cloneDeep(self.engine.contractsManager.compiledContracts); + callback(); + }); + }); + } + + onReady(callback) { + const self = this; + if (this.ready) { + return callback(); + } + if (this.error) { + return callback(this.error); + } + + let errorCallback, readyCallback; + + errorCallback = (err) => { + self.events.removeListener('ready', readyCallback); + callback(err); + }; + + readyCallback = () => { + self.events.removeListener('deployError', errorCallback); + callback(); + }; + + this.events.once('ready', readyCallback); + this.events.once('deployError', errorCallback); + } + + checkDeploymentOptions(options, callback) { + const self = this; + if (!options.deployment) { + if (!self.simOptions.host && !self.simOptions.accounts) { + return callback(); + } + self.simOptions = {}; + } else { + self.simOptions = {}; + let resetServices = false; + if (options.deployment.accounts) { + // Account setup + self.simOptions.accounts = AccountParser.parseAccountsConfig(options.deployment.accounts, self.web3); + resetServices = true; + } + if (options.deployment.host && options.deployment.port && options.deployment.type) { + if (options.deployment.type !== 'rpc' && options.deployment.type !== 'ws') { + callback(__("contracts config error: unknown deployment type %s", options.deployment.type)); + } + Object.assign(self.simOptions, {host: options.deployment.host, port: options.deployment.port, type: options.deployment.type}); + resetServices = true; + } + if (!resetServices) { + return callback(); + } + } + self.initWeb3Provider((err) => { + if (err) { + return callback(err); + } + self.initDeployServices(); + callback(); + }); + } + + config(options, callback) { + const self = this; + if (typeof (options) === 'function') { + callback = options; + options = {}; + } + if (!callback) { + callback = function () { + }; + } + if (!options.contracts) { + options.contracts = {}; + } + self.ready = false; + + async.waterfall([ + function checkDeploymentOpts(next) { + self.checkDeploymentOptions(options, next); + }, + function resetContracts(next) { + self.engine.contractsManager.contracts = cloneDeep(self.builtContracts); + self.engine.contractsManager.compiledContracts = cloneDeep(self.compiledContracts); + next(); + }, + function deploy(next) { + self._deploy(options, (err, accounts) => { + if (err) { + self.events.emit('deployError', err); + self.error = err; + return next(err); + } + self.ready = true; + self.error = false; + self.events.emit('ready'); + next(null, accounts); + }); + } + ], (err, accounts) => { + if (err) { + process.exit(1); + } + callback(null, accounts); + }); + } + + _deploy(config, callback) { + const self = this; + async.waterfall([ + function getConfig(next) { + self.engine.config.contractsConfig = {contracts: config.contracts, versions: self.versions_default}; + self.engine.events.emit(constants.events.contractConfigChanged, self.engine.config.contractsConfig); + next(); + }, + function getAccounts(next) { + self.web3.eth.getAccounts(function (err, accounts) { + if (err) { + return next(err); + } + self.accounts = accounts; + self.web3.eth.defaultAccount = accounts[0]; + next(null, accounts); + }); + }, + function getBalance(accounts, next) { + self.web3.eth.getBalance(self.web3.eth.defaultAccount).then((balance) => { + if (parseInt(balance, 10) === 0) { + console.warn("Warning: default account has no funds"); + } + next(null, accounts); + }).catch((err) => { next(err); }); + }, + function deploy(accounts, next) { self.engine.deployManager.gasLimit = 6000000; self.engine.contractsManager.gasLimit = 6000000; self.engine.deployManager.fatalErrors = true; self.engine.deployManager.deployOnlyOnConfig = true; - self.engine.deployManager.deployContracts(function(err, _result) { - if (err) { - callback(err); + self.engine.events.request('deploy:contracts', () => { + next(null, accounts); + }); + }, + function createContractObject(accounts, next) { + async.each(Object.keys(self.engine.contractsManager.contracts), (contractName, eachCb) => { + const contract = self.engine.contractsManager.contracts[contractName]; + let data; + if (!self.contracts[contractName]) { + self.contracts[contractName] = {}; + data = ""; + } else { + data = self.contracts[contractName].options.data; } + Object.assign(self.contracts[contractName], new EmbarkJS.Contract({abi: contract.abiDefinition, address: contract.deployedAddress, from: self.web3.eth.defaultAccount, gas: 6000000, web3: self.web3})); + + self.contracts[contractName].address = contract.deployedAddress; + if (self.contracts[contractName].options) { + self.contracts[contractName].options.from = self.contracts[contractName].options.from || self.web3.eth.defaultAccount; + self.contracts[contractName].options.data = data; + self.contracts[contractName].options.gas = 6000000; + } + eachCb(); + }, (err) => { + next(err, accounts); }); } - ], function(err, result) { - if (err) { - console.log('terminating due to error'); - process.exit(1); - } - // this should be part of the waterfall and not just something done at the - // end - self.web3.eth.getAccounts(function(err, accounts) { + ], function (err, accounts) { if (err) { - throw new Error(err); + console.log(__('terminating due to error')); + return callback(err); } - self.web3.eth.defaultAccount = accounts[0]; - RunCode.doEval(result, self.web3); - //cb(); - cb(accounts); + callback(null, accounts); }); - }); -}; + } + + require(module) { + if (module.startsWith('Embark/contracts/')) { + const contractName = module.substr(17); + if (this.contracts[contractName]) { + return this.contracts[contractName]; + } + let contract = this.engine.contractsManager.contracts[contractName]; + if (!contract) { + const contractNames = Object.keys(this.engine.contractsManager.contracts); + // It is probably an instanceof + contractNames.find(contrName => { + // Find a contract with a similar name + if (contractName.indexOf(contrName) > -1) { + contract = this.engine.contractsManager.contracts[contrName]; + return true; + } + return false; + }); + // If still nothing, assign bogus one, we will redefine it anyway on deploy + if (!contract) { + console.warn(__('Could not recognize the contract name "%s"', contractName)); + console.warn(__('If it is an instance of another contract, it will be reassigned on deploy')); + console.warn(__('Otherwise, you can rename the contract to contain the parent contract in the name eg: Token2 for Token')); + contract = this.engine.contractsManager.contracts[contractNames[0]]; + } + } + this.contracts[contractName] = new EmbarkJS.Contract({abi: contract.abiDefinition, address: contract.address, from: this.web3.eth.defaultAccount, gas: 6000000, web3: this.web3}); + this.contracts[contractName].address = contract.address; + this.contracts[contractName].options.data = contract.code; + this.contracts[contractName].options.gas = 6000000; + this.web3.eth.getAccounts().then((accounts) => { + this.contracts[contractName].options.from = contract.from || accounts[0]; + }); + return this.contracts[contractName]; + } + throw new Error(__('Unknown module %s', module)); + } +} module.exports = Test; diff --git a/lib/tests/test_logger.js b/lib/tests/test_logger.js index e30298eb0..9d9fe39fb 100644 --- a/lib/tests/test_logger.js +++ b/lib/tests/test_logger.js @@ -5,21 +5,11 @@ require('colors'); class TestLogger { constructor(options) { this.logLevels = ['error', 'warn', 'info', 'debug', 'trace']; - this.logs = []; this.logLevel = options.logLevel || 'info'; } logFunction() { - this.logs.push(arguments); - //console.dir(arguments[0]); - } - - contractsState() { - this.logs.push(arguments); - } - - availableServices() { - this.logs.push(arguments); + console.log(...arguments); } error(txt) { diff --git a/lib/utils/utils.js b/lib/utils/utils.js index 192c5507d..172423d3f 100644 --- a/lib/utils/utils.js +++ b/lib/utils/utils.js @@ -1,29 +1,23 @@ -let path = require('path'); -let globule = require('globule'); -let merge = require('merge'); let http = require('follow-redirects').http; let https = require('follow-redirects').https; -let shelljs = require('shelljs'); -var tar = require('tar'); -var propose = require('propose'); -const constants = require('../constants'); - -//let fs = require('../core/fs.js'); -let o_fs = require('fs-extra'); function joinPath() { + const path = require('path'); return path.join.apply(path.join, arguments); } function filesMatchingPattern(files) { + const globule = require('globule'); return globule.find(files, {nonull: true}); } function fileMatchesPattern(patterns, intendedPath) { + const globule = require('globule'); return globule.isMatch(patterns, intendedPath); } function recursiveMerge(target, source) { + const merge = require('merge'); return merge.recursive(target, source); } @@ -68,7 +62,60 @@ 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 pingEndpoint(host, port, type, protocol, origin, callback) { + const options = { + protocolVersion: 13, + perMessageDeflate: true, + origin: origin, + host: host, + port: port + }; + if (type === 'ws') { + options.headers = { + 'Sec-WebSocket-Version': 13, + Connection: 'Upgrade', + Upgrade: 'websocket', + 'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits', + Origin: origin + }; + } + let req; + // remove trailing api key from infura, ie rinkeby.infura.io/nmY8WtT4QfEwz2S7wTbl + if (options.host.indexOf('/') > -1){ + options.host = options.host.split('/')[0]; + } + if (protocol === 'https') { + req = require('https').get(options); + } else { + req = require('http').get(options); + } + + req.on('error', (err) => { + callback(err); + }); + + req.on('response', (_response) => { + callback(); + }); + + req.on('upgrade', (_res, _socket, _head) => { + callback(); + }); +} + function runCmd(cmd, options) { + const shelljs = require('shelljs'); let result = shelljs.exec(cmd, options || {silent: true}); if (result.code !== 0) { console.log("error doing.. " + cmd); @@ -81,10 +128,12 @@ function runCmd(cmd, options) { } function cd(folder) { + const shelljs = require('shelljs'); shelljs.cd(folder); } function sed(file, pattern, replace) { + const shelljs = require('shelljs'); shelljs.sed('-i', pattern, replace, file); } @@ -93,6 +142,7 @@ function exit(code) { } function downloadFile(url, dest, cb) { + const o_fs = require('fs-extra'); var file = o_fs.createWriteStream(dest); (url.substring(0,5) === 'https' ? https : http).get(url, function(response) { response.pipe(file); @@ -106,6 +156,8 @@ function downloadFile(url, dest, cb) { } function extractTar(filename, packageDirectory, cb) { + const o_fs = require('fs-extra'); + const tar = require('tar'); o_fs.createReadStream(filename).pipe( tar.x({ strip: 1, @@ -117,6 +169,7 @@ function extractTar(filename, packageDirectory, cb) { } function proposeAlternative(word, _dictionary, _exceptions) { + const propose = require('propose'); let exceptions = _exceptions || []; let dictionary = _dictionary.filter((entry) => { return exceptions.indexOf(entry) < 0; @@ -129,6 +182,7 @@ function pwd() { } function getExternalContractUrl(file) { + const constants = require('../constants'); let url; const RAW_URL = 'https://raw.githubusercontent.com/'; const MALFORMED_ERROR = 'Malformed Github URL for '; @@ -173,6 +227,76 @@ function getExternalContractUrl(file) { }; } +function hexToNumber(hex){ + const Web3 = require('web3'); + return Web3.utils.hexToNumber(hex); +} + +function decodeParams(typesArray, hexString){ + var Web3EthAbi = require('web3-eth-abi'); + return Web3EthAbi.decodeParameters(typesArray, hexString); +} + +function toChecksumAddress(address) { + const Web3 = require('web3'); + return Web3.utils.toChecksumAddress(address); +} + +function sha3(arg) { + const Web3 = require('web3'); + return Web3.utils.sha3(arg); +} + +function normalizeInput(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() + ']'); +} + +/** + * 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, @@ -182,6 +306,10 @@ module.exports = { httpGet: httpGet, httpsGet: httpsGet, httpGetJson: httpGetJson, + httpsGetJson: httpsGetJson, + hexToNumber: hexToNumber, + pingEndpoint, + decodeParams: decodeParams, runCmd: runCmd, cd: cd, sed: sed, @@ -190,5 +318,10 @@ module.exports = { extractTar: extractTar, proposeAlternative: proposeAlternative, pwd: pwd, - getExternalContractUrl + getExternalContractUrl, + toChecksumAddress: toChecksumAddress, + sha3: sha3, + normalizeInput, + buildUrl, + buildUrlFromConfig }; diff --git a/lib/versions/library_manager.js b/lib/versions/library_manager.js index 05bf2879a..b5cc3d8a5 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 ("${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; } }); @@ -40,8 +42,8 @@ class LibraryManager { registerCommands() { const self = this; this.embark.registerConsoleCommand((cmd, _options) => { - if (cmd === "versions") { - let text = ['versions in use:']; + if (cmd === "versions" || cmd === __('versions')) { + let text = [__('versions in use') + ':']; for (let lib in self.versions) { text.push(lib + ": " + self.versions[lib]); } @@ -66,6 +68,9 @@ class LibraryManager { this.embark.events.setCommandHandler('version:getPackageLocation', (libName, version, cb) => { npm.getPackageVersion(libName, version, cb); }); + this.embark.events.setCommandHandler('version:getPackagePath', (libName, version, cb) => { + cb(null, Npm.getPackagePath(libName, version)); + }); } } diff --git a/lib/versions/npm.js b/lib/versions/npm.js index a6d50246b..8d37831f3 100644 --- a/lib/versions/npm.js +++ b/lib/versions/npm.js @@ -1,26 +1,57 @@ -let fs = require('../core/fs.js'); - -let PluginManager = require('live-plugin-manager').PluginManager; +const fs = require('../core/fs.js'); +const PluginManager = require('live-plugin-manager-git-fix').PluginManager; +require('colors'); +const NpmTimer = require('./npmTimer'); class Npm { constructor(options) { - this.logger = options.logger; + this._logger = options.logger; + this._packageName = options.packageName; + this._version = options.version; + this._installing = {}; + } + + static getPackagePath(packageName, version){ + return './.embark/versions/' + packageName + '/' + version + '/' + packageName; + } + + _isInstalling(packageName, version){ + return typeof this._installing[packageName + version] != 'undefined'; } getPackageVersion(packageName, version, callback) { - let packageDirectory = './.embark/versions/' + packageName + '/' + version + '/'; + const packagePath = Npm.getPackagePath(packageName, version); - let manager = new PluginManager({pluginsPath: packageDirectory}); - - if (fs.existsSync(packageDirectory + packageName)) { - return callback(null, packageDirectory + packageName); + // check if this package already exists in the filesystem + if (fs.existsSync(packagePath)) { + return callback(null, packagePath); } - this.logger.info("downloading " + packageName + " " + version + "...."); - manager.install(packageName, version).then((result) => { - callback(null , result.location); - }).catch(callback); + const pluginManager = new PluginManager({pluginsPath: './.embark/versions/' + packageName + '/' + version + '/'}); + + // check if we're already installing this package + if(this._isInstalling(packageName, version)){ + this._installing[packageName + version].push(callback); + }else{ + this._installing[packageName + version] = [callback]; + + const timer = new NpmTimer({logger: this._logger, packageName: packageName, version: version}); + timer.start(); + + // do the package download/install + pluginManager.install(packageName, version).then((result) => { + timer.end(); + this._installing[packageName + version].forEach((cb) => { + cb(null, result.location); + }); + delete this._installing[packageName + version]; + }).catch(err => { + this._installing[packageName + version].forEach((cb) => { + cb(err); + }); + }); + } } } diff --git a/lib/versions/npmTimer.js b/lib/versions/npmTimer.js new file mode 100644 index 000000000..99a84a9c8 --- /dev/null +++ b/lib/versions/npmTimer.js @@ -0,0 +1,99 @@ +const {PerformanceObserver, performance} = require('perf_hooks'); +const _ = require('underscore'); +require('colors'); +const i18n = require('../i18n/i18n.js'); +i18n.setOrDetectLocale('en'); + + +class NpmTimer{ + constructor(options){ + this._logger = (options.logger && typeof options.logger.info == 'function') ? options.logger : console; + this._packageName = options.packageName; + this._version = options.version; + this._showSpinner = options.showSpinner || false; + this._spinnerStyle = options.spinnerStyle || 'dots'; + this._interval = options.interval || 750; + + // define mark and measurement names + this._startMark = 'downloadStart' + this._packageName + this._version; + this._ongoingMark = 'downloadOngoingMark' + this._packageName + this._version; + this._downloadOngoing = 'downloadOngoing' + this._packageName + this._version; + this._endMark = 'downloadEnd' + this._packageName + this._version; + this._downloadComplete = 'downloadComplete' + this._packageName + this._version; + + this.observer.observe({entryTypes: ['measure']}); + + + } + + get observer(){ + if(typeof this._observer == 'undefined'){ + this._observer = new PerformanceObserver((items) => { + let entry; + let strDuration; + + // find any download ongoing measurements we've made + entry = _.last(_.where(items.getEntries(), {name: this._downloadOngoing})); + if(entry){ + // ongoing performance mark + strDuration = __('Downloading and installing {{packageName}} {{version}}... ({{duration}}ms elapsed)', {packageName: this._packageName, version: this._version, duration: entry.duration}); + if(this._spinner) this._spinner.text = strDuration; + } + else{ + // otherwise, find our download complete measurement + entry = _.last(_.where(items.getEntries(), {name: this._downloadComplete})); + + if(entry){ + strDuration = __('Finished downloading and installing {{packageName}} {{version}} in {{duration}}ms', {packageName: this._packageName, version: this._version, duration: entry.duration}); + performance.clearMarks(); + if(this._spinner) this._spinner.succeed(strDuration); + } + } + + // log our measurement and make it red if it has taken too long + if(!this._showSpinner && entry && strDuration){ + if(entry.duration > 4000){ + strDuration = strDuration.red; + } + this._logger.info(strDuration); + } + + }); + } + return this._observer; + } + + start(){ + let self = this; + + const strDownloadStart = __("Downloading and installing {{packageName}} {{version}}...", {packageName: this._packageName, version: this._version}); + if(this._showSpinner){ + const ora = require('ora'); + this._spinner = ora({ + spinner: this._spinnerStyle, + text: strDownloadStart + }).start(); + }else{ + this._logger.info(strDownloadStart); + } + + // mark our start time + performance.mark(this._startMark); + + // function that continually updates the console to show user that we're downloading a library + this._intOngoingDownload = setInterval( + function(){ + performance.mark(self._ongoingMark); + performance.measure(self._downloadOngoing, self._startMark, self._ongoingMark); + }, this._interval); + } + + end(){ + // stop updating console for ongoing download + clearInterval(this._intOngoingDownload); + performance.mark(this._endMark); + performance.measure(this._downloadComplete, this._startMark, this._endMark); + } +} + +module.exports = NpmTimer; diff --git a/package-lock.json b/package-lock.json index fe2098bd0..a4bd6653d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,39 @@ { "name": "embark", - "version": "3.0.10", + "version": "3.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "requires": { + "call-me-maybe": "1.0.1", + "glob-to-regexp": "0.3.0" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz", + "integrity": "sha512-LAQ1d4OPfSJ/BMbI2DuizmYrrkD9JMaTdi2hQTlI53lQ4kRQPyZQRS4CYQ7O66bnBBnP/oYdRxbk++X0xuFU6A==" + }, + "@samverschueren/stream-to-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", + "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "requires": { + "any-observable": "0.3.0" + } + }, + "@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" + }, "@sinonjs/formatio": { "version": "2.0.0", - "resolved": "http://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", "dev": true, "requires": { @@ -19,11 +46,11 @@ "integrity": "sha512-orGL5LXERPYsLov6CWs3Fh6203+dXzJkR7OnddIr2514Hsecwc8xRpzCapshBbKFImCsvS/mk6+FWiN5LyZJAQ==" }, "@types/fs-extra": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.2.tgz", - "integrity": "sha512-Q3FWsbdmkQd1ib11A4XNWQvRD//5KpPoGawA8aB2DR7pWKoW9XQv3+dGxD/Z1eVFze23Okdo27ZQytVFlweKvQ==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-5.0.3.tgz", + "integrity": "sha512-m2QKoRrJnei1s10e1ZfMIa7QcABBVLdQhVUv5+bMRaHhPzxO/IWMmREiags59AqFbI+piWPq/PupTahNS/0kyA==", "requires": { - "@types/node": "10.1.2" + "@types/node": "10.3.2" } }, "@types/lockfile": { @@ -32,16 +59,16 @@ "integrity": "sha512-pD6JuijPmrfi84qF3/TzGQ7zi0QIX+d7ZdetD6jUA6cp+IsCzAquXZfi5viesew+pfpOTIdAVKuh1SHA7KeKzg==" }, "@types/node": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.1.2.tgz", - "integrity": "sha512-bjk1RIeZBCe/WukrFToIVegOf91Pebr8cXYBwLBIsfiGWVQ+ifwWsT59H3RxrWzWrzd1l/Amk1/ioY5Fq3/bpA==" + "version": "10.3.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.3.2.tgz", + "integrity": "sha512-9NfEUDp3tgRhmoxzTpTo+lq+KIVFxZahuRX0LHF/9IzKHaWuoWsIrrJ61zw5cnnlGINX8lqJzXYfQTOICS5Q+A==" }, "@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": "10.1.2" + "@types/node": "10.3.2" } }, "@types/semver": { @@ -54,7 +81,7 @@ "resolved": "https://registry.npmjs.org/@types/tar/-/tar-4.0.0.tgz", "integrity": "sha512-YybbEHNngcHlIWVCYsoj7Oo1JU9JqONuAlt1LlTH/lmL8BMhbzdFUgReY87a05rY1j8mfK47Del+TCkaLAXwLw==", "requires": { - "@types/node": "10.1.2" + "@types/node": "10.3.2" } }, "@types/url-join": { @@ -65,8 +92,15 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=", - "dev": true + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "abstract-leveldown": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz", + "integrity": "sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA==", + "requires": { + "xtend": "4.0.1" + } }, "accepts": { "version": "1.3.5", @@ -75,12 +109,27 @@ "requires": { "mime-types": "2.1.18", "negotiator": "0.6.1" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + } } }, "acorn": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", - "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==" + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.6.2.tgz", + "integrity": "sha512-zUzo1E5dI2Ey8+82egfnttyMlMZ2y0D8xOCO3PNPPlYXpl8NZvF6Qk9L9BEtJs+43FqEmfBViDqc5d1ckRDguw==" }, "acorn-dynamic-import": { "version": "2.0.2", @@ -114,15 +163,20 @@ } } }, + "aes-js": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-0.2.4.tgz", + "integrity": "sha1-lLiBq3FyhtAV+iGeCPtmcJ3aWj0=" + }, "ajv": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.0.tgz", - "integrity": "sha512-VDUX1oSajablmiyFyED9L1DFndg0P9h7p1F+NO8FkIzei6EPrR6Zu1n18rd5P8PqaSRd/FrWv3G1TVBqpM83gA==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.1.tgz", + "integrity": "sha512-pgZos1vgOHDiC7gKNbZW8eKvCnNXARv2oqrGQT7Hzbq5Azp7aZG6DJzADnkuSq7RH6qkXp4J/m68yPX/2uBHyQ==", "requires": { "fast-deep-equal": "2.0.1", "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1", - "uri-js": "4.2.1" + "json-schema-traverse": "0.4.1", + "uri-js": "4.2.2" } }, "ajv-keywords": { @@ -155,11 +209,34 @@ "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=" }, + "ambi": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ambi/-/ambi-2.5.0.tgz", + "integrity": "sha1-fI43K+SIkRV+fOoBy2+RQ9H3QiA=", + "requires": { + "editions": "1.3.4", + "typechecker": "4.5.0" + }, + "dependencies": { + "typechecker": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/typechecker/-/typechecker-4.5.0.tgz", + "integrity": "sha512-bqPE/ck3bVIaXP7gMKTKSHrypT32lpYTpiqzPYeYzdSQnmaGvaGhy7TnN/M/+5R+2rs/kKcp9ZLPRp/Q9Yj+4w==", + "requires": { + "editions": "1.3.4" + } + } + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, "ansi-escapes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", - "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", - "dev": true + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==" }, "ansi-regex": { "version": "2.1.1", @@ -171,6 +248,11 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, + "any-observable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", + "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==" + }, "any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -185,10 +267,26 @@ "normalize-path": "2.1.1" } }, + "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.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "requires": { "sprintf-js": "1.0.3" } @@ -201,13 +299,18 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=" + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" }, "arr-union": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=" }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" + }, "array-find-index": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", @@ -223,7 +326,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, "requires": { "array-uniq": "1.0.3" } @@ -231,8 +333,7 @@ "array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" }, "array-unique": { "version": "0.3.2", @@ -242,18 +343,22 @@ "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "ascii-table": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/ascii-table/-/ascii-table-0.0.9.tgz", + "integrity": "sha1-BqZgTWpV1L9BqaR9mHLXp42jHnM=" }, "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=" }, "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.0.1.tgz", + "integrity": "sha512-aO8EaEgbgqq77IEw+1jfx5c9zTbzvkfuRBuZsSsPnTHMkmd5AI4J6OtITLZFa381jReeaQL67J0GBTUu0+ZTVw==", "requires": { "bn.js": "4.11.8", "inherits": "2.0.3", @@ -266,18 +371,38 @@ "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", "requires": { "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "requires": { + "inherits": "2.0.1" + } + } } }, "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=" }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=" }, + "ast-types": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.5.tgz", + "integrity": "sha512-oJjo+5e7/vEc2FBK8gUalV0pba4L3VdBIs2EKhOLHLcOd2FgQIVQN9xb0eZ9IjEWyAL7vq6fGJxOvVvdCHNyMw==" + }, "async": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", @@ -291,6 +416,14 @@ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" }, + "async-eventemitter": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", + "integrity": "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==", + "requires": { + "async": "2.6.1" + } + }, "async-limiter": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", @@ -312,7 +445,7 @@ "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", "requires": { "browserslist": "1.7.7", - "caniuse-db": "1.0.30000844", + "caniuse-db": "1.0.30000853", "normalize-range": "0.1.2", "num2fraction": "1.2.2", "postcss": "5.2.18", @@ -320,9 +453,9 @@ } }, "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=" }, "aws4": { "version": "1.7.0", @@ -368,7 +501,7 @@ "babel-generator": { "version": "6.26.1", "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha1-GERAjTuPDTWkBOp6wYDwh6YBvZA=", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", "requires": { "babel-messages": "6.23.0", "babel-runtime": "6.26.0", @@ -380,6 +513,16 @@ "trim-right": "1.0.1" } }, + "babel-helper-bindify-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz", + "integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=", + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, "babel-helper-builder-binary-assignment-operator-visitor": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", @@ -432,6 +575,17 @@ "babel-types": "6.26.0" } }, + "babel-helper-explode-class": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz", + "integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=", + "requires": { + "babel-helper-bindify-decorators": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, "babel-helper-function-name": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", @@ -518,7 +672,7 @@ "babel-loader": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.4.tgz", - "integrity": "sha1-40Y5OL1ObVXRwXTFSF1AahiO0BU=", + "integrity": "sha512-/hbyEvPzBJuGpk9o80R0ZyTej6heEOr59GoEUtn8qFKbnx4cJm9FWES6J/iv644sYgrtVw9JJQkjaLW/bqb5gw==", "requires": { "find-cache-dir": "1.0.0", "loader-utils": "1.1.0", @@ -546,11 +700,41 @@ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" }, + "babel-plugin-syntax-async-generators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz", + "integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=" + }, + "babel-plugin-syntax-class-constructor-call": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz", + "integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=" + }, + "babel-plugin-syntax-class-properties": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", + "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=" + }, + "babel-plugin-syntax-decorators": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz", + "integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=" + }, + "babel-plugin-syntax-dynamic-import": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz", + "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=" + }, "babel-plugin-syntax-exponentiation-operator": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=" }, + "babel-plugin-syntax-export-extensions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz", + "integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=" + }, "babel-plugin-syntax-flow": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", @@ -561,11 +745,26 @@ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" + }, "babel-plugin-syntax-trailing-function-commas": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=" }, + "babel-plugin-transform-async-generator-functions": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz", + "integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=", + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-generators": "6.13.0", + "babel-runtime": "6.26.0" + } + }, "babel-plugin-transform-async-to-generator": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", @@ -576,6 +775,39 @@ "babel-runtime": "6.26.0" } }, + "babel-plugin-transform-class-constructor-call": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.24.1.tgz", + "integrity": "sha1-gNwoVQWsBn3LjWxl4vbxGrd2Xvk=", + "requires": { + "babel-plugin-syntax-class-constructor-call": "6.18.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-class-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", + "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-plugin-syntax-class-properties": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-decorators": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz", + "integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=", + "requires": { + "babel-helper-explode-class": "6.24.1", + "babel-plugin-syntax-decorators": "6.13.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, "babel-plugin-transform-es2015-arrow-functions": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", @@ -798,6 +1030,15 @@ "babel-runtime": "6.26.0" } }, + "babel-plugin-transform-export-extensions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz", + "integrity": "sha1-U3OLR+deghhYnuqUbLvTkQm75lM=", + "requires": { + "babel-plugin-syntax-export-extensions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, "babel-plugin-transform-flow-strip-types": { "version": "6.22.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", @@ -807,6 +1048,15 @@ "babel-runtime": "6.26.0" } }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "requires": { + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-runtime": "6.26.0" + } + }, "babel-plugin-transform-react-display-name": { "version": "6.25.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", @@ -888,6 +1138,54 @@ } } }, + "babel-preset-env": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.2", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0", + "browserslist": "3.2.8", + "invariant": "2.2.4", + "semver": "5.5.0" + }, + "dependencies": { + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "requires": { + "caniuse-lite": "1.0.30000856", + "electron-to-chromium": "1.3.48" + } + } + } + }, "babel-preset-es2015": { "version": "6.24.1", "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", @@ -957,6 +1255,39 @@ "babel-preset-flow": "6.23.0" } }, + "babel-preset-stage-1": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-1/-/babel-preset-stage-1-6.24.1.tgz", + "integrity": "sha1-dpLNfc1oSZB+auSgqFWJz7niv7A=", + "requires": { + "babel-plugin-transform-class-constructor-call": "6.24.1", + "babel-plugin-transform-export-extensions": "6.22.0", + "babel-preset-stage-2": "6.24.1" + } + }, + "babel-preset-stage-2": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz", + "integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=", + "requires": { + "babel-plugin-syntax-dynamic-import": "6.18.0", + "babel-plugin-transform-class-properties": "6.24.1", + "babel-plugin-transform-decorators": "6.24.1", + "babel-preset-stage-3": "6.24.1" + } + }, + "babel-preset-stage-3": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz", + "integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=", + "requires": { + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-generator-functions": "6.24.1", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-object-rest-spread": "6.26.0" + } + }, "babel-register": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", @@ -964,7 +1295,7 @@ "requires": { "babel-core": "6.26.3", "babel-runtime": "6.26.0", - "core-js": "2.5.6", + "core-js": "2.5.7", "home-or-tmp": "2.0.0", "lodash": "4.17.10", "mkdirp": "0.5.1", @@ -976,7 +1307,7 @@ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", "requires": { - "core-js": "2.5.6", + "core-js": "2.5.7", "regenerator-runtime": "0.11.1" } }, @@ -1019,10 +1350,27 @@ "to-fast-properties": "1.0.3" } }, + "babelify": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", + "requires": { + "babel-core": "6.26.3", + "object-assign": "4.1.1" + } + }, "babylon": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha1-ry87iPpvXB5MY00aD46sT1WzleM=" + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + }, + "backoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", + "integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=", + "requires": { + "precond": "0.2.3" + } }, "balanced-match": { "version": "1.0.0", @@ -1032,7 +1380,7 @@ "base": { "version": "0.11.2", "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "requires": { "cache-base": "1.0.1", "class-utils": "0.3.6", @@ -1080,12 +1428,9 @@ } }, "base-x": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.4.tgz", - "integrity": "sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA==", - "requires": { - "safe-buffer": "5.1.2" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-1.1.0.tgz", + "integrity": "sha1-QtPXF0dPnqAiB/bRqh9CaRPut6w=" }, "base64-js": { "version": "1.3.0", @@ -1112,17 +1457,34 @@ "big.js": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha1-pfwpi4G54Nyi5FiCR4S2XFK6WI4=" + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" }, "binary-extensions": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=" }, + "binaryextensions": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.1.1.tgz", + "integrity": "sha512-XBaoWE9RW8pPdPQNibZsW2zh8TW6gcarXp1FZPwT8Uop8ScSNldJEWf2k9l3HeTqdrEwsOsFcq74RiJECW34yA==" + }, "bindings": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", - "integrity": "sha1-s0b27PapX1qBXFg5/HzbIlAvHtc=" + "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==" + }, + "bip39": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-2.5.0.tgz", + "integrity": "sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA==", + "requires": { + "create-hash": "1.2.0", + "pbkdf2": "3.0.16", + "randombytes": "2.0.6", + "safe-buffer": "5.1.2", + "unorm": "1.4.1" + } }, "bip66": { "version": "1.1.5", @@ -1146,11 +1508,6 @@ "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", "integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U=" }, - "blessed": { - "version": "0.1.81", - "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz", - "integrity": "sha1-+WLWh+wsNpVwrnGvhDJW5tDKESk=" - }, "block-stream": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", @@ -1167,7 +1524,7 @@ "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=" + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" }, "body-parser": { "version": "1.18.3", @@ -1186,10 +1543,18 @@ "type-is": "1.6.16" } }, + "boom": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", + "requires": { + "hoek": "0.9.1" + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { "balanced-match": "1.0.0", "concat-map": "0.0.1" @@ -1222,22 +1587,16 @@ } } }, - "brfs": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/brfs/-/brfs-1.6.1.tgz", - "integrity": "sha512-OfZpABRQQf+Xsmju8XE9bDjs+uU4vLREGolP7bDgcpsI17QREyZ4Bl+2KLxxx1kCgA0fAIhKQBaBYh+PEcCqYQ==", - "requires": { - "quote-stream": "1.0.2", - "resolve": "1.7.1", - "static-module": "2.2.5", - "through2": "2.0.3" - } - }, "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=" + }, "browserify-aes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", @@ -1322,61 +1681,64 @@ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "requires": { - "caniuse-db": "1.0.30000844", + "caniuse-db": "1.0.30000853", "electron-to-chromium": "1.3.48" } }, "bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-3.1.0.tgz", + "integrity": "sha1-1MJjiL9IBMrHFBQbGUWqR+XrJI4=", "requires": { - "base-x": "3.0.4" + "base-x": "1.1.0" + } + }, + "bs58check": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-1.3.4.tgz", + "integrity": "sha1-xSVABzdJEXcU+gQsMEfrj5FRy/g=", + "requires": { + "bs58": "3.1.0", + "create-hash": "1.2.0" } }, "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.1.0.tgz", + "integrity": "sha512-YkIRgwsZwJWTnyQrsBTWefizHh+8GYj3kbL1BTiAQ/9pwpino0G7B2gp5tx/FUBqUlvtxV85KNR3mwfAtv15Yw==", "requires": { "base64-js": "1.3.0", - "ieee754": "1.1.11", - "isarray": "1.0.0" + "ieee754": "1.1.12" } }, "buffer-alloc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.1.0.tgz", - "integrity": "sha1-BVFNM78WVtNUDGhPZbEgLpDsowM=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", "requires": { - "buffer-alloc-unsafe": "0.1.1", - "buffer-fill": "0.1.1" + "buffer-alloc-unsafe": "1.1.0", + "buffer-fill": "1.0.0" } }, "buffer-alloc-unsafe": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-0.1.1.tgz", - "integrity": "sha1-/+H2dVHdBVc33iUzN7/oU9+rGmo=" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" }, "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" }, - "buffer-equal": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", - "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=" - }, "buffer-fill": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-0.1.1.tgz", - "integrity": "sha512-YgBMBzdRLEfgxJIGu2wrvI2E03tMCFU1p7d1KhB4BOoMN0VxmTFjSyN5JtKt9z8Z9JajMHruI6SE25W96wNv7Q==" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=" }, "buffer-from": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", - "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==" }, "buffer-loader": { "version": "0.0.1", @@ -1393,6 +1755,11 @@ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, + "bufferhelper": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bufferhelper/-/bufferhelper-0.2.0.tgz", + "integrity": "sha1-7C842SU4dpzqKQFIeTXp4h2Bc7M=" + }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -1411,7 +1778,7 @@ "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", "requires": { "collection-visit": "1.0.0", "component-emitter": "1.2.1", @@ -1424,6 +1791,65 @@ "unset-value": "1.0.0" } }, + "cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0=", + "requires": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + }, + "dependencies": { + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" + }, + "normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "requires": { + "prepend-http": "2.0.0", + "query-string": "5.1.1", + "sort-keys": "2.0.0" + } + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + }, + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "requires": { + "decode-uri-component": "0.2.0", + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" + } + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "requires": { + "is-plain-obj": "1.1.0" + } + } + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + }, "caller-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", @@ -1440,9 +1866,9 @@ "dev": true }, "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" }, "camelcase-keys": { "version": "2.1.0", @@ -1468,20 +1894,25 @@ "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", "requires": { "browserslist": "1.7.7", - "caniuse-db": "1.0.30000844", + "caniuse-db": "1.0.30000853", "lodash.memoize": "4.1.2", "lodash.uniq": "4.5.0" } }, "caniuse-db": { - "version": "1.0.30000844", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000844.tgz", - "integrity": "sha1-vKV5jNoraTHWgQDC1p5V+zOMu0E=" + "version": "1.0.30000853", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000853.tgz", + "integrity": "sha1-MpAafWuTqH1Z8Iqu5H6o/27JD98=" + }, + "caniuse-lite": { + "version": "1.0.30000856", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000856.tgz", + "integrity": "sha512-x3mYcApHMQemyaHuH/RyqtKCGIYTgEA63fdi+VBvDz8xUSmRiVWTLeyKcoGQCGG6UPR9/+4qG4OKrTa6aSQRKg==" }, "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.8.0.tgz", + "integrity": "sha1-W8oogdQUN/VLJAfr40iIx7mtT30=" }, "center-align": { "version": "0.1.3", @@ -1507,8 +1938,15 @@ "chardet": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" + }, + "checkpoint-store": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/checkpoint-store/-/checkpoint-store-1.1.0.tgz", + "integrity": "sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY=", + "requires": { + "functional-red-black-tree": "1.0.1" + } }, "chokidar": { "version": "2.0.3", @@ -1537,17 +1975,17 @@ "cids": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/cids/-/cids-0.5.3.tgz", - "integrity": "sha1-miW2l+t2+vgHr87DXEq5Nu370KQ=", + "integrity": "sha512-ujWbNP8SeLKg5KmGrxYZM4c+ttd+wwvegrdtgmbi2KNFUbQN4pqsGZaGQE3rhjayXTbKFq36bYDbKhsnD0eMsg==", "requires": { "multibase": "0.4.0", - "multicodec": "0.2.6", + "multicodec": "0.2.7", "multihashes": "0.4.13" } }, "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "requires": { "inherits": "2.0.3", "safe-buffer": "5.1.2" @@ -1562,7 +2000,7 @@ "clap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", - "integrity": "sha1-TzZ0WzIAhJJVf0ZBLWbVDLmbzlE=", + "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", "requires": { "chalk": "1.1.3" } @@ -1570,7 +2008,7 @@ "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "requires": { "arr-union": "3.1.0", "define-property": "0.2.5", @@ -1592,25 +2030,87 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, "requires": { "restore-cursor": "2.0.0" } }, + "cli-spinners": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", + "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=" + }, + "cli-table": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", + "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", + "requires": { + "colors": "1.0.3" + }, + "dependencies": { + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" + } + } + }, + "cli-truncate": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", + "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=", + "requires": { + "slice-ansi": "0.0.4", + "string-width": "1.0.2" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, "cli-width": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" }, "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + } } }, "clone": { @@ -1618,6 +2118,43 @@ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=" + }, + "clone-deep": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.0.tgz", + "integrity": "sha512-aNJ5/7Bz2IYBb7nIj34TLGk78lBXpXUgV9qsLngtTvJ9+scsZNnlU0OX2S2N4ax/sUQt7sDBkXiGjGJEmNbXOQ==", + "requires": { + "kind-of": "6.0.2", + "shallow-clone": "3.0.0" + } + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "1.0.0" + } + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=" + }, + "cloneable-readable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "requires": { + "inherits": "2.0.3", + "process-nextick-args": "2.0.0", + "readable-stream": "2.3.6" + } + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -1642,6 +2179,22 @@ "integrity": "sha1-56qDAZF+9iGzXYo580jc3R234z4=", "dev": true }, + "coinstring": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/coinstring/-/coinstring-2.3.0.tgz", + "integrity": "sha1-zbYzY6lhUCQEolr7gsLibV/2J6Q=", + "requires": { + "bs58": "2.0.1", + "create-hash": "1.2.0" + }, + "dependencies": { + "bs58": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-2.0.1.tgz", + "integrity": "sha1-VZCNWPGYKrogCPob7Y+RmYopv40=" + } + } + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -1657,29 +2210,29 @@ "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", "requires": { "clone": "1.0.4", - "color-convert": "1.9.1", + "color-convert": "1.9.2", "color-string": "0.3.0" } }, "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", + "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", "requires": { - "color-name": "1.1.3" + "color-name": "1.1.1" } }, "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=" }, "color-string": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", "requires": { - "color-name": "1.1.3" + "color-name": "1.1.1" } }, "colormin": { @@ -1689,7 +2242,7 @@ "requires": { "color": "0.11.4", "css-color-names": "0.0.4", - "has": "1.0.1" + "has": "1.0.3" } }, "colors": { @@ -1698,11 +2251,11 @@ "integrity": "sha512-EDpX3a7wHMWFA7PUHWPHNWqOxIIRSJetuwl0AS5Oi/5FMV8kWm69RTlgm00GKjBO1xFHMtBbL49yRtMMdticBw==" }, "combined-stream": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "0.0.5" } }, "commander": { @@ -1730,7 +2283,7 @@ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "requires": { - "buffer-from": "1.0.0", + "buffer-from": "1.1.0", "inherits": "2.0.3", "readable-stream": "2.3.6", "typedarray": "0.0.6" @@ -1744,6 +2297,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", @@ -1780,9 +2338,9 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=" }, "core-js": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.6.tgz", - "integrity": "sha512-lQUVfQi0aLix2xpyjrrJEvfuYCqPc/HwmTKsC/VNf8q0zsjX7SQZtp4+oRONN5Tsur9GDETPjj+Ub2iDiGZfSQ==" + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" }, "core-util-is": { "version": "1.0.2", @@ -1798,11 +2356,6 @@ "vary": "1.1.2" } }, - "crdts": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/crdts/-/crdts-0.0.1.tgz", - "integrity": "sha1-1G5aB0hfuBs3tAoCu4PqQgMwoOE=" - }, "create-ecdh": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", @@ -1837,20 +2390,39 @@ "sha.js": "2.4.11" } }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "cross-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.2.1.tgz", + "integrity": "sha1-lshZEE113vyWf7XbYkdOdUJrArA=", "requires": { - "lru-cache": "4.1.3", + "node-fetch": "2.1.2", + "whatwg-fetch": "2.0.4" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", "shebang-command": "1.2.0", - "which": "1.3.0" + "which": "1.3.1" + } + }, + "cryptiles": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", + "requires": { + "boom": "0.4.2" } }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha1-OWz58xN/A+S45TLFj2mCVOAPgOw=", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", "requires": { "browserify-cipher": "1.0.1", "browserify-sign": "4.0.4", @@ -1865,6 +2437,11 @@ "randomfill": "1.0.4" } }, + "csextends": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/csextends/-/csextends-1.2.0.tgz", + "integrity": "sha512-S/8k1bDTJIwuGgQYmsRoE+8P+ohV32WhQ0l4zqrc0XDdxOhjQQD7/wTZwCzoZX53jSX3V/qwjT+OkPTxWQcmjg==" + }, "css-color-names": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", @@ -1926,7 +2503,7 @@ "autoprefixer": "6.7.7", "decamelize": "1.2.0", "defined": "1.0.0", - "has": "1.0.1", + "has": "1.0.3", "object-assign": "4.1.1", "postcss": "5.2.18", "postcss-calc": "5.3.1", @@ -1966,6 +2543,11 @@ "source-map": "0.5.7" } }, + "ctype": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=" + }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -1980,36 +2562,48 @@ "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "requires": { - "es5-ext": "0.10.42" + "es5-ext": "0.10.45" } }, + "dargs": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-5.1.0.tgz", + "integrity": "sha1-7H6lDHhWTNNsnV7Bj2Yyn63ieCk=" + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "requires": { "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } } }, + "date-fns": { + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", + "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==" + }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" }, "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "requires": { - "get-stdin": "4.0.1", - "meow": "3.7.0" - } + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "requires": { "ms": "2.0.0" } @@ -2101,7 +2695,7 @@ "file-type": "3.9.0", "get-stream": "2.3.1", "pify": "2.3.0", - "yauzl": "2.9.1" + "yauzl": "2.9.2" }, "dependencies": { "file-type": { @@ -2130,15 +2724,46 @@ "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==" + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "requires": { + "clone": "1.0.4" + } + }, + "deferred-leveldown": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", + "requires": { + "abstract-leveldown": "2.6.3" + } + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "requires": { "is-descriptor": "1.0.2", "isobject": "3.0.1" @@ -2189,9 +2814,23 @@ "object-assign": "4.1.1", "pify": "2.3.0", "pinkie-promise": "2.0.1", - "rimraf": "2.6.2" + "rimraf": "2.2.8" }, "dependencies": { + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -2201,9 +2840,15 @@ } }, "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=" + }, + "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "optional": true }, "depd": { "version": "1.1.2", @@ -2224,6 +2869,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "detect-conflict": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/detect-conflict/-/detect-conflict-1.0.1.tgz", + "integrity": "sha1-CIZXpmqWHAUBnbfEIwiDsca0F24=" + }, "detect-indent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", @@ -2232,20 +2882,21 @@ "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", "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=" }, - "dexie": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/dexie/-/dexie-1.5.1.tgz", - "integrity": "sha1-rDrVoOuvfm5Cdg21hxBBjUp1ZiQ=" - }, "diff": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", - "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=" + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==" }, "diffie-hellman": { "version": "5.0.3", @@ -2257,6 +2908,15 @@ "randombytes": "2.0.6" } }, + "dir-glob": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.0.0.tgz", + "integrity": "sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag==", + "requires": { + "arrify": "1.0.1", + "path-type": "3.0.0" + } + }, "doctrine": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", @@ -2286,19 +2946,24 @@ "create-hmac": "1.1.7" } }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "requires": { - "readable-stream": "2.3.6" - } - }, "duplexer3": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" }, + "eachr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/eachr/-/eachr-2.0.4.tgz", + "integrity": "sha1-Rm98qhBwj2EFCeMsgHqv5X/BIr8=", + "requires": { + "typechecker": "2.1.0" + } + }, + "easy-stack": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.0.tgz", + "integrity": "sha1-EskbMIWjfwuqM26UhurEv5Tj54g=" + }, "ecc-jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", @@ -2308,6 +2973,11 @@ "jsbn": "0.1.1" } }, + "editions": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/editions/-/editions-1.3.4.tgz", + "integrity": "sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg==" + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -2323,6 +2993,11 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.48.tgz", "integrity": "sha1-07DYWTgUBE4JLs4hCPw6ya6kuQA=" }, + "elegant-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", + "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=" + }, "elliptic": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", @@ -2330,13 +3005,70 @@ "requires": { "bn.js": "4.11.8", "brorand": "1.1.0", - "hash.js": "1.1.3", + "hash.js": "1.1.4", "hmac-drbg": "1.0.1", "inherits": "2.0.3", "minimalistic-assert": "1.0.1", "minimalistic-crypto-utils": "1.0.1" } }, + "embark-web3-provider-engine": { + "version": "14.0.6", + "resolved": "https://registry.npmjs.org/embark-web3-provider-engine/-/embark-web3-provider-engine-14.0.6.tgz", + "integrity": "sha512-/F829/RaNqT8AV3TVU/r4cYYyC9bBEY7RM2rhElyBoIhPehRfJr0WblaS8kpK9M6qdb9DpHZWb8EIc3qOJv8kw==", + "requires": { + "async": "2.6.1", + "backoff": "2.5.0", + "clone": "2.1.1", + "cross-fetch": "2.2.1", + "eth-block-tracker": "3.0.1", + "eth-json-rpc-infura": "3.1.2", + "eth-sig-util": "1.4.2", + "ethereumjs-block": "1.7.1", + "ethereumjs-tx": "1.3.4", + "ethereumjs-util": "5.2.0", + "ethereumjs-vm": "2.3.5", + "json-rpc-error": "2.0.0", + "json-stable-stringify": "1.0.1", + "promise-to-callback": "1.0.0", + "readable-stream": "2.3.6", + "request": "2.87.0", + "semaphore": "1.1.0", + "tape": "4.9.1", + "ws": "5.2.0", + "xhr": "2.5.0", + "xtend": "4.0.1" + }, + "dependencies": { + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" + }, + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "ethjs-util": "0.1.6", + "keccak": "1.4.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.2", + "secp256k1": "3.5.0" + } + }, + "ws": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.0.tgz", + "integrity": "sha512-c18dMeW+PEQdDFzkhDsnBAlS4Z8KGStBQQUcQ5mf7Nf689jyGk0594L+i9RaQuf4gog6SvWLJorz2NfSaqxZ7w==", + "requires": { + "async-limiter": "1.0.0" + } + } + } + }, "emojis-list": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", @@ -2347,25 +3079,37 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "0.4.23" + } + }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "requires": { "once": "1.4.0" } }, "enhanced-resolve": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", - "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.0.0.tgz", + "integrity": "sha512-jox/62b2GofV1qTUQTMPEJSDIGycS43evqYzD/KVtEb9OCoki9cnacUPxCrZa7JfPzZSYOCZhu9O9luaMxAX8g==", "requires": { "graceful-fs": "4.1.11", "memory-fs": "0.4.1", - "object-assign": "4.1.1", - "tapable": "0.2.8" + "tapable": "1.0.0" } }, + "envinfo": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-5.10.0.tgz", + "integrity": "sha512-rXbzXWvnQxy+TcqZlARbWVQwgGVVouVJgFZhLVN5htjLxl1thstrP2ZGi0pXC309AbK7gVOPU+ulz/tmpCI7iw==" + }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -2374,6 +3118,15 @@ "prr": "1.0.1" } }, + "error": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/error/-/error-7.0.2.tgz", + "integrity": "sha1-pfdf/02ZJhJt2sDqXcOOaJFTywI=", + "requires": { + "string-template": "0.2.1", + "xtend": "4.0.1" + } + }, "error-ex": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", @@ -2382,10 +3135,32 @@ "is-arrayish": "0.2.1" } }, + "es-abstract": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.3", + "is-callable": "1.1.3", + "is-regex": "1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "requires": { + "is-callable": "1.1.3", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" + } + }, "es5-ext": { - "version": "0.10.42", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.42.tgz", - "integrity": "sha512-AJxO1rmPe1bDEfSR6TJ/FgMFYuTBhR5R57KW58iCkYACMyFbrkqVyzXSurYoScDGvgyMpk7uRF/lPUPPTmsRSA==", + "version": "0.10.45", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz", + "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==", "requires": { "es6-iterator": "2.0.3", "es6-symbol": "3.1.1", @@ -2398,7 +3173,7 @@ "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "requires": { "d": "1.0.0", - "es5-ext": "0.10.42", + "es5-ext": "0.10.45", "es6-symbol": "3.1.1" } }, @@ -2408,7 +3183,7 @@ "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", "requires": { "d": "1.0.0", - "es5-ext": "0.10.42", + "es5-ext": "0.10.45", "es6-iterator": "2.0.3", "es6-set": "0.1.5", "es6-symbol": "3.1.1", @@ -2421,7 +3196,7 @@ "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", "requires": { "d": "1.0.0", - "es5-ext": "0.10.42", + "es5-ext": "0.10.45", "es6-iterator": "2.0.3", "es6-symbol": "3.1.1", "event-emitter": "0.3.5" @@ -2433,7 +3208,7 @@ "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", "requires": { "d": "1.0.0", - "es5-ext": "0.10.42" + "es5-ext": "0.10.45" } }, "es6-weak-map": { @@ -2442,7 +3217,7 @@ "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", "requires": { "d": "1.0.0", - "es5-ext": "0.10.42", + "es5-ext": "0.10.45", "es6-iterator": "2.0.3", "es6-symbol": "3.1.1" } @@ -2457,31 +3232,6 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, - "escodegen": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.1.tgz", - "integrity": "sha512-6hTjO1NAWkHnDk3OqQ4YrCuwwmGHL9S3nPlzBOUG/R44rda3wLNrfvQ5fkSGjyhHFKM7ALPKcKGrwvCLe0lC7Q==", - "requires": { - "esprima": "3.1.3", - "estraverse": "4.2.0", - "esutils": "2.0.2", - "optionator": "0.8.2", - "source-map": "0.6.1" - }, - "dependencies": { - "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "optional": true - } - } - }, "escope": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", @@ -2519,7 +3269,7 @@ "imurmurhash": "0.1.4", "inquirer": "3.3.0", "is-resolvable": "1.1.0", - "js-yaml": "3.11.0", + "js-yaml": "3.12.0", "json-stable-stringify-without-jsonify": "1.0.1", "levn": "0.3.0", "lodash": "4.17.10", @@ -2562,7 +3312,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "1.9.2" } }, "chalk": { @@ -2576,6 +3326,17 @@ "supports-color": "5.4.0" } }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.3", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", @@ -2609,16 +3370,44 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + } + }, "js-yaml": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", - "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", "dev": true, "requires": { "argparse": "1.0.10", "esprima": "4.0.0" } }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -2655,7 +3444,7 @@ "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", "dev": true, "requires": { - "acorn": "5.5.3", + "acorn": "5.6.2", "acorn-jsx": "3.0.1" } }, @@ -2676,7 +3465,7 @@ "esrecurse": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8=", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "requires": { "estraverse": "4.2.0" } @@ -2696,6 +3485,98 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, + "eth-block-tracker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz", + "integrity": "sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug==", + "requires": { + "eth-query": "2.1.2", + "ethereumjs-tx": "1.3.4", + "ethereumjs-util": "5.2.0", + "ethjs-util": "0.1.6", + "json-rpc-engine": "3.7.3", + "pify": "2.3.0", + "tape": "4.9.1" + }, + "dependencies": { + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "ethjs-util": "0.1.6", + "keccak": "1.4.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.2", + "secp256k1": "3.5.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } + } + }, + "eth-ens-namehash": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", + "integrity": "sha1-IprEbsqG1S4MmR58sq74P/D2i88=", + "requires": { + "idna-uts46-hx": "2.3.1", + "js-sha3": "0.5.7" + } + }, + "eth-json-rpc-infura": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eth-json-rpc-infura/-/eth-json-rpc-infura-3.1.2.tgz", + "integrity": "sha512-IuK5Iowfs6taluA/3Okmu6EfZcFMq6MQuyrUL1PrCoJstuuBr3TvVeSy3keDyxfbrjFB34nCo538I8G+qMtsbw==", + "requires": { + "cross-fetch": "2.2.1", + "eth-json-rpc-middleware": "1.6.0", + "json-rpc-engine": "3.7.3", + "json-rpc-error": "2.0.0", + "tape": "4.9.1" + } + }, + "eth-json-rpc-middleware": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz", + "integrity": "sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q==", + "requires": { + "async": "2.6.1", + "eth-query": "2.1.2", + "eth-tx-summary": "3.2.3", + "ethereumjs-block": "1.7.1", + "ethereumjs-tx": "1.3.4", + "ethereumjs-util": "5.2.0", + "ethereumjs-vm": "2.3.5", + "fetch-ponyfill": "4.1.0", + "json-rpc-engine": "3.7.3", + "json-rpc-error": "2.0.0", + "json-stable-stringify": "1.0.1", + "promise-to-callback": "1.0.0", + "tape": "4.9.1" + }, + "dependencies": { + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "ethjs-util": "0.1.6", + "keccak": "1.4.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.2", + "secp256k1": "3.5.0" + } + } + } + }, "eth-lib": { "version": "0.2.8", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", @@ -2706,12 +3587,340 @@ "xhr-request-promise": "0.1.2" } }, - "ethereumjs-testrpc": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/ethereumjs-testrpc/-/ethereumjs-testrpc-6.0.3.tgz", - "integrity": "sha512-lAxxsxDKK69Wuwqym2K49VpXtBvLEsXr1sryNG4AkvL5DomMdeCBbu3D87UEevKenLHBiT8GTjARwN6Yj039gA==", + "eth-query": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/eth-query/-/eth-query-2.1.2.tgz", + "integrity": "sha1-1nQdkAAQa1FRDHLbktY2VFam2l4=", "requires": { - "webpack": "3.12.0" + "json-rpc-random-id": "1.0.1", + "xtend": "4.0.1" + } + }, + "eth-sig-util": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/eth-sig-util/-/eth-sig-util-1.4.2.tgz", + "integrity": "sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA=", + "requires": { + "ethereumjs-abi": "git+https://github.com/ethereumjs/ethereumjs-abi.git#4ea2fdfed09e8f99117d9362d17c6b01b64a2bcf", + "ethereumjs-util": "5.2.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "ethjs-util": "0.1.6", + "keccak": "1.4.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.2", + "secp256k1": "3.5.0" + } + } + } + }, + "eth-tx-summary": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/eth-tx-summary/-/eth-tx-summary-3.2.3.tgz", + "integrity": "sha512-1gZpA5fKarJOVSb5OUlPnhDQuIazqAkI61zlVvf5LdG47nEgw+/qhyZnuj3CUdE/TLTKuRzPLeyXLjaB4qWTRQ==", + "requires": { + "async": "2.6.1", + "bn.js": "4.11.8", + "clone": "2.1.1", + "concat-stream": "1.6.2", + "end-of-stream": "1.4.1", + "eth-query": "2.1.2", + "ethereumjs-block": "1.7.1", + "ethereumjs-tx": "1.3.4", + "ethereumjs-util": "5.2.0", + "ethereumjs-vm": "2.3.4", + "through2": "2.0.3", + "treeify": "1.1.0", + "web3-provider-engine": "13.8.0" + }, + "dependencies": { + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" + }, + "eth-block-tracker": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/eth-block-tracker/-/eth-block-tracker-2.3.1.tgz", + "integrity": "sha512-NamWuMBIl8kmkJFVj8WzGatySTzQPQag4Xr677yFxdVtIxACFbL/dQowk0MzEqIKk93U1TwY3MjVU6mOcwZnKA==", + "requires": { + "async-eventemitter": "github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c", + "eth-query": "2.1.2", + "ethereumjs-tx": "1.3.4", + "ethereumjs-util": "5.2.0", + "ethjs-util": "0.1.6", + "json-rpc-engine": "3.7.3", + "pify": "2.3.0", + "tape": "4.9.1" + }, + "dependencies": { + "async-eventemitter": { + "version": "github:ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c", + "requires": { + "async": "2.6.1" + } + } + } + }, + "ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==" + }, + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "ethjs-util": "0.1.6", + "keccak": "1.4.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.2", + "secp256k1": "3.5.0" + } + }, + "ethereumjs-vm": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.3.4.tgz", + "integrity": "sha512-Y4SlzNDqxrCO58jhp98HdnZVdjOqB+HC0hoU+N/DEp1aU+hFkRX/nru5F7/HkQRPIlA6aJlQp/xIA6xZs1kspw==", + "requires": { + "async": "2.6.1", + "async-eventemitter": "0.2.4", + "ethereum-common": "0.2.0", + "ethereumjs-account": "2.0.5", + "ethereumjs-block": "1.7.1", + "ethereumjs-util": "5.2.0", + "fake-merkle-patricia-tree": "1.0.1", + "functional-red-black-tree": "1.0.1", + "merkle-patricia-tree": "2.3.1", + "rustbn.js": "0.1.2", + "safe-buffer": "5.1.2" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "web3-provider-engine": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/web3-provider-engine/-/web3-provider-engine-13.8.0.tgz", + "integrity": "sha512-fZXhX5VWwWpoFfrfocslyg6P7cN3YWPG/ASaevNfeO80R+nzgoPUBXcWQekSGSsNDkeRTis4aMmpmofYf1TNtQ==", + "requires": { + "async": "2.6.1", + "clone": "2.1.1", + "eth-block-tracker": "2.3.1", + "eth-sig-util": "1.4.2", + "ethereumjs-block": "1.7.1", + "ethereumjs-tx": "1.3.4", + "ethereumjs-util": "5.2.0", + "ethereumjs-vm": "2.3.4", + "fetch-ponyfill": "4.1.0", + "json-rpc-error": "2.0.0", + "json-stable-stringify": "1.0.1", + "promise-to-callback": "1.0.0", + "readable-stream": "2.3.6", + "request": "2.87.0", + "semaphore": "1.1.0", + "solc": "0.4.24", + "tape": "4.9.1", + "xhr": "2.5.0", + "xtend": "4.0.1" + } + } + } + }, + "ethereum-common": { + "version": "0.0.18", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz", + "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8=" + }, + "ethereumjs-abi": { + "version": "git+https://github.com/ethereumjs/ethereumjs-abi.git#4ea2fdfed09e8f99117d9362d17c6b01b64a2bcf", + "requires": { + "bn.js": "4.11.8", + "ethereumjs-util": "5.2.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "ethjs-util": "0.1.6", + "keccak": "1.4.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.2", + "secp256k1": "3.5.0" + } + } + } + }, + "ethereumjs-account": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz", + "integrity": "sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA==", + "requires": { + "ethereumjs-util": "5.2.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "ethjs-util": "0.1.6", + "keccak": "1.4.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.2", + "secp256k1": "3.5.0" + } + } + } + }, + "ethereumjs-block": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz", + "integrity": "sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg==", + "requires": { + "async": "2.6.1", + "ethereum-common": "0.2.0", + "ethereumjs-tx": "1.3.4", + "ethereumjs-util": "5.2.0", + "merkle-patricia-tree": "2.3.1" + }, + "dependencies": { + "ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==" + }, + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "ethjs-util": "0.1.6", + "keccak": "1.4.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.2", + "secp256k1": "3.5.0" + } + } + } + }, + "ethereumjs-tx": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.4.tgz", + "integrity": "sha512-kOgUd5jC+0tgV7t52UDECMMz9Uf+Lro+6fSpCvzWemtXfMEcwI3EOxf5mVPMRbTFkMMhuERokNNVF3jItAjidg==", + "requires": { + "ethereum-common": "0.0.18", + "ethereumjs-util": "5.2.0" + }, + "dependencies": { + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "ethjs-util": "0.1.6", + "keccak": "1.4.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.2", + "secp256k1": "3.5.0" + } + } + } + }, + "ethereumjs-util": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz", + "integrity": "sha1-PpQosxfuvaPXJg2FT93alUsfG8Y=", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "keccakjs": "0.2.1", + "rlp": "2.0.0", + "secp256k1": "3.5.0" + } + }, + "ethereumjs-vm": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/ethereumjs-vm/-/ethereumjs-vm-2.3.5.tgz", + "integrity": "sha512-AJ7x44+xqyE5+UO3Nns19WkTdZfyqFZ+sEjIEpvme7Ipbe3iBU1uwCcHEdiu/yY9bdhr3IfSa/NfIKNeXPaRVQ==", + "requires": { + "async": "2.6.1", + "async-eventemitter": "0.2.4", + "ethereum-common": "0.2.0", + "ethereumjs-account": "2.0.5", + "ethereumjs-block": "1.7.1", + "ethereumjs-util": "5.2.0", + "fake-merkle-patricia-tree": "1.0.1", + "functional-red-black-tree": "1.0.1", + "merkle-patricia-tree": "2.3.1", + "rustbn.js": "0.1.2", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "ethereum-common": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.2.0.tgz", + "integrity": "sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA==" + }, + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "ethjs-util": "0.1.6", + "keccak": "1.4.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.2", + "secp256k1": "3.5.0" + } + } + } + }, + "ethereumjs-wallet": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/ethereumjs-wallet/-/ethereumjs-wallet-0.6.0.tgz", + "integrity": "sha1-gnY7Fpfuenlr5xVdqd+0my+Yz9s=", + "requires": { + "aes-js": "0.2.4", + "bs58check": "1.3.4", + "ethereumjs-util": "4.5.0", + "hdkey": "0.7.1", + "scrypt.js": "0.2.0", + "utf8": "2.1.2", + "uuid": "2.0.3" + }, + "dependencies": { + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=" + } } }, "ethjs-unit": { @@ -2730,15 +3939,29 @@ } } }, + "ethjs-util": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", + "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "requires": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + } + }, "event-emitter": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", "requires": { "d": "1.0.0", - "es5-ext": "0.10.42" + "es5-ext": "0.10.45" } }, + "event-pubsub": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz", + "integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==" + }, "eventemitter2": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", @@ -2746,9 +3969,9 @@ "dev": true }, "eventemitter3": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.1.1.tgz", - "integrity": "sha1-R3hr2qCHyvext15zq8XH1UAVjNA=" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==" }, "events": { "version": "1.1.1", @@ -2758,7 +3981,7 @@ "evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "requires": { "md5.js": "1.3.4", "safe-buffer": "5.1.2" @@ -2776,6 +3999,18 @@ "p-finally": "1.0.0", "signal-exit": "3.0.2", "strip-eof": "1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "4.1.3", + "shebang-command": "1.2.0", + "which": "1.3.1" + } + } } }, "exit": { @@ -2784,6 +4019,11 @@ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", "dev": true }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=" + }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -2820,7 +4060,6 @@ "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.4" }, @@ -2829,7 +4068,6 @@ "version": "2.2.4", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", - "dev": true, "requires": { "is-number": "2.1.0", "isobject": "2.1.0", @@ -2842,7 +4080,6 @@ "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" } @@ -2851,7 +4088,6 @@ "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" } @@ -2860,13 +4096,20 @@ "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" } } } }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "requires": { + "homedir-polyfill": "1.0.1" + } + }, "express": { "version": "4.16.3", "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", @@ -2989,18 +4232,32 @@ "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "requires": { "is-plain-object": "2.0.4" } } } }, + "extendr": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/extendr/-/extendr-2.1.0.tgz", + "integrity": "sha1-MBqgu+pWX00tyPVw8qImEahSe1Y=", + "requires": { + "typechecker": "2.0.8" + }, + "dependencies": { + "typechecker": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/typechecker/-/typechecker-2.0.8.tgz", + "integrity": "sha1-6D2oS7ZMWEzLNFg4V2xAsDN9uC4=" + } + } + }, "external-editor": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", - "dev": true, "requires": { "chardet": "0.4.2", "iconv-lite": "0.4.23", @@ -3066,27 +4323,32 @@ } } }, + "extract-opts": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/extract-opts/-/extract-opts-2.2.0.tgz", + "integrity": "sha1-H6KOunNSxttID4hc63GkaBC+bX0=", + "requires": { + "typechecker": "2.0.8" + }, + "dependencies": { + "typechecker": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/typechecker/-/typechecker-2.0.8.tgz", + "integrity": "sha1-6D2oS7ZMWEzLNFg4V2xAsDN9uC4=" + } + } + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, - "falafel": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.1.0.tgz", - "integrity": "sha1-lrsXdh2rqU9G0AFzizzt86Z/4Gw=", + "fake-merkle-patricia-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz", + "integrity": "sha1-S4w6z7Ugr635hgsfFM2M40As3dM=", "requires": { - "acorn": "5.5.3", - "foreach": "2.0.5", - "isarray": "0.0.1", - "object-keys": "1.0.11" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - } + "checkpoint-store": "1.1.0" } }, "fast-deep-equal": { @@ -3094,6 +4356,19 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, + "fast-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.2.tgz", + "integrity": "sha512-TR6zxCKftDQnUAPvkrCWdBgDq/gbqx8A3ApnBrR5rMvpp6+KMJI0Igw7fkWPgeVK0uhRXTXdvO3O+YP0CaUX2g==", + "requires": { + "@mrmlnc/readdir-enhanced": "2.2.1", + "@nodelib/fs.stat": "1.1.0", + "glob-parent": "3.1.0", + "is-glob": "4.0.0", + "merge2": "1.2.2", + "micromatch": "3.1.10" + } + }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", @@ -3102,7 +4377,8 @@ "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true }, "fastparse": { "version": "1.1.1", @@ -3110,18 +4386,36 @@ "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=" }, "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", "requires": { "pend": "1.2.0" } }, + "fetch-ponyfill": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz", + "integrity": "sha1-rjzl9zLGReq4fkroeTQUcJsjmJM=", + "requires": { + "node-fetch": "1.7.3" + }, + "dependencies": { + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "0.1.12", + "is-stream": "1.1.0" + } + } + } + }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, "requires": { "escape-string-regexp": "1.0.5" } @@ -3139,7 +4433,7 @@ "file-loader": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz", - "integrity": "sha1-b+iGRJsPKpNuQ8q6rAzb+zaVBvg=", + "integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==", "requires": { "loader-utils": "1.1.0", "schema-utils": "0.4.5" @@ -3153,8 +4447,7 @@ "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" }, "fill-range": { "version": "4.0.0", @@ -3233,6 +4526,14 @@ } } }, + "first-chunk-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", + "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", + "requires": { + "readable-stream": "2.3.6" + } + }, "flat-cache": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", @@ -3255,6 +4556,11 @@ "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=" }, + "flow-parser": { + "version": "0.74.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.74.0.tgz", + "integrity": "sha512-iQHi88aFCkPLr8cW1L9FtP9lmiT/9g20YaycW6sSWX6U9EdwN6K6OkWBlLhrfG5rbDJfJ9k0npVSfAkGNR7x2Q==" + }, "follow-redirects": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.0.tgz", @@ -3274,11 +4580,11 @@ } }, "for-each": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz", - "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "requires": { - "is-function": "1.0.1" + "is-callable": "1.1.3" } }, "for-in": { @@ -3290,7 +4596,6 @@ "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" } @@ -3301,18 +4606,33 @@ "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" }, "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=" }, "form-data": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.2.0.tgz", + "integrity": "sha1-Jvi8JtpkQOKZy9z7aQNcT3em5GY=", "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", - "mime-types": "2.1.18" + "async": "0.9.2", + "combined-stream": "0.0.7", + "mime-types": "2.0.14" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + }, + "mime-types": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz", + "integrity": "sha1-MQ4VnbI+B3+Lsit0jav6SVcUCqY=", + "requires": { + "mime-db": "1.12.0" + } + } } }, "forwarded": { @@ -3333,6 +4653,15 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -3366,18 +4695,6 @@ "thenify-all": "1.6.0" } }, - "fs-pull-blob-store": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/fs-pull-blob-store/-/fs-pull-blob-store-0.4.1.tgz", - "integrity": "sha1-CZsKDj/FlOnaBfL4j+XOg7ajNFo=", - "requires": { - "mkdirp": "0.5.1", - "pull-defer": "0.2.2", - "pull-file": "1.1.0", - "pull-stream": "3.6.8", - "pull-write-file": "0.2.4" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3391,458 +4708,6 @@ "requires": { "nan": "2.10.0", "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 - } } }, "fstream": { @@ -3853,31 +4718,80 @@ "graceful-fs": "4.1.11", "inherits": "2.0.3", "mkdirp": "0.5.1", - "rimraf": "2.6.2" + "rimraf": "2.2.8" } }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, - "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=", + "ganache-cli": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.1.0.tgz", + "integrity": "sha512-FdTeyk4uLRHGeFiMe+Qnh4Hc5KiTVqvRVVvLDFJEVVKC1P1yHhEgZeh9sp1KhuvxSrxToxgJS25UapYQwH4zHw==", "requires": { - "is-property": "1.0.2" + "source-map-support": "0.5.6", + "webpack-cli": "2.1.5" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz", + "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==", + "requires": { + "buffer-from": "1.1.0", + "source-map": "0.6.1" + } + } + } + }, + "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.3" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "optional": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "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" + } + } } }, "get-caller-file": { @@ -3913,12 +4827,80 @@ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "requires": { "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } + } + }, + "gh-got": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gh-got/-/gh-got-6.0.0.tgz", + "integrity": "sha512-F/mS+fsWQMo1zfgG9MD8KWvTWPPzzhuVwY++fhQ5Ggd+0P+CAMHtzMZhNxG+TqGfHDChJKsbh6otfMGqO2AKBw==", + "requires": { + "got": "7.1.0", + "is-plain-obj": "1.1.0" + }, + "dependencies": { + "got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "requires": { + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-plain-obj": "1.1.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "p-cancelable": "0.3.0", + "p-timeout": "1.2.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "url-parse-lax": "1.0.0", + "url-to-options": "1.0.1" + } + }, + "p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" + }, + "p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "requires": { + "p-finally": "1.0.0" + } + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "1.0.4" + } + } + } + }, + "github-username": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/github-username/-/github-username-4.1.0.tgz", + "integrity": "sha1-y+KABBiDIG2kISrp5LXxacML9Bc=", + "requires": { + "gh-got": "6.0.0" } }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -3928,11 +4910,34 @@ "path-is-absolute": "1.0.1" } }, + "glob-all": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-all/-/glob-all-3.1.0.tgz", + "integrity": "sha1-iRPd+17hrHgSZWJBsD1SF8ZLAqs=", + "requires": { + "glob": "7.1.2", + "yargs": "1.2.6" + }, + "dependencies": { + "minimist": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.1.0.tgz", + "integrity": "sha1-md9lelJXTCHJBXSX33QnkLK0wN4=" + }, + "yargs": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.2.6.tgz", + "integrity": "sha1-nHtKgv1dWVsr8Xq23MQxNUMv40s=", + "requires": { + "minimist": "0.1.0" + } + } + } + }, "glob-base": { "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" @@ -3942,7 +4947,6 @@ "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" } @@ -3950,14 +4954,12 @@ "is-extglob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" }, "is-glob": { "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" } @@ -3988,6 +4990,11 @@ } } }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=" + }, "global": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", @@ -3997,37 +5004,51 @@ "process": "0.5.2" } }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "requires": { + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "requires": { + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.1", + "ini": "1.3.5", + "is-windows": "1.0.2", + "which": "1.3.1" + } + }, "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo=" + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" }, "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-8.0.1.tgz", + "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", "requires": { "array-union": "1.0.2", - "arrify": "1.0.1", + "dir-glob": "2.0.0", + "fast-glob": "2.2.2", "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } + "ignore": "3.3.8", + "pify": "3.0.0", + "slash": "1.0.0" } }, "globule": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz", - "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", + "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", "requires": { "glob": "7.1.2", "lodash": "4.17.10", @@ -4035,23 +5056,26 @@ } }, "got": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", - "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.1.tgz", + "integrity": "sha512-tiLX+bnYm5A56T5N/n9Xo89vMaO1mrS9qoDqj3u/anVooqGozvY/HbXzEpDfbNeKsHCBpK40gSbz8wGYSp3i1w==", "requires": { + "@sindresorhus/is": "0.7.0", + "cacheable-request": "2.1.4", "decompress-response": "3.3.0", "duplexer3": "0.1.4", "get-stream": "3.0.0", - "is-plain-obj": "1.1.0", + "into-stream": "3.1.0", "is-retry-allowed": "1.1.0", - "is-stream": "1.1.0", "isurl": "1.0.0", "lowercase-keys": "1.0.1", - "p-cancelable": "0.3.0", - "p-timeout": "1.2.1", + "mimic-response": "1.0.0", + "p-cancelable": "0.4.1", + "p-timeout": "2.0.1", + "pify": "3.0.0", "safe-buffer": "5.1.2", "timed-out": "4.0.1", - "url-parse-lax": "1.0.0", + "url-parse-lax": "3.0.0", "url-to-options": "1.0.1" } }, @@ -4065,15 +5089,23 @@ "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" }, + "grouped-queue": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/grouped-queue/-/grouped-queue-0.3.3.tgz", + "integrity": "sha1-wWfSpTGcWg4JZO9qJbfC34mWyFw=", + "requires": { + "lodash": "4.17.10" + } + }, "growl": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=" }, "grunt": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.2.tgz", - "integrity": "sha1-TmpeaVtwRy/VME9fqeNCNoNqc7w=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.3.tgz", + "integrity": "sha512-/JzmZNPfKorlCrrmxWqQO4JVodO+DVd5XX4DkocL/1WlLlKVLE9+SdEIempOAxDhWPysLle6afvn/hg7Ck2k9g==", "dev": true, "requires": { "coffeescript": "1.10.0", @@ -4084,16 +5116,27 @@ "glob": "7.0.6", "grunt-cli": "1.2.0", "grunt-known-options": "1.1.0", - "grunt-legacy-log": "1.0.2", - "grunt-legacy-util": "1.0.0", + "grunt-legacy-log": "2.0.0", + "grunt-legacy-util": "1.1.1", "iconv-lite": "0.4.23", "js-yaml": "3.5.5", "minimatch": "3.0.4", + "mkdirp": "0.5.1", "nopt": "3.0.6", "path-is-absolute": "1.0.1", - "rimraf": "2.2.8" + "rimraf": "2.6.2" }, "dependencies": { + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } + }, "glob": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", @@ -4119,10 +5162,13 @@ } }, "rimraf": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", - "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", - "dev": true + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.0.6" + } } } }, @@ -4161,6 +5207,15 @@ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } } } }, @@ -4241,13 +5296,13 @@ "dev": true }, "grunt-legacy-log": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-1.0.2.tgz", - "integrity": "sha512-WdedTJ/6zCXnI/coaouzqvkI19uwqbcPkdsXiDRKJyB5rOUlOxnCnTVbpeUdEckKVir2uHF3rDBYppj2p6N3+g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz", + "integrity": "sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw==", "dev": true, "requires": { "colors": "1.1.2", - "grunt-legacy-log-utils": "1.0.0", + "grunt-legacy-log-utils": "2.0.1", "hooker": "0.2.3", "lodash": "4.17.10" }, @@ -4261,36 +5316,65 @@ } }, "grunt-legacy-log-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-1.0.0.tgz", - "integrity": "sha1-p7ji0Ps1taUPSvmG/BEnSevJbz0=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz", + "integrity": "sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA==", "dev": true, "requires": { - "chalk": "1.1.3", - "lodash": "4.3.0" + "chalk": "2.4.1", + "lodash": "4.17.10" }, "dependencies": { - "lodash": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz", - "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=", + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "3.0.0" + } } } }, "grunt-legacy-util": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.0.0.tgz", - "integrity": "sha1-OGqnjcbtUJhsKxiVcmWxtIq7m4Y=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz", + "integrity": "sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A==", "dev": true, "requires": { "async": "1.5.2", "exit": "0.1.2", "getobject": "0.1.0", "hooker": "0.2.3", - "lodash": "4.3.0", - "underscore.string": "3.2.3", - "which": "1.2.14" + "lodash": "4.17.10", + "underscore.string": "3.3.4", + "which": "1.3.1" }, "dependencies": { "async": { @@ -4298,34 +5382,13 @@ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true - }, - "lodash": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.3.0.tgz", - "integrity": "sha1-79nEpuxT87BUEkKZFcPkgk5NJaQ=", - "dev": true - }, - "underscore.string": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.2.3.tgz", - "integrity": "sha1-gGmSYzZl1eX8tNsfs6hi62jp5to=", - "dev": true - }, - "which": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", - "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", - "dev": true, - "requires": { - "isexe": "2.0.0" - } } } }, "grunt-mocha-test": { "version": "0.13.3", "resolved": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.13.3.tgz", - "integrity": "sha1-kChHK2Fb2m3eqnswpaFk6YBd4AU=", + "integrity": "sha512-zQGEsi3d+ViPPi7/4jcj78afKKAKiAA5n61pknQYi25Ugik+aNOuRmiOkmb8mN2CeG8YxT+YdT1H1Q7B/eNkoQ==", "dev": true, "requires": { "hooker": "0.2.3", @@ -4361,13 +5424,43 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + } + } + }, + "hard-source-webpack-plugin": { + "version": "0.6.12", + "resolved": "https://registry.npmjs.org/hard-source-webpack-plugin/-/hard-source-webpack-plugin-0.6.12.tgz", + "integrity": "sha512-96nvwK79RIfIAhOjySHW1T8kDG6r/pfC0TJMNvwTPYF8uzTrfMJTUucKFHmonTrFozqtPrizY3/vyI3u9fr0RA==", + "requires": { + "lodash": "4.17.10", + "mkdirp": "0.5.1", + "node-object-hash": "1.4.1", + "rimraf": "2.6.2", + "tapable": "1.0.0", + "webpack-core": "0.6.9", + "webpack-sources": "1.1.0", + "write-json-file": "2.3.0" + }, + "dependencies": { + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } } } }, "has": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", - "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "requires": { "function-bind": "1.1.1" } @@ -4380,6 +5473,11 @@ "ansi-regex": "2.1.1" } }, + "has-color": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", + "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=" + }, "has-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", @@ -4398,6 +5496,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", @@ -4437,29 +5541,54 @@ } }, "hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.4.tgz", + "integrity": "sha512-A6RlQvvZEtFS5fLU43IDu0QUmBy+fDO9VMdTXvufKwIkt/rFfvICAViCax5fbDO4zdNzaC3/27ZhKUok5bAJyw==", "requires": { "inherits": "2.0.3", "minimalistic-assert": "1.0.1" } }, - "hashlru": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/hashlru/-/hashlru-2.2.1.tgz", - "integrity": "sha1-EPIJmg18BaQPK+r1wdOc8vfavzY=" + "hawk": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", + "requires": { + "boom": "0.4.2", + "cryptiles": "0.2.2", + "hoek": "0.9.1", + "sntp": "0.2.4" + } + }, + "hdkey": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/hdkey/-/hdkey-0.7.1.tgz", + "integrity": "sha1-yu5L6BqneSHpCbjSKN0PKayu5jI=", + "requires": { + "coinstring": "2.3.0", + "secp256k1": "3.5.0" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=" }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "requires": { - "hash.js": "1.1.3", + "hash.js": "1.1.4", "minimalistic-assert": "1.0.1", "minimalistic-crypto-utils": "1.0.1" } }, + "hoek": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=" + }, "home-or-tmp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", @@ -4469,6 +5598,14 @@ "os-tmpdir": "1.0.2" } }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "requires": { + "parse-passwd": "1.0.0" + } + }, "hooker": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", @@ -4478,13 +5615,18 @@ "hosted-git-info": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", - "integrity": "sha1-IyNbKasjDFdqqw1PE/wEawsDgiI=" + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==" }, "html-comment-regex": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz", "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=" }, + "http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" + }, "http-errors": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", @@ -4501,19 +5643,29 @@ "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", "integrity": "sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs=" }, + "http-proxy": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", + "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "requires": { + "eventemitter3": "3.1.0", + "follow-redirects": "1.5.0", + "requires-port": "1.0.0" + } + }, "http-shutdown": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-shutdown/-/http-shutdown-1.2.0.tgz", "integrity": "sha1-3y2AZ6iFbpnRHp3OshYJWR4d9RQ=" }, "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", "requires": { - "assert-plus": "1.0.0", - "jsprim": "1.4.1", - "sshpk": "1.14.1" + "asn1": "0.1.11", + "assert-plus": "0.1.5", + "ctype": "0.5.3" } }, "https-browserify": { @@ -4521,6 +5673,19 @@ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" }, + "i18n": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/i18n/-/i18n-0.8.3.tgz", + "integrity": "sha1-LYzxwkciYCwgQdAbpq5eqlE4jw4=", + "requires": { + "debug": "2.6.9", + "make-plural": "3.0.6", + "math-interval-parser": "1.1.0", + "messageformat": "0.3.1", + "mustache": "2.3.0", + "sprintf-js": "1.0.3" + } + }, "iconv-lite": { "version": "0.4.23", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", @@ -4545,9 +5710,9 @@ "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { - "color-convert": "1.9.1" + "color-convert": "1.9.2" } }, "chalk": { @@ -4578,7 +5743,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "supports-color": { "version": "5.4.0", @@ -4590,41 +5755,70 @@ } } }, - "idb-pull-blob-store": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/idb-pull-blob-store/-/idb-pull-blob-store-0.5.1.tgz", - "integrity": "sha1-nBP58Q6wWqOp8g71cVE8R1efddQ=", + "idna-uts46-hx": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", + "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", "requires": { - "dexie": "1.5.1", - "pull-defer": "0.2.2", - "pull-pushable": "2.2.0", - "pull-window": "2.1.4", - "pull-write": "1.1.4", - "typedarray-to-buffer": "3.1.5" + "punycode": "2.1.0" } }, "ieee754": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz", - "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==" + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", + "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==" }, "ignore": { "version": "3.3.8", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz", - "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg==", - "dev": true + "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg==" + }, + "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", + "integrity": "sha1-2ln7hYl25KXkNwLM0fKC/byeV1Y=", + "requires": { + "editions": "1.3.4", + "ignorepatterns": "1.1.0" + } + }, + "ignorepatterns": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ignorepatterns/-/ignorepatterns-1.1.0.tgz", + "integrity": "sha1-rI9DbyI5td+2bV8NOpBKh6xnzF4=" + }, + "immediate": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.2.3.tgz", + "integrity": "sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=" + }, + "import-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", + "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", + "requires": { + "pkg-dir": "2.0.0", + "resolve-cwd": "2.0.0" + } }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, "requires": { "repeating": "2.0.1" } @@ -4653,11 +5847,15 @@ "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==" + }, "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "dev": true, + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-5.2.0.tgz", + "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", "requires": { "ansi-escapes": "3.1.0", "chalk": "2.4.1", @@ -4668,8 +5866,7 @@ "lodash": "4.17.10", "mute-stream": "0.0.7", "run-async": "2.3.0", - "rx-lite": "4.0.8", - "rx-lite-aggregates": "4.0.8", + "rxjs": "5.5.11", "string-width": "2.1.1", "strip-ansi": "4.0.0", "through": "2.3.8" @@ -4678,23 +5875,20 @@ "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "1.9.2" } }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, "requires": { "ansi-styles": "3.2.1", "escape-string-regexp": "1.0.5", @@ -4704,14 +5898,12 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, "requires": { "ansi-regex": "3.0.0" } @@ -4720,7 +5912,6 @@ "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, "requires": { "has-flag": "3.0.0" } @@ -4732,10 +5923,19 @@ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=" }, + "into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", + "requires": { + "from2": "2.3.0", + "p-is-promise": "1.1.0" + } + }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha1-YQ88ksk1nOHbYW5TgAjSP/NRWOY=", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "requires": { "loose-envify": "1.3.1" } @@ -4758,7 +5958,7 @@ "ipfs-api": { "version": "17.2.4", "resolved": "https://registry.npmjs.org/ipfs-api/-/ipfs-api-17.2.4.tgz", - "integrity": "sha1-gTCl+pjhWyr49qJ7cUQs66/ImyQ=", + "integrity": "sha512-GFNy3Cj7EkzCrdyaQpvctHmtwtghzIDPTtW6XTqj+vybSwk2swyEMKaMHimqi8c8N+5+x5wfLpeUyRUhcZ9lDA==", "requires": { "async": "2.6.1", "bs58": "4.0.1", @@ -4769,7 +5969,7 @@ "glob": "7.1.2", "glob-escape": "0.0.2", "ipfs-block": "0.6.1", - "ipfs-unixfs": "0.1.14", + "ipfs-unixfs": "0.1.15", "ipld-dag-pb": "0.11.4", "is-ipfs": "0.3.2", "is-stream": "1.1.0", @@ -4786,33 +5986,42 @@ "pump": "1.0.3", "qs": "6.5.2", "readable-stream": "2.3.6", - "stream-http": "2.8.2", + "stream-http": "2.8.3", "stream-to-pull-stream": "1.7.2", "streamifier": "0.1.1", "tar-stream": "1.6.1" + }, + "dependencies": { + "base-x": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.4.tgz", + "integrity": "sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "requires": { + "base-x": "3.0.4" + } + } } }, "ipfs-block": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/ipfs-block/-/ipfs-block-0.6.1.tgz", - "integrity": "sha1-uTBT6eqV917SkHgX/79V2ZKgatE=", + "integrity": "sha512-28dgGsb2YsYnFs+To4cVBX8e/lTCb8eWDzGhN5csj3a/sHMOYrHeK8+Ez0IV67CI3lqKGuG/ZD01Cmd6JUvKrQ==", "requires": { "cids": "0.5.3" } }, - "ipfs-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ipfs-log/-/ipfs-log-2.0.0.tgz", - "integrity": "sha1-u7YtvYKQciem4Ymgo5439JIs3EU=", - "requires": { - "p-map": "1.0.0", - "p-whilst": "1.0.0" - } - }, "ipfs-unixfs": { - "version": "0.1.14", - "resolved": "https://registry.npmjs.org/ipfs-unixfs/-/ipfs-unixfs-0.1.14.tgz", - "integrity": "sha512-s1tEnwKhdd17MmyC/EUMNVMDYzKhCiHDI11TF8tSBeWkEQp+0WUxkYuqvz0R5TSi2lNDJ/oVnEmwWhki2spUiQ==", + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ipfs-unixfs/-/ipfs-unixfs-0.1.15.tgz", + "integrity": "sha512-fjtwBDsIlNags4btHIdAJtE02K4KqEMOhV9GEFVv1M2JO2STS23v2LAtX5qb1EOU5VrjtKlm/JIBH3XDRdAyGQ==", "requires": { "protons": "1.0.1" } @@ -4820,7 +6029,7 @@ "ipld-dag-pb": { "version": "0.11.4", "resolved": "https://registry.npmjs.org/ipld-dag-pb/-/ipld-dag-pb-0.11.4.tgz", - "integrity": "sha1-sPrlaB+tVpcTLjJdbC/xe18Mtqg=", + "integrity": "sha512-A514Bt4z44bxhPQVzmBFMJsV3res92eBaDX0snzVsLLasBPNh4Z7He8N2mwSeAX9bJNywRBlJbHMQPwC45rqXw==", "requires": { "async": "2.6.1", "bs58": "4.0.1", @@ -4834,6 +6043,24 @@ "pull-stream": "3.6.8", "pull-traverse": "1.0.3", "stable": "0.1.8" + }, + "dependencies": { + "base-x": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.4.tgz", + "integrity": "sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "requires": { + "base-x": "3.0.4" + } + } } }, "is-absolute-url": { @@ -4875,7 +6102,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=" + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-builtin-module": { "version": "1.0.0", @@ -4885,6 +6112,11 @@ "builtin-modules": "1.1.1" } }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=" + }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -4903,6 +6135,11 @@ } } }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + }, "is-descriptor": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", @@ -4923,14 +6160,12 @@ "is-dotfile": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" }, "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" } @@ -4953,13 +6188,15 @@ "number-is-nan": "1.0.1" } }, - "is-fullwidth-code-point": { + "is-fn": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "requires": { - "number-is-nan": "1.0.1" - } + "resolved": "https://registry.npmjs.org/is-fn/-/is-fn-1.0.0.tgz", + "integrity": "sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, "is-function": { "version": "1.0.1", @@ -4982,11 +6219,29 @@ "is-ipfs": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/is-ipfs/-/is-ipfs-0.3.2.tgz", - "integrity": "sha1-xGULg442/QFR3liWsv8xn+iTYYI=", + "integrity": "sha512-82V1j4LMkYy7H4seQQzOWqo7FiW3I64/1/ryo3dhtWKfOvm7ZolLMRQQfGKs4OXWauh5rAkPnamVcRISHwhmpQ==", "requires": { "bs58": "4.0.1", "cids": "0.5.3", "multihashes": "0.4.13" + }, + "dependencies": { + "base-x": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.4.tgz", + "integrity": "sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "requires": { + "base-x": "3.0.4" + } + } } }, "is-natural-number": { @@ -5017,10 +6272,25 @@ "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" }, + "is-observable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", + "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", + "requires": { + "symbol-observable": "1.2.0" + }, + "dependencies": { + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==" + } + } + }, "is-odd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", - "integrity": "sha1-dkZiRnH9fqVYzNmieVGC8pWPGyQ=", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", "requires": { "is-number": "4.0.0" }, @@ -5028,7 +6298,7 @@ "is-number": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha1-ACbjf1RU1z41bf5lZGmYZ8an8P8=" + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" } } }, @@ -5064,7 +6334,7 @@ "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "requires": { "isobject": "3.0.1" } @@ -5072,24 +6342,25 @@ "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=", - "dev": true + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" }, "is-primitive": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" }, "is-promise": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz", - "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU=" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "requires": { + "has": "1.0.3" + } }, "is-resolvable": { "version": "1.1.0", @@ -5102,6 +6373,14 @@ "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" }, + "is-scoped": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-scoped/-/is-scoped-1.0.0.tgz", + "integrity": "sha1-RJypgpnnEwOCViieyytUDcQ3yzA=", + "requires": { + "scoped-regex": "1.0.0" + } + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -5115,6 +6394,11 @@ "html-comment-regex": "1.1.1" } }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=" + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -5128,13 +6412,18 @@ "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=" + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, + "isbinaryfile": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", + "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=" + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -5150,6 +6439,16 @@ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, + "istextorbinary": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-2.2.1.tgz", + "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", + "requires": { + "binaryextensions": "2.1.1", + "editions": "1.3.4", + "textextensions": "2.2.0" + } + }, "isurl": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", @@ -5159,36 +6458,28 @@ "is-object": "1.0.1" } }, - "jade": { - "version": "0.26.3", - "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", - "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", - "requires": { - "commander": "0.6.1", - "mkdirp": "0.3.0" - }, - "dependencies": { - "commander": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", - "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=" - }, - "mkdirp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", - "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=" - } - } - }, "js-base64": { "version": "2.4.5", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.5.tgz", "integrity": "sha512-aUnNwqMOXw3yvErjMPSQu6qIIzUmT1e5KcU1OZxRDU1g/am6mzBvcrmLAYwzmB59BHPrh5/tKaiF4OPhqRWESQ==" }, + "js-message": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.5.tgz", + "integrity": "sha1-IwDSSxrwjondCVvBpMnJz8uJLRU=" + }, + "js-queue": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/js-queue/-/js-queue-2.0.0.tgz", + "integrity": "sha1-NiITz4YPRo8BJfxslqvBdCUx+Ug=", + "requires": { + "easy-stack": "1.0.0" + } + }, "js-sha3": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.7.0.tgz", - "integrity": "sha512-Wpks3yBDm0UcL5qlVhwW9Jr9n9i4FfeWBFOOXP5puDS/SiudJGhw7DPyBqn3487qD4F0lsC0q3zxink37f7zeA==" + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc=" }, "js-tokens": { "version": "3.0.2", @@ -5210,11 +6501,125 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "optional": true }, + "jscodeshift": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.5.1.tgz", + "integrity": "sha512-sRMollbhbmSDrR79JMAnhEjyZJlQQVozeeY9A6/KNuV26DNcuB3mGSCWXp0hks9dcwRNOELbNOiwraZaXXRk5Q==", + "requires": { + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-preset-es2015": "6.24.1", + "babel-preset-stage-1": "6.24.1", + "babel-register": "6.26.0", + "babylon": "7.0.0-beta.47", + "colors": "1.3.0", + "flow-parser": "0.74.0", + "lodash": "4.17.10", + "micromatch": "2.3.11", + "neo-async": "2.5.1", + "node-dir": "0.1.8", + "nomnom": "1.8.1", + "recast": "0.15.0", + "temp": "0.8.3", + "write-file-atomic": "1.3.4" + }, + "dependencies": { + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "requires": { + "arr-flatten": "1.1.0" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + }, + "babylon": { + "version": "7.0.0-beta.47", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", + "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==" + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "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" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + } + } + }, "jsesc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, "json-loader": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", @@ -5225,15 +6630,56 @@ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, + "json-rpc-engine": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/json-rpc-engine/-/json-rpc-engine-3.7.3.tgz", + "integrity": "sha512-+FO3UWu/wafh/+MZ6BXy0HZU+f5plwUn82FgxpC0scJkEh5snOjFrAAtqCITPDfvfLHRUFOG5pQDUx2pspfERQ==", + "requires": { + "async": "2.6.1", + "babel-preset-env": "1.7.0", + "babelify": "7.3.0", + "clone": "2.1.1", + "json-rpc-error": "2.0.0", + "promise-to-callback": "1.0.0" + }, + "dependencies": { + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" + } + } + }, + "json-rpc-error": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/json-rpc-error/-/json-rpc-error-2.0.0.tgz", + "integrity": "sha1-p6+cICg4tekFxyUOVH8a/3cligI=", + "requires": { + "inherits": "2.0.3" + } + }, + "json-rpc-random-id": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz", + "integrity": "sha1-uknZat7RRE27jaPSA3SKy7zeyMg=" + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" }, "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "0.0.0" + } }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -5246,6 +6692,11 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=" + }, "json5": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", @@ -5259,6 +6710,11 @@ "graceful-fs": "4.1.11" } }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -5268,6 +6724,13 @@ "extsprintf": "1.3.0", "json-schema": "0.2.3", "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } } }, "just-extend": { @@ -5276,6 +6739,17 @@ "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==", "dev": true }, + "keccak": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz", + "integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==", + "requires": { + "bindings": "1.3.0", + "inherits": "2.0.3", + "nan": "2.10.0", + "safe-buffer": "5.1.2" + } + }, "keccakjs": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/keccakjs/-/keccakjs-0.2.1.tgz", @@ -5290,6 +6764,14 @@ "resolved": "https://registry.npmjs.org/keypair/-/keypair-1.0.1.tgz", "integrity": "sha1-dgNxknCvtlZO04oiCHoG/Jqk6hs=" }, + "keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "requires": { + "json-buffer": "3.0.0" + } + }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", @@ -5316,20 +6798,116 @@ "invert-kv": "1.0.0" } }, - "length-prefixed-stream": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/length-prefixed-stream/-/length-prefixed-stream-1.5.2.tgz", - "integrity": "sha512-5kHV/7ZCefC27d4FQLgFHek/pN1S0uEQ8OEgSm55DWO1rKxGi9by4F444aStxa56wB20b6CxZw6KiGPwmJOUmQ==", + "level-codec": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/level-codec/-/level-codec-7.0.1.tgz", + "integrity": "sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ==" + }, + "level-errors": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", + "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", "requires": { - "buffer-alloc-unsafe": "1.0.0", - "readable-stream": "2.3.6", - "varint": "5.0.0" + "errno": "0.1.7" + } + }, + "level-iterator-stream": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz", + "integrity": "sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0=", + "requires": { + "inherits": "2.0.3", + "level-errors": "1.0.5", + "readable-stream": "1.1.14", + "xtend": "4.0.1" }, "dependencies": { - "buffer-alloc-unsafe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.0.0.tgz", - "integrity": "sha1-R0qojzTnvHX6MR0uZFdAnFhGw/4=" + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "level-ws": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/level-ws/-/level-ws-0.0.0.tgz", + "integrity": "sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "2.1.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "requires": { + "object-keys": "0.4.0" + } + } + } + }, + "levelup": { + "version": "1.3.9", + "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", + "requires": { + "deferred-leveldown": "1.2.2", + "level-codec": "7.0.1", + "level-errors": "1.0.5", + "level-iterator-stream": "1.3.1", + "prr": "1.0.1", + "semver": "5.4.1", + "xtend": "4.0.1" + }, + "dependencies": { + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" } } }, @@ -5342,6 +6920,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, "requires": { "prelude-ls": "1.1.2", "type-check": "0.3.2" @@ -5350,9 +6929,9 @@ "libp2p-crypto": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/libp2p-crypto/-/libp2p-crypto-0.12.1.tgz", - "integrity": "sha1-SocNJpujFQ3+AU5PmuoeVQdgFcg=", + "integrity": "sha512-1/z8rxZ0DcQNreZhEsl7PnLr7DWOioSvYbKBLGkRwNRiNh1JJLgh0PdTySBb44wkrOGT+TxcGRd7iq3/X6Wxwg==", "requires": { - "asn1.js": "5.0.0", + "asn1.js": "5.0.1", "async": "2.6.1", "browserify-aes": "1.2.0", "bs58": "4.0.1", @@ -5367,14 +6946,20 @@ "webcrypto-shim": "github:dignifiedquire/webcrypto-shim#190bc9ec341375df6025b17ae12ddb2428ea49c8" }, "dependencies": { - "asn1.js": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.0.0.tgz", - "integrity": "sha512-Y+FKviD0uyIWWo/xE0XkUl0x1allKFhzEVJ+//2Dgqpy+n+B77MlPNqvyk7Vx50M9XyVzjnRhDqJAEAsyivlbA==", + "base-x": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.4.tgz", + "integrity": "sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA==", "requires": { - "bn.js": "4.11.8", - "inherits": "2.0.3", - "minimalistic-assert": "1.0.1" + "safe-buffer": "5.1.2" + } + }, + "bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "requires": { + "base-x": "3.0.4" } } } @@ -5391,59 +6976,184 @@ "secp256k1": "3.5.0" } }, - "libp2p-floodsub": { - "version": "github:libp2p/js-libp2p-floodsub#8d2ee5bda953fd0433798e432cb70c13741fd404", + "listr": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.1.tgz", + "integrity": "sha512-MSMUUVN1f8aRnPi4034RkOqdiUlpYW+FqwFE3aL0uYNPRavkt2S2SsSpDDofn8BDpqv2RNnsdOcCHWsChcq77A==", "requires": { - "debug": "2.6.9", - "hashlru": "2.2.1", - "length-prefixed-stream": "1.5.2", - "libp2p-crypto": "0.8.8", - "lodash.values": "4.3.0", - "pull-pushable": "2.2.0", - "time-cache": "0.3.0" + "@samverschueren/stream-to-observable": "0.3.0", + "cli-truncate": "0.2.1", + "figures": "1.7.0", + "indent-string": "2.1.0", + "is-observable": "1.1.0", + "is-promise": "2.1.0", + "is-stream": "1.1.0", + "listr-silent-renderer": "1.1.1", + "listr-update-renderer": "0.4.0", + "listr-verbose-renderer": "0.4.1", + "log-symbols": "1.0.2", + "log-update": "1.0.2", + "ora": "0.2.3", + "p-map": "1.2.0", + "rxjs": "6.2.1", + "strip-ansi": "3.0.1" }, "dependencies": { - "libp2p-crypto": { - "version": "0.8.8", - "resolved": "https://registry.npmjs.org/libp2p-crypto/-/libp2p-crypto-0.8.8.tgz", - "integrity": "sha1-3IpJy87bUjnel3YZ8tGN+fwRDzk=", + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "requires": { - "asn1.js": "4.10.1", - "async": "2.6.1", - "browserify-aes": "1.2.0", - "keypair": "1.0.1", - "libp2p-crypto-secp256k1": "0.1.4", - "multihashing-async": "0.4.8", - "node-webcrypto-ossl": "1.0.37", - "nodeify": "1.0.1", - "pem-jwk": "1.5.1", - "protocol-buffers": "3.2.1", - "rsa-pem-to-jwk": "1.1.3", - "safe-buffer": "5.1.2", - "tweetnacl": "1.0.0", - "webcrypto-shim": "github:dignifiedquire/webcrypto-shim#190bc9ec341375df6025b17ae12ddb2428ea49c8" + "restore-cursor": "1.0.1" } }, - "libp2p-crypto-secp256k1": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/libp2p-crypto-secp256k1/-/libp2p-crypto-secp256k1-0.1.4.tgz", - "integrity": "sha1-IRN4/jqFnYmtEgOqng111obIW98=", + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "requires": { - "async": "2.6.1", - "libp2p-crypto": "0.8.8", - "multihashing-async": "0.4.8", - "nodeify": "1.0.1", - "safe-buffer": "5.1.2", - "secp256k1": "3.5.0" + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "requires": { + "chalk": "1.1.3" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + }, + "ora": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", + "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", + "requires": { + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-spinners": "0.1.2", + "object-assign": "4.1.1" + } + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + }, + "rxjs": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.2.1.tgz", + "integrity": "sha512-OwMxHxmnmHTUpgO+V7dZChf3Tixf4ih95cmXjzzadULziVl/FKhHScGLj4goEw9weePVOH2Q0+GcCBUhKCZc/g==", + "requires": { + "tslib": "1.9.2" } } } }, - "live-plugin-manager": { - "version": "git+https://github.com/iurimatias/live-plugin-manager.git#b494a103a84733611c7d921bd0e8c6d699b33c5a", + "listr-silent-renderer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", + "integrity": "sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4=" + }, + "listr-update-renderer": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz", + "integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=", + "requires": { + "chalk": "1.1.3", + "cli-truncate": "0.2.1", + "elegant-spinner": "1.0.1", + "figures": "1.7.0", + "indent-string": "3.2.0", + "log-symbols": "1.0.2", + "log-update": "1.0.2", + "strip-ansi": "3.0.1" + }, + "dependencies": { + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=" + }, + "log-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", + "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", + "requires": { + "chalk": "1.1.3" + } + } + } + }, + "listr-verbose-renderer": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz", + "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=", + "requires": { + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "date-fns": "1.29.0", + "figures": "1.7.0" + }, + "dependencies": { + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "requires": { + "restore-cursor": "1.0.1" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + } + } + }, + "live-plugin-manager-git-fix": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/live-plugin-manager-git-fix/-/live-plugin-manager-git-fix-0.12.1.tgz", + "integrity": "sha512-1FvmI3xP246iNgwMcdqlAdPfGhugwiKQhQwg8YY8Uzbzra47lXVpgk3Fe/YDVBRpnnBTQ2YKdDlq4WM86G41SA==", "requires": { "@types/debug": "0.0.30", - "@types/fs-extra": "5.0.2", + "@types/fs-extra": "5.0.3", "@types/lockfile": "1.0.0", "@types/node-fetch": "1.6.9", "@types/semver": "5.5.0", @@ -5506,28 +7216,20 @@ } }, "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "requires": { "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", + "parse-json": "4.0.0", + "pify": "3.0.0", "strip-bom": "3.0.0" }, "dependencies": { - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "requires": { - "error-ex": "1.3.1" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" } } }, @@ -5555,11 +7257,6 @@ "path-exists": "3.0.0" } }, - "lock": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/lock/-/lock-0.1.4.tgz", - "integrity": "sha1-/sfervF+fDoKVeHaBCgD4l2RdF0=" - }, "lockfile": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/lockfile/-/lockfile-1.0.4.tgz", @@ -5573,6 +7270,35 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=" + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" + }, "lodash.assign": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", @@ -5583,6 +7309,16 @@ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._basecreate": "3.0.3", + "lodash._isiterateecall": "3.0.9" + } + }, "lodash.filter": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", @@ -5594,6 +7330,26 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, "lodash.map": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", @@ -5604,11 +7360,6 @@ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=" }, - "lodash.throttle": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", - "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" - }, "lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -5619,20 +7370,89 @@ "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", "integrity": "sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI=" }, - "lodash.values": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-4.3.0.tgz", - "integrity": "sha1-o6bCsOvsxcLLocF+bmIP6BtT00c=" + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "requires": { + "chalk": "2.4.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } }, - "logplease": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/logplease/-/logplease-1.2.14.tgz", - "integrity": "sha512-n6bf1Ce0zvcmuyOzDi2xxLix6F1D/Niz7Qa4K3BmkjyaXcovzEjwZKUYsV+0F2Uv4rlXm5cToIEB+ynqSRdwGw==" + "log-update": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-1.0.2.tgz", + "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", + "requires": { + "ansi-escapes": "1.4.0", + "cli-cursor": "1.0.2" + }, + "dependencies": { + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "requires": { + "restore-cursor": "1.0.1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=" + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + } + } }, "lolex": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.6.0.tgz", - "integrity": "sha512-e1UtIo1pbrIqEXib/yMjHciyqkng5lc0rrIbytgjmRgDR9+2ceNIAcwOWSgylRjoEP9VdVguCSRwnNmlbnOUwA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.0.tgz", + "integrity": "sha512-uJkH2e0BVfU5KOJUevbTOtpDduooSarH5PopO+LfM/vZf8Z9sJzODqKev804JYM2i++ktJfUmC1le4LwFQ1VMg==", "dev": true }, "longest": { @@ -5677,13 +7497,10 @@ "yallist": "2.1.2" } }, - "magic-string": { - "version": "0.22.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", - "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==", - "requires": { - "vlq": "0.2.3" - } + "ltgt": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", + "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=" }, "make-dir": { "version": "1.3.0", @@ -5693,6 +7510,22 @@ "pify": "3.0.0" } }, + "make-plural": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/make-plural/-/make-plural-3.0.6.tgz", + "integrity": "sha1-IDOgO6wpC487uRJY9lud9+iwHKc=", + "requires": { + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "optional": true + } + } + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -5826,11 +7659,18 @@ "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=" }, + "math-interval-parser": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-interval-parser/-/math-interval-parser-1.1.0.tgz", + "integrity": "sha1-2+2lsGsySZc8bfYXD94jhvCv2JM=", + "requires": { + "xregexp": "2.0.0" + } + }, "math-random": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", - "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", - "dev": true + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=" }, "md5.js": { "version": "1.3.4", @@ -5854,6 +7694,87 @@ "mimic-fn": "1.2.0" } }, + "mem-fs": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/mem-fs/-/mem-fs-1.1.3.tgz", + "integrity": "sha1-uK6NLj/Lb10/kWXBLUVRoGXZicw=", + "requires": { + "through2": "2.0.3", + "vinyl": "1.2.0", + "vinyl-file": "2.0.0" + } + }, + "mem-fs-editor": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/mem-fs-editor/-/mem-fs-editor-4.0.2.tgz", + "integrity": "sha512-QHvdXLLNmwJXxKdf7x27aNUren6IoPxwcM8Sfd+S6/ddQQMcYdEtVKsh6ilpqMrU18VQuKZEaH0aCGt3JDbA0g==", + "requires": { + "commondir": "1.0.1", + "deep-extend": "0.5.1", + "ejs": "2.6.1", + "glob": "7.1.2", + "globby": "8.0.1", + "isbinaryfile": "3.0.2", + "mkdirp": "0.5.1", + "multimatch": "2.1.0", + "rimraf": "2.2.8", + "through2": "2.0.3", + "vinyl": "2.1.0" + }, + "dependencies": { + "clone": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.1.tgz", + "integrity": "sha1-0hfR6WERjjrJpLi7oyhVU79kfNs=" + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=" + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=" + }, + "vinyl": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.1.0.tgz", + "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", + "requires": { + "clone": "2.1.1", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.2", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" + } + } + } + }, + "memdown": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/memdown/-/memdown-1.4.1.tgz", + "integrity": "sha1-tOThkhdGZP+65BNhqlAPMRnv4hU=", + "requires": { + "abstract-leveldown": "2.7.2", + "functional-red-black-tree": "1.0.1", + "immediate": "3.2.3", + "inherits": "2.0.3", + "ltgt": "2.2.1", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "abstract-leveldown": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz", + "integrity": "sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w==", + "requires": { + "xtend": "4.0.1" + } + } + } + }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -5970,15 +7891,6 @@ "find-up": "1.1.2", "read-pkg": "1.1.0" } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } } } }, @@ -5992,12 +7904,76 @@ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, - "merge-source-map": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz", - "integrity": "sha1-pd5GU42uhNQRTMXqArR3KmNGcB8=", + "merge2": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.2.tgz", + "integrity": "sha512-bgM8twH86rWni21thii6WCMQMRMmwqqdW3sGWi9IipnVAszdLXRjwDwAnyrVXo6DuP3AjRMMttZKUB48QWIFGg==" + }, + "merkle-patricia-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/merkle-patricia-tree/-/merkle-patricia-tree-2.3.1.tgz", + "integrity": "sha512-Qp9Mpb3xazznXzzGQBqHbqCpT2AR9joUOHYYPiQjYCarrdCPCnLWXo4BFv77y4xN26KR224xoU1n/qYY7RYYgw==", "requires": { - "source-map": "0.5.7" + "async": "1.5.2", + "ethereumjs-util": "5.2.0", + "level-ws": "0.0.0", + "levelup": "1.3.9", + "memdown": "1.4.1", + "readable-stream": "2.3.6", + "rlp": "2.0.0", + "semaphore": "1.1.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "ethereumjs-util": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz", + "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==", + "requires": { + "bn.js": "4.11.8", + "create-hash": "1.2.0", + "ethjs-util": "0.1.6", + "keccak": "1.4.0", + "rlp": "2.0.0", + "safe-buffer": "5.1.2", + "secp256k1": "3.5.0" + } + } + } + }, + "messageformat": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/messageformat/-/messageformat-0.3.1.tgz", + "integrity": "sha1-5Y//gkXps5cXmeW0PbWLPpQX9aI=", + "requires": { + "async": "1.5.2", + "glob": "6.0.4", + "make-plural": "3.0.6", + "nopt": "3.0.6", + "watchr": "2.4.13" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + } } }, "methods": { @@ -6028,7 +8004,7 @@ "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "requires": { "bn.js": "4.11.8", "brorand": "1.1.0" @@ -6037,25 +8013,27 @@ "mime": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha1-Eh+evEnjdm8xGnbh+hyAA8SwOqY=" + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" }, "mime-db": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", - "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz", + "integrity": "sha1-PQxjGA9FjrENMlqqN9fFiuMS6dc=" }, "mime-types": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", - "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", - "requires": { - "mime-db": "1.33.0" - } + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=" + }, + "mime.json": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/mime.json/-/mime.json-1.0.18.tgz", + "integrity": "sha512-GA+bgKycQECTUKDszphjkhKO7N6frDyrWTH4mZ2W9ohFYxT0U2pkN0+XzvBU8LSRzyQLvmDK2bBpXmPfLbckWw==" }, "mimic-fn": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI=" + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" }, "mimic-response": { "version": "1.0.0", @@ -6083,7 +8061,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { "brace-expansion": "1.1.11" } @@ -6112,7 +8090,7 @@ "minizlib": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz", - "integrity": "sha1-EeE2WM5GvDpwomeqxYNZ0eDCnOs=", + "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", "requires": { "minipass": "2.3.3" } @@ -6120,7 +8098,7 @@ "mixin-deep": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "requires": { "for-in": "1.0.2", "is-extendable": "1.0.1" @@ -6129,7 +8107,7 @@ "is-extendable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "requires": { "is-plain-object": "2.0.4" } @@ -6153,72 +8131,65 @@ } }, "mocha": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz", - "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", + "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", "requires": { - "commander": "2.3.0", - "debug": "2.2.0", - "diff": "1.4.0", - "escape-string-regexp": "1.0.2", - "glob": "3.2.11", + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.8", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", "growl": "1.9.2", - "jade": "0.26.3", + "he": "1.1.1", + "json3": "3.3.2", + "lodash.create": "3.1.1", "mkdirp": "0.5.1", - "supports-color": "1.2.0", - "to-iso-string": "0.0.2" + "supports-color": "3.1.2" }, "dependencies": { "commander": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", - "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=" + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "requires": { + "graceful-readlink": "1.0.1" + } }, "debug": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", - "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", "requires": { - "ms": "0.7.1" + "ms": "2.0.0" } }, - "escape-string-regexp": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=" + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=" }, "glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", - "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", "inherits": "2.0.3", - "minimatch": "0.3.0" + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" - }, - "minimatch": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", - "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", - "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" - } - }, - "ms": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", - "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" - }, "supports-color": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", - "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "requires": { + "has-flag": "1.0.0" + } } } }, @@ -6254,20 +8225,48 @@ "lodash.map": "4.6.0", "varint": "5.0.0", "xtend": "4.0.1" + }, + "dependencies": { + "base-x": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.4.tgz", + "integrity": "sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "requires": { + "base-x": "3.0.4" + } + } } }, "multibase": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.4.0.tgz", - "integrity": "sha1-G9tiyC3gEU+CKh2HUby+6RzS77o=", + "integrity": "sha512-fnYvZJWDn3eSJ7EeWvS8zbOpRwuyPHpDggSnqGXkQMvYED5NdO9nyqnZboGvAT+r/60J8KZ09tW8YJHkS22sFw==", "requires": { "base-x": "3.0.4" + }, + "dependencies": { + "base-x": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.4.tgz", + "integrity": "sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA==", + "requires": { + "safe-buffer": "5.1.2" + } + } } }, "multicodec": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.2.6.tgz", - "integrity": "sha512-VGyRUDkxdJzWnj9x3C49MzI3+TtKKDYNfIBOaWBCNuPk6CE5CwwkL15gJtsLDfLay0fL4xTh4Af3kBbJSxSppw==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.2.7.tgz", + "integrity": "sha512-96xc9zs7bsclMW0Po9ERnRFqcsWHY8OZ8JW/I8DeHG58YYJZy3cBGI00Ze7hz9Ix56DNHMTSxEj9cgoZByruMg==", "requires": { "varint": "5.0.0" } @@ -6275,16 +8274,34 @@ "multihashes": { "version": "0.4.13", "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.13.tgz", - "integrity": "sha1-0QvXG9UdJKqJTipvFFcUa7e6wSU=", + "integrity": "sha512-HwJGEKPCpLlNlgGQA56CYh/Wsqa+c4JAq8+mheIgw7OK5T4QvNJqgp6TH8gZ4q4l1aiWeNat/H/MrFXmTuoFfQ==", "requires": { "bs58": "4.0.1", "varint": "5.0.0" + }, + "dependencies": { + "base-x": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.4.tgz", + "integrity": "sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha1-vhYedsNU9veIrkBx9j806MTwpCo=", + "requires": { + "base-x": "3.0.4" + } + } } }, "multihashing-async": { "version": "0.4.8", "resolved": "https://registry.npmjs.org/multihashing-async/-/multihashing-async-0.4.8.tgz", - "integrity": "sha1-QVcrJaj8aOsxi4ViQJ/dchpyfqE=", + "integrity": "sha512-LCc4lfxmTJOHKIjZjFNgvmfB6nXS/ErLInT9uwU8udFrRm2PH+aTPk3mfCREKmCiSHOlCWiv2O8rlnBx+OjlMw==", "requires": { "async": "2.6.1", "blakejs": "1.1.0", @@ -6292,6 +8309,24 @@ "multihashes": "0.4.13", "murmurhash3js": "3.0.1", "nodeify": "1.0.1" + }, + "dependencies": { + "js-sha3": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.7.0.tgz", + "integrity": "sha512-Wpks3yBDm0UcL5qlVhwW9Jr9n9i4FfeWBFOOXP5puDS/SiudJGhw7DPyBqn3487qD4F0lsC0q3zxink37f7zeA==" + } + } + }, + "multimatch": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", + "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", + "requires": { + "array-differ": "1.0.0", + "array-union": "1.0.2", + "arrify": "1.0.1", + "minimatch": "3.0.4" } }, "murmurhash3js": { @@ -6299,6 +8334,11 @@ "resolved": "https://registry.npmjs.org/murmurhash3js/-/murmurhash3js-3.0.1.tgz", "integrity": "sha1-Ppg+W0fCoG9DpxMXTn5DXKBEuZg=" }, + "mustache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.0.tgz", + "integrity": "sha1-QCj3d4sXcIpImTCm5SrDvKDaQdA=" + }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", @@ -6327,7 +8367,7 @@ "nanomatch": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", - "integrity": "sha1-h59xUMstq3pHElkGbBBO7m4Pp8I=", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", "requires": { "arr-diff": "4.0.0", "array-unique": "0.3.2", @@ -6367,6 +8407,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.23", + "sax": "1.2.4" + } + }, "negotiator": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", @@ -6377,20 +8428,30 @@ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.5.1.tgz", "integrity": "sha512-3KL3fvuRkZ7s4IFOMfztb7zJp3QaVWnBeGoJlgB38XnCRPj/0tLzzLG5IB8NYOHbJ8g8UGrgZv44GLDk6CxTxA==" }, + "neo-blessed": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/neo-blessed/-/neo-blessed-0.2.0.tgz", + "integrity": "sha512-C2kC4K+G2QnNQFXUIxTQvqmrdSIzGTX1ZRKeDW6ChmvPRw8rTkTEJzbEQHiHy06d36PCl/yMOCjquCRV8SpSQw==" + }, "next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" }, + "nice-try": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.4.tgz", + "integrity": "sha512-2NpiFHqC87y/zFke0fC0spBXL3bBsoh/p5H1EFhshxjCR5+0g2d6BiXbUFz9v1sAcxsk2htp2eQnNIci2dIYcA==" + }, "nise": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.3.3.tgz", - "integrity": "sha512-v1J/FLUB9PfGqZLGDBhQqODkbLotP0WtLo9R4EJY2PPu5f5Xg4o0rA8FDlmrjFSv9vBBKcfnOSpfYYuu5RTHqg==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.1.tgz", + "integrity": "sha512-9JX3YwoIt3kS237scmSSOpEv7vCukVzLfwK0I0XhocDSHUANid8ZHnLEULbbSkfeMn98B2y5kphIWzZUylESRQ==", "dev": true, "requires": { "@sinonjs/formatio": "2.0.0", "just-extend": "1.1.27", - "lolex": "2.6.0", + "lolex": "2.7.0", "path-to-regexp": "1.7.0", "text-encoding": "0.6.4" }, @@ -6412,6 +8473,11 @@ } } }, + "node-dir": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.8.tgz", + "integrity": "sha1-VfuN62mQcHB/tn+RpGDwRIKUx30=" + }, "node-fetch": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", @@ -6422,6 +8488,96 @@ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", "integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ==" }, + "node-http-proxy": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/node-http-proxy/-/node-http-proxy-0.2.3.tgz", + "integrity": "sha1-ZFv8yESYGkEnBz//Php2ff50NLc=", + "requires": { + "bufferhelper": "0.2.0", + "commander": "2.6.0", + "pm": "2.2.5", + "request": "2.51.0" + }, + "dependencies": { + "bl": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", + "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "requires": { + "readable-stream": "1.0.34" + } + }, + "commander": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz", + "integrity": "sha1-nfflL7Kgyw+4kFjugMMQQiXzfh0=" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=" + }, + "qs": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz", + "integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "request": { + "version": "2.51.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.51.0.tgz", + "integrity": "sha1-NdALvswBLlX5B7G9ng29V3v+8m4=", + "requires": { + "aws-sign2": "0.5.0", + "bl": "0.9.5", + "caseless": "0.8.0", + "combined-stream": "0.0.7", + "forever-agent": "0.5.2", + "form-data": "0.2.0", + "hawk": "1.1.1", + "http-signature": "0.10.1", + "json-stringify-safe": "5.0.1", + "mime-types": "1.0.2", + "node-uuid": "1.4.8", + "oauth-sign": "0.5.0", + "qs": "2.3.3", + "stringstream": "0.0.6", + "tough-cookie": "2.4.2", + "tunnel-agent": "0.4.3" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "node-ipc": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.1.1.tgz", + "integrity": "sha512-FAyICv0sIRJxVp3GW5fzgaf9jwwRQxAKDJlmNFUL5hOy+W4X/I5AypyHoq0DXXbo9o/gt79gj++4cMr4jVWE/w==", + "requires": { + "event-pubsub": "4.3.0", + "js-message": "1.0.5", + "js-queue": "2.0.0" + } + }, "node-libs-browser": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", @@ -6443,15 +8599,25 @@ "querystring-es3": "0.2.1", "readable-stream": "2.3.6", "stream-browserify": "2.0.1", - "stream-http": "2.8.2", + "stream-http": "2.8.3", "string_decoder": "1.1.1", "timers-browserify": "2.0.10", "tty-browserify": "0.0.0", "url": "0.11.0", - "util": "0.10.3", + "util": "0.10.4", "vm-browserify": "0.0.4" }, "dependencies": { + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "requires": { + "base64-js": "1.3.0", + "ieee754": "1.1.12", + "isarray": "1.0.0" + } + }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -6464,16 +8630,69 @@ } } }, - "node-webcrypto-ossl": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/node-webcrypto-ossl/-/node-webcrypto-ossl-1.0.37.tgz", - "integrity": "sha512-AQSux10u8NoUhRPqb2bapqM8EKMawKGYIBbGNWsBUTeq0uXYtuIheujcaJo5XY1Yy6HffC/fP7AHHtSA4KP2ig==", + "node-object-hash": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/node-object-hash/-/node-object-hash-1.4.1.tgz", + "integrity": "sha512-JQVqSM5/mOaUoUhCYR0t1vgm8RFo7qpJtPvnoFCLeqQh1xrfmr3BCD3nGBnACzpIEF7F7EVgqGD3O4lao/BY/A==" + }, + "node-pre-gyp": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.0.tgz", + "integrity": "sha512-G7kEonQLRbcA/mOoFoxvlMrw6Q6dPf92+t/l0DFSMuSlDoWaI9JWIyPwK0jyE1bph//CUEL65/Fz1m2vJbmjQQ==", "optional": true, "requires": { + "detect-libc": "1.0.3", "mkdirp": "0.5.1", - "nan": "2.10.0", - "tslib": "1.9.1", - "webcrypto-core": "0.1.22" + "needle": "2.2.1", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.8", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.4" + }, + "dependencies": { + "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" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "optional": true, + "requires": { + "glob": "7.1.2" + } + }, + "tar": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.4.tgz", + "integrity": "sha512-mq9ixIYfNF9SK0IS/h2HKMu8Q2iaCuhDDsZhdEag/FHv8fOaYld4vN7ouMgcSSt5WKZzPs8atclTcJm36OTh4w==", + "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=", + "optional": true + } } }, "nodeify": { @@ -6483,13 +8702,55 @@ "requires": { "is-promise": "1.0.1", "promise": "1.3.0" + }, + "dependencies": { + "is-promise": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz", + "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU=" + } + } + }, + "nomnom": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", + "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", + "requires": { + "chalk": "0.4.0", + "underscore": "1.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", + "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=" + }, + "chalk": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", + "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", + "requires": { + "ansi-styles": "1.0.0", + "has-color": "0.1.7", + "strip-ansi": "0.1.1" + } + }, + "strip-ansi": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", + "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=" + }, + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + } } }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, "requires": { "abbrev": "1.1.1" } @@ -6497,7 +8758,7 @@ "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "requires": { "hosted-git-info": "2.6.0", "is-builtin-module": "1.0.0", @@ -6529,6 +8790,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", @@ -6537,6 +8814,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.5", + "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", @@ -6564,9 +8853,9 @@ } }, "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.5.0.tgz", + "integrity": "sha1-12f1FpMlYg6rLgh+8MRy53PbZGE=" }, "object-assign": { "version": "4.1.1", @@ -6602,9 +8891,9 @@ } }, "object-inspect": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.4.1.tgz", - "integrity": "sha512-wqdhLpfCUbEsoEwl3FXwGyv8ief1k/1aUdIPCqVnupM6e8l63BEJdiF/0swtn04/8p05tG/T0FrpTlfwvljOdw==" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz", + "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==" }, "object-keys": { "version": "1.0.11", @@ -6623,7 +8912,6 @@ "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" @@ -6665,7 +8953,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, "requires": { "mimic-fn": "1.2.0" } @@ -6675,13 +8962,14 @@ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", "requires": { - "wordwrap": "0.0.2" + "wordwrap": "0.0.3" } }, "optionator": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, "requires": { "deep-is": "0.1.3", "fast-levenshtein": "2.0.6", @@ -6694,92 +8982,73 @@ "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true } } }, - "orbit-db": { - "version": "0.17.3", - "resolved": "https://registry.npmjs.org/orbit-db/-/orbit-db-0.17.3.tgz", - "integrity": "sha1-21ou2e+88U3uxoUoGTC/89egY9w=", + "ora": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-2.1.0.tgz", + "integrity": "sha512-hNNlAd3gfv/iPmsNxYoAPLvxg7HuPozww7fFonMZvL84tP6Ox5igfk5j/+a9rtJJwqMgKK+JgWsAQik5o0HTLA==", "requires": { - "libp2p-floodsub": "github:libp2p/js-libp2p-floodsub#8d2ee5bda953fd0433798e432cb70c13741fd404", - "logplease": "1.2.14", - "orbit-db-counterstore": "0.2.0", - "orbit-db-docstore": "0.2.0", - "orbit-db-eventstore": "0.2.0", - "orbit-db-feedstore": "0.2.0", - "orbit-db-kvstore": "0.2.0", - "orbit-db-pubsub": "0.2.1" - } - }, - "orbit-db-cache": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/orbit-db-cache/-/orbit-db-cache-0.0.7.tgz", - "integrity": "sha512-bvIimrujda1di1p0R2I0MY3VmnSz2y8l7Bc4Qvp/jsJpf5jxTIvfC97pGpO6Fm3kUGGZDhKNjY/ZW3VfXoBRFw==", - "requires": { - "fs-pull-blob-store": "0.4.1", - "idb-pull-blob-store": "0.5.1", - "lock": "0.1.4", - "pull-stream": "3.6.8" - } - }, - "orbit-db-counterstore": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/orbit-db-counterstore/-/orbit-db-counterstore-0.2.0.tgz", - "integrity": "sha1-evzn44pymhhsq8tRGaaSbhCsHMI=", - "requires": { - "crdts": "0.0.1", - "orbit-db-store": "0.2.3" - } - }, - "orbit-db-docstore": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/orbit-db-docstore/-/orbit-db-docstore-0.2.0.tgz", - "integrity": "sha1-kXnVDeFbN6yBVBDLHuGW633/54I=", - "requires": { - "orbit-db-store": "0.2.3" - } - }, - "orbit-db-eventstore": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/orbit-db-eventstore/-/orbit-db-eventstore-0.2.0.tgz", - "integrity": "sha1-vjXmAKbMf5brJhIUn0w/A9D0SrE=", - "requires": { - "orbit-db-store": "0.2.3" - } - }, - "orbit-db-feedstore": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/orbit-db-feedstore/-/orbit-db-feedstore-0.2.0.tgz", - "integrity": "sha1-971giSEhTYrPPRwk7SB8js1R0RM=", - "requires": { - "orbit-db-eventstore": "0.2.0" - } - }, - "orbit-db-kvstore": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/orbit-db-kvstore/-/orbit-db-kvstore-0.2.0.tgz", - "integrity": "sha1-QFbz/xtrq9jkEWUczCsdtreIWpo=", - "requires": { - "orbit-db-store": "0.2.3" - } - }, - "orbit-db-pubsub": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/orbit-db-pubsub/-/orbit-db-pubsub-0.2.1.tgz", - "integrity": "sha1-6Hv1b49eMmsEjxiZ3nXIPqT/NBQ=", - "requires": { - "logplease": "1.2.14" - } - }, - "orbit-db-store": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/orbit-db-store/-/orbit-db-store-0.2.3.tgz", - "integrity": "sha1-FhkXhjp4IKA8khIzxaEsktnUE9Q=", - "requires": { - "ipfs-log": "2.0.0", - "orbit-db-cache": "0.0.7" + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-spinners": "1.3.1", + "log-symbols": "2.2.0", + "strip-ansi": "4.0.0", + "wcwidth": "1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "cli-spinners": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.3.1.tgz", + "integrity": "sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } } }, "os-browserify": { @@ -6807,20 +9076,53 @@ "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", - "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==" + }, + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", + "requires": { + "p-reduce": "1.0.0" + } }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, + "p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4=" + }, + "p-iteration": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/p-iteration/-/p-iteration-1.1.7.tgz", + "integrity": "sha512-VsYvUPjm2edbKkX4QzlASC1qB2e4Z6IE9WPaRVHKwCtobmB6vfUcU9eBOwj1k5uMNi8O6w89QfsDatO5ePSjQg==" + }, + "p-lazy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-lazy/-/p-lazy-1.0.0.tgz", + "integrity": "sha1-7FPIAvLuOsKPFmzILQsrAt4nqDU=" + }, "p-limit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", - "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "requires": { "p-try": "1.0.0" } @@ -6830,18 +9132,23 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "requires": { - "p-limit": "1.2.0" + "p-limit": "1.3.0" } }, "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==" + }, + "p-reduce": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.0.0.tgz", - "integrity": "sha1-/s9XjY9GxPQlTrNjHlbQMa0w5P0=" + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=" }, "p-timeout": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", - "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", "requires": { "p-finally": "1.0.0" } @@ -6851,11 +9158,6 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" }, - "p-whilst": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-whilst/-/p-whilst-1.0.0.tgz", - "integrity": "sha1-VGaOrX+TR5n8APHlIw/Wrd645+Y=" - }, "pako": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", @@ -6871,13 +9173,24 @@ "create-hash": "1.2.0", "evp_bytestokey": "1.0.3", "pbkdf2": "3.0.16" + }, + "dependencies": { + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + } } }, "parse-glob": { "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", @@ -6888,14 +9201,12 @@ "is-extglob": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" }, "is-glob": { "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" } @@ -6907,7 +9218,7 @@ "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.1.tgz", "integrity": "sha1-aug6eqJanZtwCswoaYzR8e1+lTY=", "requires": { - "for-each": "0.3.2", + "for-each": "0.3.3", "trim": "0.0.1" } }, @@ -6920,6 +9231,11 @@ "json-parse-better-errors": "1.0.2" } }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + }, "parseurl": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", @@ -6972,18 +9288,11 @@ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "requires": { - "pify": "2.3.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" - } + "pify": "3.0.0" } }, "pbkdf2": { @@ -7012,7 +9321,7 @@ "peer-info": { "version": "0.11.6", "resolved": "https://registry.npmjs.org/peer-info/-/peer-info-0.11.6.tgz", - "integrity": "sha1-BICwAw0t+P1PCYebJppxWyvSuhI=", + "integrity": "sha512-xrVNiAF1IhVJNGEg5P2UQN+subaEkszT8YkC3zdy06MK0vTH3cMHB+HH+ZURkoSLssc3HbK58ecXeKpQ/4zq5w==", "requires": { "lodash.uniqby": "4.7.0", "multiaddr": "3.1.0", @@ -7087,6 +9396,11 @@ "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, + "pm": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/pm/-/pm-2.2.5.tgz", + "integrity": "sha1-IgJZn1m/trOID6naI0rdL0NLYK8=" + }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -7095,7 +9409,7 @@ "postcss": { "version": "5.2.18", "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", - "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "requires": { "chalk": "1.1.3", "js-base64": "2.4.5", @@ -7196,7 +9510,7 @@ "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", "requires": { - "has": "1.0.1", + "has": "1.0.3", "postcss": "5.2.18", "postcss-value-parser": "3.3.0" } @@ -7262,7 +9576,7 @@ "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", "requires": { "alphanum-sort": "1.0.2", - "has": "1.0.1", + "has": "1.0.3", "postcss": "5.2.18", "postcss-selector-parser": "2.2.3" } @@ -7278,9 +9592,9 @@ "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { - "color-convert": "1.9.1" + "color-convert": "1.9.2" } }, "chalk": { @@ -7311,7 +9625,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "supports-color": { "version": "5.4.0", @@ -7335,9 +9649,9 @@ "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { - "color-convert": "1.9.1" + "color-convert": "1.9.2" } }, "chalk": { @@ -7368,7 +9682,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "supports-color": { "version": "5.4.0", @@ -7392,9 +9706,9 @@ "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { - "color-convert": "1.9.1" + "color-convert": "1.9.2" } }, "chalk": { @@ -7425,7 +9739,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "supports-color": { "version": "5.4.0", @@ -7449,9 +9763,9 @@ "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0=", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { - "color-convert": "1.9.1" + "color-convert": "1.9.2" } }, "chalk": { @@ -7482,7 +9796,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "supports-color": { "version": "5.4.0", @@ -7544,7 +9858,7 @@ "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", "requires": { - "has": "1.0.1", + "has": "1.0.3", "postcss": "5.2.18", "postcss-value-parser": "3.3.0" } @@ -7590,15 +9904,21 @@ "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", "requires": { - "has": "1.0.1", + "has": "1.0.3", "postcss": "5.2.18", "uniqs": "2.0.0" } }, + "precond": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", + "integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=" + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true }, "prepend-http": { "version": "1.0.4", @@ -7608,13 +9928,22 @@ "preserve": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + }, + "prettier": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.13.5.tgz", + "integrity": "sha512-4M90mfvLz6yRf2Dhzd+xPIE6b4xkI8nHMJhsSm9IlfG17g6wujrrm7+H1X8x52tC4cSNm6HmuhCUSNe6Hd5wfw==" + }, + "pretty-bytes": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", + "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=" }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=" + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" }, "process": { "version": "0.5.2", @@ -7624,7 +9953,7 @@ "process-nextick-args": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha1-o31zL0JxtKsa0HDTVQjoKQeI/6o=" + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "progress": { "version": "2.0.0", @@ -7638,12 +9967,28 @@ "integrity": "sha1-5cyaTIJ45GZP/twBx9qEhCsEAXU=", "requires": { "is-promise": "1.0.1" + }, + "dependencies": { + "is-promise": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz", + "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU=" + } + } + }, + "promise-to-callback": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/promise-to-callback/-/promise-to-callback-1.0.0.tgz", + "integrity": "sha1-XSp0kBC/tn2WNZj805YHRqaP7vc=", + "requires": { + "is-fn": "1.0.0", + "set-immediate-shim": "1.0.1" } }, "promisify-es6": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/promisify-es6/-/promisify-es6-1.0.3.tgz", - "integrity": "sha1-sBJmjE3zyWXOE9qsKzpNFyapY0Y=" + "integrity": "sha512-N9iVG+CGJsI4b4ZGazjwLnxErD2d9Pe4DPvvXSxYA9tFNu8ymXME4Qs5HIQ0LMJpNM7zj+m0NlNnNeqFpKzqnA==" }, "promptly": { "version": "2.2.0", @@ -7661,28 +10006,15 @@ "levenshtein-edit-distance": "1.0.0" } }, - "protocol-buffers": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/protocol-buffers/-/protocol-buffers-3.2.1.tgz", - "integrity": "sha1-NyWOF+JKCC8G67F3MekoUdHHaIk=", - "requires": { - "brfs": "1.6.1", - "generate-function": "2.0.0", - "generate-object-property": "1.2.0", - "protocol-buffers-schema": "3.3.2", - "signed-varint": "2.0.1", - "varint": "5.0.0" - } - }, "protocol-buffers-schema": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.3.2.tgz", - "integrity": "sha1-AENPYItOjfVMWeBw7+78N/tLuFk=" + "integrity": "sha512-Xdayp8sB/mU+sUV4G7ws8xtYMGdQnxbeIfLjyO9TZZRJdztBGhlmbI5x1qcY4TG5hBkIKGnc28i7nXxaugu88w==" }, "protons": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/protons/-/protons-1.0.1.tgz", - "integrity": "sha1-HBBxRMB/wtHLi2y3ZFHmqTgjdnY=", + "integrity": "sha512-+0ZKnfVs+4c43tbAQ5j0Mck8wPcLnlxUYzKQoB4iDW4ocdXGnN4P+0dDbgX1FTpoY9+7P2Tn2scJyHHqj+S/lQ==", "requires": { "protocol-buffers-schema": "3.3.2", "safe-buffer": "5.1.2", @@ -7709,6 +10041,11 @@ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, + "psl": { + "version": "1.1.28", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.28.tgz", + "integrity": "sha512-+AqO1Ae+N/4r7Rvchrdm432afjT9hqJRyBN3DQv9At0tPz4hIFSGKbq64fN9dVoCow4oggIIax5/iONx0r9hZw==" + }, "public-encrypt": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", @@ -7721,24 +10058,11 @@ "randombytes": "2.0.6" } }, - "pull-cat": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/pull-cat/-/pull-cat-1.1.11.tgz", - "integrity": "sha1-tkLdElXaN2pwa220+pYvX9t0wxs=" - }, "pull-defer": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/pull-defer/-/pull-defer-0.2.2.tgz", "integrity": "sha1-CIew/7MK8ypW2+z6csFnInHwexM=" }, - "pull-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pull-file/-/pull-file-1.1.0.tgz", - "integrity": "sha1-HdmHYF1jV6DSPB5Lgm95FaIVEpw=", - "requires": { - "pull-utf8-decoder": "1.0.2" - } - }, "pull-pushable": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/pull-pushable/-/pull-pushable-2.2.0.tgz", @@ -7754,61 +10078,19 @@ "resolved": "https://registry.npmjs.org/pull-traverse/-/pull-traverse-1.0.3.tgz", "integrity": "sha1-dPtde+f6a9enjpeTPhmbeUWGaTg=" }, - "pull-utf8-decoder": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pull-utf8-decoder/-/pull-utf8-decoder-1.0.2.tgz", - "integrity": "sha1-p6+iOE0eZBWl1gIFQSbMjeO8vOc=" - }, - "pull-window": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/pull-window/-/pull-window-2.1.4.tgz", - "integrity": "sha1-/DuG/uvRkgx64pdpHiP3BfiFUvA=", - "requires": { - "looper": "2.0.0" - }, - "dependencies": { - "looper": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/looper/-/looper-2.0.0.tgz", - "integrity": "sha1-Zs0Md0rz1P7axTeU90LbVtqPCew=" - } - } - }, - "pull-write": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/pull-write/-/pull-write-1.1.4.tgz", - "integrity": "sha1-3d6jFJO0j2douEooHQHrO1Mf4Lg=", - "requires": { - "looper": "4.0.0", - "pull-cat": "1.1.11", - "pull-stream": "3.6.8" - }, - "dependencies": { - "looper": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/looper/-/looper-4.0.0.tgz", - "integrity": "sha1-dwat7VmpntygbmtUu4bI7BnJUVU=" - } - } - }, - "pull-write-file": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/pull-write-file/-/pull-write-file-0.2.4.tgz", - "integrity": "sha1-Q3NErrIYn2XmeO0a838PdgpUU+8=" - }, "pump": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", - "integrity": "sha1-Xf6DEcM7v2/BgmH580cCxHwIqVQ=", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", "requires": { "end-of-stream": "1.4.1", "once": "1.4.0" } }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", + "integrity": "sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0=" }, "q": { "version": "1.5.1", @@ -7839,28 +10121,10 @@ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" }, - "quote-stream": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz", - "integrity": "sha1-hJY/jJwmuULhU/7rU6rnRlK34LI=", - "requires": { - "buffer-equal": "0.0.1", - "minimist": "1.2.0", - "through2": "2.0.3" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" - } - } - }, "randomatic": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz", "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", - "dev": true, "requires": { "is-number": "4.0.0", "kind-of": "6.0.2", @@ -7870,15 +10134,14 @@ "is-number": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" } } }, "randombytes": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha1-0wLFIpSFiISKjTAMkytEwkIx2oA=", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", "requires": { "safe-buffer": "5.1.2" } @@ -7886,7 +10149,7 @@ "randomfill": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha1-ySGW/IarQr6YPxvzF3giSTHWFFg=", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "requires": { "randombytes": "2.0.6", "safe-buffer": "5.1.2" @@ -7913,6 +10176,32 @@ "unpipe": "1.0.0" } }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "optional": true, + "requires": { + "deep-extend": "0.6.0", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "optional": true + }, + "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", @@ -7921,23 +10210,32 @@ "mute-stream": "0.0.7" } }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "read-chunk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/read-chunk/-/read-chunk-2.1.0.tgz", + "integrity": "sha1-agTAkoAF7Z1C4aasVgDhnLx/9lU=", "requires": { - "load-json-file": "2.0.0", + "pify": "3.0.0", + "safe-buffer": "5.1.2" + } + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "requires": { + "load-json-file": "4.0.0", "normalize-package-data": "2.4.0", - "path-type": "2.0.0" + "path-type": "3.0.0" } }, "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "requires": { "find-up": "2.1.0", - "read-pkg": "2.0.0" + "read-pkg": "3.0.0" } }, "readable-stream": { @@ -7965,6 +10263,42 @@ "set-immediate-shim": "1.0.1" } }, + "recache": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/recache/-/recache-0.3.1.tgz", + "integrity": "sha1-MAN/ywnFlOTgeWA0LdWm/wqRTd8=" + }, + "recast": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.15.0.tgz", + "integrity": "sha512-47C2mIxQYvFICrTNuV4+xGgBa1nAoq42ANN5oDTSBIJ50NX7jcki7gAC6HWYptnQgHmqIRTHJq8OKdi3fwgyNQ==", + "requires": { + "ast-types": "0.11.5", + "esprima": "4.0.0", + "private": "0.1.8", + "source-map": "0.6.1" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "requires": { + "resolve": "1.7.1" + } + }, "redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", @@ -8015,12 +10349,12 @@ "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=" + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" }, "regenerator-transform": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha1-HkmWg3Ix2ot/PPQRTXG1aRoGgN0=", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", "requires": { "babel-runtime": "6.26.0", "babel-types": "6.26.0", @@ -8030,8 +10364,7 @@ "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", - "dev": true, + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", "requires": { "is-equal-shallow": "0.1.3" } @@ -8039,7 +10372,7 @@ "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "requires": { "extend-shallow": "3.0.2", "safe-regex": "1.1.0" @@ -8098,6 +10431,11 @@ "is-finite": "1.0.2" } }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=" + }, "request": { "version": "2.87.0", "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", @@ -8123,6 +10461,100 @@ "tough-cookie": "2.3.4", "tunnel-agent": "0.6.0", "uuid": "3.2.1" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.2" + } + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.2" + } + } } }, "require-directory": { @@ -8148,8 +10580,21 @@ "requires": { "caller-path": "0.1.0", "resolve-from": "1.0.1" + }, + "dependencies": { + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + } } }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, "resolve": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", @@ -8158,31 +10603,62 @@ "path-parse": "1.0.5" } }, - "resolve-from": { + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "requires": { + "resolve-from": "3.0.0" + } + }, + "resolve-dir": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "requires": { + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=" }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=" }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "requires": { + "lowercase-keys": "1.0.1" + } + }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, "requires": { "onetime": "2.0.1", "signal-exit": "3.0.2" } }, + "resumer": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz", + "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=", + "requires": { + "through": "2.3.8" + } + }, "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha1-uKSCXVvbH8P29Twrwz+BOIaBx7w=" + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" }, "right-align": { "version": "0.1.3", @@ -8193,12 +10669,9 @@ } }, "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "requires": { - "glob": "7.1.2" - } + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", + "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=" }, "ripemd160": { "version": "2.0.2", @@ -8209,6 +10682,11 @@ "inherits": "2.0.3" } }, + "rlp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.0.0.tgz", + "integrity": "sha1-nbOE/0uJqPYVY9kjldhiWxjzr7A=" + }, "rsa-pem-to-jwk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/rsa-pem-to-jwk/-/rsa-pem-to-jwk-1.1.3.tgz", @@ -8237,19 +10715,15 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, "requires": { "is-promise": "2.1.0" - }, - "dependencies": { - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - } } }, + "rustbn.js": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.1.2.tgz", + "integrity": "sha512-bAkNqSHYdJdFsBC7Z11JgzYktL31HIpB2o70jZcGiL1U1TVtPyvaVhDrGWwS8uZtaqwW2k6NOPGZCqW/Dgh5Lg==" + }, "rx-lite": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", @@ -8265,6 +10739,14 @@ "rx-lite": "4.0.8" } }, + "rxjs": { + "version": "5.5.11", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.11.tgz", + "integrity": "sha512-3bjO7UwWfA2CV7lmwYMBzj4fQ6Cq+ftHc2MvUe+WMS7wcdJ1LosDWmdjPQanYp2dBRj572p7PeU81JUxHKOcBA==", + "requires": { + "symbol-observable": "1.0.1" + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -8278,6 +10760,14 @@ "ret": "0.1.15" } }, + "safefs": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/safefs/-/safefs-3.2.2.tgz", + "integrity": "sha1-gXDBRE1wOOCMrqBaN0+uL6NJ4Vw=", + "requires": { + "graceful-fs": "4.1.11" + } + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -8292,17 +10782,32 @@ "sax": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=" + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "scandirectory": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/scandirectory/-/scandirectory-2.5.0.tgz", + "integrity": "sha1-bOA/VKCQtmjjy+2/IO354xBZPnI=", + "requires": { + "ignorefs": "1.2.0", + "safefs": "3.2.2", + "taskgroup": "4.3.1" + } }, "schema-utils": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.5.tgz", - "integrity": "sha1-IYNvBgiqwXt4+ePiTa/xSlyhOj4=", + "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", "requires": { - "ajv": "6.5.0", + "ajv": "6.5.1", "ajv-keywords": "3.2.0" } }, + "scoped-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/scoped-regex/-/scoped-regex-1.0.0.tgz", + "integrity": "sha1-o0a7Gs1CB65wvXwMfKnlZra63bg=" + }, "scrypt": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/scrypt/-/scrypt-6.0.3.tgz", @@ -8331,7 +10836,7 @@ "secp256k1": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-3.5.0.tgz", - "integrity": "sha1-Z307io4E4aX6OBoa5DfFQge3ONA=", + "integrity": "sha512-e5QIJl8W7Y4tT6LHffVcZAxJjvpgE5Owawv6/XCYPQljE9aP2NFFddQ8OYMKhdLshNu88FfL3qCN3/xYkXGRsA==", "requires": { "bindings": "1.3.0", "bip66": "1.1.5", @@ -8361,15 +10866,20 @@ } } }, + "semaphore": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semaphore/-/semaphore-1.1.0.tgz", + "integrity": "sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA==" + }, "semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha1-3Eu8emyp2Rbe5dQ1FvAJK1j3uKs=" + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" }, "send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha1-bsyh4PjBVtFBWXVZhI32RzCmu8E=", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "requires": { "debug": "2.6.9", "depd": "1.1.2", @@ -8389,7 +10899,7 @@ "serve-static": { "version": "1.13.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", - "integrity": "sha1-CV6Ecv1bRiN9tQzkhqQ/S4bGzsE=", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "requires": { "encodeurl": "1.0.2", "escape-html": "1.0.3", @@ -8422,7 +10932,7 @@ "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "requires": { "extend-shallow": "2.0.1", "is-extendable": "0.1.1", @@ -8467,10 +10977,13 @@ "nan": "2.10.0" } }, - "shallow-copy": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", - "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=" + "shallow-clone": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.0.tgz", + "integrity": "sha512-Drg+nOI+ofeuslBf0nulyWLZhK1BZprqNvPJaiB4VvES+9gC6GG+qOVAfuO12zVSgxq9SKevcme7S3uDT6Be8w==", + "requires": { + "kind-of": "6.0.2" + } }, "shebang-command": { "version": "1.2.0", @@ -8490,11 +11003,6 @@ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.5.3.tgz", "integrity": "sha1-xUmCuZbHbvDB5rWfvcWCX1txMRM=" }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" - }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -8523,6 +11031,15 @@ "simple-concat": "1.0.0" } }, + "simples": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/simples/-/simples-0.8.8.tgz", + "integrity": "sha1-gIRY0JK7aFhASMwQTEefAgBoNqY=", + "requires": { + "mime.json": "1.0.18", + "recache": "0.3.1" + } + }, "sinon": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", @@ -8532,18 +11049,12 @@ "@sinonjs/formatio": "2.0.0", "diff": "3.5.0", "lodash.get": "4.4.2", - "lolex": "2.6.0", - "nise": "1.3.3", + "lolex": "2.7.0", + "nise": "1.4.1", "supports-color": "5.4.0", "type-detect": "4.0.8" }, "dependencies": { - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -8567,26 +11078,19 @@ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" }, "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "2.0.0" - }, - "dependencies": { - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - } - } + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=" + }, + "slide": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", + "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "requires": { "base": "0.11.2", "debug": "2.6.9", @@ -8619,7 +11123,7 @@ "snapdragon-node": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "requires": { "define-property": "1.0.0", "isobject": "3.0.1", @@ -8665,7 +11169,7 @@ "snapdragon-util": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "requires": { "kind-of": "3.2.2" }, @@ -8680,6 +11184,14 @@ } } }, + "sntp": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", + "requires": { + "hoek": "0.9.1" + } + }, "solc": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/solc/-/solc-0.4.24.tgz", @@ -8725,7 +11237,15 @@ "jsonfile": "2.4.0", "klaw": "1.3.1", "path-is-absolute": "1.0.1", - "rimraf": "2.6.2" + "rimraf": "2.2.8" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" } }, "load-json-file": { @@ -8808,14 +11328,6 @@ "strip-ansi": "3.0.1" } }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "requires": { - "is-utf8": "0.2.1" - } - }, "which-module": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", @@ -8869,7 +11381,7 @@ "source-list-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", - "integrity": "sha1-qqR0A/eyRakvvJfqCPJQ1gh+0IU=" + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==" }, "source-map": { "version": "0.5.7", @@ -8891,7 +11403,7 @@ "source-map-support": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", - "integrity": "sha1-Aoam3ovkJkEzhZTpfM6nXwosWF8=", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "requires": { "source-map": "0.5.7" } @@ -8904,7 +11416,7 @@ "spdx-correct": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", - "integrity": "sha1-BaW01xU6GVvJLDxCW2nzsqlSTII=", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", "requires": { "spdx-expression-parse": "3.0.0", "spdx-license-ids": "3.0.0" @@ -8913,12 +11425,12 @@ "spdx-exceptions": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", - "integrity": "sha1-LHrmEFbHFKW5ubKyr30xHvXHj+k=" + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" }, "spdx-expression-parse": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "requires": { "spdx-exceptions": "2.1.0", "spdx-license-ids": "3.0.0" @@ -8927,12 +11439,12 @@ "spdx-license-ids": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", - "integrity": "sha1-enzShHDMbToc/m1miG9rxDDTrIc=" + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "requires": { "extend-shallow": "3.0.2" } @@ -8940,7 +11452,7 @@ "split2": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", - "integrity": "sha1-GGsldbz4PoW30YRldWI47k7kJJM=", + "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", "requires": { "through2": "2.0.3" } @@ -8951,9 +11463,9 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", - "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", "requires": { "asn1": "0.2.3", "assert-plus": "1.0.0", @@ -8962,9 +11474,20 @@ "ecc-jsbn": "0.1.1", "getpass": "0.1.7", "jsbn": "0.1.1", + "safer-buffer": "2.1.2", "tweetnacl": "0.14.5" }, "dependencies": { + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", @@ -8984,14 +11507,6 @@ "integrity": "sha1-qPbq7KkGdMMz58Q5U/J1tFFRBpU=", "dev": true }, - "static-eval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.0.tgz", - "integrity": "sha512-6flshd3F1Gwm+Ksxq463LtFd1liC77N/PX1FVVc3OzL3hAmo2fwHFbuArkcfi7s9rTNsLEhcRmXGFZhlgy40uw==", - "requires": { - "escodegen": "1.9.1" - } - }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -9011,27 +11526,6 @@ } } }, - "static-module": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/static-module/-/static-module-2.2.5.tgz", - "integrity": "sha512-D8vv82E/Kpmz3TXHKG8PPsCPg+RAX6cbCOyvjM6x04qZtQ47EtJFVwRsdov3n5d6/6ynrOY9XB4JkaZwB2xoRQ==", - "requires": { - "concat-stream": "1.6.2", - "convert-source-map": "1.5.1", - "duplexer2": "0.1.4", - "escodegen": "1.9.1", - "falafel": "2.1.0", - "has": "1.0.1", - "magic-string": "0.22.5", - "merge-source-map": "1.0.4", - "object-inspect": "1.4.1", - "quote-stream": "1.0.2", - "readable-stream": "2.3.6", - "shallow-copy": "0.0.1", - "static-eval": "2.0.0", - "through2": "2.0.3" - } - }, "statuses": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", @@ -9047,9 +11541,9 @@ } }, "stream-http": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.2.tgz", - "integrity": "sha512-QllfrBhqF1DPcz46WxKTs6Mz1Bpc+8Qm6vbqOpVav5odAXwbyzwnEczoWqtxrsmlO+cJqtPrp/8gWKWjaKLLlA==", + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", "requires": { "builtin-status-codes": "3.0.0", "inherits": "2.0.3", @@ -9077,10 +11571,24 @@ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" }, + "string-replace-async": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/string-replace-async/-/string-replace-async-1.2.1.tgz", + "integrity": "sha1-1SzcfjOBQbvq6jRx3jEhUCjJo6o=", + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=" + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "requires": { "is-fullwidth-code-point": "2.0.0", "strip-ansi": "4.0.0" @@ -9091,11 +11599,6 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -9106,6 +11609,16 @@ } } }, + "string.prototype.trim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz", + "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=", + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.12.0", + "function-bind": "1.1.1" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -9114,6 +11627,11 @@ "safe-buffer": "5.1.2" } }, + "stringstream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==" + }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -9123,9 +11641,21 @@ } }, "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-bom-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", + "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", + "requires": { + "first-chunk-stream": "2.0.0", + "strip-bom": "2.0.0" + } }, "strip-dirs": { "version": "2.1.0", @@ -9160,13 +11690,12 @@ "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", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.19.1.tgz", - "integrity": "sha1-WR/8gLzv4mi3fF2evAUF13Jhn4U=", + "integrity": "sha512-IRE+ijgojrygQi3rsqT0U4dd+UcPCqcVvauZpCnQrGAlEe+FUIyrK93bUDScamesjP08JlQNsFJU+KmPedP5Og==", "requires": { "loader-utils": "1.1.0", "schema-utils": "0.3.0" @@ -9188,6 +11717,11 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, "schema-utils": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", @@ -9244,15 +11778,6 @@ "xhr-request-promise": "0.1.2" }, "dependencies": { - "buffer": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.1.0.tgz", - "integrity": "sha512-YkIRgwsZwJWTnyQrsBTWefizHh+8GYj3kbL1BTiAQ/9pwpino0G7B2gp5tx/FUBqUlvtxV85KNR3mwfAtv15Yw==", - "requires": { - "base64-js": "1.3.0", - "ieee754": "1.1.11" - } - }, "eth-lib": { "version": "0.1.27", "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.27.tgz", @@ -9266,16 +11791,76 @@ "ws": "3.3.3", "xhr-request-promise": "0.1.2" } + }, + "got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "requires": { + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-plain-obj": "1.1.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "p-cancelable": "0.3.0", + "p-timeout": "1.2.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "url-parse-lax": "1.0.0", + "url-to-options": "1.0.1" + } + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + }, + "p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" + }, + "p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "requires": { + "p-finally": "1.0.0" + } + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "1.0.4" + } } } }, + "symbol-observable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz", + "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=" + }, "table": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/table/-/table-4.0.3.tgz", "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", "dev": true, "requires": { - "ajv": "6.5.0", + "ajv": "6.5.1", "ajv-keywords": "3.2.0", "chalk": "2.4.1", "lodash": "4.17.10", @@ -9289,7 +11874,7 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "1.9.1" + "color-convert": "1.9.2" } }, "chalk": { @@ -9309,6 +11894,15 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + } + }, "supports-color": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", @@ -9321,14 +11915,41 @@ } }, "tapable": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", - "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.0.0.tgz", + "integrity": "sha512-dQRhbNQkRnaqauC7WqSJ21EEksgT0fYZX2lqXzGkpo8JNig9zGZTYoMGvyI2nWmXlE2VSVXVDu7wLVGu/mQEsg==" + }, + "tape": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/tape/-/tape-4.9.1.tgz", + "integrity": "sha512-6fKIXknLpoe/Jp4rzHKFPpJUHDHDqn8jus99IfPnHIjyz78HYlefTGD3b5EkbQzuLfaEvmfPK3IolLgq2xT3kw==", + "requires": { + "deep-equal": "1.0.1", + "defined": "1.0.0", + "for-each": "0.3.3", + "function-bind": "1.1.1", + "glob": "7.1.2", + "has": "1.0.3", + "inherits": "2.0.3", + "minimist": "1.2.0", + "object-inspect": "1.6.0", + "resolve": "1.7.1", + "resumer": "0.0.0", + "string.prototype.trim": "1.1.2", + "through": "2.3.8" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } }, "tar": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-3.2.1.tgz", - "integrity": "sha1-mqjkHIjwnnbBZgdbxx+T1RZuYbE=", + "integrity": "sha512-ZSzds1E0IqutvMU8HxjMaU8eB7urw2fGwTq88ukDOVuUIh0656l7/P7LiVPxhO5kS4flcRJQk8USG+cghQbTUQ==", "requires": { "chownr": "1.0.1", "minipass": "2.3.3", @@ -9350,7 +11971,7 @@ "integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==", "requires": { "bl": "1.2.2", - "buffer-alloc": "1.1.0", + "buffer-alloc": "1.2.0", "end-of-stream": "1.4.1", "fs-constants": "1.0.0", "readable-stream": "2.3.6", @@ -9387,6 +12008,24 @@ } } }, + "taskgroup": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/taskgroup/-/taskgroup-4.3.1.tgz", + "integrity": "sha1-feGT/r12gnPEV3MElwJNUSwnkVo=", + "requires": { + "ambi": "2.5.0", + "csextends": "1.2.0" + } + }, + "temp": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", + "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", + "requires": { + "os-tmpdir": "1.0.2", + "rimraf": "2.2.8" + } + }, "text-encoding": { "version": "0.6.4", "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", @@ -9396,8 +12035,12 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, + "textextensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/textextensions/-/textextensions-2.2.0.tgz", + "integrity": "sha512-j5EMxnryTvKxwH2Cq+Pb43tsf6sdEgw6Pdwxk83mPaq0ToeFJt6WE4J3s5BqY7vmjlLgkgXvhtXUxo80FyBhCA==" }, "thenify": { "version": "3.3.0", @@ -9429,14 +12072,6 @@ "xtend": "4.0.1" } }, - "time-cache": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/time-cache/-/time-cache-0.3.0.tgz", - "integrity": "sha1-7Q388P2kXNyV+9YB/agw6/G9XYs=", - "requires": { - "lodash.throttle": "4.1.1" - } - }, "timed-out": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", @@ -9454,7 +12089,6 @@ "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, "requires": { "os-tmpdir": "1.0.2" } @@ -9474,11 +12108,6 @@ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" }, - "to-iso-string": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", - "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=" - }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -9500,7 +12129,7 @@ "to-regex": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "requires": { "define-property": "2.0.2", "extend-shallow": "3.0.2", @@ -9523,10 +12152,11 @@ "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=" }, "tough-cookie": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", - "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.2.tgz", + "integrity": "sha512-vahm+X8lSV/KjXziec8x5Vp0OTC9mq8EVCOApIsRAooeuMPSO8aT7PFACYkaL0yZ/3hVqw+8DzhCJwl8H2Ad6w==", "requires": { + "psl": "1.1.28", "punycode": "1.4.1" }, "dependencies": { @@ -9537,6 +12167,11 @@ } } }, + "treeify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz", + "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==" + }, "trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", @@ -9554,9 +12189,9 @@ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" }, "tslib": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.1.tgz", - "integrity": "sha512-avfPS28HmGLLc2o4elcc2EIq2FcH++Yo5YxpBZi9Yw93BCTGFthI4HPE4Rpep6vSYQaK8e69PelM44tPj+RaQg==" + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.2.tgz", + "integrity": "sha512-AVP5Xol3WivEr7hnssHDsaM+lVrVXWUvd1cfXTRkTj80b//6g2wIFEH6hZG0muGZRnHGrfttpdzRk3YlBkWjKw==" }, "tty-browserify": { "version": "0.0.0", @@ -9564,12 +12199,9 @@ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=" }, "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "5.1.2" - } + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=" }, "tweetnacl": { "version": "1.0.0", @@ -9580,6 +12212,7 @@ "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, "requires": { "prelude-ls": "1.1.2" } @@ -9597,8 +12230,28 @@ "requires": { "media-typer": "0.3.0", "mime-types": "2.1.18" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "1.33.0" + } + } } }, + "typechecker": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/typechecker/-/typechecker-2.1.0.tgz", + "integrity": "sha1-0cIJOlT/ihn1jP+HfuqlTyJC04M=" + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -9607,7 +12260,7 @@ "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha1-qX7nqf9CaRufeD/xvFES/j/KkIA=", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "requires": { "is-typedarray": "1.0.0" } @@ -9622,11 +12275,31 @@ "yargs": "3.10.0" }, "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + }, "yargs": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", @@ -9681,16 +12354,16 @@ "integrity": "sha1-pyyTb3e5a/UvX357RnGAYoVR3vs=", "requires": { "base64-js": "0.0.8", - "ieee754": "1.1.11", + "ieee754": "1.1.12", "isarray": "1.0.0" } } } }, "underscore": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.0.tgz", - "integrity": "sha512-4IV1DSSxC1QK48j9ONFK1MoIAKKkbE8i7u55w2R6IqBqbT7A/iG7aZBCR2Bi8piF0Uz+i/MG1aeqLwl/5vqF+A==" + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" }, "underscore.string": { "version": "3.3.4", @@ -9748,6 +12421,11 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" }, + "unorm": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.4.1.tgz", + "integrity": "sha1-NkIA1fE2RsqLzURJAnEzVhR5IwA=" + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -9789,17 +12467,22 @@ } } }, + "untildify": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.3.tgz", + "integrity": "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==" + }, "upath": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==" }, "uri-js": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.1.tgz", - "integrity": "sha512-jpKCA3HjsBfSDOEgxRDAxQCNyHfCPSbq57PqCkd3gAyBuPb3IWxw54EHncqESznIdqSetHfw3D7ylThu2Kcc9A==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "requires": { - "punycode": "2.1.1" + "punycode": "2.1.0" } }, "uri-path": { @@ -9837,7 +12520,7 @@ "url-loader": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-0.6.2.tgz", - "integrity": "sha1-oAenEJYg6dmI0UvOZ3od7Lmpk/c=", + "integrity": "sha512-h3qf9TNn53BpuXTTcpC+UehiRrl0Cv45Yr/xWayApjw6G8Bg2dGke7rIwDQ39piciWCWrC+WiqLjOh3SUp9n0Q==", "requires": { "loader-utils": "1.1.0", "mime": "1.4.1", @@ -9860,6 +12543,11 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, "schema-utils": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", @@ -9871,11 +12559,18 @@ } }, "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", "requires": { - "prepend-http": "1.0.4" + "prepend-http": "2.0.0" + }, + "dependencies": { + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + } } }, "url-set-query": { @@ -9891,29 +12586,22 @@ "use": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", - "integrity": "sha1-FHFr8D/f79AwQK71jYtLhfOnxUQ=", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", "requires": { "kind-of": "6.0.2" } }, "utf8": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", - "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz", + "integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=" }, "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", "requires": { - "inherits": "2.0.1" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" - } + "inherits": "2.0.3" } }, "util-deprecate": { @@ -9931,10 +12619,15 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" }, + "v8-compile-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.0.tgz", + "integrity": "sha512-qNdTUMaCjPs4eEnM3W9H94R3sU70YCuT+/ST7nUf+id1bVOrdjrpUaeZLqPBPRph3hsgn4a4BvwpxhHZx+oSDg==" + }, "validate-npm-package-license": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", - "integrity": "sha1-gWQ7y+8b3+zUYjeT3EZIlIupgzg=", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", "requires": { "spdx-correct": "3.0.0", "spdx-expression-parse": "3.0.0" @@ -9963,6 +12656,43 @@ "assert-plus": "1.0.0", "core-util-is": "1.0.2", "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + } + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "requires": { + "clone": "1.0.4", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz", + "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0", + "strip-bom-stream": "2.0.0", + "vinyl": "1.2.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + } } }, "viz.js": { @@ -9970,11 +12700,6 @@ "resolved": "https://registry.npmjs.org/viz.js/-/viz.js-1.8.2.tgz", "integrity": "sha512-W+1+N/hdzLpQZEcvz79n2IgUE9pfx6JLdHh3Kh8RGvLL8P1LdJVQmi2OsDcLdY4QVID4OUy+FPelyerX0nJxIQ==" }, - "vlq": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", - "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==" - }, "vm-browserify": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", @@ -9993,6 +12718,29 @@ "neo-async": "2.5.1" } }, + "watchr": { + "version": "2.4.13", + "resolved": "https://registry.npmjs.org/watchr/-/watchr-2.4.13.tgz", + "integrity": "sha1-10hHu01vkPYf4sdPn2hmKqDgdgE=", + "requires": { + "eachr": "2.0.4", + "extendr": "2.1.0", + "extract-opts": "2.2.0", + "ignorefs": "1.2.0", + "safefs": "3.2.2", + "scandirectory": "2.5.0", + "taskgroup": "4.3.1", + "typechecker": "2.1.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "requires": { + "defaults": "1.0.3" + } + }, "web3": { "version": "1.0.0-beta.34", "resolved": "https://registry.npmjs.org/web3/-/web3-1.0.0-beta.34.tgz", @@ -10017,10 +12765,52 @@ "underscore": "1.8.3" }, "dependencies": { + "got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "requires": { + "decompress-response": "3.3.0", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-plain-obj": "1.1.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "isurl": "1.0.0", + "lowercase-keys": "1.0.1", + "p-cancelable": "0.3.0", + "p-timeout": "1.2.1", + "safe-buffer": "5.1.2", + "timed-out": "4.0.1", + "url-parse-lax": "1.0.0", + "url-to-options": "1.0.1" + } + }, + "p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==" + }, + "p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y=", + "requires": { + "p-finally": "1.0.0" + } + }, "underscore": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "1.0.4" + } } } }, @@ -10078,6 +12868,13 @@ "requires": { "any-promise": "1.3.0", "eventemitter3": "1.1.1" + }, + "dependencies": { + "eventemitter3": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.1.1.tgz", + "integrity": "sha1-R3hr2qCHyvext15zq8XH1UAVjNA=" + } } }, "web3-core-requestmanager": { @@ -10109,6 +12906,11 @@ "web3-core-helpers": "1.0.0-beta.34" }, "dependencies": { + "eventemitter3": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.1.1.tgz", + "integrity": "sha1-R3hr2qCHyvext15zq8XH1UAVjNA=" + }, "underscore": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", @@ -10355,18 +13157,14 @@ "version": "1.8.3", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "utf8": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.1.tgz", + "integrity": "sha1-LgHbAvfY0JRPdxBPFgnrDDBM92g=" } } }, - "webcrypto-core": { - "version": "0.1.22", - "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-0.1.22.tgz", - "integrity": "sha512-UoNP+/3I74foiQLe1m4ToxoN3oloWnH3Na0TPWNzu/ALhDl1MbhgS0QEezdNNQbkj/6i9cf59k7LeOAAvd0hzg==", - "optional": true, - "requires": { - "tslib": "1.9.1" - } - }, "webcrypto-shim": { "version": "github:dignifiedquire/webcrypto-shim#190bc9ec341375df6025b17ae12ddb2428ea49c8" }, @@ -10375,9 +13173,9 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.12.0.tgz", "integrity": "sha512-Sw7MdIIOv/nkzPzee4o0EdvCuPmxT98+vVpIvwtcwcF1Q4SDSNp92vwcKc4REe7NItH9f1S4ra9FuQ7yuYZ8bQ==", "requires": { - "acorn": "5.5.3", + "acorn": "5.6.2", "acorn-dynamic-import": "2.0.2", - "ajv": "6.5.0", + "ajv": "6.5.1", "ajv-keywords": "3.2.0", "async": "2.6.1", "enhanced-resolve": "3.4.1", @@ -10399,11 +13197,108 @@ "yargs": "8.0.2" }, "dependencies": { + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + }, + "dependencies": { + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + } + } + }, + "enhanced-resolve": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "object-assign": "4.1.1", + "tapable": "0.2.8" + } + }, "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "1.3.1" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "requires": { + "pify": "2.3.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, "supports-color": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", @@ -10411,6 +13306,273 @@ "requires": { "has-flag": "2.0.0" } + }, + "tapable": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", + "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=" + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "requires": { + "camelcase": "4.1.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "read-pkg-up": "2.0.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "7.0.0" + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "requires": { + "camelcase": "4.1.0" + } + } + } + }, + "webpack-addons": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/webpack-addons/-/webpack-addons-1.1.5.tgz", + "integrity": "sha512-MGO0nVniCLFAQz1qv22zM02QPjcpAoJdy7ED0i3Zy7SY1IecgXCm460ib7H/Wq7e9oL5VL6S2BxaObxwIcag0g==", + "requires": { + "jscodeshift": "0.4.1" + }, + "dependencies": { + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "requires": { + "arr-flatten": "1.1.0" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + }, + "ast-types": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.10.1.tgz", + "integrity": "sha512-UY7+9DPzlJ9VM8eY0b2TUZcZvF+1pO0hzMtAyjBYKhOmnvRlqYNYnWdtsMj0V16CGaMlpL0G1jnLbLo4AyotuQ==" + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "jscodeshift": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.4.1.tgz", + "integrity": "sha512-iOX6If+hsw0q99V3n31t4f5VlD1TQZddH08xbT65ZqA7T4Vkx68emrDZMUOLVvCEAJ6NpAk7DECe3fjC/t52AQ==", + "requires": { + "async": "1.5.2", + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-preset-es2015": "6.24.1", + "babel-preset-stage-1": "6.24.1", + "babel-register": "6.26.0", + "babylon": "6.18.0", + "colors": "1.3.0", + "flow-parser": "0.74.0", + "lodash": "4.17.10", + "micromatch": "2.3.11", + "node-dir": "0.1.8", + "nomnom": "1.8.1", + "recast": "0.12.9", + "temp": "0.8.3", + "write-file-atomic": "1.3.4" + } + }, + "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" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "recast": { + "version": "0.12.9", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.12.9.tgz", + "integrity": "sha512-y7ANxCWmMW8xLOaiopiRDlyjQ9ajKRENBH+2wjntIbk3A6ZR1+BLQttkmSHMY7Arl+AAZFwJ10grg2T6f1WI8A==", + "requires": { + "ast-types": "0.10.1", + "core-js": "2.5.7", + "esprima": "4.0.0", + "private": "0.1.8", + "source-map": "0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "webpack-cli": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-2.1.5.tgz", + "integrity": "sha512-CiWQR+1JS77rmyiO6y1q8Kt/O+e8nUUC9YfJ25JtSmzDwbqJV7vIsh3+QKRHVTbTCa0DaVh8iY1LBiagUIDB3g==", + "requires": { + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "diff": "3.5.0", + "enhanced-resolve": "4.0.0", + "envinfo": "5.10.0", + "glob-all": "3.1.0", + "global-modules": "1.0.0", + "got": "8.3.1", + "import-local": "1.0.0", + "inquirer": "5.2.0", + "interpret": "1.1.0", + "jscodeshift": "0.5.1", + "listr": "0.14.1", + "loader-utils": "1.1.0", + "lodash": "4.17.10", + "log-symbols": "2.2.0", + "mkdirp": "0.5.1", + "p-each-series": "1.0.0", + "p-lazy": "1.0.0", + "prettier": "1.13.5", + "supports-color": "5.4.0", + "v8-compile-cache": "2.0.0", + "webpack-addons": "1.1.5", + "yargs": "11.1.0", + "yeoman-environment": "2.2.0", + "yeoman-generator": "2.0.5" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, + "webpack-core": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", + "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", + "requires": { + "source-list-map": "0.1.8", + "source-map": "0.4.4" + }, + "dependencies": { + "source-list-map": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", + "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=" + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": "1.0.1" + } } } }, @@ -10439,15 +13601,20 @@ "yaeti": "0.0.6" } }, + "whatwg-fetch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", + "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==" + }, "whet.extend": { "version": "0.9.9", "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=" }, "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "requires": { "isexe": "2.0.0" } @@ -10457,6 +13624,15 @@ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "optional": true, + "requires": { + "string-width": "2.1.1" + } + }, "window-size": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-1.1.0.tgz", @@ -10503,9 +13679,9 @@ } }, "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" }, "wrap-ansi": { "version": "2.1.0", @@ -10516,6 +13692,14 @@ "strip-ansi": "3.0.1" }, "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", @@ -10542,6 +13726,54 @@ "mkdirp": "0.5.1" } }, + "write-file-atomic": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-1.3.4.tgz", + "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "slide": "1.1.6" + } + }, + "write-json-file": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-2.3.0.tgz", + "integrity": "sha1-K2TIozAE1UuGmMdtWFp3zrYdoy8=", + "requires": { + "detect-indent": "5.0.0", + "graceful-fs": "4.1.11", + "make-dir": "1.3.0", + "pify": "3.0.0", + "sort-keys": "2.0.0", + "write-file-atomic": "2.3.0" + }, + "dependencies": { + "detect-indent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", + "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=" + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "requires": { + "is-plain-obj": "1.1.0" + } + }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + } + } + } + }, "ws": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", @@ -10602,6 +13834,11 @@ "resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz", "integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=" }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" + }, "xtend": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", @@ -10623,77 +13860,212 @@ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "yargs": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", - "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz", + "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", "requires": { - "camelcase": "4.1.0", - "cliui": "3.2.0", + "cliui": "4.1.0", "decamelize": "1.2.0", + "find-up": "2.1.0", "get-caller-file": "1.0.2", "os-locale": "2.1.0", - "read-pkg-up": "2.0.0", "require-directory": "2.1.1", "require-main-filename": "1.0.1", "set-blocking": "2.0.0", "string-width": "2.1.1", "which-module": "2.0.0", "y18n": "3.2.1", - "yargs-parser": "7.0.0" + "yargs-parser": "9.0.2" + } + }, + "yargs-parser": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz", + "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "requires": { + "camelcase": "4.1.0" + } + }, + "yauzl": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.2.tgz", + "integrity": "sha1-T7G8euH8L1cDe1SvasyP4QMcW3c=", + "requires": { + "buffer-crc32": "0.2.13", + "fd-slicer": "1.1.0" + } + }, + "yeoman-environment": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/yeoman-environment/-/yeoman-environment-2.2.0.tgz", + "integrity": "sha512-gQ+hIW8QRlUo4jGBDCm++qg01SXaIVJ7VyLrtSwk2jQG4vtvluWpsGIl7V8DqT2jGiqukdec0uEyffVEyQgaZA==", + "requires": { + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "globby": "8.0.1", + "grouped-queue": "0.3.3", + "inquirer": "5.2.0", + "is-scoped": "1.0.0", + "lodash": "4.17.10", + "log-symbols": "2.2.0", + "mem-fs": "1.1.3", + "strip-ansi": "4.0.0", + "text-table": "0.2.0", + "untildify": "3.0.3" }, "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "requires": { - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wrap-ansi": "2.1.0" - }, - "dependencies": { - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - } + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" } } } }, - "yargs-parser": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", - "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "yeoman-generator": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/yeoman-generator/-/yeoman-generator-2.0.5.tgz", + "integrity": "sha512-rV6tJ8oYzm4mmdF2T3wjY+Q42jKF2YiiD0VKfJ8/0ZYwmhCKC9Xs2346HVLPj/xE13i68psnFJv7iS6gWRkeAg==", "requires": { - "camelcase": "4.1.0" + "async": "2.6.1", + "chalk": "2.4.1", + "cli-table": "0.3.1", + "cross-spawn": "6.0.5", + "dargs": "5.1.0", + "dateformat": "3.0.3", + "debug": "3.1.0", + "detect-conflict": "1.0.1", + "error": "7.0.2", + "find-up": "2.1.0", + "github-username": "4.1.0", + "istextorbinary": "2.2.1", + "lodash": "4.17.10", + "make-dir": "1.3.0", + "mem-fs-editor": "4.0.2", + "minimist": "1.2.0", + "pretty-bytes": "4.0.2", + "read-chunk": "2.1.0", + "read-pkg-up": "3.0.0", + "rimraf": "2.6.2", + "run-async": "2.3.0", + "shelljs": "0.8.2", + "text-table": "0.2.0", + "through2": "2.0.3", + "yeoman-environment": "2.2.0" }, "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.2" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.4.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + }, + "shelljs": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.2.tgz", + "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", + "requires": { + "glob": "7.1.2", + "interpret": "1.1.0", + "rechoir": "0.6.2" + } + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "3.0.0" + } } } - }, - "yauzl": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", - "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=", - "requires": { - "buffer-crc32": "0.2.13", - "fd-slicer": "1.0.1" - } } } } diff --git a/package.json b/package.json index 97d20fd1f..a9c3b31ce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "embark", - "version": "3.0.10", + "version": "3.1.0", "description": "Embark is a framework that allows you to easily develop and deploy DApps", "scripts": { "lint": "./node_modules/.bin/eslint lib/", @@ -21,6 +21,7 @@ "url": "https://github.com/iurimatias/embark-framework.git" }, "dependencies": { + "ascii-table": "0.0.9", "async": "^2.0.1", "babel-core": "^6.26.0", "babel-loader": "^7.1.2", @@ -29,41 +30,55 @@ "babel-preset-es2016": "^6.24.1", "babel-preset-es2017": "6.24.1", "babel-preset-react": "^6.24.1", - "blessed": "^0.1.81", + "bip39": "^2.5.0", "chokidar": "^2.0.3", + "clone-deep": "^4.0.0", "colors": "^1.1.2", "commander": "^2.15.1", "css-loader": "^0.28.11", "deep-equal": "^1.0.1", "ejs": "^2.5.8", + "eth-ens-namehash": "^2.0.8", "eth-lib": "^0.2.8", - "ethereumjs-testrpc": "^6.0.3", + "ethereumjs-wallet": "^0.6.0", "file-loader": "^1.1.5", "finalhandler": "^1.1.1", "follow-redirects": "^1.2.4", "fs-extra": "^2.0.0", + "ganache-cli": "6.1.0", "globule": "^1.1.0", + "hard-source-webpack-plugin": "^0.6.6", + "http-proxy": "^1.17.0", "http-shutdown": "^1.2.0", + "i18n": "^0.8.3", "ipfs-api": "17.2.4", - "live-plugin-manager": "https://github.com/iurimatias/live-plugin-manager.git", + "live-plugin-manager-git-fix": "^0.12.1", "merge": "^1.2.0", - "mocha": "^2.2.5", - "orbit-db": "^0.17.3", + "mocha": "^3.2.0", + "neo-blessed": "^0.2.0", + "node-http-proxy": "^0.2.3", + "node-ipc": "^9.1.1", + "ora": "^2.1.0", + "os-locale": "^2.1.0", + "p-iteration": "^1.1.7", "parse-json": "^4.0.0", "promptly": "^2.1.0", "propose": "0.0.5", "request": "^2.85.0", "serve-static": "^1.11.1", "shelljs": "^0.5.0", - "solc": "0.4.24", + "simples": "^0.8.8", + "string-replace-async": "^1.2.1", "style-loader": "^0.19.0", "tar": "^3.1.5", "toposort": "^1.0.0", "underscore": "^1.9.0", "underscore.string": "^3.3.4", "url-loader": "^0.6.2", + "uuid": "^3.2.1", "viz.js": "^1.8.1", "web3": "1.0.0-beta.34", + "embark-web3-provider-engine": "14.0.6", "webpack": "^3.10.0", "window-size": "^1.1.0" }, @@ -73,7 +88,6 @@ "ethereum", "dapps", "ipfs", - "orbit", "solidity", "solc", "blockchain", @@ -89,7 +103,6 @@ "grunt-contrib-coffee": "^1.0.0", "grunt-mocha-test": "^0.13.2", "matchdep": "^1.0.1", - "mocha": "^3.2.0", "mocha-sinon": "^1.1.4", "sinon": "^4.5.0" } diff --git a/templates/boilerplate/config/blockchain.js b/templates/boilerplate/config/blockchain.js new file mode 100644 index 000000000..322754ee2 --- /dev/null +++ b/templates/boilerplate/config/blockchain.js @@ -0,0 +1,62 @@ +module.exports = { + development: { + enabled: true, + networkType: "custom", // Can be: testnet, rinkeby, livenet or custom, in which case, it will use the specified networkId + networkId: "1337", // Network id used when networkType is custom + isDev: true, // Uses and ephemeral proof-of-authority network with a pre-funded developer account, mining enabled + genesisBlock: "config/development/genesis.json", // Genesis block to initiate on first creation of a development node + datadir: ".embark/development/datadir", // Data directory for the databases and keystore + mineWhenNeeded: true, // Uses our custom script (if isDev is false) to mine only when needed + nodiscover: true, // Disables the peer discovery mechanism (manual peer addition) + maxpeers: 0, // Maximum number of network peers (network disabled if set to 0) (default: 25) + rpcHost: "localhost", // HTTP-RPC server listening interface (default: "localhost") + rpcPort: 8545, // HTTP-RPC server listening port (default: 8545) + rpcCorsDomain: "auto", // Comma separated list of domains from which to accept cross origin requests (browser enforced) + // When set to "auto", Embark will automatically set the cors to the address of the webserver + proxy: true, // Proxy is used to present meaningful information about transactions + account: { + // "address": "", // When specified, uses that address instead of the default one for the network + password: "config/development/password" // Password to unlock the account + }, + targetGasLimit: 8000000, // Target gas limit sets the artificial target gas floor for the blocks to mine + wsRPC: true, // Enable the WS-RPC server + wsOrigins: "auto", // Origins from which to accept websockets requests + // When set to "auto", Embark will automatically set the cors to the address of the webserver + wsHost: "localhost", // WS-RPC server listening interface (default: "localhost") + wsPort: 8546, // WS-RPC server listening port (default: 8546) + simulatorMnemonic: "example exile argue silk regular smile grass bomb merge arm assist farm", // Mnemonic used by the simulator to generate a wallet + simulatorBlocktime: 0 // Specify blockTime in seconds for automatic mining. Default is 0 and no auto-mining. + }, + testnet: { + enabled: true, + networkType: "testnet", + light: true, + rpcHost: "localhost", + rpcPort: 8545, + rpcCorsDomain: "http://localhost:8000", + account: { + password: "config/testnet/password" + } + }, + livenet: { + enabled: true, + networkType: "livenet", + light: true, + rpcHost: "localhost", + rpcPort: 8545, + rpcCorsDomain: "http://localhost:8000", + account: { + password: "config/livenet/password" + } + }, + privatenet: { + enabled: true, + networkType: "custom", + rpcHost: "localhost", + rpcPort: 8545, + rpcCorsDomain: "http://localhost:8000", + datadir: "yourdatadir", + networkId: "123", + bootnodes: "" + } +}; diff --git a/templates/boilerplate/config/communication.js b/templates/boilerplate/config/communication.js new file mode 100644 index 000000000..035d95def --- /dev/null +++ b/templates/boilerplate/config/communication.js @@ -0,0 +1,13 @@ +module.exports = { + default: { + enabled: true, + provider: "whisper", // Communication provider. Currently, Embark only supports whisper + available_providers: ["whisper"], // Array of available providers + connection: { + host: "localhost", // Host of the blockchain node + port: 8546, // Port of the blockchain node + type: "ws" // Type of connection (ws or rpc) + } + } +}; + diff --git a/templates/boilerplate/config/communication.json b/templates/boilerplate/config/communication.json deleted file mode 100644 index 80ec2f80e..000000000 --- a/templates/boilerplate/config/communication.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "default": { - "enabled": true, - "provider": "whisper", - "available_providers": ["whisper", "orbit"], - "connection": { - "host": "localhost", - "port": 8546, - "type": "ws" - } - } -} diff --git a/templates/boilerplate/config/contracts.js b/templates/boilerplate/config/contracts.js new file mode 100644 index 000000000..37f7e7c06 --- /dev/null +++ b/templates/boilerplate/config/contracts.js @@ -0,0 +1,41 @@ +module.exports = { + // default applies to all environments + default: { + // Blockchain node to deploy the contracts + deployment: { + host: "localhost", // Host of the blockchain node + port: 8545, // Port of the blockchain node + type: "rpc" // Type of connection (ws or rpc), + // Accounts to use instead of the default account to populate your wallet + /*,accounts: [ + { + privateKey: "your_private_key", + balance: "5 ether" // You can set the balance of the account in the dev environment + // Balances are in Wei, but you can specify the unit with its name + }, + { + privateKeyFile: "path/to/file" // You can put more than one key, separated by , or ; + }, + { + mnemonic: "12 word mnemonic", + addressIndex: "0", // Optionnal. The index to start getting the address + numAddresses: "1", // Optionnal. The number of addresses to get + hdpath: "m/44'/60'/0'/0/" // Optionnal. HD derivation path + } + ]*/ + }, + // order of connections the dapp should connect to + dappConnection: [ + "$WEB3", // uses pre existing web3 object if available (e.g in Mist) + "ws://localhost:8546", + "http://localhost:8545" + ], + gas: "auto", + contracts: { + // example: + //SimpleStorage: { + // args: [ 100 ] + //} + } + } +}; diff --git a/templates/boilerplate/config/contracts.json b/templates/boilerplate/config/contracts.json deleted file mode 100644 index 8ea794ea4..000000000 --- a/templates/boilerplate/config/contracts.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "default": { - "deployment": { - "host": "localhost", - "port": 8545, - "type": "rpc" - }, - "dappConnection": [ - "$WEB3", - "http://localhost:8545" - ], - "gas": "auto", - "contracts": { - } - } -} diff --git a/templates/boilerplate/config/namesystem.js b/templates/boilerplate/config/namesystem.js new file mode 100644 index 000000000..10e20d6b3 --- /dev/null +++ b/templates/boilerplate/config/namesystem.js @@ -0,0 +1,6 @@ +module.exports = { + default: { + available_providers: ["ens"], + provider: "ens" + } +}; diff --git a/templates/boilerplate/config/storage.js b/templates/boilerplate/config/storage.js new file mode 100644 index 000000000..da9dab0a5 --- /dev/null +++ b/templates/boilerplate/config/storage.js @@ -0,0 +1,35 @@ +module.exports = { + default: { + enabled: true, + ipfs_bin: "ipfs", + provider: "ipfs", + available_providers: ["ipfs"], + upload: { + host: "localhost", + port: 5001 + }, + dappConnection: [ + { + provider: "ipfs", + host: "localhost", + port: 5001, + getUrl: "http://localhost:8080/ipfs/" + } + ] + // Configuration to start Swarm in the same terminal as `embark run` + /*,account: { + address: "YOUR_ACCOUNT_ADDRESS", // Address of account accessing Swarm + password: "PATH/TO/PASSWORD/FILE" // File containing the password of the account + }, + swarmPath: "PATH/TO/SWARM/EXECUTABLE" // Path to swarm executable (default: swarm)*/ + }, + development: { + enabled: true, + provider: "ipfs", + upload: { + host: "localhost", + port: 5001, + getUrl: "http://localhost:8080/ipfs/" + } + } +}; diff --git a/templates/boilerplate/config/storage.json b/templates/boilerplate/config/storage.json deleted file mode 100644 index f1041e849..000000000 --- a/templates/boilerplate/config/storage.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "default": { - "enabled": true, - "ipfs_bin": "ipfs", - "provider": "ipfs", - "available_providers": ["ipfs"], - "host": "localhost", - "port": 5001 - }, - "development": { - "enabled": true, - "provider": "ipfs", - "host": "localhost", - "port": 5001, - "getUrl": "http://localhost:8080/ipfs/" - } -} diff --git a/templates/boilerplate/config/webserver.js b/templates/boilerplate/config/webserver.js new file mode 100644 index 000000000..1814065d0 --- /dev/null +++ b/templates/boilerplate/config/webserver.js @@ -0,0 +1,5 @@ +module.exports = { + enabled: true, + host: "localhost", + port: 8000 +}; diff --git a/templates/boilerplate/config/webserver.json b/templates/boilerplate/config/webserver.json deleted file mode 100644 index c28a31138..000000000 --- a/templates/boilerplate/config/webserver.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "enabled": true, - "host": "localhost", - "port": 8000 -} diff --git a/templates/boilerplate/embark.json b/templates/boilerplate/embark.json index 46b016465..34b29498f 100644 --- a/templates/boilerplate/embark.json +++ b/templates/boilerplate/embark.json @@ -11,7 +11,8 @@ "versions": { "web3": "1.0.0-beta", "solc": "0.4.24", - "ipfs-api": "17.2.4" + "ipfs-api": "17.2.4", + "p-iteration": "1.1.7" }, "plugins": {} } diff --git a/templates/boilerplate/test/contract_spec.js b/templates/boilerplate/test/contract_spec.js index 5fa719de5..200301761 100644 --- a/templates/boilerplate/test/contract_spec.js +++ b/templates/boilerplate/test/contract_spec.js @@ -1,24 +1,25 @@ -//describe("SimpleStorage", function() { -// this.timeout(0); -// before(function(done) { -// this.timeout(0); -// var contractsConfig = { -// "SimpleStorage": { -// args: [100] -// } -// }; -// EmbarkSpec.deployAll(contractsConfig, () => { done() }); -// }); -// -// it("should set constructor value", async function() { -// let result = await SimpleStorage.methods.storedData().call(); -// assert.equal(result, 100); -// }); -// -// it("set storage value", async function() { -// await SimpleStorage.methods.set(150).send(); -// let result = await SimpleStorage.methods.get().call(); -// assert.equal(result, 150); -// }); -// -//}); +// /*global contract, config, it, assert*/ +/*const SimpleStorage = require('Embark/contracts/SimpleStorage'); + +config({ + contracts: { + "SimpleStorage": { + args: [100] + } + } +}); + +contract("SimpleStorage", function () { + this.timeout(0); + + it("should set constructor value", async function () { + let result = await SimpleStorage.methods.storedData().call(); + assert.strictEqual(parseInt(result, 10), 100); + }); + + it("set storage value", async function () { + await SimpleStorage.methods.set(150).send(); + let result = await SimpleStorage.methods.get().call(); + assert.strictEqual(parseInt(result, 10), 150); + }); +});*/ diff --git a/templates/demo/app/dapp.js b/templates/demo/app/dapp.js index 5c5f121aa..a598da263 100644 --- a/templates/demo/app/dapp.js +++ b/templates/demo/app/dapp.js @@ -21,7 +21,7 @@ class App extends React.Component { } componentDidMount(){ - __embarkContext.execWhenReady(() => { + EmbarkJS.onReady(() => { if (EmbarkJS.isNewWeb3()) { EmbarkJS.Messages.Providers.whisper.getWhisperVersion((err, version) => { if(!err) diff --git a/templates/demo/config/blockchain.js b/templates/demo/config/blockchain.js new file mode 100644 index 000000000..322754ee2 --- /dev/null +++ b/templates/demo/config/blockchain.js @@ -0,0 +1,62 @@ +module.exports = { + development: { + enabled: true, + networkType: "custom", // Can be: testnet, rinkeby, livenet or custom, in which case, it will use the specified networkId + networkId: "1337", // Network id used when networkType is custom + isDev: true, // Uses and ephemeral proof-of-authority network with a pre-funded developer account, mining enabled + genesisBlock: "config/development/genesis.json", // Genesis block to initiate on first creation of a development node + datadir: ".embark/development/datadir", // Data directory for the databases and keystore + mineWhenNeeded: true, // Uses our custom script (if isDev is false) to mine only when needed + nodiscover: true, // Disables the peer discovery mechanism (manual peer addition) + maxpeers: 0, // Maximum number of network peers (network disabled if set to 0) (default: 25) + rpcHost: "localhost", // HTTP-RPC server listening interface (default: "localhost") + rpcPort: 8545, // HTTP-RPC server listening port (default: 8545) + rpcCorsDomain: "auto", // Comma separated list of domains from which to accept cross origin requests (browser enforced) + // When set to "auto", Embark will automatically set the cors to the address of the webserver + proxy: true, // Proxy is used to present meaningful information about transactions + account: { + // "address": "", // When specified, uses that address instead of the default one for the network + password: "config/development/password" // Password to unlock the account + }, + targetGasLimit: 8000000, // Target gas limit sets the artificial target gas floor for the blocks to mine + wsRPC: true, // Enable the WS-RPC server + wsOrigins: "auto", // Origins from which to accept websockets requests + // When set to "auto", Embark will automatically set the cors to the address of the webserver + wsHost: "localhost", // WS-RPC server listening interface (default: "localhost") + wsPort: 8546, // WS-RPC server listening port (default: 8546) + simulatorMnemonic: "example exile argue silk regular smile grass bomb merge arm assist farm", // Mnemonic used by the simulator to generate a wallet + simulatorBlocktime: 0 // Specify blockTime in seconds for automatic mining. Default is 0 and no auto-mining. + }, + testnet: { + enabled: true, + networkType: "testnet", + light: true, + rpcHost: "localhost", + rpcPort: 8545, + rpcCorsDomain: "http://localhost:8000", + account: { + password: "config/testnet/password" + } + }, + livenet: { + enabled: true, + networkType: "livenet", + light: true, + rpcHost: "localhost", + rpcPort: 8545, + rpcCorsDomain: "http://localhost:8000", + account: { + password: "config/livenet/password" + } + }, + privatenet: { + enabled: true, + networkType: "custom", + rpcHost: "localhost", + rpcPort: 8545, + rpcCorsDomain: "http://localhost:8000", + datadir: "yourdatadir", + networkId: "123", + bootnodes: "" + } +}; diff --git a/templates/demo/config/communication.js b/templates/demo/config/communication.js new file mode 100644 index 000000000..8c4d1f918 --- /dev/null +++ b/templates/demo/config/communication.js @@ -0,0 +1,12 @@ +module.exports = { + default: { + enabled: true, + provider: "whisper", // Communication provider. Currently, Embark only supports whisper + available_providers: ["whisper"], // Array of available providers + connection: { + host: "localhost", // Host of the blockchain node + port: 8546, // Port of the blockchain node + type: "ws" // Type of connection (ws or rpc) + } + } +}; diff --git a/templates/demo/config/communication.json b/templates/demo/config/communication.json deleted file mode 100644 index 80ec2f80e..000000000 --- a/templates/demo/config/communication.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "default": { - "enabled": true, - "provider": "whisper", - "available_providers": ["whisper", "orbit"], - "connection": { - "host": "localhost", - "port": 8546, - "type": "ws" - } - } -} diff --git a/templates/demo/config/contracts.js b/templates/demo/config/contracts.js new file mode 100644 index 000000000..bf2164b32 --- /dev/null +++ b/templates/demo/config/contracts.js @@ -0,0 +1,41 @@ +module.exports = { + // default applies to all environments + default: { + // Blockchain node to deploy the contracts + deployment: { + host: "localhost", // Host of the blockchain node + port: 8545, // Port of the blockchain node + type: "rpc" // Type of connection (ws or rpc), + // Accounts to use instead of the default account to populate your wallet + /*,accounts: [ + { + privateKey: "your_private_key", + balance: "5 ether" // You can set the balance of the account in the dev environment + // Balances are in Wei, but you can specify the unit with its name + }, + { + privateKeyFile: "path/to/file" // You can put more than one key, separated by , or ; + }, + { + mnemonic: "12 word mnemonic", + addressIndex: "0", // Optionnal. The index to start getting the address + numAddresses: "1", // Optionnal. The number of addresses to get + hdpath: "m/44'/60'/0'/0/" // Optionnal. HD derivation path + } + ]*/ + }, + // order of connections the dapp should connect to + dappConnection: [ + "$WEB3", // uses pre existing web3 object if available (e.g in Mist) + "ws://localhost:8546", + "http://localhost:8545" + ], + gas: "auto", + contracts: { + SimpleStorage: { + fromIndex: 0, + args: [100] + } + } + } +}; diff --git a/templates/demo/config/contracts.json b/templates/demo/config/contracts.json deleted file mode 100644 index da7463900..000000000 --- a/templates/demo/config/contracts.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "default": { - "deployment": { - "host": "localhost", - "port": 8545, - "type": "rpc" - }, - "dappConnection": [ - "$WEB3", - "http://localhost:8545" - ], - "gas": "auto", - "contracts": { - "SimpleStorage": { - "fromIndex": 0, - "args": [ - 100 - ] - } - } - } -} diff --git a/templates/demo/config/namesystem.js b/templates/demo/config/namesystem.js new file mode 100644 index 000000000..10e20d6b3 --- /dev/null +++ b/templates/demo/config/namesystem.js @@ -0,0 +1,6 @@ +module.exports = { + default: { + available_providers: ["ens"], + provider: "ens" + } +}; diff --git a/templates/demo/config/storage.js b/templates/demo/config/storage.js new file mode 100644 index 000000000..59ef12bf5 --- /dev/null +++ b/templates/demo/config/storage.js @@ -0,0 +1,35 @@ +module.exports = { + default: { + enabled: true, + ipfs_bin: "ipfs", + provider: "ipfs", + available_providers: ["ipfs"], + upload: { + host: "localhost", + port: 5001 + }, + dappConnection: [ + { + provider:"ipfs", + host: "localhost", + port: 5001, + getUrl: "http://localhost:8080/ipfs/" + } + ] + // Configuration to start Swarm in the same terminal as `embark run` + /*,account: { + address: "YOUR_ACCOUNT_ADDRESS", // Address of account accessing Swarm + password: "PATH/TO/PASSWORD/FILE" // File containing the password of the account + }, + swarmPath: "PATH/TO/SWARM/EXECUTABLE" // Path to swarm executable (default: swarm)*/ + }, + development: { + enabled: true, + provider: "ipfs", + upload: { + host: "localhost", + port: 5001, + getUrl: "http://localhost:8080/ipfs/" + } + } +}; diff --git a/templates/demo/config/storage.json b/templates/demo/config/storage.json deleted file mode 100644 index f1041e849..000000000 --- a/templates/demo/config/storage.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "default": { - "enabled": true, - "ipfs_bin": "ipfs", - "provider": "ipfs", - "available_providers": ["ipfs"], - "host": "localhost", - "port": 5001 - }, - "development": { - "enabled": true, - "provider": "ipfs", - "host": "localhost", - "port": 5001, - "getUrl": "http://localhost:8080/ipfs/" - } -} diff --git a/templates/demo/config/webserver.js b/templates/demo/config/webserver.js new file mode 100644 index 000000000..1814065d0 --- /dev/null +++ b/templates/demo/config/webserver.js @@ -0,0 +1,5 @@ +module.exports = { + enabled: true, + host: "localhost", + port: 8000 +}; diff --git a/templates/demo/config/webserver.json b/templates/demo/config/webserver.json deleted file mode 100644 index c28a31138..000000000 --- a/templates/demo/config/webserver.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "enabled": true, - "host": "localhost", - "port": 8000 -} diff --git a/templates/demo/embark.json b/templates/demo/embark.json index 2f73ec75b..f5706720e 100644 --- a/templates/demo/embark.json +++ b/templates/demo/embark.json @@ -10,7 +10,8 @@ "versions": { "web3": "1.0.0-beta", "solc": "0.4.24", - "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..262cd291a 100644 --- a/templates/demo/test/simple_storage_spec.js +++ b/templates/demo/test/simple_storage_spec.js @@ -1,24 +1,25 @@ -describe("SimpleStorage", function() { - this.timeout(0); - before(function(done) { - this.timeout(0); - var contractsConfig = { - "SimpleStorage": { - args: [100] - } - }; - EmbarkSpec.deployAll(contractsConfig, () => { done() }); - }); - - it("should set constructor value", async function() { - let result = await SimpleStorage.methods.storedData().call(); - assert.equal(result, 100); - }); - - it("set storage value", async function() { - await SimpleStorage.methods.set(150).send(); - let result = SimpleStorage.methods.get().call(); - assert.equal(result, 150); - }); +/*global contract, config, it, assert*/ +const SimpleStorage = require('Embark/contracts/SimpleStorage'); +config({ + contracts: { + "SimpleStorage": { + args: [100] + } + } +}); + +contract("SimpleStorage", function () { + this.timeout(0); + + it("should set constructor value", async function () { + let result = await SimpleStorage.methods.storedData().call(); + assert.strictEqual(parseInt(result, 10), 100); + }); + + it("set storage value", async function () { + await SimpleStorage.methods.set(150).send(); + let result = await SimpleStorage.methods.get().call(); + assert.strictEqual(parseInt(result, 10), 150); + }); }); diff --git a/templates/simple/contracts.js b/templates/simple/contracts.js new file mode 100644 index 000000000..37f7e7c06 --- /dev/null +++ b/templates/simple/contracts.js @@ -0,0 +1,41 @@ +module.exports = { + // default applies to all environments + default: { + // Blockchain node to deploy the contracts + deployment: { + host: "localhost", // Host of the blockchain node + port: 8545, // Port of the blockchain node + type: "rpc" // Type of connection (ws or rpc), + // Accounts to use instead of the default account to populate your wallet + /*,accounts: [ + { + privateKey: "your_private_key", + balance: "5 ether" // You can set the balance of the account in the dev environment + // Balances are in Wei, but you can specify the unit with its name + }, + { + privateKeyFile: "path/to/file" // You can put more than one key, separated by , or ; + }, + { + mnemonic: "12 word mnemonic", + addressIndex: "0", // Optionnal. The index to start getting the address + numAddresses: "1", // Optionnal. The number of addresses to get + hdpath: "m/44'/60'/0'/0/" // Optionnal. HD derivation path + } + ]*/ + }, + // order of connections the dapp should connect to + dappConnection: [ + "$WEB3", // uses pre existing web3 object if available (e.g in Mist) + "ws://localhost:8546", + "http://localhost:8545" + ], + gas: "auto", + contracts: { + // example: + //SimpleStorage: { + // args: [ 100 ] + //} + } + } +}; diff --git a/templates/simple/contracts.json b/templates/simple/contracts.json deleted file mode 100644 index 8ea794ea4..000000000 --- a/templates/simple/contracts.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "default": { - "deployment": { - "host": "localhost", - "port": 8545, - "type": "rpc" - }, - "dappConnection": [ - "$WEB3", - "http://localhost:8545" - ], - "gas": "auto", - "contracts": { - } - } -} diff --git a/templates/simple/embark.json b/templates/simple/embark.json index ad84f1e72..e79075014 100644 --- a/templates/simple/embark.json +++ b/templates/simple/embark.json @@ -3,7 +3,7 @@ "app": {}, "buildDir": "build/", "config": { - "contracts": "contracts.json", + "contracts": "contracts.js", "blockchain": false, "storage": false, "communication": false, diff --git a/templates/simple/test/contract_spec.js b/templates/simple/test/contract_spec.js index 5fa719de5..200301761 100644 --- a/templates/simple/test/contract_spec.js +++ b/templates/simple/test/contract_spec.js @@ -1,24 +1,25 @@ -//describe("SimpleStorage", function() { -// this.timeout(0); -// before(function(done) { -// this.timeout(0); -// var contractsConfig = { -// "SimpleStorage": { -// args: [100] -// } -// }; -// EmbarkSpec.deployAll(contractsConfig, () => { done() }); -// }); -// -// it("should set constructor value", async function() { -// let result = await SimpleStorage.methods.storedData().call(); -// assert.equal(result, 100); -// }); -// -// it("set storage value", async function() { -// await SimpleStorage.methods.set(150).send(); -// let result = await SimpleStorage.methods.get().call(); -// assert.equal(result, 150); -// }); -// -//}); +// /*global contract, config, it, assert*/ +/*const SimpleStorage = require('Embark/contracts/SimpleStorage'); + +config({ + contracts: { + "SimpleStorage": { + args: [100] + } + } +}); + +contract("SimpleStorage", function () { + this.timeout(0); + + it("should set constructor value", async function () { + let result = await SimpleStorage.methods.storedData().call(); + assert.strictEqual(parseInt(result, 10), 100); + }); + + it("set storage value", async function () { + await SimpleStorage.methods.set(150).send(); + let result = await SimpleStorage.methods.get().call(); + assert.strictEqual(parseInt(result, 10), 150); + }); +});*/ diff --git a/test/accountParser.js b/test/accountParser.js new file mode 100644 index 000000000..288013849 --- /dev/null +++ b/test/accountParser.js @@ -0,0 +1,116 @@ +/*global describe, it*/ +const assert = require('assert'); +const sinon = require('sinon'); +const AccountParser = require('../lib/contracts/accountParser'); +let TestLogger = require('../lib/tests/test_logger.js'); +const Web3 = require('web3'); +const i18n = require('../lib/i18n/i18n.js'); +i18n.setOrDetectLocale('en'); + +describe('embark.AccountParser', function () { + describe('#getAccount', function () { + const web3 = { + eth: { + accounts: { + privateKeyToAccount: sinon.stub().callsFake((key) => { + return {key}; + }) + } + }, + utils: { + isHexStrict: sinon.stub().returns(true) + } + }; + const testLogger = new TestLogger({}); + + it('should return one account with the key', function () { + const account = AccountParser.getAccount({ + privateKey: 'myKey' + }, web3, testLogger); + + assert.deepEqual(account, {key: '0xmyKey', hexBalance: null}); + }); + + it('should return two accounts from the keys in the file', function () { + const account = AccountParser.getAccount({ + privateKeyFile: 'test/keyFiles/twoKeys' + }, web3, testLogger); + + assert.deepEqual(account, [ + {key: '0xkey1', hexBalance: null}, + {key: '0xkey2', hexBalance: null} + ]); + }); + + it('should return one account from the mnemonic', function () { + const account = AccountParser.getAccount({ + mnemonic: 'example exile argue silk regular smile grass bomb merge arm assist farm' + }, web3, testLogger); + + assert.deepEqual(account, + [{key: "0xf942d5d524ec07158df4354402bfba8d928c99d0ab34d0799a6158d56156d986", hexBalance: null}]); + }); + + it('should return two accounts from the mnemonic using numAddresses', function () { + const account = AccountParser.getAccount({ + mnemonic: 'example exile argue silk regular smile grass bomb merge arm assist farm', + numAddresses: 2 + }, web3, testLogger); + + assert.deepEqual(account, + [ + {key: "0xf942d5d524ec07158df4354402bfba8d928c99d0ab34d0799a6158d56156d986", hexBalance: null}, + {key: "0x88f37cfbaed8c0c515c62a17a3a1ce2f397d08bbf20dcc788b69f11b5a5c9791", hexBalance: null} + ]); + }); + + it('should return nothing with bad config', function () { + const account = AccountParser.getAccount({ + badConfig: 'not working' + }, web3, testLogger); + + assert.strictEqual(account, null); + }); + }); + + describe('getHexBalance', () => { + it('should return default if no balance', () => { + const hexBalance = AccountParser.getHexBalance(null, Web3); + + assert.strictEqual(hexBalance, 0xFFFFFFFFFFFFFFFFFF); + }); + + it('should return the balance string if already hexadecimal', () => { + const hexBalance = AccountParser.getHexBalance('0xFFF', Web3); + + assert.strictEqual(hexBalance, '0xFFF'); + }); + + it('should convert to hex when decimal', () => { + const hexBalance = AccountParser.getHexBalance('500', Web3); + + assert.strictEqual(hexBalance, '0x1f4'); + }); + + it('should convert to hex with eth string', () => { + const hexBalance = AccountParser.getHexBalance('4ether', Web3); + + assert.strictEqual(hexBalance, '0x3782dace9d900000'); + }); + + it('should convert to hex with eth string with space', () => { + const hexBalance = AccountParser.getHexBalance('673 shannon', Web3); + + assert.strictEqual(hexBalance, '0x9cb1ed0a00'); + }); + + it('should fail when string is not good', () => { + try { + AccountParser.getHexBalance('nogood', Web3); + assert.fail('Should have failed at getHexBalance'); + } catch (e) { + // Ok + } + }); + }); +}); diff --git a/test/blockchain.js b/test/blockchain.js index 06957e0fd..12bde8542 100644 --- a/test/blockchain.js +++ b/test/blockchain.js @@ -1,5 +1,6 @@ /*globals describe, it*/ const Blockchain = require('../lib/cmds/blockchain/blockchain'); +const constants = require('../lib/constants.json'); const assert = require('assert'); @@ -20,7 +21,7 @@ describe('embark.Blockchain', function () { mineWhenNeeded: false, rpcHost: 'localhost', rpcPort: 8545, - rpcApi: ['eth', 'web3', 'net'], + rpcApi: ['eth', 'web3', 'net', 'debug'], rpcCorsDomain: false, networkId: 12301, port: 30303, @@ -31,17 +32,22 @@ describe('embark.Blockchain', function () { whisper: true, account: {}, bootnodes: "", - wsApi: [ "eth", "web3", "net", "shh" ], + wsApi: ["eth", "web3", "net", "shh", "debug"], wsHost: "localhost", wsOrigins: false, wsPort: 8546, wsRPC: true, targetGasLimit: false, - fast: false, - light: false + syncMode: undefined, + verbosity: undefined, + proxy: true }; let blockchain = new Blockchain(config, 'geth'); + if(config.proxy){ + config.wsPort += constants.blockchain.servicePortOnProxy; + config.rpcPort += constants.blockchain.servicePortOnProxy; + } assert.deepEqual(blockchain.config, config); done(); }); @@ -57,7 +63,7 @@ describe('embark.Blockchain', function () { mineWhenNeeded: true, rpcHost: 'someserver', rpcPort: 12345, - rpcApi: ['eth', 'web3', 'net'], + rpcApi: ['eth', 'web3', 'net', 'debug'], rpcCorsDomain: true, networkId: 1, port: 123456, @@ -68,17 +74,23 @@ describe('embark.Blockchain', function () { whisper: false, account: {}, bootnodes: "", - wsApi: [ "eth", "web3", "net", "shh" ], + wsApi: ["eth", "web3", "net", "shh", "debug"], wsHost: "localhost", wsOrigins: false, wsPort: 8546, wsRPC: true, targetGasLimit: false, - fast: false, - light: false + syncMode: undefined, + verbosity: undefined, + proxy: true }; let blockchain = new Blockchain(config, 'geth'); + if(config.proxy){ + config.wsPort += constants.blockchain.servicePortOnProxy; + config.rpcPort += constants.blockchain.servicePortOnProxy; + } + assert.deepEqual(blockchain.config, config); done(); }); diff --git a/test/code_generator.js b/test/code_generator.js index 3331a0824..b8d7c6dd2 100644 --- a/test/code_generator.js +++ b/test/code_generator.js @@ -10,40 +10,33 @@ function replaceCRLF(string) { // and check the generate code interacts as expected describe('embark.CodeGenerator', function() { this.timeout(0); - describe('#generateProvider', function() { - let generator = new CodeGenerator({contractsConfig: {"dappConnection": [ "$WEB3", "http://somehost:1234" ] }, contractsManager: {}}); - - it('should generate code to connect to a provider', function() { - var providerCode = 'function __reduce(arr, memo, iteratee, cb) {\n if (typeof cb !== \'function\') {\n if (typeof memo === \'function\' && typeof iteratee === \'function\') {\n cb = iteratee;\n iteratee = memo;\n memo = [];\n } else {\n throw new TypeError(\'expected callback to be a function\');\n }\n }\n\n if (!Array.isArray(arr)) {\n cb(new TypeError(\'expected an array\'));\n return;\n }\n\n if (typeof iteratee !== \'function\') {\n cb(new TypeError(\'expected iteratee to be a function\'));\n return;\n }\n\n (function next(i, acc) {\n if (i === arr.length) {\n cb(null, acc);\n return;\n }\n\n iteratee(acc, arr[i], function(err, val) {\n if (err) {\n cb(err);\n return;\n }\n next(i + 1, val);\n });\n })(0, memo);\n};\n\nfunction __isNewWeb3_1() {\n return (typeof(web3.version) === \"string\");\n};\n\nfunction __getAccounts(cb) {\n if (__isNewWeb3_1()) {\n web3.eth.getAccounts().then(function(accounts) {\n cb(null, accounts);\n return null;\n }).catch(function(err) {\n cb(err);\n return null;\n });\n return;\n }\n web3.eth.getAccounts(cb);\n};\n\nvar __mainContext = __mainContext || this;\n__mainContext.__LoadManager = function() { this.list = []; this.done = false; }\n__mainContext.__LoadManager.prototype.execWhenReady = function(cb) { if (this.done) { cb(); } else { this.list.push(cb) } }\n__mainContext.__LoadManager.prototype.doFirst = function(todo) { var self = this; todo(function() { self.done = true; self.list.map((x) => x.apply()) }) }\n__mainContext.__loadManagerInstance = new __mainContext.__LoadManager();\nvar whenEnvIsLoaded = function(cb) {\n if (typeof document !== \'undefined\' && document !== null && !/comp|inter|loaded/.test(document.readyState)) {\n document.addEventListener(\'DOMContentLoaded\', cb);\n } else {\n cb();\n }\n}\nwhenEnvIsLoaded(function(){\n __mainContext.__loadManagerInstance.doFirst(function(done) {\n __mainContext.web3 = undefined;\n__reduce([\"$WEB3\",\"http://somehost:1234\"],function(prev, value, next) {\n if (prev === false) {\n return next(null, false);\n }\n\n if (value === \'$WEB3\' && (typeof web3 !== \'undefined\' && typeof Web3 !== \'undefined\')) {\n web3.setProvider(web3.givenProvider);\n } else if (value !== \'$WEB3\' && (typeof Web3 !== \'undefined\' && ((typeof web3 === \'undefined\') || (typeof web3 !== \'undefined\' && (!web3.isConnected || (web3.isConnected && !web3.isConnected())))))) {\n if (value.indexOf(\'ws://\') >= 0) {\n web3.setProvider(new Web3.providers.WebsocketProvider(value));\n } else {\n web3.setProvider(new Web3.providers.HttpProvider(value));\n }\n } else if (value === \'$WEB3\') {\n return next(null, \'\');\n }\n\n __getAccounts(function(err, account) {\n if (err) {\n next(null, true)\n } else {\n next(null, false)\n }\n });\n}, function(err, _result) {\n __getAccounts(function(err, accounts) {\n web3.eth.defaultAccount = accounts[0];\n done();\n });\n});\n\n })\n});\n\n' - - assert.strictEqual(replaceCRLF(generator.generateProvider()), providerCode); - }); - }); describe('#generateContracts', function() { - let generator = new CodeGenerator({blockchainConfig: {}, contractsManager: { - contracts: { - SimpleStorage: { - abiDefinition: [{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"initialValue","type":"uint256"}],"type":"constructor"}], - gasEstimates: 12000, - deployedAddress: "0x123", - code: '12345' - }, - Foo: { - abiDefinition: [{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"initialValue","type":"uint256"}],"type":"constructor"}], - gasEstimates: 12000, - deployedAddress: "0x124", - code: '123456' - } + let contracts = [ + { + className: 'SimpleStorage', + abiDefinition: [{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"initialValue","type":"uint256"}],"type":"constructor"}], + gasEstimates: 12000, + deployedAddress: "0x123", + code: '12345' + }, + { + className: 'Foo', + abiDefinition: [{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"initialValue","type":"uint256"}],"type":"constructor"}], + gasEstimates: 12000, + deployedAddress: "0x124", + code: '123456' } - }}); + ] + + let generator = new CodeGenerator({blockchainConfig: {}}); describe('with EmbarkJS', function() { let withEmbarkJS = true; it('should generate contract code', function() { var contractCode = "\n__mainContext.__loadManagerInstance.execWhenReady(function() {\n __mainContext.SimpleStorage = new EmbarkJS.Contract({abi: [{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialValue\",\"type\":\"uint256\"}],\"type\":\"constructor\"}], address: '0x123', code: '12345', gasEstimates: 12000});\n\n});\n__mainContext.__loadManagerInstance.execWhenReady(function() {\n __mainContext.Foo = new EmbarkJS.Contract({abi: [{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialValue\",\"type\":\"uint256\"}],\"type\":\"constructor\"}], address: '0x124', code: '123456', gasEstimates: 12000});\n\n});\n"; - assert.strictEqual(replaceCRLF(generator.generateContracts(withEmbarkJS)), contractCode); + assert.strictEqual(replaceCRLF(generator.generateContracts(contracts, withEmbarkJS)), contractCode); }); }); @@ -52,7 +45,7 @@ describe('embark.CodeGenerator', function() { it('should generate contract code', function() { var contractCode = "\n__mainContext.__loadManagerInstance.execWhenReady(function() {\n SimpleStorageAbi = [{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialValue\",\"type\":\"uint256\"}],\"type\":\"constructor\"}];\nSimpleStorage = new web3.eth.Contract(SimpleStorageAbi);\nSimpleStorage.options.address = '0x123';\nSimpleStorage.address = '0x123';\nSimpleStorage.options.from = web3.eth.defaultAccount;\n\n\n});\n__mainContext.__loadManagerInstance.execWhenReady(function() {\n FooAbi = [{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialValue\",\"type\":\"uint256\"}],\"type\":\"constructor\"}];\nFoo = new web3.eth.Contract(FooAbi);\nFoo.options.address = '0x124';\nFoo.address = '0x124';\nFoo.options.from = web3.eth.defaultAccount;\n\n\n});\n"; - assert.strictEqual(replaceCRLF(generator.generateContracts(withEmbarkJS)), contractCode); + assert.strictEqual(replaceCRLF(generator.generateContracts(contracts, withEmbarkJS)), contractCode); }); }); diff --git a/test/compiler.js b/test/compiler.js index 96e3ea0b8..7f9a8649a 100644 --- a/test/compiler.js +++ b/test/compiler.js @@ -2,6 +2,7 @@ let SolidityCompiler = require('../lib/modules/solidity'); let TestLogger = require('../lib/tests/test_logger.js'); let File = require('../lib/core/file.js'); +let Ipc = require('../lib/core/ipc.js'); let assert = require('assert'); let readFile = function(file) { @@ -16,24 +17,49 @@ var TestEvents = { } }; +let ipcObject = new Ipc({ + ipcRole: 'none' +}); + var apiObject = { registerCompiler: function() {}, logger: new TestLogger({}), - events: TestEvents + events: TestEvents, + config: { + contractDirectories: ['app/contracts/'] + } }; describe('embark.Compiler', function() { //let compiler = new Compiler({logger: new TestLogger({})}); - let compiler = new SolidityCompiler(apiObject, {contractDirectories: ['app/contracts/']}); + let compiler = new SolidityCompiler(apiObject, {ipc: ipcObject}); describe('#compile_solidity', function() { this.timeout(0); let expectedObject = {}; - expectedObject["SimpleStorage"] = {"code":"608060405234801561001057600080fd5b50604051602080610114833981016040525160005560e1806100336000396000f30060806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632a1afcd98114605757806360fe47b114607b5780636d4ce63c146092575b600080fd5b348015606257600080fd5b50606960a4565b60408051918252519081900360200190f35b348015608657600080fd5b50609060043560aa565b005b348015609d57600080fd5b50606960af565b60005481565b600055565b600054905600a165627a7a723058200d15419363aede339114aad0374f61d748071e4d9cd677583967b8b94eeb35ed0029","runtimeBytecode":"60806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632a1afcd98114605757806360fe47b114607b5780636d4ce63c146092575b600080fd5b348015606257600080fd5b50606960a4565b60408051918252519081900360200190f35b348015608657600080fd5b50609060043560aa565b005b348015609d57600080fd5b50606960af565b60005481565b600055565b600054905600a165627a7a723058200d15419363aede339114aad0374f61d748071e4d9cd677583967b8b94eeb35ed0029","realRuntimeBytecode":"60806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632a1afcd98114605757806360fe47b114607b5780636d4ce63c146092575b600080fd5b348015606257600080fd5b50606960a4565b60408051918252519081900360200190f35b348015608657600080fd5b50609060043560aa565b005b348015609d57600080fd5b50606960af565b60005481565b600055565b600054905600a165627a7a72305820","swarmHash":"0d15419363aede339114aad0374f61d748071e4d9cd677583967b8b94eeb35ed","gasEstimates":{"creation":{"codeDepositCost":"45000","executionCost":"20141","totalCost":"65141"},"external":{"get()":"428","set(uint256)":"20161","storedData()":"384"}},"functionHashes":{"get()":"6d4ce63c","set(uint256)":"60fe47b1","storedData()":"2a1afcd9"},"abiDefinition":[{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initialValue","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}],"filename":"test/contracts/simple_storage.sol"}; + expectedObject["SimpleStorage"] = { + "code":"608060405234801561001057600080fd5b50604051602080610114833981016040525160005560e1806100336000396000f30060806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632a1afcd98114605757806360fe47b114607b5780636d4ce63c146092575b600080fd5b348015606257600080fd5b50606960a4565b60408051918252519081900360200190f35b348015608657600080fd5b50609060043560aa565b005b348015609d57600080fd5b50606960af565b60005481565b600055565b600054905600a165627a7a723058200d15419363aede339114aad0374f61d748071e4d9cd677583967b8b94eeb35ed0029", + "runtimeBytecode":"60806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632a1afcd98114605757806360fe47b114607b5780636d4ce63c146092575b600080fd5b348015606257600080fd5b50606960a4565b60408051918252519081900360200190f35b348015608657600080fd5b50609060043560aa565b005b348015609d57600080fd5b50606960af565b60005481565b600055565b600054905600a165627a7a723058200d15419363aede339114aad0374f61d748071e4d9cd677583967b8b94eeb35ed0029", + "realRuntimeBytecode":"60806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416632a1afcd98114605757806360fe47b114607b5780636d4ce63c146092575b600080fd5b348015606257600080fd5b50606960a4565b60408051918252519081900360200190f35b348015608657600080fd5b50609060043560aa565b005b348015609d57600080fd5b50606960af565b60005481565b600055565b600054905600a165627a7a72305820", + "swarmHash":"0d15419363aede339114aad0374f61d748071e4d9cd677583967b8b94eeb35ed", + "gasEstimates":{"creation":{"codeDepositCost":"45000","executionCost":"20141","totalCost":"65141"},"external":{"get()":"428","set(uint256)":"20161","storedData()":"384"}}, + "functionHashes":{"get()":"6d4ce63c","set(uint256)":"60fe47b1","storedData()":"2a1afcd9"}, + "abiDefinition":[{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initialValue","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}], + "filename":"test/contracts/simple_storage.sol" + }; - expectedObject["Token"] = {"code":"608060405234801561001057600080fd5b506040516020806104618339810160409081529051336000908152602081905291909120819055600255610418806100496000396000f3006080604052600436106100775763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663095ea7b3811461007c57806318160ddd146100b457806323b872dd146100db57806370a0823114610105578063a9059cbb14610126578063dd62ed3e1461014a575b600080fd5b34801561008857600080fd5b506100a0600160a060020a0360043516602435610171565b604080519115158252519081900360200190f35b3480156100c057600080fd5b506100c96101d7565b60408051918252519081900360200190f35b3480156100e757600080fd5b506100a0600160a060020a03600435811690602435166044356101dd565b34801561011157600080fd5b506100c9600160a060020a03600435166102e9565b34801561013257600080fd5b506100a0600160a060020a0360043516602435610304565b34801561015657600080fd5b506100c9600160a060020a03600435811690602435166103ba565b336000818152600160209081526040808320600160a060020a038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b60025490565b600160a060020a03831660009081526020819052604081205482111561020257600080fd5b600160a060020a038416600090815260016020908152604080832033845290915290205482111561023257600080fd5b600160a060020a03831660009081526020819052604090205461025590836103e5565b151561026057600080fd5b600160a060020a03808516600081815260016020908152604080832033845282528083208054889003905583835282825280832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b600160a060020a031660009081526020819052604090205490565b3360009081526020819052604081205482111561032057600080fd5b600160a060020a03831660009081526020819052604090205461034390836103e5565b151561034e57600080fd5b3360008181526020818152604080832080548790039055600160a060020a03871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350600192915050565b600160a060020a03918216600090815260016020908152604080832093909416825291909152205490565b81011015905600a165627a7a72305820f4d3e54bdfabcdb60435da61d6a6d650b6814ec3bfa0ac2cb0e4eec3795d11a20029","runtimeBytecode":"6080604052600436106100775763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663095ea7b3811461007c57806318160ddd146100b457806323b872dd146100db57806370a0823114610105578063a9059cbb14610126578063dd62ed3e1461014a575b600080fd5b34801561008857600080fd5b506100a0600160a060020a0360043516602435610171565b604080519115158252519081900360200190f35b3480156100c057600080fd5b506100c96101d7565b60408051918252519081900360200190f35b3480156100e757600080fd5b506100a0600160a060020a03600435811690602435166044356101dd565b34801561011157600080fd5b506100c9600160a060020a03600435166102e9565b34801561013257600080fd5b506100a0600160a060020a0360043516602435610304565b34801561015657600080fd5b506100c9600160a060020a03600435811690602435166103ba565b336000818152600160209081526040808320600160a060020a038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b60025490565b600160a060020a03831660009081526020819052604081205482111561020257600080fd5b600160a060020a038416600090815260016020908152604080832033845290915290205482111561023257600080fd5b600160a060020a03831660009081526020819052604090205461025590836103e5565b151561026057600080fd5b600160a060020a03808516600081815260016020908152604080832033845282528083208054889003905583835282825280832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b600160a060020a031660009081526020819052604090205490565b3360009081526020819052604081205482111561032057600080fd5b600160a060020a03831660009081526020819052604090205461034390836103e5565b151561034e57600080fd5b3360008181526020818152604080832080548790039055600160a060020a03871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350600192915050565b600160a060020a03918216600090815260016020908152604080832093909416825291909152205490565b81011015905600a165627a7a72305820f4d3e54bdfabcdb60435da61d6a6d650b6814ec3bfa0ac2cb0e4eec3795d11a20029","realRuntimeBytecode":"6080604052600436106100775763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663095ea7b3811461007c57806318160ddd146100b457806323b872dd146100db57806370a0823114610105578063a9059cbb14610126578063dd62ed3e1461014a575b600080fd5b34801561008857600080fd5b506100a0600160a060020a0360043516602435610171565b604080519115158252519081900360200190f35b3480156100c057600080fd5b506100c96101d7565b60408051918252519081900360200190f35b3480156100e757600080fd5b506100a0600160a060020a03600435811690602435166044356101dd565b34801561011157600080fd5b506100c9600160a060020a03600435166102e9565b34801561013257600080fd5b506100a0600160a060020a0360043516602435610304565b34801561015657600080fd5b506100c9600160a060020a03600435811690602435166103ba565b336000818152600160209081526040808320600160a060020a038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b60025490565b600160a060020a03831660009081526020819052604081205482111561020257600080fd5b600160a060020a038416600090815260016020908152604080832033845290915290205482111561023257600080fd5b600160a060020a03831660009081526020819052604090205461025590836103e5565b151561026057600080fd5b600160a060020a03808516600081815260016020908152604080832033845282528083208054889003905583835282825280832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b600160a060020a031660009081526020819052604090205490565b3360009081526020819052604081205482111561032057600080fd5b600160a060020a03831660009081526020819052604090205461034390836103e5565b151561034e57600080fd5b3360008181526020818152604080832080548790039055600160a060020a03871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350600192915050565b600160a060020a03918216600090815260016020908152604080832093909416825291909152205490565b81011015905600a165627a7a72305820","swarmHash":"f4d3e54bdfabcdb60435da61d6a6d650b6814ec3bfa0ac2cb0e4eec3795d11a2","gasEstimates":{"creation":{"codeDepositCost":"209600","executionCost":"40385","totalCost":"249985"},"external":{"allowance(address,address)":"818","approve(address,uint256)":"22332","balanceOf(address)":"675","totalSupply()":"406","transfer(address,uint256)":"43544","transferFrom(address,address,uint256)":"64387"},"internal":{"safeToAdd(uint256,uint256)":"24"}},"functionHashes":{"allowance(address,address)":"dd62ed3e","approve(address,uint256)":"095ea7b3","balanceOf(address)":"70a08231","totalSupply()":"18160ddd","transfer(address,uint256)":"a9059cbb","transferFrom(address,address,uint256)":"23b872dd"},"abiDefinition":[{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"value","type":"uint256"}],"name":"approve","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"supply","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"who","type":"address"}],"name":"balanceOf","outputs":[{"name":"value","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"_allowance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initial_balance","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}],"filename":"test/contracts/token.sol"}; + expectedObject["Token"] = { + "code":"608060405234801561001057600080fd5b506040516020806104618339810160409081529051336000908152602081905291909120819055600255610418806100496000396000f3006080604052600436106100775763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663095ea7b3811461007c57806318160ddd146100b457806323b872dd146100db57806370a0823114610105578063a9059cbb14610126578063dd62ed3e1461014a575b600080fd5b34801561008857600080fd5b506100a0600160a060020a0360043516602435610171565b604080519115158252519081900360200190f35b3480156100c057600080fd5b506100c96101d7565b60408051918252519081900360200190f35b3480156100e757600080fd5b506100a0600160a060020a03600435811690602435166044356101dd565b34801561011157600080fd5b506100c9600160a060020a03600435166102e9565b34801561013257600080fd5b506100a0600160a060020a0360043516602435610304565b34801561015657600080fd5b506100c9600160a060020a03600435811690602435166103ba565b336000818152600160209081526040808320600160a060020a038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b60025490565b600160a060020a03831660009081526020819052604081205482111561020257600080fd5b600160a060020a038416600090815260016020908152604080832033845290915290205482111561023257600080fd5b600160a060020a03831660009081526020819052604090205461025590836103e5565b151561026057600080fd5b600160a060020a03808516600081815260016020908152604080832033845282528083208054889003905583835282825280832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b600160a060020a031660009081526020819052604090205490565b3360009081526020819052604081205482111561032057600080fd5b600160a060020a03831660009081526020819052604090205461034390836103e5565b151561034e57600080fd5b3360008181526020818152604080832080548790039055600160a060020a03871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350600192915050565b600160a060020a03918216600090815260016020908152604080832093909416825291909152205490565b81011015905600a165627a7a72305820f4d3e54bdfabcdb60435da61d6a6d650b6814ec3bfa0ac2cb0e4eec3795d11a20029", + "runtimeBytecode":"6080604052600436106100775763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663095ea7b3811461007c57806318160ddd146100b457806323b872dd146100db57806370a0823114610105578063a9059cbb14610126578063dd62ed3e1461014a575b600080fd5b34801561008857600080fd5b506100a0600160a060020a0360043516602435610171565b604080519115158252519081900360200190f35b3480156100c057600080fd5b506100c96101d7565b60408051918252519081900360200190f35b3480156100e757600080fd5b506100a0600160a060020a03600435811690602435166044356101dd565b34801561011157600080fd5b506100c9600160a060020a03600435166102e9565b34801561013257600080fd5b506100a0600160a060020a0360043516602435610304565b34801561015657600080fd5b506100c9600160a060020a03600435811690602435166103ba565b336000818152600160209081526040808320600160a060020a038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b60025490565b600160a060020a03831660009081526020819052604081205482111561020257600080fd5b600160a060020a038416600090815260016020908152604080832033845290915290205482111561023257600080fd5b600160a060020a03831660009081526020819052604090205461025590836103e5565b151561026057600080fd5b600160a060020a03808516600081815260016020908152604080832033845282528083208054889003905583835282825280832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b600160a060020a031660009081526020819052604090205490565b3360009081526020819052604081205482111561032057600080fd5b600160a060020a03831660009081526020819052604090205461034390836103e5565b151561034e57600080fd5b3360008181526020818152604080832080548790039055600160a060020a03871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350600192915050565b600160a060020a03918216600090815260016020908152604080832093909416825291909152205490565b81011015905600a165627a7a72305820f4d3e54bdfabcdb60435da61d6a6d650b6814ec3bfa0ac2cb0e4eec3795d11a20029", + "realRuntimeBytecode":"6080604052600436106100775763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663095ea7b3811461007c57806318160ddd146100b457806323b872dd146100db57806370a0823114610105578063a9059cbb14610126578063dd62ed3e1461014a575b600080fd5b34801561008857600080fd5b506100a0600160a060020a0360043516602435610171565b604080519115158252519081900360200190f35b3480156100c057600080fd5b506100c96101d7565b60408051918252519081900360200190f35b3480156100e757600080fd5b506100a0600160a060020a03600435811690602435166044356101dd565b34801561011157600080fd5b506100c9600160a060020a03600435166102e9565b34801561013257600080fd5b506100a0600160a060020a0360043516602435610304565b34801561015657600080fd5b506100c9600160a060020a03600435811690602435166103ba565b336000818152600160209081526040808320600160a060020a038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a350600192915050565b60025490565b600160a060020a03831660009081526020819052604081205482111561020257600080fd5b600160a060020a038416600090815260016020908152604080832033845290915290205482111561023257600080fd5b600160a060020a03831660009081526020819052604090205461025590836103e5565b151561026057600080fd5b600160a060020a03808516600081815260016020908152604080832033845282528083208054889003905583835282825280832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060019392505050565b600160a060020a031660009081526020819052604090205490565b3360009081526020819052604081205482111561032057600080fd5b600160a060020a03831660009081526020819052604090205461034390836103e5565b151561034e57600080fd5b3360008181526020818152604080832080548790039055600160a060020a03871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a350600192915050565b600160a060020a03918216600090815260016020908152604080832093909416825291909152205490565b81011015905600a165627a7a72305820", + "swarmHash":"f4d3e54bdfabcdb60435da61d6a6d650b6814ec3bfa0ac2cb0e4eec3795d11a2", + "gasEstimates":{"creation":{"codeDepositCost":"209600","executionCost":"40385","totalCost":"249985"},"external":{"allowance(address,address)":"818","approve(address,uint256)":"22332","balanceOf(address)":"675","totalSupply()":"406","transfer(address,uint256)":"43544","transferFrom(address,address,uint256)":"64387"},"internal":{"safeToAdd(uint256,uint256)":"24"}}, + "functionHashes":{"allowance(address,address)":"dd62ed3e","approve(address,uint256)":"095ea7b3","balanceOf(address)":"70a08231","totalSupply()":"18160ddd","transfer(address,uint256)":"a9059cbb","transferFrom(address,address,uint256)":"23b872dd"}, + "abiDefinition":[{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"value","type":"uint256"}],"name":"approve","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"supply","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"who","type":"address"}],"name":"balanceOf","outputs":[{"name":"value","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"ok","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"_allowance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initial_balance","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}], + "filename":"test/contracts/token.sol" + }; it('should generate compiled code and abi', function(done) { compiler.compile_solidity([ diff --git a/test/contracts.js b/test/contracts.js index 229aa0f26..0c7a19258 100644 --- a/test/contracts.js +++ b/test/contracts.js @@ -1,9 +1,11 @@ /*globals describe, it*/ let ContractsManager = require('../lib/contracts/contracts.js'); +let Compiler = require('../lib/contracts/compiler.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 Ipc = require('../lib/core/ipc.js'); let assert = require('assert'); //let SolidityCompiler = require('../lib/modules/solidity'); @@ -13,13 +15,74 @@ let readFile = function(file) { return new File({filename: file, type: File.types.dapp_file, path: file}); }; +const currentSolcVersion = require('../package.json').dependencies.solc; +const TestEvents = { + request: (cmd, cb) => { + cb(currentSolcVersion); + } +}; + describe('embark.Contracts', function() { this.timeout(0); describe('simple', function() { let plugins = new Plugins({ - logger: new TestLogger({}) + logger: new TestLogger({}), + events: TestEvents, + config: { + contractDirectories: ['app/contracts/'] + } }); - plugins.loadInternalPlugin('solidity', {solcVersion: '0.4.17', contractDirectories: ['app/contracts/']}); + let ipcObject = new Ipc({ + ipcRole: 'none' + }); + plugins.loadInternalPlugin('solidity', {ipc: ipcObject}); + + let compiler = new Compiler({plugins: plugins, logger: plugins.logger}); + let events = new Events(); + events.setCommandHandler("compiler:contracts", function(contractFiles, cb) { + compiler.compile_contracts(contractFiles, cb); + }); + + events.setCommandHandler("config:contractsConfig", function(cb) { + cb(contractsConfig); + }); + + events.setCommandHandler("config:contractsFiles", (cb) => { + cb([]); + }); + + events.setCommandHandler("blockchain:gasPrice", (cb) => { + cb(null, 100); + }); + + let contractsConfig = { + "versions": { + "web3.js": "1.0.0-beta", + "solc": "0.4.17" + }, + "deployment": { + "host": "localhost", + "port": 8545, + "type": "rpc" + }, + "dappConnection": [ + "$WEB3", + "localhost:8545" + ], + "gas": "auto", + "contracts": { + "Token": { + "args": [ + 100 + ] + }, + "SimpleStorage": { + "args": [ + 200 + ] + } + } + }; let contractsManager = new ContractsManager({ plugins: plugins, @@ -28,36 +91,9 @@ describe('embark.Contracts', function() { readFile('test/contracts/token.sol') ], contractDirectories: ['app/contracts'], - contractsConfig: { - "versions": { - "web3.js": "1.0.0-beta", - "solc": "0.4.17" - }, - "deployment": { - "host": "localhost", - "port": 8545, - "type": "rpc" - }, - "dappConnection": [ - "$WEB3", - "localhost:8545" - ], - "gas": "auto", - "contracts": { - "Token": { - "args": [ - 100 - ] - }, - "SimpleStorage": { - "args": [ - 200 - ] - } - } - }, + contractsConfig: contractsConfig, logger: new Logger({}), - events: new Events() + events: events }); describe('#build', function() { @@ -99,9 +135,73 @@ describe('embark.Contracts', function() { describe('config with contract instances', function() { let plugins = new Plugins({ - logger: new TestLogger({}) + logger: new TestLogger({}), + events: TestEvents, + config: { + contractDirectories: ['app/contracts/'] + } }); - plugins.loadInternalPlugin('solidity', {solcVersion: '0.4.17', contractDirectories: ['app/contracts/']}); + let ipcObject = new Ipc({ + ipcRole: 'none' + }); + plugins.loadInternalPlugin('solidity', {ipc: ipcObject}); + + let compiler = new Compiler({plugins: plugins, logger: plugins.logger}); + let events = new Events(); + events.setCommandHandler("compiler:contracts", function(contractFiles, cb) { + compiler.compile_contracts(contractFiles, cb); + }); + + events.setCommandHandler("config:contractsConfig", function(cb) { + cb(contractsConfig); + }); + + events.setCommandHandler("config:contractsFiles", (cb) => { + cb([]); + }); + + events.setCommandHandler("blockchain:gasPrice", (cb) => { + cb(null, 100); + }); + + let contractsConfig = { + "versions": { + "web3.js": "1.0.0-beta", + "solc": "0.4.17" + }, + "deployment": { + "host": "localhost", + "port": 8545, + "type": "rpc" + }, + "dappConnection": [ + "$WEB3", + "localhost:8545" + ], + "gas": "auto", + "contracts": { + "TokenStorage": { + "args": [ + 100, + "$SimpleStorage" + ] + }, + "MySimpleStorage": { + "instanceOf": "SimpleStorage", + "args": [ + 300 + ] + }, + "SimpleStorage": { + "args": [ + 200 + ] + }, + "AnotherSimpleStorage": { + "instanceOf": "SimpleStorage" + } + } + } let contractsManager = new ContractsManager({ plugins: plugins, @@ -110,46 +210,9 @@ describe('embark.Contracts', function() { readFile('test/contracts/token_storage.sol') ], contractDirectories: ['app/contracts'], - contractsConfig: { - "versions": { - "web3.js": "1.0.0-beta", - "solc": "0.4.17" - }, - "deployment": { - "host": "localhost", - "port": 8545, - "type": "rpc" - }, - "dappConnection": [ - "$WEB3", - "localhost:8545" - ], - "gas": "auto", - "contracts": { - "TokenStorage": { - "args": [ - 100, - "$SimpleStorage" - ] - }, - "MySimpleStorage": { - "instanceOf": "SimpleStorage", - "args": [ - 300 - ] - }, - "SimpleStorage": { - "args": [ - 200 - ] - }, - "AnotherSimpleStorage": { - "instanceOf": "SimpleStorage" - } - } - }, + contractsConfig: contractsConfig, logger: new Logger({}), - events: new Events() + events: events }); describe('#build', function() { diff --git a/test/keyFiles/twoKeys b/test/keyFiles/twoKeys new file mode 100644 index 000000000..e500e8b9f --- /dev/null +++ b/test/keyFiles/twoKeys @@ -0,0 +1 @@ +key1;key2 diff --git a/test/processLauncher.js b/test/processLauncher.js new file mode 100644 index 000000000..8fa8f238f --- /dev/null +++ b/test/processLauncher.js @@ -0,0 +1,174 @@ +/*global describe, it, before, beforeEach*/ +const assert = require('assert'); +const sinon = require('sinon'); +const TestLogger = require('../lib/tests/test_logger.js'); +const ProcessLauncher = require('../lib/process/processLauncher'); + +describe('ProcessWrapper', () => { + let processLauncher; + + before(() => { + sinon.stub(ProcessLauncher.prototype, '_subscribeToMessages'); + processLauncher = new ProcessLauncher({ + logger: new TestLogger({}), + modulePath: 'test.js' + }); + }); + + describe('on', () => { + + beforeEach(() => { + processLauncher.subscriptions = {}; + }); + + it('should create an array for the key value', function () { + processLauncher.on('test', 'value', 'myCallback'); + assert.deepEqual(processLauncher.subscriptions, { + "test": [ + { + "callback": "myCallback", + "value": "value" + } + ] + }); + }); + + it('should add another value to the key', () => { + processLauncher.on('test', 'value', 'myCallback'); + processLauncher.on('test', 'value2', 'myCallback2'); + assert.deepEqual(processLauncher.subscriptions, { + "test": [ + { + "callback": "myCallback", + "value": "value" + }, + { + "callback": "myCallback2", + "value": "value2" + } + ] + }); + }); + }); + + describe('unsubscribeTo', () => { + it('should remove the value for the key', () => { + processLauncher.subscriptions = { + "test": [ + { + "callback": "myCallback", + "value": "value" + }, + { + "callback": "myCallback2", + "value": "value2" + } + ] + }; + + processLauncher.unsubscribeTo('test', 'value2'); + assert.deepEqual(processLauncher.subscriptions, { + "test": [ + { + "callback": "myCallback", + "value": "value" + } + ] + }); + }); + + it('should remove the whole key', () => { + processLauncher.subscriptions = { + "test": [ + { + "callback": "myCallback", + "value": "value" + } + ] + }; + + processLauncher.unsubscribeTo('test'); + assert.deepEqual(processLauncher.subscriptions, {test: []}); + }); + }); + + describe('unsubscribeToAll', () => { + it('clears every subscriptions', () => { + processLauncher.subscriptions = { + "test": [ + { + "callback": "myCallback", + "value": "value" + } + ] + }; + + processLauncher.unsubscribeToAll(); + assert.deepEqual(processLauncher.subscriptions, {}); + }); + }); + + describe('_checkSubscriptions', function () { + it('should not do anything if not in subscription', function () { + const callback = sinon.stub(); + processLauncher.subscriptions = { + "test": [ + { + "callback": callback, + "value": "value" + } + ] + }; + processLauncher._checkSubscriptions({does: 'nothing', for: 'real'}); + assert.strictEqual(callback.callCount, 0); + }); + + it('should call the callback', function () { + const callback = sinon.stub(); + processLauncher.subscriptions = { + "test": [ + { + "callback": callback, + "value": "value" + } + ] + }; + processLauncher._checkSubscriptions({test: 'value'}); + assert.strictEqual(callback.callCount, 1); + }); + + it('should call the callback and remove the sub', function () { + const callback = sinon.stub(); + processLauncher.subscriptions = { + "test": [ + { + "callback": callback, + "value": "value", + "once": true + } + ] + }; + processLauncher._checkSubscriptions({test: 'value'}); + assert.strictEqual(callback.callCount, 1); + assert.deepEqual(processLauncher.subscriptions, {test: []}); + }); + + it('should call the callback twice', function () { + const callback = sinon.stub(); + processLauncher.subscriptions = { + "test": [ + { + "callback": callback, + "value": "value" + }, + { + "callback": callback, + "value": "value" + } + ] + }; + processLauncher._checkSubscriptions({test: 'value'}); + assert.strictEqual(callback.callCount, 2); + }); + }); +}); diff --git a/test_apps/contracts_app/blockchain.json b/test_apps/contracts_app/blockchain.json index ee5b1b968..80394f5f1 100644 --- a/test_apps/contracts_app/blockchain.json +++ b/test_apps/contracts_app/blockchain.json @@ -25,7 +25,20 @@ "testnet": { "networkType": "testnet", "rpcHost": "localhost", - "rpcPort": 8545 + "rpcPort": 8545, + "syncMode": "fast", + "account": { + "password": "config/ropsten/password" + } + }, + "rinkeby": { + "networkType": "rinkeby", + "rpcHost": "localhost", + "rpcPort": 8545, + "syncMode": "fast", + "account": { + "password": "config/rinkeby/password" + } }, "livenet": { "networkType": "livenet", diff --git a/test_apps/contracts_app/embark.json b/test_apps/contracts_app/embark.json index 4f2b9380f..cf27cae37 100644 --- a/test_apps/contracts_app/embark.json +++ b/test_apps/contracts_app/embark.json @@ -10,6 +10,6 @@ }, "versions": { "web3": "1.0.0-beta", - "solc": "0.4.17" + "solc": "0.4.24" } } diff --git a/test_apps/contracts_app/rinkeby/password b/test_apps/contracts_app/rinkeby/password new file mode 100644 index 000000000..c747d679e --- /dev/null +++ b/test_apps/contracts_app/rinkeby/password @@ -0,0 +1 @@ +dev_password diff --git a/test_apps/contracts_app/ropsten/password b/test_apps/contracts_app/ropsten/password new file mode 100644 index 000000000..c747d679e --- /dev/null +++ b/test_apps/contracts_app/ropsten/password @@ -0,0 +1 @@ +dev_password diff --git a/test_apps/contracts_app/test/another_storage_spec.js b/test_apps/contracts_app/test/another_storage_spec.js index 255a5d4b8..e304e8a1e 100644 --- a/test_apps/contracts_app/test/another_storage_spec.js +++ b/test_apps/contracts_app/test/another_storage_spec.js @@ -1,21 +1,24 @@ +/*global contract, config, it*/ +const assert = require('assert'); +const AnotherStorage = require('Embark/contracts/AnotherStorage'); +const SimpleStorage = require('Embark/contracts/SimpleStorage'); + +config({ + contracts: { + "SimpleStorage": { + args: [100] + }, + "AnotherStorage": { + args: ["$SimpleStorage"] + } + } +}); + contract("AnotherStorage", function() { this.timeout(0); - before(function(done) { - this.timeout(0); - var contractsConfig = { - "SimpleStorage": { - args: [100] - }, - "AnotherStorage": { - args: ["$SimpleStorage"] - } - }; - EmbarkSpec.deployAll(contractsConfig, () => { done() }); - }); it("set SimpleStorage address", async function() { let result = await AnotherStorage.methods.simpleStorageAddress().call(); assert.equal(result.toString(), SimpleStorage.options.address); }); - }); diff --git a/test_apps/contracts_app/test/array_references_spec.js b/test_apps/contracts_app/test/array_references_spec.js index 99cf37da9..ca11c3bb9 100644 --- a/test_apps/contracts_app/test/array_references_spec.js +++ b/test_apps/contracts_app/test/array_references_spec.js @@ -1,37 +1,42 @@ +/*global contract, config, it*/ +const assert = require('assert'); +const SomeContract = require('Embark/contracts/SomeContract'); +const SimpleStorage = require('Embark/contracts/SimpleStorage'); +const MyToken2 = require('Embark/contracts/MyToken2'); + +config({ + contracts: { + "SimpleStorage": { + args: [100] + }, + "Token": { + deploy: false, + args: [1000] + }, + "MyToken2": { + instanceOf: "Token", + args: [2000] + }, + "SomeContract": { + "args": [ + ["$MyToken2", "$SimpleStorage"], + 100 + ] + } + } +}); + contract("SomeContract", function() { this.timeout(0); - before(function(done) { - this.timeout(0); - var contractsConfig = { - "SimpleStorage": { - args: [100] - }, - "Token": { - deploy: false, - args: [1000] - }, - "MyToken2": { - instanceOf: "Token", - args: [2000] - }, - "SomeContract": { - "args": [ - ["$MyToken2", "$SimpleStorage"], - 100 - ] - } - }; - EmbarkSpec.deployAll(contractsConfig, () => { done() }); - }); it("set MyToken2 address", async function() { let address = await SomeContract.methods.addr_1().call(); - assert.equal(address, MyToken2.options.address); + assert.strictEqual(address, MyToken2.options.address); }); it("set SimpleStorage address", async function() { let address = await SomeContract.methods.addr_2().call(); - assert.equal(address, SimpleStorage.options.address); + assert.strictEqual(address, SimpleStorage.options.address); }); }); diff --git a/test_apps/contracts_app/test/lib_test_spec.js b/test_apps/contracts_app/test/lib_test_spec.js index 18aef2c9f..fe2a2729a 100644 --- a/test_apps/contracts_app/test/lib_test_spec.js +++ b/test_apps/contracts_app/test/lib_test_spec.js @@ -1,22 +1,23 @@ +/*global contract, config, it*/ +const assert = require('assert'); +const Test2 = require('Embark/contracts/Test2'); + +config({ + contracts: { + "Test2": { + }, + "ZAMyLib": { + }, + "ZAMyLib2": { + "deploy": true + } + } +}); + contract("Test", function() { - before(function(done) { - this.timeout(0); - var contractsConfig = { - "Test2": { - }, - "ZAMyLib": { - }, - "ZAMyLib2": { - "deploy": true - } - }; - - EmbarkSpec.deployAll(contractsConfig, () => { done() }); - }); - it("should call library correctly", async function() { let result = await Test2.methods.testAdd().call(); - assert.equal(result, 3); + assert.strictEqual(parseInt(result, 10), 3); }); }); diff --git a/test_apps/contracts_app/test/simple_storage_spec.js b/test_apps/contracts_app/test/simple_storage_spec.js index b43e0b354..42b5cd2b0 100644 --- a/test_apps/contracts_app/test/simple_storage_spec.js +++ b/test_apps/contracts_app/test/simple_storage_spec.js @@ -1,31 +1,26 @@ +/*global contract, config, it*/ +const assert = require('assert'); +const SimpleStorage = require('Embark/contracts/SimpleStorage'); -contract("SimpleStorage", function() { +config({ + contracts: { + "SimpleStorage": { + args: [100] + } + } +}); +contract("SimpleStorage", function () { this.timeout(0); - before(function(done) { - this.timeout(0); - //config({ - // node: "http://localhost:8545" - //}); - - var contractsConfig = { - "SimpleStorage": { - args: [100] - } - }; - EmbarkSpec.deployAll(contractsConfig, () => { done() }); - }); - - it("should set constructor value", async function() { + it("should set constructor value", async function () { let result = await SimpleStorage.methods.storedData().call(); - assert.equal(result, 100); + assert.strictEqual(parseInt(result, 10), 100); }); - it("set storage value", async function() { + it("set storage value", async function () { await SimpleStorage.methods.set(150).send(); let result = await SimpleStorage.methods.get().call(); - assert.equal(result, 499650); + assert.strictEqual(parseInt(result, 10), 499650); }); - }); diff --git a/test_apps/contracts_app/test/token_spec.js b/test_apps/contracts_app/test/token_spec.js index f101a7898..a6e542100 100644 --- a/test_apps/contracts_app/test/token_spec.js +++ b/test_apps/contracts_app/test/token_spec.js @@ -1,87 +1,82 @@ +/*global describe, config, it*/ +const assert = require('assert'); +const Token = require('Embark/contracts/Token'); +const MyToken = require('Embark/contracts/MyToken'); +const MyToken2 = require('Embark/contracts/MyToken2'); +const AlreadyDeployedToken = require('Embark/contracts/AlreadyDeployedToken'); +const Test = require('Embark/contracts/Test'); -describe("Token", function() { - - this.timeout(0); - before(function(done) { - this.timeout(0); - - //config({ - // node: "http://localhost:8545" - //}); - - var contractsConfig = { - "ZAMyLib": { - }, - "Token": { - }, - "SimpleStorage": { - args: [100] - }, - "AnotherStorage": { - args: ["$SimpleStorage"] - }, - "Token": { - deploy: false, - args: [1000] - }, - "MyToken": { - instanceOf: "Token" - }, - "MyToken2": { - instanceOf: "Token", - args: [2000] - }, - "AlreadyDeployedToken": { - "address": "0xCAFECAFECAFECAFECAFECAFECAFECAFECAFECAFE", - instanceOf: "Token" - }, - "Test": { - onDeploy: [ - "Test.methods.changeAddress('$MyToken').send()" - ] - }, - "ContractArgs": { - "args": { - "initialValue": 123, - "_addresses": ["$MyToken2", "$SimpleStorage"] - } - }, - "SomeContract": { - "args": [ - ["$MyToken2", "$SimpleStorage"], - 100 - ] +config({ + contracts: { + ZAMyLib: {}, + SimpleStorage: { + args: [100] + }, + AnotherStorage: { + args: ["$SimpleStorage"] + }, + Token: { + deploy: false, + args: [1000] + }, + MyToken: { + instanceOf: "Token" + }, + MyToken2: { + instanceOf: "Token", + args: [2000] + }, + AlreadyDeployedToken: { + address: "0xCAFECAFECAFECAFECAFECAFECAFECAFECAFECAFE", + instanceOf: "Token" + }, + Test: { + onDeploy: ["Test.methods.changeAddress('$MyToken').send()"] + }, + ContractArgs: { + args: { + initialValue: 123, + _addresses: ["$MyToken2", "$SimpleStorage"] } - }; - EmbarkSpec.deployAll(contractsConfig, () => { done() }); - }); - - it("not deploy Token", function() { - assert.equal(Token.address, ""); - }); - - it("not deploy MyToken and MyToken2", function() { - assert.notEqual(MyToken.address, ""); - assert.notEqual(MyToken2.address, ""); - }); - - it("set MyToken Balance correctly", async function() { - let result = await MyToken.methods._supply().call(); - assert.equal(result, 1000); - }); - - it("set MyToken2 Balance correctly", async function() { - let result = await MyToken2.methods._supply().call(); - assert.equal(result, 2000); - }); - - it("get right address", function() { - assert.equal(AlreadyDeployedToken.address, "0xCAFECAFECAFECAFECAFECAFECAFECAFECAFECAFE"); - }); - - it("should use onDeploy", async function() { - let result = await Test.methods.addr().call(); - assert.equal(result, MyToken.address) - }); - + }, + SomeContract: { + args: [ + ["$MyToken2", "$SimpleStorage"], + 100 + ] + } + } +}); + +describe("Token", function () { + this.timeout(0); + + it("not deploy Token", function () { + assert.strictEqual(Token.address, undefined); + }); + + it("should deploy MyToken and MyToken2", function () { + assert.ok(MyToken.options.address); + assert.ok(MyToken2.options.address); + }); + + it("set MyToken Balance correctly", async function () { + let result = await MyToken.methods._supply().call(); + assert.strictEqual(parseInt(result, 10), 1000); + }); + + it("set MyToken2 Balance correctly", async function () { + let result = await MyToken2.methods._supply().call(); + assert.strictEqual(parseInt(result, 10), 2000); + }); + + it("get right address", function () { + assert.strictEqual(AlreadyDeployedToken.options.address.toLowerCase(), + "0xCAFECAFECAFECAFECAFECAFECAFECAFECAFECAFE".toLowerCase()); + }); + + it("should use onDeploy", async function () { + let result = await Test.methods.addr().call(); + assert.strictEqual(result, MyToken.options.address); + }); }); diff --git a/test_apps/test_app/README.md b/test_apps/test_app/README.md index 45b4c9373..c4971454f 100644 --- a/test_apps/test_app/README.md +++ b/test_apps/test_app/README.md @@ -5,4 +5,3 @@ Test App for integration testing purposes. ```../../bin/embark test``` to see tests are working as expected ```dist/index.html``` and ```dist/test.html``` to check different functionality - diff --git a/test_apps/test_app/app/contracts/simple_storage.sol b/test_apps/test_app/app/contracts/simple_storage.sol index c72e8e98d..05808ddb9 100644 --- a/test_apps/test_app/app/contracts/simple_storage.sol +++ b/test_apps/test_app/app/contracts/simple_storage.sol @@ -12,6 +12,8 @@ library Assert { contract SimpleStorage is Ownable { uint public storedData; + address public registar; + event EventOnSet2(bool passed, string message); function() public payable { } @@ -29,6 +31,7 @@ contract SimpleStorage is Ownable { function set2(uint x, uint unusedGiveWarning) public onlyOwner { storedData = x; + emit EventOnSet2(true, "hi"); } function get() public view returns (uint retVal) { @@ -39,4 +42,8 @@ contract SimpleStorage is Ownable { return "hello"; } + function setRegistar(address x) public { + registar = x; + } + } diff --git a/test_apps/test_app/config/blockchain.json b/test_apps/test_app/config/blockchain.json index d86d2c768..cf136e8d4 100644 --- a/test_apps/test_app/config/blockchain.json +++ b/test_apps/test_app/config/blockchain.json @@ -19,13 +19,26 @@ "wsOrigins": "auto", "wsRPC": true, "wsHost": "localhost", - "wsPort": 8546 - + "wsPort": 8546, + "proxy": true }, "testnet": { "networkType": "testnet", "rpcHost": "localhost", - "rpcPort": 8545 + "rpcPort": 8545, + "syncMode": "fast", + "account": { + "password": "config/ropsten/password" + } + }, + "rinkeby": { + "networkType": "rinkeby", + "rpcHost": "localhost", + "rpcPort": 8545, + "syncMode": "fast", + "account": { + "password": "config/rinkeby/password" + } }, "livenet": { "networkType": "livenet", diff --git a/test_apps/test_app/config/communication.json b/test_apps/test_app/config/communication.json index 80ec2f80e..a6b7f7617 100644 --- a/test_apps/test_app/config/communication.json +++ b/test_apps/test_app/config/communication.json @@ -2,7 +2,7 @@ "default": { "enabled": true, "provider": "whisper", - "available_providers": ["whisper", "orbit"], + "available_providers": ["whisper"], "connection": { "host": "localhost", "port": 8546, diff --git a/test_apps/test_app/config/contracts.js b/test_apps/test_app/config/contracts.js new file mode 100644 index 000000000..d6e9be776 --- /dev/null +++ b/test_apps/test_app/config/contracts.js @@ -0,0 +1,101 @@ +module.exports = { + default: { + deployment: { + host: "localhost", + port: 8545, + type: "rpc" + }, + dappConnection: [ + "$WEB3", + "ws://localhost:8546", + "http://localhost:8550", + "http://localhost:8545", + "http://localhost:8550" + ], + gas: "auto", + contracts: { + Ownable: { + deploy: false + }, + SimpleStorage: { + fromIndex: 0, + args: [ + 100 + ], + onDeploy: [ + "SimpleStorage.methods.setRegistar(web3.eth.defaultAccount).send()" + ] + }, + AnotherStorage: { + args: [ + "$SimpleStorage" + ] + }, + Token: { + deploy: false, + args: [1000] + }, + Test: { + onDeploy: [ + "Test.methods.changeAddress('$MyToken')" + ] + }, + MyToken: { + instanceOf: "Token" + }, + MyToken2: { + instanceOf: "Token", + args: [200] + }, + AlreadyDeployedToken: { + address: "0xece374063fe5cc7efbaca0a498477cada94e5ad6", + instanceOf: "Token" + }, + MyToken3: { + instanceOf: "Tokn" + }, + ContractArgs: { + args: { + initialValue: 123, + "_addresses": ["$MyToken2", "$SimpleStorage"] + } + }, + SomeContract: { + args: [ + ["$MyToken2", "$SimpleStorage"], + 100 + ] + }, + ERC20: { + file: "zeppelin-solidity/contracts/token/ERC20/ERC20.sol" + }, + SimpleStorageTest: { + file: "./some_folder/test_contract.sol", + args: [ + 1000 + ] + }, + Identity: { + file: "https://github.com/status-im/contracts/blob/master/contracts/identity/Identity.sol" + }, + SimpleStorageWithHttpImport: { + fromIndex: 0, + args: [ + 100 + ] + } + }, + afterDeploy: [ + "Test.methods.changeAddress('$MyToken')", + "web3.eth.getAccounts((err, accounts) => Test.methods.changeAddress(accounts[0]))" + ] + }, + development: { + contracts: { + MyToken2: { + instanceOf: "Token", + args: [2000] + } + } + } +}; diff --git a/test_apps/test_app/config/contracts.json b/test_apps/test_app/config/contracts.json deleted file mode 100644 index b1f0597fa..000000000 --- a/test_apps/test_app/config/contracts.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "default": { - "deployment": { - "host": "localhost", - "port": 8545, - "type": "rpc" - }, - "dappConnection": [ - "$WEB3", - "ws://localhost:8546", - "http://localhost:8550", - "http://localhost:8545", - "http://localhost:8550" - ], - "gas": "auto", - "contracts": { - "Ownable": { - "deploy": false - }, - "SimpleStorage": { - "fromIndex": 0, - "args": [ - 100 - ] - }, - "AnotherStorage": { - "args": [ - "$SimpleStorage" - ] - }, - "Token": { - "deploy": false, - "args": [1000] - }, - "Test": { - "onDeploy": [ - "Test.methods.changeAddress('$MyToken')" - ] - }, - "MyToken": { - "instanceOf": "Token" - }, - "MyToken2": { - "instanceOf": "Token", - "args": [200] - }, - "AlreadyDeployedToken": { - "address": "0xece374063fe5cc7efbaca0a498477cada94e5ad6", - "instanceOf": "Token" - }, - "MyToken3": { - "instanceOf": "Tokn" - }, - "ContractArgs": { - "args": { - "initialValue": 123, - "_addresses": ["$MyToken2", "$SimpleStorage"] - } - }, - "SomeContract": { - "args": [ - ["$MyToken2", "$SimpleStorage"], - 100 - ] - }, - "ERC20": { - "file": "zeppelin-solidity/contracts/token/ERC20/ERC20.sol" - }, - "SimpleStorageTest": { - "file": "./some_folder/test_contract.sol", - "args": [ - 1000 - ] - }, - "Identity": { - "file": "https://github.com/status-im/contracts/blob/master/contracts/identity/Identity.sol" - }, - "SimpleStorageWithHttpImport": { - "fromIndex": 0, - "args": [ - 100 - ] - } - }, - "afterDeploy": [ - "Test.methods.changeAddress('$MyToken')", - "web3.eth.getAccounts((err, accounts) => Test.methods.changeAddress(accounts[0]))" - ] - }, - "development": { - "contracts": { - "MyToken2": { - "instanceOf": "Token", - "args": [2000] - } - } - } -} diff --git a/test_apps/test_app/config/rinkeby/password b/test_apps/test_app/config/rinkeby/password new file mode 100644 index 000000000..c747d679e --- /dev/null +++ b/test_apps/test_app/config/rinkeby/password @@ -0,0 +1 @@ +dev_password diff --git a/test_apps/test_app/config/ropsten/password b/test_apps/test_app/config/ropsten/password new file mode 100644 index 000000000..c747d679e --- /dev/null +++ b/test_apps/test_app/config/ropsten/password @@ -0,0 +1 @@ +dev_password diff --git a/test_apps/test_app/config/storage.json b/test_apps/test_app/config/storage.json index 55eb593a3..2209629d8 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": 80, - "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/" + } } } diff --git a/test_apps/test_app/embark.json b/test_apps/test_app/embark.json index 66dfb0066..3a5f72bcb 100644 --- a/test_apps/test_app/embark.json +++ b/test_apps/test_app/embark.json @@ -15,9 +15,10 @@ "buildDir": "dist/", "config": "config/", "versions": { - "solc": "0.4.18", + "solc": "0.4.24", "web3": "1.0.0-beta.34", - "ipfs-api": "17.2.7" + "ipfs-api": "17.2.7", + "p-iteration": "1.1.7" }, "plugins": { "embark-service": {} diff --git a/test_apps/test_app/extensions/embark-service/index.js b/test_apps/test_app/extensions/embark-service/index.js index b60c7e3fb..75acc5646 100644 --- a/test_apps/test_app/extensions/embark-service/index.js +++ b/test_apps/test_app/extensions/embark-service/index.js @@ -23,9 +23,12 @@ module.exports = function (embark) { 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.registerActionForEvent("deploy:contract:beforeDeploy", (params, cb) => { + embark.logger.info("applying beforeDeploy plugin..."); + //console.dir(params); + //console.dir(cb); + //console.dir('------------------'); + cb(); }); //embark.registerClientWeb3Provider(function(options) { diff --git a/test_apps/test_app/package-lock.json b/test_apps/test_app/package-lock.json index 1269406e8..3dba66074 100644 --- a/test_apps/test_app/package-lock.json +++ b/test_apps/test_app/package-lock.json @@ -152,6 +152,11 @@ "ua-parser-js": "0.7.17" } }, + "haml": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/haml/-/haml-0.4.3.tgz", + "integrity": "sha1-90BTGPPC7dGXpIsbjysvE+C7U3g=" + }, "has-ansi": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", diff --git a/test_apps/test_app/package.json b/test_apps/test_app/package.json index b29e3d6ca..8dd7bc59e 100644 --- a/test_apps/test_app/package.json +++ b/test_apps/test_app/package.json @@ -15,6 +15,7 @@ "dependencies": { "bootstrap": "^3.3.6", "embark-service": "file:extensions/embark-service", + "haml": "^0.4.3", "jquery": "^1.11.3", "react": "^16.0.0", "react-bootstrap": "^0.32.0", diff --git a/test_apps/test_app/test/another_storage_spec.js b/test_apps/test_app/test/another_storage_spec.js index 255a5d4b8..c054c3534 100644 --- a/test_apps/test_app/test/another_storage_spec.js +++ b/test_apps/test_app/test/another_storage_spec.js @@ -1,16 +1,38 @@ +/*global contract, config, it, web3*/ +const assert = require('assert'); +const AnotherStorage = require('Embark/contracts/AnotherStorage'); +const SimpleStorage = require('Embark/contracts/SimpleStorage'); + +let accounts; + +config({ + deployment: { + "accounts": [ + { + "mnemonic": "example exile argue silk regular smile grass bomb merge arm assist farm", + balance: "5ether" + } + ] + }, + contracts: { + "SimpleStorage": { + args: [100] + }, + "AnotherStorage": { + args: ["$SimpleStorage"] + } + } +}, (err, theAccounts) => { + accounts = theAccounts; +}); + contract("AnotherStorage", function() { this.timeout(0); - before(function(done) { - this.timeout(0); - var contractsConfig = { - "SimpleStorage": { - args: [100] - }, - "AnotherStorage": { - args: ["$SimpleStorage"] - } - }; - EmbarkSpec.deployAll(contractsConfig, () => { done() }); + + it("should have account with balance", async function() { + let balance = await web3.eth.getBalance(accounts[0]); + assert.ok(parseInt(balance, 10) > 4900000000000000000); + assert.ok(parseInt(balance, 10) <= 5000000000000000000); }); it("set SimpleStorage address", async function() { @@ -18,4 +40,8 @@ contract("AnotherStorage", function() { assert.equal(result.toString(), SimpleStorage.options.address); }); + it("set SimpleStorage address with alternative syntax", async function() { + let result = await AnotherStorage.simpleStorageAddress(); + assert.equal(result.toString(), SimpleStorage.options.address); + }); }); diff --git a/test_apps/test_app/test/array_references_spec.js b/test_apps/test_app/test/array_references_spec.js index 99cf37da9..ca11c3bb9 100644 --- a/test_apps/test_app/test/array_references_spec.js +++ b/test_apps/test_app/test/array_references_spec.js @@ -1,37 +1,42 @@ +/*global contract, config, it*/ +const assert = require('assert'); +const SomeContract = require('Embark/contracts/SomeContract'); +const SimpleStorage = require('Embark/contracts/SimpleStorage'); +const MyToken2 = require('Embark/contracts/MyToken2'); + +config({ + contracts: { + "SimpleStorage": { + args: [100] + }, + "Token": { + deploy: false, + args: [1000] + }, + "MyToken2": { + instanceOf: "Token", + args: [2000] + }, + "SomeContract": { + "args": [ + ["$MyToken2", "$SimpleStorage"], + 100 + ] + } + } +}); + contract("SomeContract", function() { this.timeout(0); - before(function(done) { - this.timeout(0); - var contractsConfig = { - "SimpleStorage": { - args: [100] - }, - "Token": { - deploy: false, - args: [1000] - }, - "MyToken2": { - instanceOf: "Token", - args: [2000] - }, - "SomeContract": { - "args": [ - ["$MyToken2", "$SimpleStorage"], - 100 - ] - } - }; - EmbarkSpec.deployAll(contractsConfig, () => { done() }); - }); it("set MyToken2 address", async function() { let address = await SomeContract.methods.addr_1().call(); - assert.equal(address, MyToken2.options.address); + assert.strictEqual(address, MyToken2.options.address); }); it("set SimpleStorage address", async function() { let address = await SomeContract.methods.addr_2().call(); - assert.equal(address, SimpleStorage.options.address); + assert.strictEqual(address, SimpleStorage.options.address); }); }); diff --git a/test_apps/test_app/test/interface_spec.js b/test_apps/test_app/test/interface_spec.js new file mode 100644 index 000000000..f546c2a83 --- /dev/null +++ b/test_apps/test_app/test/interface_spec.js @@ -0,0 +1,22 @@ +/*global contract, config, it*/ +const assert = require('assert'); +const AnotherStorage = require('Embark/contracts/AnotherStorage'); + +config({ + contracts: { + AnotherStorage: { + args: ['$ERC20'] + } + } +}); + + +contract("AnotherStorageWithInterface", function() { + this.timeout(0); + + it("sets an empty address because ERC20 is an interface", async function() { + let result = await AnotherStorage.methods.simpleStorageAddress().call(); + assert.equal(result.toString(), '0x0000000000000000000000000000000000000000'); + }); +}); + diff --git a/test_apps/test_app/test/lib_test_spec.js b/test_apps/test_app/test/lib_test_spec.js index 18aef2c9f..fe2a2729a 100644 --- a/test_apps/test_app/test/lib_test_spec.js +++ b/test_apps/test_app/test/lib_test_spec.js @@ -1,22 +1,23 @@ +/*global contract, config, it*/ +const assert = require('assert'); +const Test2 = require('Embark/contracts/Test2'); + +config({ + contracts: { + "Test2": { + }, + "ZAMyLib": { + }, + "ZAMyLib2": { + "deploy": true + } + } +}); + contract("Test", function() { - before(function(done) { - this.timeout(0); - var contractsConfig = { - "Test2": { - }, - "ZAMyLib": { - }, - "ZAMyLib2": { - "deploy": true - } - }; - - EmbarkSpec.deployAll(contractsConfig, () => { done() }); - }); - it("should call library correctly", async function() { let result = await Test2.methods.testAdd().call(); - assert.equal(result, 3); + assert.strictEqual(parseInt(result, 10), 3); }); }); diff --git a/test_apps/test_app/test/plugin_storage_spec.js b/test_apps/test_app/test/plugin_storage_spec.js index 24a58c4e8..623ec3cce 100644 --- a/test_apps/test_app/test/plugin_storage_spec.js +++ b/test_apps/test_app/test/plugin_storage_spec.js @@ -1,23 +1,23 @@ -/*global contract, before, EmbarkSpec, PluginStorage, SimpleStorage, it*/ +/*global contract, config, it*/ const assert = require('assert'); +const PluginStorage = require('Embark/contracts/PluginStorage'); +const SimpleStorage = require('Embark/contracts/SimpleStorage'); + +config({ + contracts: { + "SimpleStorage": { + args: [100] + }, + "PluginStorage": { + args: ["$SimpleStorage"] + } + } +}); + 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/simple_storage_deploy_spec.js b/test_apps/test_app/test/simple_storage_deploy_spec.js new file mode 100644 index 000000000..cab91835d --- /dev/null +++ b/test_apps/test_app/test/simple_storage_deploy_spec.js @@ -0,0 +1,22 @@ +/*global contract, it, embark, assert, before*/ +const SimpleStorage = embark.require('Embark/contracts/SimpleStorage'); + +contract("SimpleStorage Deploy", function () { + let SimpleStorageInstance; + + before(async function() { + SimpleStorageInstance = await SimpleStorage.deploy({arguments: [150]}).send(); + }); + + it("should set constructor value", async function () { + let result = await SimpleStorageInstance.methods.storedData().call(); + assert.strictEqual(parseInt(result, 10), 150); + }); + + it("set storage value", async function () { + await SimpleStorageInstance.methods.set(150).send(); + let result = await SimpleStorageInstance.methods.get().call(); + assert.strictEqual(parseInt(result, 10), 499650); + }); + +}); diff --git a/test_apps/test_app/test/simple_storage_spec.js b/test_apps/test_app/test/simple_storage_spec.js index b43e0b354..230c39d95 100644 --- a/test_apps/test_app/test/simple_storage_spec.js +++ b/test_apps/test_app/test/simple_storage_spec.js @@ -1,31 +1,51 @@ +/*global contract, config, it, assert, web3*/ +const SimpleStorage = require('Embark/contracts/SimpleStorage'); +let accounts; -contract("SimpleStorage", function() { +config({ + contracts: { + "SimpleStorage": { + args: [100], + onDeploy: ["SimpleStorage.methods.setRegistar(web3.eth.defaultAccount).send()"] + } + } +}, (err, theAccounts) => { + accounts = theAccounts; +}); +contract("SimpleStorage", function () { this.timeout(0); - before(function(done) { - this.timeout(0); - //config({ - // node: "http://localhost:8545" - //}); - - var contractsConfig = { - "SimpleStorage": { - args: [100] - } - }; - EmbarkSpec.deployAll(contractsConfig, () => { done() }); - }); - - it("should set constructor value", async function() { + it("should set constructor value", async function () { let result = await SimpleStorage.methods.storedData().call(); - assert.equal(result, 100); + assert.strictEqual(parseInt(result, 10), 100); }); - it("set storage value", async function() { + it("set storage value", async function () { await SimpleStorage.methods.set(150).send(); let result = await SimpleStorage.methods.get().call(); - assert.equal(result, 499650); + assert.strictEqual(parseInt(result, 10), 499650); + }); + + it("should set defaultAccount", async function () { + let result = await SimpleStorage.methods.registar().call(); + assert.strictEqual(result, web3.eth.defaultAccount); + assert.strictEqual(accounts[0], web3.eth.defaultAccount); + }); + + it("should alias contract address", function () { + assert.strictEqual(SimpleStorage.options.address, SimpleStorage.address); + }); + + it('listens to events', function (done) { + SimpleStorage.once('EventOnSet2', async function(error, _result){ + assert.strictEqual(error, null); + let result = await SimpleStorage.methods.get().call(); + assert.strictEqual(parseInt(result, 10), 150); + done(); + }); + + SimpleStorage.methods.set2(150, 100).send(); }); }); diff --git a/test_apps/test_app/test/token_spec.js b/test_apps/test_app/test/token_spec.js index 88dfc1a87..a6e542100 100644 --- a/test_apps/test_app/test/token_spec.js +++ b/test_apps/test_app/test/token_spec.js @@ -1,86 +1,82 @@ -/*global describe, it, before*/ +/*global describe, config, it*/ +const assert = require('assert'); +const Token = require('Embark/contracts/Token'); +const MyToken = require('Embark/contracts/MyToken'); +const MyToken2 = require('Embark/contracts/MyToken2'); +const AlreadyDeployedToken = require('Embark/contracts/AlreadyDeployedToken'); +const Test = require('Embark/contracts/Test'); -describe("Token", function() { - - this.timeout(0); - before(function(done) { - this.timeout(0); - - //config({ - // node: "http://localhost:8545" - //}); - - var contractsConfig = { - "ZAMyLib": { - }, - "SimpleStorage": { - args: [100] - }, - "AnotherStorage": { - args: ["$SimpleStorage"] - }, - "Token": { - deploy: false, - args: [1000] - }, - "MyToken": { - instanceOf: "Token" - }, - "MyToken2": { - instanceOf: "Token", - args: [2000] - }, - "AlreadyDeployedToken": { - "address": "0xCAFECAFECAFECAFECAFECAFECAFECAFECAFECAFE", - instanceOf: "Token" - }, - "Test": { - onDeploy: [ - "Test.methods.changeAddress('$MyToken').send()" - ] - }, - "ContractArgs": { - "args": { - "initialValue": 123, - "_addresses": ["$MyToken2", "$SimpleStorage"] - } - }, - "SomeContract": { - "args": [ - ["$MyToken2", "$SimpleStorage"], - 100 - ] +config({ + contracts: { + ZAMyLib: {}, + SimpleStorage: { + args: [100] + }, + AnotherStorage: { + args: ["$SimpleStorage"] + }, + Token: { + deploy: false, + args: [1000] + }, + MyToken: { + instanceOf: "Token" + }, + MyToken2: { + instanceOf: "Token", + args: [2000] + }, + AlreadyDeployedToken: { + address: "0xCAFECAFECAFECAFECAFECAFECAFECAFECAFECAFE", + instanceOf: "Token" + }, + Test: { + onDeploy: ["Test.methods.changeAddress('$MyToken').send()"] + }, + ContractArgs: { + args: { + initialValue: 123, + _addresses: ["$MyToken2", "$SimpleStorage"] } - }; - EmbarkSpec.deployAll(contractsConfig, () => { done() }); - }); - - it("not deploy Token", function() { - assert.equal(Token.address, ""); - }); - - it("not deploy MyToken and MyToken2", function() { - assert.notEqual(MyToken.address, ""); - assert.notEqual(MyToken2.address, ""); - }); - - it("set MyToken Balance correctly", async function() { - let result = await MyToken.methods._supply().call(); - assert.equal(result, 1000); - }); - - it("set MyToken2 Balance correctly", async function() { - let result = await MyToken2.methods._supply().call(); - assert.equal(result, 2000); - }); - - it("get right address", function() { - assert.equal(AlreadyDeployedToken.address, "0xCAFECAFECAFECAFECAFECAFECAFECAFECAFECAFE"); - }); - - it("should use onDeploy", async function() { - let result = await Test.methods.addr().call(); - assert.equal(result, MyToken.address) - }); - + }, + SomeContract: { + args: [ + ["$MyToken2", "$SimpleStorage"], + 100 + ] + } + } +}); + +describe("Token", function () { + this.timeout(0); + + it("not deploy Token", function () { + assert.strictEqual(Token.address, undefined); + }); + + it("should deploy MyToken and MyToken2", function () { + assert.ok(MyToken.options.address); + assert.ok(MyToken2.options.address); + }); + + it("set MyToken Balance correctly", async function () { + let result = await MyToken.methods._supply().call(); + assert.strictEqual(parseInt(result, 10), 1000); + }); + + it("set MyToken2 Balance correctly", async function () { + let result = await MyToken2.methods._supply().call(); + assert.strictEqual(parseInt(result, 10), 2000); + }); + + it("get right address", function () { + assert.strictEqual(AlreadyDeployedToken.options.address.toLowerCase(), + "0xCAFECAFECAFECAFECAFECAFECAFECAFECAFECAFE".toLowerCase()); + }); + + it("should use onDeploy", async function () { + let result = await Test.methods.addr().call(); + assert.strictEqual(result, MyToken.options.address); + }); });