2015-06-28 02:20:07 +00:00
|
|
|
var web3 = require('web3');
|
|
|
|
var fs = require('fs');
|
|
|
|
var grunt = require('grunt');
|
|
|
|
var readYaml = require('read-yaml');
|
2015-06-28 13:51:58 +00:00
|
|
|
var Config = require('./config/config.js');
|
2015-10-21 21:26:57 +00:00
|
|
|
var BigNumber = require('bignumber.js');
|
2015-08-01 22:04:22 +00:00
|
|
|
|
2015-10-09 17:20:35 +00:00
|
|
|
Deploy = function(env, contractFiles, blockchainConfig, contractsConfig, chainManager, withProvider, withChain, _web3) {
|
2015-10-09 14:18:18 +00:00
|
|
|
if (_web3 !== undefined) {
|
|
|
|
web3 = _web3;
|
|
|
|
}
|
2015-07-03 08:59:33 +00:00
|
|
|
this.contractsManager = contractsConfig;
|
|
|
|
this.contractsConfig = this.contractsManager.config(env);
|
|
|
|
this.deployedContracts = {};
|
2015-10-09 17:20:35 +00:00
|
|
|
this.blockchainConfig = blockchainConfig;
|
2015-06-28 02:20:07 +00:00
|
|
|
|
|
|
|
try {
|
2015-10-09 17:20:35 +00:00
|
|
|
if (withProvider) {
|
2015-10-09 14:18:18 +00:00
|
|
|
web3.setProvider(new web3.providers.HttpProvider("http://" + this.blockchainConfig.rpcHost + ":" + this.blockchainConfig.rpcPort));
|
|
|
|
}
|
2015-06-28 02:20:07 +00:00
|
|
|
primaryAddress = web3.eth.coinbase;
|
|
|
|
web3.eth.defaultAccount = primaryAddress;
|
2015-07-04 02:41:39 +00:00
|
|
|
} catch (e) {
|
|
|
|
throw new Error("==== can't connect to " + this.blockchainConfig.rpcHost + ":" + this.blockchainConfig.rpcPort + " check if an ethereum node is running");
|
2015-06-28 02:20:07 +00:00
|
|
|
}
|
|
|
|
|
2015-10-09 17:20:35 +00:00
|
|
|
this.chainManager = chainManager;
|
|
|
|
this.chainManager.init(env, this.blockchainConfig, web3);
|
|
|
|
this.withChain = withChain;
|
|
|
|
|
2015-08-01 15:19:21 +00:00
|
|
|
console.log("primary account address is : " + primaryAddress);
|
2015-07-04 02:41:39 +00:00
|
|
|
};
|
2015-06-28 02:20:07 +00:00
|
|
|
|
2016-05-30 00:14:27 +00:00
|
|
|
Deploy.waitForContract = function(transactionHash, cb) {
|
|
|
|
web3.eth.getTransactionReceipt(transactionHash, function(e, receipt) {
|
|
|
|
if (!e && receipt && receipt.contractAddress !== undefined) {
|
|
|
|
cb(receipt.contractAddress);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Deploy.waitForContract(transactionHash, cb);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-10-08 19:30:47 +00:00
|
|
|
Deploy.prototype.deploy_contract = function(contractObject, contractParams, cb) {
|
|
|
|
var callback = function(e, contract) {
|
|
|
|
if(!e && contract.address !== undefined) {
|
|
|
|
cb(contract.address);
|
2015-08-01 22:04:22 +00:00
|
|
|
}
|
2015-10-08 19:30:47 +00:00
|
|
|
else {
|
2016-05-30 00:14:27 +00:00
|
|
|
Deploy.waitForContract(contract.transactionHash, cb);
|
2015-10-08 19:30:47 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
contractParams.push(callback);
|
|
|
|
contractObject["new"].apply(contractObject, contractParams);
|
2015-08-01 22:04:22 +00:00
|
|
|
}
|
|
|
|
|
2015-10-08 19:30:47 +00:00
|
|
|
Deploy.prototype.deploy_contracts = function(env, cb) {
|
2015-07-03 08:59:33 +00:00
|
|
|
this.contractsManager.compileContracts(env);
|
2015-10-08 19:30:47 +00:00
|
|
|
var all_contracts = this.contractsManager.all_contracts;
|
2015-07-03 08:59:33 +00:00
|
|
|
this.contractDB = this.contractsManager.contractDB;
|
|
|
|
this.deployedContracts = {};
|
2015-06-28 02:20:07 +00:00
|
|
|
|
2015-11-20 18:02:18 +00:00
|
|
|
if(this.blockchainConfig.deploy_synchronously)
|
2015-11-20 18:11:12 +00:00
|
|
|
this.deploy_contract_list_synchronously(env, all_contracts, cb);
|
2015-11-20 18:02:18 +00:00
|
|
|
else
|
|
|
|
this.deploy_contract_list(all_contracts.length, env, all_contracts, cb);
|
2015-10-08 19:30:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Deploy.prototype.deploy_contract_list = function(index, env, all_contracts, cb) {
|
|
|
|
if(index === 0) {
|
|
|
|
cb();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
var _this = this;
|
|
|
|
this.deploy_contract_list(index - 1, env, all_contracts, function() {
|
|
|
|
var className = all_contracts[index - 1];
|
|
|
|
_this.deploy_a_contract(env, className, cb);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-20 18:02:18 +00:00
|
|
|
Deploy.prototype.deploy_contract_list_synchronously = function(env, all_contracts, cb) {
|
|
|
|
|
2015-11-23 17:49:51 +00:00
|
|
|
var _this = this
|
|
|
|
,deployed_contracts_count = 0
|
2015-11-20 18:02:18 +00:00
|
|
|
|
|
|
|
all_contracts.forEach(function(className){
|
|
|
|
_this.deploy_a_contract(env, className, function(){
|
|
|
|
mark_contract_as_deployed()
|
|
|
|
});
|
|
|
|
})
|
|
|
|
|
|
|
|
function mark_contract_as_deployed(){
|
|
|
|
deployed_contracts_count ++;
|
|
|
|
|
|
|
|
if(deployed_contracts_count === all_contracts.length)
|
|
|
|
cb()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-08 19:30:47 +00:00
|
|
|
Deploy.prototype.deploy_a_contract = function(env, className, cb) {
|
|
|
|
var contractDependencies = this.contractsManager.contractDependencies;
|
|
|
|
var contract = this.contractDB[className];
|
2015-07-03 08:59:33 +00:00
|
|
|
|
2015-09-01 00:53:17 +00:00
|
|
|
if (contract.deploy === false) {
|
|
|
|
console.log("skipping " + className);
|
2015-10-08 19:30:47 +00:00
|
|
|
cb();
|
|
|
|
return;
|
2015-09-01 00:53:17 +00:00
|
|
|
}
|
|
|
|
|
2015-08-06 02:19:21 +00:00
|
|
|
var realArgs = [];
|
|
|
|
for (var l = 0; l < contract.args.length; l++) {
|
|
|
|
arg = contract.args[l];
|
|
|
|
if (arg[0] === "$") {
|
|
|
|
realArgs.push(this.deployedContracts[arg.substr(1)]);
|
|
|
|
} else {
|
|
|
|
realArgs.push(arg);
|
|
|
|
}
|
|
|
|
}
|
2015-08-04 12:18:04 +00:00
|
|
|
|
2015-07-06 12:19:25 +00:00
|
|
|
if (contract.address !== undefined) {
|
|
|
|
this.deployedContracts[className] = contract.address;
|
|
|
|
|
2015-07-09 11:31:37 +00:00
|
|
|
console.log("contract " + className + " at " + contract.address);
|
2015-10-08 19:30:47 +00:00
|
|
|
cb();
|
2015-06-28 02:20:07 +00:00
|
|
|
}
|
2015-07-06 12:19:25 +00:00
|
|
|
else {
|
2015-08-06 02:19:21 +00:00
|
|
|
var chainContract = this.chainManager.getContract(className, contract.compiled.code, realArgs);
|
2015-08-04 12:18:04 +00:00
|
|
|
|
2015-09-01 01:14:12 +00:00
|
|
|
if (chainContract != undefined && web3.eth.getCode(chainContract.address) !== "0x") {
|
2015-08-04 12:18:04 +00:00
|
|
|
console.log("contract " + className + " is unchanged and already deployed at " + chainContract.address);
|
2015-08-05 14:11:32 +00:00
|
|
|
this.deployedContracts[className] = chainContract.address;
|
2015-08-05 14:01:44 +00:00
|
|
|
this.execute_cmds(contract.onDeploy);
|
2015-10-08 19:30:47 +00:00
|
|
|
cb();
|
2015-07-06 12:19:25 +00:00
|
|
|
}
|
2015-08-04 12:18:04 +00:00
|
|
|
else {
|
2015-07-03 08:59:33 +00:00
|
|
|
|
2015-08-04 12:18:04 +00:00
|
|
|
contractObject = web3.eth.contract(contract.compiled.info.abiDefinition);
|
2015-07-03 08:59:33 +00:00
|
|
|
|
2015-08-06 02:19:21 +00:00
|
|
|
contractParams = realArgs.slice();
|
2015-08-04 12:18:04 +00:00
|
|
|
contractParams.push({
|
|
|
|
from: primaryAddress,
|
|
|
|
data: contract.compiled.code,
|
|
|
|
gas: contract.gasLimit,
|
|
|
|
gasPrice: contract.gasPrice
|
|
|
|
});
|
2015-08-01 22:04:22 +00:00
|
|
|
|
2015-08-04 12:18:04 +00:00
|
|
|
console.log('trying to obtain ' + className + ' address...');
|
2015-08-01 23:34:26 +00:00
|
|
|
|
2015-10-08 19:30:47 +00:00
|
|
|
var _this = this;
|
|
|
|
this.deploy_contract(contractObject, contractParams, function(contractAddress) {
|
|
|
|
if (web3.eth.getCode(contractAddress) === "0x") {
|
|
|
|
console.log("=========");
|
|
|
|
console.log("contract was deployed at " + contractAddress + " but doesn't seem to be working");
|
|
|
|
console.log("try adjusting your gas values");
|
|
|
|
console.log("=========");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
console.log("deployed " + className + " at " + contractAddress);
|
|
|
|
_this.chainManager.addContract(className, contract.compiled.code, realArgs, contractAddress);
|
2015-10-09 17:20:35 +00:00
|
|
|
if (_this.withChain) {
|
|
|
|
_this.chainManager.save();
|
|
|
|
}
|
2015-10-08 19:30:47 +00:00
|
|
|
}
|
2015-08-04 12:18:04 +00:00
|
|
|
|
2015-10-08 19:30:47 +00:00
|
|
|
_this.deployedContracts[className] = contractAddress;
|
2015-08-01 23:34:26 +00:00
|
|
|
|
2015-10-08 19:30:47 +00:00
|
|
|
_this.execute_cmds(contract.onDeploy);
|
2015-07-09 12:23:04 +00:00
|
|
|
|
2015-10-08 19:30:47 +00:00
|
|
|
cb();
|
|
|
|
});
|
|
|
|
|
2015-08-04 12:18:04 +00:00
|
|
|
}
|
2015-07-09 11:31:37 +00:00
|
|
|
}
|
2015-07-04 02:41:39 +00:00
|
|
|
};
|
2015-07-03 08:59:33 +00:00
|
|
|
|
2015-08-02 23:43:37 +00:00
|
|
|
Deploy.prototype.execute_cmds = function(cmds) {
|
2015-08-08 15:36:00 +00:00
|
|
|
if (cmds == undefined || cmds.length === 0) return;
|
2015-08-02 23:43:37 +00:00
|
|
|
|
|
|
|
eval(this.generate_abi_file());
|
|
|
|
for (var i = 0; i < cmds.length; i++) {
|
|
|
|
var cmd = cmds[i];
|
|
|
|
|
2015-08-03 00:50:12 +00:00
|
|
|
for(className in this.deployedContracts) {
|
|
|
|
var contractAddress = this.deployedContracts[className];
|
|
|
|
|
|
|
|
var re = new RegExp("\\$" + className, 'g');
|
|
|
|
cmd = cmd.replace(re, '"' + contractAddress + '"');
|
|
|
|
}
|
2015-08-02 23:43:37 +00:00
|
|
|
|
|
|
|
console.log("executing: " + cmd);
|
|
|
|
eval(cmd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-09 14:18:18 +00:00
|
|
|
Deploy.prototype.generate_provider_file = function() {
|
|
|
|
var result = "";
|
2016-05-23 13:20:11 +00:00
|
|
|
result += "var web3 = new Web3();";
|
|
|
|
result += "web3.setProvider(new web3.providers.HttpProvider('http://" + this.blockchainConfig.rpcHost + ":" + this.blockchainConfig.rpcPort + "'));";
|
2015-10-09 14:18:18 +00:00
|
|
|
result += "web3.eth.defaultAccount = web3.eth.accounts[0];";
|
2015-07-03 08:59:33 +00:00
|
|
|
|
2015-10-09 14:18:18 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
Deploy.prototype.generate_abi_file = function() {
|
|
|
|
var result = "";
|
2015-07-03 08:59:33 +00:00
|
|
|
|
2015-12-02 23:42:36 +00:00
|
|
|
result += 'blockchain = '+JSON.stringify(this.blockchainConfig)+';';
|
|
|
|
|
2015-07-03 08:59:33 +00:00
|
|
|
for(className in this.deployedContracts) {
|
|
|
|
var deployedContract = this.deployedContracts[className];
|
|
|
|
var contract = this.contractDB[className];
|
|
|
|
|
2015-07-04 21:02:01 +00:00
|
|
|
var abi = JSON.stringify(contract.compiled.info.abiDefinition);
|
2015-07-09 12:23:04 +00:00
|
|
|
var contractAddress = deployedContract;
|
2015-07-09 11:43:53 +00:00
|
|
|
|
2015-07-09 08:49:04 +00:00
|
|
|
console.log('address is ' + contractAddress);
|
|
|
|
|
2015-07-07 10:51:03 +00:00
|
|
|
result += className + "Abi = " + abi + ";";
|
|
|
|
result += className + "Contract = web3.eth.contract(" + className + "Abi);";
|
|
|
|
result += className + " = " + className + "Contract.at('" + contractAddress + "');";
|
2015-06-28 02:20:07 +00:00
|
|
|
}
|
2015-10-14 14:54:07 +00:00
|
|
|
result += 'contractDB = '+JSON.stringify(this.contractDB)+';'
|
2015-06-28 02:20:07 +00:00
|
|
|
|
2015-07-03 08:59:33 +00:00
|
|
|
return result;
|
2015-07-04 02:41:39 +00:00
|
|
|
};
|
2015-06-28 02:20:07 +00:00
|
|
|
|
2015-07-03 08:59:33 +00:00
|
|
|
Deploy.prototype.generate_and_write_abi_file = function(destFile) {
|
|
|
|
var result = this.generate_abi_file();
|
|
|
|
grunt.file.write(destFile, result);
|
2015-07-04 02:41:39 +00:00
|
|
|
};
|
2015-06-28 02:20:07 +00:00
|
|
|
|
2015-07-04 02:41:39 +00:00
|
|
|
module.exports = Deploy;
|