mirror of
https://github.com/status-im/embark-area-51.git
synced 2025-01-10 05:56:00 +00:00
1d6da99e8f
display last line on tx fix debugger call listen to source event only after jumping to the end keep track of last tx; add minimal debug feature; fix ast issue initial debugger apis & ui integration prevent crash when step is out of bounds; send all all available data in websocket add debugger commands fix line number tracking in editor; toggle breakpoints replace timeouts with callbacks add debugger manager & refactor refactor debugger api refactor cmd line debugger reduce debugger decoupling reduce debugger decoupling fix debug buttons trigger source update so api triggers ws event to update source location move locals and contracts vars to a json view improve debugger icons simplify debugger data update debug package add command handler to get a contract given a tx; update debugger so it can get a contract by its tx instead of tracking latest txs only update debugger package
196 lines
6.5 KiB
JavaScript
196 lines
6.5 KiB
JavaScript
let async = require('../../utils/async_extend.js');
|
|
let SolcW = require('./solcW.js');
|
|
|
|
class Solidity {
|
|
|
|
constructor(embark, options) {
|
|
this.logger = embark.logger;
|
|
this.events = embark.events;
|
|
this.ipc = options.ipc;
|
|
this.contractDirectories = embark.config.contractDirectories;
|
|
this.solcAlreadyLoaded = false;
|
|
this.solcW = null;
|
|
this.useDashboard = options.useDashboard;
|
|
this.options = embark.config.embarkConfig.options.solc;
|
|
|
|
embark.registerCompiler(".sol", this.compile_solidity.bind(this));
|
|
|
|
embark.registerAPICall(
|
|
'post',
|
|
'/embark-api/contract/compile',
|
|
(req, res) => {
|
|
if(typeof req.body.code !== 'string'){
|
|
return res.send({error: 'Body parameter \'code\' must be a string'});
|
|
}
|
|
const input = {[req.body.name]: {content: req.body.code.replace(/\r\n/g, '\n')}};
|
|
this.compile_solidity_code(input, {}, true, {}, (errors, result) => {
|
|
const responseData = {errors: errors, result: result};
|
|
this.logger.trace(`POST response /embark-api/contract/compile:\n ${JSON.stringify(responseData)}`);
|
|
res.send(responseData);
|
|
});
|
|
}
|
|
);
|
|
}
|
|
|
|
_compile(jsonObj, returnAllErrors, callback) {
|
|
const self = this;
|
|
self.solcW.compile(jsonObj, function (err, output) {
|
|
self.events.emit('contracts:compile:solc', jsonObj);
|
|
|
|
if(err){
|
|
return callback(err);
|
|
}
|
|
if (output.errors && returnAllErrors) {
|
|
return callback(output.errors);
|
|
}
|
|
|
|
if (output.errors) {
|
|
for (let i=0; i<output.errors.length; i++) {
|
|
if (output.errors[i].type === 'Warning') {
|
|
self.logger.warn(output.errors[i].formattedMessage);
|
|
}
|
|
if (output.errors[i].type === 'Error' || output.errors[i].severity === 'error') {
|
|
return callback(new Error("Solidity errors: " + output.errors[i].formattedMessage).message);
|
|
}
|
|
}
|
|
}
|
|
|
|
self.events.emit('contracts:compiled:solc', output);
|
|
callback(null, output);
|
|
});
|
|
}
|
|
|
|
compile_solidity_code(codeInputs, originalFilepaths, returnAllErrors, options = {}, cb) {
|
|
const self = this;
|
|
|
|
async.waterfall([
|
|
function loadCompiler(callback) {
|
|
if (self.solcAlreadyLoaded) {
|
|
return callback();
|
|
}
|
|
self.solcW = new SolcW({logger: self.logger, events: self.events, ipc: self.ipc, useDashboard: self.useDashboard});
|
|
|
|
self.logger.info(__("loading solc compiler") + "..");
|
|
self.solcW.load_compiler(function (err) {
|
|
self.solcAlreadyLoaded = true;
|
|
callback(err);
|
|
});
|
|
},
|
|
function compileContracts(callback) {
|
|
self.logger.info(__("compiling solidity contracts") + "...");
|
|
let jsonObj = {
|
|
language: 'Solidity',
|
|
sources: codeInputs,
|
|
settings: {
|
|
optimizer: {
|
|
enabled: (!options.disableOptimizations && self.options.optimize),
|
|
runs: self.options["optimize-runs"]
|
|
},
|
|
outputSelection: {
|
|
'*': {
|
|
'': ['ast', 'legacyAST'], // legacyAST is needed by the debugger, for now
|
|
'*': [
|
|
'abi',
|
|
'devdoc',
|
|
'evm.bytecode',
|
|
'evm.deployedBytecode',
|
|
'evm.gasEstimates',
|
|
'evm.legacyAssembly',
|
|
'evm.methodIdentifiers',
|
|
'metadata',
|
|
'userdoc'
|
|
]
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
self._compile(jsonObj, returnAllErrors, callback);
|
|
},
|
|
function createCompiledObject(output, callback) {
|
|
let json = output.contracts;
|
|
|
|
if (!output || !output.contracts) {
|
|
return callback(new Error(__("error compiling for unknown reasons")));
|
|
}
|
|
|
|
if (Object.keys(output.contracts).length === 0 && output.sourceList && output.sourceList.length > 0) {
|
|
return callback(new Error(__("error compiling. There are sources available but no code could be compiled, likely due to fatal errors in the solidity code")).message);
|
|
}
|
|
|
|
let compiled_object = {};
|
|
|
|
for (let contractFile in json) {
|
|
for (let contractName in json[contractFile]) {
|
|
let contract = json[contractFile][contractName];
|
|
|
|
const className = contractName;
|
|
let filename = contractFile;
|
|
|
|
compiled_object[className] = {};
|
|
compiled_object[className].code = contract.evm.bytecode.object;
|
|
compiled_object[className].runtimeBytecode = contract.evm.deployedBytecode.object;
|
|
compiled_object[className].realRuntimeBytecode = contract.evm.deployedBytecode.object.slice(0, -68);
|
|
compiled_object[className].swarmHash = contract.evm.deployedBytecode.object.slice(-68).slice(0, 64);
|
|
compiled_object[className].gasEstimates = contract.evm.gasEstimates;
|
|
compiled_object[className].functionHashes = contract.evm.methodIdentifiers;
|
|
compiled_object[className].abiDefinition = contract.abi;
|
|
compiled_object[className].filename = filename;
|
|
compiled_object[className].originalFilename = originalFilepaths[filename];
|
|
}
|
|
}
|
|
|
|
callback(null, compiled_object);
|
|
}
|
|
], function (err, result) {
|
|
cb(err, result);
|
|
});
|
|
}
|
|
|
|
compile_solidity(contractFiles, options, cb) {
|
|
if (!contractFiles.length) {
|
|
return cb();
|
|
}
|
|
let self = this;
|
|
let input = {};
|
|
let originalFilepath = {};
|
|
|
|
async.waterfall([
|
|
function prepareInput(callback) {
|
|
async.each(contractFiles,
|
|
function (file, fileCb) {
|
|
let filename = file.filename;
|
|
|
|
for (let directory of self.contractDirectories) {
|
|
let match = new RegExp("^" + directory);
|
|
filename = filename.replace(match, '');
|
|
}
|
|
|
|
originalFilepath[filename] = file.filename;
|
|
|
|
file.content(function (fileContent) {
|
|
if (!fileContent) {
|
|
self.logger.error(__('Error while loading the content of ') + filename);
|
|
return fileCb();
|
|
}
|
|
input[filename] = {content: fileContent.replace(/\r\n/g, '\n')};
|
|
fileCb();
|
|
});
|
|
},
|
|
function (err) {
|
|
callback(err);
|
|
}
|
|
);
|
|
},
|
|
function compile(callback) {
|
|
self.compile_solidity_code(input, originalFilepath, false, options, callback);
|
|
}
|
|
], function (err, result) {
|
|
cb(err, result);
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
module.exports = Solidity;
|