[SDK] Fix abi param parsing (#4229)
## Problem solved
Short description of the bug fixed or feature added
<!-- start pr-codex -->
---
## PR-Codex overview
The focus of this PR is to enhance the parsing functionality for Solidity types in the contract UI components and transaction handling.
### Detailed summary
- Added parsing logic for `string` type in `parseAbiParams`
- Improved handling of different data types in contract transactions
- Added test cases for parsing `string` and `number` in contract transactions
> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`
<!-- end pr-codex -->
This commit is contained in:
@@ -3,6 +3,7 @@ import { parseEther } from "ethers/lib/utils";
|
||||
import { useCallback } from "react";
|
||||
import { Button } from "tw-components";
|
||||
import type { SolidityInputWithTypeProps } from ".";
|
||||
|
||||
import { validateInt } from "./helpers";
|
||||
|
||||
export const SolidityIntInput: React.FC<SolidityInputWithTypeProps> = ({
|
||||
|
||||
@@ -31,4 +31,34 @@ describe.runIf(process.env.TW_SECRET_KEY)("transaction: read", () => {
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it("should work with string and number, not just bigint", async () => {
|
||||
/**
|
||||
* The following 3 readContracts all result in the same value because
|
||||
* the param is still parsed and encoded properly downstream by `numberToHex`
|
||||
* See this docs for more context: "../utils/encoding/hex.test.js"
|
||||
*/
|
||||
const [bigintResult, numberResult, stringResult] = await Promise.all([
|
||||
readContract({
|
||||
contract: DOODLES_CONTRACT,
|
||||
method: "function ownerOf(uint256 tokenId) view returns (address)",
|
||||
params: [1n],
|
||||
}),
|
||||
readContract({
|
||||
contract: DOODLES_CONTRACT,
|
||||
method: "function ownerOf(uint256 tokenId) view returns (address)",
|
||||
// @ts-ignore Intentional
|
||||
params: [1], // <- supposed to be a bigint
|
||||
}),
|
||||
readContract({
|
||||
contract: DOODLES_CONTRACT,
|
||||
method: "function ownerOf(uint256 tokenId) view returns (address)",
|
||||
// @ts-ignore Intentional
|
||||
params: ["1"], // <- supposed to be a bigint
|
||||
}),
|
||||
]);
|
||||
|
||||
expect(bigintResult === numberResult).toBe(true);
|
||||
expect(bigintResult === stringResult).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -156,5 +156,17 @@ describe("parseAbiParams", () => {
|
||||
const result = parseAbiParams(["bytes64"], [value]);
|
||||
expect(result).toStrictEqual([value]);
|
||||
});
|
||||
|
||||
it("should return a string for type string", () => {
|
||||
const value = "this is a string";
|
||||
const result = parseAbiParams(["string"], [value]);
|
||||
expect(result).toStrictEqual(["this is a string"]);
|
||||
});
|
||||
|
||||
it("should return the value itself if it falls through to the end", () => {
|
||||
const value = { whatever: true };
|
||||
const result = parseAbiParams(["non-existent-type"], [value]);
|
||||
expect(result).toStrictEqual([{ whatever: true }]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -32,6 +32,17 @@ export function parseAbiParams(
|
||||
constructorParamTypes: string[],
|
||||
constructorParamValues: unknown[],
|
||||
): Array<string | bigint | boolean> {
|
||||
/**
|
||||
* Internal Solidity type checklist
|
||||
* 1. tuple, array -> JSON.parse | todo: Recursively parse the content
|
||||
* 2. uint, int -> bigint
|
||||
* 3. address -> string
|
||||
* 4. string -> string
|
||||
* 5. bytes, bytes32 etc. -> string
|
||||
* 6. bool -> boolean
|
||||
* >>> Make sure to return the original value at the end of the function <<<
|
||||
*/
|
||||
|
||||
// Make sure they have the same length
|
||||
if (constructorParamTypes.length !== constructorParamValues.length) {
|
||||
throw new Error(
|
||||
@@ -46,6 +57,9 @@ export function parseAbiParams(
|
||||
}
|
||||
return value;
|
||||
}
|
||||
if (type === "string") {
|
||||
return String(value);
|
||||
}
|
||||
if (type === "bytes32") {
|
||||
if (!isHex(value)) {
|
||||
throw new Error(`${value} is not a valid hex string`);
|
||||
@@ -86,5 +100,8 @@ export function parseAbiParams(
|
||||
"Invalid boolean value. Expecting either 'true' or 'false'",
|
||||
);
|
||||
}
|
||||
|
||||
// Return the value here if none of the types match
|
||||
return value;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,4 +8,44 @@ describe("hex.ts", () => {
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000064",
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* This test is put here as a docs for the method `numberToHex` because:
|
||||
*
|
||||
* `numberToHex` can still work with number-convertible strings - even tho it only accepts number or bigint
|
||||
* because there's is one line of code that's converting the param into bigint anyway
|
||||
* ```ts
|
||||
* const value = BigInt(value_);
|
||||
* ```
|
||||
*
|
||||
* As a side effect, the following 3 return the same result:
|
||||
* ```ts
|
||||
* readContract({
|
||||
* contract,
|
||||
* method: "function tokenURI(uint256 tokenId) returns (string)",
|
||||
* params: [1n],
|
||||
* })
|
||||
*
|
||||
* readContract({
|
||||
* contract,
|
||||
* method: "function tokenURI(uint256 tokenId) returns (string)",
|
||||
* // @ts-ignore
|
||||
* params: [1],
|
||||
* })
|
||||
*
|
||||
* readContract({
|
||||
* contract,
|
||||
* method: "function tokenURI(uint256 tokenId) returns (string)",
|
||||
* // @ts-ignore
|
||||
* params: ["1"],
|
||||
* })
|
||||
* ```
|
||||
*/
|
||||
it("should work with string !!!!", () => {
|
||||
// @ts-ignore Intentional
|
||||
const result = numberToHex("100", { size: 32, signed: false });
|
||||
expect(result).toBe(
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000064",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user