diff --git a/packages/util/src/eth-rpc-handlers.ts b/packages/util/src/eth-rpc-handlers.ts index f589fdd5..9cb288ca 100644 --- a/packages/util/src/eth-rpc-handlers.ts +++ b/packages/util/src/eth-rpc-handlers.ts @@ -13,7 +13,49 @@ export const createEthRPCHandlers = async ( }, eth_call: async (args: any, callback: any) => { - // TODO: Implement + // TODO: Handle empty args + // TODO: Set errors in response + // TODO: Parse blockTag + + const { to, data, blockTag } = args[0]; + + // For values other than blockHash, resolve value from block_progress table + const latestBlock = await indexer.getLatestCanonicalBlock(); + const blockHash = latestBlock?.blockHash; + + const watchedContract = indexer.getWatchedContracts().find(contract => contract.address === to); + if (!watchedContract) { + throw new Error('Contract not recognized'); + } + + if (!indexer.contractMap) { + throw new Error('Contract map not found'); + } + + const contractInterface = indexer.contractMap.get(watchedContract.kind); + if (!contractInterface) { + throw new Error('Contract ABI not found'); + } + + // Slice out method signature + const functionSelector = data.slice(0, 10); + + // Find the matching function from the ABI + const functionFragment = contractInterface.getFunction(functionSelector); + if (!functionFragment) { + throw new Error('Method not found'); + } + + // Decode the data based on the matched function + const decodedData = contractInterface.decodeFunctionData(functionFragment, data); + + const functionName = functionFragment.name; + const indexerMethod = (indexer as any)[functionName].bind(indexer); + if (indexerMethod && typeof indexerMethod === 'function') { + const result = await indexerMethod(blockHash, to, ...decodedData); + const encodedResult = contractInterface.encodeFunctionResult(functionFragment, [result.value]); + callback(null, encodedResult); + } }, eth_getLogs: async (args: any, callback: any) => { diff --git a/packages/util/src/types.ts b/packages/util/src/types.ts index ee49108c..5afca668 100644 --- a/packages/util/src/types.ts +++ b/packages/util/src/types.ts @@ -3,7 +3,7 @@ // import { Connection, DeepPartial, EntityTarget, FindConditions, FindManyOptions, ObjectLiteral, QueryRunner } from 'typeorm'; -import { Transaction } from 'ethers'; +import { ethers, Transaction } from 'ethers'; import { MappingKey, StorageLayout } from '@cerc-io/solidity-mapper'; @@ -161,6 +161,7 @@ export interface IndexerInterface { readonly serverConfig: ServerConfig readonly upstreamConfig: UpstreamConfig readonly storageLayoutMap: Map + readonly contractMap: Map // eslint-disable-next-line no-use-before-define readonly graphWatcher?: GraphWatcherInterface init (): Promise