mirror of
https://github.com/cerc-io/watcher-ts
synced 2026-05-08 08:14:08 +00:00
Parse block tag in eth_call handler
This commit is contained in:
parent
fb7e1790d9
commit
7869b72aef
@ -277,7 +277,7 @@ export class ServerCmd {
|
||||
) => Promise<any>,
|
||||
typeDefs: TypeSource,
|
||||
paymentsManager?: PaymentsManager,
|
||||
createEthRPCHandlers?: (indexer: IndexerInterface) => Promise<any>
|
||||
createEthRPCHandlers?: (indexer: IndexerInterface, ethProvider: JsonRpcProvider) => Promise<any>
|
||||
): Promise<{
|
||||
app: Application,
|
||||
server: ApolloServer
|
||||
@ -286,6 +286,7 @@ export class ServerCmd {
|
||||
const jobQueue = this._baseCmd.jobQueue;
|
||||
const indexer = this._baseCmd.indexer;
|
||||
const eventWatcher = this._baseCmd.eventWatcher;
|
||||
const ethProvider = this._baseCmd.ethProvider;
|
||||
|
||||
assert(config);
|
||||
assert(jobQueue);
|
||||
@ -318,7 +319,7 @@ export class ServerCmd {
|
||||
const gqlLogger = createGQLLogger(config.server.gql.logDir);
|
||||
const resolvers = await createResolvers(indexer, eventWatcher, gqlLogger);
|
||||
|
||||
const ethRPCHandlers = createEthRPCHandlers ? await createEthRPCHandlers(indexer) : {};
|
||||
const ethRPCHandlers = createEthRPCHandlers ? await createEthRPCHandlers(indexer, ethProvider) : {};
|
||||
|
||||
// Create an Express app
|
||||
const app: Application = express();
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { utils } from 'ethers';
|
||||
|
||||
import { JsonRpcProvider } from '@ethersproject/providers';
|
||||
|
||||
import { IndexerInterface } from './types';
|
||||
|
||||
const CODE_INVALID_PARAMS = -32602;
|
||||
@ -11,6 +15,7 @@ const ERROR_CONTRACT_INSUFFICIENT_PARAMS = 'Insufficient params';
|
||||
const ERROR_CONTRACT_NOT_RECOGNIZED = 'Contract not recognized';
|
||||
const ERROR_CONTRACT_METHOD_NOT_FOUND = 'Contract method not found';
|
||||
const ERROR_METHOD_NOT_IMPLEMENTED = 'Method not implemented';
|
||||
const ERROR_INVALID_BLOCK_TAG = 'Invalid block tag';
|
||||
|
||||
class ErrorWithCode extends Error {
|
||||
code: number;
|
||||
@ -21,7 +26,8 @@ class ErrorWithCode extends Error {
|
||||
}
|
||||
|
||||
export const createEthRPCHandlers = async (
|
||||
indexer: IndexerInterface
|
||||
indexer: IndexerInterface,
|
||||
ethProvider: JsonRpcProvider
|
||||
): Promise<any> => {
|
||||
return {
|
||||
eth_blockNumber: async (args: any, callback: any) => {
|
||||
@ -32,22 +38,18 @@ export const createEthRPCHandlers = async (
|
||||
},
|
||||
|
||||
eth_call: async (args: any, callback: any) => {
|
||||
// TODO: Parse blockTag
|
||||
|
||||
try {
|
||||
if (!indexer.contractMap) {
|
||||
throw new ErrorWithCode(CODE_INTERNAL_ERROR, ERROR_CONTRACT_MAP_NOT_SET);
|
||||
}
|
||||
|
||||
if (args.length === 0) {
|
||||
throw new ErrorWithCode(CODE_INVALID_PARAMS, ERROR_CONTRACT_INSUFFICIENT_PARAMS);
|
||||
}
|
||||
|
||||
const { to, data, blockTag } = args[0];
|
||||
|
||||
if (!indexer.contractMap) {
|
||||
throw new ErrorWithCode(CODE_INTERNAL_ERROR, ERROR_CONTRACT_MAP_NOT_SET);
|
||||
}
|
||||
|
||||
// For values other than blockHash, resolve value from block_progress table
|
||||
const latestBlock = await indexer.getLatestCanonicalBlock();
|
||||
const blockHash = latestBlock?.blockHash;
|
||||
const blockHash = await parseBlockTag(indexer, ethProvider, blockTag);
|
||||
|
||||
const watchedContract = indexer.getWatchedContracts().find(contract => contract.address === to);
|
||||
if (!watchedContract) {
|
||||
@ -78,7 +80,7 @@ export const createEthRPCHandlers = async (
|
||||
}
|
||||
|
||||
const result = await indexerMethod(blockHash, to, ...decodedData);
|
||||
const encodedResult = contractInterface.encodeFunctionResult(functionFragment, [result.value]);
|
||||
const encodedResult = contractInterface.encodeFunctionResult(functionFragment, Array.isArray(result.value) ? result.value : [result.value]);
|
||||
|
||||
callback(null, encodedResult);
|
||||
} catch (error: any) {
|
||||
@ -98,3 +100,32 @@ export const createEthRPCHandlers = async (
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const parseBlockTag = async (indexer: IndexerInterface, ethProvider: JsonRpcProvider, blockTag: any): Promise<string> => {
|
||||
if (utils.isHexString(blockTag)) {
|
||||
// Return value if hex string is of block hash length
|
||||
if (utils.hexDataLength(blockTag) === 32) {
|
||||
return blockTag;
|
||||
}
|
||||
|
||||
// Treat hex value as a block number
|
||||
const block = await ethProvider.getBlock(blockTag);
|
||||
return block.hash;
|
||||
}
|
||||
|
||||
// TODO: Handle pending, safe and finalized
|
||||
if (['earliest', 'latest', 'pending', 'safe', 'finalized', null, undefined].includes(blockTag)) {
|
||||
const syncStatus = await indexer.getSyncStatus();
|
||||
if (!syncStatus) {
|
||||
throw new ErrorWithCode(CODE_INTERNAL_ERROR, 'SyncStatus not found');
|
||||
}
|
||||
|
||||
if (blockTag === 'earliest') {
|
||||
return syncStatus.initialIndexedBlockHash;
|
||||
}
|
||||
|
||||
return syncStatus.latestIndexedBlockHash;
|
||||
}
|
||||
|
||||
throw new ErrorWithCode(CODE_INVALID_PARAMS, ERROR_INVALID_BLOCK_TAG);
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user