embark/lib/config/contracts.js

165 lines
4.6 KiB
JavaScript

var readYaml = require('read-yaml');
var fs = require('fs');
var toposort = require('toposort');
ContractsConfig = function(blockchainConfig, compiler) {
this.blockchainConfig = blockchainConfig;
this.compiler = compiler;
this.contractFiles = [];
}
ContractsConfig.prototype.init = function(files, env) {
this.all_contracts = [];
this.contractDB = {};
this.contractFiles = files;
this.contractDependencies = {};
this.contractStubs = {};
//TODO: have to specify environment otherwise wouldn't work with staging
if (this.blockchainConfig.config != undefined) {
//this.blockchainConfig = this.blockchainConfig.config('development');
this.blockchainConfig = this.blockchainConfig.config(env);
}
};
ContractsConfig.prototype.loadConfigFile = function(filename) {
try {
this.contractConfig = readYaml.sync(filename);
} catch (e) {
throw new Error("error reading " + filename);
}
return this;
};
ContractsConfig.prototype.loadConfig = function(config) {
this.contractConfig = config;
return this;
};
ContractsConfig.prototype.config = function(env) {
return this.contractConfig[env];
};
ContractsConfig.prototype.is_a_interface = function(target, className) {
if (this.contractStubs[className] && this.contractStubs[className].indexOf(target) >= 0)
return true;
return false;
};
ContractsConfig.prototype.compileContracts = function(env) {
var contractFile, source, j;
var contractsConfig = this.config(env);
this.compiler.init(env);
// determine dependencies
if (contractsConfig != null) {
for (className in contractsConfig) {
options = contractsConfig[className];
if (options.args == null) continue;
ref = options.args; //get arguments
for (j = 0; j < ref.length; j++) {
arg = ref[j];
if (arg[0] === "$") { //check if they are a contract dependency
if (this.contractDependencies[className] === void 0) {
this.contractDependencies[className] = [];
}
this.contractDependencies[className].push(arg.substr(1));
}
}
this.contractStubs[className] = options.stubs;
}
}
compiled_contracts = this.compiler.compile(this.contractFiles); //compile and push to contract DB
for (var className in compiled_contracts) {
if (this.is_a_interface(className, compiled_contracts)) {
continue;
}
this.all_contracts.push(className);
this.contractDB[className] = {
args: [],
types: ['file'],
gasPrice: this.blockchainConfig.gasPrice,
gasLimit: this.blockchainConfig.gasLimit,
compiled: compiled_contracts[className]
}
}
this.configureContractsParameters(contractsConfig);
this.sortContracts();
};
ContractsConfig.prototype.configureContractsParameters = function(contractsConfig) {
for(className in contractsConfig) {
var contractConfig = contractsConfig[className];
var contract;
contract = this.contractDB[className];
if (contract === undefined) {
contract = {
args: [],
types: ['file'],
gasPrice: this.blockchainConfig.gasPrice,
gasLimit: this.blockchainConfig.gasLimit,
compiled: contract
}
this.contractDB[className] = contract;
}
contract.gasPrice = contractConfig.gas_price || contract.gasPrice;
contract.gasLimit = contractConfig.gas_limit || contract.gasLimit;
contract.args = contractConfig.args || [];
contract.address = contractConfig.address;
contract.onDeploy = contractConfig.onDeploy || [];
if (contractConfig.instanceOf !== undefined) {
contract.types.push('instance');
contract.instanceOf = contractConfig.instanceOf;
contract.compiled = compiled_contracts[contractConfig.instanceOf];
}
if (contractConfig.address !== undefined) {
contract.types.push('static');
}
contract.deploy = contractConfig.deploy;
if (contractConfig.deploy === undefined) {
contract.deploy = true;
}
if (this.all_contracts.indexOf(className) < 0) {
this.all_contracts.push(className);
}
}
}
ContractsConfig.prototype.sortContracts = function() {
var converted_dependencies = [], i;
for(contract in this.contractDependencies) {
var dependencies = this.contractDependencies[contract];
for(i=0; i < dependencies.length; i++) {
converted_dependencies.push([contract, dependencies[i]]);
}
}
var orderedDependencies = toposort(converted_dependencies).reverse();
this.all_contracts = this.all_contracts.sort(function(a,b) {
var order_a = orderedDependencies.indexOf(a);
var order_b = orderedDependencies.indexOf(b);
return order_a - order_b;
});;
};
module.exports = ContractsConfig;