UNPKG

@tevm/compiler

Version:
381 lines (375 loc) 9.87 kB
import { moduleFactory } from '@tevm/resolutions'; import { solcCompile } from '@tevm/solc'; import { Effect } from 'effect'; import { runPromise, runSync } from 'effect/Effect'; import resolve from 'resolve'; // src/compiler/compileContracts.js // src/utils/invariant.js function invariant(condition, message) { if (!condition) { throw new Error(message); } } var resolveEffect = (filePath, basedir, fao, logger) => { return Effect.async((resume) => { resolve( filePath, { basedir, readFile: (file, cb) => { fao.readFile(file, "utf8").then((fileContent) => { cb(null, fileContent); }).catch((e) => { logger.error(e); logger.error("Error reading file"); cb(e); }); }, isFile: async (file, cb) => { try { cb(null, await fao.exists(file)); } catch (e) { cb( /** @type Error */ e ); logger.error( /** @type any */ e ); logger.error(`Error checking if isFile ${file}`); resume(Effect.fail( /** @type Error */ e )); return; } } }, (err, res) => { if (err) { logger.error( /** @type any */ err ); logger.error(`There was an error resolving ${filePath}`); resume(Effect.fail(err)); } else { resume(Effect.succeed( /** @type string */ res )); } } ); }); }; // src/compiler/compileContracts.js var compileContract = async (filePath, basedir, config, includeAst, includeBytecode, fao, logger, solc) => { var _a, _b; const moduleMap = await runPromise( moduleFactory( filePath, await fao.readFile(await Effect.runPromise(resolveEffect(filePath, basedir, fao, logger)), "utf8").then((code) => { return code; }), config.remappings, config.libs, fao, false ) ); const entryModule = moduleMap.get(filePath); invariant(entryModule, "Entry module should exist"); const modules = {}; const stack = [entryModule]; while (stack.length !== 0) { const m = stack.pop(); invariant(m, "Module should exist"); if (m.id in modules) { continue; } modules[m.id] = m; const resolutions = m.importedIds.map((id) => ( /** @type {import("../types.js").ModuleInfo}*/ moduleMap.get(id) )); for (const dep of resolutions) { stack.push(dep); } } const sources = Object.fromEntries( Object.entries(modules).map(([id, module]) => { return [ id, { content: ( /** @type {string} */ module.code ) } ]; }) ); const emptyString = ""; const evmBytecode = ["evm.bytecode.object", "evm.deployedBytecode.object"]; const input = { language: "Solidity", sources, settings: { outputSelection: { "*": { "*": ["abi", "userdoc", ...includeBytecode ? evmBytecode : []], ...includeAst ? { [emptyString]: ["ast"] } : {} } } } }; const output = solcCompile(solc, input); const warnings = (_a = output == null ? void 0 : output.errors) == null ? void 0 : _a.filter(({ type }) => type === "Warning"); const isErrors = (((_b = output == null ? void 0 : output.errors) == null ? void 0 : _b.length) ?? 0) > ((warnings == null ? void 0 : warnings.length) ?? 0); if (isErrors) { logger.error("Compilation errors:"); logger.error( /** @type {any} */ output == null ? void 0 : output.errors ); throw new Error("Compilation failed"); } if (warnings == null ? void 0 : warnings.length) { logger.warn( /** @type {any} */ warnings ); logger.warn("Compilation warnings:"); } if (includeAst) { const asts = Object.fromEntries( Object.entries(output.sources).map(([id, source]) => { return [id, source.ast]; }) ); return { artifacts: output.contracts[entryModule.id], modules: ( /** @type {any} */ modules ), asts: ( /** @type {any} */ asts ), solcInput: input, solcOutput: output }; } return { artifacts: output.contracts[entryModule.id], modules: ( /** @type {any} */ modules ), asts: ( /** @type {any} */ void 0 ), solcInput: input, solcOutput: output }; }; // src/resolveArtifacts.js var resolveArtifacts = async (solFile, basedir, logger, config, includeAst, includeBytecode, fao, solc) => { if (!solFile.endsWith(".sol")) { throw new Error("Not a solidity file"); } const { artifacts, modules, asts, solcInput, solcOutput } = await compileContract( solFile, basedir, config, includeAst, includeBytecode, fao, logger, solc ); if (!artifacts) { logger.error(`Compilation failed for ${solFile}`); throw new Error("Compilation failed"); } return { artifacts: Object.fromEntries( Object.entries(artifacts).map(([contractName, contract]) => { return [ contractName, { contractName, abi: contract.abi, userdoc: contract.userdoc, evm: contract.evm } ]; }) ), modules, asts, solcInput, solcOutput }; }; function compileContractSync(filePath, basedir, config, includeAst, includeBytecode, fao, logger, solc) { var _a, _b; const moduleMap = runSync( moduleFactory( filePath, fao.readFileSync( resolve.sync(filePath, { basedir, readFileSync: (file) => fao.readFileSync(file, "utf8"), isFile: fao.existsSync }), "utf8" ), config.remappings, config.libs, fao, true ) ); const entryModule = moduleMap.get(filePath); invariant(entryModule, "Entry module should exist"); const modules = {}; const stack = [entryModule]; while (stack.length !== 0) { const m = stack.pop(); invariant(m, "Module should exist"); if (m.id in modules) { continue; } modules[m.id] = m; for (const dep of m.importedIds) { stack.push( /** @type {import("../types.js").ModuleInfo} */ moduleMap.get(dep) ); } } const sources = Object.fromEntries( Object.entries(modules).map(([id, module]) => { const code = ( /** @type {string} */ module.code ); return [id, { content: code }]; }) ); const evmBytecode = ["evm.bytecode.object", "evm.deployedBytecode.object"]; const solcInput = { language: "Solidity", sources, settings: { outputSelection: { "*": { "*": [ "abi", "userdoc", ...includeBytecode ? evmBytecode : [], ...includeAst ? ( /** @type {['evm.deployedBytecode.sourceMap', 'evm.bytecode.sourceMap', 'metadata']}*/ [ "evm.deployedBytecode.sourceMap", // Source map for deployed code "evm.bytecode.sourceMap", // Source map for creation code "metadata" // Additional metadata for debugging ] ) : [] ], ...includeAst ? { "": ["ast"] } : {} } } } }; const solcOutput = solcCompile(solc, solcInput); const warnings = (_a = solcOutput == null ? void 0 : solcOutput.errors) == null ? void 0 : _a.filter(({ type }) => type === "Warning"); const isErrors = (((_b = solcOutput == null ? void 0 : solcOutput.errors) == null ? void 0 : _b.length) ?? 0) > ((warnings == null ? void 0 : warnings.length) ?? 0); if (isErrors) { logger.error( "Compilation errors:", /** @type {any}*/ solcOutput == null ? void 0 : solcOutput.errors ); console.log(solcOutput.errors); throw new Error("Compilation failed"); } if (warnings == null ? void 0 : warnings.length) { logger.warn( "Compilation warnings:", /** @type {any}*/ solcOutput == null ? void 0 : solcOutput.errors ); } if (includeAst) { const asts = Object.fromEntries( Object.entries(solcOutput.sources).map(([id, source]) => { return [id, source.ast]; }) ); return { artifacts: solcOutput.contracts[entryModule.id], modules, asts, solcInput, solcOutput }; } return { artifacts: solcOutput.contracts[entryModule.id], modules, asts: void 0, solcInput, solcOutput }; } // src/resolveArtifactsSync.js var resolveArtifactsSync = (solFile, basedir, logger, config, includeAst, includeBytecode, fao, solc) => { if (!solFile.endsWith(".sol")) { throw new Error("Not a solidity file"); } const { artifacts, modules, asts, solcInput, solcOutput } = compileContractSync( solFile, basedir, config, includeAst, includeBytecode, fao, logger, solc ); if (!artifacts) { logger.error(`Compilation failed for ${solFile}`); throw new Error("Compilation failed"); } return { artifacts: Object.fromEntries( Object.entries(artifacts).map(([contractName, contract]) => { return [ contractName, { contractName, abi: contract.abi, userdoc: contract.userdoc, evm: contract.evm } ]; }) ), modules, asts, solcInput, solcOutput }; }; export { resolveArtifacts, resolveArtifactsSync }; //# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map