UNPKG

typechain-target-ethers-v5

Version:

🔌 TypeChain target for ethers-v5

127 lines (124 loc) • 5.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const path_1 = require("path"); const ts_generator_1 = require("ts-generator"); const typechain_1 = require("typechain"); const codegen_1 = require("./codegen"); const common_1 = require("./common"); const DEFAULT_OUT_PATH = './types/ethers-contracts/'; class Ethers extends ts_generator_1.TsGeneratorPlugin { constructor(ctx) { super(ctx); this.name = 'Ethers'; this.allContracts = []; this.contractCache = {}; this.bytecodeCache = {}; const { cwd, rawConfig } = ctx; this.outDirAbs = path_1.resolve(cwd, rawConfig.outDir || DEFAULT_OUT_PATH); } transformFile(file) { const fileExt = typechain_1.getFileExtension(file.path); // For json files with both ABI and bytecode, both the contract typing and factory can be // generated at once. For split files (.abi and .bin) we don't know in which order they will // be transformed -- so we temporarily store whichever comes first, and generate the factory // only when both ABI and bytecode are present. if (fileExt === '.bin') { return this.transformBinFile(file); } return this.transformAbiOrFullJsonFile(file); } transformBinFile(file) { const name = typechain_1.getFilename(file.path); const bytecode = typechain_1.extractBytecode(file.contents); if (!bytecode) { return; } if (this.contractCache[name]) { const { contract, abi } = this.contractCache[name]; delete this.contractCache[name]; return [this.genContractFactoryFile(contract, abi, bytecode)]; } else { this.bytecodeCache[name] = bytecode; } } transformAbiOrFullJsonFile(file) { const name = typechain_1.getFilename(file.path); const abi = typechain_1.extractAbi(file.contents); if (abi.length === 0) { return; } const documentation = typechain_1.extractDocumentation(file.contents); const contract = typechain_1.parse(abi, name, documentation); const bytecode = typechain_1.extractBytecode(file.contents) || this.bytecodeCache[name]; if (bytecode) { return [this.genContractTypingsFile(contract), this.genContractFactoryFile(contract, abi, bytecode)]; } else { this.contractCache[name] = { abi, contract }; return [this.genContractTypingsFile(contract)]; } } genContractTypingsFile(contract) { this.allContracts.push(contract.name); return { path: path_1.join(this.outDirAbs, `${contract.name}.d.ts`), contents: codegen_1.codegenContractTypings(contract), }; } genContractFactoryFile(contract, abi, bytecode) { return { path: path_1.join(this.outDirAbs, 'factories', `${contract.name}${common_1.FACTORY_POSTFIX}.ts`), contents: codegen_1.codegenContractFactory(contract, abi, bytecode), }; } afterRun() { // For each contract that doesn't have bytecode (it's either abstract, or only ABI was provided) // generate a simplified factory, that allows to interact with deployed contract instances. const abstractFactoryFiles = Object.keys(this.contractCache).map((contractName) => { const { contract, abi } = this.contractCache[contractName]; return { path: path_1.join(this.outDirAbs, 'factories', `${contract.name}${common_1.FACTORY_POSTFIX}.ts`), contents: codegen_1.codegenAbstractContractFactory(contract, abi), }; }); const allFiles = [ ...abstractFactoryFiles, { path: path_1.join(this.outDirAbs, 'commons.ts'), contents: this.genCommons(), }, { path: path_1.join(this.outDirAbs, 'index.ts'), contents: this.genReExports(), }, ]; return allFiles; } genCommons() { return ` import { EventFilter, Event } from 'ethers' import { Result } from '@ethersproject/abi' export interface TypedEventFilter<T, G> extends EventFilter {} export interface TypedEvent<T extends Result> extends Event { args: T; } export type TypedListener<T extends Array<any>, G> = (...listenerArg: [...T, TypedEventFilter<T, G>]) => void;`; } genReExports() { const codegen = []; for (const fileName of this.allContracts) { const desiredSymbol = fileName; codegen.push(`export type { ${desiredSymbol} } from './${desiredSymbol}'`); } codegen.push('\n'); // then generate reexports for TypeChain generated factories for (const fileName of this.allContracts) { const desiredSymbol = fileName + '__factory'; codegen.push(`export { ${desiredSymbol} } from './factories/${desiredSymbol}'`); } return codegen.join('\n'); } } exports.default = Ethers; //# sourceMappingURL=index.js.map