diff --git a/.changeset/long-ducks-jump.md b/.changeset/long-ducks-jump.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/long-ducks-jump.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/fuel-gauge/src/abi/abi-coder.test.ts b/packages/fuel-gauge/src/abi/abi-coder.test.ts new file mode 100644 index 00000000000..cf3b9459fbd --- /dev/null +++ b/packages/fuel-gauge/src/abi/abi-coder.test.ts @@ -0,0 +1,2635 @@ +import { bn, FuelError, getRandomB256 } from 'fuels'; +import type { AssetId, BigNumberish, EvmAddress, RawSlice, WalletUnlocked } from 'fuels'; +import { expectToThrowFuelError, launchTestNode } from 'fuels/test-utils'; + +import { AbiContractFactory } from '../../test/typegen'; +import type { AbiContract } from '../../test/typegen'; +import { + EnumWithNativeInput, + EnumWithNativeOutput, + ExternalEnumInput, +} from '../../test/typegen/contracts/AbiContract'; +import type { + EnumWithBuiltinTypeInput, + EnumWithBuiltinTypeOutput, + EnumWithVectorInput, + EnumWithVectorOutput, + IdentityInput, + IdentityOutput, + StructDoubleGenericInput, + StructSimpleInput, + StructSimpleOutput, + StructWithGenericArrayInput, + StructWithMultiOptionInput, + StructWithMultiOptionOutput, + StructCInput, + StructWithNestedArrayInput, + StructWithNestedTupleInput, + StructSingleGenericInput, + StructWithImplicitGenericsInput, + AssetIdInput, + StructWithEnumArrayInput, + StructWithEnumArrayOutput, + StructWithSingleOptionOutput, + StructWithSingleOptionInput, +} from '../../test/typegen/contracts/AbiContract'; +import type { Option, Result, Vec } from '../../test/typegen/contracts/common'; + +import { + U16_MAX, + U16_MIN, + U256_MAX, + U256_MIN, + U32_MAX, + U32_MIN, + U64_MAX, + U64_MIN, + U8_MAX, + U8_MIN, +} from './constants'; +import { toEqualBn } from './vitest.matcher'; + +expect.extend({ toEqualBn }); + +/** + * @group browser + * @group node + */ +describe('AbiCoder', () => { + let contract: AbiContract; + let wallet: WalletUnlocked; + let cleanup: () => void; + + beforeAll(async () => { + const launched = await launchTestNode({ + contractsConfigs: [{ factory: AbiContractFactory }], + }); + + const { contracts, wallets } = launched; + + wallet = wallets[0]; + contract = contracts[0] as AbiContract; + cleanup = launched.cleanup; + }); + + afterAll(() => { + cleanup(); + }); + + describe('configurables', () => { + it('should encode/decode just fine', async () => { + const EXPECTED = { + U8_VALUE: 10, + BOOL_VALUE: true, + B256_VALUE: '0x38966262edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + OPTION_U8_VALUE: undefined, + GENERIC_STRUCT_VALUE: { + a: { a: 4, b: 257 }, + b: 57000, + }, + }; + + const { waitForResult } = await contract.functions.configurables().call(); + + const { value } = await waitForResult(); + expect(value).toEqual(EXPECTED); + }); + + it('should set configurables', async () => { + const NEW_CONFIGURABLES = { + U8_VALUE: 123, + BOOL_VALUE: false, + B256_VALUE: getRandomB256(), + OPTION_U8_VALUE: 11, + GENERIC_STRUCT_VALUE: { + a: { a: 234, b: 12 }, + b: 3525, + }, + }; + + const { waitForResult: waitForDeploy } = await AbiContractFactory.deploy(wallet, { + configurableConstants: NEW_CONFIGURABLES, + }); + + const { contract: contractWithConfigurables } = await waitForDeploy(); + const { waitForResult } = await contractWithConfigurables.functions.configurables().call(); + const { value } = await waitForResult(); + expect(value).toEqual(NEW_CONFIGURABLES); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('configurables'); + + expect(fn.name).toBe('configurables'); + expect(fn.signature).toEqual('configurables()'); + expect(fn.selector).toEqual('0x00000000fdaf4480'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 13, 99, 111, 110, 102, 105, 103, 117, 114, 97, 98, 108, 101, 115, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_u8', () => { + it('should encode/decode just fine', async () => { + const input = 8; + const expected = 255; + + const fn = contract.functions.types_u8(input); + + const { waitForResult } = await fn.call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_u8'); + + expect(fn.name).toBe('types_u8'); + expect(fn.signature).toEqual('types_u8(u8)'); + expect(fn.selector).toEqual('0x00000000469feadd'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 8, 116, 121, 112, 101, 115, 95, 117, 56]) + ); + expect(fn.attributes).toEqual([]); + }); + + it('should fail to encode/decode [min - 1]', async () => { + const input = U8_MIN - 1; + + await expectToThrowFuelError( + () => contract.functions.types_u8(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid u8.') + ); + }); + + it('should fail to encode/decode [max + 1]', async () => { + const input = U8_MAX + 1; + + await expectToThrowFuelError( + () => contract.functions.types_u8(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid u8, too many bytes.') + ); + }); + }); + + describe('types_u16', () => { + it('should encode/decode just fine', async () => { + const input = 16; + const expected = 65535; + + const { waitForResult } = await contract.functions.types_u16(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_u16'); + + expect(fn.name).toBe('types_u16'); + expect(fn.signature).toEqual('types_u16(u16)'); + expect(fn.selector).toEqual('0x0000000014b491ca'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 9, 116, 121, 112, 101, 115, 95, 117, 49, 54]) + ); + expect(fn.attributes).toEqual([]); + }); + + it('should fail to encode/decode [min - 1]', async () => { + const input = U16_MIN - 1; + + await expectToThrowFuelError( + () => contract.functions.types_u16(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid u16.') + ); + }); + + it('should fail to encode/decode [max + 1]', async () => { + const input = U16_MAX + 1; + + await expectToThrowFuelError( + () => contract.functions.types_u16(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid u16, too many bytes.') + ); + }); + }); + + describe('types_u32', () => { + it('should encode/decode just fine', async () => { + const input = 32; + const expected = 4294967295; + + const { waitForResult } = await contract.functions.types_u32(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_u32'); + + expect(fn.name).toBe('types_u32'); + expect(fn.signature).toEqual('types_u32(u32)'); + expect(fn.selector).toEqual('0x0000000060564dd0'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 9, 116, 121, 112, 101, 115, 95, 117, 51, 50]) + ); + expect(fn.attributes).toEqual([]); + }); + + it('should fail to encode/decode [min - 1]', async () => { + const input = U32_MIN - 1; + + await expectToThrowFuelError( + () => contract.functions.types_u32(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid u32.') + ); + }); + + it('should fail to encode/decode [max + 1]', async () => { + const input = U32_MAX + 1; + + await expectToThrowFuelError( + () => contract.functions.types_u32(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid u32, too many bytes.') + ); + }); + }); + + describe('types_u64', () => { + it('should encode/decode just fine', async () => { + const input = 64; + const expected = '4294967295000'; + + const { waitForResult } = await contract.functions.types_u64(input).call(); + + const { + value, + logs: [log], + } = await waitForResult(); + expect(value.toString()).toBe(expected); + expect(log.toString()).toBe(expected); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_u64'); + + expect(fn.name).toBe('types_u64'); + expect(fn.signature).toEqual('types_u64(u64)'); + expect(fn.selector).toEqual('0x000000005366a006'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 9, 116, 121, 112, 101, 115, 95, 117, 54, 52]) + ); + expect(fn.attributes).toEqual([]); + }); + + it('should fail to encode/decode [min - 1]', async () => { + const input = U64_MIN - 1; + + await expectToThrowFuelError( + () => contract.functions.types_u64(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid u64.') + ); + }); + + it('should fail to encode/decode [max + 1]', async () => { + const input = U64_MAX.add(1); + + await expectToThrowFuelError( + () => contract.functions.types_u64(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid u64.') + ); + }); + }); + + describe('types_u256', () => { + it('should encode/decode just fine', async () => { + const input = 256; + const expected = '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; + + const { waitForResult } = await contract.functions.types_u256(input).call(); + + const { + value, + logs: [log], + } = await waitForResult(); + expect(value.toHex()).toStrictEqual(expected); + expect(log.toHex()).toStrictEqual(expected); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_u256'); + + expect(fn.name).toBe('types_u256'); + expect(fn.signature).toEqual('types_u256(u256)'); + expect(fn.selector).toEqual('0x00000000385e74cd'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 10, 116, 121, 112, 101, 115, 95, 117, 50, 53, 54]) + ); + expect(fn.attributes).toEqual([]); + }); + + it('should fail to encode/decode [min - 1]', async () => { + const input = U256_MIN - 1; + + await expectToThrowFuelError( + () => contract.functions.types_u256(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid u256.') + ); + }); + + it('should fail to encode/decode [max + 1]', async () => { + const input = U256_MAX.add(1); + + await expectToThrowFuelError( + () => contract.functions.types_u256(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid u256.') + ); + }); + }); + + describe('types_bool', () => { + it('should encode/decode just fine', async () => { + const input = false; + const expected = true; + + const { waitForResult } = await contract.functions.types_bool(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_bool'); + + expect(fn.name).toBe('types_bool'); + expect(fn.signature).toEqual('types_bool(bool)'); + expect(fn.selector).toEqual('0x0000000040b71e0f'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 10, 116, 121, 112, 101, 115, 95, 98, 111, 111, 108]) + ); + expect(fn.attributes).toEqual([]); + }); + + it('should fail to encode/decode [number]', async () => { + const input = 2; + + await expectToThrowFuelError( + () => contract.functions.types_bool(input as unknown as boolean).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid boolean value.') + ); + }); + + it('should fail to encode/decode [string]', async () => { + const input = new Uint8Array([2]); + + await expectToThrowFuelError( + () => contract.functions.types_bool(input as unknown as boolean).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid boolean value.') + ); + }); + }); + + describe('types_b256', () => { + it('should encode/decode just fine', async () => { + const input = `0x${'a'.repeat(64)}`; + const expected = `0x${'0'.repeat(64)}`; + + const { waitForResult } = await contract.functions.types_b256(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_b256'); + + expect(fn.name).toBe('types_b256'); + expect(fn.signature).toEqual('types_b256(b256)'); + expect(fn.selector).toEqual('0x00000000124e3f18'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 10, 116, 121, 112, 101, 115, 95, 98, 50, 53, 54]) + ); + expect(fn.attributes).toEqual([]); + }); + + it('should fail to encode/decode [too short]', async () => { + const input = `0x${'a'.repeat(63)}`; + + await expectToThrowFuelError( + () => contract.functions.types_b256(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid b256.') + ); + }); + + it('should fail to encode/decode [too long]', async () => { + const input = `0x${'a'.repeat(65)}`; + + await expectToThrowFuelError( + () => contract.functions.types_b256(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid b256.') + ); + }); + + it('should fail to encode/decode [not a hex]', async () => { + const input = 'not a hex value'; + + await expectToThrowFuelError( + () => contract.functions.types_b256(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid b256.') + ); + }); + }); + + describe('types_b512', () => { + it('should encode/decode just fine', async () => { + const input = `0xbd0c9b8792876713afa8bff383eebf31c43437823ed761cc3600d0016de5110c44ac566bd156b4fc71a4a4cb2655d3dd360c695edb17dc3b64d611e122fea23d`; + const expected = `0xad0c9b8792876713afa8bff383eebf31c43437823ed761cc3600d0016de5110c54ac566bd156b4fc71a4a4cb2655d3dd360c695edb17dc3b64d611e122fea23d`; + + const { waitForResult } = await contract.functions.types_b512(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_b512'); + + expect(fn.name).toBe('types_b512'); + expect(fn.signature).toEqual('types_b512(s(a[b256;2]))'); + expect(fn.selector).toEqual('0x00000000e628dc42'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 10, 116, 121, 112, 101, 115, 95, 98, 53, 49, 50]) + ); + expect(fn.attributes).toEqual([]); + }); + + it('should fail to encode/decode [too short]', async () => { + const input = `0x${'a'.repeat(127)}`; + + await expectToThrowFuelError( + () => contract.functions.types_b512(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid struct B512.') + ); + }); + + it('should fail to encode/decode [too long]', async () => { + const input = `0x${'a'.repeat(129)}`; + + await expectToThrowFuelError( + () => contract.functions.types_b512(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid struct B512.') + ); + }); + + it('should fail to encode/decode [not a hex]', async () => { + const input = 'not a hex value'; + + await expectToThrowFuelError( + () => contract.functions.types_b512(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Invalid struct B512.') + ); + }); + }); + + describe('types_bytes', () => { + it('should encode/decode just fine [Uint8Array]', async () => { + const input = Uint8Array.from([1, 2, 3]); + const expected = Uint8Array.from([3, 2, 1]); + const { waitForResult } = await contract.functions.types_bytes(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should encode/decode just fine [number]', async () => { + const input = [1, 2, 3]; + const expected = Uint8Array.from([3, 2, 1]); + const { waitForResult } = await contract.functions.types_bytes(input).call(); + + const { + value, + logs: [log], + } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(log).toStrictEqual(expected); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_bytes'); + + expect(fn.name).toBe('types_bytes'); + expect(fn.signature).toEqual('types_bytes(s(s(rawptr,u64),u64))'); + expect(fn.selector).toEqual('0x00000000647316a2'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 11, 116, 121, 112, 101, 115, 95, 98, 121, 116, 101, 115, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + /** + * Strings + */ + describe('types_str', () => { + it('should encode/decode just fine [length = 5]', async () => { + const input = 'Input'; + const expected = 'Hello'; + + const { waitForResult } = await contract.functions.types_str(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_str'); + + expect(fn.name).toBe('types_str'); + expect(fn.signature).toEqual('types_str(str[5])'); + expect(fn.selector).toEqual('0x00000000476ddcb5'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 9, 116, 121, 112, 101, 115, 95, 115, 116, 114]) + ); + expect(fn.attributes).toEqual([]); + }); + + it('should fail to encode/decode [length - 1]', async () => { + const input = 'a'.repeat(4); + + await expectToThrowFuelError( + () => contract.functions.types_str(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Value length mismatch during encode.') + ); + }); + + it('should fail to encode/decode [length + 1]', async () => { + const input = 'a'.repeat(6); + + await expectToThrowFuelError( + () => contract.functions.types_str(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Value length mismatch during encode.') + ); + }); + }); + + describe('types_str_slice', () => { + it('should encode/decode just fine', async () => { + const input = 'Input'; + const expected = 'Output'; + + const { waitForResult } = await contract.functions.types_str_slice(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_str_slice'); + + expect(fn.name).toBe('types_str_slice'); + expect(fn.signature).toEqual('types_str_slice(str)'); + expect(fn.selector).toEqual('0x0000000010afc4e3'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 15, 116, 121, 112, 101, 115, 95, 115, 116, 114, 95, 115, 108, 105, + 99, 101, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_std_string', () => { + it('should encode/decode just fine', async () => { + const input = 'Input'; + const expected = 'Output'; + + const { waitForResult } = await contract.functions.types_std_string(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_std_string'); + + expect(fn.name).toBe('types_std_string'); + expect(fn.signature).toEqual('types_std_string(s(s(s(rawptr,u64),u64)))'); + expect(fn.selector).toEqual('0x0000000088a7be99'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 16, 116, 121, 112, 101, 115, 95, 115, 116, 100, 95, 115, 116, 114, + 105, 110, 103, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_raw_slice', () => { + it('should encode/decode just fine', async () => { + const input: RawSlice = [1, 2, 3]; + const expected: RawSlice = [4, 3, 2, 1]; + + const { waitForResult } = await contract.functions.types_raw_slice(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_raw_slice'); + + expect(fn.name).toBe('types_raw_slice'); + expect(fn.signature).toEqual('types_raw_slice(rawslice)'); + expect(fn.selector).toEqual('0x00000000e009cdab'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 15, 116, 121, 112, 101, 115, 95, 114, 97, 119, 95, 115, 108, 105, 99, + 101, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + /** + * Arrays + */ + describe('types_array', () => { + it('should encode/decode just fine', async () => { + const input = [1, 2, 3, 4] as [number, number, number, number]; + const expected = [4, 3, 2, 1] as [number, number, number, number]; + + const { waitForResult } = await contract.functions.types_array(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_array'); + + expect(fn.name).toBe('types_array'); + expect(fn.signature).toEqual('types_array(a[u8;4])'); + expect(fn.selector).toEqual('0x0000000006fd70c6'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 11, 116, 121, 112, 101, 115, 95, 97, 114, 114, 97, 121, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + + it('should fail to encode/decode [empty]', async () => { + const input = [] as unknown as [number, number, number, number]; + + await expectToThrowFuelError( + () => contract.functions.types_array(input).call(), + new FuelError(FuelError.CODES.ENCODE_ERROR, 'Types/values length mismatch.') + ); + }); + }); + + describe('types_array_struct', () => { + it('should encode/decode just fine', async () => { + const input = [ + { a: true, b: 10 }, + { a: true, b: 10 }, + { a: true, b: 10 }, + ] as [{ a: boolean; b: number }, { a: boolean; b: number }, { a: boolean; b: number }]; + const expected = [ + { a: false, b: 30 }, + { a: false, b: 30 }, + { a: false, b: 30 }, + ]; + + const { waitForResult } = await contract.functions.types_array_struct(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_array_struct'); + + expect(fn.name).toBe('types_array_struct'); + expect(fn.signature).toEqual('types_array_struct(a[s(bool,u32);3])'); + expect(fn.selector).toEqual('0x000000000e99463a'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 18, 116, 121, 112, 101, 115, 95, 97, 114, 114, 97, 121, 95, 115, 116, + 114, 117, 99, 116, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_array_with_generic_struct', () => { + it('should encode/decode just fine', async () => { + const INPUT_STRUCT = { + a: { + a: 10, + }, + b: 'A', + }; + const input = [INPUT_STRUCT, INPUT_STRUCT] as [ + StructDoubleGenericInput, string>, + StructDoubleGenericInput, string>, + ]; + + const EXPECTED_STRUCT = { + a: { + // @ts-expect-error: Custom matcher 'toEqualBn' + a: expect.toEqualBn(20), + }, + b: 'B', + }; + const expected = [EXPECTED_STRUCT, EXPECTED_STRUCT]; + + const { waitForResult } = await contract.functions + .types_array_with_generic_struct(input) + .call(); + + const { value, logs } = await waitForResult(); + expect(value).toEqual(expected); + expect(logs).toEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_array_with_generic_struct'); + + expect(fn.name).toBe('types_array_with_generic_struct'); + expect(fn.signature).toEqual( + 'types_array_with_generic_struct(a[s(u64),str[1]>(s(u64),str[1]);2])' + ); + expect(fn.selector).toEqual('0x0000000026db0b1a'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 31, 116, 121, 112, 101, 115, 95, 97, 114, 114, 97, 121, 95, 119, 105, + 116, 104, 95, 103, 101, 110, 101, 114, 105, 99, 95, 115, 116, 114, 117, 99, 116, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_array_with_vector', () => { + it('should encode/decode just fine', async () => { + const input = [[1, 2, 3]] as [Vec]; + const expected = [[3, 2, 1]]; + + const { waitForResult } = await contract.functions.types_array_with_vector(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_array_with_vector'); + + expect(fn.name).toBe('types_array_with_vector'); + expect(fn.signature).toEqual('types_array_with_vector(a[s(s(rawptr,u64),u64);1])'); + expect(fn.selector).toEqual('0x00000000f433e5fd'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 23, 116, 121, 112, 101, 115, 95, 97, 114, 114, 97, 121, 95, 119, 105, + 116, 104, 95, 118, 101, 99, 116, 111, 114, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + /** + * Structs + */ + describe('types_struct_simple', () => { + it('should encode/decode just fine', async () => { + const input = { a: true, b: 10 }; + const expected = { a: false, b: 30 }; + + const { waitForResult } = await contract.functions.types_struct_simple(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_struct_simple'); + + expect(fn.name).toBe('types_struct_simple'); + expect(fn.signature).toEqual('types_struct_simple(s(bool,u32))'); + expect(fn.selector).toEqual('0x000000005497d4b2'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 19, 116, 121, 112, 101, 115, 95, 115, 116, 114, 117, 99, 116, 95, + 115, 105, 109, 112, 108, 101, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_struct_generic', () => { + it('should encode/decode just fine', async () => { + const input = { a: 10 }; + const expected = { a: 20 }; + + const { waitForResult } = await contract.functions.types_struct_generic(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_struct_generic'); + + expect(fn.name).toBe('types_struct_generic'); + expect(fn.signature).toEqual('types_struct_generic(s(u8))'); + expect(fn.selector).toEqual('0x000000007b2086ec'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 20, 116, 121, 112, 101, 115, 95, 115, 116, 114, 117, 99, 116, 95, + 103, 101, 110, 101, 114, 105, 99, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_struct_with_tuple', () => { + it('should encode/decode just fine', async () => { + const input: StructSingleGenericInput<[boolean, BigNumberish]> = { a: [true, 10] }; + // @ts-expect-error: Custom matcher 'toEqualBn' + const expected = { a: [false, expect.toEqualBn(20)] }; + + const { waitForResult } = await contract.functions.types_struct_with_tuple(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_struct_with_tuple'); + + expect(fn.name).toBe('types_struct_with_tuple'); + expect(fn.signature).toEqual('types_struct_with_tuple(s<(bool,u64)>((bool,u64)))'); + expect(fn.selector).toEqual('0x00000000adeb6dfa'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 23, 116, 121, 112, 101, 115, 95, 115, 116, 114, 117, 99, 116, 95, + 119, 105, 116, 104, 95, 116, 117, 112, 108, 101, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_struct_double_generic', () => { + it('should encode/decode just fine', async () => { + const input = { a: 10, b: { a: 10 } }; + const expected = { a: 20, b: { b: 10 } }; + + const { waitForResult } = await contract.functions.types_struct_double_generic(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_struct_double_generic'); + + expect(fn.name).toBe('types_struct_double_generic'); + expect(fn.signature).toEqual('types_struct_double_generic(s(u8,e(u8,u16)))'); + expect(fn.selector).toEqual('0x0000000096e85141'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 27, 116, 121, 112, 101, 115, 95, 115, 116, 114, 117, 99, 116, 95, + 100, 111, 117, 98, 108, 101, 95, 103, 101, 110, 101, 114, 105, 99, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_struct_external', () => { + it('should encode/decode just fine', async () => { + const input = { value: 10 }; + // @ts-expect-error: Custom matcher 'toEqualBn' + const expected = { value: expect.toEqualBn(20) }; + + const { waitForResult } = await contract.functions.types_struct_external(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_struct_external'); + + expect(fn.name).toBe('types_struct_external'); + expect(fn.signature).toEqual('types_struct_external(s(u64))'); + expect(fn.selector).toEqual('0x00000000080aff53'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 21, 116, 121, 112, 101, 115, 95, 115, 116, 114, 117, 99, 116, 95, + 101, 120, 116, 101, 114, 110, 97, 108, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_struct_with_implicit_generics', () => { + it('should encode/decode just fine', async () => { + const INPUT_B256 = '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; + const INPUT: StructWithImplicitGenericsInput = { + a: [INPUT_B256, INPUT_B256, INPUT_B256], + b: [INPUT_B256, 10], + }; + + const EXPECTED_B256 = '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'; + + const EXPECTED: StructWithImplicitGenericsInput = { + a: [EXPECTED_B256, EXPECTED_B256, EXPECTED_B256], + b: [EXPECTED_B256, 25], + }; + + const { waitForResult } = await contract.functions + .types_struct_with_implicit_generics(INPUT) + .call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(EXPECTED); + expect(logs).toStrictEqual([EXPECTED]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_struct_with_implicit_generics'); + + expect(fn.name).toBe('types_struct_with_implicit_generics'); + expect(fn.signature).toEqual( + 'types_struct_with_implicit_generics(s(a[b256;3],(b256,u8)))' + ); + expect(fn.selector).toEqual('0x0000000099d41855'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 35, 116, 121, 112, 101, 115, 95, 115, 116, 114, 117, 99, 116, 95, + 119, 105, 116, 104, 95, 105, 109, 112, 108, 105, 99, 105, 116, 95, 103, 101, 110, 101, + 114, 105, 99, 115, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_struct_with_array', () => { + /** + * TODO: This is causing a generic to be left into the parsed format. + */ + it.skip('should encode/decode just fine', async () => { + // Inputs + const inputB256: string = + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; + const inputStruct: StructDoubleGenericInput = { + a: inputB256, + b: 10, + }; + const input: StructWithGenericArrayInput = { + a: [inputStruct, inputStruct, inputStruct], + }; + + // Expected + const expectedB256: string = + '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'; + const expectedStruct: StructDoubleGenericInput = { + a: expectedB256, + b: 20, + }; + const expected: StructWithGenericArrayInput = { + a: [expectedStruct, expectedStruct, expectedStruct], + }; + + const { waitForResult } = await contract.functions.types_struct_with_array(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_struct_with_array'); + + expect(fn.name).toBe('types_struct_with_array'); + expect(fn.signature).toEqual('types_struct_with_array(s(a[s(b256,u8);3]))'); + expect(fn.selector).toEqual('0x00000000b2b64104'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 23, 116, 121, 112, 101, 115, 95, 115, 116, 114, 117, 99, 116, 95, + 119, 105, 116, 104, 95, 97, 114, 114, 97, 121, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_struct_with_vector', () => { + it('should encode/decode just fine', async () => { + const input = { a: 1, b: [1, 2, 3] }; + const expected = { a: 3, b: [3, 2, 1] }; + + const { waitForResult } = await contract.functions.types_struct_with_vector(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_struct_with_vector'); + + expect(fn.name).toBe('types_struct_with_vector'); + expect(fn.signature).toEqual('types_struct_with_vector(s(u8,s(s(rawptr,u64),u64)))'); + expect(fn.selector).toEqual('0x000000007d0fb2b3'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 24, 116, 121, 112, 101, 115, 95, 115, 116, 114, 117, 99, 116, 95, + 119, 105, 116, 104, 95, 118, 101, 99, 116, 111, 114, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + /** + * TODO: Fix this test + * + * Currently the expected value is not correct + */ + describe('types_struct_with_array_of_enums', () => { + it.todo('should encode/decode just fine', async () => { + const input: StructWithEnumArrayInput = { + a: [EnumWithNativeInput.Checked, EnumWithNativeInput.Checked, EnumWithNativeInput.Checked], + }; + const expected: StructWithEnumArrayOutput = { + a: [ + EnumWithNativeOutput.Pending, + EnumWithNativeOutput.Pending, + EnumWithNativeOutput.Pending, + ], + }; + + const { waitForResult } = await contract.functions + .types_struct_with_array_of_enums(input) + .call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_struct_with_array_of_enums'); + + expect(fn.name).toBe('types_struct_with_array_of_enums'); + expect(fn.signature).toEqual('types_struct_with_array_of_enums(s(a[e((),());3]))'); + expect(fn.selector).toEqual('0x0000000096a7800d'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 32, 116, 121, 112, 101, 115, 95, 115, 116, 114, 117, 99, 116, 95, + 119, 105, 116, 104, 95, 97, 114, 114, 97, 121, 95, 111, 102, 95, 101, 110, 117, 109, 115, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_struct_with_nested_array', () => { + it('should encode/decode just fine', async () => { + const INPUT_STRUCT = { a: { a: 10 }, b: 'A' }; + const input: StructWithNestedArrayInput = { a: [INPUT_STRUCT, INPUT_STRUCT] }; + // @ts-expect-error: Custom matcher 'toEqualBn' + const EXPECTED_STRUCT = { a: { a: expect.toEqualBn(20) }, b: 'B' }; + const EXPECTED = { a: [EXPECTED_STRUCT, EXPECTED_STRUCT] }; + + const { waitForResult } = await contract.functions + .types_struct_with_nested_array(input) + .call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(EXPECTED); + expect(logs).toStrictEqual([EXPECTED]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_struct_with_nested_array'); + + expect(fn.name).toBe('types_struct_with_nested_array'); + expect(fn.signature).toEqual( + 'types_struct_with_nested_array(s(a[s(u64),str[1]>(s(u64),str[1]);2]))' + ); + expect(fn.selector).toEqual('0x00000000199261fa'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 30, 116, 121, 112, 101, 115, 95, 115, 116, 114, 117, 99, 116, 95, + 119, 105, 116, 104, 95, 110, 101, 115, 116, 101, 100, 95, 97, 114, 114, 97, 121, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_struct_with_nested_tuple', () => { + it('should encode/decode just fine', async () => { + const input: StructWithNestedTupleInput = { a: [10, { a: { a: 20 } }, 'ABC'] }; + // @ts-expect-error: Custom matcher 'toEqualBn' + const expected = { a: [30, { a: { a: expect.toEqualBn(40) } }, 'CBA'] }; + + const { waitForResult } = await contract.functions + .types_struct_with_nested_tuple(input) + .call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_struct_with_nested_tuple'); + + expect(fn.name).toBe('types_struct_with_nested_tuple'); + expect(fn.signature).toEqual( + 'types_struct_with_nested_tuple(s((u8,s(u64)>(s(u64)),str[3])))' + ); + expect(fn.selector).toEqual('0x000000007fb152f7'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 30, 116, 121, 112, 101, 115, 95, 115, 116, 114, 117, 99, 116, 95, + 119, 105, 116, 104, 95, 110, 101, 115, 116, 101, 100, 95, 116, 117, 112, 108, 101, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_struct_with_nested_struct', () => { + it('should encode/decode just fine', async () => { + const input = { a: { a: { a: 10 }, b: 20 } }; + const expected = { a: { a: { a: 30 }, b: 40 } }; + + const { waitForResult } = await contract.functions + .types_struct_with_nested_struct(input) + .call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_struct_with_nested_struct'); + + expect(fn.name).toBe('types_struct_with_nested_struct'); + expect(fn.signature).toEqual( + 'types_struct_with_nested_struct(s(s(u8),u16>(s(u8),u16)))' + ); + expect(fn.selector).toEqual('0x00000000511602c7'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 31, 116, 121, 112, 101, 115, 95, 115, 116, 114, 117, 99, 116, 95, + 119, 105, 116, 104, 95, 110, 101, 115, 116, 101, 100, 95, 115, 116, 114, 117, 99, 116, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_struct_with_multiple_struct_params', () => { + it.todo('should encode/decode just fine', async () => { + const STRUCT_A = { propA1: 10 }; + const STRUCT_B = { propB1: STRUCT_A, propB2: 20 }; + + const INPUT_X = STRUCT_A; + const INPUT_Y = STRUCT_B; + const INPUT_Z: StructCInput = { + propC1: STRUCT_A, + propC2: [STRUCT_B], + propC3: { + propD1: [{ propE1: STRUCT_A, propE2: STRUCT_B, propE3: 30 }], + propD2: 40, + propD3: { propF1: 50, propF2: 'A' }, + }, + }; + + const { waitForResult } = await contract.functions + .types_struct_with_multiple_struct_params(INPUT_X, INPUT_Y, INPUT_Z) + .call(); + + await waitForResult(); + // const { value, logs } = await waitForResult(); + // expect(value).toStrictEqual(expected); + // expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_struct_with_multiple_struct_params'); + + expect(fn.name).toBe('types_struct_with_multiple_struct_params'); + expect(fn.signature).toEqual( + 'types_struct_with_multiple_struct_params(s(u8),s(s(u8),u16),s(s(u8),s(s(rawptr,u64),u64),s(u64,str[1])>(s(s(u8),s(s(u8),u16),u8)>(s(s(u8),s(s(u8),u16),u8)>(rawptr,u64),u64),u8,s(u64,str[1]))))' + ); + expect(fn.selector).toEqual('0x00000000c61458a4'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 40, 116, 121, 112, 101, 115, 95, 115, 116, 114, 117, 99, 116, 95, + 119, 105, 116, 104, 95, 109, 117, 108, 116, 105, 112, 108, 101, 95, 115, 116, 114, 117, + 99, 116, 95, 112, 97, 114, 97, 109, 115, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_struct_with_complex_nested_struct', () => { + it.todo('should encode/decode just fine'); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_struct_with_complex_nested_struct'); + + expect(fn.name).toBe('types_struct_with_complex_nested_struct'); + expect(fn.signature).toEqual( + 'types_struct_with_complex_nested_struct(s(s(rawptr,u64),u64)>(u64,s(s(rawptr,u64),u64))>(s(s(u8),s(s(u8),u16),u32)>(s(s(u8),s(s(u8),u16),u32)>(rawptr,u64),u64),u32,s(s(rawptr,u64),u64)>(u64,s(s(rawptr,u64),u64))))' + ); + expect(fn.selector).toEqual('0x000000003bb27fd2'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 39, 116, 121, 112, 101, 115, 95, 115, 116, 114, 117, 99, 116, 95, + 119, 105, 116, 104, 95, 99, 111, 109, 112, 108, 101, 120, 95, 110, 101, 115, 116, 101, + 100, 95, 115, 116, 114, 117, 99, 116, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_struct_with_single_option', () => { + it('should encode/decode just fine', async () => { + const input: StructWithSingleOptionInput = { + a: { + a: [1, undefined, 2, undefined, 3], + }, + }; + const expected: StructWithSingleOptionOutput = { + a: undefined, + }; + + const { waitForResult } = await contract.functions + .types_struct_with_single_option(input) + .call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_struct_with_single_option'); + + expect(fn.name).toBe('types_struct_with_single_option'); + expect(fn.signature).toEqual( + 'types_struct_with_single_option(s(e((),u8);5])>((),s(a[e((),u8);5]))))' + ); + expect(fn.selector).toEqual('0x000000003ec1dd13'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 31, 116, 121, 112, 101, 115, 95, 115, 116, 114, 117, 99, 116, 95, + 119, 105, 116, 104, 95, 115, 105, 110, 103, 108, 101, 95, 111, 112, 116, 105, 111, 110, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + /** + * Tuples + */ + describe('types_tuple', () => { + it('should encode/decode just fine', async () => { + const input = [1, 2, 3] as [number, number, number]; + const expected = [3, 2, 1] as [number, number, number]; + + const { waitForResult } = await contract.functions.types_tuple(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_tuple'); + + expect(fn.name).toBe('types_tuple'); + expect(fn.signature).toEqual('types_tuple((u8,u8,u8))'); + expect(fn.selector).toEqual('0x00000000d4afe0f7'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 11, 116, 121, 112, 101, 115, 95, 116, 117, 112, 108, 101, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_tuple_complex', () => { + it('should encode/decode just fine', async () => { + const input = [1, { a: { a: 10 } }, 'ABC'] as [ + BigNumberish, + StructSingleGenericInput>, + string, + ]; + // @ts-expect-error: Custom matcher 'toEqualBn' + const expected = [3, { a: { a: expect.toEqualBn(30) } }, 'CBA']; + + const { waitForResult } = await contract.functions.types_tuple_complex(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_tuple_complex'); + + expect(fn.name).toBe('types_tuple_complex'); + expect(fn.signature).toEqual('types_tuple_complex((u8,s(u64)>(s(u64)),str[3]))'); + expect(fn.selector).toEqual('0x000000003976bc45'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 19, 116, 121, 112, 101, 115, 95, 116, 117, 112, 108, 101, 95, 99, + 111, 109, 112, 108, 101, 120, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_tuple_with_native_types', () => { + it('should encode/decode just fine', async () => { + const A: AssetId = { + bits: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + }; + const B: AssetId = { + bits: '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', + }; + const input = [A, B, true] as [AssetIdInput, AssetIdInput, boolean]; + const expected = [B, A, false]; + + const { waitForResult } = await contract.functions + .types_tuple_with_native_types(input) + .call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_tuple_with_native_types'); + + expect(fn.name).toBe('types_tuple_with_native_types'); + expect(fn.signature).toEqual('types_tuple_with_native_types((s(b256),s(b256),bool))'); + expect(fn.selector).toEqual('0x0000000070139504'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 29, 116, 121, 112, 101, 115, 95, 116, 117, 112, 108, 101, 95, 119, + 105, 116, 104, 95, 110, 97, 116, 105, 118, 101, 95, 116, 121, 112, 101, 115, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_alias_tuple_with_native_types', () => { + it('should encode/decode just fine', async () => { + const A: AssetId = { + bits: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + }; + const B: AssetId = { + bits: '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', + }; + const input = [A, B, true] as [AssetIdInput, AssetIdInput, boolean]; + const expected = [B, A, false]; + + const { waitForResult } = await contract.functions + .types_alias_tuple_with_native_types(input) + .call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_alias_tuple_with_native_types'); + + expect(fn.name).toBe('types_alias_tuple_with_native_types'); + expect(fn.signature).toEqual('types_alias_tuple_with_native_types((s(b256),s(b256),bool))'); + expect(fn.selector).toEqual('0x00000000f1230bbf'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 35, 116, 121, 112, 101, 115, 95, 97, 108, 105, 97, 115, 95, 116, 117, + 112, 108, 101, 95, 119, 105, 116, 104, 95, 110, 97, 116, 105, 118, 101, 95, 116, 121, 112, + 101, 115, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + /** + * Enums + */ + describe('types_enum', () => { + it('should encode/decode just fine', async () => { + const input = EnumWithNativeInput.Checked; + const expected = EnumWithNativeInput.Pending; + + const { waitForResult } = await contract.functions.types_enum(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_enum'); + + expect(fn.name).toBe('types_enum'); + expect(fn.signature).toEqual('types_enum(e((),()))'); + expect(fn.selector).toEqual('0x000000003227c41f'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 10, 116, 121, 112, 101, 115, 95, 101, 110, 117, 109]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_enum_with_builtin_type', () => { + it('should encode/decode just fine', async () => { + const input: EnumWithBuiltinTypeInput = { a: true }; + // @ts-expect-error: Custom matcher 'toEqualBn' + const expected: EnumWithBuiltinTypeOutput = { b: expect.toEqualBn(20) }; + + const { waitForResult } = await contract.functions.types_enum_with_builtin_type(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_enum_with_builtin_type'); + + expect(fn.name).toBe('types_enum_with_builtin_type'); + expect(fn.signature).toEqual('types_enum_with_builtin_type(e(bool,u64))'); + expect(fn.selector).toEqual('0x000000000d46aae9'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 28, 116, 121, 112, 101, 115, 95, 101, 110, 117, 109, 95, 119, 105, + 116, 104, 95, 98, 117, 105, 108, 116, 105, 110, 95, 116, 121, 112, 101, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_enum_with_vector', () => { + it('should encode/decode just fine', async () => { + const input: EnumWithVectorInput = { a: 10 }; + const expected: EnumWithVectorOutput = { b: [1, 2, 3] }; + + const { waitForResult } = await contract.functions.types_enum_with_vector(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_enum_with_vector'); + + expect(fn.name).toBe('types_enum_with_vector'); + expect(fn.signature).toEqual('types_enum_with_vector(e(u8,s(s(rawptr,u64),u64)))'); + expect(fn.selector).toEqual('0x000000002cbc0dda'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 22, 116, 121, 112, 101, 115, 95, 101, 110, 117, 109, 95, 119, 105, + 116, 104, 95, 118, 101, 99, 116, 111, 114, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_generic_enum', () => { + it('should encode/decode just fine', async () => { + const input = { a: 10 }; + const expected = { b: 20 }; + + const { waitForResult } = await contract.functions.types_generic_enum(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_generic_enum'); + + expect(fn.name).toBe('types_generic_enum'); + expect(fn.signature).toEqual('types_generic_enum(e(u8,u16))'); + expect(fn.selector).toEqual('0x0000000097aaba95'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 18, 116, 121, 112, 101, 115, 95, 103, 101, 110, 101, 114, 105, 99, + 95, 101, 110, 117, 109, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_enum_external', () => { + it('should encode/decode just fine', async () => { + const input = ExternalEnumInput.A; + const expected = ExternalEnumInput.B; + + const { waitForResult } = await contract.functions.types_enum_external(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_enum_external'); + + expect(fn.name).toBe('types_enum_external'); + expect(fn.signature).toEqual('types_enum_external(e((),()))'); + expect(fn.selector).toEqual('0x0000000085288d18'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 19, 116, 121, 112, 101, 115, 95, 101, 110, 117, 109, 95, 101, 120, + 116, 101, 114, 110, 97, 108, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_enum_with_structs', () => { + it('should encode/decode just fine', async () => { + const input = { a: EnumWithNativeInput.Checked }; + const expected = { b: { a: true, b: 10 } }; + + const { waitForResult } = await contract.functions.types_enum_with_structs(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_enum_with_structs'); + + expect(fn.name).toBe('types_enum_with_structs'); + expect(fn.signature).toEqual( + 'types_enum_with_structs(e(e((),()),s(bool,u32),s(u64,s(bool,u32))))' + ); + expect(fn.selector).toEqual('0x000000005da5a1c9'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 23, 116, 121, 112, 101, 115, 95, 101, 110, 117, 109, 95, 119, 105, + 116, 104, 95, 115, 116, 114, 117, 99, 116, 115, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + /** + * Vectors + */ + describe('types_vector_u8', () => { + it('should encode/decode just fine', async () => { + const input = [1, 2, 3]; + const expected = [3, 2, 1]; + + const { waitForResult } = await contract.functions.types_vector_u8(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_vector_u8'); + + expect(fn.name).toBe('types_vector_u8'); + expect(fn.signature).toEqual('types_vector_u8(s(s(rawptr,u64),u64))'); + expect(fn.selector).toEqual('0x00000000c6e0e9a2'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 15, 116, 121, 112, 101, 115, 95, 118, 101, 99, 116, 111, 114, 95, + 117, 56, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_vector_boolean', () => { + it('should encode/decode just fine', async () => { + const input = [true, false, true, false]; + const expected = [false, true, false, true]; + + const { waitForResult } = await contract.functions.types_vector_boolean(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_vector_boolean'); + + expect(fn.name).toBe('types_vector_boolean'); + expect(fn.signature).toEqual('types_vector_boolean(s(s(rawptr,u64),u64))'); + expect(fn.selector).toEqual('0x0000000056c4f119'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 20, 116, 121, 112, 101, 115, 95, 118, 101, 99, 116, 111, 114, 95, 98, + 111, 111, 108, 101, 97, 110, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_vector_inside_vector', () => { + it('should encode/decode just fine', async () => { + const input = [[1, 2, 3]]; + const expected = [ + [3, 2, 1], + [6, 5, 4], + ]; + + const { waitForResult } = await contract.functions.types_vector_inside_vector(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_vector_inside_vector'); + + expect(fn.name).toBe('types_vector_inside_vector'); + expect(fn.signature).toEqual( + 'types_vector_inside_vector(s(s(rawptr,u64),u64)>(s(s(rawptr,u64),u64)>(rawptr,u64),u64))' + ); + expect(fn.selector).toEqual('0x00000000c40617f1'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 26, 116, 121, 112, 101, 115, 95, 118, 101, 99, 116, 111, 114, 95, + 105, 110, 115, 105, 100, 101, 95, 118, 101, 99, 116, 111, 114, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_vector_with_struct', () => { + it('should encode/decode just fine', async () => { + const input = [{ a: true, b: 10 }]; + const expected = [{ a: false, b: 30 }]; + + const { waitForResult } = await contract.functions.types_vector_with_struct(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_vector_with_struct'); + + expect(fn.name).toBe('types_vector_with_struct'); + expect(fn.signature).toEqual( + 'types_vector_with_struct(s(s(rawptr,u64),u64))' + ); + expect(fn.selector).toEqual('0x000000006c28b333'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 24, 116, 121, 112, 101, 115, 95, 118, 101, 99, 116, 111, 114, 95, + 119, 105, 116, 104, 95, 115, 116, 114, 117, 99, 116, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_vector_option', () => { + it('should encode/decode just fine', async () => { + const input: Vec = [{ a: [1, 2, 3, 4, 5] }]; + const expected: Vec = [{ a: [5, 4, 3, 2, 1] }]; + + const { waitForResult } = await contract.functions.types_vector_option(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_vector_option'); + + expect(fn.name).toBe('types_vector_option'); + expect(fn.signature).toEqual( + 'types_vector_option(s((),u8);5])>(s((),u8);5])>(rawptr,u64),u64))' + ); + expect(fn.selector).toEqual('0x000000007d911a50'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 19, 116, 121, 112, 101, 115, 95, 118, 101, 99, 116, 111, 114, 95, + 111, 112, 116, 105, 111, 110, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + /** + * Options + */ + describe('types_option', () => { + it('should encode/decode just fine', async () => { + const input: Option = 10; // Some + const expected: Option = undefined; // None + + const { waitForResult } = await contract.functions.types_option(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_option'); + + expect(fn.name).toBe('types_option'); + expect(fn.signature).toEqual('types_option(e((),u8))'); + expect(fn.selector).toEqual('0x000000004f547ea4'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 12, 116, 121, 112, 101, 115, 95, 111, 112, 116, 105, 111, 110, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_option_struct', () => { + it('should encode/decode just fine', async () => { + const input: Option = { + a: true, + b: 10, + }; + const expected: Option = undefined; + + const { waitForResult } = await contract.functions.types_option_struct(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_option_struct'); + + expect(fn.name).toBe('types_option_struct'); + expect(fn.signature).toEqual('types_option_struct(e((),s(bool,u32)))'); + expect(fn.selector).toEqual('0x000000003d47e5fd'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 19, 116, 121, 112, 101, 115, 95, 111, 112, 116, 105, 111, 110, 95, + 115, 116, 114, 117, 99, 116, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + /** + * Native types + */ + describe('types_identity_address', () => { + it('should encode/decode just fine', async () => { + const input: IdentityInput = { + Address: { bits: '0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' }, + }; + const expected: IdentityOutput = { + Address: { bits: '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' }, + }; + + const { waitForResult } = await contract.functions.types_identity_address(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_identity_address'); + + expect(fn.name).toBe('types_identity_address'); + expect(fn.signature).toEqual('types_identity_address(e(s(b256),s(b256)))'); + expect(fn.selector).toEqual('0x00000000aa402b49'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 22, 116, 121, 112, 101, 115, 95, 105, 100, 101, 110, 116, 105, 116, + 121, 95, 97, 100, 100, 114, 101, 115, 115, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_identity_contract_id', () => { + it('should encode/decode just fine', async () => { + const input: IdentityInput = { + ContractId: { bits: '0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' }, + }; + const expected: IdentityOutput = { + ContractId: { bits: '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' }, + }; + + const { waitForResult } = await contract.functions.types_identity_contract_id(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_identity_contract_id'); + + expect(fn.name).toBe('types_identity_contract_id'); + expect(fn.signature).toEqual('types_identity_contract_id(e(s(b256),s(b256)))'); + expect(fn.selector).toEqual('0x00000000b133fa5b'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 26, 116, 121, 112, 101, 115, 95, 105, 100, 101, 110, 116, 105, 116, + 121, 95, 99, 111, 110, 116, 114, 97, 99, 116, 95, 105, 100, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_address', () => { + it('should encode/decode just fine', async () => { + const input = { bits: '0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' }; + const expected = { + bits: '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', + }; + + const { waitForResult } = await contract.functions.types_address(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_address'); + + expect(fn.name).toBe('types_address'); + expect(fn.signature).toEqual('types_address(s(b256))'); + expect(fn.selector).toEqual('0x000000005b7bb428'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 13, 116, 121, 112, 101, 115, 95, 97, 100, 100, 114, 101, 115, 115, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_contract_id', () => { + it('should encode/decode just fine', async () => { + const input = { bits: '0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' }; + const expected = { + bits: '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', + }; + + const { waitForResult } = await contract.functions.types_contract_id(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_contract_id'); + + expect(fn.name).toBe('types_contract_id'); + expect(fn.signature).toEqual('types_contract_id(s(b256))'); + expect(fn.selector).toEqual('0x0000000051bcfff5'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 17, 116, 121, 112, 101, 115, 95, 99, 111, 110, 116, 114, 97, 99, 116, + 95, 105, 100, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_asset_id', () => { + it('should encode/decode just fine', async () => { + const input: AssetId = { + bits: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + }; + const expected: AssetId = { + bits: '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', + }; + + const { waitForResult } = await contract.functions.types_asset_id(input).call(); + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_asset_id'); + + expect(fn.name).toBe('types_asset_id'); + expect(fn.signature).toEqual('types_asset_id(s(b256))'); + expect(fn.selector).toEqual('0x00000000bdd1d050'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 14, 116, 121, 112, 101, 115, 95, 97, 115, 115, 101, 116, 95, 105, + 100, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_evm_address', () => { + it('should encode/decode just fine', async () => { + const input: EvmAddress = { + bits: '0x000000000000000000000000AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', + }; + const expected = { + bits: '0x000000000000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', + }; + + const { waitForResult } = await contract.functions.types_evm_address(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_evm_address'); + + expect(fn.name).toBe('types_evm_address'); + expect(fn.signature).toEqual('types_evm_address(s(b256))'); + expect(fn.selector).toEqual('0x00000000727fec9d'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 17, 116, 121, 112, 101, 115, 95, 101, 118, 109, 95, 97, 100, 100, + 114, 101, 115, 115, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_result', () => { + it('should accept result just fine [Ok - 10]', async () => { + const input: Result = { + Ok: 10, + }; + const expected: Result = { + // @ts-expect-error: Custom matcher 'toEqualBn' + Ok: expect.toEqualBn(2), + }; + + const { waitForResult } = await contract.functions.types_result(input).call(); + + const { value } = await waitForResult(); + expect(value).toStrictEqual(expected); + }); + + it('should accept result just fine [Err - divide by zero]', async () => { + const input: Result = { + Ok: 0, + }; + const expected: Result = { + Err: 'DivisError', + }; + + const { waitForResult } = await contract.functions.types_result(input).call(); + + const { value } = await waitForResult(); + expect(value).toStrictEqual(expected); + }); + + it('should accept result just fine [Err - 10]', async () => { + const input: Result = { + Err: 10, + }; + const expected: Result = { + Err: 'InputError', + }; + + const { waitForResult } = await contract.functions.types_result(input).call(); + + const { value } = await waitForResult(); + expect(value).toStrictEqual(expected); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_result'); + + expect(fn.name).toBe('types_result'); + expect(fn.signature).toEqual('types_result(e(u64,u32))'); + expect(fn.selector).toEqual('0x00000000ec4468f8'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 12, 116, 121, 112, 101, 115, 95, 114, 101, 115, 117, 108, 116, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + /** + * Void + */ + describe('types_void', () => { + it('should encode/decode just fine', async () => { + const input = undefined; + const expected = undefined; + + const { waitForResult } = await contract.functions.types_void(input).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should encode/decode just fine [omit optional args]', async () => { + const expected = undefined; + + const { waitForResult } = await contract.functions.types_void().call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_void'); + + expect(fn.name).toBe('types_void'); + expect(fn.signature).toEqual('types_void(())'); + expect(fn.selector).toEqual('0x00000000fd833d6f'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 10, 116, 121, 112, 101, 115, 95, 118, 111, 105, 100]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_void_then_value', () => { + it('should encode/decode just fine', async () => { + const inputX = undefined; + const inputY = 10; + const expected = undefined; + + const { waitForResult } = await contract.functions + .types_void_then_value(inputX, inputY) + .call(); + + const { value } = await waitForResult(); + expect(value).toBe(expected); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_void_then_value'); + + expect(fn.name).toBe('types_void_then_value'); + expect(fn.signature).toEqual('types_void_then_value((),u8)'); + expect(fn.selector).toEqual('0x0000000027599008'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 21, 116, 121, 112, 101, 115, 95, 118, 111, 105, 100, 95, 116, 104, + 101, 110, 95, 118, 97, 108, 117, 101, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_value_then_void', () => { + it('should encode/decode just fine', async () => { + const inputX = 10; + const inputY = undefined; + const { waitForResult } = await contract.functions + .types_value_then_void(inputX, inputY) + .call(); + + const { value } = await waitForResult(); + expect(value).toBeUndefined(); + }); + + it('should encode/decode just fine [omitting optional args]', async () => { + const inputX = 10; + + const { waitForResult } = await contract.functions.types_value_then_void(inputX).call(); + + const { value } = await waitForResult(); + expect(value).toBeUndefined(); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_value_then_void'); + + expect(fn.name).toBe('types_value_then_void'); + expect(fn.signature).toEqual('types_value_then_void(u8,())'); + expect(fn.selector).toEqual('0x00000000fe7792d4'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 21, 116, 121, 112, 101, 115, 95, 118, 97, 108, 117, 101, 95, 116, + 104, 101, 110, 95, 118, 111, 105, 100, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_value_then_void_then_value', () => { + it('should encode/decode just fine', async () => { + const inputX = 10; + const inputY = undefined; + const inputZ = 20; + + const { waitForResult } = await contract.functions + .types_value_then_void_then_value(inputX, inputY, inputZ) + .call(); + + const { value } = await waitForResult(); + expect(value).toBeUndefined(); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_value_then_void_then_value'); + + expect(fn.name).toBe('types_value_then_void_then_value'); + expect(fn.signature).toEqual('types_value_then_void_then_value(u8,(),u8)'); + expect(fn.selector).toEqual('0x000000005c3c9a25'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 32, 116, 121, 112, 101, 115, 95, 118, 97, 108, 117, 101, 95, 116, + 104, 101, 110, 95, 118, 111, 105, 100, 95, 116, 104, 101, 110, 95, 118, 97, 108, 117, 101, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('types_value_then_value_then_void_then_void', () => { + it('should encode/decode just fine', async () => { + const inputX = 10; + const inputY = 20; + const inputZ = undefined; + const inputA = undefined; + + const { waitForResult } = await contract.functions + .types_value_then_value_then_void_then_void(inputX, inputY, inputZ, inputA) + .call(); + + const { value } = await waitForResult(); + expect(value).toBeUndefined(); + }); + + it('should encode/decode just fine [omitting optional args]', async () => { + const inputX = 10; + const inputY = 20; + + const { waitForResult } = await contract.functions + .types_value_then_value_then_void_then_void(inputX, inputY) + .call(); + + const { value } = await waitForResult(); + expect(value).toBeUndefined(); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('types_value_then_value_then_void_then_void'); + + expect(fn.name).toBe('types_value_then_value_then_void_then_void'); + expect(fn.signature).toEqual('types_value_then_value_then_void_then_void(u8,u8,(),())'); + expect(fn.selector).toEqual('0x00000000ef0dd323'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 42, 116, 121, 112, 101, 115, 95, 118, 97, 108, 117, 101, 95, 116, + 104, 101, 110, 95, 118, 97, 108, 117, 101, 95, 116, 104, 101, 110, 95, 118, 111, 105, 100, + 95, 116, 104, 101, 110, 95, 118, 111, 105, 100, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + /** + * Multi-arg + */ + describe('multi_arg_u64_u64', () => { + it('should encode/decode just fine', async () => { + const inputX = 1; + const inputY = 2; + // @ts-expect-error: Custom matcher 'toEqualBn' + const expected = expect.toEqualBn(3); + + const { waitForResult } = await contract.functions.multi_arg_u64_u64(inputX, inputY).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('multi_arg_u64_u64'); + + expect(fn.name).toBe('multi_arg_u64_u64'); + expect(fn.signature).toEqual('multi_arg_u64_u64(u64,u64)'); + expect(fn.selector).toEqual('0x000000008da21283'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 17, 109, 117, 108, 116, 105, 95, 97, 114, 103, 95, 117, 54, 52, 95, + 117, 54, 52, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('multi_arg_b256_bool', () => { + it('should encode/decode just fine', async () => { + const inputX = '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; + const inputY = true; + const expected = [ + '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', + false, + ]; + + const { waitForResult } = await contract.functions.multi_arg_b256_bool(inputX, inputY).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('multi_arg_b256_bool'); + + expect(fn.name).toBe('multi_arg_b256_bool'); + expect(fn.signature).toEqual('multi_arg_b256_bool(b256,bool)'); + expect(fn.selector).toEqual('0x0000000087e6d52c'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 19, 109, 117, 108, 116, 105, 95, 97, 114, 103, 95, 98, 50, 53, 54, + 95, 98, 111, 111, 108, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('multi_arg_vector_vector', () => { + it('should encode/decode just fine', async () => { + const inputX = [1, 2, 3]; + const inputY = [4, 5, 6]; + const expected = [ + [7, 8, 9], + [10, 11, 12], + ]; + + const { waitForResult } = await contract.functions + .multi_arg_vector_vector(inputX, inputY) + .call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('multi_arg_vector_vector'); + + expect(fn.name).toBe('multi_arg_vector_vector'); + expect(fn.signature).toEqual( + 'multi_arg_vector_vector(s(s(rawptr,u64),u64),s(s(rawptr,u64),u64))' + ); + expect(fn.selector).toEqual('0x000000008f38c8a0'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 23, 109, 117, 108, 116, 105, 95, 97, 114, 103, 95, 118, 101, 99, 116, + 111, 114, 95, 118, 101, 99, 116, 111, 114, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('multi_arg_vector_b256', () => { + it('should encode/decode just fine', async () => { + const inputX = [1, 2, 3]; + const inputY = '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; + const expected = [ + [7, 8, 9], + '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', + ]; + + const { waitForResult } = await contract.functions + .multi_arg_vector_b256(inputX, inputY) + .call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('multi_arg_vector_b256'); + + expect(fn.name).toBe('multi_arg_vector_b256'); + expect(fn.signature).toEqual('multi_arg_vector_b256(s(s(rawptr,u64),u64),b256)'); + expect(fn.selector).toEqual('0x0000000031ca0fba'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 21, 109, 117, 108, 116, 105, 95, 97, 114, 103, 95, 118, 101, 99, 116, + 111, 114, 95, 98, 50, 53, 54, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('multi_arg_struct_vector', () => { + it('should encode/decode just fine', async () => { + const inputX = { a: true, b: 1 }; + const inputY = [1, 2, 3]; + const expected = [{ a: false, b: 2 }, [4, 5, 6]]; + + const { waitForResult } = await contract.functions + .multi_arg_struct_vector(inputX, inputY) + .call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('multi_arg_struct_vector'); + + expect(fn.name).toBe('multi_arg_struct_vector'); + expect(fn.signature).toEqual( + 'multi_arg_struct_vector(s(bool,u32),s(s(rawptr,u64),u64))' + ); + expect(fn.selector).toEqual('0x00000000d63bf118'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 23, 109, 117, 108, 116, 105, 95, 97, 114, 103, 95, 115, 116, 114, + 117, 99, 116, 95, 118, 101, 99, 116, 111, 114, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('multi_arg_u64_struct', () => { + it('should encode/decode just fine', async () => { + const inputX = bn(99); + const inputY: StructSimpleInput = { a: true, b: 51 }; + const expected = [bn(3), { a: false, b: 4 }]; + + const { waitForResult } = await contract.functions + .multi_arg_u64_struct(inputX, inputY) + .call(); + + const { value, logs } = await waitForResult(); + expect(JSON.stringify(value)).toEqual(JSON.stringify(expected)); + expect(JSON.stringify(logs)).toEqual(JSON.stringify([expected])); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('multi_arg_u64_struct'); + + expect(fn.name).toBe('multi_arg_u64_struct'); + expect(fn.signature).toEqual('multi_arg_u64_struct(u64,s(bool,u32))'); + expect(fn.selector).toEqual('0x00000000259174ac'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 20, 109, 117, 108, 116, 105, 95, 97, 114, 103, 95, 117, 54, 52, 95, + 115, 116, 114, 117, 99, 116, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('multi_arg_str_str', () => { + it('should encode/decode just fine', async () => { + const inputX = 'Input'; + const inputY = 'False'; + + const expected = ['Fuuel', 'Niice']; + + const { waitForResult } = await contract.functions.multi_arg_str_str(inputX, inputY).call(); + + const { value, logs } = await waitForResult(); + expect(value).toStrictEqual(expected); + expect(logs).toStrictEqual([expected]); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('multi_arg_str_str'); + + expect(fn.name).toBe('multi_arg_str_str'); + expect(fn.signature).toEqual('multi_arg_str_str(str[5],str[5])'); + expect(fn.selector).toEqual('0x0000000001cf9e71'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 17, 109, 117, 108, 116, 105, 95, 97, 114, 103, 95, 115, 116, 114, 95, + 115, 116, 114, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('multi_arg_u32_vector_vector', () => { + it('should encode/decode just fine', async () => { + const inputX = 1; + const inputY = [bn(10020), bn(1231231), bn(777657)]; + const inputZ = [bn(99), bn(101)]; + + const expected = [2, [bn(7), bn(8), bn(9)], [bn(10), bn(11), bn(12)]]; + + const { waitForResult } = await contract.functions + .multi_arg_u32_vector_vector(inputX, inputY, inputZ) + .call(); + + const { value, logs } = await waitForResult(); + expect(JSON.stringify(value)).toEqual(JSON.stringify(expected)); + expect(JSON.stringify(logs)).toEqual(JSON.stringify([expected])); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('multi_arg_u32_vector_vector'); + + expect(fn.name).toBe('multi_arg_u32_vector_vector'); + expect(fn.signature).toEqual( + 'multi_arg_u32_vector_vector(u32,s(s(rawptr,u64),u64),s(s(rawptr,u64),u64))' + ); + expect(fn.selector).toEqual('0x000000003f794313'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 27, 109, 117, 108, 116, 105, 95, 97, 114, 103, 95, 117, 51, 50, 95, + 118, 101, 99, 116, 111, 114, 95, 118, 101, 99, 116, 111, 114, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); + + describe('multi_arg_complex', () => { + it('should encode/decode just fine', async () => { + const inputX: StructDoubleGenericInput<[string, string, string], number> = { + a: [ + '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb', + '0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', + ], + b: 10, + }; + + const inputY: [ + StructDoubleGenericInput, + StructDoubleGenericInput, + StructDoubleGenericInput, + StructDoubleGenericInput, + ] = [ + { a: bn(99), b: false }, + { a: bn(199), b: false }, + { a: bn(2000), b: false }, + { a: bn(31), b: true }, + ]; + + const inputZ: [string, boolean] = ['Input', true]; + + const inputA = { a: true, b: 10 }; + + const expectedX: StructDoubleGenericInput<[string, string, string], number> = { + a: [ + '0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', + '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', + '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', + ], + b: 99, + }; + + const expectedY: [ + StructDoubleGenericInput, + StructDoubleGenericInput, + StructDoubleGenericInput, + StructDoubleGenericInput, + ] = [ + { a: bn(11), b: true }, + { a: bn(99), b: true }, + { a: bn(567), b: true }, + { a: bn(971), b: false }, + ]; + + const expectedZ: [string, boolean] = ['tupni', false]; + + const expectedA = { + a: false, + b: 57, + }; + + const expected = [expectedX, expectedY, expectedZ, expectedA]; + + const { waitForResult } = await contract.functions + .multi_arg_complex(inputX, inputY, inputZ, inputA) + .call(); + + const { value, logs } = await waitForResult(); + expect(JSON.stringify(value)).toEqual(JSON.stringify(expected)); + expect(JSON.stringify(logs)).toEqual(JSON.stringify([expected])); + }); + + it('should have function properties', () => { + const fn = contract.interface.getFunction('multi_arg_complex'); + + expect(fn.name).toBe('multi_arg_complex'); + expect(fn.signature).toEqual( + 'multi_arg_complex(s(a[b256;3],u8),a[s(u64,bool);4],(str[5],bool),s(bool,u32))' + ); + expect(fn.selector).toEqual('0x00000000808afb73'); + expect(fn.selectorBytes).toEqual( + new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 17, 109, 117, 108, 116, 105, 95, 97, 114, 103, 95, 99, 111, 109, 112, + 108, 101, 120, + ]) + ); + expect(fn.attributes).toEqual([]); + }); + }); +}); diff --git a/packages/fuel-gauge/src/abi/constants.ts b/packages/fuel-gauge/src/abi/constants.ts new file mode 100644 index 00000000000..a81232d91c1 --- /dev/null +++ b/packages/fuel-gauge/src/abi/constants.ts @@ -0,0 +1,63 @@ +import { bn } from 'fuels'; + +export const U8_MIN = 0; +export const U8_MAX = 2 ** 8 - 1; +export const U8_MAX_ENCODED = new Uint8Array([255]); +export const U8_MIN_ENCODED = new Uint8Array([0]); +export const U16_MIN = 0; +export const U16_MAX = 2 ** 16 - 1; +export const U16_MAX_ENCODED = new Uint8Array([255, 255]); +export const U16_MIN_ENCODED = new Uint8Array([0, 0]); +export const U32_MIN = 0; +export const U32_MAX = 2 ** 32 - 1; +export const U32_MAX_ENCODED = new Uint8Array([255, 255, 255, 255]); +export const U32_MIN_ENCODED = new Uint8Array([0, 0, 0, 0]); +export const U64_MIN = 0; +export const U64_MAX = bn(2).pow(64).sub(1); +export const U64_MAX_ENCODED = new Uint8Array([255, 255, 255, 255, 255, 255, 255, 255]); +export const U64_MIN_ENCODED = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0]); +export const U256_MIN = 0; +export const U256_MAX = bn(2).pow(256).sub(1); +export const U256_MAX_ENCODED = new Uint8Array(32).fill(255); +export const U256_MIN_ENCODED = new Uint8Array(32).fill(0); + +export const EMPTY_8_BYTE_ARRAY = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0]); +export const ENUM_FIRST_INDEX = EMPTY_8_BYTE_ARRAY; +export const ENUM_SECOND_INDEX = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 1]); +export const ENUM_THIRD_INDEX = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 2]); + +export const STRING_MIN_DECODED = ''; +export const STRING_MIN_ENCODED = new Uint8Array(); +export const STRING_MAX_DECODED = 'a'.repeat(U8_MAX); +export const STRING_MAX_ENCODED = new Uint8Array([ + ...Array.from(Array(U8_MAX + 1).fill(97, 0, U8_MAX)), +]); + +export const B256_DECODED = '0xd5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b'; +export const B256_ENCODED = new Uint8Array([ + 213, 87, 156, 70, 223, 204, 127, 24, 32, 112, 19, 230, 91, 68, 228, 203, 78, 44, 34, 152, 244, + 172, 69, 123, 168, 248, 39, 67, 243, 30, 147, 11, +]); +export const B256_ZERO_DECODED = + '0x0000000000000000000000000000000000000000000000000000000000000000'; +export const B256_ZERO_ENCODED = new Uint8Array(32); + +export const BYTE_MIN_DECODED = 0; +export const BYTE_MIN_ENCODED = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0]); +export const BYTE_MAX_DECODED = U8_MAX; +export const BYTE_MAX_ENCODED = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 255]); + +export const BOOL_TRUE_ENCODED = new Uint8Array([1]); +export const BOOL_FALSE_ENCODED = new Uint8Array([0]); + +export const B512_DECODED = + '0x8e9dda6f7793745ac5aacf9e907cae30b2a01fdf0d23b7750a85c6a44fca0c29f0906f9d1f1e92e6a1fb3c3dcef3cc3b3cdbaae27e47b9d9a4c6a4fce4cf16b2'; +export const B512_ENCODED = new Uint8Array([ + 142, 157, 218, 111, 119, 147, 116, 90, 197, 170, 207, 158, 144, 124, 174, 48, 178, 160, 31, 223, + 13, 35, 183, 117, 10, 133, 198, 164, 79, 202, 12, 41, 240, 144, 111, 157, 31, 30, 146, 230, 161, + 251, 60, 61, 206, 243, 204, 59, 60, 219, 170, 226, 126, 71, 185, 217, 164, 198, 164, 252, 228, + 207, 22, 178, +]); +export const B512_ZERO_DECODED = + '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'; +export const B512_ZERO_ENCODED = new Uint8Array(64); diff --git a/packages/fuel-gauge/src/abi/vitest.matcher.ts b/packages/fuel-gauge/src/abi/vitest.matcher.ts new file mode 100644 index 00000000000..32a1cd3b4a8 --- /dev/null +++ b/packages/fuel-gauge/src/abi/vitest.matcher.ts @@ -0,0 +1,20 @@ +import { bn } from 'fuels'; +import type { BNInput } from 'fuels'; + +export const toEqualBn = (_received: BNInput, _argument: BNInput) => { + const received = bn(_received); + const argument = bn(_argument); + + const pass = received.eq(argument); + + if (pass) { + return { + message: () => `Expected ${received.toString()} not to equal ${argument.toString()}`, + pass: true, + }; + } + return { + message: () => `expected ${received.toString()} to equal ${argument.toString()}`, + pass: false, + }; +}; diff --git a/packages/fuel-gauge/test/fixtures/forc-projects/Forc.toml b/packages/fuel-gauge/test/fixtures/forc-projects/Forc.toml index f76d1d3d097..0c656a9f286 100644 --- a/packages/fuel-gauge/test/fixtures/forc-projects/Forc.toml +++ b/packages/fuel-gauge/test/fixtures/forc-projects/Forc.toml @@ -1,5 +1,6 @@ [workspace] members = [ + "abi-contract", "advanced-logging", "advanced-logging-abi", "advanced-logging-other-contract", diff --git a/packages/fuel-gauge/test/fixtures/forc-projects/abi-contract/Forc.toml b/packages/fuel-gauge/test/fixtures/forc-projects/abi-contract/Forc.toml new file mode 100644 index 00000000000..7e941f84b42 --- /dev/null +++ b/packages/fuel-gauge/test/fixtures/forc-projects/abi-contract/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["Fuel Labs "] +license = "Apache-2.0" +name = "abi-contract" + +[dependencies] +abi-library = { path = "../abi-library" } diff --git a/packages/fuel-gauge/test/fixtures/forc-projects/abi-contract/src/data_structures.sw b/packages/fuel-gauge/test/fixtures/forc-projects/abi-contract/src/data_structures.sw new file mode 100644 index 00000000000..5e7ec1e6938 --- /dev/null +++ b/packages/fuel-gauge/test/fixtures/forc-projects/abi-contract/src/data_structures.sw @@ -0,0 +1,136 @@ +library; + +pub struct Configurables { + pub U8_VALUE: u8, + pub BOOL_VALUE: bool, + pub B256_VALUE: b256, + pub OPTION_U8_VALUE: Option, + pub GENERIC_STRUCT_VALUE: StructDoubleGeneric, u32>, +} + +pub enum EnumWithNative { + pub Checked: (), + pub Pending: (), +} + +pub enum EnumWithVector { + pub a: u8, + pub b: Vec, +} + +pub enum EnumWithBuiltinType { + pub a: bool, + pub b: u64, +} + +pub enum EnumDoubleGeneric { + pub a: T1, + pub b: T2, +} + +pub enum EnumWithStructs { + pub a: EnumWithNative, + pub b: StructSimple, + pub c: StructDoubleGeneric, +} + +pub struct StructSimple { + pub a: bool, + pub b: u32, +} + +pub struct StructWithEnumArray { + pub a: [EnumWithNative; 3], +} + +pub struct StructWithMultiOption { + pub a: [Option; 5], +} + +pub struct StructWithSingleOption { + pub a: Option, +} + +pub struct StructWithVector { + pub a: u8, + pub b: Vec, +} + +pub struct StructSingleGeneric { + pub a: T, +} + +pub struct StructDoubleGeneric { + pub a: T1, + pub b: T2, +} + +pub struct StructGenericWithEnum { + pub a: T1, + pub b: EnumDoubleGeneric, +} + +pub struct StructWithImplicitGenerics { + pub a: [E; 3], + pub b: (E, F), +} + +pub struct StructWithGenericArray { + pub a: [StructDoubleGeneric; 3], +} + +pub struct StructWithNestedArray { + pub a: [StructDoubleGeneric, str[1]>; 2], +} + +pub struct StructWithNestedTuple { + pub a: (u8, StructSingleGeneric>, str[3]), +} + +pub struct StructWithNestedStruct { + pub a: StructDoubleGeneric, u16>, +} + +pub struct StructA { + pub propA1: u8, +} + +pub struct StructB { + pub propB1: StructA, + pub propB2: u16, +} + +pub struct StructC { + pub propC1: StructA, + pub propC2: Vec, + pub propC3: StructD>, + // propC4: Vec>>, + // propC5: Vec>>>, +} + +pub struct StructD { + pub propD1: Vec>, + pub propD2: U, + pub propD3: V, +} + +pub struct StructE { + pub propE1: StructA, + pub propE2: StructB, + pub propE3: T, +} + +pub struct StructF { + pub propF1: u64, + pub propF2: T, +} + +pub struct StructG { + pub propG1: u8, +} + +pub enum MyContractError { + pub DivisionByZero: (), +} + +pub type TupleWithNativeAssets = (AssetId, AssetId, bool); diff --git a/packages/fuel-gauge/test/fixtures/forc-projects/abi-contract/src/equality.sw b/packages/fuel-gauge/test/fixtures/forc-projects/abi-contract/src/equality.sw new file mode 100644 index 00000000000..d370a24cc28 --- /dev/null +++ b/packages/fuel-gauge/test/fixtures/forc-projects/abi-contract/src/equality.sw @@ -0,0 +1,481 @@ +library; + +use ::data_structures::*; +use core::ops::Eq; + +impl Eq for [u8; 4] { + fn eq(self, other: Self) -> bool { + self[0] == other[0] && self[1] == other[1] && self[2] == other[2] && self[3] == other[3] + } +} + +impl Eq for StructSimple { + fn eq(self, other: Self) -> bool { + self.a == other.a && self.b == other.b + } +} + +impl Eq for [StructSimple; 3] { + fn eq(self, other: Self) -> bool { + self[0] == other[0] && self[1] == other[1] && self[2] == other[2] + } +} + +impl Eq for StructSingleGeneric { + fn eq(self, other: Self) -> bool { + self.a == other.a + } +} + +impl Eq for [b256; 3] { + fn eq(self, other: Self) -> bool { + self[0] == other[0] && self[1] == other[1] && self[2] == other[2] + } +} + +impl Eq for (b256, u8) { + fn eq(self, other: Self) -> bool { + self.0 == other.0 && self.1 == other.1 + } +} + +impl Eq for str[1] { + fn eq(self, other: Self) -> bool { + from_str_array(self) == from_str_array(other) + } +} + +impl Eq for str[3] { + fn eq(self, other: Self) -> bool { + from_str_array(self) == from_str_array(other) + } +} + +impl Eq for str[5] { + fn eq(self, other: Self) -> bool { + from_str_array(self) == from_str_array(other) + } +} + +impl Eq for StructDoubleGeneric, str[1]> { + fn eq(self, other: Self) -> bool { + self.a == other.a && self.b == other.b + } +} + +impl Eq for StructDoubleGeneric { + fn eq(self, other: Self) -> bool { + self.a == other.a && self.b == other.b + } +} + +impl Eq for StructDoubleGeneric { + fn eq(self, other: Self) -> bool { + self.a == other.a + } +} + +impl Eq for [StructDoubleGeneric; 3] { + fn eq(self, other: Self) -> bool { + self[0] == other[0] && self[1] == other[1] && self[2] == other[2] + } +} + +impl Eq for [StructDoubleGeneric, str[1]>; 2] { + fn eq(self, other: Self) -> bool { + self[0] == other[0] && self[1] == other[1] + } +} + +impl Eq for [StructDoubleGeneric; 4] { + fn eq(self, other: Self) -> bool { + self[0] == other[0] && self[1] == other[1] && self[2] == other[2] && self[3] == other[3] + } +} + +impl Eq for StructSingleGeneric<[b256; 3]> { + fn eq(self, other: Self) -> bool { + self.a == other.a + } +} + +impl Eq for StructDoubleGeneric<[b256; 3], u8> { + fn eq(self, other: Self) -> bool { + self.a == other.a + } +} + +impl Eq for StructDoubleGeneric, u8> { + fn eq(self, other: Self) -> bool { + self.a == other.a && self.b == other.b + } +} + +impl Eq for Vec { + fn eq(self, other: Self) -> bool { + if self.len() != other.len() { + return false; + } + let mut i = 0; + while i < self.len() { + if self.get(i).unwrap() != other.get(i).unwrap() { + return false; + } + i += 1; + } + true + } +} + +impl Eq for Vec { + fn eq(self, other: Self) -> bool { + if self.len() != other.len() { + return false; + } + let mut i = 0; + while i < self.len() { + if self.get(i).unwrap() != other.get(i).unwrap() { + return false; + } + i += 1; + } + true + } +} + +impl Eq for [Vec; 1] { + fn eq(self, other: Self) -> bool { + self[0] == other[0] + } +} + +impl Eq for (u8, u8, u8) { + fn eq(self, other: Self) -> bool { + self.0 == other.0 && self.1 == other.1 && self.2 == other.2 + } +} + +impl Eq for StructSingleGeneric> { + fn eq(self, other: Self) -> bool { + self.a == other.a + } +} + +impl Eq for (u8, StructSingleGeneric>, str[3]) { + fn eq(self, other: Self) -> bool { + self.0 == other.0 && self.1 == other.1 && self.2 == other.2 + } +} + +impl Eq for (AssetId, AssetId, bool) { + fn eq(self, other: Self) -> bool { + self.0 == other.0 && self.1 == other.1 && self.2 == other.2 + } +} + +impl Eq for StructSingleGeneric { + fn eq(self, other: Self) -> bool { + self.a == other.a + } +} + +impl Eq for (bool, u64) { + fn eq(self, other: Self) -> bool { + self.0 == other.0 && self.1 == other.1 + } +} + +impl Eq for (str[5], bool) { + fn eq(self, other: Self) -> bool { + self.0 == other.0 && self.1 == other.1 + } +} + +impl Eq for StructSingleGeneric<(bool, u64)> { + fn eq(self, other: Self) -> bool { + self.a == other.a + } +} + +impl Eq for StructWithNestedArray { + fn eq(self, other: Self) -> bool { + self.a == other.a + } +} + +impl Eq for EnumDoubleGeneric { + fn eq(self, other: Self) -> bool { + match (self, other) { + (EnumDoubleGeneric::a(a), EnumDoubleGeneric::a(b)) => a == b, + (EnumDoubleGeneric::b(a), EnumDoubleGeneric::b(b)) => a == b, + _ => false, + } + } +} + +impl Eq for StructGenericWithEnum { + fn eq(self, other: Self) -> bool { + self.a == other.a && self.b == other.b + } +} + +impl Eq for StructWithNestedTuple { + fn eq(self, other: Self) -> bool { + self.a == other.a + } +} + +impl Eq for StructDoubleGeneric, u16> { + fn eq(self, other: Self) -> bool { + self.a == other.a && self.b == other.b + } +} + +impl Eq for StructWithNestedStruct { + fn eq(self, other: Self) -> bool { + self.a == other.a + } +} + +impl Eq for StructA { + fn eq(self, other: Self) -> bool { + self.propA1 == other.propA1 + } +} + +impl Eq for StructB { + fn eq(self, other: Self) -> bool { + self.propB1 == other.propB1 && self.propB2 == other.propB2 + } +} + +impl Eq for StructE { + fn eq(self, other: Self) -> bool { + self.propE1 == other.propE1 && self.propE2 == other.propE2 && self.propE3 == other.propE3 + } +} + +impl Eq for Vec> { + fn eq(self, other: Self) -> bool { + if self.len() != other.len() { + return false; + } + let mut i = 0; + while i < self.len() { + if self.get(i).unwrap() != other.get(i).unwrap() { + return false; + } + i += 1; + } + true + } +} + +impl Eq for StructF { + fn eq(self, other: Self) -> bool { + self.propF1 == other.propF1 && self.propF2 == other.propF2 + } +} + +impl Eq for StructD> { + fn eq(self, other: Self) -> bool { + self.propD1 == other.propD1 && self.propD2 == other.propD2 && self.propD3 == other.propD3 + } +} + +impl Eq for Vec { + fn eq(self, other: Self) -> bool { + if self.len() != other.len() { + return false; + } + let mut i = 0; + while i < self.len() { + if self.get(i).unwrap() != other.get(i).unwrap() { + return false; + } + i += 1; + } + true + } +} + +impl Eq for StructC { + fn eq(self, other: Self) -> bool { + self.propC1 == other.propC1 && self.propC2 == other.propC2 && self.propC3 == other.propC3 + } +} + +impl Eq for EnumWithNative { + fn eq(self, other: Self) -> bool { + match (self, other) { + (EnumWithNative::Checked, EnumWithNative::Checked) => true, + (EnumWithNative::Pending, EnumWithNative::Pending) => true, + _ => false, + } + } +} + +impl Eq for EnumWithBuiltinType { + fn eq(self, other: Self) -> bool { + match (self, other) { + (EnumWithBuiltinType::a(a), EnumWithBuiltinType::a(b)) => a == b, + (EnumWithBuiltinType::b(a), EnumWithBuiltinType::b(b)) => a == b, + _ => false, + } + } +} + +impl Eq for Vec { + fn eq(self, other: Self) -> bool { + if self.len() != other.len() { + return false; + } + let mut i = 0; + while i < self.len() { + if self.get(i).unwrap() != other.get(i).unwrap() { + return false; + } + i += 1; + } + true + } +} + +impl Eq for EnumWithVector { + fn eq(self, other: Self) -> bool { + match (self, other) { + (EnumWithVector::a(a), EnumWithVector::a(b)) => a == b, + (EnumWithVector::b(a), EnumWithVector::b(b)) => a == b, + _ => false, + } + } +} + +impl Eq for StructDoubleGeneric { + fn eq(self, other: Self) -> bool { + self.a == other.a && self.b == other.b + } +} + +impl Eq for EnumWithStructs { + fn eq(self, other: Self) -> bool { + match (self, other) { + (EnumWithStructs::a(a), EnumWithStructs::a(b)) => a == b, + (EnumWithStructs::b(a), EnumWithStructs::b(b)) => a == b, + (EnumWithStructs::c(a), EnumWithStructs::c(b)) => a == b, + _ => false, + } + } +} + +impl Eq for Vec { + fn eq(self, other: Self) -> bool { + if self.len() != other.len() { + return false; + } + let mut i = 0; + while i < self.len() { + if self.get(i).unwrap() != other.get(i).unwrap() { + return false; + } + i += 1; + } + true + } +} + +impl Eq for Vec> { + fn eq(self, other: Self) -> bool { + if self.len() != other.len() { + return false; + } + let mut i = 0; + while i < self.len() { + if self.get(i).unwrap() != other.get(i).unwrap() { + return false; + } + i += 1; + } + true + } +} + +impl Eq for Vec { + fn eq(self, other: Self) -> bool { + if self.len() != other.len() { + return false; + } + let mut i = 0; + while i < self.len() { + if self.get(i).unwrap() != other.get(i).unwrap() { + return false; + } + i += 1; + } + true + } +} + +impl Eq for [Option; 5] { + fn eq(self, other: Self) -> bool { + self[0] == other[0] && self[1] == other[1] && self[2] == other[2] && self[3] == other[3] && self[4] == other[4] + } +} + +impl Eq for StructWithMultiOption { + fn eq(self, other: Self) -> bool { + self.a == other.a + } +} + +impl Eq for Vec { + fn eq(self, other: Self) -> bool { + if self.len() != other.len() { + return false; + } + let mut i = 0; + while i < self.len() { + if self.get(i).unwrap() != other.get(i).unwrap() { + return false; + } + i += 1; + } + true + } +} + +impl Eq for StructWithGenericArray { + fn eq(self, other: Self) -> bool { + self.a == other.a + } +} + +impl Eq for StructWithImplicitGenerics { + fn eq(self, other: Self) -> bool { + self.a == other.a && self.b == other.b + } +} + +impl Eq for StructWithVector { + fn eq(self, other: Self) -> bool { + self.a == other.a && self.b == other.b + } +} + +impl Eq for [EnumWithNative; 3] { + fn eq(self, other: Self) -> bool { + self[0] == other[0] && self[1] == other[1] && self[2] == other[2] + } +} + +impl Eq for StructWithEnumArray { + fn eq(self, other: Self) -> bool { + self.a == other.a + } +} + +impl Eq for StructWithSingleOption { + fn eq(self, other: Self) -> bool { + self.a == other.a + } +} diff --git a/packages/fuel-gauge/test/fixtures/forc-projects/abi-contract/src/main.sw b/packages/fuel-gauge/test/fixtures/forc-projects/abi-contract/src/main.sw new file mode 100644 index 00000000000..afc7ebb063f --- /dev/null +++ b/packages/fuel-gauge/test/fixtures/forc-projects/abi-contract/src/main.sw @@ -0,0 +1,1155 @@ +contract; + +mod data_structures; +mod equality; +mod utils; + +use data_structures::*; +use equality::*; +use utils::*; + +use abi_library::ExternalStruct; +use abi_library::ExternalEnum; +use std::vm::evm::evm_address::EvmAddress; +use std::b512::B512; +use std::string::String; +use std::bytes::Bytes; + +fn divide(numerator: u64, denominator: u64) -> Result { + if (denominator == 0) { + return Err(MyContractError::DivisionByZero); + } else { + Ok(numerator / denominator) + } +} + +abi AbiContract { + fn configurables() -> Configurables; + + fn types_u8(x: u8) -> u8; + fn types_u16(x: u16) -> u16; + fn types_u32(x: u32) -> u32; + fn types_u64(x: u64) -> u64; + fn types_u256(x: u256) -> u256; + fn types_bool(x: bool) -> bool; + fn types_b256(x: b256) -> b256; + fn types_b512(x: B512) -> B512; + fn types_bytes(x: Bytes) -> Bytes; + + fn types_str(x: str[5]) -> str[5]; + fn types_str_slice(x: str) -> str; + fn types_raw_slice(x: raw_slice) -> raw_slice; + fn types_std_string(x: String) -> String; + + fn types_array(x: [u8; 4]) -> [u8; 4]; + fn types_array_struct(x: [StructSimple; 3]) -> [StructSimple; 3]; + fn types_array_with_generic_struct( + x: [StructDoubleGeneric, str[1]>; 2], + ) -> [StructDoubleGeneric, str[1]>; 2]; + fn types_array_with_vector(x: [Vec; 1]) -> [Vec; 1]; + + fn types_struct_simple(x: StructSimple) -> StructSimple; + fn types_struct_generic(x: StructSingleGeneric) -> StructSingleGeneric; + fn types_struct_with_tuple( + x: StructSingleGeneric<(bool, u64)>, + ) -> StructSingleGeneric<(bool, u64)>; + fn types_struct_double_generic( + x: StructGenericWithEnum, + ) -> StructGenericWithEnum; + fn types_struct_external(x: ExternalStruct) -> ExternalStruct; + fn types_struct_with_implicit_generics( + x: StructWithImplicitGenerics, + ) -> StructWithImplicitGenerics; + fn types_struct_with_array(x: StructWithGenericArray) -> StructWithGenericArray; + fn types_struct_with_vector(x: StructWithVector) -> StructWithVector; + fn types_struct_with_array_of_enums(x: StructWithEnumArray) -> StructWithEnumArray; + fn types_struct_with_nested_array(x: StructWithNestedArray) -> StructWithNestedArray; + fn types_struct_with_nested_tuple(x: StructWithNestedTuple) -> StructWithNestedTuple; + fn types_struct_with_nested_struct(x: StructWithNestedStruct) -> StructWithNestedStruct; + fn types_struct_with_multiple_struct_params(x: StructA, y: StructB, z: StructC) -> bool; + fn types_struct_with_complex_nested_struct(x: StructD>>) -> bool; + fn types_struct_with_single_option(x: StructWithSingleOption) -> StructWithSingleOption; + + fn types_tuple(x: (u8, u8, u8)) -> (u8, u8, u8); + fn types_tuple_complex( + x: (u8, StructSingleGeneric>, str[3]), + ) -> (u8, StructSingleGeneric>, str[3]); + fn types_tuple_with_native_types(x: (AssetId, AssetId, bool)) -> (AssetId, AssetId, bool); + fn types_alias_tuple_with_native_types(x: TupleWithNativeAssets) -> TupleWithNativeAssets; + + fn types_enum(x: EnumWithNative) -> EnumWithNative; + fn types_enum_with_builtin_type(x: EnumWithBuiltinType) -> EnumWithBuiltinType; + fn types_enum_with_vector(x: EnumWithVector) -> EnumWithVector; + fn types_generic_enum(x: EnumDoubleGeneric) -> EnumDoubleGeneric; + fn types_enum_external(x: ExternalEnum) -> ExternalEnum; + fn types_enum_with_structs(x: EnumWithStructs) -> EnumWithStructs; + + fn types_vector_u8(x: Vec) -> Vec; + fn types_vector_boolean(x: Vec) -> Vec; + fn types_vector_inside_vector(x: Vec>) -> Vec>; + fn types_vector_with_struct(x: Vec) -> Vec; + fn types_vector_option(x: Vec) -> Vec; + + fn types_option(x: Option) -> Option; + fn types_option_struct(x: Option) -> Option; + + fn types_identity_address(x: Identity) -> Identity; + fn types_identity_contract_id(x: Identity) -> Identity; + fn types_address(x: Address) -> Address; + fn types_contract_id(x: ContractId) -> ContractId; + fn types_asset_id(x: AssetId) -> AssetId; + fn types_evm_address(x: EvmAddress) -> EvmAddress; + fn types_result(x: Result) -> Result; + + fn types_void(x: ()) -> (); + fn types_void_then_value(x: (), y: u8) -> (); + fn types_value_then_void(x: u8, y: ()) -> (); + fn types_value_then_void_then_value(x: u8, y: (), z: u8) -> (); + fn types_value_then_value_then_void_then_void(x: u8, y: u8, z: (), a: ()) -> (); + + fn multi_arg_u64_u64(x: u64, y: u64) -> u64; + fn multi_arg_b256_bool(x: b256, y: bool) -> (b256, bool); + fn multi_arg_vector_vector(x: Vec, y: Vec) -> (Vec, Vec); + fn multi_arg_vector_b256(x: Vec, y: b256) -> (Vec, b256); + fn multi_arg_struct_vector(x: StructSimple, y: Vec) -> (StructSimple, Vec); + fn multi_arg_u64_struct(x: u64, y: StructSimple) -> (u64, StructSimple); + fn multi_arg_str_str(x: str[5], y: str[5]) -> (str[5], str[5]); + fn multi_arg_u32_vector_vector(x: u32, y: Vec, z: Vec) -> (u32, Vec, Vec); + fn multi_arg_complex( + x: StructDoubleGeneric<[b256; 3], u8>, + y: [StructDoubleGeneric; 4], + z: (str[5], bool), + a: StructSimple, + ) -> (StructDoubleGeneric<[b256; 3], u8>, [StructDoubleGeneric; 4], (str[5], bool), StructSimple); +} + +configurable { + U8_VALUE: u8 = 10, + BOOL_VALUE: bool = true, + B256_VALUE: b256 = 0x38966262edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96, + OPTION_U8_VALUE: Option = Option::None, + GENERIC_STRUCT_VALUE: StructDoubleGeneric, u32> = StructDoubleGeneric { + a: StructDoubleGeneric { a: 4, b: 257 }, + b: 57000, + }, +} + +impl AbiContract for Contract { + fn configurables() -> Configurables { + Configurables { + U8_VALUE: U8_VALUE, + BOOL_VALUE: BOOL_VALUE, + B256_VALUE: B256_VALUE, + OPTION_U8_VALUE: OPTION_U8_VALUE, + GENERIC_STRUCT_VALUE: GENERIC_STRUCT_VALUE, + } + } + + fn types_u8(x: u8) -> u8 { + assert_eq(x, 8); + + const EXPECTED: u8 = 255; + log(EXPECTED); + return EXPECTED; + } + + fn types_u16(x: u16) -> u16 { + assert_eq(x, 16); + + const EXPECTED: u16 = 65535; + log(EXPECTED); + return EXPECTED; + } + + fn types_u32(x: u32) -> u32 { + assert_eq(x, 32); + + const EXPECTED: u32 = 4294967295; + log(EXPECTED); + return EXPECTED; + } + + fn types_u64(x: u64) -> u64 { + assert_eq(x, 64); + + const EXPECTED: u64 = 4294967295000; + log(EXPECTED); + return EXPECTED; + } + + fn types_u256(x: u256) -> u256 { + assert_eq(x, 256); + + const EXPECTED: u256 = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFu256; + log(EXPECTED); + return EXPECTED; + } + + fn types_bool(x: bool) -> bool { + const INPUT: bool = false; + assert_eq(x, INPUT); + + const EXPECTED: bool = true; + log(EXPECTED); + return EXPECTED; + } + + fn types_b256(x: b256) -> b256 { + const INPUT: b256 = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; + assert_eq(x, INPUT); + + const EXPECTED: b256 = 0x0000000000000000000000000000000000000000000000000000000000000000; + log(EXPECTED); + return EXPECTED; + } + + fn types_b512(x: B512) -> B512 { + // HIGH_BIT and **LOW_BIT** + const HI_BITS = 0xbd0c9b8792876713afa8bff383eebf31c43437823ed761cc3600d0016de5110c; + const LO_BITS = 0x44ac566bd156b4fc71a4a4cb2655d3dd360c695edb17dc3b64d611e122fea23d; + const INPUT: B512 = B512::from((HI_BITS, LO_BITS)); + assert_eq(x, INPUT); + + // HIGH_BIT and **LOW_BIT2** + const HI_BITS2 = 0xad0c9b8792876713afa8bff383eebf31c43437823ed761cc3600d0016de5110c; + const LO_BITS2 = 0x54ac566bd156b4fc71a4a4cb2655d3dd360c695edb17dc3b64d611e122fea23d; + const EXPECTED: B512 = B512::from((HI_BITS2, LO_BITS2)); + log(EXPECTED); + return EXPECTED; + } + + fn types_bytes(x: Bytes) -> Bytes { + let mut INPUT = Bytes::new(); + INPUT.push(1u8); + INPUT.push(2u8); + INPUT.push(3u8); + assert_eq(x, INPUT); + + let mut EXPECTED = Bytes::new(); + EXPECTED.push(3u8); + EXPECTED.push(2u8); + EXPECTED.push(1u8); + log(EXPECTED); + return EXPECTED; + } + + /** + * Strings + */ + fn types_str(x: str[5]) -> str[5] { + const INPUT: str[5] = __to_str_array("Input"); + assert_eq(x, INPUT); + + const EXPECTED: str[5] = __to_str_array("Hello"); + log(EXPECTED); + return EXPECTED; + } + + fn types_str_slice(x: str) -> str { + let INPUT = "Input"; + assert(x == INPUT); + + let EXPECTED = "Output"; + log(EXPECTED); + return EXPECTED; + } + + fn types_std_string(x: String) -> String { + let INPUT = "Input"; + assert_eq(x, String::from_ascii_str(INPUT)); + + let EXPECTED = String::from_ascii_str("Output"); + log(EXPECTED); + return EXPECTED; + } + + fn types_raw_slice(x: raw_slice) -> raw_slice { + let vec: Vec = Vec::from(x); + require(vec.len() == 3, "raw slice len is not 3"); + require(vec.get(2).unwrap() == 3, "expected 3rd slice entry to be 3"); + require(vec.get(1).unwrap() == 2, "expected 2nd slice entry to be 2"); + require(vec.get(0).unwrap() == 1, "expected 1st slice entry to be 1"); + + let mut vec_expected: Vec = Vec::new(); + vec_expected.push(4); + vec_expected.push(3); + vec_expected.push(2); + vec_expected.push(1); + let EXPECTED = vec_expected.as_raw_slice(); + log(EXPECTED); + return EXPECTED + } + + /** + * Arrays + */ + fn types_array(x: [u8; 4]) -> [u8; 4] { + const INPUT: [u8; 4] = [1, 2, 3, 4]; + assert(x == INPUT); + + const EXPECTED: [u8; 4] = [4, 3, 2, 1]; + log(EXPECTED); + return EXPECTED + } + + fn types_array_struct(x: [StructSimple; 3]) -> [StructSimple; 3] { + const INPUT_STRUCT_1: StructSimple = StructSimple { a: true, b: 10 }; + const INPUT = [INPUT_STRUCT_1, INPUT_STRUCT_1, INPUT_STRUCT_1]; + assert(x == INPUT); + + const EXPECTED_STRUCT: StructSimple = StructSimple { + a: false, + b: 30, + }; + const EXPECTED = [EXPECTED_STRUCT, EXPECTED_STRUCT, EXPECTED_STRUCT]; + log(EXPECTED); + return EXPECTED; + } + + fn types_array_with_generic_struct( + x: [StructDoubleGeneric, str[1]>; 2], + ) -> [StructDoubleGeneric, str[1]>; 2] { + const INPUT_STRUCT: StructDoubleGeneric, str[1]> = StructDoubleGeneric { + a: StructSingleGeneric { a: 10 }, + b: __to_str_array("A"), + }; + const INPUT = [INPUT_STRUCT, INPUT_STRUCT]; + assert(x == INPUT); + + const EXPECTED_STRUCT: StructDoubleGeneric, str[1]> = StructDoubleGeneric { + a: StructSingleGeneric { a: 20 }, + b: __to_str_array("B"), + }; + const EXPECTED = [EXPECTED_STRUCT, EXPECTED_STRUCT]; + log(EXPECTED); + return EXPECTED; + } + + fn types_array_with_vector(x: [Vec; 1]) -> [Vec; 1] { + let INPUT_VEC = vec_u32_from([1, 2, 3]); + let INPUT = [INPUT_VEC]; + assert(x == INPUT); + + let EXPECTED_VEC: Vec = vec_u32_from([3, 2, 1]); + let EXPECTED: [Vec; 1] = [EXPECTED_VEC]; + log(EXPECTED); + return EXPECTED + } + + /** + * Tuples + */ + fn types_tuple(x: (u8, u8, u8)) -> (u8, u8, u8) { + const INPUT: (u8, u8, u8) = (1, 2, 3); + assert(x == INPUT); + + const EXPECTED: (u8, u8, u8) = (3, 2, 1); + log(EXPECTED); + return EXPECTED + } + + fn types_tuple_complex( + x: (u8, StructSingleGeneric>, str[3]), + ) -> (u8, StructSingleGeneric>, str[3]) { + let INPUT: (u8, StructSingleGeneric>, str[3]) = ( + 1, + StructSingleGeneric { + a: StructSingleGeneric { a: 10 }, + }, + __to_str_array("ABC"), + ); + assert(x == INPUT); + + let EXPECTED: (u8, StructSingleGeneric>, str[3]) = ( + 3, + StructSingleGeneric { + a: StructSingleGeneric { a: 30 }, + }, + __to_str_array("CBA"), + ); + log(EXPECTED); + return EXPECTED + } + + fn types_tuple_with_native_types(x: (AssetId, AssetId, bool)) -> (AssetId, AssetId, bool) { + const A = AssetId::from(0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA); + const B = AssetId::from(0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB); + const C = true; + const INPUT: (AssetId, AssetId, bool) = (A, B, C); + assert(x == INPUT); + + const F = false; + const EXPECTED: (AssetId, AssetId, bool) = (B, A, F); + log(EXPECTED); + return EXPECTED + } + + fn types_alias_tuple_with_native_types(x: TupleWithNativeAssets) -> TupleWithNativeAssets { + const A = AssetId::from(0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA); + const B = AssetId::from(0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB); + const C = true; + const INPUT: (AssetId, AssetId, bool) = (A, B, C); + assert(x == INPUT); + + const F = false; + const EXPECTED: (AssetId, AssetId, bool) = (B, A, F); + log(EXPECTED); + return EXPECTED + } + + /** + * Structs + */ + fn types_struct_simple(x: StructSimple) -> StructSimple { + const INPUT: StructSimple = StructSimple { a: true, b: 10 }; + assert(x == INPUT); + + const EXPECTED: StructSimple = StructSimple { + a: false, + b: 30, + }; + log(EXPECTED); + return EXPECTED; + } + + fn types_struct_generic(x: StructSingleGeneric) -> StructSingleGeneric { + const INPUT: StructSingleGeneric = StructSingleGeneric { a: 10 }; + assert(x == INPUT); + + const EXPECTED: StructSingleGeneric = StructSingleGeneric { a: 20 }; + log(EXPECTED); + return EXPECTED; + } + + fn types_struct_with_tuple( + x: StructSingleGeneric<(bool, u64)>, + ) -> StructSingleGeneric<(bool, u64)> { + const INPUT: StructSingleGeneric<(bool, u64)> = StructSingleGeneric { a: (true, 10) }; + assert(x == INPUT); + + const EXPECTED: StructSingleGeneric<(bool, u64)> = StructSingleGeneric { a: (false, 20) }; + log(EXPECTED); + return EXPECTED; + } + + fn types_struct_double_generic( + x: StructGenericWithEnum, + ) -> StructGenericWithEnum { + const INPUT: StructGenericWithEnum = StructGenericWithEnum { + a: 10, + b: EnumDoubleGeneric::a(10), + }; + assert(x == INPUT); + + const EXPECTED: StructGenericWithEnum = StructGenericWithEnum { + a: 20, + b: EnumDoubleGeneric::b(10), + }; + log(EXPECTED); + return EXPECTED; + } + + fn types_struct_external(x: ExternalStruct) -> ExternalStruct { + const INPUT: ExternalStruct = ExternalStruct { value: 10 }; + assert(x == INPUT); + + const EXPECTED: ExternalStruct = ExternalStruct { value: 20 }; + log(EXPECTED); + return EXPECTED; + } + + fn types_struct_with_nested_array(x: StructWithNestedArray) -> StructWithNestedArray { + const INPUT_STRUCT: StructDoubleGeneric, str[1]> = StructDoubleGeneric { + a: StructSingleGeneric { a: 10 }, + b: __to_str_array("A"), + }; + const INPUT = StructWithNestedArray { + a: [INPUT_STRUCT, INPUT_STRUCT], + }; + assert(x == INPUT); + + const EXPECTED_STRUCT: StructDoubleGeneric, str[1]> = StructDoubleGeneric { + a: StructSingleGeneric { a: 20 }, + b: __to_str_array("B"), + }; + const EXPECTED = StructWithNestedArray { + a: [EXPECTED_STRUCT, EXPECTED_STRUCT], + }; + log(EXPECTED); + return EXPECTED; + } + + fn types_struct_with_nested_tuple(x: StructWithNestedTuple) -> StructWithNestedTuple { + const INPUT: StructWithNestedTuple = StructWithNestedTuple { + a: ( + 10, + StructSingleGeneric { + a: StructSingleGeneric { a: 20 }, + }, + __to_str_array("ABC"), + ), + }; + assert(x == INPUT); + + const EXPECTED: StructWithNestedTuple = StructWithNestedTuple { + a: ( + 30, + StructSingleGeneric { + a: StructSingleGeneric { a: 40 }, + }, + __to_str_array("CBA"), + ), + }; + log(EXPECTED); + return EXPECTED; + } + + fn types_struct_with_nested_struct(x: StructWithNestedStruct) -> StructWithNestedStruct { + const INPUT: StructWithNestedStruct = StructWithNestedStruct { + a: StructDoubleGeneric { + a: StructSingleGeneric { a: 10 }, + b: 20, + }, + }; + assert(x == INPUT); + + const EXPECTED: StructWithNestedStruct = StructWithNestedStruct { + a: StructDoubleGeneric { + a: StructSingleGeneric { a: 30 }, + b: 40, + }, + }; + log(EXPECTED); + return EXPECTED; + } + + fn types_struct_with_multiple_struct_params(x: StructA, y: StructB, z: StructC) -> bool { + const STRUCT_A: StructA = StructA { propA1: 10 }; + assert(x == STRUCT_A); + + const STRUCT_B: StructB = StructB { + propB1: STRUCT_A, + propB2: 20, + }; + assert(y == STRUCT_B); + + // PropC2 + let mut propC2 = Vec::new(); + propC2.push(STRUCT_B); + + // PropC3 + const STRUCT_E: StructE = StructE { + propE1: STRUCT_A, + propE2: STRUCT_B, + propE3: 30, + }; + let mut propD1 = Vec::new(); + propD1.push(STRUCT_E); + + const STRUCT_F: StructF = StructF { + propF1: 50, + propF2: __to_str_array("A"), + }; + let propC3: StructD> = StructD { + propD1: propD1, + propD2: 40, + propD3: STRUCT_F, + }; + + let STRUCT_C: StructC = StructC { + propC1: STRUCT_A, + propC2: propC2, + propC3: propC3, + // propC4: [STRUCT_D], + // propC5: [STRUCT_D], + }; + + assert(z == STRUCT_C); + + return true; + + // const STRUCT_C4: StructD> = StructD { + // propD1: [StructE { propE1: STRUCT_A, propE2: STRUCT_B, propE3: 30 }], + // propD2: 40, + // propD3: StructF { propF1: 50, propF2: true }, + // }; + + // const STRUCT_C5: StructD>> = StructD> { + // propD1: [StructE { propE1: STRUCT_A, propE2: STRUCT_B, propE3: 30 }], + // propD2: 40, + // propD3: StructF { propF1: 50, propF2: [StructG { propG1: 60 }] }, + // }; + + // const STRUCT_C: StructC = StructC { + // propC1: STRUCT_A, + // propC2: [STRUCT_B], + // propC3: STRUCT_C3, + // propC4: [STRUCT_C4], + // propC5: [STRUCT_C5], + // }; + // const STRUCT_B: StructB = StructB { propB1: INPUT_X, propB2: 20 }; + // const STRUCT_C: StructC = StructC { propC1: INPUT_X, propC2: [INPUT_Y], propC3: INPUT_D, propC4: [INPUT_D], propC5: [INPUT_D] }; + // const STRUCT_D: StructD = StructD { + // propD1: [StructE { propE1: INPUT_X, propE2: INPUT_Y, propE3: 30 }], + // propD2: 40, + // propD3: StructF { propF1: 50, propF2: __to_str_array("ABC") }, + // }; + // assert(y == INPUT_Y); + } + + fn types_struct_with_implicit_generics( + x: StructWithImplicitGenerics, + ) -> StructWithImplicitGenerics { + const INPUT_B256: b256 = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; + const INPUT: StructWithImplicitGenerics = StructWithImplicitGenerics { + a: [INPUT_B256, INPUT_B256, INPUT_B256], + b: (INPUT_B256, 10), + }; + + assert(x == INPUT); + + const EXPECTED_B256: b256 = 0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + const EXPECTED: StructWithImplicitGenerics = StructWithImplicitGenerics { + a: [EXPECTED_B256, EXPECTED_B256, EXPECTED_B256], + b: (EXPECTED_B256, 25), + }; + log(EXPECTED); + return EXPECTED; + } + + fn types_struct_with_array(x: StructWithGenericArray) -> StructWithGenericArray { + const INPUT_B256: b256 = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; + const INPUT_STRUCT: StructDoubleGeneric = StructDoubleGeneric { + a: INPUT_B256, + b: 10, + }; + const INPUT: StructWithGenericArray = StructWithGenericArray { + a: [INPUT_STRUCT, INPUT_STRUCT, INPUT_STRUCT], + }; + assert(x == INPUT); + + const EXPECTED_B256: b256 = 0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + const EXPECTED_STRUCT: StructDoubleGeneric = StructDoubleGeneric { + a: EXPECTED_B256, + b: 20, + }; + const EXPECTED: StructWithGenericArray = StructWithGenericArray { + a: [EXPECTED_STRUCT, EXPECTED_STRUCT, EXPECTED_STRUCT], + }; + log(EXPECTED); + return EXPECTED; + } + + fn types_struct_with_vector(x: StructWithVector) -> StructWithVector { + let INPUT_VEC: Vec = vec_u8_from([1, 2, 3]); + let INPUT: StructWithVector = StructWithVector { + a: 1, + b: INPUT_VEC, + }; + assert(x == INPUT); + + let EXPECTED_VEC: Vec = vec_u8_from([3, 2, 1]); + let EXPECTED: StructWithVector = StructWithVector { + a: 3, + b: EXPECTED_VEC, + }; + log(EXPECTED); + return EXPECTED; + } + + fn types_struct_with_array_of_enums(x: StructWithEnumArray) -> StructWithEnumArray { + const INPUT_ENUM = EnumWithNative::Checked; + const INPUT: StructWithEnumArray = StructWithEnumArray { + a: [INPUT_ENUM, INPUT_ENUM, INPUT_ENUM], + }; + assert(x == INPUT); + + const EXPECTED_ENUM = EnumWithNative::Pending; + const EXPECTED: StructWithEnumArray = StructWithEnumArray { + a: [EXPECTED_ENUM, EXPECTED_ENUM, EXPECTED_ENUM], + }; + + log(EXPECTED); + return EXPECTED; + } + + fn types_struct_with_complex_nested_struct(x: StructD>>) -> bool { + false + } + + fn types_struct_with_single_option(x: StructWithSingleOption) -> StructWithSingleOption { + const OPTION_ARRAY: [Option; 5] = [Option::Some(1), Option::None, Option::Some(2), Option::None, Option::Some(3)]; + const OPTION_STRUCT: Option = Option::Some(StructWithMultiOption { + a: OPTION_ARRAY, + }); + const INPUT: StructWithSingleOption = StructWithSingleOption { + a: OPTION_STRUCT, + }; + assert(x == INPUT); + + const EXPECTED: StructWithSingleOption = StructWithSingleOption { + a: Option::None, + }; + log(EXPECTED); + return EXPECTED; + } + + /** + * Enums + */ + fn types_enum(x: EnumWithNative) -> EnumWithNative { + assert(x == EnumWithNative::Checked); + + const EXPECTED = EnumWithNative::Pending; + log(EXPECTED); + return EXPECTED; + } + + fn types_enum_with_builtin_type(x: EnumWithBuiltinType) -> EnumWithBuiltinType { + assert(x == EnumWithBuiltinType::a(true)); + + const EXPECTED = EnumWithBuiltinType::b(20); + log(EXPECTED); + return EXPECTED; + } + + fn types_enum_with_vector(x: EnumWithVector) -> EnumWithVector { + assert(x == EnumWithVector::a(10)); + + let EXPECTED_VEC = vec_u8_from([1, 2, 3]); + let EXPECTED = EnumWithVector::b(EXPECTED_VEC); + log(EXPECTED); + return EXPECTED; + } + + fn types_generic_enum(x: EnumDoubleGeneric) -> EnumDoubleGeneric { + const INPUT: EnumDoubleGeneric = EnumDoubleGeneric::a(10); + assert(x == INPUT); + + const EXPECTED: EnumDoubleGeneric = EnumDoubleGeneric::b(20); + log(EXPECTED); + return EXPECTED; + } + + fn types_enum_external(x: ExternalEnum) -> ExternalEnum { + assert_eq(x, ExternalEnum::A); + + const EXPECTED = ExternalEnum::B; + log(EXPECTED); + return EXPECTED; + } + + fn types_enum_with_structs(x: EnumWithStructs) -> EnumWithStructs { + const INPUT: EnumWithStructs = EnumWithStructs::a(EnumWithNative::Checked); + assert(x == INPUT); + + const EXPECTED: EnumWithStructs = EnumWithStructs::b(StructSimple { a: true, b: 10 }); + log(EXPECTED); + return EXPECTED; + } + + /** + * Vectors + */ + fn types_vector_u8(x: Vec) -> Vec { + let INPUT = vec_u8_from([1, 2, 3]); + assert(x == INPUT); + + let EXPECTED = vec_u8_from([3, 2, 1]); + log(EXPECTED); + return EXPECTED; + } + + fn types_vector_boolean(x: Vec) -> Vec { + let INPUT = vec_bool_from([true, false, true, false]); + assert(x == INPUT); + + let EXPECTED = vec_bool_from([false, true, false, true]); + log(EXPECTED); + return EXPECTED; + } + + fn types_vector_inside_vector(x: Vec>) -> Vec> { + let mut INPUT = Vec::new(); + INPUT.push(vec_u32_from([1, 2, 3])); + assert(x == INPUT); + + let mut EXPECTED = Vec::new(); + EXPECTED.push(vec_u32_from([3, 2, 1])); + EXPECTED.push(vec_u32_from([6, 5, 4])); + log(EXPECTED); + return EXPECTED; + } + + fn types_vector_with_struct(x: Vec) -> Vec { + let mut INPUT = Vec::new(); + INPUT.push(StructSimple { a: true, b: 10 }); + assert(x == INPUT); + + let mut EXPECTED = Vec::new(); + EXPECTED.push(StructSimple { + a: false, + b: 30, + }); + log(EXPECTED); + return EXPECTED; + } + + fn types_vector_option(x: Vec) -> Vec { + let mut INPUT = Vec::new(); + INPUT.push(StructWithMultiOption { + a: [Some(1), Some(2), Some(3), Some(4), Some(5)], + }); + assert(x == INPUT); + + let mut EXPECTED = Vec::new(); + EXPECTED.push(StructWithMultiOption { + a: [Some(5), Some(4), Some(3), Some(2), Some(1)], + }); + log(EXPECTED); + return EXPECTED; + } + + /** + * Options + */ + fn types_option(x: Option) -> Option { + const INPUT: Option = Option::Some(10); + assert(x == INPUT); + + const EXPECTED: Option = Option::None; + log(EXPECTED); + return EXPECTED; + } + + fn types_option_struct(x: Option) -> Option { + let input_struct: StructSimple = StructSimple { + a: true, + b: 10, + }; + let input: Option = Option::Some(input_struct); + assert(x == input); + + const EXPECTED: Option = Option::None; + log(EXPECTED); + return EXPECTED; + } + + /** + * Native types + */ + fn types_asset_id(x: AssetId) -> AssetId { + const INPUT = AssetId::from(0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA); + assert(x == INPUT); + + const EXPECTED = AssetId::from(0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + log(EXPECTED); + return EXPECTED; + } + + fn types_identity_address(x: Identity) -> Identity { + const ADDRESS = Address::from(0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA); + const INPUT = Identity::Address(ADDRESS); + assert(x == INPUT); + + const EXPECTED_ADDRESS = Address::from(0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + const EXPECTED = Identity::Address(EXPECTED_ADDRESS); + log(EXPECTED); + return EXPECTED; + } + + fn types_identity_contract_id(x: Identity) -> Identity { + const INPUT_CONTRACT_ID = ContractId::from(0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA); + const INPUT = Identity::ContractId(INPUT_CONTRACT_ID); + assert(x == INPUT); + + const EXPECTED_ADDRESS = ContractId::from(0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + const EXPECTED = Identity::ContractId(EXPECTED_ADDRESS); + log(EXPECTED); + return EXPECTED; + } + + fn types_address(x: Address) -> Address { + const INPUT = Address::from(0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA); + assert(x == INPUT); + + const EXPECTED = Address::from(0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + log(EXPECTED); + return EXPECTED; + } + + fn types_contract_id(x: ContractId) -> ContractId { + const INPUT = ContractId::from(0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA); + assert(x == INPUT); + + const EXPECTED = ContractId::from(0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + log(EXPECTED); + return EXPECTED; + } + + fn types_evm_address(x: EvmAddress) -> EvmAddress { + let INPUT = EvmAddress::from(0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA); + assert(x == INPUT); + + let EXPECTED = EvmAddress::from(0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb); + log(EXPECTED); + return EXPECTED; + } + + fn types_result(x: Result) -> Result { + if (x.is_err()) { + return Err(__to_str_array("InputError")); + } + + let result = divide(20, x.unwrap()); + match result { + Ok(value) => Ok(value), + Err(MyContractError::DivisionByZero) => Err(__to_str_array("DivisError")), + } + } + + /** + * Void + */ + fn types_void(x: ()) -> () { + log(x); + return x; + } + + fn types_void_then_value(x: (), y: u8) -> () { + const inputY = 10; + assert(y == inputY); + () + } + + fn types_value_then_void(x: u8, y: ()) -> () { + const inputX = 10; + assert(x == inputX); + () + } + + fn types_value_then_void_then_value(x: u8, y: (), z: u8) -> () { + const inputX = 10; + assert(x == inputX); + + const inputZ = 20; + assert(z == inputZ); + () + } + + fn types_value_then_value_then_void_then_void(x: u8, y: u8, z: (), a: ()) -> () { + const inputX = 10; + assert(x == inputX); + + const inputY = 20; + assert(y == inputY); + () + } + + /** + * Multi-args + */ + fn multi_arg_u64_u64(x: u64, y: u64) -> u64 { + const INPUT_X = 1; + const INPUT_Y = 2; + assert(x == INPUT_X); + assert(y == INPUT_Y); + + const EXPECTED = 3; + log(EXPECTED); + return EXPECTED; + } + + fn multi_arg_b256_bool(x: b256, y: bool) -> (b256, bool) { + const INPUT_X: b256 = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; + const INPUT_Y: bool = true; + assert_eq(x, INPUT_X); + assert_eq(y, INPUT_Y); + + const EXPECTED: (b256, bool) = (0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, false); + log(EXPECTED); + return EXPECTED; + } + + fn multi_arg_vector_vector(x: Vec, y: Vec) -> (Vec, Vec) { + let INPUT_X = vec_u8_from([1, 2, 3]); + let INPUT_Y = vec_u8_from([4, 5, 6]); + assert(x == INPUT_X); + assert(y == INPUT_Y); + + let EXPECTED_X = vec_u8_from([7, 8, 9]); + let EXPECTED_Y = vec_u8_from([10, 11, 12]); + let EXPECTED = (EXPECTED_X, EXPECTED_Y); + log(EXPECTED); + return EXPECTED; + } + + fn multi_arg_vector_b256(x: Vec, y: b256) -> (Vec, b256) { + let INPUT_X = vec_u8_from([1, 2, 3]); + let INPUT_Y: b256 = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; + assert(x == INPUT_X); + assert(y == INPUT_Y); + + let EXPECTED_X = vec_u8_from([7, 8, 9]); + const EXPECTED_Y = 0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb; + let EXPECTED = (EXPECTED_X, EXPECTED_Y); + log(EXPECTED); + return EXPECTED; + } + + fn multi_arg_struct_vector(x: StructSimple, y: Vec) -> (StructSimple, Vec) { + const INPUT_X = StructSimple { a: true, b: 1 }; + let INPUT_Y = vec_u8_from([1, 2, 3]); + assert(x == INPUT_X); + assert(y == INPUT_Y); + + const EXPECTED_X = StructSimple { a: false, b: 2 }; + let EXPECTED_Y = vec_u8_from([4, 5, 6]); + let EXPECTED = (EXPECTED_X, EXPECTED_Y); + log(EXPECTED); + return EXPECTED; + } + + fn multi_arg_u64_struct(x: u64, y: StructSimple) -> (u64, StructSimple) { + const INPUT_X = 99u64; + let input_y = StructSimple { a: true, b: 51 }; + assert(x == INPUT_X); + assert(y == input_y); + + const EXPECTED_X = 3u64; + let expected_y = StructSimple { a: false, b: 4 }; + let EXPECTED = (EXPECTED_X, expected_y); + log(EXPECTED); + return EXPECTED; + } + + fn multi_arg_str_str(x: str[5], y: str[5]) -> (str[5], str[5]) { + let input_x: str = "Input"; + let input_y: str = "False"; + + assert_eq(from_str_array(x), input_x); + assert_eq(from_str_array(y), input_y); + + let EXPECTED_X: str[5] = __to_str_array("Fuuel"); + let EXPECTED_Y: str[5] = __to_str_array("Niice"); + let EXPECTED = (EXPECTED_X, EXPECTED_Y); + log(EXPECTED); + return EXPECTED; + } + + fn multi_arg_u32_vector_vector(x: u32, y: Vec, z: Vec) -> (u32, Vec, Vec) { + const INPUT_X = 1u32; + + let mut input_y: Vec = Vec::new(); + input_y.push(10020); + input_y.push(1231231); + input_y.push(777657); + + let mut input_z: Vec = Vec::new(); + input_z.push(99); + input_z.push(101); + + assert(x == INPUT_X); + assert(y == input_y); + assert(z == input_z); + + const EXPECTED_X = 2u32; + + let mut expected_y: Vec = Vec::new(); + expected_y.push(7); + expected_y.push(8); + expected_y.push(9); + + let mut expected_z: Vec = Vec::new(); + expected_z.push(10); + expected_z.push(11); + expected_z.push(12); + + let expected = (EXPECTED_X, expected_y, expected_z); + log(expected); + return expected; + } + + fn multi_arg_complex( + x: StructDoubleGeneric<[b256; 3], u8>, + y: [StructDoubleGeneric; 4], + z: (str[5], bool), + a: StructSimple, + ) -> (StructDoubleGeneric<[b256; 3], u8>, [StructDoubleGeneric; 4], (str[5], bool), StructSimple) { + let input_x: StructDoubleGeneric<[b256; 3], u8> = StructDoubleGeneric { + a: [ + 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, + 0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + 0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc, + ], + b: 10, + }; + + let input_y: [StructDoubleGeneric; 4] = [ + StructDoubleGeneric { + a: 99u64, + b: false, + }, + StructDoubleGeneric { + a: 199u64, + b: false, + }, + StructDoubleGeneric { + a: 2000u64, + b: false, + }, + StructDoubleGeneric { + a: 31u64, + b: true, + }, + ]; + + let input_z: (str[5], bool) = (__to_str_array("Input"), true); + + let input_a: StructSimple = StructSimple { a: true, b: 10 }; + + assert(x == input_x); + assert(y == input_y); + assert(z == input_z); + assert(a == input_a); + + let expected_x: StructDoubleGeneric<[b256; 3], u8> = StructDoubleGeneric { + a: [ + 0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd, + 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee, + 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff, + ], + b: 99, + }; + + let expected_y: [StructDoubleGeneric; 4] = [ + StructDoubleGeneric { + a: 11u64, + b: true, + }, + StructDoubleGeneric { + a: 99u64, + b: true, + }, + StructDoubleGeneric { + a: 567u64, + b: true, + }, + StructDoubleGeneric { + a: 971u64, + b: false, + }, + ]; + + let expected_z: (str[5], bool) = (__to_str_array("tupni"), false); + + let expected_a: StructSimple = StructSimple { + a: false, + b: 57, + }; + + let expected = (expected_x, expected_y, expected_z, expected_a); + log(expected); + return expected; + } +} diff --git a/packages/fuel-gauge/test/fixtures/forc-projects/abi-contract/src/utils.sw b/packages/fuel-gauge/test/fixtures/forc-projects/abi-contract/src/utils.sw new file mode 100644 index 00000000000..27338730220 --- /dev/null +++ b/packages/fuel-gauge/test/fixtures/forc-projects/abi-contract/src/utils.sw @@ -0,0 +1,26 @@ +library; + +pub fn vec_u32_from(vals: [u32; 3]) -> Vec { + let mut vec = Vec::new(); + vec.push(vals[0]); + vec.push(vals[1]); + vec.push(vals[2]); + vec +} + +pub fn vec_u8_from(vals: [u8; 3]) -> Vec { + let mut vec = Vec::new(); + vec.push(vals[0]); + vec.push(vals[1]); + vec.push(vals[2]); + vec +} + +pub fn vec_bool_from(vals: [bool; 4]) -> Vec { + let mut vec = Vec::new(); + vec.push(vals[0]); + vec.push(vals[1]); + vec.push(vals[2]); + vec.push(vals[3]); + vec +} diff --git a/packages/fuel-gauge/test/fixtures/forc-projects/abi-library/Forc.toml b/packages/fuel-gauge/test/fixtures/forc-projects/abi-library/Forc.toml new file mode 100644 index 00000000000..d28ab3240d9 --- /dev/null +++ b/packages/fuel-gauge/test/fixtures/forc-projects/abi-library/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["Fuel Labs "] +entry = "lib.sw" +license = "Apache-2.0" +name = "abi-library" + +[dependencies] diff --git a/packages/fuel-gauge/test/fixtures/forc-projects/abi-library/src/lib.sw b/packages/fuel-gauge/test/fixtures/forc-projects/abi-library/src/lib.sw new file mode 100644 index 00000000000..90c6c70044a --- /dev/null +++ b/packages/fuel-gauge/test/fixtures/forc-projects/abi-library/src/lib.sw @@ -0,0 +1,27 @@ +library; + +// anything `pub` here will be exported as a part of this library's API +pub struct ExternalStruct { + pub value: u64, +} + +pub enum ExternalEnum { + A: (), + B: (), +} + +impl Eq for ExternalStruct { + fn eq(self, other: Self) -> bool { + self.value == other.value + } +} + +impl Eq for ExternalEnum { + fn eq(self, other: Self) -> bool { + match (self, other) { + (ExternalEnum::A, ExternalEnum::A) => true, + (ExternalEnum::B, ExternalEnum::B) => true, + _ => false, + } + } +}