UNPKG

@tevm/runtime

Version:

Tools for generating the Tevm contract runtime

152 lines (148 loc) 6.3 kB
import { die, map, succeed } from 'effect/Effect'; import { formatAbi } from 'abitype'; // src/generateRuntime.js var generateDtsBody = (artifacts, includeBytecode) => { return succeed( ` ${Object.entries(artifacts).flatMap(([contractName, { abi, userdoc = {} }]) => { const contract = { humanReadableAbi: formatAbi(abi) }; const natspec = Object.entries(userdoc.methods ?? {}).map( ([method, { notice }]) => ` * @property ${method} ${notice}` ); if (userdoc.notice) { natspec.unshift(` * @notice ${userdoc.notice}`); } if (includeBytecode) { return [ // Define constants for name and ABI with const assertions for type safety `const _name${contractName} = ${JSON.stringify(contractName, null, 2)} as const;`, `const _abi${contractName} = ${JSON.stringify(contract.humanReadableAbi, null, 2)} as const;`, // JSDoc comments for the contract "/**", ` * ${contractName} Contract (with bytecode)`, ...natspec, " * @see [contract docs](https://tevm.sh/learn/contracts/) for more documentation", " */", // Type declaration for the contract `export const ${contractName}: Contract<`, ` typeof _name${contractName},`, // Contract name ` typeof _abi${contractName},`, // ABI " undefined,", // Address placeholder " `0x${string}`,", // Bytecode " `0x${string}`,", // Deployed bytecode " undefined", // Additional data - removed trailing comma ">;" ].filter(Boolean); } return [ // Define constants for ABI and name with const assertions `const _abi${contractName} = ${JSON.stringify(contract.humanReadableAbi)} as const;`, `const _name${contractName} = ${JSON.stringify(contractName)} as const;`, // JSDoc comments for the contract "/**", ` * ${contractName} Contract (no bytecode)`, ` * change file name or add file that ends in '.s.sol' extension if you wish to compile the bytecode`, " * @see [contract docs](https://tevm.sh/learn/contracts/) for more documentation", ...natspec, " */", // Type declaration for the contract (without bytecode) `export const ${contractName}: Contract<typeof _name${contractName}, typeof _abi${contractName}, undefined, undefined, undefined, undefined>;` ].filter(Boolean); }).join("\n")} // solc artifacts of compilation export const artifacts = ${JSON.stringify(artifacts, null, 2)}; ` ); }; // src/generateTevmBody.js var generateTevmBody = (artifacts, moduleType, includeBytecode) => { if (moduleType === "dts") { return generateDtsBody(artifacts, includeBytecode); } return succeed( Object.entries(artifacts).flatMap(([contractName, { abi, userdoc = {}, evm }], i) => { var _a, _b; const contract = JSON.stringify( { name: contractName, humanReadableAbi: formatAbi(abi), // Include bytecode if requested and available (checking for empty string for interfaces) ...includeBytecode ? { bytecode: ((_a = evm == null ? void 0 : evm.bytecode) == null ? void 0 : _a.object) && evm.bytecode.object !== "" ? `0x${evm.bytecode.object}` : void 0, deployedBytecode: ((_b = evm == null ? void 0 : evm.deployedBytecode) == null ? void 0 : _b.object) && evm.deployedBytecode.object !== "" ? `0x${evm.deployedBytecode.object}` : void 0 } : {} }, null, 2 ); const natspec = Object.entries(userdoc.methods ?? {}).map( ([method, { notice }]) => ` * @property ${method} ${notice}` ); if (userdoc.notice) { natspec.unshift(` * ${userdoc.notice}`); } natspec.push(" * @see [contract docs](https://tevm.sh/learn/contracts/) for more documentation"); natspec.unshift("/**"); natspec.push(" */"); if (moduleType === "cjs") { return [ `const _${contractName} = ${contract};`, ...natspec, `module.exports.${contractName} = createContract(_${contractName});`, i === 0 ? `module.exports.artifacts = ${JSON.stringify(artifacts, null, 2)};` : "" ]; } if (moduleType === "ts") { return [ `const _${contractName} = ${contract} as const`, ...natspec, `export const ${contractName} = createContract(_${contractName});`, i === 0 ? `export const artifacts = ${JSON.stringify(artifacts, null, 2)};` : "" ]; } return [ `const _${contractName} = ${contract};`, ...natspec, `export const ${contractName} = createContract(_${contractName});`, i === 0 ? `export const artifacts = ${JSON.stringify(artifacts, null, 2)};` : "" ]; }).join("\n") ); }; // src/generateRuntime.js var importsByModuleType = (contractPackage) => ({ contract: { cjs: `const { createContract } = require('${contractPackage}')`, dts: `import type { Contract } from '${contractPackage}'`, ts: `import { createContract } from '${contractPackage}'`, mjs: `import { createContract } from '${contractPackage}'` }, script: { cjs: `const { createContract } = require('${contractPackage}')`, dts: `import type { Contract } from '${contractPackage}'`, ts: `import { createContract } from '${contractPackage}'`, mjs: `import { createContract } from '${contractPackage}'` } }); var generateRuntime = (artifacts, moduleType, includeBytecode, tevmPackage) => { if (!artifacts || Object.keys(artifacts).length === 0) { return die("No artifacts provided to generateRuntime"); } const contractType = includeBytecode ? "script" : "contract"; const imports = importsByModuleType(tevmPackage)[contractType][moduleType]; if (!imports) { return die(`Unknown module type: ${moduleType}. Valid module types include 'cjs', 'dts', 'ts', and 'mjs'`); } return generateTevmBody(artifacts, moduleType, includeBytecode).pipe(map((body) => [imports, body].join("\n"))); }; export { generateRuntime }; //# sourceMappingURL=index.js.map //# sourceMappingURL=index.js.map