@melonproject/protocol
Version:
Technology Regulated and Operated Investment Funds
126 lines (100 loc) • 3.48 kB
text/typescript
import * as fs from 'fs';
import * as path from 'path';
import * as glob from 'glob';
import * as solc from 'solc';
import * as mkdirp from 'mkdirp';
import * as R from 'ramda';
import * as rimraf from 'rimraf';
const soliditySourceDirectory = path.join(__dirname, '..', 'src', 'contracts');
const solidityCompileTarget = path.join(__dirname, '..', 'out');
const debug = require('debug').default('melon:protocol:bin');
const findImports = (missingPath: string, b, c) => {
const query = path.join(soliditySourceDirectory, '**', missingPath);
const candidates = glob.sync(query);
if (candidates.length > 1) {
throw new Error(
`Multiple source files named ${missingPath} found. ${candidates}`,
);
}
if (candidates.length === 0) {
throw new Error(`Can not find import named: ${missingPath}`);
}
debug('Resolved import', missingPath, candidates[0]);
const contents = fs.readFileSync(candidates[0], { encoding: 'utf-8' });
return {
contents,
};
};
const writeFiles = (compileOutput, contract) => {
const [sourceName, contractName] = contract.split(':');
const parsedPath = path.parse(sourceName);
const targetDir = path.join(solidityCompileTarget, parsedPath.dir);
const targetBasePath = path.join(targetDir, contractName);
debug('Writing', contract);
mkdirp.sync(targetDir);
if (fs.existsSync(`${targetBasePath}.abi`)) {
console.warn(
// tslint:disable-next-line:max-line-length
`Contract name duplication detected: ${targetBasePath}.abi. Please make sure that every contract is uniquely named across all dirctories.`,
);
}
fs.writeFileSync(`${targetBasePath}.bin`, compileOutput.bytecode);
fs.writeFileSync(
`${targetBasePath}.abi.json`,
JSON.stringify(JSON.parse(compileOutput.interface), null, 2),
);
fs.writeFileSync(`${targetBasePath}.abi`, compileOutput.interface);
fs.writeFileSync(
`${targetBasePath}.gasEstimates.json`,
JSON.stringify(compileOutput.gasEstimates, null, 2),
);
};
export const compileGlob = (
query = path.join(soliditySourceDirectory, '**', '*.sol'),
) => {
const candidates = glob.sync(query);
debug(`Compiling ${query}, ${candidates.length} files ...`);
const unmerged = candidates.map(source => ({
[path.basename(source)]: fs.readFileSync(source, {
encoding: 'utf-8',
}),
}));
const sources = R.mergeAll(unmerged);
const output = solc.compile({ sources }, 1, findImports);
const messages = output.errors;
const errors = [];
const warnings = [];
messages.forEach(msg => {
if (msg.match(/^(.*:[0-9]*:[0-9]* )?Warning: /)) {
warnings.push(msg);
} else {
errors.push(msg);
}
process.stderr.write(msg);
});
debug('Writing compilation results');
if (query === path.join(soliditySourceDirectory, '**', '*.sol')) {
// Delete and recreate out/
rimraf.sync(solidityCompileTarget);
mkdirp.sync(solidityCompileTarget);
}
fs.writeFileSync(
path.join(solidityCompileTarget, 'compilerResult.json'),
JSON.stringify(output, null, 2),
);
if (messages.length > 0) {
fs.writeFileSync(
path.join(solidityCompileTarget, 'compilerMessages.txt'),
output.errors.join('\n\n'),
);
}
R.forEachObjIndexed(writeFiles, output.contracts);
if (errors.length > 0) {
debug('Finished with errors');
process.stderr.write(errors.join('\n\n'));
process.exit(1);
} else {
debug('Finished');
process.exit(0);
}
};