From c00e2ea40a40126644f2115ace7ce676dd80e4cb Mon Sep 17 00:00:00 2001 From: Yota Date: Thu, 7 Nov 2024 15:17:45 +0900 Subject: [PATCH 01/12] helpers: Add abiFillEmptyNames --- src/__tests__/helpers.test.ts | 259 ++++++++++++++++++++++++++++++++++ src/abi.ts | 19 ++- src/helpers.ts | 92 ++++++++++++ 3 files changed, 368 insertions(+), 2 deletions(-) create mode 100644 src/__tests__/helpers.test.ts create mode 100644 src/helpers.ts diff --git a/src/__tests__/helpers.test.ts b/src/__tests__/helpers.test.ts new file mode 100644 index 0000000..a491601 --- /dev/null +++ b/src/__tests__/helpers.test.ts @@ -0,0 +1,259 @@ +import { expect, describe, it } from "vitest"; + +import { abiFillEmptyNames } from "../helpers"; +import { ABI } from "../abi"; + +describe("abiFillEmptyNames", () => { + type testCase = { + name: string; + abi: Array; + want: Array; + }; + + const testCases: testCase[] = [ + { + name: "Basic test", + abi: [ + { + type: "function", + selector: "0x95d376d7", + payable: false, + stateMutability: "payable", + inputs: [ + { + type: "tuple", + name: "", + components: [ + { type: "uint32", name: "" }, + { type: "bytes", name: "" }, + { type: "bytes32", name: "" }, + { type: "uint64", name: "" }, + { type: "address", name: "" }, + ], + }, + { type: "bytes", name: "" }, + ], + outputs: [ + { + type: "tuple", + name: "", + components: [ + { type: "uint32", name: "" }, + { type: "bytes", name: "" }, + { type: "bytes32", name: "" }, + { type: "uint64", name: "" }, + { type: "address", name: "" }, + ], + }, + { type: "bytes", name: "" }, + ], + sig: "assignJob((uint32,bytes,bytes32,uint64,address),bytes)", + name: "assignJob", + constant: false, + }, + ], + want: [ + { + type: "function", + selector: "0x95d376d7", + payable: false, + stateMutability: "payable", + inputs: [ + { + type: "tuple", + name: "", + components: [ + { type: "uint32", name: "field0" }, + { type: "bytes", name: "field1" }, + { type: "bytes32", name: "field2" }, + { type: "uint64", name: "field3" }, + { type: "address", name: "field4" }, + ], + }, + { type: "bytes", name: "" }, + ], + outputs: [ + { + type: "tuple", + name: "", + components: [ + { type: "uint32", name: "field0" }, + { type: "bytes", name: "field1" }, + { type: "bytes32", name: "field2" }, + { type: "uint64", name: "field3" }, + { type: "address", name: "field4" }, + ], + }, + { type: "bytes", name: "" }, + ], + sig: "assignJob((uint32,bytes,bytes32,uint64,address),bytes)", + name: "assignJob", + constant: false, + }, + ], + }, + { + name: "Nested tuple test", + abi: [ + { + name: "test", + selector: "0x12345679", + inputs: [ + { + name: "", + type: "tuple", + components: [ + { + type: "tuple", + name: "", + components: [ + { + type: "tuple", + name: "", + components: [ + { type: "uint256", name: "" }, + { type: "address", name: "x" }, + ], + }, + { + type: "tuple", + name: "n1", + components: [ + { type: "uint256", name: "y" }, + { type: "address", name: "" }, + ], + }, + ], + }, + ], + }, + ], + stateMutability: "view", + type: "function", + }, + ], + want: [ + { + name: "test", + selector: "0x12345679", + inputs: [ + { + name: "", + type: "tuple", + components: [ + { + type: "tuple", + name: "field0", + components: [ + { + type: "tuple", + name: "field0", + components: [ + { + type: "uint256", + name: "field0", + }, + { type: "address", name: "x" }, + ], + }, + { + type: "tuple", + name: "n1", + components: [ + { type: "uint256", name: "y" }, + { + type: "address", + name: "field1", + }, + ], + }, + ], + }, + ], + }, + ], + stateMutability: "view", + type: "function", + }, + ], + }, + { + name: "Other Tuple types: Tuple[] and Tuple[k]", + abi: [ + { + name: "test", + selector: "0x12345679", + inputs: [ + { + name: "s", + type: "tuple", + components: [ + { + name: "", + type: "tuple[]", + components: [ + { name: "", type: "uint256" }, + { name: "", type: "uint256" }, + ], + }, + { + name: "", + type: "tuple[2]", + components: [ + { name: "", type: "uint256" }, + { name: "", type: "uint256" }, + ], + }, + ], + }, + ], + stateMutability: "view", + type: "function", + }, + ], + want: [ + { + name: "test", + selector: "0x12345679", + inputs: [ + { + name: "s", + type: "tuple", + components: [ + { + name: "field0", + type: "tuple[]", + components: [ + { name: "field0", type: "uint256" }, + { name: "field1", type: "uint256" }, + ], + }, + { + name: "field1", + type: "tuple[2]", + components: [ + { name: "field0", type: "uint256" }, + { name: "field1", type: "uint256" }, + ], + }, + ], + }, + ], + stateMutability: "view", + type: "function", + }, + ], + }, + { + name: "Empty ABI", + abi: [], + want: [], + }, + ]; + + testCases.forEach((tc) => { + it(tc.name, () => { + expect(abiFillEmptyNames(tc.abi as ABI)).toStrictEqual(tc.want); + }); + }); +}); diff --git a/src/abi.ts b/src/abi.ts index 995e177..861295b 100644 --- a/src/abi.ts +++ b/src/abi.ts @@ -4,8 +4,8 @@ export type ABIFunction = { type: "function"; // TODO: constructor, receive, fallback selector: string; name?: string; - outputs?: {type: string, length?: number, name: string}[]; - inputs?: {type: string, name: string}[]; + outputs?: ABIOutput[]; + inputs?: ABIInput[]; sig?: string; sigAlts?: string[]; payable?: boolean; @@ -21,4 +21,19 @@ export type ABIEvent = { // TODO: ... }; +export type ABIInput = { + type: string; + name: string; + length?: number; + components?: ABIInOut[]; +} + +export type ABIOutput = { + type: string; + name: string; + components?: ABIInOut[]; +} + +export type ABIInOut = ABIInput|ABIOutput; + export type ABI = (ABIFunction|ABIEvent)[]; diff --git a/src/helpers.ts b/src/helpers.ts new file mode 100644 index 0000000..ae0ef26 --- /dev/null +++ b/src/helpers.ts @@ -0,0 +1,92 @@ +import type { ABI, ABIFunction, ABIInOut } from "./abi.js"; + +// Regular expression to match tuple types. +// Example: tuple, tuple[], tuple[5] +const reTupleType = /^tuple(\[\d*\])?$/; + +/** + * Fills tuple component's empty names in an ABI with generated names + * + * @example + * Input: { + * "type": "function", + * "selector": "0x95d376d7", + * "payable": false, + * "stateMutability": "payable", + * "inputs": [ + * { + * "type": "tuple", + * "name": "", + * "components": [ + * { "type": "uint32", "name": "" }, + * { "type": "bytes", "name": "" }, + * { "type": "bytes32", "name": "" }, + * { "type": "uint64", "name": "" }, + * { "type": "address", "name": "" } + * ] + * }, + * { "type": "bytes", "name": "" } + * ], + * "sig": "assignJob((uint32,bytes,bytes32,uint64,address),bytes)", + * "name": "assignJob", + * "constant": false + * } + * + * Output: { + * "type": "function", + * "selector": "0x95d376d7", + * "payable": false, + * "stateMutability": "payable", + * "inputs": [ + * { + * "type": "tuple", + * "name": "", + * "components": [ + * { "type": "uint32", "name": "field0" }, + * { "type": "bytes", "name": "field1" }, + * { "type": "bytes32", "name": "field2" }, + * { "type": "uint64", "name": "field3" }, + * { "type": "address", "name": "field4" } + * ] + * }, + * { "type": "bytes", "name": "" } + * ], + * "sig": "assignJob((uint32,bytes,bytes32,uint64,address),bytes)", + * "name": "assignJob", + * "constant": false + * } + * + * @param abi The ABI to process + * @param options Configuration options + * @returns A new ABI with filled parameter names + */ +export function abiFillEmptyNames(abi: ABI): ABI { + function processComponents(components: ABIInOut[]): void { + components.forEach((component, index) => { + component.name ||= `field${index}`; + if (component.type.match(reTupleType) && component.components) { + processComponents(component.components); + } + }); + } + + const result: ABI = abi.map((item) => { + if (item.type === "function") { + const func: ABIFunction = { ...item }; + func.inputs?.forEach((input) => { + if (input.type.match(reTupleType) && input.components) { + processComponents(input.components); + } + }); + func.outputs?.forEach((output) => { + if (output.type.match(reTupleType) && output.components) { + processComponents(output.components); + } + }); + return func; + } + return item; + }); + + return result; +} From 6f120b5f72aa2e6ddd1f70b270b8f5f993fd7e04 Mon Sep 17 00:00:00 2001 From: Yota Date: Thu, 7 Nov 2024 15:27:58 +0900 Subject: [PATCH 02/12] auto: Add abiHelpers option to AutoloadConfig --- src/auto.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/auto.ts b/src/auto.ts index 33196ae..69d11e4 100644 --- a/src/auto.ts +++ b/src/auto.ts @@ -111,6 +111,13 @@ export type AutoloadConfig = { * @experimental */ enableExperimentalMetadata?: boolean; + + /** + * Enable ABI helpers to apply additional transformations to the ABI before returning. + * @group Settings + * @experimental + */ + abiHelpers?: Array<(abi: ABI) => ABI>; } /** @@ -360,6 +367,12 @@ export async function autoload(address: string, config: AutoloadConfig): Promise ); } + if (config.abiHelpers) { + for (const helper of config.abiHelpers) { + result.abi = helper(result.abi); + } + } + return result; } From ed0d9a545075e0be55d7b8170df99c105c00156e Mon Sep 17 00:00:00 2001 From: Yota Date: Thu, 7 Nov 2024 15:31:47 +0900 Subject: [PATCH 03/12] Adjusted a test case --- src/__tests__/helpers.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/__tests__/helpers.test.ts b/src/__tests__/helpers.test.ts index a491601..1885bba 100644 --- a/src/__tests__/helpers.test.ts +++ b/src/__tests__/helpers.test.ts @@ -185,7 +185,7 @@ describe("abiFillEmptyNames", () => { selector: "0x12345679", inputs: [ { - name: "s", + name: "", type: "tuple", components: [ { @@ -217,7 +217,7 @@ describe("abiFillEmptyNames", () => { selector: "0x12345679", inputs: [ { - name: "s", + name: "", type: "tuple", components: [ { From 31feb6392ea0b86a880ba7deb056a287cf79c51e Mon Sep 17 00:00:00 2001 From: Yota Date: Thu, 7 Nov 2024 15:34:50 +0900 Subject: [PATCH 04/12] helpers: modify fucntion comment --- src/helpers.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/helpers.ts b/src/helpers.ts index ae0ef26..972a678 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -57,8 +57,7 @@ const reTupleType = /^tuple(\[\d*\])?$/; * } * * @param abi The ABI to process - * @param options Configuration options - * @returns A new ABI with filled parameter names + * @returns A new ABI with tuple component names filled */ export function abiFillEmptyNames(abi: ABI): ABI { function processComponents(components: ABIInOut[]): void { From 4a1af221434f78e2b3866d7bbd2e865a1794a2d7 Mon Sep 17 00:00:00 2001 From: Yota Date: Thu, 7 Nov 2024 15:36:06 +0900 Subject: [PATCH 05/12] whatsabi: Add exports --- src/whatsabi.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/whatsabi.ts b/src/whatsabi.ts index 3747ad0..6b20413 100644 --- a/src/whatsabi.ts +++ b/src/whatsabi.ts @@ -26,5 +26,8 @@ export { proxies }; import * as providers from "./providers.js"; export { providers }; +import * as helpers from "./helpers.js"; +export { helpers }; + import * as errors from "./errors.js"; export { errors }; From d582649ae004a6b9e58011f56b3bebbc4274f635 Mon Sep 17 00:00:00 2001 From: Yota Date: Fri, 8 Nov 2024 09:30:20 +0900 Subject: [PATCH 06/12] use startsWith to type check --- src/helpers.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/helpers.ts b/src/helpers.ts index 972a678..89aa024 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -1,9 +1,5 @@ import type { ABI, ABIFunction, ABIInOut } from "./abi.js"; -// Regular expression to match tuple types. -// Example: tuple, tuple[], tuple[5] -const reTupleType = /^tuple(\[\d*\])?$/; - /** * Fills tuple component's empty names in an ABI with generated names * @@ -63,7 +59,7 @@ export function abiFillEmptyNames(abi: ABI): ABI { function processComponents(components: ABIInOut[]): void { components.forEach((component, index) => { component.name ||= `field${index}`; - if (component.type.match(reTupleType) && component.components) { + if (isTupleType(component.type) && component.components) { processComponents(component.components); } }); @@ -73,12 +69,12 @@ export function abiFillEmptyNames(abi: ABI): ABI { if (item.type === "function") { const func: ABIFunction = { ...item }; func.inputs?.forEach((input) => { - if (input.type.match(reTupleType) && input.components) { + if (isTupleType(input.type) && input.components) { processComponents(input.components); } }); func.outputs?.forEach((output) => { - if (output.type.match(reTupleType) && output.components) { + if (isTupleType(output.type) && output.components) { processComponents(output.components); } }); @@ -89,3 +85,12 @@ export function abiFillEmptyNames(abi: ABI): ABI { return result; } + +/** + * Checks if a type is a tuple type (e.g. "tuple", "tuple[]", "tuple[2]") + * @param type type to check + * @returns true if the type is a tuple type + */ +function isTupleType(type: string): boolean { + return type.startsWith("tuple"); +} \ No newline at end of file From 6a0590f2a8fbfef7e3dedee097bfcb090aeed202 Mon Sep 17 00:00:00 2001 From: Yota Date: Fri, 8 Nov 2024 09:35:06 +0900 Subject: [PATCH 07/12] merge helper.ts and abi.ts --- .../{helpers.test.ts => abi.test.ts} | 3 +- src/abi.ts | 95 ++++++++++++++++++ src/helpers.ts | 96 ------------------- src/whatsabi.ts | 4 +- 4 files changed, 98 insertions(+), 100 deletions(-) rename src/__tests__/{helpers.test.ts => abi.test.ts} (98%) delete mode 100644 src/helpers.ts diff --git a/src/__tests__/helpers.test.ts b/src/__tests__/abi.test.ts similarity index 98% rename from src/__tests__/helpers.test.ts rename to src/__tests__/abi.test.ts index 1885bba..c6c4beb 100644 --- a/src/__tests__/helpers.test.ts +++ b/src/__tests__/abi.test.ts @@ -1,7 +1,6 @@ import { expect, describe, it } from "vitest"; -import { abiFillEmptyNames } from "../helpers"; -import { ABI } from "../abi"; +import { ABI, abiFillEmptyNames } from "../abi"; describe("abiFillEmptyNames", () => { type testCase = { diff --git a/src/abi.ts b/src/abi.ts index 861295b..25f96e6 100644 --- a/src/abi.ts +++ b/src/abi.ts @@ -37,3 +37,98 @@ export type ABIOutput = { export type ABIInOut = ABIInput|ABIOutput; export type ABI = (ABIFunction|ABIEvent)[]; + +/** + * Fills tuple component's empty names in an ABI with generated names + * + * @example + * Input: { + * "type": "function", + * "selector": "0x95d376d7", + * "payable": false, + * "stateMutability": "payable", + * "inputs": [ + * { + * "type": "tuple", + * "name": "", + * "components": [ + * { "type": "uint32", "name": "" }, + * { "type": "bytes", "name": "" }, + * { "type": "bytes32", "name": "" }, + * { "type": "uint64", "name": "" }, + * { "type": "address", "name": "" } + * ] + * }, + * { "type": "bytes", "name": "" } + * ], + * "sig": "assignJob((uint32,bytes,bytes32,uint64,address),bytes)", + * "name": "assignJob", + * "constant": false + * } + * + * Output: { + * "type": "function", + * "selector": "0x95d376d7", + * "payable": false, + * "stateMutability": "payable", + * "inputs": [ + * { + * "type": "tuple", + * "name": "", + * "components": [ + * { "type": "uint32", "name": "field0" }, + * { "type": "bytes", "name": "field1" }, + * { "type": "bytes32", "name": "field2" }, + * { "type": "uint64", "name": "field3" }, + * { "type": "address", "name": "field4" } + * ] + * }, + * { "type": "bytes", "name": "" } + * ], + * "sig": "assignJob((uint32,bytes,bytes32,uint64,address),bytes)", + * "name": "assignJob", + * "constant": false + * } + * + * @param abi The ABI to process + * @returns A new ABI with tuple component names filled + */ +export function abiFillEmptyNames(abi: ABI): ABI { + function processComponents(components: ABIInOut[]): void { + components.forEach((component, index) => { + component.name ||= `field${index}`; + if (isTupleType(component.type) && component.components) { + processComponents(component.components); + } + }); + } + + const result: ABI = abi.map((item) => { + if (item.type === "function") { + const func: ABIFunction = { ...item }; + func.inputs?.forEach((input) => { + if (isTupleType(input.type) && input.components) { + processComponents(input.components); + } + }); + func.outputs?.forEach((output) => { + if (isTupleType(output.type) && output.components) { + processComponents(output.components); + } + }); + return func; + } + return item; + }); + + return result; +} + +/** + * Checks if a type is a tuple type (e.g. "tuple", "tuple[]", "tuple[2]") + * @param type type to check + * @returns true if the type is a tuple type + */ +function isTupleType(type: string): boolean { + return type.startsWith("tuple"); +} \ No newline at end of file diff --git a/src/helpers.ts b/src/helpers.ts deleted file mode 100644 index 89aa024..0000000 --- a/src/helpers.ts +++ /dev/null @@ -1,96 +0,0 @@ -import type { ABI, ABIFunction, ABIInOut } from "./abi.js"; - -/** - * Fills tuple component's empty names in an ABI with generated names - * - * @example - * Input: { - * "type": "function", - * "selector": "0x95d376d7", - * "payable": false, - * "stateMutability": "payable", - * "inputs": [ - * { - * "type": "tuple", - * "name": "", - * "components": [ - * { "type": "uint32", "name": "" }, - * { "type": "bytes", "name": "" }, - * { "type": "bytes32", "name": "" }, - * { "type": "uint64", "name": "" }, - * { "type": "address", "name": "" } - * ] - * }, - * { "type": "bytes", "name": "" } - * ], - * "sig": "assignJob((uint32,bytes,bytes32,uint64,address),bytes)", - * "name": "assignJob", - * "constant": false - * } - * - * Output: { - * "type": "function", - * "selector": "0x95d376d7", - * "payable": false, - * "stateMutability": "payable", - * "inputs": [ - * { - * "type": "tuple", - * "name": "", - * "components": [ - * { "type": "uint32", "name": "field0" }, - * { "type": "bytes", "name": "field1" }, - * { "type": "bytes32", "name": "field2" }, - * { "type": "uint64", "name": "field3" }, - * { "type": "address", "name": "field4" } - * ] - * }, - * { "type": "bytes", "name": "" } - * ], - * "sig": "assignJob((uint32,bytes,bytes32,uint64,address),bytes)", - * "name": "assignJob", - * "constant": false - * } - * - * @param abi The ABI to process - * @returns A new ABI with tuple component names filled - */ -export function abiFillEmptyNames(abi: ABI): ABI { - function processComponents(components: ABIInOut[]): void { - components.forEach((component, index) => { - component.name ||= `field${index}`; - if (isTupleType(component.type) && component.components) { - processComponents(component.components); - } - }); - } - - const result: ABI = abi.map((item) => { - if (item.type === "function") { - const func: ABIFunction = { ...item }; - func.inputs?.forEach((input) => { - if (isTupleType(input.type) && input.components) { - processComponents(input.components); - } - }); - func.outputs?.forEach((output) => { - if (isTupleType(output.type) && output.components) { - processComponents(output.components); - } - }); - return func; - } - return item; - }); - - return result; -} - -/** - * Checks if a type is a tuple type (e.g. "tuple", "tuple[]", "tuple[2]") - * @param type type to check - * @returns true if the type is a tuple type - */ -function isTupleType(type: string): boolean { - return type.startsWith("tuple"); -} \ No newline at end of file diff --git a/src/whatsabi.ts b/src/whatsabi.ts index 6b20413..04ec134 100644 --- a/src/whatsabi.ts +++ b/src/whatsabi.ts @@ -26,8 +26,8 @@ export { proxies }; import * as providers from "./providers.js"; export { providers }; -import * as helpers from "./helpers.js"; -export { helpers }; +import * as abi from "./abi.js"; +export { abi }; import * as errors from "./errors.js"; export { errors }; From add0386da903f63f1bb25538f516c293f534f655 Mon Sep 17 00:00:00 2001 From: Yota Date: Fri, 8 Nov 2024 09:57:42 +0900 Subject: [PATCH 08/12] fix convention --- src/__tests__/abi.test.ts | 40 +++++++++++++++++++-------------------- src/abi.ts | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/__tests__/abi.test.ts b/src/__tests__/abi.test.ts index c6c4beb..ae8d8e7 100644 --- a/src/__tests__/abi.test.ts +++ b/src/__tests__/abi.test.ts @@ -62,11 +62,11 @@ describe("abiFillEmptyNames", () => { type: "tuple", name: "", components: [ - { type: "uint32", name: "field0" }, - { type: "bytes", name: "field1" }, - { type: "bytes32", name: "field2" }, - { type: "uint64", name: "field3" }, - { type: "address", name: "field4" }, + { type: "uint32", name: "_p0" }, + { type: "bytes", name: "_p1" }, + { type: "bytes32", name: "_p2" }, + { type: "uint64", name: "_p3" }, + { type: "address", name: "_p4" }, ], }, { type: "bytes", name: "" }, @@ -76,11 +76,11 @@ describe("abiFillEmptyNames", () => { type: "tuple", name: "", components: [ - { type: "uint32", name: "field0" }, - { type: "bytes", name: "field1" }, - { type: "bytes32", name: "field2" }, - { type: "uint64", name: "field3" }, - { type: "address", name: "field4" }, + { type: "uint32", name: "_p0" }, + { type: "bytes", name: "_p1" }, + { type: "bytes32", name: "_p2" }, + { type: "uint64", name: "_p3" }, + { type: "address", name: "_p4" }, ], }, { type: "bytes", name: "" }, @@ -142,15 +142,15 @@ describe("abiFillEmptyNames", () => { components: [ { type: "tuple", - name: "field0", + name: "_p0", components: [ { type: "tuple", - name: "field0", + name: "_p0", components: [ { type: "uint256", - name: "field0", + name: "_p0", }, { type: "address", name: "x" }, ], @@ -162,7 +162,7 @@ describe("abiFillEmptyNames", () => { { type: "uint256", name: "y" }, { type: "address", - name: "field1", + name: "_p1", }, ], }, @@ -220,19 +220,19 @@ describe("abiFillEmptyNames", () => { type: "tuple", components: [ { - name: "field0", + name: "_p0", type: "tuple[]", components: [ - { name: "field0", type: "uint256" }, - { name: "field1", type: "uint256" }, + { name: "_p0", type: "uint256" }, + { name: "_p1", type: "uint256" }, ], }, { - name: "field1", + name: "_p1", type: "tuple[2]", components: [ - { name: "field0", type: "uint256" }, - { name: "field1", type: "uint256" }, + { name: "_p0", type: "uint256" }, + { name: "_p1", type: "uint256" }, ], }, ], diff --git a/src/abi.ts b/src/abi.ts index 25f96e6..0532404 100644 --- a/src/abi.ts +++ b/src/abi.ts @@ -96,7 +96,7 @@ export type ABI = (ABIFunction|ABIEvent)[]; export function abiFillEmptyNames(abi: ABI): ABI { function processComponents(components: ABIInOut[]): void { components.forEach((component, index) => { - component.name ||= `field${index}`; + component.name ||= `_p${index}`; if (isTupleType(component.type) && component.components) { processComponents(component.components); } From 1b24265de78205c174d8ab6cfc26a42301a91296 Mon Sep 17 00:00:00 2001 From: Yota Date: Fri, 8 Nov 2024 10:04:50 +0900 Subject: [PATCH 09/12] update convention --- src/__tests__/abi.test.ts | 40 +++++++++++++++++++-------------------- src/abi.ts | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/__tests__/abi.test.ts b/src/__tests__/abi.test.ts index ae8d8e7..7c8a1cc 100644 --- a/src/__tests__/abi.test.ts +++ b/src/__tests__/abi.test.ts @@ -62,11 +62,11 @@ describe("abiFillEmptyNames", () => { type: "tuple", name: "", components: [ - { type: "uint32", name: "_p0" }, - { type: "bytes", name: "_p1" }, - { type: "bytes32", name: "_p2" }, - { type: "uint64", name: "_p3" }, - { type: "address", name: "_p4" }, + { type: "uint32", name: "_param0" }, + { type: "bytes", name: "_param1" }, + { type: "bytes32", name: "_param2" }, + { type: "uint64", name: "_param3" }, + { type: "address", name: "_param4" }, ], }, { type: "bytes", name: "" }, @@ -76,11 +76,11 @@ describe("abiFillEmptyNames", () => { type: "tuple", name: "", components: [ - { type: "uint32", name: "_p0" }, - { type: "bytes", name: "_p1" }, - { type: "bytes32", name: "_p2" }, - { type: "uint64", name: "_p3" }, - { type: "address", name: "_p4" }, + { type: "uint32", name: "_param0" }, + { type: "bytes", name: "_param1" }, + { type: "bytes32", name: "_param2" }, + { type: "uint64", name: "_param3" }, + { type: "address", name: "_param4" }, ], }, { type: "bytes", name: "" }, @@ -142,15 +142,15 @@ describe("abiFillEmptyNames", () => { components: [ { type: "tuple", - name: "_p0", + name: "_param0", components: [ { type: "tuple", - name: "_p0", + name: "_param0", components: [ { type: "uint256", - name: "_p0", + name: "_param0", }, { type: "address", name: "x" }, ], @@ -162,7 +162,7 @@ describe("abiFillEmptyNames", () => { { type: "uint256", name: "y" }, { type: "address", - name: "_p1", + name: "_param1", }, ], }, @@ -220,19 +220,19 @@ describe("abiFillEmptyNames", () => { type: "tuple", components: [ { - name: "_p0", + name: "_param0", type: "tuple[]", components: [ - { name: "_p0", type: "uint256" }, - { name: "_p1", type: "uint256" }, + { name: "_param0", type: "uint256" }, + { name: "_param1", type: "uint256" }, ], }, { - name: "_p1", + name: "_param1", type: "tuple[2]", components: [ - { name: "_p0", type: "uint256" }, - { name: "_p1", type: "uint256" }, + { name: "_param0", type: "uint256" }, + { name: "_param1", type: "uint256" }, ], }, ], diff --git a/src/abi.ts b/src/abi.ts index 0532404..d7f76fe 100644 --- a/src/abi.ts +++ b/src/abi.ts @@ -96,7 +96,7 @@ export type ABI = (ABIFunction|ABIEvent)[]; export function abiFillEmptyNames(abi: ABI): ABI { function processComponents(components: ABIInOut[]): void { components.forEach((component, index) => { - component.name ||= `_p${index}`; + component.name ||= `_param${index}`; if (isTupleType(component.type) && component.components) { processComponents(component.components); } From 2ba3e9e366c27e62c6b8cb7611faa3ebbf76d990 Mon Sep 17 00:00:00 2001 From: Yota Date: Fri, 8 Nov 2024 10:28:10 +0900 Subject: [PATCH 10/12] rename function --- src/__tests__/abi.test.ts | 6 +++--- src/abi.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/__tests__/abi.test.ts b/src/__tests__/abi.test.ts index 7c8a1cc..b9c8b79 100644 --- a/src/__tests__/abi.test.ts +++ b/src/__tests__/abi.test.ts @@ -1,8 +1,8 @@ import { expect, describe, it } from "vitest"; -import { ABI, abiFillEmptyNames } from "../abi"; +import { ABI, fillEmptyNames } from "../abi"; -describe("abiFillEmptyNames", () => { +describe("fillEmptyNames", () => { type testCase = { name: string; abi: Array; @@ -252,7 +252,7 @@ describe("abiFillEmptyNames", () => { testCases.forEach((tc) => { it(tc.name, () => { - expect(abiFillEmptyNames(tc.abi as ABI)).toStrictEqual(tc.want); + expect(fillEmptyNames(tc.abi as ABI)).toStrictEqual(tc.want); }); }); }); diff --git a/src/abi.ts b/src/abi.ts index d7f76fe..d58e649 100644 --- a/src/abi.ts +++ b/src/abi.ts @@ -93,7 +93,7 @@ export type ABI = (ABIFunction|ABIEvent)[]; * @param abi The ABI to process * @returns A new ABI with tuple component names filled */ -export function abiFillEmptyNames(abi: ABI): ABI { +export function fillEmptyNames(abi: ABI): ABI { function processComponents(components: ABIInOut[]): void { components.forEach((component, index) => { component.name ||= `_param${index}`; From 32be43b2d3b525177bba37196871232701fd4a39 Mon Sep 17 00:00:00 2001 From: Yota Date: Fri, 8 Nov 2024 10:35:07 +0900 Subject: [PATCH 11/12] remove from autoload --- src/auto.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/auto.ts b/src/auto.ts index 69d11e4..33196ae 100644 --- a/src/auto.ts +++ b/src/auto.ts @@ -111,13 +111,6 @@ export type AutoloadConfig = { * @experimental */ enableExperimentalMetadata?: boolean; - - /** - * Enable ABI helpers to apply additional transformations to the ABI before returning. - * @group Settings - * @experimental - */ - abiHelpers?: Array<(abi: ABI) => ABI>; } /** @@ -367,12 +360,6 @@ export async function autoload(address: string, config: AutoloadConfig): Promise ); } - if (config.abiHelpers) { - for (const helper of config.abiHelpers) { - result.abi = helper(result.abi); - } - } - return result; } From 6f618fc2e3d3cbb15d1450cf76f4db7104bee06a Mon Sep 17 00:00:00 2001 From: Yota Date: Fri, 8 Nov 2024 10:45:28 +0900 Subject: [PATCH 12/12] fix comments --- src/abi.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/abi.ts b/src/abi.ts index d58e649..d3dcd1d 100644 --- a/src/abi.ts +++ b/src/abi.ts @@ -76,11 +76,11 @@ export type ABI = (ABIFunction|ABIEvent)[]; * "type": "tuple", * "name": "", * "components": [ - * { "type": "uint32", "name": "field0" }, - * { "type": "bytes", "name": "field1" }, - * { "type": "bytes32", "name": "field2" }, - * { "type": "uint64", "name": "field3" }, - * { "type": "address", "name": "field4" } + * { "type": "uint32", "name": "_param0" }, + * { "type": "bytes", "name": "_param1" }, + * { "type": "bytes32", "name": "_param2" }, + * { "type": "uint64", "name": "_param3" }, + * { "type": "address", "name": "_param4" } * ] * }, * { "type": "bytes", "name": "" }