ox
Version:
Ethereum Standard Library
211 lines (197 loc) • 4.83 kB
text/typescript
import { expect, test } from 'vp/test'
import { parseStructs } from './structs.js'
test('no structs', () => {
expect(parseStructs([])).toMatchInlineSnapshot('{}')
expect(parseStructs([''])).toMatchInlineSnapshot('{}')
expect(parseStructs(['function foo()', 'event Foo()'])).toMatchInlineSnapshot(
'{}',
)
expect(
parseStructs(['function addPerson(Person person)']),
).toMatchInlineSnapshot('{}')
})
test('parses basic structs', () => {
expect(
parseStructs([
'struct Foo { string bar; address baz; }',
'struct FulfillmentComponent { uint256 orderIndex; uint256 itemIndex; }',
]),
).toMatchInlineSnapshot(`
{
"Foo": [
{
"name": "bar",
"type": "string",
},
{
"name": "baz",
"type": "address",
},
],
"FulfillmentComponent": [
{
"name": "orderIndex",
"type": "uint256",
},
{
"name": "itemIndex",
"type": "uint256",
},
],
}
`)
})
test('parses valid names', () => {
expect(
parseStructs([
'struct $ { string; }',
'struct $_a9 { string; }',
'struct _ { string; }',
'struct abc$_9 { string; }',
]),
).toMatchInlineSnapshot(`
{
"$": [
{
"type": "string",
},
],
"$_a9": [
{
"type": "string",
},
],
"_": [
{
"type": "string",
},
],
"abc$_9": [
{
"type": "string",
},
],
}
`)
})
test('parses and resolves nested structs', () => {
expect(
parseStructs([
'struct Fulfillment { FulfillmentComponent[] offerComponents; FulfillmentComponent[] considerationComponents; }',
'struct FulfillmentComponent { uint256 orderIndex; uint256 itemIndex; }',
'struct Foo { Fulfillment fulfillment; }',
]),
).toMatchInlineSnapshot(`
{
"Foo": [
{
"components": [
{
"components": [
{
"name": "orderIndex",
"type": "uint256",
},
{
"name": "itemIndex",
"type": "uint256",
},
],
"name": "offerComponents",
"type": "tuple[]",
},
{
"components": [
{
"name": "orderIndex",
"type": "uint256",
},
{
"name": "itemIndex",
"type": "uint256",
},
],
"name": "considerationComponents",
"type": "tuple[]",
},
],
"name": "fulfillment",
"type": "tuple",
},
],
"Fulfillment": [
{
"components": [
{
"name": "orderIndex",
"type": "uint256",
},
{
"name": "itemIndex",
"type": "uint256",
},
],
"name": "offerComponents",
"type": "tuple[]",
},
{
"components": [
{
"name": "orderIndex",
"type": "uint256",
},
{
"name": "itemIndex",
"type": "uint256",
},
],
"name": "considerationComponents",
"type": "tuple[]",
},
],
"FulfillmentComponent": [
{
"name": "orderIndex",
"type": "uint256",
},
{
"name": "itemIndex",
"type": "uint256",
},
],
}
`)
})
test('no properties', () => {
expect(() =>
parseStructs(['struct Foo {}']),
).toThrowErrorMatchingInlineSnapshot(
`
[Abi.InvalidStructSignatureError: Invalid struct signature.
No properties exist.
Details: struct Foo {}]
`,
)
})
test('struct does not exist when resolving', () => {
expect(() => parseStructs(['struct Foo { Bar bar; }']))
.toThrowErrorMatchingInlineSnapshot(`
[HumanReadableAbi.UnknownTypeError: Unknown type.
Type "Bar" is not a valid ABI type. Perhaps you forgot to include a struct signature?]
`)
})
test('throws if recursive structs are detected', () => {
expect(() =>
parseStructs(['struct Foo { Bar bar; }', 'struct Bar { Foo foo; }']),
).toThrowErrorMatchingInlineSnapshot(
`
[Abi.CircularReferenceError: Circular reference detected.
Struct "Bar" is a circular reference.]
`,
)
})
test.todo('throws if property is missing semicolon', () => {
expect(() =>
parseStructs(['struct Foo { string bar; address baz }']),
).toThrowErrorMatchingInlineSnapshot()
})