Merge pull request #361 from embark-framework/graphviz-contracts
Graphviz contracts
This commit is contained in:
commit
82726e07e1
14
lib/cmd.js
14
lib/cmd.js
|
@ -18,6 +18,7 @@ class Cmd {
|
|||
this.simulator();
|
||||
this.test();
|
||||
this.reset();
|
||||
this.graph();
|
||||
this.upload();
|
||||
this.versionCmd();
|
||||
this.otherCommands();
|
||||
|
@ -179,6 +180,18 @@ class Cmd {
|
|||
});
|
||||
}
|
||||
|
||||
graph() {
|
||||
program
|
||||
.command('graph [environment]')
|
||||
.description('generates documentation based on the smart contracts configured')
|
||||
.action(function (env, options) {
|
||||
embark.graph({
|
||||
env: env || 'development',
|
||||
logfile: options.logfile
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
reset() {
|
||||
program
|
||||
.command('reset')
|
||||
|
@ -214,6 +227,7 @@ class Cmd {
|
|||
process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
const Viz = require('viz.js');
|
||||
const fs = require('fs');
|
||||
|
||||
class GraphGenerator {
|
||||
constructor(engine) {
|
||||
this.engine = engine;
|
||||
}
|
||||
|
||||
generate() {
|
||||
let id = 0;
|
||||
let contractString = "";
|
||||
let relationshipString = "";
|
||||
let idMapping = {};
|
||||
let contractInheritance = {};
|
||||
|
||||
|
||||
for (let contract in this.engine.contractsManager.contracts) {
|
||||
id++;
|
||||
|
||||
idMapping[contract] = id;
|
||||
|
||||
let contractLabel = "";
|
||||
|
||||
contractLabel += `${contract}`;
|
||||
let tooltip = contract;
|
||||
|
||||
if(this.engine.contractsManager.contracts[contract].instanceOf !== undefined &&
|
||||
this.engine.contractsManager.contracts[this.engine.contractsManager.contracts[contract].instanceOf] !== undefined){
|
||||
contractInheritance[contract] = this.engine.contractsManager.contracts[contract].instanceOf;
|
||||
contractLabel += ": " + this.engine.contractsManager.contracts[contract].instanceOf;
|
||||
tooltip += " instance of " + this.engine.contractsManager.contracts[contract].instanceOf;
|
||||
} else {
|
||||
contractLabel += "|";
|
||||
|
||||
for(let i = 0; i < this.engine.contractsManager.contracts[contract].abiDefinition.length; i++){
|
||||
switch(this.engine.contractsManager.contracts[contract].abiDefinition[i].type){
|
||||
case 'fallback':
|
||||
contractLabel += "«fallback»()\\l";
|
||||
break;
|
||||
case 'constructor':
|
||||
contractLabel += "«constructor»(";
|
||||
this.engine.contractsManager.contracts[contract].abiDefinition[i].inputs.forEach(function(elem, index){
|
||||
contractLabel += (index == 0 ? "" : ", ") + elem.type;
|
||||
});
|
||||
contractLabel += ")\\l";
|
||||
break;
|
||||
case 'event':
|
||||
contractLabel += "«event»" + this.engine.contractsManager.contracts[contract].abiDefinition[i].name + "(";
|
||||
this.engine.contractsManager.contracts[contract].abiDefinition[i].inputs.forEach(function(elem, index){
|
||||
contractLabel += (index == 0 ? "" : ", ") + elem.type;
|
||||
});
|
||||
contractLabel += ")\\l";
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
let fHashes = this.engine.contractsManager.contracts[contract].functionHashes;
|
||||
if(fHashes != {} && fHashes != undefined){
|
||||
for(let method in this.engine.contractsManager.contracts[contract].functionHashes){
|
||||
contractLabel += method + '\\l';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let others = '';
|
||||
if(!this.engine.contractsManager.contracts[contract].deploy){
|
||||
others = 'fontcolor="#c3c3c3", color="#a0a0a0"';
|
||||
tooltip += " (not deployed)";
|
||||
}
|
||||
|
||||
contractString += `${id}[label = "{${contractLabel}}", tooltip="${tooltip}", fillcolor=gray95, ${others}]\n`;
|
||||
|
||||
}
|
||||
|
||||
for (let c in this.engine.contractsManager.contractDependencies){
|
||||
let contractDependencies = Array.from(new Set(this.engine.contractsManager.contractDependencies[c]));
|
||||
contractDependencies.forEach(function(d){
|
||||
if(idMapping[c] !== undefined && idMapping[d] !== undefined){
|
||||
relationshipString += `${idMapping[d]}->${idMapping[c]}[constraint=true, arrowtail=diamond, tooltip="${c} uses ${d}"]\n`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (let c in contractInheritance){
|
||||
relationshipString += `${idMapping[contractInheritance[c]]}->${idMapping[c]}[tooltip="${c} instance of ${contractInheritance[c]}"]\n`;
|
||||
}
|
||||
|
||||
|
||||
let dot = `
|
||||
digraph Contracts {
|
||||
node[shape=record,style=filled]
|
||||
edge[dir=back, arrowtail=empty]
|
||||
${contractString}
|
||||
${relationshipString}
|
||||
}`;
|
||||
|
||||
let svg = Viz(dot);
|
||||
|
||||
let filename = "diagram.svg";
|
||||
|
||||
fs.writeFileSync(filename, svg, (err) => {
|
||||
if (err) throw err;
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GraphGenerator;
|
|
@ -17,6 +17,7 @@ class DeployManager {
|
|||
this.gasLimit = false;
|
||||
this.fatalErrors = false;
|
||||
this.deployOnlyOnConfig = false;
|
||||
this.onlyCompile = options.onlyCompile !== undefined ? options.onlyCompile : false;
|
||||
}
|
||||
|
||||
deployContracts(done) {
|
||||
|
@ -33,6 +34,13 @@ class DeployManager {
|
|||
self.contractsManager.deployOnlyOnConfig = self.deployOnlyOnConfig; // temporary, should refactor
|
||||
self.contractsManager.build(callback);
|
||||
},
|
||||
function checkCompileOnly(contractsManager, callback){
|
||||
if(self.onlyCompile){
|
||||
self.events.emit('contractsDeployed', contractsManager);
|
||||
return done();
|
||||
}
|
||||
return callback(contractsManager, null);
|
||||
},
|
||||
function checkWeb3IsConnected(contractsManager, callback) {
|
||||
if (!self.web3) {
|
||||
return callback(Error("no web3 instance found"));
|
||||
|
|
|
@ -153,7 +153,8 @@ class Engine {
|
|||
logger: this.logger,
|
||||
plugins: this.plugins,
|
||||
events: this.events,
|
||||
contractsManager: this.contractsManager
|
||||
contractsManager: this.contractsManager,
|
||||
onlyCompile: options.onlyCompile
|
||||
});
|
||||
|
||||
this.events.on('file-event', function (fileType, _path) {
|
||||
|
|
47
lib/index.js
47
lib/index.js
|
@ -194,6 +194,53 @@ class Embark {
|
|||
return new Test(options);
|
||||
}
|
||||
|
||||
graph(options) {
|
||||
options.onlyCompile = true;
|
||||
|
||||
let engine = new Engine({
|
||||
env: options.env,
|
||||
version: this.version,
|
||||
embarkConfig: options.embarkConfig || 'embark.json',
|
||||
logfile: options.logfile
|
||||
});
|
||||
engine.init();
|
||||
|
||||
|
||||
async.parallel([
|
||||
|
||||
function (callback) {
|
||||
let pluginList = engine.plugins.listPlugins();
|
||||
if (pluginList.length > 0) {
|
||||
engine.logger.info("loaded plugins: " + pluginList.join(", "));
|
||||
}
|
||||
|
||||
engine.startMonitor();
|
||||
engine.startService("libraryManager");
|
||||
engine.startService("pipeline");
|
||||
engine.startService("codeGenerator");
|
||||
engine.startService("deployment", {onlyCompile: true});
|
||||
|
||||
engine.deployManager.deployContracts(function (err) {
|
||||
callback(err);
|
||||
});
|
||||
}
|
||||
], function (err, _result) {
|
||||
if (err) {
|
||||
engine.logger.error(err.message);
|
||||
engine.logger.info(err.stack);
|
||||
} else {
|
||||
|
||||
const GraphGenerator = require('./cmds/graph.js');
|
||||
let graphGen = new GraphGenerator(engine);
|
||||
graphGen.generate();
|
||||
|
||||
engine.logger.info("Done".underline);
|
||||
process.exit();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
reset() {
|
||||
let resetCmd = require('./cmds/reset.js');
|
||||
resetCmd();
|
||||
|
|
|
@ -10063,6 +10063,11 @@
|
|||
"extsprintf": "1.3.0"
|
||||
}
|
||||
},
|
||||
"viz.js": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/viz.js/-/viz.js-1.8.1.tgz",
|
||||
"integrity": "sha512-KrSNgnIxec+JCAqDPliO6xYA69ToH2WTYB2Kbt8Bp/XRUvm23rTyfffFi4rvQLFkIRNUz/xCnnqhh/gChhsgGA=="
|
||||
},
|
||||
"vlq": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
"underscore": "^1.8.3",
|
||||
"underscore.string": "^3.3.4",
|
||||
"url-loader": "^0.6.2",
|
||||
"viz.js": "^1.8.1",
|
||||
"web3": "1.0.0-beta.27",
|
||||
"webpack": "^3.10.0",
|
||||
"window-size": "^1.1.0"
|
||||
|
|
Loading…
Reference in New Issue