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
JavaScript
;
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;