From e45fe0f419931a51ae7991d7a06f40ca3b0a8456 Mon Sep 17 00:00:00 2001 From: Tom Meagher Date: Fri, 31 Oct 2025 20:37:09 -0400 Subject: [PATCH 1/8] feat(experiment): named tuples --- packages/abitype/src/utils.bench-d.ts | 11 ++++++++ packages/abitype/src/utils.test-d.ts | 10 ++++++++ packages/abitype/src/utils.ts | 37 ++++++++++++++++++++------- 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/packages/abitype/src/utils.bench-d.ts b/packages/abitype/src/utils.bench-d.ts index 424c8a3f..e0a5c584 100644 --- a/packages/abitype/src/utils.bench-d.ts +++ b/packages/abitype/src/utils.bench-d.ts @@ -1,9 +1,11 @@ import { attest } from '@arktype/attest' import { describe, test } from 'vitest' +import type { erc20Abi } from './abis/json.js' import type { AbiParameterToPrimitiveType, AbiParametersToPrimitiveTypes, + ExtractAbiFunction, TypedDataToPrimitiveTypes, } from './utils.js' @@ -266,3 +268,12 @@ test('self-referencing', () => { } }>(res) }) + +type abiItem = ExtractAbiFunction['inputs'] +test('custom named tuples', () => { + const res = {} as AbiParametersToPrimitiveTypes + attest.instantiations([902, 'instantiations']) + attest< + readonly [sender: `0x${string}`, recipient: `0x${string}`, amount: bigint] + >(res) +}) diff --git a/packages/abitype/src/utils.test-d.ts b/packages/abitype/src/utils.test-d.ts index 8c17e6c6..d97d9c97 100644 --- a/packages/abitype/src/utils.test-d.ts +++ b/packages/abitype/src/utils.test-d.ts @@ -4,6 +4,7 @@ import type { Abi } from './abi.js' import type { customSolidityErrorsAbi, ensRegistryWithFallbackAbi, + erc20Abi, nestedTupleArrayAbi, nounsAuctionHouseAbi, wagmiMintExampleAbi, @@ -517,6 +518,15 @@ describe('AbiParametersToPrimitiveTypes', () => { '0xfoo', ]) }) + + test('named parameters', () => { + type Result = AbiParametersToPrimitiveTypes< + ExtractAbiFunction['inputs'] + > + expectTypeOf().toEqualTypeOf< + [sender: `0x${string}`, recipient: `0x${string}`, amount: bigint] + >() + }) }) describe('IsAbi', () => { diff --git a/packages/abitype/src/utils.ts b/packages/abitype/src/utils.ts index 6f0bfca6..4269ec74 100644 --- a/packages/abitype/src/utils.ts +++ b/packages/abitype/src/utils.ts @@ -15,8 +15,9 @@ import type { TypedDataParameter, TypedDataType, } from './abi.js' +import type { erc20Abi } from './abis/json.ts' import type { ResolvedRegister } from './register.js' -import type { Error, Merge, Pretty, Tuple } from './types.js' +import type { Error, IsNever, Merge, Pretty, Tuple } from './types.js' /** * Converts {@link AbiType} to corresponding TypeScript primitive type. @@ -188,15 +189,33 @@ type AbiArrayToPrimitiveType< export type AbiParametersToPrimitiveTypes< abiParameters extends readonly AbiParameter[], abiParameterKind extends AbiParameterKind = AbiParameterKind, -> = Pretty<{ - // TODO: Convert to labeled tuple so parameter names show up in autocomplete - // e.g. [foo: string, bar: string] - // https://github.com/microsoft/TypeScript/issues/44939 - [key in keyof abiParameters]: AbiParameterToPrimitiveType< - abiParameters[key], + /// + namedOutput extends ToNamedTuple< + abiParameters, abiParameterKind - > -}> + > = ToNamedTuple, +> = IsNever extends true + ? Pretty<{ + // TODO: Convert to labeled tuple so parameter names show up in autocomplete + // e.g. [foo: string, bar: string] + // https://github.com/microsoft/TypeScript/issues/44939 + [key in keyof abiParameters]: AbiParameterToPrimitiveType< + abiParameters[key], + abiParameterKind + > + }> + : namedOutput + +// biome-ignore format: no formatting +type ToNamedTuple< + ap extends readonly AbiParameter[], + apk extends AbiParameterKind = AbiParameterKind, +> = + | ap extends readonly [{name:"owner"} & AbiParameter, {name:"spender"} & AbiParameter] ? readonly [owner: AbiParameterToPrimitiveType, spender: AbiParameterToPrimitiveType] : never + | ap extends readonly [{name:"spender"} & AbiParameter, {name:"amount"} & AbiParameter] ? readonly [spender: AbiParameterToPrimitiveType, amount: AbiParameterToPrimitiveType] : never + | ap extends readonly [{name:"account"} & AbiParameter] ? [account: AbiParameterToPrimitiveType] : never + | ap extends readonly [{name:"recipient"} & AbiParameter, {name:"amount"} & AbiParameter] ? readonly [recipient: AbiParameterToPrimitiveType, amount: AbiParameterToPrimitiveType] : never + | ap extends readonly [{name:"sender"} & AbiParameter, {name:"recipient"} & AbiParameter, {name:"amount"} & AbiParameter] ? readonly [sender: AbiParameterToPrimitiveType, recipient: AbiParameterToPrimitiveType, amount: AbiParameterToPrimitiveType] : never /** * Checks if type is {@link Abi}. From 42ea6a78589e65893cffea1d8cbaaab99b2a4026 Mon Sep 17 00:00:00 2001 From: Tom Meagher Date: Tue, 18 Nov 2025 19:39:00 -0500 Subject: [PATCH 2/8] refactor: use tail recursion instead --- packages/abitype/src/register.ts | 7 ++ packages/abitype/src/utils.bench-d.ts | 52 +++++++++-- packages/abitype/src/utils.test-d.ts | 2 +- packages/abitype/src/utils.ts | 109 +++++++++++++++++------ playgrounds/functions/src/read.test-d.ts | 4 +- 5 files changed, 140 insertions(+), 34 deletions(-) diff --git a/packages/abitype/src/register.ts b/packages/abitype/src/register.ts index 4f29120e..c3021cff 100644 --- a/packages/abitype/src/register.ts +++ b/packages/abitype/src/register.ts @@ -102,6 +102,11 @@ export type ResolvedRegister = { ? type : DefaultRegister['strictAbiType'] + /** TODO */ + namedTuples: Register extends { namedTuples: infer type extends boolean } + ? type + : DefaultRegister['namedTuples'] + /** @deprecated Use `addressType` instead */ AddressType: ResolvedRegister['addressType'] /** @deprecated Use `addressType` instead */ @@ -145,6 +150,8 @@ export type DefaultRegister = { /** When set, validates {@link AbiParameter}'s `type` against {@link AbiType} */ strictAbiType: false + namedTuples: false + /** @deprecated Use `arrayMaxDepth` instead */ ArrayMaxDepth: DefaultRegister['arrayMaxDepth'] /** @deprecated Use `fixedArrayMinLength` instead */ diff --git a/packages/abitype/src/utils.bench-d.ts b/packages/abitype/src/utils.bench-d.ts index e0a5c584..a201017e 100644 --- a/packages/abitype/src/utils.bench-d.ts +++ b/packages/abitype/src/utils.bench-d.ts @@ -1,6 +1,5 @@ import { attest } from '@arktype/attest' import { describe, test } from 'vitest' - import type { erc20Abi } from './abis/json.js' import type { AbiParameterToPrimitiveType, @@ -227,7 +226,7 @@ test('deeply nested parameters', () => { attest.instantiations([11348, 'instantiations']) attest< [ - { + s: { a: number b: readonly number[] c: readonly { @@ -269,11 +268,52 @@ test('self-referencing', () => { }>(res) }) -type abiItem = ExtractAbiFunction['inputs'] -test('custom named tuples', () => { - const res = {} as AbiParametersToPrimitiveTypes - attest.instantiations([902, 'instantiations']) +type transferFrom = ExtractAbiFunction< + typeof erc20Abi, + 'transferFrom' +>['inputs'] +test('basic without named tuple', () => { + const res = {} as AbiParametersToPrimitiveTypes + attest.instantiations([917, 'instantiations']) attest< readonly [sender: `0x${string}`, recipient: `0x${string}`, amount: bigint] >(res) }) +test('basic with named tuple', () => { + const res = {} as AbiParametersToPrimitiveTypes + attest.instantiations([1172, 'instantiations']) + attest< + readonly [sender: `0x${string}`, recipient: `0x${string}`, amount: bigint] + >(res) +}) + +type parameters = readonly [ + { name: 'account'; type: 'uint8' }, + { name: 'address'; type: 'uint8' }, + { name: 'admin'; type: 'uint8' }, + { name: 'allowed'; type: 'uint8' }, + { name: 'amount'; type: 'uint8' }, + { name: 'authority'; type: 'uint8' }, + { name: 'available'; type: 'uint8' }, + { name: 'count'; type: 'uint8' }, + { name: 'currency'; type: 'uint8' }, + { name: 'deadline'; type: 'uint8' }, + { name: 'from'; type: 'uint8' }, + { name: 'funder'; type: 'uint8' }, + { name: 'hash'; type: 'address' }, + { name: 'id'; type: 'uint8' }, + { name: 'memo'; type: 'uint8' }, + { name: 'nonce'; type: 'uint8' }, + { name: 'nonceKey'; type: 'uint8' }, + { name: 'owner'; type: 'uint8' }, + { name: 'policyId'; type: 'uint8' }, + { name: 'policyType'; type: 'uint8' }, +] +test('without named tuples', () => { + ;({}) as AbiParametersToPrimitiveTypes + attest.instantiations([1286, 'instantiations']) +}) +test('with named tuples', () => { + ;({}) as AbiParametersToPrimitiveTypes + attest.instantiations([3591, 'instantiations']) +}) diff --git a/packages/abitype/src/utils.test-d.ts b/packages/abitype/src/utils.test-d.ts index d97d9c97..8e414e1d 100644 --- a/packages/abitype/src/utils.test-d.ts +++ b/packages/abitype/src/utils.test-d.ts @@ -524,7 +524,7 @@ describe('AbiParametersToPrimitiveTypes', () => { ExtractAbiFunction['inputs'] > expectTypeOf().toEqualTypeOf< - [sender: `0x${string}`, recipient: `0x${string}`, amount: bigint] + readonly [sender: `0x${string}`, recipient: `0x${string}`, amount: bigint] >() }) }) diff --git a/packages/abitype/src/utils.ts b/packages/abitype/src/utils.ts index 4269ec74..d4d55703 100644 --- a/packages/abitype/src/utils.ts +++ b/packages/abitype/src/utils.ts @@ -1,5 +1,6 @@ import type { Abi, + AbiFunction, AbiParameter, AbiParameterKind, AbiStateMutability, @@ -15,9 +16,8 @@ import type { TypedDataParameter, TypedDataType, } from './abi.js' -import type { erc20Abi } from './abis/json.ts' import type { ResolvedRegister } from './register.js' -import type { Error, IsNever, Merge, Pretty, Tuple } from './types.js' +import type { Error, Merge, Pretty, Tuple } from './types.js' /** * Converts {@link AbiType} to corresponding TypeScript primitive type. @@ -190,32 +190,91 @@ export type AbiParametersToPrimitiveTypes< abiParameters extends readonly AbiParameter[], abiParameterKind extends AbiParameterKind = AbiParameterKind, /// - namedOutput extends ToNamedTuple< - abiParameters, + namedTuples extends boolean = ResolvedRegister['namedTuples'], +> = namedTuples extends true + ? AbiParametersToPrimitiveTypes_named + : AbiParametersToPrimitiveTypes_mapped + +export type AbiParametersToPrimitiveTypes_mapped< + abiParameters extends readonly AbiParameter[], + abiParameterKind extends AbiParameterKind = AbiParameterKind, +> = Pretty<{ + [key in keyof abiParameters]: AbiParameterToPrimitiveType< + abiParameters[key], abiParameterKind - > = ToNamedTuple, -> = IsNever extends true - ? Pretty<{ - // TODO: Convert to labeled tuple so parameter names show up in autocomplete - // e.g. [foo: string, bar: string] - // https://github.com/microsoft/TypeScript/issues/44939 - [key in keyof abiParameters]: AbiParameterToPrimitiveType< - abiParameters[key], - abiParameterKind - > - }> - : namedOutput + > +}> + +export type AbiParametersToPrimitiveTypes_named< + abiParameters extends readonly AbiParameter[], + abiParameterKind extends AbiParameterKind = AbiParameterKind, + /// + acc extends readonly unknown[] = [], + // FIXME: Workaround to create labeled tuple so parameter names show up in autocomplete + // e.g. [foo: string, bar: string] + // Ideally this is a simple mapped type instead of tail recurision, but TypeScript does not support dynamic tuple labels + // https://github.com/microsoft/TypeScript/issues/44939 +> = abiParameters extends readonly [ + infer head extends AbiParameter, + ...infer tail extends readonly AbiParameter[], +] + ? AbiParametersToPrimitiveTypes_named< + tail, + abiParameterKind, + readonly [...acc, ...ToNamedTuple] + > + : acc extends readonly [] + ? abiParameters extends readonly [] + ? readonly [] + : readonly unknown[] + : acc -// biome-ignore format: no formatting type ToNamedTuple< - ap extends readonly AbiParameter[], - apk extends AbiParameterKind = AbiParameterKind, -> = - | ap extends readonly [{name:"owner"} & AbiParameter, {name:"spender"} & AbiParameter] ? readonly [owner: AbiParameterToPrimitiveType, spender: AbiParameterToPrimitiveType] : never - | ap extends readonly [{name:"spender"} & AbiParameter, {name:"amount"} & AbiParameter] ? readonly [spender: AbiParameterToPrimitiveType, amount: AbiParameterToPrimitiveType] : never - | ap extends readonly [{name:"account"} & AbiParameter] ? [account: AbiParameterToPrimitiveType] : never - | ap extends readonly [{name:"recipient"} & AbiParameter, {name:"amount"} & AbiParameter] ? readonly [recipient: AbiParameterToPrimitiveType, amount: AbiParameterToPrimitiveType] : never - | ap extends readonly [{name:"sender"} & AbiParameter, {name:"recipient"} & AbiParameter, {name:"amount"} & AbiParameter] ? readonly [sender: AbiParameterToPrimitiveType, recipient: AbiParameterToPrimitiveType, amount: AbiParameterToPrimitiveType] : never + abiParameter extends AbiParameter, + abiParameterKind extends AbiParameterKind, + /// + type = AbiParameterToPrimitiveType, +> = NameLookup[(abiParameter & { name: string })['name']] + +interface NameLookup extends Record { + account: [account: type] + address: [address: type] + admin: [admin: type] + allowed: [allowed: type] + amount: [amount: type] + authority: [authority: type] + available: [available: type] + count: [count: type] + currency: [currency: type] + deadline: [deadline: type] + from: [from: type] + funder: [funder: type] + hash: [hash: type] + id: [id: type] + memo: [memo: type] + nonce: [nonce: type] + nonceKey: [nonceKey: type] + owner: [owner: type] + policyId: [policyId: type] + policyType: [policyType: type] + quoteToken: [quoteToken: type] + r: [r: type] + recipient: [recipient: type] + refund: [refund: type] + restricted: [restricted: type] + s: [s: type] + secs: [secs: type] + sender: [sender: type] + signature: [signature: type] + symbol: [symbol: type] + to: [to: type] + token: [token: type] + tokenId: [tokenId: type] + updater: [updater: type] + user: [user: type] + v: [v: type] + value: [value: type] +} /** * Checks if type is {@link Abi}. diff --git a/playgrounds/functions/src/read.test-d.ts b/playgrounds/functions/src/read.test-d.ts index 6ee334a7..556fe029 100644 --- a/playgrounds/functions/src/read.test-d.ts +++ b/playgrounds/functions/src/read.test-d.ts @@ -220,8 +220,8 @@ const abi = parseAbi([ 'function foo() returns (bool)', 'function foo() returns (uint8)', 'function foo(uint) view returns (address)', - 'function foo(address) view returns (uint)', - 'function foo(uint256, address) view returns (address, uint8)', + 'function foo(address account) view returns (uint)', + 'function foo(uint256 amount, address account) view returns (address, uint8)', 'function bar() pure returns (address)', 'function baz(uint) pure returns (string)', 'function boo(bytes32) pure returns (bytes32)', From 79115a7e91907f557e0e0e5f6f16b7e871732a08 Mon Sep 17 00:00:00 2001 From: Tom Meagher Date: Wed, 19 Nov 2025 00:41:41 -0500 Subject: [PATCH 3/8] chore: tweaks --- .github/workflows/verify.yml | 2 +- docs/pages/config.md | 15 +++++++++++++++ packages/abitype/src/register.ts | 19 ++++++++++++------- packages/abitype/src/utils.bench-d.ts | 2 +- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 4f802115..07d782f3 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -50,7 +50,7 @@ jobs: timeout-minutes: 5 strategy: matrix: - version: ['5.0.4', '5.1.6', '5.2.2', '5.3.3', '5.4.5', '5.5.2', '5.6', 'latest'] + version: ['5.0.4', '5.1.6', '5.2.2', '5.3.3', '5.4.5', '5.5.4', '5.6.3', '5.7.3', '5.8.3', '5.9.3', 'latest'] steps: - name: Clone repository diff --git a/docs/pages/config.md b/docs/pages/config.md index 5297b012..a242f7a0 100644 --- a/docs/pages/config.md +++ b/docs/pages/config.md @@ -153,6 +153,21 @@ declare module 'abitype' { } ``` +### `namedTuples` + +Enables named tuple generation in [`AbiParametersToPrimitiveTypes`](/api/utilities#abiparameterstoprimitivetypes) for common ABI parameter names. + +- Type `boolean` +- Default `false` + +```ts twoslash +declare module 'abitype' { + export interface Register { + namedTuples: false + } +} +``` + ### `strictAbiType` When set, validates `AbiParameter`'s `type` against `AbiType`. diff --git a/packages/abitype/src/register.ts b/packages/abitype/src/register.ts index c3021cff..a11c4b61 100644 --- a/packages/abitype/src/register.ts +++ b/packages/abitype/src/register.ts @@ -88,6 +88,15 @@ export type ResolvedRegister = { ? type : DefaultRegister['fixedArrayMaxLength'] + /** + * Enables named tuple generation in {@link AbiParametersToPrimitiveTypes} for common ABI parameter names. + * + * @default false + */ + namedTuples: Register extends { namedTuples: infer type extends boolean } + ? type + : DefaultRegister['namedTuples'] + /** * When set, validates {@link AbiParameter}'s `type` against {@link AbiType} * @@ -102,11 +111,6 @@ export type ResolvedRegister = { ? type : DefaultRegister['strictAbiType'] - /** TODO */ - namedTuples: Register extends { namedTuples: infer type extends boolean } - ? type - : DefaultRegister['namedTuples'] - /** @deprecated Use `addressType` instead */ AddressType: ResolvedRegister['addressType'] /** @deprecated Use `addressType` instead */ @@ -147,11 +151,12 @@ export type DefaultRegister = { /** TypeScript type to use for `int` and `uint` values, where `M <= 48` */ intType: number + /** Enables named tuple generation in {@link AbiParametersToPrimitiveTypes} for common ABI parameter names */ + namedTuples: false + /** When set, validates {@link AbiParameter}'s `type` against {@link AbiType} */ strictAbiType: false - namedTuples: false - /** @deprecated Use `arrayMaxDepth` instead */ ArrayMaxDepth: DefaultRegister['arrayMaxDepth'] /** @deprecated Use `fixedArrayMinLength` instead */ diff --git a/packages/abitype/src/utils.bench-d.ts b/packages/abitype/src/utils.bench-d.ts index a201017e..58b55113 100644 --- a/packages/abitype/src/utils.bench-d.ts +++ b/packages/abitype/src/utils.bench-d.ts @@ -315,5 +315,5 @@ test('without named tuples', () => { }) test('with named tuples', () => { ;({}) as AbiParametersToPrimitiveTypes - attest.instantiations([3591, 'instantiations']) + attest.instantiations([3800, 'instantiations']) }) From 33d59da3d9d2f9e50b97ef2e16cfaa542c69332a Mon Sep 17 00:00:00 2001 From: Tom Meagher Date: Wed, 19 Nov 2025 01:09:27 -0500 Subject: [PATCH 4/8] chore: mv names --- packages/abitype/src/abi.ts | 100 ++++++++++++++++++++++++++++++++++ packages/abitype/src/utils.ts | 44 +-------------- 2 files changed, 102 insertions(+), 42 deletions(-) diff --git a/packages/abitype/src/abi.ts b/packages/abitype/src/abi.ts index 1eaa84ca..f7d6dffe 100644 --- a/packages/abitype/src/abi.ts +++ b/packages/abitype/src/abi.ts @@ -245,3 +245,103 @@ export type TypedData = Pretty< [_ in TypedDataType]?: never } > + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// ABI Parameter Names + +// TODO: Generate fields from common/ERC ABIs +export interface AbiParameterTupleNameLookup + extends Record { + account: [account: type] + accounts: [accounts: type] + address: [address: type] + addresses: [addresses: type] + admin: [admin: type] + allowFailure: [allowFailure: type] + allowed: [allowed: type] + amount: [amount: type] + approved: [approved: type] + approver: [approver: type] + assets: [assets: type] + authority: [authority: type] + available: [available: type] + balance: [balance: type] + callData: [callData: type] + caller: [caller: type] + calls: [calls: type] + coinType: [coinType: type] + count: [count: type] + currency: [currency: type] + data: [data: type] + deadline: [deadline: type] + dns: [dns: type] + dst: [dst: type] + ens: [ens: type] + errorData: [errorData: type] + failures: [failues: type] + from: [from: type] + funder: [funder: type] + gateways: [gateways: type] + guy: [guy: type] + hash: [hash: type] + id: [id: type] + ids: [ids: type] + idsLength: [idsLength: type] + interfaceId: [inferfaceId: type] + key: [key: type] + label: [label: type] + memo: [memo: type] + message: [message: type] + name: [name: type] + needed: [needed: type] + node: [node: type] + nonce: [nonce: type] + nonceKey: [nonceKey: type] + operator: [operator: type] + order: [order: type] + orders: [orders: type] + owner: [owner: type] + policyId: [policyId: type] + policyType: [policyType: type] + primary: [primary: type] + proposer: [proposer: type] + queries: [queries: type] + quoteToken: [quoteToken: type] + r: [r: type] + receiver: [receiver: type] + recipient: [recipient: type] + refund: [refund: type] + required: [required: type] + resolvedName: [resolvedName: type] + resolver: [resolver: type] + responses: [responses: type] + restricted: [restricted: type] + returnData: [returnData: type] + reverseName: [reverseName: type] + reverseResolver: [reverseResolver: type] + s: [s: type] + secs: [secs: type] + selector: [selector: type] + sender: [sender: type] + shares: [shares: type] + signature: [signature: type] + signer: [signer: type] + src: [src: type] + status: [status: type] + success: [success: type] + symbol: [symbol: type] + target: [target: type] + timestamp: [timestamp: type] + to: [to: type] + token: [token: type] + tokenId: [tokenId: type] + ttl: [ttl: type] + updater: [updater: type] + user: [user: type] + v: [v: type] + value: [value: type] + values: [values: type] + valuesLength: [valuesLength: type] + version: [version: type] + wad: [wad: type] +} diff --git a/packages/abitype/src/utils.ts b/packages/abitype/src/utils.ts index d4d55703..ea2ecfe2 100644 --- a/packages/abitype/src/utils.ts +++ b/packages/abitype/src/utils.ts @@ -1,8 +1,8 @@ import type { Abi, - AbiFunction, AbiParameter, AbiParameterKind, + AbiParameterTupleNameLookup, AbiStateMutability, AbiType, MBits, @@ -234,47 +234,7 @@ type ToNamedTuple< abiParameterKind extends AbiParameterKind, /// type = AbiParameterToPrimitiveType, -> = NameLookup[(abiParameter & { name: string })['name']] - -interface NameLookup extends Record { - account: [account: type] - address: [address: type] - admin: [admin: type] - allowed: [allowed: type] - amount: [amount: type] - authority: [authority: type] - available: [available: type] - count: [count: type] - currency: [currency: type] - deadline: [deadline: type] - from: [from: type] - funder: [funder: type] - hash: [hash: type] - id: [id: type] - memo: [memo: type] - nonce: [nonce: type] - nonceKey: [nonceKey: type] - owner: [owner: type] - policyId: [policyId: type] - policyType: [policyType: type] - quoteToken: [quoteToken: type] - r: [r: type] - recipient: [recipient: type] - refund: [refund: type] - restricted: [restricted: type] - s: [s: type] - secs: [secs: type] - sender: [sender: type] - signature: [signature: type] - symbol: [symbol: type] - to: [to: type] - token: [token: type] - tokenId: [tokenId: type] - updater: [updater: type] - user: [user: type] - v: [v: type] - value: [value: type] -} +> = AbiParameterTupleNameLookup[(abiParameter & { name: string })['name']] /** * Checks if type is {@link Abi}. From d104da11de0c4aa62fe8b5d2181de3be0b3fad54 Mon Sep 17 00:00:00 2001 From: Tom Meagher Date: Wed, 19 Nov 2025 17:27:32 -0500 Subject: [PATCH 5/8] chore: changeset --- .changeset/fresh-jokes-guess.md | 5 +++++ packages/abitype/src/abi.ts | 1 + packages/abitype/src/register.ts | 4 ++-- packages/abitype/src/utils.bench-d.ts | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 .changeset/fresh-jokes-guess.md diff --git a/.changeset/fresh-jokes-guess.md b/.changeset/fresh-jokes-guess.md new file mode 100644 index 00000000..848ee1b7 --- /dev/null +++ b/.changeset/fresh-jokes-guess.md @@ -0,0 +1,5 @@ +--- +"abitype": minor +--- + +Added common tuple labels to output of `AbiParametersToPrimitiveTypes` diff --git a/packages/abitype/src/abi.ts b/packages/abitype/src/abi.ts index f7d6dffe..69e50a50 100644 --- a/packages/abitype/src/abi.ts +++ b/packages/abitype/src/abi.ts @@ -252,6 +252,7 @@ export type TypedData = Pretty< // TODO: Generate fields from common/ERC ABIs export interface AbiParameterTupleNameLookup extends Record { + _data: [_data: type] account: [account: type] accounts: [accounts: type] address: [address: type] diff --git a/packages/abitype/src/register.ts b/packages/abitype/src/register.ts index a11c4b61..ae7d1be0 100644 --- a/packages/abitype/src/register.ts +++ b/packages/abitype/src/register.ts @@ -91,7 +91,7 @@ export type ResolvedRegister = { /** * Enables named tuple generation in {@link AbiParametersToPrimitiveTypes} for common ABI parameter names. * - * @default false + * @default true */ namedTuples: Register extends { namedTuples: infer type extends boolean } ? type @@ -152,7 +152,7 @@ export type DefaultRegister = { intType: number /** Enables named tuple generation in {@link AbiParametersToPrimitiveTypes} for common ABI parameter names */ - namedTuples: false + namedTuples: true /** When set, validates {@link AbiParameter}'s `type` against {@link AbiType} */ strictAbiType: false diff --git a/packages/abitype/src/utils.bench-d.ts b/packages/abitype/src/utils.bench-d.ts index 58b55113..7690c429 100644 --- a/packages/abitype/src/utils.bench-d.ts +++ b/packages/abitype/src/utils.bench-d.ts @@ -225,7 +225,7 @@ test('deeply nested parameters', () => { > attest.instantiations([11348, 'instantiations']) attest< - [ + readonly [ s: { a: number b: readonly number[] From 351d9271b645ff6ecbe5819ce136b5f7971184de Mon Sep 17 00:00:00 2001 From: Tom Meagher Date: Wed, 19 Nov 2025 20:55:52 -0500 Subject: [PATCH 6/8] chore: gen --- .changeset/fresh-jokes-guess.md | 2 +- docs/pages/config.md | 4 +- packages/abitype/src/abi.ts | 34 ++++-- packages/abitype/src/register.ts | 10 +- packages/abitype/src/utils.bench-d.ts | 2 +- packages/abitype/src/utils.ts | 5 +- scripts/genAbiParameterNameLookup.ts | 144 ++++++++++++++++++++++++++ 7 files changed, 185 insertions(+), 16 deletions(-) create mode 100644 scripts/genAbiParameterNameLookup.ts diff --git a/.changeset/fresh-jokes-guess.md b/.changeset/fresh-jokes-guess.md index 848ee1b7..c55ae14e 100644 --- a/.changeset/fresh-jokes-guess.md +++ b/.changeset/fresh-jokes-guess.md @@ -2,4 +2,4 @@ "abitype": minor --- -Added common tuple labels to output of `AbiParametersToPrimitiveTypes` +Added experimental named tuple support to `AbiParametersToPrimitiveTypes` diff --git a/docs/pages/config.md b/docs/pages/config.md index a242f7a0..2dc703e9 100644 --- a/docs/pages/config.md +++ b/docs/pages/config.md @@ -153,7 +153,7 @@ declare module 'abitype' { } ``` -### `namedTuples` +### `experimental_namedTuples` Enables named tuple generation in [`AbiParametersToPrimitiveTypes`](/api/utilities#abiparameterstoprimitivetypes) for common ABI parameter names. @@ -163,7 +163,7 @@ Enables named tuple generation in [`AbiParametersToPrimitiveTypes`](/api/utiliti ```ts twoslash declare module 'abitype' { export interface Register { - namedTuples: false + experimental_namedTuples: false } } ``` diff --git a/packages/abitype/src/abi.ts b/packages/abitype/src/abi.ts index 69e50a50..a22dc584 100644 --- a/packages/abitype/src/abi.ts +++ b/packages/abitype/src/abi.ts @@ -247,12 +247,11 @@ export type TypedData = Pretty< > //////////////////////////////////////////////////////////////////////////////////////////////////// -// ABI Parameter Names -// TODO: Generate fields from common/ERC ABIs -export interface AbiParameterTupleNameLookup - extends Record { +// biome-ignore format: no formatting +export interface AbiParameterTupleNameLookup extends Record { _data: [_data: type] + a: [a: type] account: [account: type] accounts: [accounts: type] address: [address: type] @@ -266,46 +265,62 @@ export interface AbiParameterTupleNameLookup assets: [assets: type] authority: [authority: type] available: [available: type] + b: [b: type] balance: [balance: type] + c: [c: type] callData: [callData: type] caller: [caller: type] calls: [calls: type] coinType: [coinType: type] count: [count: type] currency: [currency: type] + d: [d: type] data: [data: type] deadline: [deadline: type] dns: [dns: type] dst: [dst: type] + e: [e: type] ens: [ens: type] errorData: [errorData: type] - failures: [failues: type] + f: [f: type] + failures: [failures: type] from: [from: type] funder: [funder: type] + g: [g: type] gateways: [gateways: type] guy: [guy: type] + h: [h: type] hash: [hash: type] + i: [i: type] id: [id: type] ids: [ids: type] idsLength: [idsLength: type] - interfaceId: [inferfaceId: type] + interfaceId: [interfaceId: type] + j: [j: type] + k: [k: type] key: [key: type] + l: [l: type] label: [label: type] + m: [m: type] memo: [memo: type] message: [message: type] + n: [n: type] name: [name: type] needed: [needed: type] node: [node: type] nonce: [nonce: type] nonceKey: [nonceKey: type] + o: [o: type] operator: [operator: type] order: [order: type] orders: [orders: type] owner: [owner: type] + p: [p: type] policyId: [policyId: type] policyType: [policyType: type] primary: [primary: type] proposer: [proposer: type] + q: [q: type] queries: [queries: type] quoteToken: [quoteToken: type] r: [r: type] @@ -331,12 +346,14 @@ export interface AbiParameterTupleNameLookup status: [status: type] success: [success: type] symbol: [symbol: type] + t: [t: type] target: [target: type] timestamp: [timestamp: type] to: [to: type] token: [token: type] tokenId: [tokenId: type] ttl: [ttl: type] + u: [u: type] updater: [updater: type] user: [user: type] v: [v: type] @@ -344,5 +361,10 @@ export interface AbiParameterTupleNameLookup values: [values: type] valuesLength: [valuesLength: type] version: [version: type] + w: [w: type] wad: [wad: type] + x: [x: type] + y: [y: type] + z: [z: type] } + diff --git a/packages/abitype/src/register.ts b/packages/abitype/src/register.ts index ae7d1be0..f2ed7695 100644 --- a/packages/abitype/src/register.ts +++ b/packages/abitype/src/register.ts @@ -91,11 +91,13 @@ export type ResolvedRegister = { /** * Enables named tuple generation in {@link AbiParametersToPrimitiveTypes} for common ABI parameter names. * - * @default true + * @default false */ - namedTuples: Register extends { namedTuples: infer type extends boolean } + experimental_namedTuples: Register extends { + experimental_namedTuples: infer type extends boolean + } ? type - : DefaultRegister['namedTuples'] + : DefaultRegister['experimental_namedTuples'] /** * When set, validates {@link AbiParameter}'s `type` against {@link AbiType} @@ -152,7 +154,7 @@ export type DefaultRegister = { intType: number /** Enables named tuple generation in {@link AbiParametersToPrimitiveTypes} for common ABI parameter names */ - namedTuples: true + experimental_namedTuples: false /** When set, validates {@link AbiParameter}'s `type` against {@link AbiType} */ strictAbiType: false diff --git a/packages/abitype/src/utils.bench-d.ts b/packages/abitype/src/utils.bench-d.ts index 7690c429..58b55113 100644 --- a/packages/abitype/src/utils.bench-d.ts +++ b/packages/abitype/src/utils.bench-d.ts @@ -225,7 +225,7 @@ test('deeply nested parameters', () => { > attest.instantiations([11348, 'instantiations']) attest< - readonly [ + [ s: { a: number b: readonly number[] diff --git a/packages/abitype/src/utils.ts b/packages/abitype/src/utils.ts index ea2ecfe2..8a48791e 100644 --- a/packages/abitype/src/utils.ts +++ b/packages/abitype/src/utils.ts @@ -190,8 +190,9 @@ export type AbiParametersToPrimitiveTypes< abiParameters extends readonly AbiParameter[], abiParameterKind extends AbiParameterKind = AbiParameterKind, /// - namedTuples extends boolean = ResolvedRegister['namedTuples'], -> = namedTuples extends true + experimental_namedTuples extends + boolean = ResolvedRegister['experimental_namedTuples'], +> = experimental_namedTuples extends true ? AbiParametersToPrimitiveTypes_named : AbiParametersToPrimitiveTypes_mapped diff --git a/scripts/genAbiParameterNameLookup.ts b/scripts/genAbiParameterNameLookup.ts new file mode 100644 index 00000000..7cc1fca4 --- /dev/null +++ b/scripts/genAbiParameterNameLookup.ts @@ -0,0 +1,144 @@ +import fs from 'node:fs/promises' + +// Generates ABI parameter name lookup from common names + +console.log('Generating ABI parameter name lookup.') + +let content = + 'export interface AbiParameterTupleNameLookup extends Record {\n' +for (const name of names()) content += ` ${name}: [${name}: type]\n` +content += '}' + +const path = './packages/abitype/src/abi.ts' +const text = await fs + .readFile(path, 'utf8') + .then((text) => + text.replace( + /export interface AbiParameterTupleNameLookup[\s\S]*$/, + content, + ), + ) +await fs.writeFile(path, text, 'utf8') + +console.log(`Done. Added ${names().size} names.`) + +function names() { + return new Set([ + '_data', + 'a', + 'account', + 'accounts', + 'address', + 'addresses', + 'admin', + 'allowFailure', + 'allowed', + 'amount', + 'approved', + 'approver', + 'assets', + 'authority', + 'available', + 'b', + 'balance', + 'c', + 'callData', + 'caller', + 'calls', + 'coinType', + 'count', + 'currency', + 'd', + 'data', + 'deadline', + 'dns', + 'dst', + 'e', + 'ens', + 'errorData', + 'f', + 'failures', + 'from', + 'funder', + 'g', + 'gateways', + 'guy', + 'h', + 'hash', + 'i', + 'id', + 'ids', + 'idsLength', + 'interfaceId', + 'j', + 'k', + 'key', + 'l', + 'label', + 'm', + 'memo', + 'message', + 'n', + 'name', + 'needed', + 'node', + 'nonce', + 'nonceKey', + 'o', + 'operator', + 'order', + 'orders', + 'owner', + 'p', + 'policyId', + 'policyType', + 'primary', + 'proposer', + 'q', + 'queries', + 'quoteToken', + 'r', + 'receiver', + 'recipient', + 'refund', + 'required', + 'resolvedName', + 'resolver', + 'responses', + 'restricted', + 'returnData', + 'reverseName', + 'reverseResolver', + 's', + 'secs', + 'selector', + 'sender', + 'shares', + 'signature', + 'signer', + 'src', + 'status', + 'success', + 'symbol', + 't', + 'target', + 'timestamp', + 'to', + 'token', + 'tokenId', + 'ttl', + 'u', + 'updater', + 'user', + 'v', + 'value', + 'values', + 'valuesLength', + 'version', + 'w', + 'wad', + 'x', + 'y', + 'z', + ]) +} From e7891deb3d8a6a427df6242458f893488a43b6fa Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Thu, 20 Nov 2025 01:57:31 +0000 Subject: [PATCH 7/8] ci: apply automated fixes --- packages/abitype/src/abi.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/abitype/src/abi.ts b/packages/abitype/src/abi.ts index a22dc584..e065ad68 100644 --- a/packages/abitype/src/abi.ts +++ b/packages/abitype/src/abi.ts @@ -367,4 +367,3 @@ export interface AbiParameterTupleNameLookup extends Record Date: Thu, 20 Nov 2025 18:43:28 -0500 Subject: [PATCH 8/8] chore: perf tweaks --- .github/workflows/verify.yml | 2 +- packages/abitype/src/abi.ts | 31 +++++++ packages/abitype/src/utils.bench-d.ts | 8 +- packages/abitype/src/utils.test-d.ts | 107 +++++++++++++++++++++--- packages/abitype/src/utils.ts | 88 ++++++++++++++++--- playgrounds/functions/src/types.ts | 6 +- playgrounds/functions/src/watchEvent.ts | 6 +- scripts/genAbiParameterNameLookup.ts | 32 ++++++- 8 files changed, 248 insertions(+), 32 deletions(-) diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 07d782f3..812dc269 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -50,7 +50,7 @@ jobs: timeout-minutes: 5 strategy: matrix: - version: ['5.0.4', '5.1.6', '5.2.2', '5.3.3', '5.4.5', '5.5.4', '5.6.3', '5.7.3', '5.8.3', '5.9.3', 'latest'] + version: ['5.0.4', '5.2.2', '5.3.3', '5.4.5', '5.5.4', '5.6.3', '5.7.3', '5.8.3', '5.9.3', 'latest'] steps: - name: Clone repository diff --git a/packages/abitype/src/abi.ts b/packages/abitype/src/abi.ts index e065ad68..f526bca4 100644 --- a/packages/abitype/src/abi.ts +++ b/packages/abitype/src/abi.ts @@ -248,6 +248,7 @@ export type TypedData = Pretty< //////////////////////////////////////////////////////////////////////////////////////////////////// +// update lookup with `pnpm node scripts/genAbiParameterNameLookup.ts` // biome-ignore format: no formatting export interface AbiParameterTupleNameLookup extends Record { _data: [_data: type] @@ -262,24 +263,34 @@ export interface AbiParameterTupleNameLookup extends Record extends Record extends Record extends Record extends Record['inputs'] test('basic without named tuple', () => { const res = {} as AbiParametersToPrimitiveTypes - attest.instantiations([917, 'instantiations']) + attest.instantiations([906, 'instantiations']) attest< readonly [sender: `0x${string}`, recipient: `0x${string}`, amount: bigint] >(res) }) test('basic with named tuple', () => { const res = {} as AbiParametersToPrimitiveTypes - attest.instantiations([1172, 'instantiations']) + attest.instantiations([1131, 'instantiations']) attest< readonly [sender: `0x${string}`, recipient: `0x${string}`, amount: bigint] >(res) @@ -311,9 +311,9 @@ type parameters = readonly [ ] test('without named tuples', () => { ;({}) as AbiParametersToPrimitiveTypes - attest.instantiations([1286, 'instantiations']) + attest.instantiations([1276, 'instantiations']) }) test('with named tuples', () => { ;({}) as AbiParametersToPrimitiveTypes - attest.instantiations([3800, 'instantiations']) + attest.instantiations([1998, 'instantiations']) }) diff --git a/packages/abitype/src/utils.test-d.ts b/packages/abitype/src/utils.test-d.ts index 8e414e1d..465a95f4 100644 --- a/packages/abitype/src/utils.test-d.ts +++ b/packages/abitype/src/utils.test-d.ts @@ -1,6 +1,6 @@ import { assertType, describe, expectTypeOf, test } from 'vitest' -import type { Abi } from './abi.js' +import type { Abi, AbiParameterKind } from './abi.js' import type { customSolidityErrorsAbi, ensRegistryWithFallbackAbi, @@ -424,12 +424,14 @@ describe('AbiParameterToPrimitiveType', () => { describe('AbiParametersToPrimitiveTypes', () => { test('no parameters', () => { - type Result = AbiParametersToPrimitiveTypes<[]> - assertType([]) + type r1 = AbiParametersToPrimitiveTypes<[]> + assertType([]) + type r2 = AbiParametersToPrimitiveTypes<[], AbiParameterKind, true> + assertType([]) }) test('single parameter', () => { - type Result = AbiParametersToPrimitiveTypes< + type r1 = AbiParametersToPrimitiveTypes< [ { name: 'tokenId' @@ -437,23 +439,48 @@ describe('AbiParametersToPrimitiveTypes', () => { }, ] > - assertType([[1, 1]]) + assertType([[1, 1]]) // ^? + type r2 = AbiParametersToPrimitiveTypes< + [ + { + name: 'tokenId' + type: 'uint8[2]' + }, + ], + AbiParameterKind, + true + > + expectTypeOf().toEqualTypeOf< + readonly [tokenId: readonly [number, number]] + >() }) test('multiple parameters', () => { - type Result = AbiParametersToPrimitiveTypes< + type r1 = AbiParametersToPrimitiveTypes< [ { name: 'to'; type: 'address' }, { name: 'tokenId'; type: 'uint256' }, { name: 'trait'; type: 'string[]' }, ] > - assertType([zeroAddress, 1n, ['foo']]) + assertType([zeroAddress, 1n, ['foo']]) + type r2 = AbiParametersToPrimitiveTypes< + [ + { name: 'to'; type: 'address' }, + { name: 'tokenId'; type: 'uint256' }, + { name: 'trait'; type: 'string[]' }, + ], + AbiParameterKind, + true + > + expectTypeOf().toEqualTypeOf< + readonly [to: `0x${string}`, tokenId: bigint, readonly string[]] + >() }) test('deeply nested parameters', () => { - type Result = AbiParametersToPrimitiveTypes< + type r1 = AbiParametersToPrimitiveTypes< [ { name: 's' @@ -490,7 +517,55 @@ describe('AbiParametersToPrimitiveTypes', () => { }, ] > - assertType([ + assertType([ + { a: 1, b: [2], c: [{ x: 1, y: 1 }] }, + { x: 1, y: 1 }, + 1, + [ + { x: 1n, y: 1n }, + { x: 1n, y: 1n }, + ], + ]) + type r2 = AbiParametersToPrimitiveTypes< + [ + { + name: 's' + type: 'tuple' + components: [ + { name: 'a'; type: 'uint8' }, + { name: 'b'; type: 'uint8[]' }, + { + name: 'c' + type: 'tuple[]' + components: [ + { name: 'x'; type: 'uint8' }, + { name: 'y'; type: 'uint8' }, + ] + }, + ] + }, + { + name: 't' + type: 'tuple' + components: [ + { name: 'x'; type: 'uint8' }, + { name: 'y'; type: 'uint8' }, + ] + }, + { name: 'a'; type: 'uint8' }, + { + name: 't' + type: 'tuple[2]' + components: [ + { name: 'x'; type: 'uint256' }, + { name: 'y'; type: 'uint256' }, + ] + }, + ], + AbiParameterKind, + true + > + assertType([ { a: 1, b: [2], c: [{ x: 1, y: 1 }] }, { x: 1, y: 1 }, 1, @@ -514,14 +589,20 @@ describe('AbiParametersToPrimitiveTypes', () => { assertType>([ '0xfoo', ]) - assertType>([ - '0xfoo', - ]) + assertType< + AbiParametersToPrimitiveTypes + >(['0xfoo']) + assertType< + AbiParametersToPrimitiveTypes + >(['0xfoo']) }) test('named parameters', () => { type Result = AbiParametersToPrimitiveTypes< - ExtractAbiFunction['inputs'] + // ^? + ExtractAbiFunction['inputs'], + 'inputs', + true > expectTypeOf().toEqualTypeOf< readonly [sender: `0x${string}`, recipient: `0x${string}`, amount: bigint] diff --git a/packages/abitype/src/utils.ts b/packages/abitype/src/utils.ts index 8a48791e..bc3e8087 100644 --- a/packages/abitype/src/utils.ts +++ b/packages/abitype/src/utils.ts @@ -216,26 +216,94 @@ export type AbiParametersToPrimitiveTypes_named< // Ideally this is a simple mapped type instead of tail recurision, but TypeScript does not support dynamic tuple labels // https://github.com/microsoft/TypeScript/issues/44939 > = abiParameters extends readonly [ - infer head extends AbiParameter, + // Significantly reduce type instantiations by batch proccessing up to six parameters at a time instead of processing one parameter per recursion + infer head1 extends AbiParameter, + infer head2 extends AbiParameter, + infer head3 extends AbiParameter, + infer head4 extends AbiParameter, + infer head5 extends AbiParameter, + infer head6 extends AbiParameter, ...infer tail extends readonly AbiParameter[], ] ? AbiParametersToPrimitiveTypes_named< tail, abiParameterKind, - readonly [...acc, ...ToNamedTuple] + readonly [ + ...acc, + ...ToNamedTuple, + ...ToNamedTuple, + ...ToNamedTuple, + ...ToNamedTuple, + ...ToNamedTuple, + ...ToNamedTuple, + ] > - : acc extends readonly [] - ? abiParameters extends readonly [] - ? readonly [] - : readonly unknown[] - : acc + : abiParameters extends readonly [ + infer head1 extends AbiParameter, + infer head2 extends AbiParameter, + infer head3 extends AbiParameter, + infer head4 extends AbiParameter, + infer head5 extends AbiParameter, + ] + ? readonly [ + ...acc, + ...ToNamedTuple, + ...ToNamedTuple, + ...ToNamedTuple, + ...ToNamedTuple, + ...ToNamedTuple, + ] + : abiParameters extends readonly [ + infer head1 extends AbiParameter, + infer head2 extends AbiParameter, + infer head3 extends AbiParameter, + infer head4 extends AbiParameter, + ] + ? readonly [ + ...acc, + ...ToNamedTuple, + ...ToNamedTuple, + ...ToNamedTuple, + ...ToNamedTuple, + ] + : abiParameters extends readonly [ + infer head1 extends AbiParameter, + infer head2 extends AbiParameter, + infer head3 extends AbiParameter, + ] + ? readonly [ + ...acc, + ...ToNamedTuple, + ...ToNamedTuple, + ...ToNamedTuple, + ] + : abiParameters extends readonly [ + infer head1 extends AbiParameter, + infer head2 extends AbiParameter, + ] + ? readonly [ + ...acc, + ...ToNamedTuple, + ...ToNamedTuple, + ] + : abiParameters extends readonly [infer head extends AbiParameter] + ? readonly [...acc, ...ToNamedTuple] + : acc extends readonly [] + ? abiParameters extends readonly [] + ? readonly [] + : readonly unknown[] + : acc type ToNamedTuple< abiParameter extends AbiParameter, abiParameterKind extends AbiParameterKind, - /// - type = AbiParameterToPrimitiveType, -> = AbiParameterTupleNameLookup[(abiParameter & { name: string })['name']] +> = unwrapName< + AbiParameterToPrimitiveType, + abiParameter['name'] +> +type unwrapName = name extends string + ? AbiParameterTupleNameLookup[name] + : [type] /** * Checks if type is {@link Abi}. diff --git a/playgrounds/functions/src/types.ts b/playgrounds/functions/src/types.ts index 18024f5b..71ed6fdb 100644 --- a/playgrounds/functions/src/types.ts +++ b/playgrounds/functions/src/types.ts @@ -36,7 +36,8 @@ type GetArgs< : AbiFunction, primitiveTypes = AbiParametersToPrimitiveTypes< abiFunction['inputs'], - 'inputs' + 'inputs', + true >, args_ = | primitiveTypes // show all values @@ -91,7 +92,8 @@ export type ContractReturnType< outputs extends readonly AbiParameter[] = abiFunction['outputs'], primitiveTypes extends readonly unknown[] = AbiParametersToPrimitiveTypes< outputs, - 'outputs' + 'outputs', + true >, > = [abiFunction] extends [never] ? unknown // `abiFunction` was not inferrable (e.g. `abi` declared as `Abi`) diff --git a/playgrounds/functions/src/watchEvent.ts b/playgrounds/functions/src/watchEvent.ts index 4c85ae76..4c1ca203 100644 --- a/playgrounds/functions/src/watchEvent.ts +++ b/playgrounds/functions/src/watchEvent.ts @@ -21,7 +21,11 @@ export type WatchEventParameters< abiEvent extends AbiEvent = abi extends Abi ? ExtractAbiEvent : AbiEvent, - primitiveTypes = AbiParametersToPrimitiveTypes, + primitiveTypes = AbiParametersToPrimitiveTypes< + abiEvent['inputs'], + 'inputs', + true + >, > = { abi: abi eventName: diff --git a/scripts/genAbiParameterNameLookup.ts b/scripts/genAbiParameterNameLookup.ts index 7cc1fca4..4c938628 100644 --- a/scripts/genAbiParameterNameLookup.ts +++ b/scripts/genAbiParameterNameLookup.ts @@ -7,7 +7,7 @@ console.log('Generating ABI parameter name lookup.') let content = 'export interface AbiParameterTupleNameLookup extends Record {\n' for (const name of names()) content += ` ${name}: [${name}: type]\n` -content += '}' +content += '}\n' const path = './packages/abitype/src/abi.ts' const text = await fs @@ -36,24 +36,34 @@ function names() { 'amount', 'approved', 'approver', + 'ask', + 'asset', 'assets', 'authority', 'available', 'b', 'balance', + 'bid', + 'buffer', 'c', + 'call', 'callData', 'caller', 'calls', + 'clone', 'coinType', 'count', 'currency', 'd', 'data', 'deadline', + 'decimals', + 'dest', + 'divisor', 'dns', 'dst', 'e', + 'endTime', 'ens', 'errorData', 'f', @@ -61,30 +71,43 @@ function names() { 'from', 'funder', 'g', + 'gateway', 'gateways', 'guy', 'h', 'hash', + 'hashes', 'i', 'id', 'ids', 'idsLength', + 'implementation', + 'index', 'interfaceId', 'j', 'k', 'key', 'l', 'label', + 'length', + 'limit', 'm', + 'market', 'memo', 'message', 'n', 'name', 'needed', + 'new', + 'next', + 'nextOwner', 'node', 'nonce', 'nonceKey', + 'numerator', 'o', + 'offerer', + 'old', 'operator', 'order', 'orders', @@ -92,6 +115,9 @@ function names() { 'p', 'policyId', 'policyType', + 'previous', + 'previousOwner', + 'price', 'primary', 'proposer', 'q', @@ -116,7 +142,9 @@ function names() { 'shares', 'signature', 'signer', + 'source', 'src', + 'startTime', 'status', 'success', 'symbol', @@ -137,8 +165,10 @@ function names() { 'version', 'w', 'wad', + 'weth', 'x', 'y', 'z', + 'zone', ]) }