From 62f8bade9a94d8f36eae84b0f9e5e74738a31f49 Mon Sep 17 00:00:00 2001 From: Prithvish Baidya Date: Sat, 2 Nov 2024 01:56:53 +0530 Subject: [PATCH] refactor: Improve argument parsing in readContract function (#749) * refactor: Improve argument parsing in readContract function The readContract function in the src/server/routes/contract/read/read.ts file has been refactored to improve the parsing of arguments. Previously, the function split the arguments string by comma and mapped each argument. Now, the function first tries to parse the arguments as a JSON array. If successful, it uses the parsed arguments. If parsing fails, it falls back to the previous method of splitting the string. This change improves the flexibility and reliability of argument parsing in the readContract function. * refactor: Update test description for reading a contract method with struct and number params --- src/server/routes/contract/read/read.ts | 11 ++++++- src/server/utils/convertor.ts | 7 ++++- test/e2e/tests/read.test.ts | 38 +++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 test/e2e/tests/read.test.ts diff --git a/src/server/routes/contract/read/read.ts b/src/server/routes/contract/read/read.ts index fb6cb9ddd..46dc8fffd 100644 --- a/src/server/routes/contract/read/read.ts +++ b/src/server/routes/contract/read/read.ts @@ -43,7 +43,16 @@ export async function readContract(fastify: FastifyInstance) { contractAddress, }); - const parsedArgs = args?.split(",").map((arg) => { + let parsedArgs: unknown[] | undefined = []; + + try { + const jsonStringArgs = `[${args}]`; + parsedArgs = JSON.parse(jsonStringArgs); + } catch { + // fallback to string split + } + + parsedArgs ??= args?.split(",").map((arg) => { if (arg === "true") { return true; } diff --git a/src/server/utils/convertor.ts b/src/server/utils/convertor.ts index 722ba8fab..7082e53c9 100644 --- a/src/server/utils/convertor.ts +++ b/src/server/utils/convertor.ts @@ -1,6 +1,6 @@ import { BigNumber } from "ethers"; -export const bigNumberReplacer = (value: any): string => { +export const bigNumberReplacer = (value: any): any => { // if we find a BigNumber then make it into a string (since that is safe) if ( BigNumber.isBigNumber(value) || @@ -11,5 +11,10 @@ export const bigNumberReplacer = (value: any): string => { ) { return BigNumber.from(value).toString(); } + + if (Array.isArray(value)) { + return value.map(bigNumberReplacer); + } + return value; }; diff --git a/test/e2e/tests/read.test.ts b/test/e2e/tests/read.test.ts new file mode 100644 index 000000000..b1612b55d --- /dev/null +++ b/test/e2e/tests/read.test.ts @@ -0,0 +1,38 @@ +import { beforeAll, describe, test } from "bun:test"; +import { sepolia } from "thirdweb/chains"; +import { expect } from "vitest"; +import type { setupEngine } from "../utils/engine"; +import { setup } from "./setup"; + +const structContractAddress = "0x83ca896ef0a66d39f0e6fcc1a93c0a09366b85b1"; +const chainIdString = sepolia.id.toString(); + +describe("Read Tests", () => { + let engine: ReturnType; + + beforeAll(async () => { + const { engine: _engine, backendWallet: _backendWallet } = await setup(); + engine = _engine; + }); + + test("Read a contract method with struct and number params", async () => { + const structValues = { + name: "test", + value: 123, + }; + + const structString = JSON.stringify(structValues); + + const { result } = await engine.contract.read( + "readStructAndInts", + chainIdString, + structContractAddress, + `${structString},1,2`, + ); + + expect(result[0]).toEqual("test"); + expect(result[1]).toEqual("123"); + expect(result[2]).toEqual("1"); + expect(result[3]).toEqual("2"); + }); +});