From b9472892cb7967254a57ae6de818c45921f71226 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Thu, 10 May 2018 14:52:30 -0400 Subject: [PATCH 1/3] fix conflict in engine --- lib/core/engine.js | 5 +++-- lib/core/provider.js | 37 +++++++++++++++++++++++++++++++++++++ package.json | 1 + 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 lib/core/provider.js diff --git a/lib/core/engine.js b/lib/core/engine.js index 2254d1ac..35d8ed32 100644 --- a/lib/core/engine.js +++ b/lib/core/engine.js @@ -10,6 +10,7 @@ const Watch = require('../pipeline/watch.js'); const LibraryManager = require('../versions/library_manager.js'); const Pipeline = require('../pipeline/pipeline.js'); const async = require('async'); +const Provider = require('./provider'); class Engine { constructor(options) { @@ -271,8 +272,8 @@ class Engine { 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)); + const web3Endpoint = 'http://' + this.config.contractsConfig.deployment.host + ':' + this.config.contractsConfig.deployment.port; + this.web3.setProvider(new Provider(web3Endpoint)); } else { throw new Error("contracts config error: unknown deployment type " + this.config.contractsConfig.deployment.type); } diff --git a/lib/core/provider.js b/lib/core/provider.js new file mode 100644 index 00000000..66f92d3a --- /dev/null +++ b/lib/core/provider.js @@ -0,0 +1,37 @@ +const ProviderEngine = require('web3-provider-engine'); +// const ProviderSubprovider = require("web3-provider-engine/subproviders/provider.js"); +const RpcSubprovider = require('web3-provider-engine/subproviders/rpc.js'); + +class Provider { + constructor(web3Endpoint) { + this.engine = new ProviderEngine(); + // this.web3 = new Web3(engine); + + this.engine.addProvider(new RpcSubprovider({ + rpcUrl: web3Endpoint + })); + + this.engine.on('block', function (block) { + console.log('================================'); + console.log('BLOCK CHANGED:', '#' + block.number.toString('hex'), '0x' + block.hash.toString('hex')); + console.log('================================'); + }); + + // network connectivity error + this.engine.on('error', function (err) { + // report connectivity errors + console.error(err.stack); + }); + this.engine.start(); + } + + sendAsync() { + this.engine.sendAsync.apply(this.engine, arguments); + } + + send() { + return this.engine.send.apply(this.engine, arguments); + } +} + +module.exports = Provider; diff --git a/package.json b/package.json index c2a35728..fc27e7f9 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "url-loader": "^0.6.2", "viz.js": "^1.8.1", "web3": "1.0.0-beta.34", + "web3-provider-engine": "^14.0.5", "webpack": "^3.10.0", "window-size": "^1.1.0" }, From c1dd5dde9d750d28b0a68aa049ad5d6dd95d2a35 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Thu, 10 May 2018 14:52:51 -0400 Subject: [PATCH 2/3] conflict in package lock --- lib/core/engine.js | 8 ++++- lib/core/provider.js | 69 ++++++++++++++++++++++++++++++++++++++++++-- package.json | 2 ++ 3 files changed, 75 insertions(+), 4 deletions(-) diff --git a/lib/core/engine.js b/lib/core/engine.js index 35d8ed32..6638ee00 100644 --- a/lib/core/engine.js +++ b/lib/core/engine.js @@ -273,7 +273,13 @@ class Engine { this.web3 = new Web3(); if (this.config.contractsConfig.deployment.type === "rpc") { const web3Endpoint = 'http://' + this.config.contractsConfig.deployment.host + ':' + this.config.contractsConfig.deployment.port; - this.web3.setProvider(new Provider(web3Endpoint)); + const providerOptions = { + web3: this.web3, + accountsConfig: this.config.contractsConfig.deployment.accounts, + logger: this.logger, + web3Endpoint + }; + this.web3.setProvider(new Provider(providerOptions)); } else { throw new Error("contracts config error: unknown deployment type " + this.config.contractsConfig.deployment.type); } diff --git a/lib/core/provider.js b/lib/core/provider.js index 66f92d3a..7857e332 100644 --- a/lib/core/provider.js +++ b/lib/core/provider.js @@ -1,16 +1,51 @@ const ProviderEngine = require('web3-provider-engine'); -// const ProviderSubprovider = require("web3-provider-engine/subproviders/provider.js"); const RpcSubprovider = require('web3-provider-engine/subproviders/rpc.js'); +const HookedWalletSubprovider = require('web3-provider-engine/subproviders/hooked-wallet.js'); +const bip39 = require("bip39"); +const hdkey = require('ethereumjs-wallet/hdkey'); +const fs = require('./fs'); class Provider { - constructor(web3Endpoint) { + constructor(options) { + const self = this; + this.web3 = options.web3; + this.accountsConfig = options.accountsConfig; + this.logger = options.logger; this.engine = new ProviderEngine(); // this.web3 = new Web3(engine); this.engine.addProvider(new RpcSubprovider({ - rpcUrl: web3Endpoint + rpcUrl: options.web3Endpoint })); + if (this.accountsConfig && this.accountsConfig.length) { + this.accounts = []; + this.accountsConfig.forEach(accountConfig => { + const account = this.getAccount(accountConfig); + if (!account) { + return; + } + if (Array.isArray(account)) { + this.accounts = this.accounts.concat(account); + return; + } + this.accounts.push(this.getAccount(accountConfig)); + }); + + /*this.engine.addProvider(new HookedWalletSubprovider({ + getAccounts: function (cb) { + cb(null, self.accounts); + }, + approveTransaction: function (cb) { + + }, + signTransaction: function (cb) { + + } + }));*/ + } + + this.engine.on('block', function (block) { console.log('================================'); console.log('BLOCK CHANGED:', '#' + block.number.toString('hex'), '0x' + block.hash.toString('hex')); @@ -25,6 +60,34 @@ class Provider { this.engine.start(); } + getAccount(accountConfig) { + if (accountConfig.privateKey) { + return this.web3.eth.accounts.privateKeyToAccount(accountConfig.privateKey); + } + if (accountConfig.privateKeyFile) { + let fileContent = fs.readFileSync(fs.dappPath(accountConfig.privateKeyFile)).toString(); + return this.web3.eth.accounts.privateKeyToAccount(fileContent.trim()); + } + 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 = "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(this.web3.eth.accounts.privateKeyToAccount(wallet.getPrivateKey())); + } + + return accounts; + } + this.logger.warn('Unsupported account configuration: ' + JSON.stringify(accountConfig)); + this.logger.warn('Try using one of those: ' + + '{ "privateKey": "your-private-key", "privateKeyFile": "path/to/file/containing/key", "mnemonic": "12 word mnemonic" }'); + } + sendAsync() { this.engine.sendAsync.apply(this.engine, arguments); } diff --git a/package.json b/package.json index fc27e7f9..bc14f1e9 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "babel-preset-es2016": "^6.24.1", "babel-preset-es2017": "6.24.1", "babel-preset-react": "^6.24.1", + "bip39": "^2.5.0", "blessed": "^0.1.81", "chokidar": "^2.0.3", "colors": "^1.1.2", @@ -39,6 +40,7 @@ "ejs": "^2.5.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", From 391207e1bb8746174572ea769ea5ba9c41f48083 Mon Sep 17 00:00:00 2001 From: Jonathan Rainville Date: Fri, 11 May 2018 11:41:54 -0400 Subject: [PATCH 3/3] intercept get accounts --- lib/core/provider.js | 62 ++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/lib/core/provider.js b/lib/core/provider.js index 7857e332..c8bcc9f2 100644 --- a/lib/core/provider.js +++ b/lib/core/provider.js @@ -1,18 +1,16 @@ const ProviderEngine = require('web3-provider-engine'); const RpcSubprovider = require('web3-provider-engine/subproviders/rpc.js'); -const HookedWalletSubprovider = require('web3-provider-engine/subproviders/hooked-wallet.js'); const bip39 = require("bip39"); const hdkey = require('ethereumjs-wallet/hdkey'); const fs = require('./fs'); class Provider { constructor(options) { - const self = this; + const self = this; this.web3 = options.web3; this.accountsConfig = options.accountsConfig; this.logger = options.logger; this.engine = new ProviderEngine(); - // this.web3 = new Web3(engine); this.engine.addProvider(new RpcSubprovider({ rpcUrl: options.web3Endpoint @@ -20,6 +18,7 @@ class Provider { if (this.accountsConfig && this.accountsConfig.length) { this.accounts = []; + this.addresses = []; this.accountsConfig.forEach(accountConfig => { const account = this.getAccount(accountConfig); if (!account) { @@ -27,25 +26,25 @@ class Provider { } if (Array.isArray(account)) { this.accounts = this.accounts.concat(account); + account.forEach(acc => { + this.addresses.push(acc.address); + }); return; } - this.accounts.push(this.getAccount(accountConfig)); + this.accounts.push(account); + this.addresses.push(account.address); }); - /*this.engine.addProvider(new HookedWalletSubprovider({ - getAccounts: function (cb) { - cb(null, self.accounts); - }, - approveTransaction: function (cb) { - - }, - signTransaction: function (cb) { - - } - }));*/ + if (this.accounts.length) { + this.asyncMethods = { + eth_accounts: self.eth_accounts.bind(this) + }; + this.syncMethods = { + eth_accounts: self.eth_accounts_sync.bind(this) + }; + } } - this.engine.on('block', function (block) { console.log('================================'); console.log('BLOCK CHANGED:', '#' + block.number.toString('hex'), '0x' + block.hash.toString('hex')); @@ -73,10 +72,10 @@ class Provider { const addressIndex = accountConfig.addressIndex || 0; const numAddresses = accountConfig.numAddresses || 1; - const wallet_hdpath = "m/44'/60'/0'/0/"; + const wallet_hdpath = "m/44'/60'/0'/0/"; // TODO check if this can change const accounts = []; - for (let i = addressIndex; i < addressIndex + numAddresses; i++){ + for (let i = addressIndex; i < addressIndex + numAddresses; i++) { const wallet = hdwallet.derivePath(wallet_hdpath + i).getWallet(); accounts.push(this.web3.eth.accounts.privateKeyToAccount(wallet.getPrivateKey())); } @@ -88,11 +87,34 @@ class Provider { '{ "privateKey": "your-private-key", "privateKeyFile": "path/to/file/containing/key", "mnemonic": "12 word mnemonic" }'); } - sendAsync() { + eth_accounts(payload, cb) { + return cb(null, this.addresses); + } + + eth_accounts_sync() { + return this.addresses; + } + + sendAsync(payload, callback) { + // this.engine.sendAsync.apply(this.engine, arguments); + 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() { + send(payload) { + let method = this.syncMethods[payload.method]; + if (method) { + return method.call(method, payload); // TODO check if that makes sense + } return this.engine.send.apply(this.engine, arguments); } }