import { Abi, AbiEvent, AbiFunction, AbiItem, AbiParameters, Bytes, type Hex, } from 'ox' import { describe, expect, test } from 'vp/test' import { erc20Abi, seaportContractConfig, wagmiContractConfig, } from '../../../test/constants/abis.js' import { getAmbiguousTypes, isArgOfType, normalizeSignature, } from '../internal/abiItem.js' describe('format', () => { test('default', () => { const abiItem = AbiItem.from({ type: 'function', name: 'approve', stateMutability: 'nonpayable', inputs: [ { name: 'spender', type: 'address', }, { name: 'amount', type: 'uint256', }, ], outputs: [{ type: 'bool' }], }) const formatted = AbiItem.format(abiItem) expect(formatted).toMatchInlineSnapshot( `"function approve(address spender, uint256 amount) returns (bool)"`, ) }) }) describe('from', () => { test('default', () => { { const abiItem = AbiItem.from({ type: 'function', name: 'approve', stateMutability: 'nonpayable', inputs: [ { name: 'spender', type: 'address', }, { name: 'amount', type: 'uint256', }, ], outputs: [{ type: 'bool' }], }) expect(abiItem).toMatchInlineSnapshot(` { "hash": "0x095ea7b334ae44009aa867bfb386f5c3b4b443ac6f0ee573fa91c4608fbadfba", "inputs": [ { "name": "spender", "type": "address", }, { "name": "amount", "type": "uint256", }, ], "name": "approve", "outputs": [ { "type": "bool", }, ], "stateMutability": "nonpayable", "type": "function", } `) } { const abiItem = AbiItem.from( 'function approve(address spender, uint256 amount) returns (bool)', ) expect(abiItem).toMatchInlineSnapshot(` { "hash": "0x095ea7b334ae44009aa867bfb386f5c3b4b443ac6f0ee573fa91c4608fbadfba", "inputs": [ { "name": "spender", "type": "address", }, { "name": "amount", "type": "uint256", }, ], "name": "approve", "outputs": [ { "type": "bool", }, ], "stateMutability": "nonpayable", "type": "function", } `) } { const abiItem = AbiItem.from([ 'struct Foo { address owner; address spender; uint256 amount; }', 'function approve(Foo foo) returns (bool)', ]) expect(abiItem).toMatchInlineSnapshot(` { "hash": "0xe0ac316e47844d88260c3fd7bfe62c3348cee1a015524358c41abe32d0d91266", "inputs": [ { "components": [ { "name": "owner", "type": "address", }, { "name": "spender", "type": "address", }, { "name": "amount", "type": "uint256", }, ], "name": "foo", "type": "tuple", }, ], "name": "approve", "outputs": [ { "type": "bool", }, ], "stateMutability": "nonpayable", "type": "function", } `) } }) test('options: prepare', () => { const abiItem = AbiItem.from( { type: 'function', name: 'approve', stateMutability: 'nonpayable', inputs: [ { name: 'spender', type: 'address', }, { name: 'amount', type: 'uint256', }, ], outputs: [{ type: 'bool' }], }, { prepare: false }, ) expect(abiItem).toMatchInlineSnapshot(` { "inputs": [ { "name": "spender", "type": "address", }, { "name": "amount", "type": "uint256", }, ], "name": "approve", "outputs": [ { "type": "bool", }, ], "stateMutability": "nonpayable", "type": "function", } `) }) }) describe('fromAbi', () => { test('default', () => { expect(AbiItem.fromAbi(wagmiContractConfig.abi, 'balanceOf')) .toMatchInlineSnapshot(` { "hash": "0x70a08231b98ef4ca268c9cc3f6b4590e4bfec28280db06bb5d45e689f2a360be", "inputs": [ { "name": "owner", "type": "address", }, ], "name": "balanceOf", "outputs": [ { "name": "", "type": "uint256", }, ], "stateMutability": "view", "type": "function", } `) }) test('behavior: prepare = false', () => { expect( AbiItem.fromAbi(wagmiContractConfig.abi, 'balanceOf', { prepare: false, }), ).toMatchInlineSnapshot(` { "inputs": [ { "name": "owner", "type": "address", }, ], "name": "balanceOf", "outputs": [ { "name": "", "type": "uint256", }, ], "stateMutability": "view", "type": "function", } `) }) describe('behavior: data', () => { test('function', () => { const item = AbiItem.fromAbi(wagmiContractConfig.abi, 'approve') const data = AbiFunction.encodeData(item, [ '0x0000000000000000000000000000000000000000', 1n, ]) expect(AbiItem.fromAbi(wagmiContractConfig.abi, data)) .toMatchInlineSnapshot(` { "hash": "0x095ea7b334ae44009aa867bfb386f5c3b4b443ac6f0ee573fa91c4608fbadfba", "inputs": [ { "name": "to", "type": "address", }, { "name": "tokenId", "type": "uint256", }, ], "name": "approve", "outputs": [], "stateMutability": "nonpayable", "type": "function", } `) }) test('event', () => { const hash = AbiItem.getSignatureHash( AbiItem.fromAbi(seaportContractConfig.abi, 'CounterIncremented'), ) expect(AbiItem.fromAbi(seaportContractConfig.abi, hash)) .toMatchInlineSnapshot(` { "anonymous": false, "hash": "0x721c20121297512b72821b97f5326877ea8ecf4bb9948fea5bfcb6453074d37f", "inputs": [ { "indexed": false, "name": "newCounter", "type": "uint256", }, { "indexed": true, "name": "offerer", "type": "address", }, ], "name": "CounterIncremented", "type": "event", } `) }) test('error', () => { const selector = AbiItem.getSelector( AbiItem.fromAbi(seaportContractConfig.abi, 'BadSignatureV'), ) expect(AbiItem.fromAbi(seaportContractConfig.abi, selector)) .toMatchInlineSnapshot(` { "hash": "0x1f003d0ab3c21a082e88d5c936eb366321476aa1508b9238066e9f135aa38772", "inputs": [ { "name": "v", "type": "uint8", }, ], "name": "BadSignatureV", "type": "error", } `) }) }) test('no matching name', () => { expect(() => AbiItem.fromAbi([] as readonly unknown[], 'balanceOf', { args: ['0x0000000000000000000000000000000000000000'], }), ).toThrowErrorMatchingInlineSnapshot( `[AbiItem.NotFoundError: ABI item with name "balanceOf" not found.]`, ) }) test('no matching data', () => { expect(() => AbiItem.fromAbi([], '0xdeadbeef'), ).toThrowErrorMatchingInlineSnapshot( `[AbiItem.NotFoundError: ABI item with name "0xdeadbeef" not found.]`, ) }) test('behavior: overloads', () => { const abi = Abi.from([ 'function bar()', 'function foo(bytes)', 'function foo(uint256)', ]) const item = AbiItem.fromAbi(abi, 'foo') expect(item).toMatchInlineSnapshot(` { "hash": "0x30c8d1da93067416f4fed4bc024d665b120d7271f9d1000c7632a48d39765324", "inputs": [ { "type": "bytes", }, ], "name": "foo", "outputs": [], "overloads": [ { "inputs": [ { "type": "uint256", }, ], "name": "foo", "outputs": [], "stateMutability": "nonpayable", "type": "function", }, ], "stateMutability": "nonpayable", "type": "function", } `) }) test('behavior: overloads: no inputs', () => { const abi = Abi.from([ 'function bar()', 'function foo()', 'function foo(uint256)', ]) const item = AbiItem.fromAbi(abi, 'foo') expect(item).toMatchInlineSnapshot(` { "hash": "0xc2985578b8f3b75f7dc66a767be2a4ef7d7c2224896a1c86e92ccf30bae678b7", "inputs": [], "name": "foo", "outputs": [], "stateMutability": "nonpayable", "type": "function", } `) }) test('overloads: no args', () => { const abi = Abi.from([ 'function bar()', 'function foo(uint256)', 'function foo()', ]) const item = AbiItem.fromAbi(abi, 'foo') expect(item).toMatchInlineSnapshot(` { "hash": "0xc2985578b8f3b75f7dc66a767be2a4ef7d7c2224896a1c86e92ccf30bae678b7", "inputs": [], "name": "foo", "outputs": [], "stateMutability": "nonpayable", "type": "function", } `) }) test('behavior: overloads: different lengths without abi order define effect', () => { const abi = wagmiContractConfig.abi.filter( (abi) => abi.type === 'function' && abi.name === 'safeTransferFrom', ) const shortArgs = [ '0x0000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000', 420n, ] as const const shortSnapshot = ` { "hash": "0x42842e0eb38857a7775b4e7364b2775df7325074d088e7fb39590cd6281184ed", "inputs": [ { "name": "from", "type": "address", }, { "name": "to", "type": "address", }, { "name": "tokenId", "type": "uint256", }, ], "name": "safeTransferFrom", "outputs": [], "stateMutability": "nonpayable", "type": "function", } ` const longArgs = [ '0x0000000000000000000000000000000000000000', '0x0000000000000000000000000000000000000000', 420n, '0x0000000000000000000000000000000000000000', ] as const const longSnapshot = ` { "hash": "0xb88d4fde60196325a28bb7f99a2582e0b46de55b18761e960c14ad7a32099465", "inputs": [ { "name": "from", "type": "address", }, { "name": "to", "type": "address", }, { "name": "tokenId", "type": "uint256", }, { "name": "_data", "type": "bytes", }, ], "name": "safeTransferFrom", "outputs": [], "stateMutability": "nonpayable", "type": "function", } ` expect( AbiItem.fromAbi(abi, 'safeTransferFrom', { args: shortArgs, }), ).toMatchInlineSnapshot(shortSnapshot) expect( AbiItem.fromAbi(abi.reverse(), 'safeTransferFrom', { args: shortArgs, }), ).toMatchInlineSnapshot(shortSnapshot) expect( AbiItem.fromAbi(abi, 'safeTransferFrom', { args: longArgs, }), ).toMatchInlineSnapshot(longSnapshot) expect( AbiItem.fromAbi(abi.reverse(), 'safeTransferFrom', { args: longArgs, }), ).toMatchInlineSnapshot(longSnapshot) }) test('behavior: overloads: different types', () => { const abi = Abi.from([ 'function mint()', 'function mint(uint256)', 'function mint(string)', ]) const item = AbiItem.fromAbi(abi, 'mint') expect(item).toMatchInlineSnapshot(` { "hash": "0x1249c58b84ff771f36a0d1d2bf0b42e48832b1567c4213f113d3990903cea57d", "inputs": [], "name": "mint", "outputs": [], "stateMutability": "nonpayable", "type": "function", } `) const item_2 = AbiItem.fromAbi(abi, 'mint', { args: [420n], }) expect(item_2).toMatchInlineSnapshot(` { "hash": "0xa0712d680358d64f694230b7cc0b277c73686bdf768385d55cd7c547d0ffd30e", "inputs": [ { "type": "uint256", }, ], "name": "mint", "outputs": [], "stateMutability": "nonpayable", "type": "function", } `) const item_3 = AbiItem.fromAbi(abi, 'mint', { args: ['foo'], }) expect(item_3).toMatchInlineSnapshot(` { "hash": "0xd85d3d2718c3cc9b33ff08eede5eea8b009f9d6e830a4fb9f651e3174175a5a1", "inputs": [ { "type": "string", }, ], "name": "mint", "outputs": [], "stateMutability": "nonpayable", "type": "function", } `) }) test('behavior: overloads: tuple', () => { const abi = Abi.from([ 'function foo(uint256 foo, (string a, string b, uint256 c) bar)', 'function foo(uint256 foo, (string a, (string merp, string meep) b, address c) bar)', ]) const item = AbiItem.fromAbi(abi, 'foo', { args: [ 420n, { a: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e', b: { merp: 'test', meep: 'test' }, c: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e', }, ], }) expect(item).toMatchInlineSnapshot(` { "hash": "0x7994c7de29322475e8941809c4c1405aef16daab07153633b8863148687cb0c5", "inputs": [ { "name": "foo", "type": "uint256", }, { "components": [ { "name": "a", "type": "string", }, { "components": [ { "name": "merp", "type": "string", }, { "name": "meep", "type": "string", }, ], "name": "b", "type": "tuple", }, { "name": "c", "type": "address", }, ], "name": "bar", "type": "tuple", }, ], "name": "foo", "outputs": [], "stateMutability": "nonpayable", "type": "function", } `) }) test('behavior: overloads: ambiguious types', () => { expect(() => AbiItem.fromAbi( Abi.from(['function foo(address)', 'function foo(bytes20)']), 'foo', { args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], }, ), ).toThrowErrorMatchingInlineSnapshot(` [AbiItem.AmbiguityError: Found ambiguous types in overloaded ABI Items. \`bytes20\` in \`foo(bytes20)\`, and \`address\` in \`foo(address)\` These types encode differently and cannot be distinguished at runtime. Remove one of the ambiguous items in the ABI.] `) expect(() => AbiItem.fromAbi( Abi.from([ 'function foo(string)', 'function foo(uint)', 'function foo(address)', ]), 'foo', { args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], }, ), ).toThrowErrorMatchingInlineSnapshot(` [AbiItem.AmbiguityError: Found ambiguous types in overloaded ABI Items. \`address\` in \`foo(address)\`, and \`string\` in \`foo(string)\` These types encode differently and cannot be distinguished at runtime. Remove one of the ambiguous items in the ABI.] `) expect( AbiItem.fromAbi( Abi.from([ 'function foo(string)', 'function foo(uint)', 'function foo(address)', ]), 'foo', { // 21 bytes (invalid address) args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251eee'], }, ), ).toMatchInlineSnapshot(` { "hash": "0xf31a6969fc2f2e0b01964045ad21a28ad3ee38d276e1e6cf5b80124e63ba8190", "inputs": [ { "type": "string", }, ], "name": "foo", "outputs": [], "stateMutability": "nonpayable", "type": "function", } `) expect( AbiItem.fromAbi( Abi.from([ 'function foo(string)', 'function foo(uint)', 'function foo(address)', ]), 'foo', { // non-hex (invalid address) args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251z'], }, ), ).toMatchInlineSnapshot(` { "hash": "0xf31a6969fc2f2e0b01964045ad21a28ad3ee38d276e1e6cf5b80124e63ba8190", "inputs": [ { "type": "string", }, ], "name": "foo", "outputs": [], "stateMutability": "nonpayable", "type": "function", } `) expect(() => AbiItem.fromAbi( Abi.from([ 'function foo(address)', 'function foo(uint)', 'function foo(string)', ]), 'foo', { args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], }, ), ).toThrowErrorMatchingInlineSnapshot(` [AbiItem.AmbiguityError: Found ambiguous types in overloaded ABI Items. \`string\` in \`foo(string)\`, and \`address\` in \`foo(address)\` These types encode differently and cannot be distinguished at runtime. Remove one of the ambiguous items in the ABI.] `) expect(() => AbiItem.fromAbi( Abi.from(['function foo((address))', 'function foo((bytes20))']), 'foo', { args: [['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e']], }, ), ).toThrowErrorMatchingInlineSnapshot(` [AbiItem.AmbiguityError: Found ambiguous types in overloaded ABI Items. \`bytes20\` in \`foo((bytes20))\`, and \`address\` in \`foo((address))\` These types encode differently and cannot be distinguished at runtime. Remove one of the ambiguous items in the ABI.] `) expect(() => AbiItem.fromAbi( Abi.from([ 'function foo(string, (address))', 'function foo(string, (bytes))', ]), 'foo', { args: ['foo', ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e']], }, ), ).toThrowErrorMatchingInlineSnapshot(` [AbiItem.AmbiguityError: Found ambiguous types in overloaded ABI Items. \`bytes\` in \`foo(string,(bytes))\`, and \`address\` in \`foo(string,(address))\` These types encode differently and cannot be distinguished at runtime. Remove one of the ambiguous items in the ABI.] `) }) describe('getAmbiguousTypes', () => { test('string/address', () => { expect( getAmbiguousTypes( AbiParameters.from('string'), AbiParameters.from('address'), ['0xA0Cf798816D4b9b9866b5330EEa46a18382f2522'], ), ).toMatchInlineSnapshot(` [ "string", "address", ] `) expect( getAmbiguousTypes( AbiParameters.from('string'), AbiParameters.from('address'), // 21 bytes (invalid address) ['0xA0Cf798816D4b9b9866b5330EEa46a18382f252223'], ), ).toBeUndefined() expect( getAmbiguousTypes( AbiParameters.from('(string)'), AbiParameters.from('(address)'), [['0xA0Cf798816D4b9b9866b5330EEa46a18382f2522']], ), ).toMatchInlineSnapshot(` [ "string", "address", ] `) expect( getAmbiguousTypes( AbiParameters.from('(address)'), AbiParameters.from('(string)'), [['0xA0Cf798816D4b9b9866b5330EEa46a18382f2522']], ), ).toMatchInlineSnapshot(` [ "address", "string", ] `) expect( getAmbiguousTypes( AbiParameters.from('uint, (string, (string))'), AbiParameters.from('uint, (string, (address))'), [69420n, ['lol', ['0xA0Cf798816D4b9b9866b5330EEa46a18382f2522']]], ), ).toMatchInlineSnapshot(` [ "string", "address", ] `) }) test('bytes/address', () => { expect( getAmbiguousTypes( AbiParameters.from('address'), AbiParameters.from('bytes20'), ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], ), ).toMatchInlineSnapshot(` [ "address", "bytes20", ] `) expect( getAmbiguousTypes( AbiParameters.from('bytes20'), AbiParameters.from('address'), ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], ), ).toMatchInlineSnapshot(` [ "bytes20", "address", ] `) expect( getAmbiguousTypes( AbiParameters.from('address'), AbiParameters.from('bytes'), ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], ), ).toMatchInlineSnapshot(` [ "address", "bytes", ] `) expect( getAmbiguousTypes( AbiParameters.from('bytes'), AbiParameters.from('address'), // 21 bytes (invalid address) ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251eee'], ), ).toBeUndefined() expect( getAmbiguousTypes( AbiParameters.from('bytes'), AbiParameters.from('address'), ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'], ), ).toMatchInlineSnapshot(` [ "bytes", "address", ] `) expect( getAmbiguousTypes( AbiParameters.from('(address)'), AbiParameters.from('(bytes20)'), [['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e']], ), ).toMatchInlineSnapshot(` [ "address", "bytes20", ] `) expect( getAmbiguousTypes( AbiParameters.from('uint256, (address)'), AbiParameters.from('uint128, (bytes20)'), [69420n, ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e']], ), ).toMatchInlineSnapshot(` [ "address", "bytes20", ] `) expect( getAmbiguousTypes( AbiParameters.from('uint256, (string, (address))'), AbiParameters.from('uint128, (string, (bytes20))'), [69420n, ['foo', ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e']]], ), ).toMatchInlineSnapshot(` [ "address", "bytes20", ] `) expect( getAmbiguousTypes( AbiParameters.from('uint256, (string, (address, bytes))'), AbiParameters.from('uint128, (string, (bytes20, address))'), [ 123n, [ 'foo', [ '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e', '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e', ], ], ], ), ).toMatchInlineSnapshot(` [ "address", "bytes20", ] `) }) }) describe.each([ // array { arg: ['foo'], abiParameter: { type: 'string[]' }, expected: true }, { arg: ['foo'], abiParameter: { type: 'string[1]' }, expected: true }, { arg: [['foo']], abiParameter: { type: 'string[][]' }, expected: true }, { arg: [['foo']], abiParameter: { type: 'string[][1]' }, expected: true }, { arg: [1n], abiParameter: { type: 'uint256[]' }, expected: true, }, { arg: [{ foo: 1n, bar: [{ baz: 1n }] }], abiParameter: { type: 'tuple[]', components: [ { name: 'foo', type: 'uint256' }, { name: 'bar', type: 'tuple[]', components: [{ name: 'baz', type: 'uint256' }], }, ], }, expected: true, }, { arg: ['foo'], abiParameter: { type: 'string[test]' }, expected: false }, { arg: [1], abiParameter: { type: 'uint69[]' }, expected: false }, // address { arg: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e', abiParameter: { type: 'address' }, expected: true, }, { arg: 'A0Cf798816D4b9b9866b5330EEa46a18382f251e', abiParameter: { type: 'address' }, expected: false, }, { arg: 'test', abiParameter: { type: 'address' }, expected: false }, // bool { arg: true, abiParameter: { type: 'bool' }, expected: true }, { arg: false, abiParameter: { type: 'bool' }, expected: true }, { arg: 'true', abiParameter: { type: 'bool' }, expected: false }, // bytes { arg: 'foo', abiParameter: { type: 'bytes' }, expected: true }, { arg: 'foo', abiParameter: { type: 'bytes32' }, expected: true }, { arg: Bytes.fromString('foo'), abiParameter: { type: 'bytes' }, expected: true, }, { arg: 1, abiParameter: { type: 'bytes32' }, expected: false }, // function { arg: 'foo', abiParameter: { type: 'function' }, expected: true }, { arg: 1, abiParameter: { type: 'function' }, expected: false }, // int { arg: 1, abiParameter: { type: 'int' }, expected: true }, { arg: 1n, abiParameter: { type: 'int' }, expected: true }, { arg: 1n, abiParameter: { type: 'int' }, expected: true }, { arg: 1, abiParameter: { type: 'uint' }, expected: true }, { arg: 1n, abiParameter: { type: 'uint' }, expected: true }, { arg: 1n, abiParameter: { type: 'uint' }, expected: true }, { arg: 1, abiParameter: { type: 'int256' }, expected: true }, { arg: 1, abiParameter: { type: 'uint256' }, expected: true }, { arg: 1, abiParameter: { type: 'int69' }, expected: false }, { arg: 1, abiParameter: { type: 'uint69' }, expected: false }, // string { arg: 'foo', abiParameter: { type: 'string' }, expected: true }, { arg: 1, abiParameter: { type: 'string' }, expected: false }, // tuple { arg: { bar: 1, baz: 'test' }, abiParameter: { name: 'foo', type: 'tuple', components: [ { name: 'bar', type: 'uint256' }, { name: 'baz', type: 'string' }, ], }, expected: true, }, { arg: [1, 'test'], abiParameter: { name: 'foo', type: 'tuple', components: [ { name: 'bar', type: 'uint256' }, { name: 'baz', type: 'string' }, ], }, expected: true, }, { arg: { bar: ['test'] }, abiParameter: { name: 'foo', type: 'tuple', components: [ { name: 'bar', type: 'tuple', components: [{ name: 'baz', type: 'string' }], }, ], }, expected: true, }, { arg: {}, abiParameter: { name: 'foo', type: 'tuple', components: [ { name: 'bar', type: 'uint256' }, { name: 'baz', type: 'uint256' }, ], }, expected: false, }, ] as { arg: unknown abiParameter: AbiParameters.Parameter expected: boolean }[])( 'isArgOfType($arg, $abiParameter)', ({ arg, abiParameter, expected }) => { test(`isArgOfType: returns ${expected}`, () => { expect(isArgOfType(arg, abiParameter)).toEqual(expected) }) }, ) }) describe('getSelector', () => { test('creates function signature', () => { expect(AbiItem.getSelector('_compound(uint256,uint256,uint256)')).toEqual( '0xf4fbb312', ) expect( AbiItem.getSelector( 'function _compound(uint256 a, uint256 b, uint256 c)', ), ).toEqual('0xf4fbb312') expect(AbiItem.getSelector('function ownerOf(uint256 tokenId)')).toEqual( '0x6352211e', ) expect(AbiItem.getSelector('ownerOf(uint256)')).toEqual('0x6352211e') expect( AbiItem.getSelector('processInvestment(address,uint256,bool)'), ).toEqual('0xcf4b8f61') expect(AbiItem.getSelector('processAccount(uint256 , address )')).toEqual( '0x73933128', ) expect(AbiItem.getSelector('claimed()')).toEqual('0xe834a834') expect(AbiItem.getSelector('function claimed()')).toEqual('0xe834a834') }) test('creates function signature from `AbiFunction`', () => { expect( AbiItem.getSelector({ name: '_compound', type: 'function', inputs: [ { name: 'a', type: 'uint256' }, { name: 'b', type: 'uint256' }, { name: 'c', type: 'uint256' }, ], outputs: [], stateMutability: 'nonpayable', }), ).toEqual('0xf4fbb312') expect( AbiItem.getSelector({ name: '_compound', type: 'function', inputs: [ { name: '', type: 'uint256' }, { name: '', type: 'uint256' }, { name: '', type: 'uint256' }, ], outputs: [], stateMutability: 'nonpayable', }), ).toEqual('0xf4fbb312') expect( AbiItem.getSelector({ name: 'ownerOf', type: 'function', inputs: [{ name: 'tokenId', type: 'uint256' }], outputs: [], stateMutability: 'view', }), ).toEqual('0x6352211e') expect( AbiItem.getSelector({ name: 'ownerOf', type: 'function', inputs: [{ name: '', type: 'uint256' }], outputs: [], stateMutability: 'view', }), ).toEqual('0x6352211e') expect( AbiItem.getSelector({ name: 'processInvestment', type: 'function', inputs: [ { name: '', type: 'address' }, { name: '', type: 'uint256' }, { name: '', type: 'bool' }, ], outputs: [], stateMutability: 'nonpayable', }), ).toEqual('0xcf4b8f61') expect( AbiItem.getSelector({ name: 'processAccount', type: 'function', inputs: [ { name: '', type: 'uint256' }, { name: '', type: 'address' }, ], outputs: [], stateMutability: 'nonpayable', }), ).toEqual('0x73933128') expect( AbiItem.getSelector({ name: 'claimed', type: 'function', inputs: [], outputs: [], stateMutability: 'view', }), ).toEqual('0xe834a834') expect( AbiItem.getSelector({ inputs: [ { components: [ { name: 'position', type: 'uint64', }, { name: 'owner', type: 'address', }, { name: 'color', type: 'uint8', }, { name: 'life', type: 'uint8', }, ], name: 'cells', type: 'tuple[]', }, ], name: 'forceSimpleCells', outputs: [], stateMutability: 'nonpayable', type: 'function', }), ).toEqual('0xd703f50a') }) }) describe('getSignature', () => { test('creates function signature', () => { expect(AbiItem.getSignature('_compound(uint256,uint256,uint256)')).toEqual( '_compound(uint256,uint256,uint256)', ) expect( AbiItem.getSignature( 'function _compound(uint256 a, uint256 b, uint256 c)', ), ).toEqual('_compound(uint256,uint256,uint256)') expect(AbiItem.getSignature('function ownerOf(uint256 tokenId)')).toEqual( 'ownerOf(uint256)', ) expect(AbiItem.getSignature('ownerOf(uint256)')).toEqual('ownerOf(uint256)') expect( AbiItem.getSignature('processInvestment(address,uint256,bool)'), ).toEqual('processInvestment(address,uint256,bool)') expect(AbiItem.getSignature('processAccount(uint256 , address)')).toEqual( 'processAccount(uint256,address)', ) expect(AbiItem.getSignature('claimed()')).toEqual('claimed()') expect(AbiItem.getSignature('function claimed()')).toEqual('claimed()') expect(AbiItem.getSignature(erc20Abi, 'approve')).toEqual( 'approve(address,uint256)', ) }) test('creates function signature from `AbiFunction`', () => { expect( AbiItem.getSignature({ name: '_compound', type: 'function', inputs: [ { name: 'a', type: 'uint256' }, { name: 'b', type: 'uint256' }, { name: 'c', type: 'uint256' }, ], outputs: [], stateMutability: 'nonpayable', }), ).toEqual('_compound(uint256,uint256,uint256)') expect( AbiItem.getSignature({ name: 'ownerOf', type: 'function', inputs: [{ name: 'tokenId', type: 'uint256' }], outputs: [], stateMutability: 'view', }), ).toEqual('ownerOf(uint256)') expect( AbiItem.getSignature({ name: 'ownerOf', type: 'function', inputs: [{ name: '', type: 'uint256' }], outputs: [], stateMutability: 'view', }), ).toEqual('ownerOf(uint256)') expect( AbiItem.getSignature({ name: 'processInvestment', type: 'function', inputs: [ { name: '', type: 'address' }, { name: '', type: 'uint256' }, { name: '', type: 'bool' }, ], outputs: [], stateMutability: 'nonpayable', }), ).toEqual('processInvestment(address,uint256,bool)') expect( AbiItem.getSignature({ name: 'processAccount', type: 'function', inputs: [ { name: '', type: 'uint256' }, { name: '', type: 'address' }, ], outputs: [], stateMutability: 'nonpayable', }), ).toEqual('processAccount(uint256,address)') expect( AbiItem.getSignature({ name: 'claimed', type: 'function', inputs: [], outputs: [], stateMutability: 'view', }), ).toEqual('claimed()') expect( AbiItem.getSignature({ inputs: [ { components: [ { name: 'position', type: 'uint64', }, { name: 'owner', type: 'address', }, { name: 'color', type: 'uint8', }, { name: 'life', type: 'uint8', }, ], name: 'cells', type: 'tuple[]', }, ], name: 'forceSimpleCells', outputs: [], stateMutability: 'nonpayable', type: 'function', }), ).toEqual('forceSimpleCells((uint64,address,uint8,uint8)[])') expect( AbiItem.getSignature({ inputs: [ { name: 'name', type: 'string' }, { name: 'symbol', type: 'string' }, { name: 'editionSize', type: 'uint64' }, { name: 'royaltyBPS', type: 'uint16' }, { name: 'fundsRecipient', type: 'address', }, { name: 'defaultAdmin', type: 'address' }, { components: [ { name: 'publicSalePrice', type: 'uint104', }, { name: 'maxSalePurchasePerAddress', type: 'uint32', }, { name: 'publicSaleStart', type: 'uint64' }, { name: 'publicSaleEnd', type: 'uint64' }, { name: 'presaleStart', type: 'uint64' }, { name: 'presaleEnd', type: 'uint64' }, { name: 'presaleMerkleRoot', type: 'bytes32', }, ], name: 'saleConfig', type: 'tuple', }, { name: 'description', type: 'string' }, { name: 'animationURI', type: 'string' }, { name: 'imageURI', type: 'string' }, ], name: 'createEdition', outputs: [{ name: '', type: 'address' }], stateMutability: 'nonpayable', type: 'function', }), ).toEqual( 'createEdition(string,string,uint64,uint16,address,address,(uint104,uint32,uint64,uint64,uint64,uint64,bytes32),string,string,string)', ) expect( AbiItem.getSignature({ inputs: [ { name: 't', type: 'address', }, { name: 'ah', type: 'address', }, { name: '_owner', type: 'address', }, { components: [ { name: 'maxBid', type: 'uint256', }, { name: 'minBid', type: 'uint256', }, { name: 'bidWindow', type: 'uint256', }, { name: 'tip', type: 'uint256', }, { name: 'receiver', type: 'address', }, ], name: 'cfg', type: 'tuple', }, ], name: 'clone', outputs: [ { name: '', type: 'address', }, ], stateMutability: 'payable', type: 'function', }), ).toEqual( 'clone(address,address,address,(uint256,uint256,uint256,uint256,address))', ) expect( AbiItem.getSignature({ inputs: [ { name: 'payer', type: 'address' }, { name: 'recipient', type: 'address' }, { name: 'tokenAmount', type: 'uint256' }, { name: 'tokenAddress', type: 'address' }, { name: 'startTime', type: 'uint256' }, { name: 'stopTime', type: 'uint256' }, { name: 'nonce', type: 'uint8' }, ], name: 'createStream', outputs: [{ name: 'stream', type: 'address' }], stateMutability: 'nonpayable', type: 'function', }), ).toEqual( 'createStream(address,address,uint256,address,uint256,uint256,uint8)', ) }) test('creates event signature', () => { expect( AbiItem.getSignature('Transfer(address,address,uint256)'), ).toMatchInlineSnapshot('"Transfer(address,address,uint256)"') expect( AbiItem.getSignature( 'Transfer(address indexed from, address indexed to, uint256 amount)', ), ).toMatchInlineSnapshot('"Transfer(address,address,uint256)"') expect( AbiItem.getSignature( 'event Transfer(address indexed from, address indexed to, uint256 amount)', ), ).toMatchInlineSnapshot('"Transfer(address,address,uint256)"') expect(AbiItem.getSignature('drawNumber()')).toMatchInlineSnapshot( '"drawNumber()"', ) expect(AbiItem.getSignature('drawNumber( )')).toMatchInlineSnapshot( '"drawNumber()"', ) expect( AbiItem.getSignature( 'ProcessedAccountDividendTracker(uint256,uint256,uint256,uint256,bool,uint256,address)', ), ).toMatchInlineSnapshot( '"ProcessedAccountDividendTracker(uint256,uint256,uint256,uint256,bool,uint256,address)"', ) expect( AbiItem.getSignature( 'ProcessedAccountDividendTracker(uint256 indexed foo, uint256 indexed bar, uint256 baz, uint256 a, bool b, uint256 c, address d)', ), ).toMatchInlineSnapshot( '"ProcessedAccountDividendTracker(uint256,uint256,uint256,uint256,bool,uint256,address)"', ) expect( AbiItem.getSignature('BlackListMultipleAddresses(address[], bool)'), ).toMatchInlineSnapshot('"BlackListMultipleAddresses(address[],bool)"') expect(AbiItem.getSignature('checkBatch(bytes)')).toMatchInlineSnapshot( '"checkBatch(bytes)"', ) expect( AbiItem.getSignature( 'Approval(address indexed owner, address indexed approved, uint256 indexed tokenId)', ), ).toMatchInlineSnapshot('"Approval(address,address,uint256)"') expect( AbiItem.getSignature( 'ApprovalForAll(address indexed owner, address indexed operator, bool approved)', ), ).toMatchInlineSnapshot('"ApprovalForAll(address,address,bool)"') }) test('creates event signature for `AbiEvent`', () => { expect( AbiItem.getSignature({ name: 'Transfer', type: 'event', inputs: [ { name: 'address', type: 'address', indexed: true }, { name: 'address', type: 'address', indexed: true }, { name: 'uint256', type: 'uint256', indexed: false }, ], }), ).toMatchInlineSnapshot('"Transfer(address,address,uint256)"') expect( AbiItem.getSignature({ name: 'Transfer', type: 'event', inputs: [ { name: 'from', type: 'address', indexed: true }, { name: 'to', type: 'address', indexed: true }, { name: 'amount', type: 'uint256', indexed: false }, ], }), ).toMatchInlineSnapshot('"Transfer(address,address,uint256)"') expect( AbiItem.getSignature({ name: 'drawNumber', type: 'event', inputs: [], }), ).toMatchInlineSnapshot('"drawNumber()"') expect( AbiItem.getSignature({ name: 'drawNumber', type: 'event', inputs: [], }), ).toMatchInlineSnapshot('"drawNumber()"') expect( AbiItem.getSignature({ name: 'ProcessedAccountDividendTracker', type: 'event', inputs: [ { name: 'uint256', type: 'uint256', indexed: false }, { name: 'uint256', type: 'uint256', indexed: false }, { name: 'uint256', type: 'uint256', indexed: false }, { name: 'uint256', type: 'uint256', indexed: false }, { name: 'bool', type: 'bool', indexed: false }, { name: 'uint256', type: 'uint256', indexed: false }, { name: 'address', type: 'address', indexed: false }, ], }), ).toMatchInlineSnapshot( '"ProcessedAccountDividendTracker(uint256,uint256,uint256,uint256,bool,uint256,address)"', ) expect( AbiItem.getSignature({ name: 'ProcessedAccountDividendTracker', type: 'event', inputs: [ { name: 'foo', type: 'uint256', indexed: true }, { name: 'bar', type: 'uint256', indexed: true }, { name: 'baz', type: 'uint256', indexed: false }, { name: 'a', type: 'uint256', indexed: false }, { name: 'b', type: 'bool', indexed: false }, { name: 'c', type: 'uint256', indexed: false }, { name: 'd', type: 'address', indexed: false }, ], }), ).toMatchInlineSnapshot( '"ProcessedAccountDividendTracker(uint256,uint256,uint256,uint256,bool,uint256,address)"', ) expect( AbiItem.getSignature({ name: 'BlackListMultipleAddresses', type: 'event', inputs: [ { name: 'addresses', type: 'address[]', indexed: false }, { name: 'isBlackListed', type: 'bool', indexed: false }, ], }), ).toMatchInlineSnapshot('"BlackListMultipleAddresses(address[],bool)"') expect( AbiItem.getSignature({ name: 'checkBatch', type: 'event', inputs: [{ name: '', type: 'bytes', indexed: false }], }), ).toMatchInlineSnapshot('"checkBatch(bytes)"') expect( AbiItem.getSignature({ name: 'Approval', type: 'event', inputs: [ { name: 'owner', type: 'address', indexed: true }, { name: 'approved', type: 'address', indexed: true }, { name: 'tokenId', type: 'uint256', indexed: true }, ], }), ).toMatchInlineSnapshot('"Approval(address,address,uint256)"') expect( AbiItem.getSignature({ name: 'ApprovalForAll', type: 'event', inputs: [ { name: 'owner', type: 'address', indexed: true }, { name: 'operator', type: 'address', indexed: true }, { name: 'approved', type: 'bool', indexed: false }, ], }), ).toMatchInlineSnapshot('"ApprovalForAll(address,address,bool)"') expect( AbiItem.getSignature({ anonymous: false, inputs: [ { indexed: false, name: 'smolRecipeId', type: 'uint256', }, { components: [ { components: [ { name: 'background', type: 'uint24', }, { name: 'body', type: 'uint24' }, { name: 'clothes', type: 'uint24' }, { name: 'mouth', type: 'uint24' }, { name: 'glasses', type: 'uint24' }, { name: 'hat', type: 'uint24' }, { name: 'hair', type: 'uint24' }, { name: 'skin', type: 'uint24' }, { name: 'gender', type: 'uint8' }, { name: 'headSize', type: 'uint8' }, ], name: 'smol', type: 'tuple', }, { name: 'exists', type: 'bool' }, { name: 'smolInputAmount', type: 'uint8', }, ], indexed: false, name: 'smolData', type: 'tuple', }, ], name: 'SmolRecipeAdded', type: 'event', }), ).toMatchInlineSnapshot( '"SmolRecipeAdded(uint256,((uint24,uint24,uint24,uint24,uint24,uint24,uint24,uint24,uint8,uint8),bool,uint8))"', ) }) describe('normalizeSignature', () => { test('foo()', () => { expect(normalizeSignature('foo()')).toBe('foo()') }) test('bar(uint foo)', () => { expect(normalizeSignature('bar(uint foo)')).toBe('bar(uint)') }) test('processAccount(uint256 , address )', () => { expect(normalizeSignature('processAccount(uint256 , address )')).toBe( 'processAccount(uint256,address)', ) }) test('function bar()', () => { expect(normalizeSignature('function bar()')).toBe('bar()') }) test('function bar()', () => { expect(normalizeSignature('function bar( )')).toBe('bar()') }) test('event Bar()', () => { expect(normalizeSignature('event Bar()')).toBe('Bar()') }) test('function bar(uint foo)', () => { expect(normalizeSignature('function bar(uint foo)')).toBe('bar(uint)') }) test('function bar(uint foo, address baz)', () => { expect(normalizeSignature('function bar(uint foo, address baz)')).toBe( 'bar(uint,address)', ) }) test('event Barry(uint foo)', () => { expect(normalizeSignature('event Barry(uint foo)')).toBe('Barry(uint)') }) test('Barry(uint indexed foo)', () => { expect(normalizeSignature('Barry(uint indexed foo)')).toBe('Barry(uint)') }) test('event Barry(uint indexed foo)', () => { expect(normalizeSignature('event Barry(uint indexed foo)')).toBe( 'Barry(uint)', ) }) test('function _compound(uint256 a, uint256 b, uint256 c)', () => { expect( normalizeSignature( 'function _compound(uint256 a, uint256 b, uint256 c)', ), ).toBe('_compound(uint256,uint256,uint256)') }) test('bar(uint foo, (uint baz))', () => { expect(normalizeSignature('bar(uint foo, (uint baz))')).toBe( 'bar(uint,(uint))', ) }) test('bar(uint foo, (uint baz, bool x))', () => { expect(normalizeSignature('bar(uint foo, (uint baz, bool x))')).toBe( 'bar(uint,(uint,bool))', ) }) test('bar(uint foo, (uint baz, bool x) foo)', () => { expect(normalizeSignature('bar(uint foo, (uint baz, bool x) foo)')).toBe( 'bar(uint,(uint,bool))', ) }) test('bar(uint[] foo, (uint baz, bool x))', () => { expect(normalizeSignature('bar(uint[] foo, (uint baz, bool x))')).toBe( 'bar(uint[],(uint,bool))', ) }) test('bar(uint[] foo, (uint baz, bool x)[])', () => { expect(normalizeSignature('bar(uint[] foo, (uint baz, bool x)[])')).toBe( 'bar(uint[],(uint,bool)[])', ) }) test('foo(uint bar)', () => { expect(normalizeSignature('foo(uint bar) payable returns (uint)')).toBe( 'foo(uint)', ) }) test('function submitBlocksWithCallbacks(bool isDataCompressed, bytes calldata data, ((uint16,(uint16,uint16,uint16,bytes)[])[], address[]) calldata config)', () => { expect( normalizeSignature( 'function submitBlocksWithCallbacks(bool isDataCompressed, bytes calldata data, ((uint16,(uint16,uint16,uint16,bytes)[])[], address[]) calldata config)', ), ).toBe( 'submitBlocksWithCallbacks(bool,bytes,((uint16,(uint16,uint16,uint16,bytes)[])[],address[]))', ) }) test('function createEdition(string name, string symbol, uint64 editionSize, uint16 royaltyBPS, address fundsRecipient, address defaultAdmin, (uint104 publicSalePrice, uint32 maxSalePurchasePerAddress, uint64 publicSaleStart, uint64 publicSaleEnd, uint64 presaleStart, uint64 presaleEnd, bytes32 presaleMerkleRoot) saleConfig, string description, string animationURI, string imageURI) returns (address)', () => { expect( normalizeSignature( 'function createEdition(string name, string symbol, uint64 editionSize, uint16 royaltyBPS, address fundsRecipient, address defaultAdmin, (uint104 publicSalePrice, uint32 maxSalePurchasePerAddress, uint64 publicSaleStart, uint64 publicSaleEnd, uint64 presaleStart, uint64 presaleEnd, bytes32 presaleMerkleRoot) saleConfig, string description, string animationURI, string imageURI) returns (address)', ), ).toBe( 'createEdition(string,string,uint64,uint16,address,address,(uint104,uint32,uint64,uint64,uint64,uint64,bytes32),string,string,string)', ) }) test('trim spaces', () => { expect( normalizeSignature( 'function createEdition(string name,string symbol, uint64 editionSize , uint16 royaltyBPS, address fundsRecipient, address defaultAdmin, ( uint104 publicSalePrice , uint32 maxSalePurchasePerAddress, uint64 publicSaleStart, uint64 publicSaleEnd, uint64 presaleStart, uint64 presaleEnd, bytes32 presaleMerkleRoot) saleConfig , string description, string animationURI, string imageURI ) returns (address)', ), ).toBe( 'createEdition(string,string,uint64,uint16,address,address,(uint104,uint32,uint64,uint64,uint64,uint64,bytes32),string,string,string)', ) }) test('error: invalid signatures', () => { expect(() => normalizeSignature('bar'), ).toThrowErrorMatchingInlineSnapshot( '[BaseError: Unable to normalize signature.]', ) expect(() => normalizeSignature('bar(uint foo'), ).toThrowErrorMatchingInlineSnapshot( '[BaseError: Unable to normalize signature.]', ) expect(() => normalizeSignature('baruint foo)'), ).toThrowErrorMatchingInlineSnapshot( '[BaseError: Unable to normalize signature.]', ) expect(() => normalizeSignature('bar(uint foo, (uint baz)'), ).toThrowErrorMatchingInlineSnapshot( '[BaseError: Unable to normalize signature.]', ) }) }) }) describe('getSignatureHash', () => { test('hashes functions', () => { expect(AbiItem.getSignatureHash('function ownerOf(uint256)')).toEqual( '0x6352211e6566aa027e75ac9dbf2423197fbd9b82b9d981a3ab367d355866aa1c', ) expect( AbiItem.getSignatureHash('Transfer(address,address,uint256)'), ).toEqual( '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', ) expect( AbiItem.getSignatureHash( 'Transfer(address indexed from, address indexed to, uint256 amount)', ), ).toEqual( '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', ) expect( AbiItem.getSignatureHash( 'event Transfer(address indexed from, address indexed to, uint256 amount)', ), ).toEqual( '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', ) expect(AbiItem.getSignatureHash('drawNumber()')).toEqual( '0xd80ffb20d597d029eb14b9def3d14da7e6d862943d830906185b1b0b576d8f26', ) expect(AbiItem.getSignatureHash('drawNumber( )')).toEqual( '0xd80ffb20d597d029eb14b9def3d14da7e6d862943d830906185b1b0b576d8f26', ) expect( AbiItem.getSignatureHash( 'ProcessedAccountDividendTracker(uint256,uint256,uint256,uint256,bool,uint256,address)', ), ).toEqual( '0x4a73985b7c9415b88fbbfbb5e2fb377c08586d96f5c42646ecef7e3717587f6a', ) expect( AbiItem.getSignatureHash( 'ProcessedAccountDividendTracker(uint256 indexed foo, uint256 indexed bar, uint256 baz, uint256 a, bool b, uint256 c, address d)', ), ).toEqual( '0x4a73985b7c9415b88fbbfbb5e2fb377c08586d96f5c42646ecef7e3717587f6a', ) expect( AbiItem.getSignatureHash('BlackListMultipleAddresses(address[], bool)'), ).toEqual( '0x170cd84eddb1952bf41adcce9be0e44b66ff38f07cddda1cf64d32708742bd2d', ) expect(AbiItem.getSignatureHash('checkBatch(bytes)')).toEqual( '0x9b6f373667d9cf576e3a17e6aa047c5d864fcb7f41836b11613215db446698d8', ) expect( AbiItem.getSignatureHash( 'Approval(address indexed owner, address indexed approved, uint256 indexed tokenId)', ), ).toBe('0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925') expect( AbiItem.getSignatureHash( 'ApprovalForAll(address indexed owner, address indexed operator, bool approved)', ), ).toBe('0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31') expect(AbiItem.getSignatureHash('function balanceOf(address owner)')).toBe( '0x70a08231b98ef4ca268c9cc3f6b4590e4bfec28280db06bb5d45e689f2a360be', ) expect(AbiItem.getSignatureHash('function ownerOf(uint256 tokenId)')).toBe( '0x6352211e6566aa027e75ac9dbf2423197fbd9b82b9d981a3ab367d355866aa1c', ) expect(AbiItem.getSignatureHash(erc20Abi, 'approve')).toBe( '0x095ea7b334ae44009aa867bfb386f5c3b4b443ac6f0ee573fa91c4608fbadfba', ) }) test('hashes `AbiFunction`', () => { expect( AbiItem.getSignatureHash({ name: 'drawNumber', type: 'function', inputs: [], outputs: [], stateMutability: 'nonpayable', }), ).toEqual( '0xd80ffb20d597d029eb14b9def3d14da7e6d862943d830906185b1b0b576d8f26', ) expect( AbiItem.getSignatureHash({ name: 'BlackListMultipleAddresses', type: 'function', inputs: [ { name: 'address[]', type: 'address[]' }, { name: 'bool', type: 'bool' }, ], outputs: [], stateMutability: 'nonpayable', }), ).toEqual( '0x170cd84eddb1952bf41adcce9be0e44b66ff38f07cddda1cf64d32708742bd2d', ) expect( AbiItem.getSignatureHash({ name: 'checkBatch', type: 'function', inputs: [{ name: 'bytes', type: 'bytes' }], outputs: [], stateMutability: 'nonpayable', }), ).toEqual( '0x9b6f373667d9cf576e3a17e6aa047c5d864fcb7f41836b11613215db446698d8', ) expect( AbiItem.getSignatureHash({ name: 'balanceOf', type: 'function', inputs: [{ name: 'owner', type: 'address' }], outputs: [], stateMutability: 'nonpayable', }), ).toBe('0x70a08231b98ef4ca268c9cc3f6b4590e4bfec28280db06bb5d45e689f2a360be') expect( AbiItem.getSignatureHash({ name: 'ownerOf', type: 'function', inputs: [{ name: 'tokenId', type: 'uint256' }], outputs: [], stateMutability: 'nonpayable', }), ).toBe('0x6352211e6566aa027e75ac9dbf2423197fbd9b82b9d981a3ab367d355866aa1c') }) test('hashes `AbiEvent`', () => { expect( AbiItem.getSignatureHash({ name: 'Transfer', type: 'event', inputs: [ { name: 'from', type: 'address', indexed: true }, { name: 'to', type: 'address', indexed: true }, { name: 'amount', type: 'uint256', indexed: false }, ], }), ).toEqual( '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', ) expect( AbiItem.getSignatureHash({ name: 'ProcessedAccountDividendTracker', type: 'event', inputs: [ { name: 'lastProcessedIndex', type: 'uint256', indexed: false }, { name: 'iterationsUntilProcessed', type: 'uint256', indexed: false }, { name: 'withdrawableDividends', type: 'uint256', indexed: false }, { name: 'totalDividends', type: 'uint256', indexed: false }, { name: 'process', type: 'bool', indexed: false }, { name: 'gas', type: 'uint256', indexed: false }, { name: 'rewardsToken', type: 'address', indexed: false }, ], }), ).toEqual( '0x4a73985b7c9415b88fbbfbb5e2fb377c08586d96f5c42646ecef7e3717587f6a', ) expect( AbiItem.getSignatureHash({ name: 'Approval', type: 'event', inputs: [ { name: 'owner', type: 'address', indexed: true }, { name: 'approved', type: 'address', indexed: true }, { name: 'tokenId', type: 'uint256', indexed: true }, ], }), ).toBe('0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925') expect( AbiItem.getSignatureHash({ name: 'ApprovalForAll', type: 'event', inputs: [ { name: 'owner', type: 'address', indexed: true }, { name: 'operator', type: 'address', indexed: true }, { name: 'approved', type: 'bool', indexed: false }, ], }), ).toBe('0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31') expect( AbiItem.getSignatureHash({ name: 'BlackListMultipleAddresses', type: 'event', inputs: [ { name: 'addresses', type: 'address[]', indexed: false }, { name: 'isBlackListed', type: 'bool', indexed: false }, ], }), ).toEqual( '0x170cd84eddb1952bf41adcce9be0e44b66ff38f07cddda1cf64d32708742bd2d', ) }) test('behavior: abi item contains hash', () => { const event = AbiEvent.from( 'event Transfer(address indexed from, address indexed to, uint256 amount)', ) expect(AbiItem.getSignatureHash(event)).toEqual( (event as unknown as { hash: Hex.Hex }).hash, ) }) }) test('exports', () => { expect(Object.keys(AbiItem)).toMatchInlineSnapshot(` [ "InvalidAbiItemError", "UnknownSolidityTypeError", "UnknownTypeError", "format", "from", "fromAbi", "getSelector", "getSignature", "getSignatureHash", "AmbiguityError", "NotFoundError", "InvalidSelectorSizeError", ] `) })