UNPKG

dop-stick

Version:

Source control tooling for versionable-upgradeable smart contracts

255 lines 11.6 kB
"use strict"; // import fs from 'fs'; // import path from 'path'; // import { ethers } from 'ethers'; // import { Logger as logger } from './logsAndMetrics/core/logger'; // import { FunctionFragment } from 'ethers/lib/utils'; // // Add custom error types for better error handling // export class TypechainProcessorError extends Error { // constructor(message: string, public readonly code: string) { // super(message); // this.name = 'TypechainProcessorError'; // } // } // export class AbiValidationError extends TypechainProcessorError { // constructor(message: string) { // super(message, 'ABI_VALIDATION_ERROR'); // } // } // export interface TypechainContractInfo { // name: string; // Original contract name // path: string; // Full path to contract // functions: { // [selector: string]: { // name: string; // signature: string; // fragment: ethers.utils.FunctionFragment; // } // }; // } // export class TypechainProcessor { // private factoryMap: Map<string, string> = new Map(); // contractName -> factoryPath // private typechainPath: string; // constructor(typechainPath: string = 'typechain-types') { // this.typechainPath = path.join(process.cwd(), typechainPath); // if (!fs.existsSync(this.typechainPath)) { // throw new TypechainProcessorError( // `Typechain directory not found at: ${this.typechainPath}`, // 'TYPECHAIN_DIR_NOT_FOUND' // ); // } // } // /** // * Initialize by parsing index.ts to build factory mappings // */ // async initialize(): Promise<void> { // try { // const indexPath = path.join(this.typechainPath, 'index.ts'); // if (!fs.existsSync(indexPath)) { // throw new Error('index.ts not found in typechain directory'); // } // const content = fs.readFileSync(indexPath, 'utf8'); // // Parse factory exports // const factoryExports = content.match(/export \{ (\w+)__factory \}/g) || []; // for (const exp of factoryExports) { // const contractName = exp.match(/(\w+)__factory/)?.[1]; // if (contractName) { // // Find the corresponding import line // const importRegex = new RegExp(`import.*${contractName}__factory.*from "(.*?)"`); // const importMatch = content.match(importRegex); // if (importMatch?.[1]) { // this.factoryMap.set(contractName, importMatch[1]); // } // } // } // logger.debug(`Loaded ${this.factoryMap.size} contract factories`); // } catch (error) { // logger.error('Failed to initialize typechain processor:', error); // throw error; // } // } // /** // * Validates ABI format and structure // */ // private static validateAbi(abi: any[]): void { // if (!Array.isArray(abi)) { // throw new AbiValidationError('ABI must be an array'); // } // for (const item of abi) { // if (typeof item !== 'object' || item === null) { // throw new AbiValidationError('ABI item must be an object'); // } // if (!item.type) { // throw new AbiValidationError('ABI item must have a type property'); // } // if (item.type === 'function') { // // Validate function ABI structure // if (!item.name) { // throw new AbiValidationError('Function item must have a name'); // } // if (!Array.isArray(item.inputs)) { // throw new AbiValidationError('Function inputs must be an array'); // } // if (!Array.isArray(item.outputs)) { // throw new AbiValidationError('Function outputs must be an array'); // } // // Validate input parameters // for (const input of item.inputs) { // if (!input.type) { // throw new AbiValidationError( // `Input parameter in function ${item.name} must have a type` // ); // } // } // // Validate stateMutability // if (!['pure', 'view', 'nonpayable', 'payable'].includes(item.stateMutability)) { // throw new AbiValidationError( // `Invalid stateMutability in function ${item.name}` // ); // } // } // } // } // private static getFunctionSelectors(abi: any[]): Map<string, { // name: string; // signature: string; // fragment: ethers.utils.FunctionFragment; // }> { // try { // TypechainProcessor.validateAbi(abi); // const selectors = new Map(); // const iface = new ethers.utils.Interface(abi); // for (const item of abi) { // if (item.type === 'function') { // try { // const fragment = FunctionFragment.from(item); // const selector = iface.getSighash(fragment).toLowerCase(); // // Validate the selector format // if (!/^0x[0-9a-f]{8}$/.test(selector)) { // throw new Error(`Invalid selector format: ${selector}`); // } // selectors.set(selector, { // name: fragment.name, // signature: fragment.format('full'), // fragment // }); // logger.debug(`Processed function ${fragment.name} with selector ${selector}`); // } catch (error: unknown) { // logger.error(`Failed to process function: ${item.name}`, { // error, // functionDetails: JSON.stringify(item, null, 2) // }); // // Properly handle the unknown error type // const errorMessage = error instanceof Error // ? error.message // : 'Unknown error occurred'; // throw new TypechainProcessorError( // `Failed to process function ${item.name}: ${errorMessage}`, // 'FUNCTION_PROCESSING_ERROR' // ); // } // } // } // return selectors; // } catch (error: unknown) { // if (error instanceof TypechainProcessorError) { // throw error; // } // const errorMessage = error instanceof Error // ? error.message // : 'Unknown error occurred'; // throw new TypechainProcessorError( // `Failed to process ABI: ${errorMessage}`, // 'ABI_PROCESSING_ERROR' // ); // } // } // /** // * Find contract info by matching function selectors // */ // async findContractBySelectors(selectors: string[]): Promise<TypechainContractInfo | null> { // if (!selectors.length) { // throw new TypechainProcessorError( // 'No selectors provided', // 'INVALID_SELECTORS' // ); // } // // Validate selector format // for (const selector of selectors) { // if (!/^0x[0-9a-f]{8}$/.test(selector.toLowerCase())) { // throw new TypechainProcessorError( // `Invalid selector format: ${selector}`, // 'INVALID_SELECTOR_FORMAT' // ); // } // } // const selectorsSet = new Set(selectors.map(s => s.toLowerCase())); // for (const [contractName, factoryPath] of this.factoryMap) { // try { // // Import the factory file dynamically // const fullPath = path.join(this.typechainPath, factoryPath); // if (!fs.existsSync(fullPath)) { // logger.warn(`Factory file not found: ${fullPath}`); // continue; // } // const Factory = await import(fullPath); // if (!Factory.abi) { // logger.debug(`No ABI found in factory: ${contractName}`); // continue; // } // const functionSelectors = TypechainProcessor.getFunctionSelectors(Factory.abi); // const matchedFunctions: { // [selector: string]: { // name: string; // signature: string; // fragment: ethers.utils.FunctionFragment; // } // } = {}; // let matchCount = 0; // const unmatchedSelectors = new Set(selectorsSet); // // Check each selector we're looking for // for (const selector of selectorsSet) { // const functionInfo = functionSelectors.get(selector); // if (functionInfo) { // matchedFunctions[selector] = functionInfo; // matchCount++; // unmatchedSelectors.delete(selector); // } // } // // If all selectors are found in this contract // if (matchCount === selectors.length) { // logger.debug(`Found matching contract: ${contractName}`); // return { // name: contractName, // path: factoryPath, // functions: matchedFunctions // }; // } else if (matchCount > 0) { // // Log partial matches for debugging // logger.debug(`Partial match in ${contractName}: ${matchCount}/${selectors.length} selectors matched`); // logger.debug(`Unmatched selectors: ${Array.from(unmatchedSelectors).join(', ')}`); // } // } catch (error) { // if (error instanceof TypechainProcessorError) { // logger.error(`Error processing ${contractName}: ${error.message}`, { // code: error.code, // contractName, // factoryPath // }); // } else { // logger.error(`Unexpected error processing ${contractName}:`, error); // } // continue; // } // } // logger.warn(`No matching contract found for selectors: ${selectors.join(', ')}`); // return null; // } // /** // * Get all available contract names // */ // getAvailableContracts(): string[] { // return Array.from(this.factoryMap.keys()); // } // } //# sourceMappingURL=typechainProcessor.js.map