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",