Skip to content

Commit e56c1fa

Browse files
committed
chore: perf tweaks
1 parent 0e9db23 commit e56c1fa

8 files changed

Lines changed: 188 additions & 32 deletions

File tree

.github/workflows/verify.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
timeout-minutes: 5
5151
strategy:
5252
matrix:
53-
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']
53+
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']
5454

5555
steps:
5656
- name: Clone repository

packages/abitype/src/abi.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ export type TypedData = Pretty<
248248

249249
////////////////////////////////////////////////////////////////////////////////////////////////////
250250

251+
// update lookup with `pnpm node scripts/genAbiParameterNameLookup.ts`
251252
// biome-ignore format: no formatting
252253
export interface AbiParameterTupleNameLookup<type> extends Record<string, [type]> {
253254
_data: [_data: type]

packages/abitype/src/utils.bench-d.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,14 +274,14 @@ type transferFrom = ExtractAbiFunction<
274274
>['inputs']
275275
test('basic without named tuple', () => {
276276
const res = {} as AbiParametersToPrimitiveTypes<transferFrom, 'inputs', false>
277-
attest.instantiations([917, 'instantiations'])
277+
attest.instantiations([906, 'instantiations'])
278278
attest<
279279
readonly [sender: `0x${string}`, recipient: `0x${string}`, amount: bigint]
280280
>(res)
281281
})
282282
test('basic with named tuple', () => {
283283
const res = {} as AbiParametersToPrimitiveTypes<transferFrom, 'inputs', true>
284-
attest.instantiations([1172, 'instantiations'])
284+
attest.instantiations([1131, 'instantiations'])
285285
attest<
286286
readonly [sender: `0x${string}`, recipient: `0x${string}`, amount: bigint]
287287
>(res)
@@ -311,9 +311,9 @@ type parameters = readonly [
311311
]
312312
test('without named tuples', () => {
313313
;({}) as AbiParametersToPrimitiveTypes<parameters, 'inputs', false>
314-
attest.instantiations([1286, 'instantiations'])
314+
attest.instantiations([1276, 'instantiations'])
315315
})
316316
test('with named tuples', () => {
317317
;({}) as AbiParametersToPrimitiveTypes<parameters, 'inputs', true>
318-
attest.instantiations([3800, 'instantiations'])
318+
attest.instantiations([1998, 'instantiations'])
319319
})

packages/abitype/src/utils.test-d.ts

Lines changed: 94 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { assertType, describe, expectTypeOf, test } from 'vitest'
22

3-
import type { Abi } from './abi.js'
3+
import type { Abi, AbiParameterKind } from './abi.js'
44
import type {
55
customSolidityErrorsAbi,
66
ensRegistryWithFallbackAbi,
@@ -424,36 +424,63 @@ describe('AbiParameterToPrimitiveType', () => {
424424

425425
describe('AbiParametersToPrimitiveTypes', () => {
426426
test('no parameters', () => {
427-
type Result = AbiParametersToPrimitiveTypes<[]>
428-
assertType<Result>([])
427+
type r1 = AbiParametersToPrimitiveTypes<[]>
428+
assertType<r1>([])
429+
type r2 = AbiParametersToPrimitiveTypes<[], AbiParameterKind, true>
430+
assertType<r2>([])
429431
})
430432

431433
test('single parameter', () => {
432-
type Result = AbiParametersToPrimitiveTypes<
434+
type r1 = AbiParametersToPrimitiveTypes<
433435
[
434436
{
435437
name: 'tokenId'
436438
type: 'uint8[2]'
437439
},
438440
]
439441
>
440-
assertType<Result>([[1, 1]])
442+
assertType<r1>([[1, 1]])
441443
// ^?
444+
type r2 = AbiParametersToPrimitiveTypes<
445+
[
446+
{
447+
name: 'tokenId'
448+
type: 'uint8[2]'
449+
},
450+
],
451+
AbiParameterKind,
452+
true
453+
>
454+
expectTypeOf<r2>().toEqualTypeOf<
455+
readonly [tokenId: readonly [number, number]]
456+
>()
442457
})
443458

444459
test('multiple parameters', () => {
445-
type Result = AbiParametersToPrimitiveTypes<
460+
type r1 = AbiParametersToPrimitiveTypes<
446461
[
447462
{ name: 'to'; type: 'address' },
448463
{ name: 'tokenId'; type: 'uint256' },
449464
{ name: 'trait'; type: 'string[]' },
450465
]
451466
>
452-
assertType<Result>([zeroAddress, 1n, ['foo']])
467+
assertType<r1>([zeroAddress, 1n, ['foo']])
468+
type r2 = AbiParametersToPrimitiveTypes<
469+
[
470+
{ name: 'to'; type: 'address' },
471+
{ name: 'tokenId'; type: 'uint256' },
472+
{ name: 'trait'; type: 'string[]' },
473+
],
474+
AbiParameterKind,
475+
true
476+
>
477+
expectTypeOf<r2>().toEqualTypeOf<
478+
readonly [to: `0x${string}`, tokenId: bigint, readonly string[]]
479+
>()
453480
})
454481

455482
test('deeply nested parameters', () => {
456-
type Result = AbiParametersToPrimitiveTypes<
483+
type r1 = AbiParametersToPrimitiveTypes<
457484
[
458485
{
459486
name: 's'
@@ -490,7 +517,55 @@ describe('AbiParametersToPrimitiveTypes', () => {
490517
},
491518
]
492519
>
493-
assertType<Result>([
520+
assertType<r1>([
521+
{ a: 1, b: [2], c: [{ x: 1, y: 1 }] },
522+
{ x: 1, y: 1 },
523+
1,
524+
[
525+
{ x: 1n, y: 1n },
526+
{ x: 1n, y: 1n },
527+
],
528+
])
529+
type r2 = AbiParametersToPrimitiveTypes<
530+
[
531+
{
532+
name: 's'
533+
type: 'tuple'
534+
components: [
535+
{ name: 'a'; type: 'uint8' },
536+
{ name: 'b'; type: 'uint8[]' },
537+
{
538+
name: 'c'
539+
type: 'tuple[]'
540+
components: [
541+
{ name: 'x'; type: 'uint8' },
542+
{ name: 'y'; type: 'uint8' },
543+
]
544+
},
545+
]
546+
},
547+
{
548+
name: 't'
549+
type: 'tuple'
550+
components: [
551+
{ name: 'x'; type: 'uint8' },
552+
{ name: 'y'; type: 'uint8' },
553+
]
554+
},
555+
{ name: 'a'; type: 'uint8' },
556+
{
557+
name: 't'
558+
type: 'tuple[2]'
559+
components: [
560+
{ name: 'x'; type: 'uint256' },
561+
{ name: 'y'; type: 'uint256' },
562+
]
563+
},
564+
],
565+
AbiParameterKind,
566+
true
567+
>
568+
assertType<r2>([
494569
{ a: 1, b: [2], c: [{ x: 1, y: 1 }] },
495570
{ x: 1, y: 1 },
496571
1,
@@ -514,14 +589,20 @@ describe('AbiParametersToPrimitiveTypes', () => {
514589
assertType<AbiParametersToPrimitiveTypes<typeof parameters, 'outputs'>>([
515590
'0xfoo',
516591
])
517-
assertType<AbiParametersToPrimitiveTypes<typeof parameters, 'outputs'>>([
518-
'0xfoo',
519-
])
592+
assertType<
593+
AbiParametersToPrimitiveTypes<typeof parameters, 'inputs', true>
594+
>(['0xfoo'])
595+
assertType<
596+
AbiParametersToPrimitiveTypes<typeof parameters, 'outputs', true>
597+
>(['0xfoo'])
520598
})
521599

522600
test('named parameters', () => {
523601
type Result = AbiParametersToPrimitiveTypes<
524-
ExtractAbiFunction<typeof erc20Abi, 'transferFrom'>['inputs']
602+
// ^?
603+
ExtractAbiFunction<typeof erc20Abi, 'transferFrom'>['inputs'],
604+
'inputs',
605+
true
525606
>
526607
expectTypeOf<Result>().toEqualTypeOf<
527608
readonly [sender: `0x${string}`, recipient: `0x${string}`, amount: bigint]

packages/abitype/src/utils.ts

Lines changed: 78 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -216,26 +216,94 @@ export type AbiParametersToPrimitiveTypes_named<
216216
// Ideally this is a simple mapped type instead of tail recurision, but TypeScript does not support dynamic tuple labels
217217
// https://github.com/microsoft/TypeScript/issues/44939
218218
> = abiParameters extends readonly [
219-
infer head extends AbiParameter,
219+
// Significantly reduce type instantiations by batch proccessing up to six parameters at a time instead of processing one parameter per recursion
220+
infer head1 extends AbiParameter,
221+
infer head2 extends AbiParameter,
222+
infer head3 extends AbiParameter,
223+
infer head4 extends AbiParameter,
224+
infer head5 extends AbiParameter,
225+
infer head6 extends AbiParameter,
220226
...infer tail extends readonly AbiParameter[],
221227
]
222228
? AbiParametersToPrimitiveTypes_named<
223229
tail,
224230
abiParameterKind,
225-
readonly [...acc, ...ToNamedTuple<head, abiParameterKind>]
231+
readonly [
232+
...acc,
233+
...ToNamedTuple<head1, abiParameterKind>,
234+
...ToNamedTuple<head2, abiParameterKind>,
235+
...ToNamedTuple<head3, abiParameterKind>,
236+
...ToNamedTuple<head4, abiParameterKind>,
237+
...ToNamedTuple<head5, abiParameterKind>,
238+
...ToNamedTuple<head6, abiParameterKind>,
239+
]
226240
>
227-
: acc extends readonly []
228-
? abiParameters extends readonly []
229-
? readonly []
230-
: readonly unknown[]
231-
: acc
241+
: abiParameters extends readonly [
242+
infer head1 extends AbiParameter,
243+
infer head2 extends AbiParameter,
244+
infer head3 extends AbiParameter,
245+
infer head4 extends AbiParameter,
246+
infer head5 extends AbiParameter,
247+
]
248+
? readonly [
249+
...acc,
250+
...ToNamedTuple<head1, abiParameterKind>,
251+
...ToNamedTuple<head2, abiParameterKind>,
252+
...ToNamedTuple<head3, abiParameterKind>,
253+
...ToNamedTuple<head4, abiParameterKind>,
254+
...ToNamedTuple<head5, abiParameterKind>,
255+
]
256+
: abiParameters extends readonly [
257+
infer head1 extends AbiParameter,
258+
infer head2 extends AbiParameter,
259+
infer head3 extends AbiParameter,
260+
infer head4 extends AbiParameter,
261+
]
262+
? readonly [
263+
...acc,
264+
...ToNamedTuple<head1, abiParameterKind>,
265+
...ToNamedTuple<head2, abiParameterKind>,
266+
...ToNamedTuple<head3, abiParameterKind>,
267+
...ToNamedTuple<head4, abiParameterKind>,
268+
]
269+
: abiParameters extends readonly [
270+
infer head1 extends AbiParameter,
271+
infer head2 extends AbiParameter,
272+
infer head3 extends AbiParameter,
273+
]
274+
? readonly [
275+
...acc,
276+
...ToNamedTuple<head1, abiParameterKind>,
277+
...ToNamedTuple<head2, abiParameterKind>,
278+
...ToNamedTuple<head3, abiParameterKind>,
279+
]
280+
: abiParameters extends readonly [
281+
infer head1 extends AbiParameter,
282+
infer head2 extends AbiParameter,
283+
]
284+
? readonly [
285+
...acc,
286+
...ToNamedTuple<head1, abiParameterKind>,
287+
...ToNamedTuple<head2, abiParameterKind>,
288+
]
289+
: abiParameters extends readonly [infer head extends AbiParameter]
290+
? readonly [...acc, ...ToNamedTuple<head, abiParameterKind>]
291+
: acc extends readonly []
292+
? abiParameters extends readonly []
293+
? readonly []
294+
: readonly unknown[]
295+
: acc
232296

233297
type ToNamedTuple<
234298
abiParameter extends AbiParameter,
235299
abiParameterKind extends AbiParameterKind,
236-
///
237-
type = AbiParameterToPrimitiveType<abiParameter, abiParameterKind>,
238-
> = AbiParameterTupleNameLookup<type>[(abiParameter & { name: string })['name']]
300+
> = unwrapName<
301+
AbiParameterToPrimitiveType<abiParameter, abiParameterKind>,
302+
abiParameter['name']
303+
>
304+
type unwrapName<type, name> = name extends string
305+
? AbiParameterTupleNameLookup<type>[name]
306+
: [type]
239307

240308
/**
241309
* Checks if type is {@link Abi}.

playgrounds/functions/src/types.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ type GetArgs<
3636
: AbiFunction,
3737
primitiveTypes = AbiParametersToPrimitiveTypes<
3838
abiFunction['inputs'],
39-
'inputs'
39+
'inputs',
40+
true
4041
>,
4142
args_ =
4243
| primitiveTypes // show all values
@@ -91,7 +92,8 @@ export type ContractReturnType<
9192
outputs extends readonly AbiParameter[] = abiFunction['outputs'],
9293
primitiveTypes extends readonly unknown[] = AbiParametersToPrimitiveTypes<
9394
outputs,
94-
'outputs'
95+
'outputs',
96+
true
9597
>,
9698
> = [abiFunction] extends [never]
9799
? unknown // `abiFunction` was not inferrable (e.g. `abi` declared as `Abi`)

playgrounds/functions/src/watchEvent.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ export type WatchEventParameters<
2121
abiEvent extends AbiEvent = abi extends Abi
2222
? ExtractAbiEvent<abi, eventName>
2323
: AbiEvent,
24-
primitiveTypes = AbiParametersToPrimitiveTypes<abiEvent['inputs'], 'inputs'>,
24+
primitiveTypes = AbiParametersToPrimitiveTypes<
25+
abiEvent['inputs'],
26+
'inputs',
27+
true
28+
>,
2529
> = {
2630
abi: abi
2731
eventName:

scripts/genAbiParameterNameLookup.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ console.log('Generating ABI parameter name lookup.')
77
let content =
88
'export interface AbiParameterTupleNameLookup<type> extends Record<string, [type]> {\n'
99
for (const name of names()) content += ` ${name}: [${name}: type]\n`
10-
content += '}'
10+
content += '}\n'
1111

1212
const path = './packages/abitype/src/abi.ts'
1313
const text = await fs

0 commit comments

Comments
 (0)