UNPKG

locklift

Version:

Node JS framework for working with Ever contracts. Inspired by Truffle and Hardhat. Helps you to build, test, run and maintain your smart contracts.

255 lines (254 loc) 13.6 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.compileBySolD = exports.compileBySolC = exports.resolveExternalContracts = exports.isValidCompilerOutputLog = exports.tryToGetNodeModules = exports.execSyncWrapper = exports.extractContractName = exports.tvcToBase64 = exports.compilerConfigResolver = exports.flatDirTree = exports.checkDirEmpty = void 0; const fs_1 = __importDefault(require("fs")); const constants_1 = require("../../compilerComponentsStore/constants"); const compilerComponentsStore_1 = require("../../compilerComponentsStore"); const child_process_1 = require("child_process"); const path_1 = __importStar(require("path")); const util_1 = require("util"); const logger_1 = require("../../logger"); const rxjs_1 = require("rxjs"); const preload_1 = __importDefault(require("semver/preload")); function checkDirEmpty(dir) { if (!fs_1.default.existsSync(dir)) { return dir; } return fs_1.default.readdirSync(dir).length === 0; } exports.checkDirEmpty = checkDirEmpty; function flatDirTree(tree) { return tree.children?.reduce((acc, current) => { if (current.children === undefined) { return [...acc, current]; } const flatChild = flatDirTree(current); if (!flatChild) return acc; return [...acc, ...flatChild]; }, []); } exports.flatDirTree = flatDirTree; const compilerConfigResolver = async ({ compiler, linker, }) => { const builderConfig = { includesPath: compiler.includesPath, externalContracts: compiler.externalContracts, compilerParams: compiler.compilerParams, externalContractsArtifacts: compiler.externalContractsArtifacts, }; if ("path" in compiler) { builderConfig.compilerPath = compiler.path; } if ("version" in compiler) { if (preload_1.default.lte(compiler.version, "0.71.0")) { builderConfig.compilerPath = await (0, compilerComponentsStore_1.getComponent)({ component: constants_1.ComponentType.COMPILER, version: compiler.version, }); builderConfig.mode = "solc"; } if (preload_1.default.gte(compiler.version, "0.72.0") && preload_1.default.lt(compiler.version, "0.77.0")) { builderConfig.compilerPath = await (0, compilerComponentsStore_1.getComponent)({ component: constants_1.ComponentType.SOLD_COMPILER, version: compiler.version, }); builderConfig.mode = "sold"; } if (preload_1.default.gte(compiler.version, "0.77.0")) { builderConfig.compilerPath = await (0, compilerComponentsStore_1.getComponent)({ component: constants_1.ComponentType.SOLD_COMPILER_TYCHO, version: compiler.version, }); builderConfig.mode = "sold"; } } if (linker && "path" in linker) { builderConfig.linkerPath = linker.path; builderConfig.linkerLibPath = linker.lib; } if (linker && "version" in linker) { if (!("version" in compiler)) { throw new Error("You can't provide linker version without compiler version!"); } if (preload_1.default.gte(compiler.version, "0.77.0")) { logger_1.logger.printWarn("Linker for version 0.77.0 and grater is deprecated."); return builderConfig; } builderConfig.linkerPath = await (0, compilerComponentsStore_1.getComponent)({ version: linker.version, component: constants_1.ComponentType.LINKER, }); builderConfig.linkerLibPath = await (0, compilerComponentsStore_1.getComponent)({ version: compiler.version, component: constants_1.ComponentType.LIB, }); } return builderConfig; }; exports.compilerConfigResolver = compilerConfigResolver; const tvcToBase64 = (tvc) => tvc.toString("base64"); exports.tvcToBase64 = tvcToBase64; const extractContractName = (pathToFile) => // eslint-disable-next-line @typescript-eslint/no-non-null-assertion pathToFile.match(new RegExp("contracts(.*).sol"))[1].slice(1); exports.extractContractName = extractContractName; function execSyncWrapper(command, options) { try { return (0, child_process_1.execSync)(command, options); } catch (err) { const ioError = err; throw new Error(`${ioError.toString()}stdout: ${ioError.stdout.toString()}`); } } exports.execSyncWrapper = execSyncWrapper; const tryToGetNodeModules = () => { const findNodeModules = require("find-node-modules"); try { return (0, path_1.resolve)(findNodeModules()[0]); } catch (e) { return undefined; } }; exports.tryToGetNodeModules = tryToGetNodeModules; const isValidCompilerOutputLog = (output) => !!output.trim() && output.trim() !== "Compiler run successful, no output requested."; exports.isValidCompilerOutputLog = isValidCompilerOutputLog; const resolveExternalContracts = async (externalContracts) => { return Promise.all(Object.entries(externalContracts || {}).map(async ([pathToFolder, contractsNames]) => { const folderFiles = await (0, util_1.promisify)(fs_1.default.readdir)(pathToFolder).catch(() => { throw new Error(`Cannot read folder ${pathToFolder} that was provided in config.externalContracts`); }); const contractsArtifacts = folderFiles .filter(file => contractsNames.some(contract => contract === file.split(".")[0])) .filter(file => file.endsWith(".abi.json") || file.endsWith(".tvc") || file.endsWith(".base64")) .map(file => path_1.default.join(pathToFolder, file)); if (contractsArtifacts.length > 0) { logger_1.logger.printWarn(`config.compiler.externalContracts WARNING: Folder ${pathToFolder} contains contract artifacts, but this is deprecated, please use config.compiler.externalContractsArtifacts instead`); } const contractFiles = folderFiles .filter(file => file.endsWith(".tsol") || file.endsWith(".sol")) .filter(file => contractsNames.some(contract => contract === file.split(".")[0])) .map(file => path_1.default.join(pathToFolder, file)); return { contractsArtifacts, contractFiles, }; })).then(contractsAndArtifacts => contractsAndArtifacts.reduce((acc, { contractsArtifacts, contractFiles }) => { return { contractsToBuild: [...acc.contractsToBuild, ...contractFiles], contractArtifacts: [...acc.contractArtifacts, ...contractsArtifacts], }; }, { contractArtifacts: [], contractsToBuild: [] })); }; exports.resolveExternalContracts = resolveExternalContracts; const compileBySolC = async ({ contracts, compilerVersion, buildFolder, disableIncludePath, compilerPath, compilerParams, linkerLibPath, linkerPath, }) => { await (0, rxjs_1.lastValueFrom)((0, rxjs_1.from)(contracts).pipe((0, rxjs_1.mergeMap)(({ path, contractFileName }) => { const nodeModules = (0, exports.tryToGetNodeModules)(); return (0, rxjs_1.defer)(async () => { if (preload_1.default.lte(compilerVersion, "0.66.0")) { const additionalIncludesPath = `--include-path ${(0, path_1.resolve)(process.cwd(), "node_modules")} ${nodeModules ? `--include-path ${nodeModules}` : ""}`; const includePath = `${additionalIncludesPath}`; const execCommand = `cd ${buildFolder} && \ ${compilerPath} ${!disableIncludePath ? includePath : ""} ${path} ${(compilerParams || []).join(" ")}`; return (0, util_1.promisify)(child_process_1.exec)(execCommand); } if (preload_1.default.gte(compilerVersion, "0.68.0")) { const additionalIncludesPath = `${nodeModules ? `--include-path ${nodeModules}` : ""}`; const includePath = `${additionalIncludesPath} ${"--base-path"} . `; const execCommand = ` ${compilerPath} ${!disableIncludePath ? includePath : ""} -o ${buildFolder} ${path} ${(compilerParams || []).join(" ")}`; return (0, util_1.promisify)(child_process_1.exec)(execCommand); } throw new Error("Unsupported compiler version"); }).pipe((0, rxjs_1.map)(output => ({ output, contractFileName: (0, path_1.parse)(contractFileName).name, path, })), (0, rxjs_1.catchError)(e => { logger_1.logger.printError(`path: ${path}, contractFile: ${contractFileName} error: ${e?.stderr?.toString() || e}`); return (0, rxjs_1.throwError)(undefined); })); }), //Warnings (0, rxjs_1.tap)(output => (0, exports.isValidCompilerOutputLog)(output.output.stderr.toString()) && logger_1.logger.printBuilderLog(output.output.stderr.toString())), (0, rxjs_1.filter)(({ output }) => { //Only contracts return !!output?.stdout.toString(); }), (0, rxjs_1.mergeMap)(({ contractFileName }) => { const lib = linkerLibPath ? ` --lib ${linkerLibPath} ` : ""; const resolvedPathCode = (0, path_1.resolve)(buildFolder, `${contractFileName}.code`); const resolvedPathAbi = (0, path_1.resolve)(buildFolder, `${contractFileName}.abi.json`); const resolvedPathMap = (0, path_1.resolve)(buildFolder, `${contractFileName}.map.json`); return (0, rxjs_1.defer)(async () => { const command = `${linkerPath} compile "${resolvedPathCode}" -a "${resolvedPathAbi}" -o ${(0, path_1.resolve)(buildFolder, `${contractFileName}.tvc`)} ${lib} --debug-map ${resolvedPathMap}`; return (0, util_1.promisify)(child_process_1.exec)(command); }).pipe((0, rxjs_1.map)(tvmLinkerLog => { return tvmLinkerLog.stdout.toString().match(new RegExp("Saved to file (.*).")); }), (0, rxjs_1.catchError)(e => { logger_1.logger.printError(`contractFileName: ${contractFileName} error:${e?.stderr?.toString()}`); return (0, rxjs_1.throwError)(undefined); }), (0, rxjs_1.map)(matchResult => { if (!matchResult) { throw new Error("Linking error, noting linking"); } return matchResult[1]; }), (0, rxjs_1.mergeMap)(tvcFile => { return (0, rxjs_1.concat)((0, rxjs_1.defer)(() => (0, util_1.promisify)(fs_1.default.writeFile)((0, path_1.resolve)(buildFolder, `${contractFileName}.base64`), (0, exports.tvcToBase64)(fs_1.default.readFileSync(tvcFile))))).pipe((0, rxjs_1.catchError)(e => { logger_1.logger.printError(e?.stderr?.toString()); return (0, rxjs_1.throwError)(undefined); })); })); }), (0, rxjs_1.toArray)())); }; exports.compileBySolC = compileBySolC; const compileBySolD = async ({ contracts, compilerVersion, buildFolder, disableIncludePath, compilerPath, compilerParams, }) => { await (0, rxjs_1.lastValueFrom)((0, rxjs_1.from)(contracts).pipe((0, rxjs_1.mergeMap)(({ path, contractFileName }) => { const nodeModules = (0, exports.tryToGetNodeModules)(); return (0, rxjs_1.defer)(async () => { if (preload_1.default.gte(compilerVersion, "0.72.0")) { const additionalIncludesPath = `${nodeModules ? `--include-path ${nodeModules}` : ""}`; const includePath = `${additionalIncludesPath} ${"--base-path"} . `; const execCommand = ` ${compilerPath} ${!disableIncludePath ? includePath : ""} -o ${buildFolder} ${path} ${(compilerParams || []).join(" ")}`; return (0, util_1.promisify)(child_process_1.exec)(execCommand); } throw new Error("Unsupported compiler version"); }).pipe((0, rxjs_1.map)(output => ({ output, contractFileName: (0, path_1.parse)(contractFileName).name, path, })), (0, rxjs_1.catchError)(e => { logger_1.logger.printError(`path: ${path}, contractFile: ${contractFileName} error: ${e?.stderr?.toString() || e}`); return (0, rxjs_1.throwError)(undefined); })); }), //Warnings (0, rxjs_1.tap)(output => (0, exports.isValidCompilerOutputLog)(output.output.stderr.toString()) && logger_1.logger.printBuilderLog(output.output.stderr.toString())), (0, rxjs_1.toArray)())); }; exports.compileBySolD = compileBySolD;