dop-stick
Version:
Source control tooling for versionable-upgradeable smart contracts
255 lines • 11.6 kB
JavaScript
;
// 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