UNPKG

@authereum/zos

Version:

Command-line interface for the ZeppelinOS smart contract platform

146 lines 7.88 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const path_1 = __importDefault(require("path")); const lodash_max_1 = __importDefault(require("lodash.max")); const lodash_maxby_1 = __importDefault(require("lodash.maxby")); const lodash_pick_1 = __importDefault(require("lodash.pick")); const lodash_omitby_1 = __importDefault(require("lodash.omitby")); const lodash_isundefined_1 = __importDefault(require("lodash.isundefined")); const fs_extra_1 = require("fs-extra"); const fs_1 = require("fs"); const zos_lib_1 = require("zos-lib"); const SolidityContractsCompiler_1 = require("./SolidityContractsCompiler"); const imports_fs_1 = require("@resolver-engine/imports-fs"); const ResolverEngineGatherer_1 = require("./ResolverEngineGatherer"); const solidity_1 = require("../../../utils/solidity"); const try_1 = require("../../../utils/try"); function compileProject(options = {}) { return __awaiter(this, void 0, void 0, function* () { const inputDir = options.inputDir || zos_lib_1.Contracts.getLocalContractsDir(); const outputDir = options.outputDir || zos_lib_1.Contracts.getLocalBuildDir(); const projectCompiler = new SolidityProjectCompiler(inputDir, outputDir, options); yield projectCompiler.call(); return { contracts: projectCompiler.contracts, compilerVersion: projectCompiler.compilerVersion, }; }); } exports.compileProject = compileProject; class SolidityProjectCompiler { constructor(inputDir, outputDir, options = {}) { this.inputDir = inputDir; this.outputDir = outputDir; this.roots = []; this.contracts = []; this.compilerOutput = []; this.options = options; } call() { return __awaiter(this, void 0, void 0, function* () { yield this._loadSoliditySourcesFromDir(); yield this._loadDependencies(); if (this.contracts.length === 0) { zos_lib_1.Loggy.noSpin(__filename, 'call', 'compile-contracts', 'No contracts found to compile.'); return; } yield this._resolveCompilerVersion(); if (!this._shouldCompile()) { zos_lib_1.Loggy.noSpin(__filename, 'call', `compile-contracts`, 'Nothing to compile, all contracts are up to date.'); return; } zos_lib_1.Loggy.spin(__filename, 'call', 'compile-contracts', `Compiling contracts with solc ${this.compilerVersion.version} (${this.compilerVersion.build})`); this.compilerOutput = yield SolidityContractsCompiler_1.compileWith(this.compilerVersion, this.contracts, this.options); this._writeOutput(); zos_lib_1.Loggy.succeed('compile-contracts', `Compiled contracts with solc ${this.compilerVersion.version} (${this.compilerVersion.build})`); }); } _loadSoliditySourcesFromDir(dir = this.inputDir) { // TODO: Replace by a glob expression fs_1.readdirSync(dir).forEach(fileName => { const filePath = path_1.default.resolve(dir, fileName); if (fs_1.lstatSync(filePath).isDirectory()) { this._loadSoliditySourcesFromDir(filePath); } else if (path_1.default.extname(filePath).toLowerCase() === '.sol') { this.roots.push(filePath); } }); } _loadDependencies() { return __awaiter(this, void 0, void 0, function* () { const importFiles = yield ResolverEngineGatherer_1.gatherSources(this.roots, this.inputDir, imports_fs_1.ImportsFsEngine()); const cwd = process.cwd(); this.contracts = importFiles.map(file => ({ fileName: path_1.default.basename(file.url), filePath: path_1.default.isAbsolute(file.url) ? path_1.default.relative(cwd, file.url) : file.url, source: file.source, lastModified: try_1.tryFunc(() => fs_1.statSync(file.url).mtimeMs), })); }); } _resolveCompilerVersion() { return __awaiter(this, void 0, void 0, function* () { this.compilerVersion = yield SolidityContractsCompiler_1.resolveCompilerVersion(this.contracts, this.options); }); } _shouldCompile() { const artifacts = this._listArtifacts(); const artifactsWithMtimes = artifacts.map(artifact => ({ artifact, mtime: fs_1.statSync(artifact).mtimeMs, })); // We pick a single artifact (the most recent one) to get the version it was compiled with const latestArtifact = lodash_maxby_1.default(artifactsWithMtimes, 'mtime'); const latestSchema = latestArtifact && fs_extra_1.readJsonSync(latestArtifact.artifact); const artifactCompiledVersion = latestSchema && latestSchema.compiler.version; const artifactSettings = latestSchema && lodash_pick_1.default(latestSchema.compiler, 'evmVersion', 'optimizer'); // Build current settings based on defaults const currentSettings = Object.assign({ optimizer: SolidityContractsCompiler_1.DEFAULT_OPTIMIZER, evmVersion: SolidityContractsCompiler_1.DEFAULT_EVM_VERSION }, lodash_omitby_1.default(this.options, lodash_isundefined_1.default)); // Gather artifacts vs sources modified times const maxArtifactsMtimes = lodash_max_1.default(artifactsWithMtimes.map(({ mtime }) => mtime)); const maxSourcesMtimes = lodash_max_1.default(this.contracts.map(({ lastModified }) => lastModified)); // Compile if there are no previous artifacts, or no mtimes could be collected for sources, // or sources were modified after artifacts, or compiler version changed, or compiler settings changed return (!maxArtifactsMtimes || !maxSourcesMtimes || maxArtifactsMtimes < maxSourcesMtimes || !artifactCompiledVersion || !solidity_1.compilerVersionsMatch(artifactCompiledVersion, this.compilerVersion.longVersion) || !solidity_1.compilerSettingsMatch(currentSettings, artifactSettings)); } _writeOutput() { // Create directory if not exists, or clear it of artifacts if it does if (!fs_1.existsSync(this.outputDir)) fs_extra_1.ensureDirSync(this.outputDir); else this._listArtifacts().forEach(filePath => fs_1.unlinkSync(filePath)); // Write compiler output this.compilerOutput.forEach(data => { const buildFileName = `${this.outputDir}/${data.contractName}.json`; fs_extra_1.writeJsonSync(buildFileName, data); }); } _listArtifacts() { if (!fs_1.existsSync(this.outputDir)) return []; return fs_1.readdirSync(this.outputDir) .map(fileName => path_1.default.resolve(this.outputDir, fileName)) .filter(fileName => !fs_1.lstatSync(fileName).isDirectory()) .filter(fileName => path_1.default.extname(fileName) === '.json'); } } //# sourceMappingURL=SolidityProjectCompiler.js.map