11import { Type } from "@sinclair/typebox" ;
22import type { FastifyInstance } from "fastify" ;
33import { StatusCodes } from "http-status-codes" ;
4- import { getContract } from "../../../../shared/utils/cache/get-contract" ;
4+ import type { AbiParameters } from "ox" ;
5+ import { readContract as readContractV5 , resolveMethod } from "thirdweb" ;
6+ import { parseAbiParams } from "thirdweb/utils" ;
7+ import type { AbiFunction } from "thirdweb/utils" ;
8+ import { getContractV5 } from "../../../../shared/utils/cache/get-contractv5" ;
59import { prettifyError } from "../../../../shared/utils/error" ;
610import { createCustomError } from "../../../middleware/error" ;
711import {
@@ -12,6 +16,8 @@ import {
1216 partialRouteSchema ,
1317 standardResponseSchema ,
1418} from "../../../schemas/shared-api-schemas" ;
19+ import { sanitizeFunctionName } from "../../../utils/abi" ;
20+ import { sanitizeAbi } from "../../../utils/abi" ;
1521import { getChainIdFromChain } from "../../../utils/chain" ;
1622import { bigNumberReplacer } from "../../../utils/convertor" ;
1723
@@ -37,12 +43,13 @@ export async function readContract(fastify: FastifyInstance) {
3743 } ,
3844 handler : async ( request , reply ) => {
3945 const { chain, contractAddress } = request . params ;
40- const { functionName, args } = request . query ;
46+ const { functionName, args, abi } = request . query ;
4147
4248 const chainId = await getChainIdFromChain ( chain ) ;
43- const contract = await getContract ( {
49+ const contract = await getContractV5 ( {
4450 chainId,
4551 contractAddress,
52+ abi : sanitizeAbi ( abi ) ,
4653 } ) ;
4754
4855 let parsedArgs : unknown [ ] | undefined ;
@@ -54,19 +61,33 @@ export async function readContract(fastify: FastifyInstance) {
5461 // fallback to string split
5562 }
5663
57- parsedArgs ??= args ?. split ( "," ) . map ( ( arg ) => {
58- if ( arg === "true" ) {
59- return true ;
60- }
61- if ( arg === "false" ) {
62- return false ;
63- }
64- return arg ;
65- } ) ;
64+ parsedArgs ??= args ?. split ( "," ) ;
65+
66+ // 3 possible ways to get function from abi:
67+ // 1. functionName passed as solidity signature
68+ // 2. functionName passed as function name + passed in ABI
69+ // 3. functionName passed as function name + inferred ABI (fetched at encode time)
70+ // this is all handled inside the `resolveMethod` function
71+ let method : AbiFunction ;
72+ let params : Array < string | bigint | boolean | object > ;
73+ try {
74+ const functionNameOrSignature = sanitizeFunctionName ( functionName ) ;
75+ method = await resolveMethod ( functionNameOrSignature ) ( contract ) ;
76+ params = parseAbiParams (
77+ method . inputs . map ( ( i : AbiParameters . Parameter ) => i . type ) ,
78+ parsedArgs ?? [ ] ,
79+ ) ;
80+ } catch ( e ) {
81+ throw createCustomError (
82+ prettifyError ( e ) ,
83+ StatusCodes . BAD_REQUEST ,
84+ "BAD_REQUEST" ,
85+ ) ;
86+ }
6687
6788 let returnData : unknown ;
6889 try {
69- returnData = await contract . call ( functionName , parsedArgs ?? [ ] ) ;
90+ returnData = await readContractV5 ( { contract , method , params } ) ;
7091 } catch ( e ) {
7192 throw createCustomError (
7293 prettifyError ( e ) ,
0 commit comments