refactor contracts manager; deployment; blockchain client

This commit is contained in:
Iuri Matias 2019-07-24 18:27:34 -04:00
parent d80f04850a
commit 261dee8ad0
31 changed files with 1310 additions and 909 deletions

View File

@ -1,170 +1,176 @@
/*global web3*/
import React from 'react';
import EmbarkJS from 'Embark/EmbarkJS';
import {SimpleStorage, Test, SimpleStorageTest} from '../../embarkArtifacts/contracts';
window.SimpleStorageTest = SimpleStorageTest;
import {SimpleStorage} from '../../embarkArtifacts/contracts';
import ReactDOM from 'react-dom';
import $ from 'jquery';
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap/dist/css/bootstrap-theme.css';
import 'bootstrap/dist/js/bootstrap.min.js';
window.EmbarkJS = EmbarkJS;
window.SimpleStorage = SimpleStorage;
window.Test = Test;
//window.Assert = Assert;
window.React = React;
import './foo.css';
import App from './app.js';
ReactDOM.render(<App />, document.getElementById('root'));
var addToLog = function(id, txt) {
$(id + " .logs").append("<br>" + txt);
};
// ===========================
// Blockchain example
// ===========================
$(document).ready(function() {
EmbarkJS.onReady((err) => {
if (err) {
console.error(err);
}
});
console.log([1,2,3].map(v => v + 1));
$("#blockchain button.set").click(function() {
var value = parseInt($("#blockchain input.text").val(), 10);
SimpleStorage.methods.set(value).send({from: web3.eth.defaultAccount, gas: 5300000});
addToLog("#blockchain", "SimpleStorage.methods.set(value).send({from: web3.eth.defaultAccount, gas: 5300000})");
});
$("#blockchain button.get").click(function() {
SimpleStorage.methods.get().call(function(err, value) {
$("#blockchain .value").html(value);
});
addToLog("#blockchain", "SimpleStorage.methods.get(console.log)");
});
});
// ===========================
// Storage (IPFS) example
// ===========================
$(document).ready(function() {
// automatic set if config/storage.json has "enabled": true and "provider": "ipfs"
//EmbarkJS.Storage.setProvider('ipfs',{server: 'localhost', port: '5001'});
$("#storage .error").hide();
//EmbarkJS.Storage.ipfsConnection.version()
// .then(function(){
$("#status-storage").addClass('status-online');
$("#storage-controls").show();
// })
// .catch(function(err) {
// if(err){
// console.log("IPFS Connection Error => " + err.message);
// $("#storage .error").show();
// $("#status-storage").addClass('status-offline');
// $("#storage-controls").hide();
// }
// });
$("#storage button.setIpfsText").click(function() {
var value = $("#storage input.ipfsText").val();
EmbarkJS.Storage.saveText(value).then(function(hash) {
$("span.textHash").html(hash);
$("input.textHash").val(hash);
addToLog("#storage", "EmbarkJS.Storage.saveText('" + value + "').then(function(hash) { })");
})
.catch(function(err) {
if(err){
console.log("IPFS saveText Error => " + err.message);
}
});
});
$("#storage button.loadIpfsHash").click(function() {
var value = $("#storage input.textHash").val();
EmbarkJS.Storage.get(value).then(function(content) {
$("span.ipfsText").html(content);
addToLog("#storage", "EmbarkJS.Storage.get('" + value + "').then(function(content) { })");
})
.catch(function(err) {
if(err){
console.log("IPFS get Error => " + err.message);
}
});
});
$("#storage button.uploadFile").click(function() {
var input = $("#storage input[type=file]");
EmbarkJS.Storage.uploadFile(input).then(function(hash) {
$("span.fileIpfsHash").html(hash);
$("input.fileIpfsHash").val(hash);
addToLog("#storage", "EmbarkJS.Storage.uploadFile($('input[type=file]')).then(function(hash) { })");
})
.catch(function(err) {
if(err){
console.log("IPFS uploadFile Error => " + err.message);
}
});
});
$("#storage button.loadIpfsFile").click(function() {
var hash = $("#storage input.fileIpfsHash").val();
var url = EmbarkJS.Storage.getUrl(hash);
var link = '<a href="' + url + '" target="_blank">' + url + '</a>';
$("span.ipfsFileUrl").html(link);
$(".ipfsImage").attr('src', url);
addToLog("#storage", "EmbarkJS.Storage.getUrl('" + hash + "')");
});
});
// ===========================
// Communication (Whisper) example
// ===========================
$(document).ready(function() {
$("#communication .error").hide();
$("#communication .errorVersion").hide();
if (EmbarkJS.Messages.providerName === 'whisper') {
EmbarkJS.Messages.getWhisperVersion(function(err, _version) {
if (err) {
$("#communication .error").show();
$("#communication-controls").hide();
$("#status-communication").addClass('status-offline');
} else {
EmbarkJS.Messages.setProvider('whisper');
$("#status-communication").addClass('status-online');
}
});
}
$("#communication button.listenToChannel").click(function() {
var channel = $("#communication .listen input.channel").val();
$("#communication #subscribeList").append("<br> subscribed to " + channel + " now try sending a message");
EmbarkJS.Messages.listenTo({topic: [channel]}).subscribe(function({data: message}) {
$("#communication #messagesList").append("<br> channel: " + channel + " message: " + message);
});
addToLog("#communication", "EmbarkJS.Messages.listenTo({topic: ['" + channel + "']}).then(function(message) {})");
});
$("#communication button.sendMessage").click(function() {
var channel = $("#communication .send input.channel").val();
var message = $("#communication .send input.message").val();
EmbarkJS.Messages.sendMessage({topic: channel, data: message});
addToLog("#communication", "EmbarkJS.Messages.sendMessage({topic: '" + channel + "', data: '" + message + "'})");
});
});
// /*global web3*/
// import React from 'react';
// import EmbarkJS from 'Embark/EmbarkJS';
// import {SimpleStorage, Test, SimpleStorageTest} from '../../embarkArtifacts/contracts';
//
// window.SimpleStorageTest = SimpleStorageTest;
//
// import ReactDOM from 'react-dom';
//
// import $ from 'jquery';
// import 'bootstrap/dist/css/bootstrap.css';
// import 'bootstrap/dist/css/bootstrap-theme.css';
// import 'bootstrap/dist/js/bootstrap.min.js';
//
// window.EmbarkJS = EmbarkJS;
// window.SimpleStorage = SimpleStorage;
// window.Test = Test;
// //window.Assert = Assert;
//
// window.React = React;
//
// import './foo.css';
//
// import App from './app.js';
//
// ReactDOM.render(<App />, document.getElementById('root'));
//
// var addToLog = function(id, txt) {
// $(id + " .logs").append("<br>" + txt);
// };
//
// // ===========================
// // Blockchain example
// // ===========================
// $(document).ready(function() {
// EmbarkJS.onReady((err) => {
// if (err) {
// console.error(err);
// }
// });
//
// console.log([1,2,3].map(v => v + 1));
//
// $("#blockchain button.set").click(function() {
// var value = parseInt($("#blockchain input.text").val(), 10);
//
// SimpleStorage.methods.set(value).send({from: web3.eth.defaultAccount, gas: 5300000});
// addToLog("#blockchain", "SimpleStorage.methods.set(value).send({from: web3.eth.defaultAccount, gas: 5300000})");
// });
//
// $("#blockchain button.get").click(function() {
// SimpleStorage.methods.get().call(function(err, value) {
// $("#blockchain .value").html(value);
// });
// addToLog("#blockchain", "SimpleStorage.methods.get(console.log)");
// });
//
// });
//
// // ===========================
// // Storage (IPFS) example
// // ===========================
// $(document).ready(function() {
// // automatic set if config/storage.json has "enabled": true and "provider": "ipfs"
// //EmbarkJS.Storage.setProvider('ipfs',{server: 'localhost', port: '5001'});
//
// $("#storage .error").hide();
// //EmbarkJS.Storage.ipfsConnection.version()
// // .then(function(){
// $("#status-storage").addClass('status-online');
// $("#storage-controls").show();
// // })
// // .catch(function(err) {
// // if(err){
// // console.log("IPFS Connection Error => " + err.message);
// // $("#storage .error").show();
// // $("#status-storage").addClass('status-offline');
// // $("#storage-controls").hide();
// // }
// // });
//
// $("#storage button.setIpfsText").click(function() {
// var value = $("#storage input.ipfsText").val();
// EmbarkJS.Storage.saveText(value).then(function(hash) {
// $("span.textHash").html(hash);
// $("input.textHash").val(hash);
// addToLog("#storage", "EmbarkJS.Storage.saveText('" + value + "').then(function(hash) { })");
// })
// .catch(function(err) {
// if(err){
// console.log("IPFS saveText Error => " + err.message);
// }
// });
// });
//
// $("#storage button.loadIpfsHash").click(function() {
// var value = $("#storage input.textHash").val();
// EmbarkJS.Storage.get(value).then(function(content) {
// $("span.ipfsText").html(content);
// addToLog("#storage", "EmbarkJS.Storage.get('" + value + "').then(function(content) { })");
// })
// .catch(function(err) {
// if(err){
// console.log("IPFS get Error => " + err.message);
// }
// });
// });
//
// $("#storage button.uploadFile").click(function() {
// var input = $("#storage input[type=file]");
// EmbarkJS.Storage.uploadFile(input).then(function(hash) {
// $("span.fileIpfsHash").html(hash);
// $("input.fileIpfsHash").val(hash);
// addToLog("#storage", "EmbarkJS.Storage.uploadFile($('input[type=file]')).then(function(hash) { })");
// })
// .catch(function(err) {
// if(err){
// console.log("IPFS uploadFile Error => " + err.message);
// }
// });
// });
//
// $("#storage button.loadIpfsFile").click(function() {
// var hash = $("#storage input.fileIpfsHash").val();
// var url = EmbarkJS.Storage.getUrl(hash);
// var link = '<a href="' + url + '" target="_blank">' + url + '</a>';
// $("span.ipfsFileUrl").html(link);
// $(".ipfsImage").attr('src', url);
// addToLog("#storage", "EmbarkJS.Storage.getUrl('" + hash + "')");
// });
//
// });
//
// // ===========================
// // Communication (Whisper) example
// // ===========================
// $(document).ready(function() {
//
// $("#communication .error").hide();
// $("#communication .errorVersion").hide();
// if (EmbarkJS.Messages.providerName === 'whisper') {
// EmbarkJS.Messages.getWhisperVersion(function(err, _version) {
// if (err) {
// $("#communication .error").show();
// $("#communication-controls").hide();
// $("#status-communication").addClass('status-offline');
// } else {
// EmbarkJS.Messages.setProvider('whisper');
// $("#status-communication").addClass('status-online');
// }
// });
// }
//
// $("#communication button.listenToChannel").click(function() {
// var channel = $("#communication .listen input.channel").val();
// $("#communication #subscribeList").append("<br> subscribed to " + channel + " now try sending a message");
// EmbarkJS.Messages.listenTo({topic: [channel]}).subscribe(function({data: message}) {
// $("#communication #messagesList").append("<br> channel: " + channel + " message: " + message);
// });
// addToLog("#communication", "EmbarkJS.Messages.listenTo({topic: ['" + channel + "']}).then(function(message) {})");
// });
//
// $("#communication button.sendMessage").click(function() {
// var channel = $("#communication .send input.channel").val();
// var message = $("#communication .send input.message").val();
// EmbarkJS.Messages.sendMessage({topic: channel, data: message});
// addToLog("#communication", "EmbarkJS.Messages.sendMessage({topic: '" + channel + "', data: '" + message + "'})");
// });
//
// });
//

View File

@ -1,60 +1,61 @@
import $ from 'jquery';
import {AlreadyDeployedToken, AnotherStorage, MyToken, MyToken2, SimpleStorage, Token} from '../../embarkArtifacts/contracts';
import async from 'async';
$(document).ready(function() {
document.getElementById("runTests").onclick = function() {
async.waterfall([
function test1(callback) {
AnotherStorage.methods.simpleStorageAddress().call().then(function(simpleStorageAddress) {
$("#tests").append("<br>test 1: " + (simpleStorageAddress === SimpleStorage._address));
callback();
});
},
function test2(callback) {
SimpleStorage.methods.storedData().call().then(function(result) {
$("#tests").append("<br>test 2 (true first time): " + (result === "100"));
$("#tests").append("<br>test 2 (true after): " + (result === "150"));
callback();
});
},
function test3(callback) {
SimpleStorage.methods.set(150).send({from: web3.eth.defaultAccount}).then(function() {
SimpleStorage.methods.get().call().then(function(result) {
$("#tests").append("<br>test 3: " + (result === "150"));
callback();
});
});
},
function test4(callback) {
$("#tests").append("<br>test 4: " + (Token._address === null));
$("#tests").append("<br>test 4: " + (MyToken._address !== undefined));
$("#tests").append("<br>test 4: " + (MyToken2._address !== undefined));
callback();
},
function test5(callback) {
MyToken.methods._supply().call().then(function(result) {
$("#tests").append("<br>test 5: " + (result === "1000"));
callback();
});
},
function test6(callback) {
MyToken2.methods._supply().call().then(function(result) {
$("#tests").append("<br>test 6: " + (result === "2000"));
callback();
});
},
function test7(callback) {
$("#tests").append("<br>test 7: " + (AlreadyDeployedToken._address === "0xeCE374063fE5Cc7EFbACA0a498477CaDA94E5AD6"));
callback();
}
], function (err, result) {
$("#tests").append("<br>done");
});
};
});
/// import $ from 'jquery';
///
/// import {AlreadyDeployedToken, AnotherStorage, MyToken, MyToken2, SimpleStorage, Token} from '../../embarkArtifacts/contracts';
/// import async from 'async';
///
/// $(document).ready(function() {
///
/// document.getElementById("runTests").onclick = function() {
/// async.waterfall([
/// function test1(callback) {
/// AnotherStorage.methods.simpleStorageAddress().call().then(function(simpleStorageAddress) {
/// $("#tests").append("<br>test 1: " + (simpleStorageAddress === SimpleStorage._address));
/// callback();
/// });
/// },
/// function test2(callback) {
/// SimpleStorage.methods.storedData().call().then(function(result) {
/// $("#tests").append("<br>test 2 (true first time): " + (result === "100"));
/// $("#tests").append("<br>test 2 (true after): " + (result === "150"));
/// callback();
/// });
/// },
/// function test3(callback) {
/// SimpleStorage.methods.set(150).send({from: web3.eth.defaultAccount}).then(function() {
/// SimpleStorage.methods.get().call().then(function(result) {
/// $("#tests").append("<br>test 3: " + (result === "150"));
/// callback();
/// });
/// });
/// },
/// function test4(callback) {
/// $("#tests").append("<br>test 4: " + (Token._address === null));
/// $("#tests").append("<br>test 4: " + (MyToken._address !== undefined));
/// $("#tests").append("<br>test 4: " + (MyToken2._address !== undefined));
/// callback();
/// },
/// function test5(callback) {
/// MyToken.methods._supply().call().then(function(result) {
/// $("#tests").append("<br>test 5: " + (result === "1000"));
/// callback();
/// });
/// },
/// function test6(callback) {
/// MyToken2.methods._supply().call().then(function(result) {
/// $("#tests").append("<br>test 6: " + (result === "2000"));
/// callback();
/// });
/// },
/// function test7(callback) {
/// $("#tests").append("<br>test 7: " + (AlreadyDeployedToken._address === "0xeCE374063fE5Cc7EFbACA0a498477CaDA94E5AD6"));
/// callback();
/// }
/// ], function (err, result) {
/// $("#tests").append("<br>done");
/// });
///
/// };
///
/// });
///
///

View File

@ -0,0 +1,38 @@
pragma solidity ^0.4.25;
contract SimpleStorage {
uint public storedData;
address public registar;
address owner;
event EventOnSet2(bool passed, string message);
constructor(uint initialValue) public {
storedData = initialValue;
owner = msg.sender;
}
function set(uint x) public {
storedData = x;
//require(msg.sender == owner);
//require(msg.sender == 0x0);
//storedData = x + 2;
}
function set2(uint x) public {
storedData = x;
emit EventOnSet2(true, "hi");
}
function get() public view returns (uint retVal) {
return storedData;
}
function getS() public pure returns (string d) {
return "hello";
}
function setRegistar(address x) public {
registar = x;
}
}

View File

@ -9,79 +9,23 @@ module.exports = {
],
gas: "auto",
deploy: {
Ownable: {
deploy: false
},
SimpleStorage: {
fromIndex: 0,
args: [100],
onDeploy: ["SimpleStorage.methods.setRegistar(web3.eth.defaultAccount).send()"]
},
AnotherStorage: {
args: ["$SimpleStorage"]
},
Token: {
deploy: false,
args: [1000]
},
Test: {
onDeploy: ["Test.methods.changeAddress('$MyToken')", "Test.methods.changeENS('embark.eth')"]
},
MyToken: {
instanceOf: "Token"
},
MyToken2: {
instanceOf: "Token",
args: [200]
},
AlreadyDeployedToken: {
address: "0xece374063fe5cc7efbaca0a498477cada94e5ad6",
instanceOf: "Token"
},
MyToken3: {
instanceOf: "Tokn"
},
ContractArgs: {
args: {
initialValue: 123,
"_addresses": ["$MyToken2", "$SimpleStorage"]
}
},
SomeContract: {
deployIf: 'await MyToken.methods.isAvailable().call()',
deps: ['MyToken'],
args: [
["$MyToken2", "$SimpleStorage"],
100
]
},
ERC20: {
file: "zeppelin-solidity/contracts/token/ERC20/ERC20.sol"
},
SimpleStorageTest: {
file: "./some_folder/test_contract.sol",
args: [1000]
},
StandardToken: {
file: "https://github.com/status-im/contracts/blob/151-embark31/contracts/token/StandardToken.sol",
deploy: false
},
SimpleStorageWithHttpImport: {
fromIndex: 0,
args: [100]
}
},
},
afterDeploy: [
"Test.methods.changeAddress('$MyToken')",
"web3.eth.getAccounts((err, accounts) => Test.methods.changeAddress(accounts[0]))"
//"Test.methods.changeAddress('$MyToken')",
//"web3.eth.getAccounts((err, accounts) => Test.methods.changeAddress(accounts[0]))"
]
},
development: {
deploy: {
MyToken2: {
instanceOf: "Token",
args: [2000]
}
// MyToken2: {
// instanceOf: "Token",
// args: [2000]
// }
}
}
};

View File

@ -0,0 +1,87 @@
module.exports = {
default: {
dappConnection: [
"ws://localhost:8546",
"http://localhost:8550",
"http://localhost:8545",
"http://localhost:8550",
"$WEB3"
],
gas: "auto",
deploy: {
Ownable: {
deploy: false
},
SimpleStorage: {
fromIndex: 0,
args: [100],
onDeploy: ["SimpleStorage.methods.setRegistar(web3.eth.defaultAccount).send()"]
},
AnotherStorage: {
args: ["$SimpleStorage"]
},
Token: {
deploy: false,
args: [1000]
},
Test: {
onDeploy: ["Test.methods.changeAddress('$MyToken')", "Test.methods.changeENS('embark.eth')"]
},
MyToken: {
instanceOf: "Token"
},
MyToken2: {
instanceOf: "Token",
args: [200]
},
AlreadyDeployedToken: {
address: "0xece374063fe5cc7efbaca0a498477cada94e5ad6",
instanceOf: "Token"
},
MyToken3: {
instanceOf: "Tokn"
},
ContractArgs: {
args: {
initialValue: 123,
"_addresses": ["$MyToken2", "$SimpleStorage"]
}
},
SomeContract: {
deployIf: 'await MyToken.methods.isAvailable().call()',
deps: ['MyToken'],
args: [
["$MyToken2", "$SimpleStorage"],
100
]
},
ERC20: {
file: "zeppelin-solidity/contracts/token/ERC20/ERC20.sol"
},
SimpleStorageTest: {
file: "./some_folder/test_contract.sol",
args: [1000]
},
StandardToken: {
file: "https://github.com/status-im/contracts/blob/151-embark31/contracts/token/StandardToken.sol",
deploy: false
},
SimpleStorageWithHttpImport: {
fromIndex: 0,
args: [100]
}
},
afterDeploy: [
"Test.methods.changeAddress('$MyToken')",
"web3.eth.getAccounts((err, accounts) => Test.methods.changeAddress(accounts[0]))"
]
},
development: {
deploy: {
MyToken2: {
instanceOf: "Token",
args: [2000]
}
}
}
};

View File

@ -1,5 +1,5 @@
{
"contracts": ["app/contracts/**", "contracts/**"],
"contracts": ["app/contracts/**"],
"app": {
"js/jquery.js": "app/js/_vendor/jquery.min.js",
"js/bootstrap.js": "app/js/_vendor/bootstrap.min.js",

View File

@ -0,0 +1,32 @@
{
"contracts": ["app/contracts/**", "contracts/**"],
"app": {
"js/jquery.js": "app/js/_vendor/jquery.min.js",
"js/bootstrap.js": "app/js/_vendor/bootstrap.min.js",
"css/app.css": ["app/css/**"],
"images/": ["app/images/**"],
"js/app.js": ["app/js/index.js"],
"js/test.js": ["app/js/_vendor/jquery.min.js", "app/js/_vendor/async.min.js", "app/js/test.js"],
"index.html": "app/index.html",
"test.html": "app/test.html",
"test2.html": "app/test2.html",
"test3.html": "app/test3.haml"
},
"buildDir": "dist/",
"config": "config/",
"versions": {
"solc": "0.4.25",
"web3": "1.0.0-beta",
"ipfs-api": "17.2.7"
},
"plugins": {
"embarkjs-connector-web3": {}
},
"options": {
"solc": {
"optimize": true,
"optimize-runs": 200
}
},
"generationDir": "embarkArtifacts"
}

View File

@ -47,11 +47,11 @@ class BlockchainConnector {
});
});
self.events.setCommandHandler("blockchain:ready", self.onReady.bind(this));
// self.events.setCommandHandler("blockchain:ready", self.onReady.bind(this));
self.events.setCommandHandler("blockchain:web3:isReady", (cb) => {
cb(self.isWeb3Ready);
});
// self.events.setCommandHandler("blockchain:web3:isReady", (cb) => {
// cb(self.isWeb3Ready);
// });
self.events.setCommandHandler("blockchain:object", (cb) => {
cb(self);
@ -127,10 +127,11 @@ class BlockchainConnector {
};
this.provider = new Provider(providerOptions);
self.events.request("processes:launch", "blockchain", (err) => {
if (err) {
return self.logger.error(err);
}
// self.events.request("processes:launch", "blockchain", (err) => {
// if (err) {
// return self.logger.error(err);
// }
// setTimeout(() => {
self.provider.startWeb3Provider(async () => {
try {
const blockNumber = await self.web3.eth.getBlockNumber();
@ -165,7 +166,7 @@ class BlockchainConnector {
console.error(e);
}
});
});
// });
}
_setupVM(cb) {

View File

@ -37,6 +37,14 @@ class ContractsManager {
this.events.setCommandHandler("contracts:build", this.buildContracts.bind(this));
this.events.setCommandHandler('contracts:list', (cb) => {
cb(this.compileError, this.listContracts());
});
this.events.setCommandHandler('contracts:state', (cb) => {
cb(this.compileError, this.contractsState());
});
console.dir("---- contracts manager---- ")
// this.registerCommands()
// this.registerAPIs()
@ -52,10 +60,6 @@ class ContractsManager {
// });
// });
self.events.setCommandHandler('contracts:list', (cb) => {
cb(self.compileError, self.listContracts());
});
self.events.setCommandHandler('contracts:add', (contract) => {
this.contracts[contract.className] = contract;
});
@ -81,18 +85,6 @@ class ContractsManager {
cb();
});
self.events.on("deploy:contract:error", (_contract) => {
self.events.emit('contractsState', self.contractsState());
});
self.events.on("deploy:contract:deployed", (_contract) => {
self.events.emit('contractsState', self.contractsState());
});
self.events.on("deploy:contract:undeployed", (_contract) => {
self.events.emit('contractsState', self.contractsState());
});
this.events.setCommandHandler('setDashboardState', () => {
self.events.emit('contractsState', self.contractsState());
});
@ -558,7 +550,7 @@ class ContractsManager {
self.logger.trace("finished".underline);
console.dir("done!!")
done(err, self.contracts);
done(err, self.contracts, self.contractDependencies);
});
}

View File

@ -0,0 +1,398 @@
import { __ } from 'embark-i18n';
const async = require('async');
import {AddressUtils, toChecksumAddress} from 'embark-utils';
const {ZERO_ADDRESS} = AddressUtils;
// Check out definition 97 of the yellow paper: https://ethereum.github.io/yellowpaper/paper.pdf
const MAX_CONTRACT_BYTECODE_LENGTH = 24576;
const GANACHE_CLIENT_VERSION_NAME = "EthereumJS TestRPC";
class ContractDeployer {
constructor(options) {
this.logger = options.logger;
this.events = options.events;
this.plugins = options.plugins;
this.events.setCommandHandler('deploy:contract', (contract, cb) => {
this.checkAndDeployContract(contract, null, cb);
});
this.events.setCommandHandler('deploy:contract:object', (contract, cb) => {
this.checkAndDeployContract(contract, null, cb, true);
});
}
// TODO: determining the arguments could also be in a module since it's not
// part of a 'normal' contract deployment
determineArguments(suppliedArgs, contract, accounts, callback) {
const self = this;
let args = suppliedArgs;
if (!Array.isArray(args)) {
args = [];
let abi = contract.abiDefinition.find((abi) => abi.type === 'constructor');
for (let input of abi.inputs) {
let inputValue = suppliedArgs[input.name];
if (!inputValue) {
this.logger.error(__("{{inputName}} has not been defined for {{className}} constructor", {inputName: input.name, className: contract.className}));
}
args.push(inputValue || "");
}
}
function parseArg(arg, cb) {
const match = arg.match(/\$accounts\[([0-9]+)]/);
if (match) {
if (!accounts[match[1]]) {
return cb(__('No corresponding account at index %d', match[1]));
}
return cb(null, accounts[match[1]]);
}
let contractName = arg.substr(1);
self.events.request('contracts:contract', contractName, (referedContract) => {
// Because we're referring to a contract that is not being deployed (ie. an interface),
// we still need to provide a valid address so that the ABI checker won't fail.
cb(null, (referedContract.deployedAddress || ZERO_ADDRESS));
});
}
function checkArgs(argus, cb) {
async.map(argus, (arg, nextEachCb) => {
if (arg[0] === "$") {
return parseArg(arg, nextEachCb);
}
if (Array.isArray(arg)) {
return checkArgs(arg, nextEachCb);
}
self.events.request('ens:isENSName', arg, (isENSName) => {
if (isENSName) {
return self.events.request("ens:resolve", arg, (err, address) => {
if (err) {
return nextEachCb(err);
}
nextEachCb(err, address);
});
}
nextEachCb(null, arg);
});
}, cb);
}
checkArgs(args, callback);
}
checkAndDeployContract(contract, params, callback, returnObject) {
console.dir("= checkAndDeployContract: " + contract.className);
let self = this;
contract.error = false;
let accounts = [];
let deploymentAccount;
if (contract.deploy === false) {
self.events.emit("deploy:contract:undeployed", contract);
return callback();
}
async.waterfall([
function checkContractBytesize(next) {
if (!contract.code) {
return next();
}
const code = (contract.code.indexOf('0x') === 0) ? contract.code.substr(2) : contract.code;
const contractCodeLength = Buffer.from(code, 'hex').toString().length;
if(contractCodeLength > MAX_CONTRACT_BYTECODE_LENGTH) {
return next(new Error(`Bytecode for ${contract.className} contract is too large. Not deploying.`));
}
next();
},
// TODO: it should just ask blockchain client to deploy contract X but shouldn't
// know details how this contract is deployed
// function requestBlockchainConnector(next) {
// self.events.request("blockchain:object", (blockchain) => {
// self.blockchain = blockchain;
// next();
// });
// },
// TODO: can potentially go to a beforeDeploy plugin
function getAccounts(next) {
deploymentAccount = self.blockchain.defaultAccount();
self.events.request('blockchain:provider:contract:accounts:get', (_err, blockchainAccounts) => {
accounts = blockchainAccounts;
// applying deployer account configuration, if any
if (typeof contract.fromIndex === 'number') {
deploymentAccount = accounts[contract.fromIndex];
if (deploymentAccount === undefined) {
return next(__("error deploying") + " " + contract.className + ": " + __("no account found at index") + " " + contract.fromIndex + __(" check the config"));
}
}
if (typeof contract.from === 'string' && typeof contract.fromIndex !== 'undefined') {
self.logger.warn(__('Both "from" and "fromIndex" are defined for contract') + ' "' + contract.className + '". ' + __('Using "from" as deployer account.'));
}
if (typeof contract.from === 'string') {
deploymentAccount = contract.from;
}
deploymentAccount = deploymentAccount || accounts[0];
contract.deploymentAccount = deploymentAccount;
next();
});
},
function applyArgumentPlugins(next) {
self.plugins.emitAndRunActionsForEvent('deploy:contract:arguments', {contract: contract}, (_params) => {
next();
});
},
function _determineArguments(next) {
self.determineArguments(params || contract.args, contract, accounts, (err, realArgs) => {
if (err) {
return next(err);
}
contract.realArgs = realArgs;
next();
});
},
function deployIt(next) {
let skipBytecodeCheck = false;
if (contract.address !== undefined) {
try {
toChecksumAddress(contract.address);
} catch(e) {
self.logger.error(__("error deploying %s", contract.className));
self.logger.error(e.message);
contract.error = e.message;
self.events.emit("deploy:contract:error", contract);
return next(e.message);
}
contract.deployedAddress = contract.address;
skipBytecodeCheck = true;
}
if (returnObject) {
return self.deployContract(contract, next, returnObject);
}
console.dir("== emitAndRunActionsForEvent / should Deploy");
self.plugins.emitAndRunActionsForEvent('deploy:contract:shouldDeploy', {contract: contract, shouldDeploy: true}, function(_err, params) {
let trackedContract = params.contract;
if (!params.shouldDeploy) {
return self.willNotDeployContract(contract, trackedContract, next);
}
if (!trackedContract.address) {
return self.deployContract(contract, next);
}
// deploy the contract regardless if track field is defined and set to false
if (trackedContract.track === false) {
self.logFunction(contract)(contract.className.bold.cyan + __(" will be redeployed").green);
return self.deployContract(contract, next);
}
self.blockchain.getCode(trackedContract.address, function(getCodeErr, codeInChain) {
if (getCodeErr) {
return next(getCodeErr);
}
if (codeInChain.length > 3 || skipBytecodeCheck) { // it is "0x" or "0x0" for empty code, depending on web3 version
self.contractAlreadyDeployed(contract, trackedContract, next);
} else {
self.deployContract(contract, next);
}
});
});
}
], (err,results) => {
callback(err, results);
});
}
willNotDeployContract(contract, trackedContract, callback) {
contract.deploy = false;
this.events.emit("deploy:contract:undeployed", contract);
callback();
}
contractAlreadyDeployed(contract, trackedContract, callback) {
console.dir("--> contractAlreadyDeployed")
this.logFunction(contract)(contract.className.bold.cyan + __(" already deployed at ").green + trackedContract.address.bold.cyan);
contract.deployedAddress = trackedContract.address;
this.events.emit("deploy:contract:deployed", contract);
this.plugins.runActionsForEvent('deploy:contract:deployed', {contract: contract}, (err) => {
callback(err);
});
}
logFunction(contract) {
return contract.silent ? this.logger.trace.bind(this.logger) : this.logger.info.bind(this.logger);
}
deployContract(contract, callback, returnObject) {
console.dir("deployContract")
let self = this;
let deployObject;
async.waterfall([
function doLinking(next) {
console.dir("= doLinking")
if (!contract.linkReferences || !Object.keys(contract.linkReferences).length) {
return next();
}
let contractCode = contract.code;
let offset = 0;
// TODO: linking can/should be done differently
async.eachLimit(contract.linkReferences, 1, (fileReference, eachCb1) => {
async.eachOfLimit(fileReference, 1, (references, libName, eachCb2) => {
self.events.request("contracts:contract", libName, (libContract) => {
async.eachLimit(references, 1, (reference, eachCb3) => {
if (!libContract) {
return eachCb3(new Error(__('{{contractName}} has a link to the library {{libraryName}}, but it was not found. Is it in your contract folder?'), {
contractName: contract.className,
libraryName: libName
}));
}
let libAddress = libContract.deployedAddress;
if (!libAddress) {
return eachCb3(new Error(__("{{contractName}} needs {{libraryName}} but an address was not found, did you deploy it or configured an address?", {
contractName: contract.className,
libraryName: libName
})));
}
libAddress = libAddress.substr(2).toLowerCase();
// Multiplying by two because the original pos and length are in bytes, but we have an hex string
contractCode = contractCode.substring(0, (reference.start * 2) + offset) + libAddress + contractCode.substring((reference.start * 2) + offset + (reference.length * 2));
// Calculating an offset in case the length is at some point different than the address length
offset += libAddress.length - (reference.length * 2);
eachCb3();
}, eachCb2);
});
}, eachCb1);
}, (err) => {
contract.code = contractCode;
next(err);
});
},
function applyBeforeDeploy(next) {
console.dir("= applyBeforeDeploy")
self.plugins.emitAndRunActionsForEvent('deploy:contract:beforeDeploy', {contract: contract}, (_params) => {
next();
});
},
function getGasPriceForNetwork(next) {
console.dir("= getGasPriceForNetwork")
self.events.request("blockchain:gasPrice", (err, gasPrice) => {
if (err) {
return next(new Error(__("could not get the gas price")));
}
contract.gasPrice = contract.gasPrice || gasPrice;
next();
});
},
function createDeployObject(next) {
console.dir("= createDeployObject")
let contractCode = contract.code;
let contractObject = self.blockchain.ContractObject({abi: contract.abiDefinition});
let contractParams = (contract.realArgs || contract.args).slice();
try {
const dataCode = contractCode.startsWith('0x') ? contractCode : "0x" + contractCode;
deployObject = self.blockchain.deployContractObject(contractObject, {arguments: contractParams, data: dataCode});
if (returnObject) {
return callback(null, deployObject);
}
} catch(e) {
if (e.message.indexOf('Invalid number of parameters for "undefined"') >= 0) {
return next(new Error(__("attempted to deploy %s without specifying parameters", contract.className)) + ". " + __("check if there are any params defined for this contract in this environment in the contracts configuration file"));
}
return next(new Error(e));
}
next();
},
function estimateCorrectGas(next) {
self.blockchain.getClientVersion((err, version) => {
if (version.split('/')[0] === GANACHE_CLIENT_VERSION_NAME) {
// This is Ganache's gas limit. We subtract 1 so we don't reach the limit.
//
// We do this because Ganache's gas estimates are wrong (contract creation
// has a base cost of 53k, not 21k, so it sometimes results in out of gas
// errors.)
contract.gas = 6721975 - 1;
} else if (contract.gas === 'auto' || !contract.gas) {
return self.blockchain.estimateDeployContractGas(deployObject, (err, gasValue) => {
if (err) {
return next(err);
}
let increase_per = 1 + (Math.random() / 10.0);
contract.gas = Math.floor(gasValue * increase_per);
next();
});
}
next();
});
},
function deployTheContract(next) {
console.dir("= deployTheContract " + contract.className)
let estimatedCost = contract.gas * contract.gasPrice;
self.blockchain.deployContractFromObject(deployObject, {
from: contract.deploymentAccount,
gas: contract.gas,
gasPrice: contract.gasPrice
}, function(error, receipt) {
console.dir("--> contract deployed")
console.dir(error)
console.dir(receipt)
if (error) {
contract.error = error.message;
self.events.emit("deploy:contract:error", contract);
if (error.message && error.message.indexOf('replacement transaction underpriced') !== -1) {
self.logger.warn("replacement transaction underpriced: This warning typically means a transaction exactly like this one is still pending on the blockchain");
}
return next(new Error("error deploying =" + contract.className + "= due to error: " + error.message));
}
self.logFunction(contract)(`${contract.className.bold.cyan} ${__('deployed at').green} ${receipt.contractAddress.bold.cyan} ${__("using").green} ${receipt.gasUsed} ${__("gas").green} (txHash: ${receipt.transactionHash.bold.cyan})`);
contract.deployedAddress = receipt.contractAddress;
contract.transactionHash = receipt.transactionHash;
receipt.className = contract.className;
if(receipt) self.events.emit("deploy:contract:receipt", receipt);
self.events.emit("deploy:contract:deployed", contract);
// console.dir("__registerContract")
// self.registerContract(contract, () => {
console.dir("__runActionsForEvent deploy:contract:deployed")
self.plugins.runActionsForEvent('deploy:contract:deployed', {contract: contract}, (err) => {
console.dir("result __runActionsForEvent deploy:contract:deployed")
if (err) {
console.dir(err)
return next(err);
}
next(null, receipt);
});
}, hash => {
self.logFunction(contract)(__("deploying") + " " + contract.className.bold.cyan + " " + __("with").green + " " + contract.gas + " " + __("gas at the price of").green + " " + contract.gasPrice + " " + __("Wei, estimated cost:").green + " " + estimatedCost + " Wei".green + " (txHash: " + hash.bold.cyan + ")");
});
}
], (__err, __results) => {
console.dir("--- deployed Contract")
callback(__err, __results)
});
}
}
module.exports = ContractDeployer;

View File

@ -0,0 +1,222 @@
import { __ } from 'embark-i18n';
const async = require('async');
// async._waterfall = async.waterfall;
// let filename = "index.js";
// async.waterfall = function (_tasks, callback) {
// let tasks = _tasks.map(function (t) {
// let fn = function () {
// console.log("async " + (new Error()).stack.split("\n")[1] + ": " + t.name);
// t.apply(t, arguments);
// };
// return fn;
// });
// async._waterfall(tasks, callback);
// };
const ContractDeployer = require('./contract_deployer.js');
const cloneDeep = require('clone-deep');
const constants = require('embark-core/constants');
class DeployManager {
constructor(embark, options) {
const self = this;
this.config = embark.config;
this.logger = embark.logger;
this.blockchainConfig = this.config.blockchainConfig;
this.events = embark.events;
this.plugins = options.plugins;
// this.blockchain = options.blockchain;
// this.gasLimit = 6000000;
this.fatalErrors = false;
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('deployment:contracts:deploy', (contractsList, contractDependencies, cb) => {
self.deployContracts(contractsList, contractDependencies, cb);
});
// 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(contracts, contractDependencies, done) {
let self = this;
// self.events.request('contracts:dependencies', (err, contractDependencies) => {
// self.events.request('contracts:list', (err, contracts) => {
// if (err) {
// return done(err);
// }
self.logger.info(__("deploying contracts"));
async.waterfall([
function (next) {
self.logger.info(__('Executing pre-deploy actions...'));
self.plugins.emitAndRunActionsForEvent("deploy:beforeAll", (err) => {
// console.dir("== err")
// console.dir(err)
// TODO: err is a function for some reason
// if (err) {
// return next(err);
// }
self.logger.info(__('Pre-deploy actions done. Deploying contracts'));
next();
});
},
function (next) {
const contractDeploys = {};
const errors = [];
console.dir("=== contracts")
console.dir(contracts.map((x) => x.className))
contracts.forEach(contract => {
function deploy(result, callback) {
if (typeof result === 'function') {
callback = result;
}
// contract._gasLimit = self.gasLimit;
self.events.request('deploy:contract', contract, (err) => {
console.dir("contract deployed " + contract.className)
if (err) {
console.dir("== err deploying contract");
console.dir(err);
contract.error = err.message || err;
if (contract.error === constants.blockchain.gasAllowanceError) {
self.logger.error(`[${contract.className}]: ${constants.blockchain.gasAllowanceErrorMessage}`);
} else {
self.logger.error(`[${contract.className}]: ${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);
});
console.dir("== async.auto");
console.dir(Object.keys(contractDeploys));
console.dir(contractDeploys);
async.auto(contractDeploys, function (_err, _results) {
if (_err) {
console.dir("error deploying contracts")
console.dir(_err)
}
if (errors.length) {
_err = __("Error deploying contracts. Please fix errors to continue.");
self.logger.error(_err);
self.events.emit("outputError", __("Error deploying contracts, please check console"));
return next(_err);
}
if (contracts.length === 0) {
self.logger.info(__("no contracts found"));
return next();
}
self.logger.info(__("finished deploying contracts"));
next(err);
});
}
], (err) => {
console.dir("==== finished deploying")
if (err) {
self.logger.error(err);
}
done(err);
});
// });
// });
}
// TODO: can be merged into deployAll
deployContracts(contractsList, contractDependencies, done) {
let self = this;
// if (self.blockchainConfig === {} || self.blockchainConfig.enabled === false) {
// self.logger.info(__("Blockchain component is disabled in the config").underline);
// this.events.emit('blockchainDisabled', {});
// return done();
// }
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);
// });
// },
// // TODO: shouldn't be necessary
// function checkCompileOnly(callback) {
// if (self.onlyCompile) {
// self.events.emit('contractsDeployed');
// return done();
// }
// return callback();
// },
// // TODO: could be implemented as an event (beforeDeployAll)
// function checkIsConnectedToBlockchain(callback) {
// self.blockchain.onReady((err) => {
// callback(err);
// });
// },
// // TODO: this can be done on the fly or as part of the initialization
// function determineDefaultAccount(callback) {
// self.blockchain.determineDefaultAccount((err) => {
// callback(err);
// });
// },
function deployAllContracts(callback) {
self.deployAll(contractsList, contractDependencies, function (err) {
if (!err) {
self.events.emit('contractsDeployed');
}
if (err && self.fatalErrors) {
return callback(err);
}
callback();
});
},
function runAfterDeploy(callback) {
self.plugins.emitAndRunActionsForEvent('contracts:deploy:afterAll', callback);
}
], function (err, _result) {
done(err);
});
}
}
module.exports = DeployManager;

View File

@ -1,391 +1,53 @@
import { __ } from 'embark-i18n';
const async = require('async');
import {AddressUtils, toChecksumAddress} from 'embark-utils';
const {ZERO_ADDRESS} = AddressUtils;
// Check out definition 97 of the yellow paper: https://ethereum.github.io/yellowpaper/paper.pdf
const MAX_CONTRACT_BYTECODE_LENGTH = 24576;
const GANACHE_CLIENT_VERSION_NAME = "EthereumJS TestRPC";
class ContractDeployer {
constructor(options) {
this.logger = options.logger;
this.events = options.events;
this.plugins = options.plugins;
this.deployer = {};
this.events.setCommandHandler("deployment:deployer:register", (blockchainType, deployerCb) => {
this.deployer[blockchainType] = deployerCb
});
this.events.setCommandHandler('deploy:contract', (contract, cb) => {
this.checkAndDeployContract(contract, null, cb);
});
this.events.setCommandHandler('deploy:contract:object', (contract, cb) => {
this.checkAndDeployContract(contract, null, cb, true);
});
this.events.setCommandHandler('deployment:contract:deploy', this.deployContract.bind(this));
}
// TODO: determining the arguments could also be in a module since it's not
// part of a 'normal' contract deployment
determineArguments(suppliedArgs, contract, accounts, callback) {
const self = this;
let args = suppliedArgs;
if (!Array.isArray(args)) {
args = [];
let abi = contract.abiDefinition.find((abi) => abi.type === 'constructor');
for (let input of abi.inputs) {
let inputValue = suppliedArgs[input.name];
if (!inputValue) {
this.logger.error(__("{{inputName}} has not been defined for {{className}} constructor", {inputName: input.name, className: contract.className}));
}
args.push(inputValue || "");
}
}
function parseArg(arg, cb) {
const match = arg.match(/\$accounts\[([0-9]+)]/);
if (match) {
if (!accounts[match[1]]) {
return cb(__('No corresponding account at index %d', match[1]));
}
return cb(null, accounts[match[1]]);
}
let contractName = arg.substr(1);
self.events.request('contracts:contract', contractName, (referedContract) => {
// Because we're referring to a contract that is not being deployed (ie. an interface),
// we still need to provide a valid address so that the ABI checker won't fail.
cb(null, (referedContract.deployedAddress || ZERO_ADDRESS));
});
}
function checkArgs(argus, cb) {
async.map(argus, (arg, nextEachCb) => {
if (arg[0] === "$") {
return parseArg(arg, nextEachCb);
}
if (Array.isArray(arg)) {
return checkArgs(arg, nextEachCb);
}
self.events.request('ens:isENSName', arg, (isENSName) => {
if (isENSName) {
return self.events.request("ens:resolve", arg, (err, address) => {
if (err) {
return nextEachCb(err);
}
nextEachCb(err, address);
});
}
nextEachCb(null, arg);
});
}, cb);
}
checkArgs(args, callback);
}
checkAndDeployContract(contract, params, callback, returnObject) {
console.dir("= checkAndDeployContract: " + contract.className);
let self = this;
contract.error = false;
let accounts = [];
let deploymentAccount;
deployContract(contract, callback) {
if (contract.deploy === false) {
self.events.emit("deploy:contract:undeployed", contract);
this.events.emit("deployment:contract:undeployed", contract);
return callback();
}
async.waterfall([
function checkContractBytesize(next) {
if (!contract.code) {
(next) => {
// self.plugins.emitAndRunActionsForEvent('deployment:contract:arguments', {contract: contract}, (_params) => {
this.plugins.emitAndRunActionsForEvent('deployment:contract:shouldDeploy', {contract: contract, shouldDeploy: true}, (_params) => {
next();
});
},
(next) => {
if (contract.deploy === false) {
this.events.emit("deployment:contract:undeployed", contract);
return next();
}
const code = (contract.code.indexOf('0x') === 0) ? contract.code.substr(2) : contract.code;
const contractCodeLength = Buffer.from(code, 'hex').toString().length;
if(contractCodeLength > MAX_CONTRACT_BYTECODE_LENGTH) {
return next(new Error(`Bytecode for ${contract.className} contract is too large. Not deploying.`));
}
next();
console.dir("deploying contract");
console.dir(contract.className);
// this.deployer[contract.blockchainType].apply(this.deployer, [contract, next])
this.deployer["ethereum"].apply(this.deployer, [contract, next])
// next();
},
function requestBlockchainConnector(next) {
self.events.request("blockchain:object", (blockchain) => {
self.blockchain = blockchain;
(next) => {
console.dir("-------> contract deployed")
if (contract.deploy === false) return next();
console.dir("-------> contract deployed 2")
this.plugins.emitAndRunActionsForEvent('deployment:contract:deployed', {contract: contract}, (_params) => {
next();
});
},
// TODO: can potentially go to a beforeDeploy plugin
function getAccounts(next) {
deploymentAccount = self.blockchain.defaultAccount();
self.events.request('blockchain:provider:contract:accounts:get', (_err, blockchainAccounts) => {
accounts = blockchainAccounts;
// applying deployer account configuration, if any
if (typeof contract.fromIndex === 'number') {
deploymentAccount = accounts[contract.fromIndex];
if (deploymentAccount === undefined) {
return next(__("error deploying") + " " + contract.className + ": " + __("no account found at index") + " " + contract.fromIndex + __(" check the config"));
}
}
if (typeof contract.from === 'string' && typeof contract.fromIndex !== 'undefined') {
self.logger.warn(__('Both "from" and "fromIndex" are defined for contract') + ' "' + contract.className + '". ' + __('Using "from" as deployer account.'));
}
if (typeof contract.from === 'string') {
deploymentAccount = contract.from;
}
deploymentAccount = deploymentAccount || accounts[0];
contract.deploymentAccount = deploymentAccount;
next();
});
},
function applyArgumentPlugins(next) {
self.plugins.emitAndRunActionsForEvent('deploy:contract:arguments', {contract: contract}, (_params) => {
next();
});
},
function _determineArguments(next) {
self.determineArguments(params || contract.args, contract, accounts, (err, realArgs) => {
if (err) {
return next(err);
}
contract.realArgs = realArgs;
next();
});
},
function deployIt(next) {
let skipBytecodeCheck = false;
if (contract.address !== undefined) {
try {
toChecksumAddress(contract.address);
} catch(e) {
self.logger.error(__("error deploying %s", contract.className));
self.logger.error(e.message);
contract.error = e.message;
self.events.emit("deploy:contract:error", contract);
return next(e.message);
}
contract.deployedAddress = contract.address;
skipBytecodeCheck = true;
}
if (returnObject) {
return self.deployContract(contract, next, returnObject);
}
console.dir("== emitAndRunActionsForEvent / should Deploy");
self.plugins.emitAndRunActionsForEvent('deploy:contract:shouldDeploy', {contract: contract, shouldDeploy: true}, function(_err, params) {
let trackedContract = params.contract;
if (!params.shouldDeploy) {
return self.willNotDeployContract(contract, trackedContract, next);
}
if (!trackedContract.address) {
return self.deployContract(contract, next);
}
// deploy the contract regardless if track field is defined and set to false
if (trackedContract.track === false) {
self.logFunction(contract)(contract.className.bold.cyan + __(" will be redeployed").green);
return self.deployContract(contract, next);
}
self.blockchain.getCode(trackedContract.address, function(getCodeErr, codeInChain) {
if (getCodeErr) {
return next(getCodeErr);
}
if (codeInChain.length > 3 || skipBytecodeCheck) { // it is "0x" or "0x0" for empty code, depending on web3 version
self.contractAlreadyDeployed(contract, trackedContract, next);
} else {
self.deployContract(contract, next);
}
});
});
}
], (err,results) => {
callback(err, results);
});
}
willNotDeployContract(contract, trackedContract, callback) {
contract.deploy = false;
this.events.emit("deploy:contract:undeployed", contract);
callback();
}
contractAlreadyDeployed(contract, trackedContract, callback) {
console.dir("--> contractAlreadyDeployed")
this.logFunction(contract)(contract.className.bold.cyan + __(" already deployed at ").green + trackedContract.address.bold.cyan);
contract.deployedAddress = trackedContract.address;
this.events.emit("deploy:contract:deployed", contract);
this.plugins.runActionsForEvent('deploy:contract:deployed', {contract: contract}, (err) => {
callback(err);
});
}
logFunction(contract) {
return contract.silent ? this.logger.trace.bind(this.logger) : this.logger.info.bind(this.logger);
}
deployContract(contract, callback, returnObject) {
console.dir("deployContract")
let self = this;
let deployObject;
async.waterfall([
function doLinking(next) {
console.dir("= doLinking")
if (!contract.linkReferences || !Object.keys(contract.linkReferences).length) {
return next();
}
let contractCode = contract.code;
let offset = 0;
async.eachLimit(contract.linkReferences, 1, (fileReference, eachCb1) => {
async.eachOfLimit(fileReference, 1, (references, libName, eachCb2) => {
self.events.request("contracts:contract", libName, (libContract) => {
async.eachLimit(references, 1, (reference, eachCb3) => {
if (!libContract) {
return eachCb3(new Error(__('{{contractName}} has a link to the library {{libraryName}}, but it was not found. Is it in your contract folder?'), {
contractName: contract.className,
libraryName: libName
}));
}
let libAddress = libContract.deployedAddress;
if (!libAddress) {
return eachCb3(new Error(__("{{contractName}} needs {{libraryName}} but an address was not found, did you deploy it or configured an address?", {
contractName: contract.className,
libraryName: libName
})));
}
libAddress = libAddress.substr(2).toLowerCase();
// Multiplying by two because the original pos and length are in bytes, but we have an hex string
contractCode = contractCode.substring(0, (reference.start * 2) + offset) + libAddress + contractCode.substring((reference.start * 2) + offset + (reference.length * 2));
// Calculating an offset in case the length is at some point different than the address length
offset += libAddress.length - (reference.length * 2);
eachCb3();
}, eachCb2);
});
}, eachCb1);
}, (err) => {
contract.code = contractCode;
next(err);
});
},
function applyBeforeDeploy(next) {
console.dir("= applyBeforeDeploy")
self.plugins.emitAndRunActionsForEvent('deploy:contract:beforeDeploy', {contract: contract}, (_params) => {
next();
});
},
function getGasPriceForNetwork(next) {
console.dir("= getGasPriceForNetwork")
self.events.request("blockchain:gasPrice", (err, gasPrice) => {
if (err) {
return next(new Error(__("could not get the gas price")));
}
contract.gasPrice = contract.gasPrice || gasPrice;
next();
});
},
function createDeployObject(next) {
console.dir("= createDeployObject")
let contractCode = contract.code;
let contractObject = self.blockchain.ContractObject({abi: contract.abiDefinition});
let contractParams = (contract.realArgs || contract.args).slice();
try {
const dataCode = contractCode.startsWith('0x') ? contractCode : "0x" + contractCode;
deployObject = self.blockchain.deployContractObject(contractObject, {arguments: contractParams, data: dataCode});
if (returnObject) {
return callback(null, deployObject);
}
} catch(e) {
if (e.message.indexOf('Invalid number of parameters for "undefined"') >= 0) {
return next(new Error(__("attempted to deploy %s without specifying parameters", contract.className)) + ". " + __("check if there are any params defined for this contract in this environment in the contracts configuration file"));
}
return next(new Error(e));
}
next();
},
function estimateCorrectGas(next) {
self.blockchain.getClientVersion((err, version) => {
if (version.split('/')[0] === GANACHE_CLIENT_VERSION_NAME) {
// This is Ganache's gas limit. We subtract 1 so we don't reach the limit.
//
// We do this because Ganache's gas estimates are wrong (contract creation
// has a base cost of 53k, not 21k, so it sometimes results in out of gas
// errors.)
contract.gas = 6721975 - 1;
} else if (contract.gas === 'auto' || !contract.gas) {
return self.blockchain.estimateDeployContractGas(deployObject, (err, gasValue) => {
if (err) {
return next(err);
}
let increase_per = 1 + (Math.random() / 10.0);
contract.gas = Math.floor(gasValue * increase_per);
next();
});
}
next();
});
},
function deployTheContract(next) {
console.dir("= deployTheContract " + contract.className)
let estimatedCost = contract.gas * contract.gasPrice;
self.blockchain.deployContractFromObject(deployObject, {
from: contract.deploymentAccount,
gas: contract.gas,
gasPrice: contract.gasPrice
}, function(error, receipt) {
console.dir("--> contract deployed")
console.dir(error)
console.dir(receipt)
if (error) {
contract.error = error.message;
self.events.emit("deploy:contract:error", contract);
if (error.message && error.message.indexOf('replacement transaction underpriced') !== -1) {
self.logger.warn("replacement transaction underpriced: This warning typically means a transaction exactly like this one is still pending on the blockchain");
}
return next(new Error("error deploying =" + contract.className + "= due to error: " + error.message));
}
self.logFunction(contract)(`${contract.className.bold.cyan} ${__('deployed at').green} ${receipt.contractAddress.bold.cyan} ${__("using").green} ${receipt.gasUsed} ${__("gas").green} (txHash: ${receipt.transactionHash.bold.cyan})`);
contract.deployedAddress = receipt.contractAddress;
contract.transactionHash = receipt.transactionHash;
receipt.className = contract.className;
if(receipt) self.events.emit("deploy:contract:receipt", receipt);
self.events.emit("deploy:contract:deployed", contract);
// console.dir("__registerContract")
// self.registerContract(contract, () => {
console.dir("__runActionsForEvent deploy:contract:deployed")
self.plugins.runActionsForEvent('deploy:contract:deployed', {contract: contract}, (err) => {
console.dir("result __runActionsForEvent deploy:contract:deployed")
if (err) {
console.dir(err)
return next(err);
}
next(null, receipt);
});
}, hash => {
self.logFunction(contract)(__("deploying") + " " + contract.className.bold.cyan + " " + __("with").green + " " + contract.gas + " " + __("gas at the price of").green + " " + contract.gasPrice + " " + __("Wei, estimated cost:").green + " " + estimatedCost + " Wei".green + " (txHash: " + hash.bold.cyan + ")");
});
}
], (__err, __results) => {
console.dir("--- deployed Contract")
callback(__err, __results)
});
], callback);
}
}

View File

@ -1,221 +1,100 @@
import { __ } from 'embark-i18n';
const async = require('async');
// async._waterfall = async.waterfall;
// let filename = "index.js";
// async.waterfall = function (_tasks, callback) {
// let tasks = _tasks.map(function (t) {
// let fn = function () {
// console.log("async " + (new Error()).stack.split("\n")[1] + ": " + t.name);
// t.apply(t, arguments);
// };
// return fn;
// });
// async._waterfall(tasks, callback);
// };
const ContractDeployer = require('./contract_deployer.js');
const cloneDeep = require('clone-deep');
const constants = require('embark-core/constants');
class DeployManager {
class Deployment {
constructor(embark, options) {
const self = this;
this.config = embark.config;
this.events = embark.events;
this.logger = embark.logger;
this.plugins = options.plugins;
this.blockchainConfig = this.config.blockchainConfig;
this.events = embark.events;
this.plugins = options.plugins;
this.blockchain = options.blockchain;
this.gasLimit = 6000000;
this.fatalErrors = false;
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('deployment:contracts:deploy', (contractsList, contractDependencies, cb) => {
self.deployContracts(contractsList, contractDependencies, cb);
this.deployContracts(contractsList, contractDependencies, cb);
});
}
// this.events.setCommandHandler('deploy:setGasLimit', (gasLimit) => {
// self.gasLimit = gasLimit;
// });
deployContracts(contracts, contractDependencies, done) {
this.logger.info(__("deploying contracts"));
async.waterfall([
// TODO used to be called this.plugins.emitAndRunActionsForEvent("deploy:beforeAll", (err) => {
(next) => { this.plugins.emitAndRunActionsForEvent('deployment:deployContracts:beforeAll', () => { next() }); },
(next) => { this.deployAll(contracts, contractDependencies, () => { next() }); },
(next) => {
this.events.emit('contractsDeployed');
this.plugins.emitAndRunActionsForEvent('deployment:deployContracts:afterAll', () => { next() });
console.dir("==== finished deploying");
}
], done);
}
// 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);
// });
deployContract(contract, callback) {
console.dir("requesting to deploy contract")
this.events.request('deployment:contract:deploy', contract, (err) => {
if (err) {
contract.error = err.message || err;
if (contract.error === constants.blockchain.gasAllowanceError) {
this.logger.error(`[${contract.className}]: ${constants.blockchain.gasAllowanceErrorMessage}`);
} else {
this.logger.error(`[${contract.className}]: ${err.message || err}`);
}
errors.push(err);
}
callback();
});
}
deployAll(contracts, contractDependencies, done) {
let self = this;
const self = this;
console.dir("doing deployAll")
const contractDeploys = {};
const errors = [];
// self.events.request('contracts:dependencies', (err, contractDependencies) => {
// self.events.request('contracts:list', (err, contracts) => {
// if (err) {
// return done(err);
// }
self.logger.info(__("deploying contracts"));
async.waterfall([
function (next) {
self.logger.info(__('Executing pre-deploy actions...'));
self.plugins.emitAndRunActionsForEvent("deploy:beforeAll", (err) => {
// console.dir("== err")
// console.dir(err)
// TODO: err is a function for some reason
// if (err) {
// return next(err);
// }
self.logger.info(__('Pre-deploy actions done. Deploying contracts'));
next();
});
},
function (next) {
const contractDeploys = {};
const errors = [];
console.dir("=== contracts")
console.dir(contracts.map((x) => x.className))
contracts.forEach(contract => {
function deploy(result, callback) {
if (typeof result === 'function') {
callback = result;
}
contract._gasLimit = self.gasLimit;
self.events.request('deploy:contract', contract, (err) => {
console.dir("contract deployed " + contract.className)
if (err) {
console.dir("== err deploying contract");
console.dir(err);
contract.error = err.message || err;
if (contract.error === constants.blockchain.gasAllowanceError) {
self.logger.error(`[${contract.className}]: ${constants.blockchain.gasAllowanceErrorMessage}`);
} else {
self.logger.error(`[${contract.className}]: ${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);
});
console.dir("== async.auto");
console.dir(Object.keys(contractDeploys));
console.dir(contractDeploys);
async.auto(contractDeploys, function (_err, _results) {
if (_err) {
console.dir("error deploying contracts")
console.dir(_err)
}
if (errors.length) {
_err = __("Error deploying contracts. Please fix errors to continue.");
self.logger.error(_err);
self.events.emit("outputError", __("Error deploying contracts, please check console"));
return next(_err);
}
if (contracts.length === 0) {
self.logger.info(__("no contracts found"));
return next();
}
self.logger.info(__("finished deploying contracts"));
next(err);
});
Object.values(contracts).forEach((contract) => {
function deploy(result, callback) {
console.dir("== deploy")
if (typeof result === 'function') callback = result;
self.deployContract(contract, callback);
}
], (err) => {
console.dir("==== finished deploying")
if (err) {
self.logger.error(err);
const className = contract.className;
if (!contractDependencies[className] || contractDependencies[className].length === 0) {
contractDeploys[className] = deploy;
return;
}
done(err);
});
// });
// });
}
contractDeploys[className] = cloneDeep(contractDependencies[className]);
contractDeploys[className].push(deploy);
})
deployContracts(contractsList, contractDependencies, done) {
let self = this;
if (self.blockchainConfig === {} || self.blockchainConfig.enabled === false) {
self.logger.info(__("Blockchain component is disabled in the config").underline);
this.events.emit('blockchainDisabled', {});
return done();
}
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);
});
},
// TODO: shouldn't be necessary
function checkCompileOnly(callback) {
if (self.onlyCompile) {
self.events.emit('contractsDeployed');
return done();
}
return callback();
},
// TODO: could be implemented as an event (beforeDeployAll)
function checkIsConnectedToBlockchain(callback) {
self.blockchain.onReady((err) => {
callback(err);
});
},
// TODO: this can be done on the fly or as part of the initialization
function determineDefaultAccount(callback) {
self.blockchain.determineDefaultAccount((err) => {
callback(err);
});
},
function deployAllContracts(callback) {
self.deployAll(contractsList, contractDependencies, function (err) {
if (!err) {
self.events.emit('contractsDeployed');
}
if (err && self.fatalErrors) {
return callback(err);
}
callback();
});
},
function runAfterDeploy(callback) {
self.plugins.emitAndRunActionsForEvent('contracts:deploy:afterAll', callback);
async.auto(contractDeploys, (_err, _results) => {
if (_err) {
console.dir("error deploying contracts")
console.dir(_err)
}
], function (err, _result) {
done(err);
if (errors.length) {
_err = __("Error deploying contracts. Please fix errors to continue.");
this.logger.error(_err);
this.events.emit("outputError", __("Error deploying contracts, please check console"));
return done(_err);
}
if (contracts.length === 0) {
this.logger.info(__("no contracts found"));
return done();
}
this.logger.info(__("finished deploying contracts"));
done(_err);
});
}
}
module.exports = DeployManager;
module.exports = Deployment;

View File

@ -14,7 +14,7 @@ class EmbarkWeb3 {
this.config = embark.config;
this.modulesPath = dappPath(embark.config.embarkConfig.generationDir, constants.dappArtifacts.symlinkDir);
this.addWeb3ToEmbarkJS();
// this.addWeb3ToEmbarkJS();
}
async addWeb3ToEmbarkJS() {

View File

@ -163,10 +163,22 @@ class EmbarkController {
}
engine.registerModuleGroup("coreComponents");
engine.registerModuleGroup("blockchain");
engine.registerModuleGroup("compiler");
engine.registerModuleGroup("contracts");
engine.registerModuleGroup("pipeline");
engine.registerModuleGroup("webserver");
engine.registerModuleGroup("filewatcher");
engine.events.on('deployment:deployContracts:afterAll', () => {
console.dir("--- generating files...")
engine.events.request('pipeline:generateAll', () => {
console.dir("outputDone")
engine.events.emit('outputDone');
});
})
// this.events.request('watcher:start');
// engine.startService("processManager");
// engine.startService("web3");

View File

@ -35,16 +35,17 @@ class Dashboard {
(ws, _req) => {
let dashboardState = {contractsState: [], environment: "", status: "", availableServices: []};
self.events.request('setDashboardState');
self.events.on('contractsState', (contracts) => {
dashboardState.contractsState = [];
contracts.forEach(function (row) {
dashboardState.contractsState.push({contractName: row[0], address: row[1], status: row[2]});
});
ws.send(JSON.stringify(dashboardState));
});
// self.events.request('setDashboardState');
// self.events.on('contractsState', (contracts) => {
// dashboardState.contractsState = [];
// contracts.forEach(function (row) {
// dashboardState.contractsState.push({contractName: row[0], address: row[1], status: row[2]});
// });
// ws.send(JSON.stringify(dashboardState));
// });
self.events.on('status', (status) => {
dashboardState.status = status;
ws.send(JSON.stringify(dashboardState));
@ -56,7 +57,32 @@ class Dashboard {
}
);
this.events.on('contractsState', monitor.setContracts);
// this.events.on('contractsState', monitor.setContracts);
this.events.on("deployment:contract:error", (_contract) => {
console.dir("---- contract error event")
this.events.request("contracts:state", (err, contracts) => {
monitor.setContracts(contracts)
});
// self.events.emit('contractsState', self.contractsState());
});
this.events.on("deployment:contract:deployed", (_contract) => {
console.dir("---- contract deployed event")
// self.events.emit('contractsState', self.contractsState());
this.events.request("contracts:state", (err, contracts) => {
monitor.setContracts(contracts)
});
});
this.events.on("deployment:contract:undeployed", (_contract) => {
console.dir("---- contract undeployed event")
// self.events.emit('contractsState', self.contractsState());
this.events.request("contracts:state", (err, contracts) => {
monitor.setContracts(contracts)
});
});
this.events.on('status', monitor.setStatus.bind(monitor));
this.events.on('servicesState', monitor.availableServices.bind(monitor));

View File

@ -79,7 +79,10 @@ class Engine {
"blockchain": this.blockchainComponents,
"coreComponents": this.coreComponents,
"compiler": this.compilerComponents,
"contracts": this.contractsComponents
"contracts": this.contractsComponents,
"pipeline": this.pipelineService,
"webserver": this.webserverService,
"filewatcher": this.filewatcherService
};
let group = groups[groupName];
@ -93,6 +96,23 @@ class Engine {
return group.apply(this, [options]);
}
webserverService(_options) {
this.registerModulePackage('embark-webserver');
}
filewatcherService(_options) {
this.registerModulePackage('embark-watcher');
}
pipelineService(_options) {
this.registerModulePackage('embark-pipeline', { plugins: this.plugins });
this.registerModule('basic-pipeline', {
plugins: this.plugins,
webpackConfigName: this.webpackConfigName,
useDashboard: this.useDashboard
});
}
coreComponents() {
// TODO: should be made into a component
this.processManager = new ProcessManager({
@ -155,6 +175,19 @@ class Engine {
contractsComponents(options) {
this.registerModulePackage('embark-contracts-manager', {plugins: this.plugins, compileOnceOnly: options.compileOnceOnly});
this.registerModulePackage('embark-deployment', {plugins: this.plugins, onlyCompile: options.onlyCompile});
// this.registerModulePackage('embark-blockchain-connector', {
// isDev: this.isDev,
// locale: this.locale,
// plugins: this.plugins,
// web3: options.web3,
// wait: options.wait
// });
this.registerModule('blockchain-client');
this.registerModule('ethereum-blockchain-client');
this.registerModule('web3', { plugins: this.plugins });
this.registerModulePackage('embark-web3');
}
startService(serviceName, _options) {
@ -230,31 +263,6 @@ class Engine {
this.registerModulePackage('embark-scaffolding', {plugins: this.plugins});
}
pipelineService(_options) {
const self = this;
this.registerModulePackage('embark-pipeline', { plugins: this.plugins });
this.registerModule('basic-pipeline', {
plugins: this.plugins,
webpackConfigName: this.webpackConfigName,
useDashboard: this.useDashboard
});
// this.events.on('code-generator-ready', function (modifiedAssets) {
// self.events.request('code', function (abi, contractsJSON) {
// self.events.request('pipeline:build', {abi, contractsJSON, modifiedAssets}, () => {
// self.events.emit('outputDone');
// });
// });
// });
// TODO: move this to cmd_controller and define all such behaviour there
this.events.on('contracts:deploy:afterAll', () => {
self.events.request('pipeline:generateAll', () => {
console.dir("outputDone")
self.events.emit('outputDone');
});
})
}
serviceMonitor() {
const ServicesMonitor = require('./services_monitor.js');
this.servicesMonitor = new ServicesMonitor({events: this.events, logger: this.logger, plugins: this.plugins});

View File

@ -0,0 +1,32 @@
class BlockchainClient {
constructor(embark, options) {
this.embark = embark;
this.events = embark.events;
this.blockchainClients = {};
this.client = null;
this.events.setCommandHandler("blockchain:client:register", (clientName, blockchainClient) => {
this.blockchainClients[clientName] = blockchainClient;
this.client = blockchainClient;
})
// TODO: maybe not the ideal event to listen to?
// for e.g, could wait for all stack components to be ready
// TODO: probably better to have 2 stages in engine, services start, then connections, etc..
this.events.on("blockchain:started", (clientName) => {
// make connections
// this.client.initAndConnect(); // and config options
// should do stuff like
// connect to endpoint given
// set default account
})
}
}
module.exports = BlockchainClient;

View File

@ -22,7 +22,12 @@ class Blockchain {
const client = this.blockchainNodes[clientName];
if (!client) return cb("client " + clientName + " not found");
client.apply(client, [cb]);
let onStart = () => {
this.events.emit("blockchain:started", clientName);
cb();
}
client.apply(client, [onStart]);
})
}

View File

@ -0,0 +1,49 @@
const Web3 = require('web3');
const embarkJsUtils = require('embarkjs').Utils;
class EthereumBlockchainClient {
constructor(embark, options) {
this.embark = embark;
this.events = embark.events;
this.events.request("blockchain:client:register", "ethereum", this.getClient.bind(this));
this.events.request("deployment:deployer:register", "ethereum", this.deployer.bind(this));
}
getClient() {
return {};
}
deployer(contract, done) {
var web3 = new Web3("ws://localhost:8556")
web3.eth.getAccounts().then((accounts) => {
let account = accounts[0];
// let contractObject = this.blockchain.ContractObject({abi: contract.abiDefinition});
console.dir("== ethereum contract deployer")
console.dir(contract)
console.dir("-------")
console.dir("------- new web3")
let contractObj = new web3.eth.Contract(contract.abiDefinition, contract.address);
// let deployObject = this.blockchain.deployContractObject(contractObject, {arguments: contractParams, data: dataCode});
console.dir("------- deploy")
let contractObject = contractObj.deploy({ arguments: (contract.args || []), data: ("0x" + contract.code) });
// this.blockchain.deployContractFromObject(deployObject,
console.dir({ arguments: contract.args, data: ("0x" + contract.code) });
console.dir("------- send")
embarkJsUtils.secureSend(web3, contractObject, {
from: account, gas: 800000
}, true, (err, receipt) => {
contract.deployedAddress = receipt.contractAddress;
contract.transactionHash = receipt.transactionHash;
done();
}, (hash) => {
console.dir('hash is ' + hash);
});
})
}
}
module.exports = EthereumBlockchainClient;

View File

@ -16,14 +16,15 @@ class Web3Plugin {
this.plugins = options.plugins;
let plugin = this.plugins.createPlugin('web3plugin', {});
plugin.registerActionForEvent("deploy:contract:deployed", this.registerInVm.bind(this));
plugin.registerActionForEvent("deploy:contract:deployed", this.addContractJSONToPipeline.bind(this));
plugin.registerActionForEvent("deploy:contract:deployed", this.addContractFileToPipeline.bind(this));
// plugin.registerActionForEvent("deployment:contract:deployed", this.registerInVm.bind(this));
plugin.registerActionForEvent("deployment:contract:deployed", this.addContractJSONToPipeline.bind(this));
plugin.registerActionForEvent("deployment:contract:deployed", this.addContractFileToPipeline.bind(this));
plugin.registerActionForEvent("pipeline:generateAll:before", this.addEmbarkJSNode.bind(this));
plugin.registerActionForEvent("pipeline:generateAll:before", this.addContractIndexToPipeline.bind(this));
}
registerInVm(params, cb) {
console.dir("-- registerInVm")
let contract = params.contract;
let abi = JSON.stringify(contract.abiDefinition);
let gasLimit = 6000000;
@ -31,10 +32,14 @@ class Web3Plugin {
this.events.request('runcode:eval', contractCode, (err) => {
if (err) {
console.dir("error!!!")
console.dir(err)
return cb(err);
}
this.events.request('runcode:eval', contract.className, (err, result) => {
if (err) {
console.dir("error!!!")
console.dir(err)
return cb(err);
}
this.events.emit("runcode:register", contract.className, result, () => { cb() });
@ -43,6 +48,7 @@ class Web3Plugin {
}
addContractJSONToPipeline(params, cb) {
console.dir("-- addContractJSONToPipeline")
// TODO: check if this is correct json object to generate
const contract = params.contract;
@ -55,6 +61,7 @@ class Web3Plugin {
}
addContractFileToPipeline(params, cb) {
console.dir("-- addContractFileToPipeline")
const contract = params.contract;
const contractName = contract.className;
console.dir("--------------");