restructure; move code from tasks into libs

This commit is contained in:
Iuri Matias 2015-06-27 22:20:07 -04:00
parent 416530dbbf
commit 12f84bf403
15 changed files with 471 additions and 205 deletions

View File

@ -1,7 +1,30 @@
module.exports = (grunt) -> module.exports = (grunt) ->
grunt.initConfig grunt.initConfig
"embark-framework": "embark-framework": {}
pkg: grunt.file.readJSON('package.json')
clean:
build: ["build/"]
coffee:
compile:
expand: true
src: 'src/**/*.coffee'
dest: 'build/'
ext: '.js'
uglify:
options: banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
build:
files:
'build/<%= pkg.name %>.min.js': [
"build/<%= pkg.name %>.js"
]
mochaTest:
test:
src: ['test/**/*.js']
grunt.loadTasks "tasks" grunt.loadTasks "tasks"
require('matchdep').filterAll('grunt-*').forEach(grunt.loadNpmTasks)
grunt.registerTask 'default', ['clean']
grunt.registerTask 'build', ['clean', 'coffee']

View File

@ -10,7 +10,7 @@
"license": "ISC", "license": "ISC",
"homepage": "", "homepage": "",
"devDependencies": { "devDependencies": {
"embark-framework": "^0.4.3", "embark-framework": "/Users/iurimatias/Projects/embark-framework",
"grunt-contrib-clean": "^0.6.0", "grunt-contrib-clean": "^0.6.0",
"grunt-contrib-coffee": "^0.13.0", "grunt-contrib-coffee": "^0.13.0",
"grunt-contrib-concat": "^0.5.1", "grunt-contrib-concat": "^0.5.1",

36
build/src/index.js Normal file
View File

@ -0,0 +1,36 @@
(function() {
var commander, compression, embark, express, hashmerge, jasmine, methodmissing, python, readYaml, shelljs, shelljs_global, syncMe, web3, wrench;
hashmerge = require('hashmerge');
readYaml = require('read-yaml');
shelljs = require('shelljs');
shelljs_global = require('shelljs/global');
web3 = require('web3');
express = require('express');
compression = require('compression');
commander = require('commander');
wrench = require('wrench');
python = require('python');
syncMe = require('sync-me');
methodmissing = require('methodmissing');
jasmine = require('jasmine');
embark = {};
embark.Tests = require('./test.js');
module.exports = embark;
}).call(this);

96
build/src/test.js Normal file
View File

@ -0,0 +1,96 @@
(function() {
var Test, TestContract, TestContractWrapper, className, compiled_contracts, contract, contractDB, contractFile, contractFiles, fs, grunt, i, len, mm, py_exec, python, request, source, sync, web3;
python = require('python').shell;
web3 = require('web3');
fs = require('fs');
mm = require('methodmissing');
sync = require('sync-me');
grunt = require('grunt');
py_exec = function(cmd) {
return sync(python, cmd)[1].trim();
};
py_exec('from ethertdd import EvmContract');
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8101'));
web3.eth.defaultAccount = web3.eth.accounts[0];
TestContractWrapper = (function() {
TestContractWrapper = function(contract, className, args) {
this.contract = contract;
this.className = className;
this.args = args;
this.initializeContract();
};
TestContractWrapper.prototype.initializeContract = function() {
var example_abi, example_binary;
example_abi = JSON.stringify(contract.info.abiDefinition);
example_binary = contract.code.slice(2);
py_exec("example_abi = '" + example_abi + "'");
py_exec("example_abi");
py_exec("example_binary = '" + example_binary + "'.decode('hex')");
py_exec("example_binary");
if (this.args === void 0) {
py_exec(this.className + '_contract = EvmContract(example_abi, example_binary, \'' + this.className + '\')');
} else {
py_exec(this.className + '_contract = EvmContract(example_abi, example_binary, \'' + this.className + '\', [' + this.args.join(',') + '])');
}
this.contractVariable = this.className + '_contract';
};
TestContractWrapper.prototype.execCmd = function(method, args) {
var arg_list, data, key, value;
arg_list = [];
for (key in args) {
value = args[key];
value = args[key];
arg_list.push(value);
}
data = py_exec(this.className + '_contract.' + method + '(' + arg_list.join(',') + ')');
return data;
};
return TestContractWrapper;
})();
TestContract = function(contract, className, args) {
var Obj, wrapper;
wrapper = new TestContractWrapper(contract, className, args);
Obj = mm(wrapper, function(key, args) {
return wrapper.execCmd(key, args);
});
return Obj;
};
contractFiles = grunt.file.expand('./app/contracts/**/*.sol');
contractDB = {};
for (i = 0, len = contractFiles.length; i < len; i++) {
contractFile = contractFiles[i];
source = fs.readFileSync(contractFile).toString();
compiled_contracts = web3.eth.compile.solidity(source);
for (className in compiled_contracts) {
contract = compiled_contracts[className];
contractDB[className] = contract;
}
}
request = function(className, args) {
contract = contractDB[className];
return TestContract(contract, className, args);
};
Test = {
request: request
};
module.exports = Test;
}).call(this);

102
lib/blockchain.js Normal file
View File

@ -0,0 +1,102 @@
var Deploy;
var readYaml = require('read-yaml');
startChain = function(env) {
try {
blockchainConfig = readYaml.sync("config/blockchain.yml");
} catch (_error) {
exception = _error;
console.log("==== error reading config/blockchain.yml");
console.log(exception);
}
rpcHost = blockchainConfig[env].rpc_host;
rpcPort = blockchainConfig[env].rpc_port;
rpcWhitelist = blockchainConfig[env].rpc_whitelist;
minerthreads = blockchainConfig[env].minerthreads;
datadir = blockchainConfig[env].datadir;
networkId = blockchainConfig[env].network_id || Math.floor((Math.random() * 100000) + 1000);
port = blockchainConfig[env].port || "30303";
console_toggle = blockchainConfig[env].console || false;
mine_when_needed = blockchainConfig[env].mine_when_needed || false;
account = blockchainConfig[env].account;
address = account.address;
cmd = "geth ";
if (datadir !== "default") {
cmd += "--datadir=\"" + datadir + "\" ";
cmd += "--logfile=\"" + datadir + ".log\" ";
}
cmd += "--port " + port + " ";
cmd += "--rpc ";
cmd += "--rpcport " + rpcPort + " ";
cmd += "--networkid " + networkId + " ";
cmd += "--rpccorsdomain \"" + rpcWhitelist + "\" ";
if (minerthreads !== void 0) {
cmd += "--minerthreads \"" + minerthreads + "\" ";
}
cmd += "--mine ";
if (account.password !== void 0) {
cmd += "--password " + account.password + " ";
}
if (account.init) {
console.log("=== initializating account");
console.log("running: " + cmd + " account list");
result = exec(cmd + "account list");
console.log("finished");
console.log("=== output is " + result.output);
if (result.output.indexOf("Fatal") < 0) {
console.log("=== already initialized");
address = result.output.match(/{(\w+)}/)[1];
} else {
console.log("running: " + cmd + " account new");
output = exec(cmd + " account new");
address = output.output.match(/{(\w+)}/)[1];
}
}
if (address !== void 0) {
cmd += "--unlock " + address + " ";
}
if (console_toggle) {
cmd += "console";
}
if (mine_when_needed) {
cmd += "js node_modules/embark-framework/js/mine.js";
}
console.log("running: " + cmd);
console.log("=== running geth");
exec(cmd);
}
Blockchain = {
startChain: startChain
}
module.exports = Blockchain

136
lib/deploy.js Normal file
View File

@ -0,0 +1,136 @@
var web3 = require('web3');
var fs = require('fs');
var grunt = require('grunt');
var readYaml = require('read-yaml');
deployContracts = function(env, contractFiles, destFile) {
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
blockchainConfig = readYaml.sync("config/blockchain.yml");
contractsConfig = readYaml.sync("config/contracts.yml")[env || "development"];
rpcHost = blockchainConfig[env || "development"].rpc_host;
rpcPort = blockchainConfig[env || "development"].rpc_port;
gasLimit = blockchainConfig[env || "development"].gas_limit || 500000;
gasPrice = blockchainConfig[env || "development"].gas_price || 10000000000000;
try {
web3.setProvider(new web3.providers.HttpProvider("http://" + rpcHost + ":" + rpcPort));
primaryAddress = web3.eth.coinbase;
web3.eth.defaultAccount = primaryAddress;
} catch (_error) {
e = _error;
console.log("==== can't connect to " + rpcHost + ":" + rpcPort + " check if an ethereum node is running");
exit;
}
console.log("address is : " + primaryAddress);
result = "web3.setProvider(new web3.providers.HttpProvider('http://" + rpcHost + ":" + rpcPort + "'));";
result += "web3.eth.defaultAccount = web3.eth.accounts[0];";
contractDependencies = {};
if (contractsConfig != null) {
for (className in contractsConfig) {
options = contractsConfig[className];
if (options.args == null) {
continue;
}
ref = options.args;
for (i = 0, len = ref.length; i < len; i++) {
arg = ref[i];
if (arg[0] === "$") {
if (contractDependencies[className] === void 0) {
contractDependencies[className] = [];
}
contractDependencies[className].push(arg.substr(1));
}
}
}
}
all_contracts = [];
contractDB = {};
for (j = 0, len1 = contractFiles.length; j < len1; j++) {
contractFile = contractFiles[j];
//source = grunt.file.read(contractFile);
source = fs.readFileSync(contractFile).toString()
console.log("deploying " + contractFile);
compiled_contracts = web3.eth.compile.solidity(source);
for (className in compiled_contracts) {
contract = compiled_contracts[className];
all_contracts.push(className);
contractDB[className] = contract;
}
}
all_contracts.sort((function(_this) {
return function(a, b) {
var contract_1, contract_2;
contract_1 = contractDependencies[a];
contract_2 = contractDependencies[b];
if (indexOf.call(contract_1, a) >= 0 && indexOf.call(contract_2, b) >= 0) {
console.log("looks like you have a circular dependency between " + a + " and " + b);
return exit;
} else if (indexOf.call(contract_1, b) >= 0) {
return 1;
} else if (indexOf.call(contract_2, a) >= 0) {
return -1;
} else {
return 0;
}
};
})(this));
deployedContracts = {};
for (k = 0, len2 = all_contracts.length; k < len2; k++) {
className = all_contracts[k];
contract = contractDB[className];
contractGasLimit = (contractsConfig != null ? (ref1 = contractsConfig[className]) != null ? ref1.gasLimit : void 0 : void 0) || gasLimit;
contractGasPrice = (contractsConfig != null ? (ref2 = contractsConfig[className]) != null ? ref2.gasPrice : void 0 : void 0) || gasPrice;
args = (contractsConfig != null ? (ref3 = contractsConfig[className]) != null ? ref3.args : void 0 : void 0) || [];
contractObject = web3.eth.contract(contract.info.abiDefinition);
realArgs = [];
for (l = 0, len3 = args.length; l < len3; l++) {
arg = args[l];
if (arg[0] === "$") {
realArgs.push(deployedContracts[arg.substr(1)]);
} else {
realArgs.push(arg);
}
}
contractParams = realArgs;
contractParams.push({
from: primaryAddress,
data: contract.code,
gas: contractGasLimit,
gasPrice: contractGasPrice
});
contractAddress = contractObject["new"].apply(contractObject, contractParams).address;
deployedContracts[className] = contractAddress;
console.log("address is " + contractAddress);
console.log("deployed " + className + " at " + contractAddress);
abi = JSON.stringify(contract.info.abiDefinition);
result += "var " + className + "Abi = " + abi + ";";
result += "var " + className + "Contract = web3.eth.contract(" + className + "Abi);";
result += "var " + className + " = " + className + "Contract.at('" + contractAddress + "');";
}
grunt.file.write(destFile, result);
}
Deploy = {
deployContracts: deployContracts
}
module.exports = Deploy

View File

@ -13,7 +13,10 @@ var methodmissing = require('methodmissing');
var jasmine = require('jasmine'); var jasmine = require('jasmine');
embark = {} embark = {}
embark.Tests = require('./lib/test.js'); embark.Tests = require('./test.js');
embark.Blockchain = require('./blockchain.js');
embark.Deploy = require('./deploy.js');
embark.Release = require('./ipfs.js');
module.exports = embark; module.exports = embark;

30
lib/ipfs.js Normal file
View File

@ -0,0 +1,30 @@
require('shelljs/global');
ipfs = function() {
ipfs_path = "~/go/bin";
build_dir = "dist/dapp/";
cmd = ipfs_path + "/ipfs add -r " + build_dir;
grunt.log.writeln("=== adding " + cmd + " to ipfs");
result = exec(cmd);
rows = result.output.split("\n");
dir_row = rows[rows.length - 2];
dir_hash = dir_row.split(" ")[1];
console.log("=== DApp available at http://localhost:8080/ipfs/" + dir_hash + "/");
console.log("=== DApp available at http://gateway.ipfs.io/ipfs/" + dir_hash + "/");
}
Release = {
ipfs: ipfs
}
module.exports = Release

View File

@ -9,11 +9,6 @@ py_exec = function(cmd) {
return sync(python, cmd)[1].trim(); return sync(python, cmd)[1].trim();
} }
py_exec("from ethertdd import EvmContract")
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8101'));
web3.eth.defaultAccount = web3.eth.accounts[0];
TestContractWrapper = (function() { TestContractWrapper = (function() {
function TestContractWrapper(contract, className, args) { function TestContractWrapper(contract, className, args) {
this.contract = contract; this.contract = contract;
@ -64,23 +59,28 @@ TestContract = function(contract, className, args) {
return Obj; return Obj;
} }
//TODO: get the files from the config
contractFiles = grunt.file.expand("./app/contracts/**/*.sol")
contractDB = {}
var i;
for (i = 0, len = contractFiles.length; i < len; i++) {
var contractFile = contractFiles[i];
var source = fs.readFileSync(contractFile).toString()
compiled_contracts = web3.eth.compile.solidity(source)
for (className in compiled_contracts) {
var contract = compiled_contracts[className];
contractDB[className] = contract;
}
}
request = function(className, args) { request = function(className, args) {
py_exec("from ethertdd import EvmContract")
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8101'));
web3.eth.defaultAccount = web3.eth.accounts[0];
//TODO: get the files from the config
contractFiles = grunt.file.expand("./app/contracts/**/*.sol")
contractDB = {}
var i;
for (i = 0, len = contractFiles.length; i < len; i++) {
var contractFile = contractFiles[i];
var source = fs.readFileSync(contractFile).toString()
compiled_contracts = web3.eth.compile.solidity(source)
for (className in compiled_contracts) {
var contract = compiled_contracts[className];
contractDB[className] = contract;
}
}
var contract = contractDB[className]; var contract = contractDB[className];
return TestContract(contract, className, args) return TestContract(contract, className, args)
} }

View File

@ -8,7 +8,7 @@
"bin": { "bin": {
"embark": "./bin/embark" "embark": "./bin/embark"
}, },
"main": "./index.js", "main": "./lib/index.js",
"directories": { "directories": {
"lib": "./lib" "lib": "./lib"
}, },
@ -38,5 +38,9 @@
}, },
"author": "Iuri Matias <iuri.matias@gmail.com>", "author": "Iuri Matias <iuri.matias@gmail.com>",
"contributors": [], "contributors": [],
"license": "ISC" "license": "ISC",
"devDependencies": {
"grunt-mocha-test": "^0.12.7",
"mocha": "^2.2.5"
}
} }

View File

@ -1,71 +1,7 @@
module.exports = (grunt) -> module.exports = (grunt) ->
readYaml = require('read-yaml')
require('shelljs/global')
grunt.registerTask "blockchain", "deploy ethereum node", (env_) => grunt.registerTask "blockchain", "deploy ethereum node", (env_) =>
env = env_ || "development" env = env_ || "development"
try Embark = require('embark-framework')
blockchainConfig = readYaml.sync("config/blockchain.yml") Embark.Blockchain.startChain(env)
catch exception
grunt.log.writeln("==== error reading config/blockchain.yml")
grunt.log.writeln(exception)
rpcHost = blockchainConfig[env].rpc_host
rpcPort = blockchainConfig[env].rpc_port
rpcWhitelist = blockchainConfig[env].rpc_whitelist
minerthreads = blockchainConfig[env].minerthreads
datadir = blockchainConfig[env].datadir
networkId = blockchainConfig[env].network_id || Math.floor(((Math.random()*100000)+1000))
port = blockchainConfig[env].port || "30303"
console = blockchainConfig[env].console || false
mine_when_needed = blockchainConfig[env].mine_when_needed || false
account = blockchainConfig[env].account
address = account.address
cmd = "geth "
unless datadir is "default"
cmd += "--datadir=\"#{datadir}\" "
cmd += "--logfile=\"#{datadir}.log\" "
cmd += "--port #{port} "
cmd += "--rpc "
cmd += "--rpcport #{rpcPort} "
cmd += "--networkid #{networkId} "
cmd += "--rpccorsdomain \"#{rpcWhitelist}\" "
unless minerthreads is undefined
cmd += "--minerthreads \"#{minerthreads}\" "
cmd += "--mine "
if account.password isnt undefined
cmd += "--password #{account.password} "
if account.init
grunt.log.writeln("=== initializating account")
grunt.log.writeln("running: #{cmd} account list")
result = exec(cmd + "account list")
grunt.log.writeln("finished")
grunt.log.writeln("=== output is #{result.output}")
if result.output.indexOf("Fatal") < 0
grunt.log.writeln("=== already initialized")
address = result.output.match(/{(\w+)}/)[1]
else
grunt.log.writeln("running: #{cmd} account new")
output = exec(cmd + " account new")
address = output.output.match(/{(\w+)}/)[1]
if address isnt undefined
cmd += "--unlock #{address} "
if console
cmd += "console"
if mine_when_needed
cmd += "js node_modules/embark-framework/js/mine.js"
grunt.log.writeln("running: #{cmd}")
grunt.log.writeln("=== running geth")
#sh.run(cmd)
exec(cmd)

View File

@ -2,99 +2,11 @@ module.exports = (grunt) ->
web3 = require('web3') web3 = require('web3')
readYaml = require('read-yaml'); readYaml = require('read-yaml');
grunt.registerTask "deploy_contracts", "deploy code", (env) => grunt.registerTask "deploy_contracts", "deploy code", (env_) =>
blockchainConfig = readYaml.sync("config/blockchain.yml") env = env_ || "development"
contractsConfig = readYaml.sync("config/contracts.yml")[env || "development"] contractFiles = grunt.file.expand(grunt.config.get("deploy.contracts"));
rpcHost = blockchainConfig[env || "development"].rpc_host destFile = grunt.config.get("deploy.dest");
rpcPort = blockchainConfig[env || "development"].rpc_port
gasLimit = blockchainConfig[env || "development"].gas_limit || 500000
gasPrice = blockchainConfig[env || "development"].gas_price || 10000000000000
try Embark = require('embark-framework')
web3.setProvider(new web3.providers.HttpProvider("http://#{rpcHost}:#{rpcPort}")) Embark.Deploy.deployContracts(env, contractFiles, destFile)
primaryAddress = web3.eth.coinbase
web3.eth.defaultAccount = primaryAddress
catch e
grunt.log.writeln("==== can't connect to #{rpcHost}:#{rpcPort} check if an ethereum node is running")
exit
grunt.log.writeln("address is : #{primaryAddress}")
result = "web3.setProvider(new web3.providers.HttpProvider('http://#{rpcHost}:#{rpcPort}'));"
result += "web3.eth.defaultAccount = web3.eth.accounts[0];"
contractDependencies = {}
if contractsConfig?
for className, options of contractsConfig
continue unless options.args?
for arg in options.args
if arg[0] is "$"
if contractDependencies[className] is undefined
contractDependencies[className] = []
contractDependencies[className].push(arg.substr(1))
all_contracts = []
contractDB = {}
contractFiles = grunt.file.expand(grunt.config.get("deploy.contracts"))
for contractFile in contractFiles
source = grunt.file.read(contractFile)
grunt.log.writeln("deploying #{contractFile}")
compiled_contracts = web3.eth.compile.solidity(source)
for className, contract of compiled_contracts
all_contracts.push(className)
contractDB[className] = contract
all_contracts.sort (a,b) =>
contract_1 = contractDependencies[a]? or []
contract_2 = contractDependencies[b]? or []
if a in contract_1 and b in contract_2
grunt.log.writeln("looks like you have a circular dependency between #{a} and #{b}")
exit
else if b in contract_1
1
else if a in contract_2
-1
else
0
deployedContracts = {}
for className in all_contracts
contract = contractDB[className]
contractGasLimit = contractsConfig?[className]?.gasLimit || gasLimit
contractGasPrice = contractsConfig?[className]?.gasPrice || gasPrice
args = contractsConfig?[className]?.args || []
contractObject = web3.eth.contract(contract.info.abiDefinition)
realArgs = []
for arg in args
if arg[0] is "$"
realArgs.push(deployedContracts[arg.substr(1)])
else
realArgs.push(arg)
contractParams = realArgs
contractParams.push({from: primaryAddress, data: contract.code, gas: contractGasLimit, gasPrice: contractGasPrice})
contractAddress = contractObject.new.apply(contractObject, contractParams).address
deployedContracts[className] = contractAddress
console.log "address is #{contractAddress}"
grunt.log.writeln("deployed #{className} at #{contractAddress}")
abi = JSON.stringify(contract.info.abiDefinition)
result += "var #{className}Abi = #{abi};"
result += "var #{className}Contract = web3.eth.contract(#{className}Abi);"
result += "var #{className} = #{className}Contract.at('#{contractAddress}');";
destFile = grunt.config.get("deploy.dest")
grunt.file.write(destFile, result)

View File

@ -1,20 +1,6 @@
module.exports = (grunt) -> module.exports = (grunt) ->
require('shelljs/global')
grunt.registerTask "ipfs", "distribute into ipfs", (env_) => grunt.registerTask "ipfs", "distribute into ipfs", (env_) =>
env = env_ || "development" Embark = require('embark-framework')
Embark.Release.ipfs()
ipfs_path = "~/go/bin"
build_dir = "dist/dapp/"
cmd = "#{ipfs_path}/ipfs add -r #{build_dir}"
grunt.log.writeln("=== adding #{cmd} to ipfs")
result = exec(cmd)
rows = result.output.split("\n")
dir_row = rows[rows.length - 2]
dir_hash = dir_row.split(" ")[1]
grunt.log.writeln("=== DApp available at http://localhost:8080/ipfs/#{dir_hash}/")
grunt.log.writeln("=== DApp available at http://gateway.ipfs.io/ipfs/#{dir_hash}/")

View File

@ -1,11 +1,11 @@
module.exports = (grunt) -> module.exports = (grunt) ->
express = require("express") express = require("express")
compression = require("compression") compression = require("compression")
readYaml = require('read-yaml'); readYaml = require('read-yaml')
serverConfig = readYaml.sync("config/server.yml")
grunt.registerTask "server", "static file development server", => grunt.registerTask "server", "static file development server", =>
serverConfig = readYaml.sync("config/server.yml")
webPort = serverConfig.port || 8000 webPort = serverConfig.port || 8000
webHost = serverConfig.host || 'localhost' webHost = serverConfig.host || 'localhost'
webRoot = "generated/dapp" webRoot = "generated/dapp"

2
test/test.js Normal file
View File

@ -0,0 +1,2 @@
EmbarkSpec = require('../lib/test.js').Tests;