diff --git a/lib/cmds/blockchain/blockchain.js b/lib/cmds/blockchain/blockchain.js index 87ae481c..100ee0e1 100644 --- a/lib/cmds/blockchain/blockchain.js +++ b/lib/cmds/blockchain/blockchain.js @@ -6,6 +6,7 @@ const fs = require('../../core/fs.js'); const constants = require('../../constants.json'); const GethCommands = require('./geth_commands.js'); +const DevFunds = require('./dev_funds.js'); /*eslint complexity: ["error", 36]*/ var Blockchain = function(options) { @@ -13,7 +14,7 @@ var Blockchain = function(options) { this.env = options.env || 'development'; this.client = options.client; this.isDev = options.isDev; - this.onReadyCallback = options.onReadyCallback; + 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")); @@ -41,7 +42,7 @@ var Blockchain = function(options) { wsHost: this.blockchainConfig.wsHost || 'localhost', wsPort: this.blockchainConfig.wsPort || 8546, wsOrigins: this.blockchainConfig.wsOrigins || false, - wsApi: (this.blockchainConfig.wsApi || ['eth', 'web3', 'net', 'shh', 'debug']), + wsApi: (this.blockchainConfig.wsApi || ['eth', 'web3', 'net', 'shh', 'debug', 'personal']), vmdebug: this.blockchainConfig.vmdebug || false, targetGasLimit: this.blockchainConfig.targetGasLimit || false, syncMode: this.blockchainConfig.syncMode, @@ -162,6 +163,12 @@ Blockchain.prototype.run = function() { self.child.stderr.on('data', (data) => { data = data.toString(); if (self.onReadyCallback && !self.readyCalled && data.indexOf('WebSocket endpoint opened') > -1) { + if (self.isDev) { + return self.createFundAndUnlockAccounts(() => { + self.readyCalled = true; + self.onReadyCallback(); + }); + } self.readyCalled = true; self.onReadyCallback(); } @@ -175,6 +182,16 @@ Blockchain.prototype.run = function() { }); }; +Blockchain.prototype.createFundAndUnlockAccounts = function(cb) { + console.dir('createFundAndUnlockAccounts'); + let devFunds = new DevFunds(this.config); + devFunds.createFundAndUnlockAccounts(() => { + console.dir("=====> done!"); + console.dir(arguments); + cb(); + }); +} + Blockchain.prototype.kill = function() { if (this.child) { this.child.kill(); diff --git a/lib/cmds/blockchain/dev_funds.js b/lib/cmds/blockchain/dev_funds.js new file mode 100644 index 00000000..b6abe4f3 --- /dev/null +++ b/lib/cmds/blockchain/dev_funds.js @@ -0,0 +1,75 @@ +const async = require('async'); +var Web3 = require('web3'); +var utils = require('../../utils/utils.js'); + +class DevFunds { + constructor(blockchainConfig) { + this.web3 = null; + this.blockchainConfig = blockchainConfig; + this.accounts = []; + this.numAccounts = this.blockchainConfig.account.numAccounts || 0; + //this.balance = this.blockchainConfig.account.balance || Web3.utils.toWei("1", "ether"); + this.balance = Web3.utils.toWei("1", "ether"); + this.password = "dev_password" + } + + connectToNode(cb) { + const self = this; + this.web3 = new Web3(); + this.web3.setProvider(new Web3.providers.WebsocketProvider(utils.buildUrl('ws', this.blockchainConfig.wsHost, this.blockchainConfig.wsPort), {headers: {Origin: "http://localhost:8000"}})); + this.web3.eth.getAccounts().then((accounts) => { + self.web3.eth.defaultAccount = accounts[0]; + cb(); + }); + } + + createAccounts(numAccounts, password, cb) { + console.dir("creating " + numAccounts + " with password " + password); + const self = this; + async.timesLimit(numAccounts, 1, (_, next) => { + console.dir("--- creating new account"); + self.web3.eth.personal.newAccount(password, next); + }, (err, accounts) => { + console.dir("-- accounts created are "); + console.dir(accounts); + this.accounts = accounts; + cb(err); + }); + } + + unlockAccounts(password, cb) { + const self = this; + async.each(this.accounts, (account, next) => { + self.web3.eth.personal.unlockAccount(account, password).then(() => { next() }); + }, cb); + } + + fundAccounts(balance, cb) { + const self = this; + async.each(this.accounts, (account, next) => { + self.web3.eth.sendTransaction({to: account, value: balance}).then(() => { + next(); + }); + }, cb); + } + + createFundAndUnlockAccounts(cb) { + const self = this; + async.waterfall([ + function connect(next) { + self.connectToNode(next); + }, + function create(next) { + self.createAccounts(self.numAccounts, self.password, next) + }, + function unlock(next) { + self.unlockAccounts(self.password, next); + }, + function fund(next) { + self.fundAccounts(self.balance, next); + }, + ], cb); + } +} + +module.exports = DevFunds; diff --git a/lib/cmds/blockchain/geth_commands.js b/lib/cmds/blockchain/geth_commands.js index 5317286d..919b37f1 100644 --- a/lib/cmds/blockchain/geth_commands.js +++ b/lib/cmds/blockchain/geth_commands.js @@ -123,7 +123,7 @@ class GethCommands { let self = this; let config = this.config; let rpc_api = (this.config.rpcApi || ['eth', 'web3', 'net', 'debug']); - let ws_api = (this.config.wsApi || ['eth', 'web3', 'net', 'debug']); + let ws_api = (this.config.wsApi || ['eth', 'web3', 'net', 'debug', 'personal']); let args = []; diff --git a/lib/index.js b/lib/index.js index 70f4b6ca..a2698080 100644 --- a/lib/index.js +++ b/lib/index.js @@ -45,7 +45,7 @@ class Embark { blockchain(env, client) { this.context = [constants.contexts.blockchain]; - return require('./cmds/blockchain/blockchain.js')(this.config.blockchainConfig, client, env, this.isDev(env)).run(); + return require('./cmds/blockchain/blockchain.js')(this.config.blockchainConfig, client, env, this.isDev(env), () => {}).run(); } simulator(options) { diff --git a/test_apps/test_app/config/blockchain.json b/test_apps/test_app/config/blockchain.json index cf136e8d..e92186eb 100644 --- a/test_apps/test_app/config/blockchain.json +++ b/test_apps/test_app/config/blockchain.json @@ -13,6 +13,8 @@ "rpcPort": 8545, "rpcCorsDomain": "auto", "account": { + "numAccounts": 3, + "balance": "5 ether", "password": "config/development/password" }, "targetGasLimit": 8000000,