Merge pull request #469 from embark-framework/refactor_contracts_part2

Refactor contracts part2
This commit is contained in:
Iuri Matias 2018-05-31 10:37:43 -04:00 committed by GitHub
commit 75c91992e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 271 additions and 320 deletions

View File

@ -28,8 +28,6 @@ class CodeGenerator {
this.communicationConfig = options.communicationConfig || {};
this.namesystemConfig = options.namesystemConfig || {};
this.env = options.env || 'development';
// TODO: this should also be removed and use events instead
this.contractsManager = options.contractsManager;
this.plugins = options.plugins;
this.events = options.events;
}
@ -43,71 +41,47 @@ class CodeGenerator {
cb(providerCode);
});
// deprecated events; to remove in embark 2.7.0
this.events.setCommandHandlerOnce('abi-vanila', function(cb) {
let vanillaABI = self.generateABI({useEmbarkJS: false});
let contractsJSON = self.generateContractsJSON();
cb(vanillaABI, contractsJSON);
});
this.events.setCommandHandlerOnce('abi', function(cb) {
let embarkJSABI = self.generateABI({useEmbarkJS: true});
let contractsJSON = self.generateContractsJSON();
cb(embarkJSABI, contractsJSON);
});
this.events.setCommandHandlerOnce('abi-contracts-vanila', function(cb) {
let vanillaContractsABI = self.generateContracts(false, true, false);
let contractsJSON = self.generateContractsJSON();
cb(vanillaContractsABI, contractsJSON);
});
this.events.setCommandHandlerOnce('abi-vanila-deployment', function(cb) {
let vanillaABI = self.generateABI({useEmbarkJS: false, deployment: true});
let contractsJSON = self.generateContractsJSON();
cb(vanillaABI, contractsJSON);
});
// new events
this.events.setCommandHandlerOnce('code-vanila', function(cb) {
let vanillaABI = self.generateABI({useEmbarkJS: false});
let contractsJSON = self.generateContractsJSON();
self.events.request("contracts:list", (contractsList) => {
let vanillaABI = self.generateABI(contractsList, {useEmbarkJS: false});
let contractsJSON = self.generateContractsJSON(contractsList);
cb(vanillaABI, contractsJSON);
});
});
this.events.setCommandHandlerOnce('code', function(cb) {
let embarkJSABI = self.generateABI({useEmbarkJS: true});
let contractsJSON = self.generateContractsJSON();
self.events.request("contracts:list", (contractsList) => {
let embarkJSABI = self.generateABI(contractsList, {useEmbarkJS: true});
let contractsJSON = self.generateContractsJSON(contractsList);
cb(embarkJSABI, contractsJSON);
});
});
this.events.setCommandHandlerOnce('code-contracts-vanila', function(cb) {
let vanillaContractsABI = self.generateContracts(false, true, false);
let contractsJSON = self.generateContractsJSON();
self.events.request("contracts:list", (contractsList) => {
let vanillaContractsABI = self.generateContracts(contractsList, false, true, false);
let contractsJSON = self.generateContractsJSON(contractsList);
cb(vanillaContractsABI, contractsJSON);
});
});
this.events.setCommandHandlerOnce('code-vanila-deployment', function(cb) {
let vanillaABI = self.generateABI({useEmbarkJS: false, deployment: true});
let contractsJSON = self.generateContractsJSON();
self.events.request("contracts:list", (contractsList) => {
let vanillaABI = self.generateABI(contractsList, {useEmbarkJS: false, deployment: true});
let contractsJSON = self.generateContractsJSON(contractsList);
cb(vanillaABI, contractsJSON);
});
});
this.events.setCommandHandlerOnce('code-generator:web3js', function(cb) {
self.buildWeb3JS(cb);
});
this.events.setCommandHandler('code-generator:contract', (contractName, cb) => {
let contract = self.contractsManager.contracts[contractName];
self.buildContractJS(contractName, self.generateContractJSON(contractName, contract), cb);
self.events.setCommandHandler('code-generator:contract', (contractName, cb) => {
self.events.request('contracts:contract', contractName, (contract) => {
self.buildContractJS(contractName, self.generateContractJSON(contract, contract), cb);
});
});
self.events.setCommandHandler('code-generator:contract:vanilla', (contract, gasLimit, cb) => {
@ -115,7 +89,7 @@ class CodeGenerator {
});
this.events.setCommandHandler('embark-building-placeholder', (cb) => {
this.buildPlaceholderPage(cb);
self.buildPlaceholderPage(cb);
});
}
@ -173,16 +147,15 @@ class CodeGenerator {
return result;
}
generateContracts(useEmbarkJS, isDeployment, useLoader) {
generateContracts(contractsList, useEmbarkJS, isDeployment, useLoader) {
let self = this;
let result = "\n";
let contractsPlugins;
if (useLoader === false) {
for (let className in this.contractsManager.contracts) {
let contract = this.contractsManager.contracts[className];
for (let contract of contractsList) {
let abi = JSON.stringify(contract.abiDefinition);
result += Templates.vanilla_contract({className: className, abi: abi, contract: contract, gasLimit: 6000000});
result += Templates.vanilla_contract({className: contract.className, abi: abi, contract: contract, gasLimit: 6000000});
}
return result;
}
@ -197,12 +170,10 @@ class CodeGenerator {
if (this.plugins && contractsPlugins.length > 0) {
contractsPlugins.forEach(function (plugin) {
result += plugin.generateContracts({contracts: self.contractsManager.contracts});
result += plugin.generateContracts({contracts: contractsList});
});
} else {
for (let className in this.contractsManager.contracts) {
let contract = this.contractsManager.contracts[className];
for (let contract of contractsList) {
let abi = JSON.stringify(contract.abiDefinition);
let gasEstimates = JSON.stringify(contract.gasEstimates);
@ -210,9 +181,9 @@ class CodeGenerator {
if (useEmbarkJS) {
let contractAddress = contract.deployedAddress ? ("'" + contract.deployedAddress + "'") : "undefined";
block += Templates.embarkjs_contract({className: className, abi: abi, contract: contract, contractAddress: contractAddress, gasEstimates: gasEstimates});
block += Templates.embarkjs_contract({className: contract.className, abi: abi, contract: contract, contractAddress: contractAddress, gasEstimates: gasEstimates});
} else {
block += Templates.vanilla_contract({className: className, abi: abi, contract: contract, gasLimit: (isDeployment ? 6000000 : false)});
block += Templates.vanilla_contract({className: contract.className, abi: abi, contract: contract, gasLimit: (isDeployment ? 6000000 : false)});
}
result += Templates.exec_when_ready({block: block});
@ -276,11 +247,11 @@ class CodeGenerator {
return result;
}
generateABI(options) {
generateABI(contractsList, options) {
let result = "";
result += this.generateProvider(options.deployment);
result += this.generateContracts(options.useEmbarkJS, options.deployment, true);
result += this.generateContracts(contractsList, options.useEmbarkJS, options.deployment, true);
result += this.generateStorageInitialization(options.useEmbarkJS);
result += this.generateCommunicationInitialization(options.useEmbarkJS);
result += this.generateNamesInitialization(options.useEmbarkJS);
@ -304,12 +275,11 @@ class CodeGenerator {
return contractJSON;
}
generateContractsJSON() {
generateContractsJSON(contractsList) {
let contracts = {};
for (let className in this.contractsManager.contracts) {
let contract = this.contractsManager.contracts[className];
contracts[className] = this.generateContractJSON(className, contract);
for (let contract of contractsList) {
contracts[contract.className] = this.generateContractJSON(contract.className, contract);
}
return contracts;

View File

@ -2,13 +2,19 @@ let async = require('async');
//require("../utils/debug_util.js")(__filename, async);
let utils = require('../utils/utils.js');
class Deploy {
class ContractDeployer {
constructor(options) {
const self = this;
this.blockchain = options.blockchain;
this.logger = options.logger;
this.events = options.events;
this.plugins = options.plugins;
this.gasLimit = options.gasLimit;
self.events.setCommandHandler('deploy:contract', (contract, cb) => {
self.checkAndDeployContract(contract, null, cb);
});
}
// TODO: determining the arguments could also be in a module since it's not
@ -30,40 +36,30 @@ class Deploy {
}
}
let realArgs = [];
async.eachLimit(args, 1, (arg, nextEachCb) => {
async.map(args, (arg, nextEachCb) => {
if (arg[0] === "$") {
let contractName = arg.substr(1);
self.events.request('contracts:contract', contractName, (referedContract) => {
realArgs.push(referedContract.deployedAddress);
nextEachCb();
nextEachCb(null, referedContract.deployedAddress);
});
} else if (Array.isArray(arg)) {
let subRealArgs = [];
async.eachLimit(arg, 1, (sub_arg, nextSubEachCb) => {
async.map(arg, (sub_arg, nextSubEachCb) => {
if (sub_arg[0] === "$") {
let contractName = sub_arg.substr(1);
self.events.request('contracts:contract', contractName, (referedContract) => {
subRealArgs.push(referedContract.deployedAddress);
nextSubEachCb();
nextSubEachCb(null, referedContract.deployedAddress);
});
} else {
subRealArgs.push(sub_arg);
nextSubEachCb();
nextSubEachCb(null, sub_arg);
}
}, () => {
realArgs.push(subRealArgs);
nextEachCb();
}, (err, subRealArgs) => {
nextEachCb(null, subRealArgs);
});
} else {
realArgs.push(arg);
nextEachCb();
nextEachCb(null, arg);
}
}, () => {
callback(realArgs);
});
}, callback);
}
checkAndDeployContract(contract, params, callback) {
@ -77,7 +73,10 @@ class Deploy {
async.waterfall([
function _determineArguments(next) {
self.determineArguments(params || contract.args, contract, (realArgs) => {
self.determineArguments(params || contract.args, contract, (err, realArgs) => {
if (err) {
return next(err);
}
contract.realArgs = realArgs;
next();
});
@ -102,14 +101,14 @@ class Deploy {
// TODO: this should be a plugin API instead, if not existing, it should by default deploy the contract
self.events.request("deploy:contract:shouldDeploy", contract, function(trackedContract) {
if (!trackedContract) {
return self.contractToDeploy(contract, params, next);
return self.deployContract(contract, next);
}
self.blockchain.getCode(trackedContract.address, function(_getCodeErr, codeInChain) {
if (codeInChain !== "0x") {
self.contractAlreadyDeployed(contract, trackedContract, next);
} else {
self.contractToDeploy(contract, params, next);
self.deployContract(contract, next);
}
});
});
@ -125,49 +124,16 @@ class Deploy {
// TODO: can be moved into a afterDeploy event
// just need to figure out the gasLimit coupling issue
self.events.request('code-generator:contract:vanilla', contract, self.gasLimit, (contractCode) => {
self.events.request('code-generator:contract:vanilla', contract, contract._gasLimit, (contractCode) => {
self.events.request('runcode:eval', contractCode);
return callback();
});
}
contractToDeploy(contract, params, callback) {
const self = this;
// TODO: refactor to async
self.determineArguments(params || contract.args, contract, (realArgs) => {
contract.realArgs = realArgs;
this.deployContract(contract, contract.realArgs, function (err, address) {
if (err) {
self.events.emit("deploy:contract:error", contract);
return callback(new Error(err));
}
contract.address = address;
self.events.emit("deploy:contract:deployed", contract);
// TODO: can be moved into a afterDeploy event
// just need to figure out the gasLimit coupling issue
self.events.request('code-generator:contract:vanilla', contract, self.gasLimit, (contractCode) => {
self.events.request('runcode:eval', contractCode);
let onDeployPlugins = self.plugins.getPluginsProperty('onDeployActions', 'onDeployActions');
async.eachLimit(onDeployPlugins, 1, function(plugin, nextEach) {
plugin.call(plugin, contract, nextEach);
}, () => {
callback();
});
});
});
});
}
deployContract(contract, params, callback) {
deployContract(contract, callback) {
let self = this;
let accounts = [];
let contractParams = (params || contract.args).slice();
let contractParams = (contract.realArgs || contract.args).slice();
let contractCode = contract.code;
let deploymentAccount = self.blockchain.defaultAccount();
let deployObject;
@ -227,34 +193,7 @@ class Deploy {
});
},
function applyBeforeDeploy(next) {
let beforeDeployPlugins = self.plugins.getPluginsFor('beforeDeploy');
//self.logger.info("applying beforeDeploy plugins...", beforeDeployPlugins.length);
async.eachSeries(beforeDeployPlugins, (plugin, eachPluginCb) => {
self.logger.info(__("running beforeDeploy plugin %s .", plugin.name));
// calling each beforeDeploy handler declared by the plugin
async.eachSeries(plugin.beforeDeploy, (beforeDeployFn, eachCb) => {
function beforeDeployCb(resObj){
contract.code = resObj.contractCode;
eachCb();
}
beforeDeployFn({
embarkDeploy: self,
pluginConfig: plugin.pluginConfig,
deploymentAccount: deploymentAccount,
contract: contract,
callback: beforeDeployCb
}, beforeDeployCb);
}, () => {
//self.logger.info('All beforeDeploy handlers of the plugin has processed.');
eachPluginCb();
});
}, () => {
//self.logger.info('All beforeDeploy plugins has been processed.');
contractCode = contract.code;
next();
});
self.plugins.emitAndRunActionsForEvent('deploy:contract:beforeDeploy', {contract: contract}, next);
},
function createDeployObject(next) {
let contractObject = self.blockchain.ContractObject({abi: contract.abiDefinition});
@ -289,46 +228,29 @@ class Deploy {
gasPrice: contract.gasPrice
}, function(error, receipt) {
if (error) {
contract.error = error.message;
self.events.emit("deploy:contract:error", contract);
return next(new Error("error deploying =" + contract.className + "= due to error: " + error.message));
}
self.logger.info(contract.className.bold.cyan + " " + __("deployed at").green + " " + receipt.contractAddress.bold.cyan);
contract.deployedAddress = receipt.contractAddress;
contract.transactionHash = receipt.transactionHash;
return next(null, receipt.contractAddress);
self.events.emit("deploy:contract:receipt", receipt);
self.events.emit("deploy:contract:deployed", contract);
// TODO: can be moved into a afterDeploy event
// just need to figure out the gasLimit coupling issue
self.events.request('code-generator:contract:vanilla', contract, contract._gasLimit, (contractCode) => {
self.events.request('runcode:eval', contractCode);
self.plugins.runActionsForEvent('deploy:contract:deployed', {contract: contract}, () => {
return next(null, receipt);
});
});
});
}
], callback);
}
deployAll(done) {
let self = this;
this.logger.info(__("deploying contracts"));
this.events.emit("deploy:beforeAll");
self.events.request('contracts:list', (contracts) => {
async.eachOfSeries(contracts,
function (contract, key, callback) {
self.logger.trace(arguments);
self.checkAndDeployContract(contract, null, callback);
},
function (err, _results) {
if (err) {
self.logger.error(__("error deploying contracts"));
self.logger.error(err.message);
self.logger.debug(err.stack);
}
if (contracts.length === 0) {
self.logger.info(__("no contracts found"));
return done();
}
self.logger.info(__("finished deploying contracts"));
self.logger.trace(arguments);
done(err);
}
);
});
}
}
module.exports = Deploy;
module.exports = ContractDeployer;

View File

@ -34,6 +34,13 @@ class ContractsManager {
cb(self.getContract(contractName));
});
self.events.setCommandHandler("contracts:build", (configOnly, cb) => {
self.deployOnlyOnConfig = configOnly; // temporary, should refactor
self.build(() => {
cb();
});
});
self.events.on("deploy:contract:error", (_contract) => {
self.events.emit('contractsState', self.contractsState());
});
@ -45,6 +52,7 @@ class ContractsManager {
self.events.on("deploy:contract:undeployed", (_contract) => {
self.events.emit('contractsState', self.contractsState());
});
}
build(done) {

View File

@ -1,9 +1,8 @@
let async = require('async');
//require("../utils/debug_util.js")(__filename, async);
let Deploy = require('./deploy.js');
class DeployManager {
constructor(options) {
const self = this;
this.config = options.config;
this.logger = options.logger;
this.blockchainConfig = this.config.blockchainConfig;
@ -11,12 +10,44 @@ class DeployManager {
this.events = options.events;
this.plugins = options.plugins;
this.blockchain = options.blockchain;
this.chainConfig = (options.trackContracts !== false) ? this.config.chainTracker : false;
this.contractsManager = options.contractsManager;
this.gasLimit = false;
this.fatalErrors = false;
this.deployOnlyOnConfig = false;
this.onlyCompile = options.onlyCompile !== undefined ? options.onlyCompile : false;
this.events.setCommandHandler('deploy:contracts', (cb) => {
self.deployContracts(cb);
});
}
deployAll(done) {
let self = this;
this.logger.info(__("deploying contracts"));
this.events.emit("deploy:beforeAll");
self.events.request('contracts:list', (contracts) => {
async.eachOfSeries(contracts,
function (contract, key, callback) {
contract._gasLimit = self.gasLimit;
self.events.request('deploy:contract', contract, () => {
callback();
});
},
function (err, _results) {
if (err) {
self.logger.error(__("error deploying contracts"));
self.logger.error(err.message);
self.logger.debug(err.stack);
}
if (contracts.length === 0) {
self.logger.info(__("no contracts found"));
return done();
}
self.logger.info(__("finished deploying contracts"));
done(err);
}
);
});
}
deployContracts(done) {
@ -30,8 +61,7 @@ class DeployManager {
async.waterfall([
function buildContracts(callback) {
self.contractsManager.deployOnlyOnConfig = self.deployOnlyOnConfig; // temporary, should refactor
self.contractsManager.build(() => {
self.events.request("contracts:build", self.deployOnlyOnConfig, () => {
callback();
});
},
@ -39,7 +69,7 @@ class DeployManager {
// TODO: shouldn't be necessary
function checkCompileOnly(callback){
if(self.onlyCompile){
self.events.emit('contractsDeployed', self.contractsManager);
self.events.emit('contractsDeployed');
return done();
}
return callback();
@ -62,20 +92,9 @@ class DeployManager {
},
function deployAllContracts(callback) {
let deploy = new Deploy({
blockchain: self.blockchain,
contractsManager: self.contractsManager,
logger: self.logger,
events: self.events,
chainConfig: self.chainConfig,
env: self.config.env,
plugins: self.plugins,
gasLimit: self.gasLimit
});
deploy.deployAll(function (err) {
self.deployAll(function (err) {
if (!err) {
self.events.emit('contractsDeployed', self.contractsManager);
self.events.emit('contractsDeployed');
}
if (err && self.fatalErrors) {
return callback(err);
@ -84,13 +103,7 @@ class DeployManager {
});
},
function runAfterDeploy(callback) {
let afterDeployPlugins = self.plugins.getPluginsProperty('afterContractsDeployActions', 'afterContractsDeployActions');
async.eachLimit(afterDeployPlugins, 1, function(plugin, nextEach) {
plugin.call(plugin, nextEach);
}, () => {
callback();
});
self.plugins.emitAndRunActionsForEvent('contracts:deploy:afterAll', callback);
}
], function (err, _result) {
done(err);

View File

@ -6,6 +6,7 @@ const Config = require('./config.js');
const Blockchain = require('../contracts/blockchain.js');
const Compiler = require('../contracts/compiler.js');
const ContractsManager = require('../contracts/contracts.js');
const ContractDeployer = require('../contracts/contract_deployer.js');
const DeployManager = require('../contracts/deploy_manager.js');
const CodeGenerator = require('../contracts/code_generator.js');
const ServicesMonitor = require('./services_monitor.js');
@ -92,7 +93,7 @@ class Engine {
}
registerModule(moduleName, options) {
this.plugins.loadInternalPlugin(moduleName, options);
this.plugins.loadInternalPlugin(moduleName, options || {});
}
startService(serviceName, _options) {
@ -148,12 +149,7 @@ class Engine {
}
namingSystem(_options) {
this.registerModule('ens', {
logger: this.logger,
events: this.events,
web3: this.blockchain.web3,
namesConfig: this.config.namesystemConfig
});
this.registerModule('ens');
}
codeRunnerService(_options) {
@ -170,7 +166,6 @@ class Engine {
this.codeGenerator = new CodeGenerator({
blockchainConfig: self.config.blockchainConfig,
contractsConfig: self.config.contractsConfig,
contractsManager: this.contractsManager,
plugins: self.plugins,
storageConfig: self.config.storageConfig,
namesystemConfig: self.config.namesystemConfig,
@ -185,12 +180,12 @@ class Engine {
self.events.emit('code-generator-ready');
});
};
const cargo = async.cargo((tasks, callback) => {
generateCode(tasks[tasks.length - 1].contractsManager);
const cargo = async.cargo((_tasks, callback) => {
generateCode();
self.events.once('outputDone', callback);
});
const addToCargo = function (contractsManager) {
cargo.push({contractsManager});
const addToCargo = function () {
cargo.push({});
};
this.events.on('contractsDeployed', addToCargo);
@ -206,22 +201,11 @@ class Engine {
compiler.compile_contracts(contractFiles, cb);
});
this.registerModule('solidity', {
contractDirectories: self.config.contractDirectories
});
this.registerModule('vyper', {
contractDirectories: self.config.contractDirectories
});
this.registerModule('profiler', {
events: this.events,
logger: this.logger
});
this.registerModule('deploytracker', {
});
this.registerModule('specialconfigs', {
});
this.registerModule('solidity');
this.registerModule('vyper');
this.registerModule('profiler');
this.registerModule('deploytracker');
this.registerModule('specialconfigs');
this.contractsManager = new ContractsManager({
contractFiles: this.config.contractsFiles,
@ -234,15 +218,20 @@ class Engine {
this.deployManager = new DeployManager({
blockchain: this.blockchain,
trackContracts: options.trackContracts,
config: this.config,
logger: this.logger,
plugins: this.plugins,
events: this.events,
contractsManager: this.contractsManager,
onlyCompile: options.onlyCompile
});
this.contractDeployer = new ContractDeployer({
blockchain: this.blockchain,
logger: this.logger,
events: this.events,
plugins: this.plugins
});
this.events.on('file-event', function (fileType) {
clearTimeout(self.fileTimeout);
self.fileTimeout = setTimeout(() => {
@ -256,8 +245,8 @@ class Engine {
// because the contractsManager config is corrupted after a deploy
if (fileType === 'contract' || fileType === 'config') {
self.config.reloadConfig();
self.deployManager.deployContracts(function () {
});
self.events.request('deploy:contracts', () => {});
}
}, 50);
});
@ -278,7 +267,6 @@ class Engine {
ipfsService(_options) {
this.registerModule('ipfs', {
addCheck: this.servicesMonitor.addCheck.bind(this.servicesMonitor),
storageConfig: this.config.storageConfig,
host: _options.host,
port: _options.port
});
@ -287,7 +275,6 @@ class Engine {
swarmService(_options) {
this.registerModule('swarm', {
addCheck: this.servicesMonitor.addCheck.bind(this.servicesMonitor),
storageConfig: this.config.storageConfig,
// TODO: this should not be needed and should be deducted from the config instead
// the eth provider is not necessary the same as the swarm one
bzz: this.blockchain.web3.bzz
@ -308,7 +295,6 @@ class Engine {
this.registerModule('whisper', {
addCheck: this.servicesMonitor.addCheck.bind(this.servicesMonitor),
communicationConfig: this.config.communicationConfig,
// 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

View File

@ -1,7 +1,7 @@
var EventEmitter = require('events');
function warnIfLegacy(eventName) {
const legacyEvents = ['abi-vanila', 'abi', 'abi-contracts-vanila', 'abi-vanila-deployment'];
const legacyEvents = [];
if (legacyEvents.indexOf(eventName) >= 0) {
console.info(__("this event is deprecated and will be removed in future versions %s", eventName));
}

View File

@ -1,6 +1,7 @@
const fs = require('./fs.js');
const utils = require('../utils/utils.js');
const constants = require('../constants');
const _ = require('underscore');
// TODO: pass other params like blockchainConfig, contract files, etc..
var Plugin = function(options) {
@ -27,6 +28,7 @@ var Plugin = function(options) {
this.embarkjs_init_code = {};
this.afterContractsDeployActions = [];
this.onDeployActions = [];
this.eventActions = {};
this.logger = options.logger;
this.events = options.events;
this.config = options.config;
@ -119,43 +121,45 @@ Plugin.prototype.interceptLogs = function(context) {
Plugin.prototype.registerClientWeb3Provider = function(cb) {
this.clientWeb3Providers.push(cb);
this.pluginTypes.push('clientWeb3Provider');
};
Plugin.prototype.registerBeforeDeploy = function(cb) {
this.beforeDeploy.push(cb);
this.pluginTypes.push('beforeDeploy');
this.pluginTypes = _.uniq(this.pluginTypes);
};
Plugin.prototype.registerContractsGeneration = function(cb) {
this.contractsGenerators.push(cb);
this.pluginTypes.push('contractGeneration');
this.pluginTypes = _.uniq(this.pluginTypes);
};
Plugin.prototype.registerPipeline = function(matcthingFiles, cb) {
// TODO: generate error for more than one pipeline per plugin
this.pipeline.push({matcthingFiles: matcthingFiles, cb: cb});
this.pluginTypes.push('pipeline');
this.pluginTypes = _.uniq(this.pluginTypes);
};
Plugin.prototype.addFileToPipeline = function(file, intendedPath, options) {
this.pipelineFiles.push({file: file, intendedPath: intendedPath, options: options});
this.pluginTypes.push('pipelineFiles');
this.pluginTypes = _.uniq(this.pluginTypes);
};
Plugin.prototype.addContractFile = function(file) {
this.contractsFiles.push(file);
this.pluginTypes.push('contractFiles');
this.pluginTypes = _.uniq(this.pluginTypes);
};
Plugin.prototype.registerConsoleCommand = function(cb) {
this.console.push(cb);
this.pluginTypes.push('console');
this.pluginTypes = _.uniq(this.pluginTypes);
};
// TODO: this only works for services done on startup
Plugin.prototype.registerServiceCheck = function(checkName, checkFn, time) {
this.serviceChecks.push({checkName: checkName, checkFn: checkFn, time: time});
this.pluginTypes.push('serviceChecks');
this.pluginTypes = _.uniq(this.pluginTypes);
};
Plugin.prototype.has = function(pluginType) {
@ -177,42 +181,47 @@ Plugin.prototype.generateContracts = function(args) {
Plugin.prototype.registerContractConfiguration = function(config) {
this.contractsConfigs.push(config);
this.pluginTypes.push('contractsConfig');
this.pluginTypes = _.uniq(this.pluginTypes);
};
Plugin.prototype.registerCompiler = function(extension, cb) {
this.compilers.push({extension: extension, cb: cb});
this.pluginTypes.push('compilers');
this.pluginTypes = _.uniq(this.pluginTypes);
};
Plugin.prototype.registerUploadCommand = function(cmd, cb) {
this.uploadCmds.push({cmd: cmd, cb: cb});
this.pluginTypes.push('uploadCmds');
this.pluginTypes = _.uniq(this.pluginTypes);
};
Plugin.prototype.addCodeToEmbarkJS = function(code) {
this.embarkjs_code.push(code);
this.pluginTypes.push('embarkjsCode');
this.pluginTypes = _.uniq(this.pluginTypes);
};
Plugin.prototype.addProviderInit = function(providerType, code, initCondition) {
this.embarkjs_init_code[providerType] = this.embarkjs_init_code[providerType] || [];
this.embarkjs_init_code[providerType].push([code, initCondition]);
this.pluginTypes.push('initCode');
this.pluginTypes = _.uniq(this.pluginTypes);
};
Plugin.prototype.registerImportFile = function(importName, importLocation) {
this.imports.push([importName, importLocation]);
this.pluginTypes.push('imports');
this.pluginTypes = _.uniq(this.pluginTypes);
};
Plugin.prototype.registerAfterAllContractsDeploy = function(cb) {
this.afterContractsDeployActions.push(cb);
this.pluginTypes.push('afterContractsDeployActions');
};
Plugin.prototype.registerOnDeployContracts = function(cb) {
this.onDeployActions.push(cb);
this.pluginTypes.push('onDeployActions');
Plugin.prototype.registerActionForEvent = function(eventName, cb) {
if (!this.eventActions[eventName]) {
this.eventActions[eventName] = [];
}
this.eventActions[eventName].push(cb);
this.pluginTypes.push('eventActions');
this.pluginTypes = _.uniq(this.pluginTypes);
};
Plugin.prototype.runFilePipeline = function() {

View File

@ -1,3 +1,4 @@
const async = require('async');
var Plugin = require('./plugin.js');
var utils = require('../utils/utils.js');
@ -58,7 +59,7 @@ Plugins.prototype.loadInternalPlugin = function(pluginName, pluginConfig) {
var pluginWrapper = new Plugin({
name: pluginName,
pluginModule: plugin,
pluginConfig: pluginConfig,
pluginConfig: pluginConfig || {},
logger: this.logger,
pluginPath: pluginPath,
interceptLogs: this.interceptLogs,
@ -98,18 +99,48 @@ Plugins.prototype.getPluginsFor = function(pluginType) {
});
};
Plugins.prototype.getPluginsProperty = function(pluginType, property) {
Plugins.prototype.getPluginsProperty = function(pluginType, property, sub_property) {
let matchingPlugins = this.plugins.filter(function(plugin) {
return plugin.has(pluginType);
});
let matchingProperties = matchingPlugins.map((plugin) => {
if (sub_property) {
return plugin[property][sub_property];
}
return plugin[property];
});
matchingProperties = matchingProperties.filter((property) => property);
//return flattened list
if (matchingProperties.length === 0) return [];
return matchingProperties.reduce((a,b) => { return a.concat(b); });
return matchingProperties.reduce((a,b) => { return a.concat(b); }) || [];
};
Plugins.prototype.runActionsForEvent = function(eventName, args, cb) {
if (typeof (args) === 'function') {
cb = args;
}
let actionPlugins = this.getPluginsProperty('eventActions', 'eventActions', eventName);
if (actionPlugins.length === 0) {
return cb();
}
async.eachLimit(actionPlugins, 1, function(plugin, nextEach) {
if (typeof (args) === 'function') {
plugin.call(plugin, nextEach);
} else {
//plugin.call(plugin, ...args, nextEach);
plugin.call(plugin, args, nextEach);
}
}, cb);
};
Plugins.prototype.emitAndRunActionsForEvent = function(eventName, args, cb) {
this.events.emit(eventName);
return this.runActionsForEvent(eventName, args, cb);
};
module.exports = Plugins;

View File

@ -167,7 +167,7 @@ class Embark {
engine.events.on('check:backOnline:Ethereum', function () {
engine.logger.info(__('Ethereum node detected') + '..');
engine.config.reloadConfig();
engine.deployManager.deployContracts(function () {
engine.events.request('deploy:contracts', function() {
engine.logger.info(__('Deployment Done'));
});
});
@ -191,6 +191,7 @@ class Embark {
engine.logger.info(__("Ready").underline);
engine.events.emit("status", __("Ready").green);
});
if (options.runWebserver) {
engine.startService("webServer", {
host: options.serverHost,
@ -255,7 +256,7 @@ class Embark {
callback();
},
function deploy(callback) {
engine.deployManager.deployContracts(function (err) {
engine.events.request('deploy:contracts', function(err) {
callback(err);
});
}
@ -306,7 +307,7 @@ class Embark {
engine.startService("deployment", {onlyCompile: true});
engine.startService("codeGenerator");
engine.deployManager.deployContracts(function (err) {
engine.events.request('deploy:contracts', function(err) {
callback(err);
});
}
@ -418,7 +419,6 @@ class Embark {
callback();
},
function deploy(callback) {
// 2. upload to storage (outputDone event triggered after webpack finished)
engine.events.on('outputDone', function () {
cmdPlugin.uploadCmds[0].cb()
.then((success) => {
@ -427,8 +427,7 @@ class Embark {
.catch(callback);
});
// 1. build the contracts and dapp webpack
engine.deployManager.deployContracts(function (err) {
engine.events.request('deploy:contracts', function(err) {
engine.logger.info(__("finished deploying").underline);
if(err){
callback(err);

View File

@ -2,11 +2,10 @@ const fs = require('../../core/fs.js');
const utils = require('../../utils/utils.js');
class ENS {
constructor(embark, options) {
constructor(embark, _options) {
this.logger = embark.logger;
this.events = embark.events;
this.web3 = options.web3;
this.namesConfig = options.namesConfig;
this.namesConfig = embark.config.namesystemConfig;
this.embark = embark;
this.addENSToEmbarkJS();

View File

@ -9,7 +9,7 @@ class IPFS {
this.logger = embark.logger;
this.events = embark.events;
this.buildDir = options.buildDir;
this.storageConfig = options.storageConfig;
this.storageConfig = embark.config.storageConfig;
this.host = options.host || this.storageConfig.host;
this.port = options.port || this.storageConfig.port;
this.addCheck = options.addCheck;

View File

@ -5,7 +5,6 @@ class Profiler {
this.embark = embark;
this.logger = embark.logger;
this.events = embark.events;
this.plugins = embark.plugins;
this.registerConsoleCommand();
}

View File

@ -3,10 +3,10 @@ let SolcW = require('./solcW.js');
class Solidity {
constructor(embark, options) {
constructor(embark, _options) {
this.logger = embark.logger;
this.events = embark.events;
this.contractDirectories = options.contractDirectories;
this.contractDirectories = embark.config.contractDirectories;
this.solcAlreadyLoaded = false;
this.solcW = null;

View File

@ -48,7 +48,7 @@ class SpecialConfigs {
registerAfterDeployAction() {
const self = this;
this.embark.registerAfterAllContractsDeploy((cb) => {
this.embark.registerActionForEvent("contracts:deploy:afterAll", (cb) => {
let afterDeployCmds = self.contractsConfig.afterDeploy || [];
async.mapLimit(afterDeployCmds, 1, (cmd, nextMapCb) => {
@ -79,7 +79,9 @@ class SpecialConfigs {
registerOnDeployAction() {
const self = this;
this.embark.registerOnDeployContracts((contract, cb) => {
this.embark.registerActionForEvent("deploy:contract:deployed", (params, cb) => {
let contract = params.contract;
if (!contract.onDeploy) {
return cb();
}

View File

@ -8,7 +8,7 @@ class Swarm {
this.logger = embark.logger;
this.events = embark.events;
this.buildDir = options.buildDir;
this.storageConfig = options.storageConfig;
this.storageConfig = embark.config.storageConfig;
this.host = options.host || this.storageConfig.host;
this.port = options.port || this.storageConfig.port;
this.addCheck = options.addCheck;

View File

@ -4,10 +4,10 @@ const path = require('path');
class Vyper {
constructor(embark, options) {
constructor(embark, _options) {
this.logger = embark.logger;
this.events = embark.events;
this.contractDirectories = options.contractDirectories;
this.contractDirectories = embark.config.contractDirectories;
// FIXME: Use array of extensions instead of duplicatiing
embark.registerCompiler(".py", this.compile_vyper.bind(this));

View File

@ -6,7 +6,7 @@ class Whisper {
constructor(embark, options) {
this.logger = embark.logger;
this.events = embark.events;
this.communicationConfig = options.communicationConfig;
this.communicationConfig = embark.config.communicationConfig;
this.addCheck = options.addCheck;
// TODO: this should not be needed and should be deducted from the config instead
this.web3 = options.web3;

View File

@ -88,7 +88,7 @@ Test.prototype.deployAll = function(contractsConfig, cb) {
self.engine.contractsManager.gasLimit = 6000000;
self.engine.deployManager.fatalErrors = true;
self.engine.deployManager.deployOnlyOnConfig = true;
self.engine.deployManager.deployContracts(function(err, _result) {
self.engine.events.request('deploy:contracts', function(err) {
if (err) {
callback(err);
}

View File

@ -12,29 +12,31 @@ describe('embark.CodeGenerator', function() {
this.timeout(0);
describe('#generateContracts', function() {
let generator = new CodeGenerator({blockchainConfig: {}, contractsManager: {
contracts: {
SimpleStorage: {
let contracts = [
{
className: 'SimpleStorage',
abiDefinition: [{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"initialValue","type":"uint256"}],"type":"constructor"}],
gasEstimates: 12000,
deployedAddress: "0x123",
code: '12345'
},
Foo: {
{
className: 'Foo',
abiDefinition: [{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"initialValue","type":"uint256"}],"type":"constructor"}],
gasEstimates: 12000,
deployedAddress: "0x124",
code: '123456'
}
}
}});
]
let generator = new CodeGenerator({blockchainConfig: {}});
describe('with EmbarkJS', function() {
let withEmbarkJS = true;
it('should generate contract code', function() {
var contractCode = "\n__mainContext.__loadManagerInstance.execWhenReady(function() {\n __mainContext.SimpleStorage = new EmbarkJS.Contract({abi: [{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialValue\",\"type\":\"uint256\"}],\"type\":\"constructor\"}], address: '0x123', code: '12345', gasEstimates: 12000});\n\n});\n__mainContext.__loadManagerInstance.execWhenReady(function() {\n __mainContext.Foo = new EmbarkJS.Contract({abi: [{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialValue\",\"type\":\"uint256\"}],\"type\":\"constructor\"}], address: '0x124', code: '123456', gasEstimates: 12000});\n\n});\n";
assert.strictEqual(replaceCRLF(generator.generateContracts(withEmbarkJS)), contractCode);
assert.strictEqual(replaceCRLF(generator.generateContracts(contracts, withEmbarkJS)), contractCode);
});
});
@ -43,7 +45,7 @@ describe('embark.CodeGenerator', function() {
it('should generate contract code', function() {
var contractCode = "\n__mainContext.__loadManagerInstance.execWhenReady(function() {\n SimpleStorageAbi = [{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialValue\",\"type\":\"uint256\"}],\"type\":\"constructor\"}];\nSimpleStorage = new web3.eth.Contract(SimpleStorageAbi);\nSimpleStorage.options.address = '0x123';\nSimpleStorage.address = '0x123';\nSimpleStorage.options.from = web3.eth.defaultAccount;\n\n\n});\n__mainContext.__loadManagerInstance.execWhenReady(function() {\n FooAbi = [{\"constant\":true,\"inputs\":[],\"name\":\"storedData\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"get\",\"outputs\":[{\"name\":\"retVal\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"initialValue\",\"type\":\"uint256\"}],\"type\":\"constructor\"}];\nFoo = new web3.eth.Contract(FooAbi);\nFoo.options.address = '0x124';\nFoo.address = '0x124';\nFoo.options.from = web3.eth.defaultAccount;\n\n\n});\n";
assert.strictEqual(replaceCRLF(generator.generateContracts(withEmbarkJS)), contractCode);
assert.strictEqual(replaceCRLF(generator.generateContracts(contracts, withEmbarkJS)), contractCode);
});
});

File diff suppressed because one or more lines are too long

View File

@ -26,9 +26,12 @@ describe('embark.Contracts', function() {
describe('simple', function() {
let plugins = new Plugins({
logger: new TestLogger({}),
events: TestEvents
events: TestEvents,
config: {
contractDirectories: ['app/contracts/']
}
});
plugins.loadInternalPlugin('solidity', {solcVersion: '0.4.17', contractDirectories: ['app/contracts/']});
plugins.loadInternalPlugin('solidity');
let compiler = new Compiler({plugins: plugins, logger: plugins.logger});
let events = new Events();
@ -115,9 +118,12 @@ describe('embark.Contracts', function() {
describe('config with contract instances', function() {
let plugins = new Plugins({
logger: new TestLogger({}),
events: TestEvents
events: TestEvents,
config: {
contractDirectories: ['app/contracts/']
}
});
plugins.loadInternalPlugin('solidity', {solcVersion: '0.4.17', contractDirectories: ['app/contracts/']});
plugins.loadInternalPlugin('solidity');
let compiler = new Compiler({plugins: plugins, logger: plugins.logger});
let events = new Events();

View File

@ -23,9 +23,12 @@ module.exports = function (embark) {
embark.addFileToPipeline('./fileInPipeline.js');
embark.addFileToPipeline('./fileInPipeline.js', 'js/fileInPipeline.js');
embark.registerBeforeDeploy(function (options, callback) {
// Just calling register to prove it works. We don't actually want to change the contracts
callback({contractCode: options.contract.code});
embark.registerActionForEvent("deploy:contract:beforeDeploy", (params, cb) => {
embark.logger.info("applying beforeDeploy plugin...");
//console.dir(params);
//console.dir(cb);
//console.dir('------------------');
cb();
});
// NOTE: uncommenting this will make dappConnection stop working

View File

@ -89,7 +89,7 @@
"dom-helpers": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.3.1.tgz",
"integrity": "sha1-/BpOFf/fYN3eA6SAqcD+zoId1KY="
"integrity": "sha512-2Sm+JaYn74OiTM2wHvxJOo3roiq/h25Yi69Fqk269cNUwIXsCvATB6CRSFC9Am/20G2b28hGv/+7NiWydIrPvg=="
},
"dotenv": {
"version": "4.0.0",
@ -229,7 +229,7 @@
"node-fetch": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
"integrity": "sha1-mA9vcthSEaU0fGsrwYxbhMPrR+8=",
"integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
"requires": {
"encoding": "0.1.12",
"is-stream": "1.1.0"
@ -252,7 +252,7 @@
"promise": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
"integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=",
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
"requires": {
"asap": "2.0.6"
}
@ -289,7 +289,7 @@
"react-bootstrap": {
"version": "0.32.1",
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-0.32.1.tgz",
"integrity": "sha1-YGJMG0ijnXc+9szmQhpPM+zBZrs=",
"integrity": "sha512-RbfzKUbsukWsToWqGHfCCyMFq9QQI0TznutdyxyJw6dih2NvIne25Mrssg8LZsprqtPpyQi8bN0L0Fx3fUsL8Q==",
"requires": {
"babel-runtime": "6.26.0",
"classnames": "2.2.5",
@ -319,7 +319,7 @@
"react-overlays": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-0.8.3.tgz",
"integrity": "sha1-+tZe6lskMBzKGSoWn13dsLINOsU=",
"integrity": "sha512-h6GT3jgy90PgctleP39Yu3eK1v9vaJAW73GOA/UbN9dJ7aAN4BTZD6793eI1D5U+ukMk17qiqN/wl3diK1Z5LA==",
"requires": {
"classnames": "2.2.5",
"dom-helpers": "3.3.1",
@ -353,7 +353,7 @@
"regenerator-runtime": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
"integrity": "sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk="
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
},
"setimmediate": {
"version": "1.0.5",
@ -412,7 +412,7 @@
"zeppelin-solidity": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/zeppelin-solidity/-/zeppelin-solidity-1.8.0.tgz",
"integrity": "sha1-BJ/N59rqn8hSEPjG25+M0auKhTo=",
"integrity": "sha512-7Mxq6Y7EES0PSLrRF6v0EVYqBVRRo8hFrr7m3jEs69VbbQ5kpANzizeEdbP1/PWKSOmBOg208qP2vSA0FlzFLA==",
"requires": {
"dotenv": "4.0.0",
"ethjs-abi": "0.2.1"