diff --git a/packages/web3-eth-abi/src/utils.ts b/packages/web3-eth-abi/src/utils.ts index e8212c28329..4124748156f 100644 --- a/packages/web3-eth-abi/src/utils.ts +++ b/packages/web3-eth-abi/src/utils.ts @@ -152,6 +152,10 @@ export const isOddHexstring = (param: unknown): boolean => export const formatOddHexstrings = (param: string): string => isOddHexstring(param) ? `0x0${param.substring(2)}` : param; +const paramTypeBytes = /^bytes([0-9]*)$/; +const paramTypeBytesArray = /^bytes([0-9]*)\[\]$/; +const paramTypeNumber = /^(u?int)([0-9]*)$/; +const paramTypeNumberArray = /^(u?int)([0-9]*)\[\]$/; /** * Handle some formatting of params for backwards compatibility with Ethers V4 */ @@ -160,13 +164,9 @@ export const formatParam = (type: string, _param: unknown): unknown => { // clone if _param is an object const param = typeof _param === 'object' && !Array.isArray(_param) ? { ..._param } : _param; - const paramTypeBytes = /^bytes([0-9]*)$/; - const paramTypeBytesArray = /^bytes([0-9]*)\[\]$/; - const paramTypeNumber = /^(u?int)([0-9]*)$/; - const paramTypeNumberArray = /^(u?int)([0-9]*)\[\]$/; // Format BN to string - if (param instanceof BigInt) { + if (param instanceof BigInt || typeof param === 'bigint') { return param.toString(10); } @@ -179,7 +179,7 @@ export const formatParam = (type: string, _param: unknown): unknown => { // Format correct width for u?int[0-9]* let match = paramTypeNumber.exec(type); if (match) { - const size = parseInt(match[2] ?? '256', 10); + const size = parseInt(match[2] ? match[2] : '256', 10); if (size / 8 < (param as { length: number }).length) { // pad to correct bit width return leftPad(param as string, size); diff --git a/packages/web3-eth-abi/test/fixtures/data.ts b/packages/web3-eth-abi/test/fixtures/data.ts index aeefb7a9541..0fe90638f95 100644 --- a/packages/web3-eth-abi/test/fixtures/data.ts +++ b/packages/web3-eth-abi/test/fixtures/data.ts @@ -1113,3 +1113,52 @@ export const invalidIsAbiConstructorFragment: { input: { inputs: [], stateMutability: 'nonpayable', type: 'function' }, }, ]; + +export const mapTypesValidData: [any, any][] = [ + [ + ['string', 'uint256'], + ['string', 'uint256'], + ], + [ + [ + { type: 'string', name: 'test' }, + { type: 'uint256', name: 'test' }, + ], + [ + { type: 'string', name: 'test' }, + { type: 'uint256', name: 'test' }, + ], + ], + [ + [ + { type: 'function', name: 'test' }, + { type: 'uint256', name: 'test' }, + ], + [ + { type: 'bytes24', name: 'test' }, + { type: 'uint256', name: 'test' }, + ], + ], + [ + [{ name1: ['string'] }], + [{ components: [{ name: '0', type: 'string' }], name: 'name1', type: 'tuple' }], + ], +]; + +export const formatParamValidData: [[string, any], any][] = [ + [['string', { name: 'test' }], { name: 'test' }], + [['string', [{ name: 'test' }]], [{ name: 'test' }]], + [['string', BigInt(1)], '1'], + [['int', 123], 123], + [['bytes', '0x99d42941'], '0x99d42941'], + [ + ['int', '0x1234567890123456789012345678901234567890'], + '0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001234567890123456789012345678901234567890', + ], + [ + ['bytes256[]', ['0x99d42941']], + [ + '0x99d42941000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + ], + ], +]; diff --git a/packages/web3-eth-abi/test/unit/utils.test.ts b/packages/web3-eth-abi/test/unit/utils.test.ts index 548e1b6a78a..7428d3bcfd6 100644 --- a/packages/web3-eth-abi/test/unit/utils.test.ts +++ b/packages/web3-eth-abi/test/unit/utils.test.ts @@ -15,12 +15,23 @@ You should have received a copy of the GNU Lesser General Public License along with web3.js. If not, see . */ -import { jsonInterfaceMethodToString, isAbiConstructorFragment } from '../../src/utils'; +import { + jsonInterfaceMethodToString, + isAbiConstructorFragment, + flattenTypes, + mapTypes, + formatParam, + isOddHexstring, + formatOddHexstrings, + isAbiFragment, +} from '../../src/utils'; import { jsonInterfaceInvalidData, jsonInterfaceValidData, validIsAbiConstructorFragment, invalidIsAbiConstructorFragment, + mapTypesValidData, + formatParamValidData, } from '../fixtures/data'; describe('utils', () => { @@ -30,11 +41,73 @@ describe('utils', () => { expect(jsonInterfaceMethodToString(input)).toEqual(output); }); }); + describe('default cases', () => { + it('default json value', () => { + // @ts-expect-error invalid input + expect(jsonInterfaceMethodToString({})).toBe('()'); + }); + it('name value with brackets', () => { + expect( + jsonInterfaceMethodToString({ + name: '(test)', + type: 'function', + inputs: [], + }), + ).toBe('(test)'); + }); + }); describe('invalid cases', () => { // TODO: To be done after `sha3` is implemented it.todo('should throw error for invalid cases'); }); }); + describe('mapTypes', () => { + describe('valid data', () => { + it.each(mapTypesValidData)('%s', (input, output) => { + expect(mapTypes(input)).toEqual(output); + }); + }); + }); + describe('formatParam', () => { + describe('default types', () => { + it.each(formatParamValidData)('%s', (input, output) => { + expect(formatParam(input[0], input[1])).toEqual(output); + }); + }); + }); + describe('isOddHexstring', () => { + it('not string param', () => { + expect(isOddHexstring('')).toBeFalsy(); + }); + }); + describe('isAbiFragment', () => { + it('nullish', () => { + expect(isAbiFragment(undefined)).toBeFalsy(); + }); + }); + describe('formatOddHexstrings', () => { + it('not string param', () => { + expect(formatOddHexstrings('')).toBeFalsy(); + }); + }); + describe('flattenTypes', () => { + it('default types with include tuples', () => { + expect( + flattenTypes(true, [ + { + type: 'tuple', + name: 'test', + components: [ + { + name: 'test', + type: '[string,number]', + }, + ], + }, + ]), + ).toEqual(['tuple([string,number])']); + }); + }); describe('jsonInterface', () => { describe('valid cases', () => { it.each(jsonInterfaceValidData)('%s', (input, output) => {