diff --git a/lib/core/processes/processWrapper.js b/lib/core/processes/processWrapper.js index 8c90d67a6..26137474d 100644 --- a/lib/core/processes/processWrapper.js +++ b/lib/core/processes/processWrapper.js @@ -1,4 +1,4 @@ -process.on('uncaughtException', function(e) { +process.on('uncaughtException', function(e){ process.send({error: e.stack}); }); diff --git a/lib/modules/blockchain_connector/index.js b/lib/modules/blockchain_connector/index.js index 32df3b72b..84593ffda 100644 --- a/lib/modules/blockchain_connector/index.js +++ b/lib/modules/blockchain_connector/index.js @@ -1,12 +1,15 @@ const Web3 = require('web3'); const async = require('async'); const Provider = require('./provider.js'); -const utils = require('../utils/utils'); +const utils = require('../../utils/utils'); +const constants = require('../../constants'); +const embarkJsUtils = require('embarkjs').Utils; const WEB3_READY = 'blockchain:ready'; -class Blockchain { - constructor(options) { +// TODO: consider another name, this is the blockchain connector +class BlockchainConnector { + constructor(embark, options) { const self = this; this.plugins = options.plugins; this.logger = embark.logger; @@ -22,6 +25,10 @@ class Blockchain { cb(self.isWeb3Ready); }); + self.events.setCommandHandler("blockchain:object", (cb) => { + cb(self); + }); + if (!this.web3) { this.initWeb3(); } else { @@ -32,6 +39,7 @@ class Blockchain { this.registerRequests(); this.registerWeb3Object(); this.registerEvents(); + this.subscribeToPendingTransactions(); } initWeb3(cb) { @@ -328,60 +336,14 @@ class Blockchain { } deployContractFromObject(deployContractObject, params, cb) { - const self = this; - let hash; - let calledBacked = false; - - function callback(err, receipt) { - if (calledBacked) { - return; - } - if (!err && !receipt.contractAddress) { - return; // Not deployed yet. Need to wait - } - if (interval) { - clearInterval(interval); - } - calledBacked = true; - cb(err, receipt); - } - - // This interval is there to compensate for the event that sometimes doesn't get triggered when using WebSocket - // FIXME The issue somehow only happens when the blockchain node is started in the same terminal - const interval = setInterval(() => { - if (!hash) { - return; // Wait until we receive the hash - } - self.web3.eth.getTransactionReceipt(hash, (err, receipt) => { - if (!err && !receipt) { - return; // Transaction is not yet complete - } - callback(err, receipt); - }); - }, 500); - - deployContractObject.send({ + embarkJsUtils.secureSend(this.web3, deployContractObject, { from: params.from, gas: params.gas, gasPrice: params.gasPrice - }, function (err, transactionHash) { - if (err) { - return callback(err); - } - hash = transactionHash; - }).on('receipt', function (receipt) { - if (receipt.contractAddress !== undefined) { - callback(null, receipt); - } - }).then(function (_contract) { - if (!hash) { - return; // Somehow we didn't get the receipt yet... Interval will catch it - } - self.web3.eth.getTransactionReceipt(hash, callback); - }).catch(callback); + }, true, cb); } determineDefaultAccount(cb) { const self = this; - self.getAccounts(function (err, accounts) { + self.getAccounts(function(err, accounts) { if (err) { self.logger.error(err); return cb(new Error(err)); @@ -399,8 +361,21 @@ class Blockchain { // can just be a command without a callback this.events.emit("runcode:register", "web3", this.web3, false); } + + subscribeToPendingTransactions() { + const self = this; + this.onReady(() => { + if (self.logsSubscription) { + self.logsSubscription.unsubscribe(); + } + self.logsSubscription = self.web3.eth + .subscribe('newBlockHeaders', () => {}) + .on("data", function (blockHeader) { + self.events.emit('block:header', blockHeader); + }); + }); + } } BlockchainConnector.ACCEPTED_TYPES = ['rpc', 'ws', 'vm']; module.exports = BlockchainConnector; - diff --git a/lib/modules/blockchain_connector/provider.js b/lib/modules/blockchain_connector/provider.js index ffe1cc52d..e4fd81cac 100644 --- a/lib/modules/blockchain_connector/provider.js +++ b/lib/modules/blockchain_connector/provider.js @@ -11,17 +11,13 @@ class Provider { 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 - })); + self.provider = new this.web3.providers.HttpProvider(self.web3Endpoint); } else if (this.type === 'ws') { // Note: don't pass to the provider things like {headers: {Origin: "embark"}}. Origin header is for browser to fill // to protect user, it has no meaning if it is used server-side. See here for more details: https://github.com/ethereum/go-ethereum/issues/16608 @@ -36,25 +32,7 @@ class Provider { 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); - }); - - self.engine.start(); - //self.on('error', (err) => { - // console.log('ERR', JSON.stringify(err)); - // // report connectivity errors as trace due to polling - // self.logger.trace('web3 provider error: ', err); - // self.logger.trace('stopping web3 provider due to error'); - - // // prevent continuous polling errors - // self.stop(); - //}); - - //self.web3.setProvider(self); - //self.start(); + self.web3.setProvider(self.provider); self.web3.eth.getAccounts((err, accounts) => { if (err) { @@ -124,36 +102,10 @@ class Provider { if (!self.isDev) { return callback(); } - async.each(self.accounts, (account, eachCb) => { + async.eachLimit(self.accounts, 1, (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/modules/blockchain_connector/provider.js~HEAD b/lib/modules/blockchain_connector/provider.js~HEAD deleted file mode 100644 index 59b1bdb96..000000000 --- a/lib/modules/blockchain_connector/provider.js~HEAD +++ /dev/null @@ -1,82 +0,0 @@ -const async = require('async'); -const AccountParser = require('../../utils/accountParser'); -const fundAccount = require('./fundAccount'); - -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; - } - - startWeb3Provider(callback) { - const self = this; - - if (this.type === 'rpc') { - self.provider = new this.web3.providers.HttpProvider(self.web3Endpoint); - } else if (this.type === 'ws') { - self.provider = new this.web3.providers.WebsocketProvider(self.web3Endpoint, {headers: {Origin: "embark"}}); - } else { - return callback(__("contracts config error: unknown deployment type %s", this.type)); - } - - self.web3.setProvider(self.provider); - - self.accounts = AccountParser.parseAccountsConfig(self.accountsConfig, self.web3, self.logger); - self.addresses = []; - - if (!self.accounts.length) { - return callback(); - } - self.accounts.forEach(account => { - self.addresses.push(account.address); - self.web3.eth.accounts.wallet.add(account); - }); - self.web3.eth.defaultAccount = self.addresses[0]; - const realSend = self.provider.send.bind(self.provider); - self.provider.send = function (payload, cb) { - if (payload.method === 'eth_accounts') { - return realSend(payload, function (err, result) { - if (err) { - return cb(err); - } - result.result = result.result.concat(self.addresses); - cb(null, result); - }); - } - realSend(payload, cb); - }; - - callback(); - } - - stop() { - if (this.provider && this.provider.removeAllListeners) { - this.provider.removeAllListeners('connect'); - this.provider.removeAllListeners('error'); - this.provider.removeAllListeners('end'); - this.provider.removeAllListeners('data'); - this.provider.responseCallbacks = {}; - this.provider = null; - } - } - - fundAccounts(callback) { - const self = this; - if (!self.accounts.length) { - return callback(); - } - if (!self.isDev) { - return callback(); - } - async.eachLimit(self.accounts, 1, (account, eachCb) => { - fundAccount(self.web3, account.address, account.hexBalance, eachCb); - }, callback); - } -} - -module.exports = Provider; diff --git a/lib/modules/ens/register.js b/lib/modules/ens/register.js index 030da5b0f..ab344403a 100644 --- a/lib/modules/ens/register.js +++ b/lib/modules/ens/register.js @@ -3,11 +3,7 @@ const namehash = require('eth-ens-namehash'); // Price of ENS registration contract functions const ENS_GAS_PRICE = 700000; -<<<<<<< HEAD function registerSubDomain(ens, registrar, resolver, defaultAccount, subdomain, rootDomain, reverseNode, address, logger, secureSend, callback) { -======= -function registerSubDomain(ens, registrar, resolver, defaultAccount, subdomain, rootDomain, reverseNode, address, callback) { ->>>>>>> if no register config, dont register anything const subnode = namehash.hash(subdomain); const rootNode = namehash.hash(rootDomain); const node = namehash.hash(`${subdomain}.${rootDomain}`); diff --git a/lib/modules/library_manager/npmTimer.js b/lib/modules/library_manager/npmTimer.js index af37b0edb..95d3a23fe 100644 --- a/lib/modules/library_manager/npmTimer.js +++ b/lib/modules/library_manager/npmTimer.js @@ -39,7 +39,6 @@ class NpmTimer{ else{ // otherwise, find our download complete measurement entry = utils.last(items.getEntries().filter(entry => entry.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(); diff --git a/lib/modules/storage/embarkjs.js b/lib/modules/storage/embarkjs.js deleted file mode 100644 index 20cf842ba..000000000 --- a/lib/modules/storage/embarkjs.js +++ /dev/null @@ -1,37 +0,0 @@ -/* global EmbarkJS */ - -import {detectSeries} from 'async'; - -let __embarkStorage = {}; - -__embarkStorage.setProviders = async function (dappConnOptions) { - try { - await detectSeries(dappConnOptions, async (dappConn, callback) => { - 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(); - callback(null, isAvailable); - }catch(err){ - callback(null, 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(); - callback(null, isAvailable); - } catch(err) { - callback(null, false); // catch but keep looping by not passing err to callback - } - } - }, function(err, result){ - if(!result) 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/processes/process_manager.js b/lib/processes/process_manager.js deleted file mode 100644 index 4da9ddeab..000000000 --- a/lib/processes/process_manager.js +++ /dev/null @@ -1,39 +0,0 @@ - -class ProcessManager { - constructor(options) { - const self = this; - this.logger = options.logger; - this.events = options.events; - this.plugins = options.plugins; - this.processes = {}; - - self.events.setCommandHandler('processes:register', (name, cb) => { - console.dir("=====> registering " + name); - this.processes[name] = { - state: 'unstarted', - cb: cb - } - }); - - self.events.setCommandHandler('processes:launch', (name, cb) => { - let process = self.processes[name]; - // TODO: should make distinction between starting and running - if (process.state != 'unstarted') { - console.dir("=====> already started " + name); - return cb(); - } - console.dir("=====> launching " + name); - process.state = 'starting'; - //let pry = require('pryjs'); - //eval(pry.it); - process.cb.apply(process.cb, [() => { - process.state = 'running'; - console.dir("=====> launched " + name); - cb(); - }]); - }); - } - -} - -module.exports = ProcessManager; diff --git a/test_apps/test_app/config/blockchain.json b/test_apps/test_app/config/blockchain.json index 9051682d4..fd4f0a514 100644 --- a/test_apps/test_app/config/blockchain.json +++ b/test_apps/test_app/config/blockchain.json @@ -1,4 +1,4 @@ - +{ "default": { "enabled": true, "rpcHost": "localhost", @@ -13,8 +13,6 @@ "networkType": "custom", "networkId": "1337", "isDev": true, - "isDev": false, - "genesisBlock": "config/development/genesis.json", "datadir": ".embark/development/datadir", "mineWhenNeeded": true, "nodiscover": true, diff --git a/test_apps/test_app/embark.json b/test_apps/test_app/embark.json index e4a75559c..a4c2f1d27 100644 --- a/test_apps/test_app/embark.json +++ b/test_apps/test_app/embark.json @@ -16,7 +16,7 @@ "config": "config/", "versions": { "solc": "0.4.24", - "web3": "1.0.0-beta.34", + "web3": "1.0.0-beta", "ipfs-api": "17.2.7" }, "plugins": { diff --git a/test_apps/test_app/test/ens_spec.js b/test_apps/test_app/test/ens_spec.js index 200f2634f..7c564734f 100644 --- a/test_apps/test_app/test/ens_spec.js +++ b/test_apps/test_app/test/ens_spec.js @@ -17,22 +17,28 @@ config({ "args": ["$ENSRegistry", rootNode], "onDeploy": [ `ENSRegistry.methods.setOwner('${rootNode}', web3.eth.defaultAccount).send().then(() => { - ENSRegistry.methods.setResolver('${rootNode}', "$Resolver").send(); - Resolver.methods.setAddr('${rootNode}', '${address}').send(); - })` + ENSRegistry.methods.setResolver('${rootNode}', "$Resolver").send(); + Resolver.methods.setAddr('${rootNode}', '${address}').send().then(() => { + global.ensTestReady = true; + }); + });` ] } } }); contract("ENS", function () { - this.timeout(0); + this.timeout(1000); before(function (done) { // Wait for onDeploy to finish - setTimeout(function () { + const wait = setInterval(() => { + if (!global.ensTestReady) { + return; + } + clearInterval(wait); done(); - }, 500); + }, 50); }); it("should have registered embark.eth", async function () {