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"
|
||||
integrity sha1-xUmCuZbHbvDB5rWfvcWCX1txMRM=
|
||||
|
||||
shelljs@^0.8.2:
|
||||
shelljs@^0.8.1, shelljs@^0.8.2:
|
||||
version "0.8.3"
|
||||
resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097"
|
||||
integrity sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==
|
||||
|
|
Loading…
Reference in New Issue