Skip to content

Commit

Permalink
fix: #247
Browse files Browse the repository at this point in the history
  • Loading branch information
tmm committed Dec 3, 2024
1 parent 473abee commit 20cb1fd
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/flat-doors-shout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"abitype": patch
---

Fixed `parseAbi` caching for structs.
2 changes: 1 addition & 1 deletion .github/workflows/changesets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,4 @@ jobs:
run: pnpm version:update && cd packages/abitype && cp ../../LICENSE LICENSE

- name: Publish to JSR
run: pnpx jsr publish --allow-slow-types --allow-dirty
run: cd packages/abitype && pnpx jsr publish --allow-slow-types --allow-dirty
47 changes: 47 additions & 0 deletions packages/abitype/src/human-readable/parseAbi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,50 @@ test('parseAbi', () => {
]
`)
})

test('busts cache', () => {
const result1 = parseAbi([
'function balanceOf(Baz baz)',
'struct Baz {uint amount; string role;}',
])
expect(result1[0].inputs).toMatchInlineSnapshot(`
[
{
"components": [
{
"name": "amount",
"type": "uint256",
},
{
"name": "role",
"type": "string",
},
],
"name": "baz",
"type": "tuple",
},
]
`)
const result2 = parseAbi([
'function balanceOf(Baz baz)',
'struct Baz {uint price; string role;}',
])
expect(result2[0].inputs).toMatchInlineSnapshot(`
[
{
"components": [
{
"name": "price",
"type": "uint256",
},
{
"name": "role",
"type": "string",
},
],
"name": "baz",
"type": "tuple",
},
]
`)
})
14 changes: 13 additions & 1 deletion packages/abitype/src/human-readable/runtime/cache.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { AbiItemType, AbiParameter } from '../../abi.js'
import type { StructLookup } from '../types/structs.js'

/**
* 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'`).
Expand All @@ -9,8 +10,19 @@ import type { AbiItemType, AbiParameter } from '../../abi.js'
export function getParameterCacheKey(
param: string,
type?: AbiItemType | 'struct',
structs?: StructLookup,
) {
if (type) return `${type}:${param}`
let structKey = ''
if (structs)
for (const struct of Object.entries(structs)) {
if (!struct) continue
let propertyKey = ''
for (const property of struct[1]) {
propertyKey += `[${property.type}${property.name ? `:${property.name}` : ''}]`
}
structKey += `(${struct[0]}{${propertyKey}})`
}
if (type) return `${type}:${param}${structKey}`
return param
}

Expand Down
6 changes: 5 additions & 1 deletion packages/abitype/src/human-readable/runtime/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,11 @@ type ParseOptions = {

export function parseAbiParameter(param: string, options?: ParseOptions) {
// optional namespace cache by `type`
const parameterCacheKey = getParameterCacheKey(param, options?.type)
const parameterCacheKey = getParameterCacheKey(
param,
options?.type,
options?.structs,
)
if (parameterCache.has(parameterCacheKey))
return parameterCache.get(parameterCacheKey)!

Expand Down

0 comments on commit 20cb1fd

Please sign in to comment.