redone deployment system

This commit is contained in:
Iuri Matias 2016-08-14 08:04:34 -04:00
parent b5d8df5efd
commit 2064b72ac6
9 changed files with 310 additions and 23 deletions

View File

@ -6,9 +6,13 @@ contract SimpleStorage {
}
function set(uint x) {
storedData = x;
for (uint same3=0; same3 < 3; same3++) {
storedData = same3;
}
//storedData = x;
}
function get() constant returns (uint retVal) {
return storedData;
}
}

View File

@ -0,0 +1,19 @@
contract token {
mapping (address => uint) public coinBalanceOf;
event CoinTransfer(address sender, address receiver, uint amount);
/* Initializes contract with initial supply tokens to the creator of the contract */
function token(uint supply) {
if (supply == 0) supply = 10000;
coinBalanceOf[msg.sender] = supply;
}
/* Very simple trade function */
function sendCoin(address receiver, uint amount) returns(bool sufficient) {
if (coinBalanceOf[msg.sender] < amount) return false;
coinBalanceOf[msg.sender] -= amount;
coinBalanceOf[receiver] += amount;
CoinTransfer(msg.sender, receiver, amount);
return true;
}
}

View File

@ -1,5 +1,7 @@
{
"default": {
"gasLimit": 500000,
"gasPrice": 10000000000000,
"contracts": {
"SimpleStorage": {
"args": [

39
lib/abi.js Normal file
View File

@ -0,0 +1,39 @@
var ABIGenerator = function(contractsManager) {
this.contractsManager = contractsManager;
this.rpcHost = 'localhost';
this.rpcPort = '8101';
};
ABIGenerator.prototype.generateProvider = function() {
var result = "";
result += "\nif (typeof web3 !== 'undefined' && typeof Web3 !== 'undefined') {";
result += '\n\tweb3 = new Web3(web3.currentProvider);';
result += "\n} else if (typeof Web3 !== 'undefined') {";
result += '\n\tweb3 = new Web3(new Web3.providers.HttpProvider("http://' + this.rpcHost + ':' + this.rpcPort + '"));';
result += '\n}';
result += "\nweb3.eth.defaultAccount = web3.eth.accounts[0];";
return result;
};
ABIGenerator.prototype.generateContracts = function() {
var result = "\n";
for(var className in this.contractsManager.contracts) {
var contract = this.contractsManager.contracts[className];
var abi = JSON.stringify(contract.abiDefinition);
console.log('address is ' + contract.deployedAddress);
result += "\n" + className + "Abi = " + abi + ";";
result += "\n" + className + "Contract = web3.eth.contract(" + className + "Abi);";
result += "\n" + className + " = " + className + "Contract.at('" + contract.deployedAddress + "');";
}
return result;
};
module.exports = ABIGenerator;

106
lib/compiler.js Normal file
View File

@ -0,0 +1,106 @@
var shelljs = require('shelljs');
var shelljs_global = require('shelljs/global');
var fs = require('fs');
var solc = require('solc');
var Compiler = function() {
};
Compiler.prototype.compile_solidity = function(contractFiles) {
var input = {};
for (var i = 0; i < contractFiles.length; i++){
// TODO: this depends on the config
var filename = contractFiles[i].replace('app/contracts/','');
input[filename] = fs.readFileSync(contractFiles[i]).toString();
}
var output = solc.compile({sources: input}, 1);
if (output.errors) {
throw new Error ("Solidity errors: " + output.errors);
}
var json = output.contracts;
compiled_object = {};
for (var className in json) {
var contract = json[className];
compiled_object[className] = {};
compiled_object[className].code = contract.bytecode;
compiled_object[className].runtimeBytecode = contract.runtimeBytecode;
compiled_object[className].gasEstimates = contract.gasEstimates;
compiled_object[className].functionHashes = contract.functionHashes;
compiled_object[className].abiDefinition = JSON.parse(contract.interface);
}
return compiled_object;
};
Compiler.prototype.compile_serpent = function(contractFiles) {
var cmd, result, output, json, compiled_object;
//TODO: figure out how to compile multiple files and get the correct json
var contractFile = contractFiles[0];
cmd = "serpent compile " + contractFile;
result = exec(cmd, {silent: true});
code = result.output;
if (result.code === 1) {
throw new Error(result.output);
}
cmd = "serpent mk_full_signature " + contractFile;
result = exec(cmd, {silent: true});
if (result.code === 1) {
throw new Error(result.output);
}
json = JSON.parse(result.output.trim());
className = contractFile.split('.')[0].split("/").pop();
for (var i=0; i < json.length; i++) {
var elem = json[i];
if (elem.outputs.length > 0) {
elem.constant = true;
}
}
compiled_object = {};
compiled_object[className] = {};
compiled_object[className].code = code.trim();
compiled_object[className].info = {};
compiled_object[className].abiDefinition = json;
return compiled_object;
};
Compiler.prototype.compile = function(contractFiles) {
var solidity = [], serpent = [];
for (var i = 0; i < contractFiles.length; i++) {
var contractParts = contractFiles[i].split('.'),
extension = contractParts[contractParts.length-1];
if (extension === 'sol') {
solidity.push(contractFiles[i]);
}
else if (extension === 'se') {
serpent.push(contractFiles[i]);
}
else {
throw new Error("extension not known, got " + extension);
}
}
//TODO: Get these compiling and returning together...problem might come with the JSON objects
if (solidity.length > 0) return this.compile_solidity(solidity);
if (serpent.length > 0) return this.compile_serpent(serpent);
};
module.exports = Compiler;

59
lib/contracts.js Normal file
View File

@ -0,0 +1,59 @@
var fs = require('fs');
var grunt = require('grunt');
var Compiler = require('./compiler.js');
var ContractsManager = function(configDir, contractFiles, env) {
this.contractFiles = grunt.file.expand(contractFiles);
this.configDir = configDir;
this.env = env;
this.contracts = {};
};
ContractsManager.prototype.init = function() {
this.contractsConfig = this.loadConfigFiles();
this.compiledContracts = this.compileContracts();
};
ContractsManager.prototype.loadConfigFiles = function() {
var defaultContractsConfig = JSON.parse(fs.readFileSync(this.configDir + "contracts.json"))['default'];
//var envContractsConfig = JSON.parse(fs.readFileSync(this.configDir + this.env + "/contracts.json"))[this.env];
//merge.recursive(defaultContractsConfig, envContractsConfig);
return defaultContractsConfig;
};
ContractsManager.prototype.compileContracts = function() {
var compiler = new Compiler();
return compiler.compile_solidity(this.contractFiles);
};
ContractsManager.prototype.build = function() {
for(var className in this.compiledContracts) {
var contract = this.compiledContracts[className];
var contractConfig = this.contractsConfig[className];
contract.gasLimit = this.contractsConfig.gasLimit;
contract.gasPrice = this.contractsConfig.gasPrice;
if (contractConfig === undefined) {
contract.args = [];
} else {
contract.args = contractConfig.args || [];
}
contract.className = className;
this.contracts[className] = contract;
}
};
ContractsManager.prototype.listContracts = function() {
var contracts = [];
for(var className in this.compiledContracts) {
var contract = this.compiledContracts[className];
contracts.push(contract);
}
return contracts;
};
module.exports = ContractsManager;

View File

@ -1,33 +1,54 @@
var async = require('async');
var Compiler = require('./compiler.js');
// needs:
// compile the contract -> file location
// gas -> config
contractObject = {
compiledCode,
abiDefinition,
gas,
gasPrice
}
var Deploy = function(web3, contractsManager) {
this.web3 = web3;
this.contractsManager = contractsManager;
};
function deployContract(web3, contractObject, params) {
var contractObject = web3.eth.contract(contract.compiled.info.abiDefinition);
Deploy.prototype.deployContract = function(contract, params, callback) {
var contractObject = this.web3.eth.contract(contract.abiDefinition);
var contractParams = params || contract.args;
var contractParams = params;
contractParams.push({
from: primaryAddress,
data: contract.compiled.code,
from: this.web3.eth.coinbase,
data: contract.code,
gas: contract.gasLimit,
gasPrice: contract.gasPrice
});
contractParams.push(callback);
contractParams.push(function(err, transaction) {
if (err) {
console.log("error");
callback(new Error(err));
} else if (transaction.address !== undefined) {
console.log("address contract: " + transaction.address);
contract.deployedAddress = transaction.address;
callback(null, transaction.address);
}
});
contractObject["new"].apply(contractObject, contractParams);
};
function buildContractObject(contractCode, gas, gasPrice) {
var compiledContract = compiler.compile(contractCode);
return {
}
}
Deploy.prototype.deployAll = function(done) {
var self = this;
console.log("deployAll");
async.eachOfSeries(this.contractsManager.listContracts(),
function(contract, key, callback) {
console.log(arguments);
self.deployContract(contract, null, callback);
},
function(err, results) {
console.log("finished");
console.log(arguments);
done();
}
);
};
module.exports = Deploy;

View File

@ -1,6 +1,44 @@
var async = require('async');
var Web3 = require('web3');
var Deploy = require('./deploy.js');
var ContractsManager = require('./contracts.js');
var ABIGenerator = require('./abi.js');
var Embark = {
initConfig: function(configDir, files, env) {
this.contractsManager = new ContractsManager(configDir, files, env);
this.contractsManager.init();
return this.contractsManager;
}
};
module.exports = Embark;
//module.exports = Embark;
async.waterfall([
function loadConfig(callback) {
var contractsManager = Embark.initConfig('config/', 'app/contracts/**/*.sol', 'development');
callback(null, contractsManager);
},
function buildContracts(contractsManager, callback) {
contractsManager.build();
callback(null, contractsManager);
},
function deployContracts(contractsManager, callback) {
var web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8101'));
var deploy = new Deploy(web3, contractsManager);
deploy.deployAll(function() {
callback(null, contractsManager);
});
},
function generateABI(contractsManager, callback) {
var abiGenerator = new ABIGenerator(contractsManager);
console.log(abiGenerator.generateProvider());
console.log(abiGenerator.generateContracts());
callback(null, 'done');
},
], function(err, result) {
console.log(arguments);
});

View File

@ -22,7 +22,6 @@
"mkdirp": "^0.5.1",
"read-yaml": "^1.0.0",
"shelljs": "^0.5.0",
"solc": "^0.4.1",
"toposort": "^0.2.10",
"web3": "^0.15.0",
"wrench": "^1.5.8"