Skip to content

Commit 20cb1fd

Browse files
committed
fix: #247
1 parent 473abee commit 20cb1fd

File tree

5 files changed

+71
-3
lines changed

5 files changed

+71
-3
lines changed

.changeset/flat-doors-shout.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"abitype": patch
3+
---
4+
5+
Fixed `parseAbi` caching for structs.

.github/workflows/changesets.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,4 @@ jobs:
7272
run: pnpm version:update && cd packages/abitype && cp ../../LICENSE LICENSE
7373

7474
- name: Publish to JSR
75-
run: pnpx jsr publish --allow-slow-types --allow-dirty
75+
run: cd packages/abitype && pnpx jsr publish --allow-slow-types --allow-dirty

packages/abitype/src/human-readable/parseAbi.test.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,50 @@ test('parseAbi', () => {
3030
]
3131
`)
3232
})
33+
34+
test('busts cache', () => {
35+
const result1 = parseAbi([
36+
'function balanceOf(Baz baz)',
37+
'struct Baz {uint amount; string role;}',
38+
])
39+
expect(result1[0].inputs).toMatchInlineSnapshot(`
40+
[
41+
{
42+
"components": [
43+
{
44+
"name": "amount",
45+
"type": "uint256",
46+
},
47+
{
48+
"name": "role",
49+
"type": "string",
50+
},
51+
],
52+
"name": "baz",
53+
"type": "tuple",
54+
},
55+
]
56+
`)
57+
const result2 = parseAbi([
58+
'function balanceOf(Baz baz)',
59+
'struct Baz {uint price; string role;}',
60+
])
61+
expect(result2[0].inputs).toMatchInlineSnapshot(`
62+
[
63+
{
64+
"components": [
65+
{
66+
"name": "price",
67+
"type": "uint256",
68+
},
69+
{
70+
"name": "role",
71+
"type": "string",
72+
},
73+
],
74+
"name": "baz",
75+
"type": "tuple",
76+
},
77+
]
78+
`)
79+
})

packages/abitype/src/human-readable/runtime/cache.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { AbiItemType, AbiParameter } from '../../abi.js'
2+
import type { StructLookup } from '../types/structs.js'
23

34
/**
45
* Gets {@link parameterCache} cache key namespaced by {@link type}. This prevents parameters from being accessible to types that don't allow them (e.g. `string indexed foo` not allowed outside of `type: 'event'`).
@@ -9,8 +10,19 @@ import type { AbiItemType, AbiParameter } from '../../abi.js'
910
export function getParameterCacheKey(
1011
param: string,
1112
type?: AbiItemType | 'struct',
13+
structs?: StructLookup,
1214
) {
13-
if (type) return `${type}:${param}`
15+
let structKey = ''
16+
if (structs)
17+
for (const struct of Object.entries(structs)) {
18+
if (!struct) continue
19+
let propertyKey = ''
20+
for (const property of struct[1]) {
21+
propertyKey += `[${property.type}${property.name ? `:${property.name}` : ''}]`
22+
}
23+
structKey += `(${struct[0]}{${propertyKey}})`
24+
}
25+
if (type) return `${type}:${param}${structKey}`
1426
return param
1527
}
1628

packages/abitype/src/human-readable/runtime/utils.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,11 @@ type ParseOptions = {
162162

163163
export function parseAbiParameter(param: string, options?: ParseOptions) {
164164
// optional namespace cache by `type`
165-
const parameterCacheKey = getParameterCacheKey(param, options?.type)
165+
const parameterCacheKey = getParameterCacheKey(
166+
param,
167+
options?.type,
168+
options?.structs,
169+
)
166170
if (parameterCache.has(parameterCacheKey))
167171
return parameterCache.get(parameterCacheKey)!
168172

0 commit comments

Comments
 (0)