first stab at refactor blockchain launcher
This commit is contained in:
parent
236667d5a4
commit
4406dddf1e
|
@ -0,0 +1,416 @@
|
|||
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;
|
||||
|
||||
this.registerProcessLaunch();
|
||||
|
||||
if (!this.web3) {
|
||||
this.initWeb3();
|
||||
} else {
|
||||
this.isWeb3Ready = true;
|
||||
}
|
||||
//this.registerServiceCheck();
|
||||
this.registerRequests();
|
||||
this.registerWeb3Object();
|
||||
}
|
||||
|
||||
registerProcessLaunch() {
|
||||
const self = this;
|
||||
this.events.request('processes:register', 'blockchain', (cb) => {
|
||||
self.startBlockchainNode(cb);
|
||||
});
|
||||
}
|
||||
|
||||
initWeb3() {
|
||||
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';
|
||||
|
||||
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
|
||||
};
|
||||
this.provider = new Provider(providerOptions);
|
||||
|
||||
self.assertNodeConnection(true, (err) => {
|
||||
if (!err) {
|
||||
self.provider.startWeb3Provider(() => {
|
||||
self.provider.fundAccounts(() => {
|
||||
self.registerWeb3Object();
|
||||
|
||||
self.events.emit("check:backOnline:Ethereum");
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
self.events.request("processes:launch", "blockchain", () => {
|
||||
console.dir("======> blockchain launched!");
|
||||
self.provider.startWeb3Provider(() => {
|
||||
self.provider.fundAccounts(() => {
|
||||
self.registerWeb3Object();
|
||||
|
||||
self.events.emit("check:backOnline:Ethereum");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
initWeb3_old() {
|
||||
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';
|
||||
|
||||
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
|
||||
};
|
||||
this.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);
|
||||
// if the ethereum node goes offline, we need a check to ensure
|
||||
// the provider is also stopped
|
||||
self.events.on('check:wentOffline:Ethereum', () => {
|
||||
self.logger.trace('Ethereum went offline: stopping web3 provider...');
|
||||
self.provider.stop();
|
||||
|
||||
// once the node goes back online, we can restart the provider
|
||||
self.events.once('check:backOnline:Ethereum', () => {
|
||||
self.logger.trace('Ethereum back online: starting web3 provider...');
|
||||
self.provider.startWeb3Provider(() => {
|
||||
self.logger.trace('web3 provider restarted after ethereum node came back online');
|
||||
});
|
||||
});
|
||||
});
|
||||
return next();
|
||||
}
|
||||
self.web3StartedInProcess = true;
|
||||
//self.startBlockchainNode(() => {
|
||||
self.events.request("processes:launch", "blockchain", () => {
|
||||
// Need to re-initialize web3 to connect to the new blockchain node
|
||||
self.provider.stop();
|
||||
//self.initWeb3(cb);
|
||||
});
|
||||
});
|
||||
},
|
||||
function startProvider(next) {
|
||||
self.provider.startWeb3Provider(next);
|
||||
},
|
||||
function fundAccountsIfNeeded(next) {
|
||||
self.provider.fundAccounts(next);
|
||||
}
|
||||
], (err) => {
|
||||
self.registerWeb3Object();
|
||||
cb(err);
|
||||
});
|
||||
}
|
||||
|
||||
onReady(callback) {
|
||||
if (this.isWeb3Ready) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
this.events.once(WEB3_READY, () => {
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
startBlockchainNode(callback) {
|
||||
console.dir("==> startBlockchainNode");
|
||||
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, () => {
|
||||
console.dir("==> blockchainReady");
|
||||
callback();
|
||||
});
|
||||
self.events.once(constants.blockchain.blockchainExit, () => {
|
||||
console.dir("==> blockchainExit");
|
||||
self.provider.stop();
|
||||
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);
|
||||
});
|
||||
|
||||
this.events.setCommandHandler("blockchain:contract:create", function(params, cb) {
|
||||
cb(self.ContractObject(params));
|
||||
});
|
||||
}
|
||||
|
||||
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, params.address);
|
||||
}
|
||||
|
||||
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) {
|
||||
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({
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
@ -36,7 +36,7 @@ class Engine {
|
|||
this.isDev = this.config && this.config.blockchainConfig && (this.config.blockchainConfig.isDev || this.config.blockchainConfig.default);
|
||||
|
||||
if (this.interceptLogs || this.interceptLogs === undefined) {
|
||||
utils.interceptLogs(console, this.logger);
|
||||
this.doInterceptLogs();
|
||||
}
|
||||
|
||||
this.ipc = new IPC({logger: this.logger, ipcRole: this.ipcRole});
|
||||
|
@ -48,7 +48,7 @@ class Engine {
|
|||
this.ipc.serve();
|
||||
return callback();
|
||||
}
|
||||
callback();
|
||||
callback();
|
||||
}
|
||||
|
||||
registerModule(moduleName, options) {
|
||||
|
@ -91,18 +91,14 @@ class Engine {
|
|||
}
|
||||
|
||||
processManagerService(_options) {
|
||||
const ProcessManager = require('./processes/processManager.js');
|
||||
this.processManager = new ProcessManager({
|
||||
const ProcessManager = require('../processes/process_manager.js');
|
||||
const processManager = new ProcessManager({
|
||||
events: this.events,
|
||||
logger: this.logger,
|
||||
plugins: this.plugins
|
||||
});
|
||||
}
|
||||
|
||||
graphService(_options) {
|
||||
this.registerModule('graph');
|
||||
}
|
||||
|
||||
pipelineService(_options) {
|
||||
const self = this;
|
||||
this.registerModule('pipeline', {
|
||||
|
@ -147,20 +143,30 @@ class Engine {
|
|||
}
|
||||
|
||||
codeRunnerService(_options) {
|
||||
const CodeRunner = require('./modules/coderunner/codeRunner.js');
|
||||
const CodeRunner = require('../coderunner/codeRunner.js');
|
||||
this.codeRunner = new CodeRunner({
|
||||
config: this.config,
|
||||
plugins: this.plugins,
|
||||
events: this.events,
|
||||
logger: this.logger,
|
||||
ipc: this.ipc
|
||||
logger: this.logger
|
||||
});
|
||||
}
|
||||
|
||||
codeGeneratorService(_options) {
|
||||
let self = this;
|
||||
|
||||
this.registerModule('code_generator', {plugins: self.plugins, env: self.env});
|
||||
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 (modifiedAssets) {
|
||||
self.events.request("code-generator:embarkjs:build", () => {
|
||||
|
@ -204,7 +210,6 @@ class Engine {
|
|||
self.fileTimeout = setTimeout(() => {
|
||||
// TODO: still need to redeploy contracts because the original contracts
|
||||
// config is being corrupted
|
||||
self.config.reloadConfig();
|
||||
if (fileType === 'asset') {
|
||||
// Throttle file changes so we re-write only once for all files
|
||||
self.events.emit('asset-changed', path);
|
||||
|
@ -212,6 +217,8 @@ class Engine {
|
|||
// 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);
|
||||
|
@ -243,15 +250,24 @@ class Engine {
|
|||
|
||||
this.registerModule('blockchain_connector', {
|
||||
isDev: this.isDev,
|
||||
locale: this.locale,
|
||||
web3: options.web3,
|
||||
wait: options.wait
|
||||
});
|
||||
|
||||
this.registerModule('whisper');
|
||||
this.registerModule('whisper', {
|
||||
// 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) {
|
||||
this.registerModule('library_manager');
|
||||
const LibraryManager = require('../versions/library_manager.js');
|
||||
this.libraryManager = new LibraryManager({
|
||||
plugins: this.plugins,
|
||||
config: this.config
|
||||
});
|
||||
}
|
||||
|
||||
testRunnerService(options) {
|
||||
|
|
|
@ -11,7 +11,6 @@ function log(eventType, eventName) {
|
|||
if (['end', 'prefinish', 'error', 'new', 'demo', 'block', 'version'].indexOf(eventName) >= 0) {
|
||||
return;
|
||||
}
|
||||
// prevents infinite loop when printing events
|
||||
if (eventType.indexOf("log") >= 0) {
|
||||
return;
|
||||
}
|
||||
|
|
416
lib/index.js
416
lib/index.js
|
@ -1,3 +1,17 @@
|
|||
let async = require('async');
|
||||
const constants = require('./constants');
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
let version = require('../package.json').version;
|
||||
|
||||
class Embark {
|
||||
|
@ -20,6 +34,408 @@ class Embark {
|
|||
this.plugins = this.config.plugins;
|
||||
}
|
||||
|
||||
blockchain(env, client) {
|
||||
this.context = [constants.contexts.blockchain];
|
||||
return require('./cmds/blockchain/blockchain.js')(this.config.blockchainConfig, client, 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
|
||||
});
|
||||
simulator.run(options);
|
||||
}
|
||||
|
||||
generateTemplate(templateName, destinationFolder, name, url) {
|
||||
this.context = [constants.contexts.templateGeneration];
|
||||
let TemplateGenerator = require('./cmds/template_generator.js');
|
||||
let templateGenerator = new TemplateGenerator(templateName);
|
||||
|
||||
if (url) {
|
||||
return templateGenerator.downloadAndGenerate(url, destinationFolder, name);
|
||||
}
|
||||
templateGenerator.generate(destinationFolder, name);
|
||||
}
|
||||
|
||||
run(options) {
|
||||
let self = this;
|
||||
self.context = options.context || [constants.contexts.run, constants.contexts.build];
|
||||
let Dashboard = require('./dashboard/dashboard.js');
|
||||
|
||||
let webServerConfig = {
|
||||
enabled: options.runWebserver
|
||||
};
|
||||
|
||||
if (options.serverHost) {
|
||||
webServerConfig.host = options.serverHost;
|
||||
}
|
||||
if (options.serverPort) {
|
||||
webServerConfig.port = options.serverPort;
|
||||
}
|
||||
|
||||
const Engine = require('./core/engine.js');
|
||||
const engine = new Engine({
|
||||
env: options.env,
|
||||
client: options.client,
|
||||
locale: options.locale,
|
||||
version: this.version,
|
||||
embarkConfig: options.embarkConfig || 'embark.json',
|
||||
logFile: options.logFile,
|
||||
logLevel: options.logLevel,
|
||||
context: self.context,
|
||||
useDashboard: options.useDashboard,
|
||||
webServerConfig: webServerConfig
|
||||
});
|
||||
engine.init();
|
||||
|
||||
if (!options.useDashboard) {
|
||||
engine.logger.info('========================'.bold.green);
|
||||
engine.logger.info((__('Welcome to Embark') + ' ' + this.version).yellow.bold);
|
||||
engine.logger.info('========================'.bold.green);
|
||||
}
|
||||
|
||||
async.parallel([
|
||||
function startDashboard(callback) {
|
||||
if (!options.useDashboard) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
let dashboard = new Dashboard({
|
||||
events: engine.events,
|
||||
logger: engine.logger,
|
||||
plugins: engine.plugins,
|
||||
version: self.version,
|
||||
env: engine.env
|
||||
});
|
||||
dashboard.start(function () {
|
||||
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.startService("processManager");
|
||||
engine.startService("serviceMonitor");
|
||||
engine.startService("libraryManager");
|
||||
engine.startService("codeRunner");
|
||||
engine.startService("web3");
|
||||
engine.startService("pipeline");
|
||||
engine.startService("deployment");
|
||||
engine.startService("storage");
|
||||
engine.startService("codeGenerator");
|
||||
engine.startService("namingSystem");
|
||||
|
||||
engine.events.on('check:backOnline:Ethereum', function () {
|
||||
engine.logger.info(__('Ethereum node detected') + '..');
|
||||
engine.config.reloadConfig();
|
||||
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.status.im/docs/".green.underline + ".".cyan);
|
||||
engine.logger.info(__("Ready").underline);
|
||||
engine.events.emit("status", __("Ready").green);
|
||||
});
|
||||
|
||||
if (options.runWebserver) {
|
||||
engine.startService("webServer", {
|
||||
host: options.serverHost,
|
||||
port: options.serverPort
|
||||
});
|
||||
}
|
||||
engine.startService("fileWatcher");
|
||||
callback();
|
||||
}
|
||||
], function (err, _result) {
|
||||
if (err) {
|
||||
engine.logger.error(err.message);
|
||||
engine.logger.info(err.stack);
|
||||
} else {
|
||||
engine.events.emit('firstDeploymentDone');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
build(options) {
|
||||
this.context = options.context || [constants.contexts.build];
|
||||
|
||||
const Engine = require('./core/engine.js');
|
||||
const engine = new Engine({
|
||||
env: options.env,
|
||||
client: options.client,
|
||||
locale: options.locale,
|
||||
version: this.version,
|
||||
embarkConfig: 'embark.json',
|
||||
interceptLogs: false,
|
||||
logFile: options.logFile,
|
||||
logLevel: options.logLevel,
|
||||
events: options.events,
|
||||
logger: options.logger,
|
||||
config: options.config,
|
||||
plugins: options.plugins,
|
||||
context: this.context
|
||||
});
|
||||
engine.init();
|
||||
|
||||
async.waterfall([
|
||||
function startServices(callback) {
|
||||
let pluginList = engine.plugins.listPlugins();
|
||||
if (pluginList.length > 0) {
|
||||
engine.logger.info(__("loaded plugins") + ": " + pluginList.join(", "));
|
||||
}
|
||||
|
||||
engine.startService("processManager");
|
||||
engine.startService("libraryManager");
|
||||
engine.startService("codeRunner");
|
||||
engine.startService("web3");
|
||||
if (!options.onlyCompile) {
|
||||
engine.startService("pipeline");
|
||||
}
|
||||
engine.startService("deployment", {onlyCompile: options.onlyCompile});
|
||||
engine.startService("storage");
|
||||
engine.startService("codeGenerator");
|
||||
|
||||
callback();
|
||||
},
|
||||
function deploy(callback) {
|
||||
engine.events.request('deploy:contracts', function (err) {
|
||||
callback(err);
|
||||
});
|
||||
},
|
||||
function waitForWriteFinish(callback) {
|
||||
if (options.onlyCompile) {
|
||||
engine.logger.info("Finished compiling".underline);
|
||||
return callback(null, true);
|
||||
}
|
||||
engine.logger.info("Finished deploying".underline);
|
||||
engine.events.on('outputDone', (err) => {
|
||||
engine.logger.info(__("finished building").underline);
|
||||
callback(err, true);
|
||||
});
|
||||
}
|
||||
], function (err, canExit) {
|
||||
if (err) {
|
||||
engine.logger.error(err.message);
|
||||
engine.logger.debug(err.stack);
|
||||
}
|
||||
|
||||
// TODO: this should be moved out and determined somewhere else
|
||||
if (canExit || !engine.config.contractsConfig.afterDeploy || !engine.config.contractsConfig.afterDeploy.length) {
|
||||
process.exit();
|
||||
}
|
||||
engine.logger.info(__('Waiting for after deploy to finish...'));
|
||||
engine.logger.info(__('You can exit with CTRL+C when after deploy completes'));
|
||||
});
|
||||
}
|
||||
|
||||
console(options) {
|
||||
this.context = options.context || [constants.contexts.run, constants.contexts.console];
|
||||
const REPL = require('./dashboard/repl.js');
|
||||
const Engine = require('./core/engine.js');
|
||||
const engine = new Engine({
|
||||
env: options.env,
|
||||
client: options.client,
|
||||
locale: options.locale,
|
||||
version: this.version,
|
||||
embarkConfig: options.embarkConfig || 'embark.json',
|
||||
logFile: options.logFile,
|
||||
logLevel: options.logLevel,
|
||||
context: this.context
|
||||
});
|
||||
engine.init();
|
||||
async.waterfall([
|
||||
function startServices(callback) {
|
||||
let pluginList = engine.plugins.listPlugins();
|
||||
if (pluginList.length > 0) {
|
||||
engine.logger.info(__("loaded plugins") + ": " + pluginList.join(", "));
|
||||
}
|
||||
|
||||
engine.startService("libraryManager");
|
||||
engine.startService("codeRunner");
|
||||
engine.startService("web3");
|
||||
engine.startService("pipeline");
|
||||
engine.startService("deployment", {onlyCompile: false});
|
||||
engine.startService("storage");
|
||||
engine.startService("codeGenerator");
|
||||
engine.startService("fileWatcher");
|
||||
|
||||
callback();
|
||||
},
|
||||
function deploy(callback) {
|
||||
engine.events.request('deploy:contracts', function (err) {
|
||||
callback(err);
|
||||
});
|
||||
},
|
||||
function waitForWriteFinish(callback) {
|
||||
engine.logger.info("Finished deploying".underline);
|
||||
engine.events.once('outputDone', (err) => {
|
||||
engine.logger.info(__("finished building").underline);
|
||||
callback(err);
|
||||
});
|
||||
},
|
||||
function startREPL(callback) {
|
||||
let repl = new REPL({
|
||||
env: engine.env,
|
||||
plugins: engine.plugins,
|
||||
version: engine.version,
|
||||
events: engine.events
|
||||
});
|
||||
repl.start(callback);
|
||||
}
|
||||
], function (err, _result) {
|
||||
if (err) {
|
||||
engine.logger.error(err.message);
|
||||
engine.logger.info(err.stack);
|
||||
} else {
|
||||
engine.events.emit('firstDeploymentDone');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
graph(options) {
|
||||
this.context = options.context || [constants.contexts.graph];
|
||||
options.onlyCompile = true;
|
||||
|
||||
const Engine = require('./core/engine.js');
|
||||
const engine = new Engine({
|
||||
env: options.env,
|
||||
version: this.version,
|
||||
embarkConfig: options.embarkConfig || 'embark.json',
|
||||
logFile: options.logFile,
|
||||
context: this.context
|
||||
});
|
||||
engine.init();
|
||||
|
||||
async.waterfall([
|
||||
function (callback) {
|
||||
let pluginList = engine.plugins.listPlugins();
|
||||
if (pluginList.length > 0) {
|
||||
engine.logger.info(__("loaded plugins") + ": " + pluginList.join(", "));
|
||||
}
|
||||
|
||||
engine.startService("processManager");
|
||||
engine.startService("serviceMonitor");
|
||||
engine.startService("libraryManager");
|
||||
engine.startService("pipeline");
|
||||
engine.startService("deployment", {onlyCompile: true});
|
||||
engine.startService("web3");
|
||||
engine.startService("codeGenerator");
|
||||
|
||||
engine.events.request('deploy:contracts', callback);
|
||||
}
|
||||
], (err) => {
|
||||
if (err) {
|
||||
engine.logger.error(err.message);
|
||||
engine.logger.info(err.stack);
|
||||
} else {
|
||||
|
||||
const GraphGenerator = require('./cmds/graph.js');
|
||||
let graphGen = new GraphGenerator(engine);
|
||||
graphGen.generate(options);
|
||||
|
||||
engine.logger.info(__("Done. %s generated", "./diagram.svg").underline);
|
||||
}
|
||||
process.exit();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.context = [constants.contexts.reset];
|
||||
let resetCmd = require('./cmds/reset.js');
|
||||
resetCmd();
|
||||
}
|
||||
|
||||
upload(options) {
|
||||
this.context = options.context || [constants.contexts.upload, constants.contexts.build];
|
||||
|
||||
const Engine = require('./core/engine.js');
|
||||
const engine = new Engine({
|
||||
env: options.env,
|
||||
client: options.client,
|
||||
locale: options.locale,
|
||||
version: this.version,
|
||||
embarkConfig: 'embark.json',
|
||||
interceptLogs: false,
|
||||
logFile: options.logFile,
|
||||
logLevel: options.logLevel,
|
||||
events: options.events,
|
||||
logger: options.logger,
|
||||
config: options.config,
|
||||
plugins: options.plugins,
|
||||
context: this.context
|
||||
});
|
||||
engine.init();
|
||||
|
||||
let platform = engine.config.storageConfig.upload.provider;
|
||||
|
||||
async.waterfall([
|
||||
|
||||
function startServices(callback) {
|
||||
|
||||
engine.startService("processManager");
|
||||
engine.startService("serviceMonitor");
|
||||
engine.startService("libraryManager");
|
||||
engine.startService("codeRunner");
|
||||
engine.startService("web3");
|
||||
engine.startService("pipeline");
|
||||
engine.startService("deployment");
|
||||
engine.startService("storage");
|
||||
engine.startService("codeGenerator");
|
||||
callback();
|
||||
},
|
||||
function listLoadedPlugin(callback) {
|
||||
let pluginList = engine.plugins.listPlugins();
|
||||
if (pluginList.length > 0) {
|
||||
engine.logger.info(__("loaded plugins") + ": " + pluginList.join(", "));
|
||||
}
|
||||
callback();
|
||||
},
|
||||
function deploy(callback) {
|
||||
engine.events.on('outputDone', function () {
|
||||
engine.events.request("storage:upload", callback);
|
||||
});
|
||||
engine.events.on('check:backOnline:Ethereum', function () {
|
||||
engine.logger.info(__('Ethereum node detected') + '..');
|
||||
engine.config.reloadConfig();
|
||||
engine.events.request('deploy:contracts', function (err) {
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
engine.logger.info(__('Deployment Done'));
|
||||
});
|
||||
});
|
||||
}
|
||||
], function (err, _result) {
|
||||
if (err) {
|
||||
engine.logger.error(err.message);
|
||||
engine.logger.debug(err.stack);
|
||||
} else {
|
||||
engine.logger.info((__("finished building DApp and deploying to") + " " + platform).underline);
|
||||
}
|
||||
|
||||
// needed due to child processes
|
||||
process.exit();
|
||||
});
|
||||
}
|
||||
|
||||
runTests(options) {
|
||||
this.context = [constants.contexts.test];
|
||||
let RunTests = require('./tests/run_tests.js');
|
||||
RunTests.run(options);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Embark;
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
let async = require('async');
|
||||
|
||||
const ContractDeployer = require('./contract_deployer.js');
|
||||
const cloneDeep = require('clone-deep');
|
||||
const utils = require('../utils/utils.js');
|
||||
//require("../utils/debug_util.js")(__filename, async);
|
||||
|
||||
class DeployManager {
|
||||
constructor(embark, options) {
|
||||
constructor(options) {
|
||||
const self = this;
|
||||
this.config = embark.config;
|
||||
this.logger = embark.logger;
|
||||
this.config = options.config;
|
||||
this.logger = options.logger;
|
||||
this.blockchainConfig = this.config.blockchainConfig;
|
||||
|
||||
this.events = embark.events;
|
||||
this.events = options.events;
|
||||
this.plugins = options.plugins;
|
||||
this.blockchain = options.blockchain;
|
||||
this.gasLimit = false;
|
||||
|
@ -18,68 +18,21 @@ class DeployManager {
|
|||
this.deployOnlyOnConfig = false;
|
||||
this.onlyCompile = options.onlyCompile !== undefined ? options.onlyCompile : false;
|
||||
|
||||
this.contractDeployer = new ContractDeployer({
|
||||
logger: this.logger,
|
||||
events: this.events,
|
||||
plugins: this.plugins
|
||||
});
|
||||
|
||||
this.events.setCommandHandler('deploy:setGasLimit', (gasLimit) => {
|
||||
self.gasLimit = gasLimit;
|
||||
});
|
||||
|
||||
this.events.setCommandHandler('deploy:contracts', (cb) => {
|
||||
self.deployContracts(cb);
|
||||
});
|
||||
|
||||
this.events.setCommandHandler('deploy:contracts:test', (cb) => {
|
||||
self.fatalErrors = true;
|
||||
self.deployOnlyOnConfig = true;
|
||||
self.deployContracts(cb);
|
||||
});
|
||||
}
|
||||
|
||||
deployAll(done) {
|
||||
let self = this;
|
||||
|
||||
self.events.request('contracts:dependencies', (err, contractDependencies) => {
|
||||
self.events.request('contracts:list', (err, contracts) => {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
self.events.request('contracts:list', (err, contracts) => {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
self.logger.info(__("deploying contracts"));
|
||||
async.waterfall([
|
||||
function (next) {
|
||||
self.plugins.emitAndRunActionsForEvent("deploy:beforeAll", next);
|
||||
},
|
||||
function () {
|
||||
const contractDeploys = {};
|
||||
const errors = [];
|
||||
contracts.forEach(contract => {
|
||||
function deploy(result, callback) {
|
||||
if (typeof result === 'function') {
|
||||
callback = result;
|
||||
}
|
||||
contract._gasLimit = self.gasLimit;
|
||||
self.events.request('deploy:contract', contract, (err) => {
|
||||
if (err) {
|
||||
contract.error = err.message || err;
|
||||
self.logger.error(err.message || err);
|
||||
errors.push(err);
|
||||
}
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
const className = contract.className;
|
||||
if (!contractDependencies[className] || contractDependencies[className].length === 0) {
|
||||
contractDeploys[className] = deploy;
|
||||
return;
|
||||
}
|
||||
contractDeploys[className] = cloneDeep(contractDependencies[className]);
|
||||
contractDeploys[className].push(deploy);
|
||||
});
|
||||
self.logger.info(__("deploying contracts"));
|
||||
self.events.emit("deploy:beforeAll");
|
||||
|
||||
try {
|
||||
async.auto(contractDeploys, 1, function(_err, _results) {
|
||||
|
@ -101,8 +54,10 @@ class DeployManager {
|
|||
done(__('Error deploying'));
|
||||
}
|
||||
}
|
||||
]);
|
||||
});
|
||||
self.logger.info(__("finished deploying contracts"));
|
||||
done(err);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -116,13 +71,6 @@ class DeployManager {
|
|||
}
|
||||
|
||||
async.waterfall([
|
||||
function requestBlockchainConnector(callback) {
|
||||
self.events.request("blockchain:object", (blockchain) => {
|
||||
self.blockchain = blockchain;
|
||||
callback();
|
||||
});
|
||||
},
|
||||
|
||||
function buildContracts(callback) {
|
||||
self.events.request("contracts:build", self.deployOnlyOnConfig, (err) => {
|
||||
callback(err);
|
||||
|
@ -130,8 +78,8 @@ class DeployManager {
|
|||
},
|
||||
|
||||
// TODO: shouldn't be necessary
|
||||
function checkCompileOnly(callback) {
|
||||
if (self.onlyCompile) {
|
||||
function checkCompileOnly(callback){
|
||||
if(self.onlyCompile){
|
||||
self.events.emit('contractsDeployed');
|
||||
return done();
|
||||
}
|
||||
|
@ -140,9 +88,12 @@ class DeployManager {
|
|||
|
||||
// TODO: could be implemented as an event (beforeDeployAll)
|
||||
function checkIsConnectedToBlockchain(callback) {
|
||||
self.blockchain.onReady((err) => {
|
||||
callback(err);
|
||||
});
|
||||
callback();
|
||||
//self.blockchain.onReady(() => {
|
||||
// self.blockchain.assertNodeConnection((err) => {
|
||||
// callback(err);
|
||||
// });
|
||||
//});
|
||||
},
|
||||
|
||||
// TODO: this can be done on the fly or as part of the initialization
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
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;
|
Loading…
Reference in New Issue