mirror of https://github.com/embarklabs/embark.git
feat(@embark/solc): add embark-solc to monorepo
This commit is contained in:
parent
ad796bc8f8
commit
1e59b58887
|
@ -0,0 +1,5 @@
|
||||||
|
engine-strict = true
|
||||||
|
package-lock = false
|
||||||
|
save-exact = true
|
||||||
|
scripts-prepend-node-path = true
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
Embark-Solc
|
||||||
|
======
|
||||||
|
|
||||||
|
Plugin for [Embark](https://github.com/embark-framework/embark) to compile contracts using solc
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
|
||||||
|
In your embark dapp directory:
|
||||||
|
|
||||||
|
```npm install embark-solc --save```
|
||||||
|
|
||||||
|
then add embark-solc to the plugins section in `embark.json`:
|
||||||
|
|
||||||
|
```Json
|
||||||
|
"plugins": {
|
||||||
|
"embark-solc": {
|
||||||
|
"outputBinary": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- `outputBinary` can be specified to generate a .bin file that contains the binary of the contracts in hex. Default value is `false`.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- [Embark](https://www.npmjs.com/package/embark) 4.0.0 or higher
|
||||||
|
- [Solc](https://github.com/ethereum/solidity/releases) installed and available globally on your machine (h)
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
{
|
||||||
|
"name": "embark-solc",
|
||||||
|
"version": "4.1.0-beta.4",
|
||||||
|
"author": "Richard Ramos",
|
||||||
|
"contributors": [],
|
||||||
|
"description": "Solc plugin for Embark (uses command line)",
|
||||||
|
"homepage": "https://github.com/embark-framework/embark/tree/master/packages/embark-solc#readme",
|
||||||
|
"bugs": "https://github.com/embark-framework/embark/issues",
|
||||||
|
"keywords": [
|
||||||
|
"blockchain",
|
||||||
|
"dapps",
|
||||||
|
"ethereum",
|
||||||
|
"ipfs",
|
||||||
|
"serverless",
|
||||||
|
"solc",
|
||||||
|
"solidity"
|
||||||
|
],
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": {
|
||||||
|
"directory": "packages/embark-solc",
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/embark-framework/embark.git"
|
||||||
|
},
|
||||||
|
"main": "./dist/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"build": "cross-env BABEL_ENV=node babel src --copy-files --extensions \".ts\" --out-dir dist --root-mode upward --source-maps",
|
||||||
|
"ci": "npm run qa",
|
||||||
|
"clean": "npm run reset",
|
||||||
|
"lint": "npm-run-all lint:*",
|
||||||
|
"lint:js": "eslint src/",
|
||||||
|
"// lint:ts": "tslint -c tslint.json \"src/**/*.ts\"",
|
||||||
|
"package": "npm pack",
|
||||||
|
"// qa": "npm-run-all lint typecheck build package",
|
||||||
|
"qa": "npm-run-all lint build package",
|
||||||
|
"reset": "npx rimraf dist embark-*.tgz package",
|
||||||
|
"start": "npm run watch",
|
||||||
|
"// typecheck": "tsc",
|
||||||
|
"watch": "run-p watch:*",
|
||||||
|
"watch:build": "npm run build -- --verbose --watch",
|
||||||
|
"// watch:typecheck": "npm run typecheck -- --preserveWatchOutput --watch"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"extends": "../../.eslintrc.json"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"async": "^2.6.0",
|
||||||
|
"semver": "^5.6.0",
|
||||||
|
"shelljs": "^0.8.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/cli": "7.2.3",
|
||||||
|
"@babel/core": "7.2.2",
|
||||||
|
"cross-env": "5.2.0",
|
||||||
|
"eslint": "5.7.0",
|
||||||
|
"npm-run-all": "4.1.5",
|
||||||
|
"rimraf": "2.6.3",
|
||||||
|
"tslint": "5.16.0",
|
||||||
|
"typescript": "3.4.5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.12.0 <12.0.0",
|
||||||
|
"npm": ">=6.4.1",
|
||||||
|
"yarn": ">=1.12.3"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*global require, module*/
|
||||||
|
const Compiler = require("./lib/Compiler");
|
||||||
|
const semver = require('semver');
|
||||||
|
|
||||||
|
module.exports = (embark) => {
|
||||||
|
if (embark.config.embarkConfig.versions.solc) {
|
||||||
|
embark.registerCompiler('.sol', (contractFiles, options, cb) => {
|
||||||
|
if (!contractFiles || !contractFiles.length) {
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
Compiler.getSolcVersion(embark.logger, (err, version) => {
|
||||||
|
if (err) {
|
||||||
|
embark.logger.error(err);
|
||||||
|
embark.logger.error("Error getting solc's version. Will default back to Embark's compiler");
|
||||||
|
return cb(null, false);
|
||||||
|
}
|
||||||
|
if (semver.lt(version, embark.config.embarkConfig.versions.solc)) {
|
||||||
|
embark.logger.warn(`Current version of solc lower than version in embark.json`);
|
||||||
|
embark.logger.warn(`Current: ${version} | Wanted: ${embark.config.embarkConfig.versions.solc}`);
|
||||||
|
embark.logger.warn('Will default back to Embark\'s compiler');
|
||||||
|
return cb(null, false);
|
||||||
|
}
|
||||||
|
Compiler.compileSolc(embark, contractFiles, embark.config.contractDirectories, options, cb);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,221 @@
|
||||||
|
const async = require('async');
|
||||||
|
const shelljs = require('shelljs');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
function compileSolcContract(logger, compileSettings, allowedDirectories, callback) {
|
||||||
|
const command = `solc --standard-json --allow-paths ${allowedDirectories.join(',')}`;
|
||||||
|
|
||||||
|
shelljs.ShellString(JSON.stringify(compileSettings)).exec(command, {silent: true}, (code, stdout, stderr) => {
|
||||||
|
if (stderr) {
|
||||||
|
logger.warn(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code !== 0) {
|
||||||
|
return callback(`solc exited with error code ${code}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stdout) {
|
||||||
|
return callback('solc execution returned nothing');
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null, stdout.replace(/\n/g, ''));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSolcVersion(logger, callback) {
|
||||||
|
shelljs.exec('solc --version', {silent: true}, (code, stdout, stderr) => {
|
||||||
|
if (stderr) {
|
||||||
|
logger.warn(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code !== 0) {
|
||||||
|
return callback(`solc exited with error code ${code}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stdout) {
|
||||||
|
return callback('solc execution returned nothing');
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = stdout.match(/(\d+.\d+.\d+)/);
|
||||||
|
callback(null, result[1]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function compileSolc(embark, contractFiles, contractDirectories, options, callback) {
|
||||||
|
if (!contractFiles || !contractFiles.length) {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
const logger = embark.logger;
|
||||||
|
const outputBinary = embark.pluginConfig.outputBinary;
|
||||||
|
const outputDir = embark.config.buildDir + embark.config.contractDirectories[0];
|
||||||
|
const solcConfig = embark.config.embarkConfig.options.solc;
|
||||||
|
|
||||||
|
let allowedDirectories = [];
|
||||||
|
const remappings = [];
|
||||||
|
const compilationSettings = {
|
||||||
|
language: 'Solidity',
|
||||||
|
sources: {},
|
||||||
|
settings: {
|
||||||
|
optimizer: {
|
||||||
|
enabled: solcConfig['optimize'],
|
||||||
|
runs: solcConfig['optimize-runs']
|
||||||
|
},
|
||||||
|
remappings,
|
||||||
|
outputSelection: {
|
||||||
|
'*': {
|
||||||
|
'': ['ast'],
|
||||||
|
'*': [
|
||||||
|
'abi',
|
||||||
|
'devdoc',
|
||||||
|
'evm.bytecode',
|
||||||
|
'evm.deployedBytecode',
|
||||||
|
'evm.gasEstimates',
|
||||||
|
'evm.legacyAssembly',
|
||||||
|
'evm.methodIdentifiers',
|
||||||
|
'metadata',
|
||||||
|
'userdoc'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
async.waterfall([
|
||||||
|
function checkSolc(next) {
|
||||||
|
const solc = shelljs.which('solc');
|
||||||
|
if (!solc) {
|
||||||
|
logger.error('solc is not installed on your machine');
|
||||||
|
logger.info('You can install it by following the instructions on: http://solidity.readthedocs.io/en/latest/installing-solidity.html');
|
||||||
|
return next('Compiler not installed');
|
||||||
|
}
|
||||||
|
logger.info("compiling solidity contracts with command line solc...");
|
||||||
|
next();
|
||||||
|
},
|
||||||
|
|
||||||
|
function getContentAndRemappings(next) {
|
||||||
|
async.each(contractFiles, (file, eachCb) => {
|
||||||
|
file.prepareForCompilation(options.isCoverage).then((content) => {
|
||||||
|
// add contract directory and all it's recusrive import direcotries to allowed directories
|
||||||
|
let dir = path.dirname(file.path);
|
||||||
|
if (!allowedDirectories.includes(dir)) allowedDirectories.push(dir);
|
||||||
|
|
||||||
|
file.importRemappings.forEach((importRemapping) => {
|
||||||
|
dir = path.dirname(importRemapping.target);
|
||||||
|
if (!allowedDirectories.includes(dir)) allowedDirectories.push(dir);
|
||||||
|
|
||||||
|
const remapping = `${importRemapping.prefix}=${importRemapping.target}`;
|
||||||
|
if (!remappings.includes(remapping)) {
|
||||||
|
remappings.push(remapping);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO change this to Embark's utils function once embark-solc is in the mono-repo
|
||||||
|
compilationSettings.sources[file.path.replace(/\\/g, '/')] = {
|
||||||
|
content: content.replace(/\r\n/g, '\n')
|
||||||
|
};
|
||||||
|
|
||||||
|
eachCb();
|
||||||
|
}).catch(eachCb);
|
||||||
|
}, next);
|
||||||
|
},
|
||||||
|
|
||||||
|
function compile(next) {
|
||||||
|
compileSolcContract(logger, compilationSettings, allowedDirectories, (err, compileString) => {
|
||||||
|
if (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
let json;
|
||||||
|
try {
|
||||||
|
json = JSON.parse(compileString);
|
||||||
|
} catch (e) {
|
||||||
|
logger.error(e.message || e);
|
||||||
|
return callback(`Compiling returned an unreadable result`);
|
||||||
|
}
|
||||||
|
|
||||||
|
embark.events.emit('contracts:compiled:solc', json);
|
||||||
|
|
||||||
|
const contracts = json.contracts;
|
||||||
|
|
||||||
|
// Check for errors
|
||||||
|
if (json.errors) {
|
||||||
|
let isError = false;
|
||||||
|
json.errors.forEach(error => {
|
||||||
|
if (error.severity === 'error') {
|
||||||
|
isError = true;
|
||||||
|
logger.error(error.formattedMessage);
|
||||||
|
} else {
|
||||||
|
logger.warn(error.formattedMessage);
|
||||||
|
}
|
||||||
|
logger.debug(error.message); // Print more error information in debug
|
||||||
|
});
|
||||||
|
if (isError) {
|
||||||
|
return next(`Error while compiling`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next(null, contracts);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
function populateCompiledObject(contracts, next) {
|
||||||
|
const compiledObject = {};
|
||||||
|
for (let contractFile in contracts) {
|
||||||
|
for (let contractName in contracts[contractFile]) {
|
||||||
|
let contract = contracts[contractFile][contractName];
|
||||||
|
let filename = contractFile;
|
||||||
|
for (let directory of contractDirectories) {
|
||||||
|
let match = new RegExp("^" + directory);
|
||||||
|
filename = filename.replace(match, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
let className = contractName;
|
||||||
|
const contractFileMatch = className.match(/.sol:(.*)/);
|
||||||
|
if (contractFileMatch) {
|
||||||
|
className = contractFileMatch[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
compiledObject[className] = {};
|
||||||
|
compiledObject[className].code = contract.evm.bytecode.object;
|
||||||
|
compiledObject[className].linkReferences = contract.evm.bytecode.linkReferences;
|
||||||
|
compiledObject[className].runtimeBytecode = contract.evm.deployedBytecode.object;
|
||||||
|
compiledObject[className].realRuntimeBytecode = contract.evm.deployedBytecode.object.slice(0, -68);
|
||||||
|
compiledObject[className].swarmHash = contract.evm.deployedBytecode.object.slice(-68).slice(0, 64);
|
||||||
|
compiledObject[className].gasEstimates = contract.evm.gasEstimates;
|
||||||
|
compiledObject[className].functionHashes = contract.evm.methodIdentifiers;
|
||||||
|
compiledObject[className].abiDefinition = contract.abi;
|
||||||
|
compiledObject[className].userdoc = contract.userdoc;
|
||||||
|
compiledObject[className].filename = filename;
|
||||||
|
const normalized = path.normalize(filename);
|
||||||
|
const origContract = contractFiles.find(contractFile => normalized.includes(path.normalize(contractFile.originalPath)));
|
||||||
|
if (origContract) {
|
||||||
|
compiledObject[className].originalFilename = path.normalize(origContract.originalPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next(null, compiledObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
], (err, compiledObject) => {
|
||||||
|
callback(err, compiledObject);
|
||||||
|
|
||||||
|
if (outputBinary) {
|
||||||
|
embark.events.once("outputDone", () => {
|
||||||
|
async.eachOf(compiledObject, (contract, className, eachCb) => {
|
||||||
|
fs.writeFile(path.join(outputDir, className + ".bin"), compiledObject[className].code, eachCb);
|
||||||
|
}, (err) => {
|
||||||
|
if (err) {
|
||||||
|
logger.error("Error writing binary file", err.message || err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
compileSolc,
|
||||||
|
compileSolcContract,
|
||||||
|
getSolcVersion
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"include": ["src/**/*"]
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tslint.json"
|
||||||
|
}
|
|
@ -16698,7 +16698,7 @@ shelljs@0.5.3:
|
||||||
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.5.3.tgz#c54982b996c76ef0c1e6b59fbdc5825f5b713113"
|
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.5.3.tgz#c54982b996c76ef0c1e6b59fbdc5825f5b713113"
|
||||||
integrity sha1-xUmCuZbHbvDB5rWfvcWCX1txMRM=
|
integrity sha1-xUmCuZbHbvDB5rWfvcWCX1txMRM=
|
||||||
|
|
||||||
shelljs@^0.8.2:
|
shelljs@^0.8.1, shelljs@^0.8.2:
|
||||||
version "0.8.3"
|
version "0.8.3"
|
||||||
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097"
|
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097"
|
||||||
integrity sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==
|
integrity sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==
|
||||||
|
|
Loading…
Reference in New Issue