diff --git a/.changeset/odd-horses-cheer.md b/.changeset/odd-horses-cheer.md new file mode 100644 index 0000000000..73d074f4b1 --- /dev/null +++ b/.changeset/odd-horses-cheer.md @@ -0,0 +1,9 @@ +--- +"@fuel-ts/abi-coder": minor +"@fuel-ts/abi-typegen": minor +"@fuel-ts/versions": minor +"@internal/forc": minor +"create-fuels": minor +--- + +feat!: adding `abi` transpiler diff --git a/apps/docs-snippets/src/guide/encoding/encode-and-decode.test.ts b/apps/docs-snippets/src/guide/encoding/encode-and-decode.test.ts index 148c1d6e49..3e9595453e 100644 --- a/apps/docs-snippets/src/guide/encoding/encode-and-decode.test.ts +++ b/apps/docs-snippets/src/guide/encoding/encode-and-decode.test.ts @@ -1,7 +1,9 @@ -import { AbiCoder, Script, ReceiptType, arrayify, buildFunctionResult } from 'fuels'; -import type { JsonAbi, JsonAbiArgument, TransactionResultReturnDataReceipt } from 'fuels'; +import type { JsonAbi, TransactionResultReturnDataReceipt } from 'fuels'; +import { buildFunctionResult, ReceiptType, arrayify, Script, Interface } from 'fuels'; import { launchTestNode } from 'fuels/test-utils'; +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore JSONC extension requires mapping but behaves fine import abiSnippet from '../../../test/fixtures/abi/encode-and-decode.jsonc'; import { SumScript as factory } from '../../../test/typegen/scripts/SumScript'; @@ -27,7 +29,7 @@ describe('encode and decode', () => { // First we need to build out the transaction via the script that we want to encode. // For that we'll need the ABI and the bytecode of the script const abi: JsonAbi = factory.abi; - const bytecode: string = factory.bytecode; + const bytecode = factory.bytecode; // Create the invocation scope for the script call, passing the initial // value for the configurable constant @@ -42,18 +44,21 @@ describe('encode and decode', () => { // #endregion encode-and-decode-3 // #region encode-and-decode-4 - // #import { JsonAbiArgument, AbiCoder}; + // #import { Interface }; // Now we can encode the argument we want to pass to the function. The argument is required - // as a function parameter for all `AbiCoder` functions and we can extract it from the ABI itself - const argument: JsonAbiArgument = abi.functions + // as a function parameter for all abi functions and we can extract it from the ABI itself + const argument = abi.functions .find((f) => f.name === 'main') - ?.inputs.find((i) => i.name === 'inputted_amount') as JsonAbiArgument; + ?.inputs.find((i) => i.name === 'inputted_amount')?.concreteTypeId as string; - // Using the `AbiCoder`'s `encode` method, we can now create the encoding required for - // a u32 which takes 4 bytes up of property space + // The `Interface` class is the entry point for encoding and decoding all things abi-related. + // We will use its `encodeType` method and create the encoding required for + // a u32 which takes 4 bytes up of property space. + + const abiInterface = new Interface(abi); const argumentToAdd = 10; - const encodedArguments = AbiCoder.encode(abi, argument, [argumentToAdd]); + const encodedArguments = abiInterface.encodeType(argument, [argumentToAdd]); // Therefore the value of 10 will be encoded to: // Uint8Array([0, 0, 0, 10] @@ -72,7 +77,7 @@ describe('encode and decode', () => { // #endregion encode-and-decode-4 // #region encode-and-decode-5 - // #import { AbiCoder, ReceiptType, TransactionResultReturnDataReceipt, arrayify, buildFunctionResult }; + // #import { ReceiptType, TransactionResultReturnDataReceipt, arrayify, buildFunctionResult }; // Get result of the transaction, including the contract call result. For this we'll need // the previously created invocation scope, the transaction response and the script @@ -99,8 +104,8 @@ describe('encode and decode', () => { // returnData = new Uint8Array([0, 0, 0, 20] // And now we can decode the returned bytes in a similar fashion to how they were - // encoded, via the `AbiCoder` - const [decodedReturnData] = AbiCoder.decode(abi, argument, returnData, 0); + // encoded, via the `Interface` + const [decodedReturnData] = abiInterface.decodeType(argument, returnData); // 20 // #endregion encode-and-decode-5 diff --git a/apps/docs-snippets/src/guide/transactions/transaction-request.test.ts b/apps/docs-snippets/src/guide/transactions/transaction-request.test.ts index 0cce5bf46f..0b2c96e837 100644 --- a/apps/docs-snippets/src/guide/transactions/transaction-request.test.ts +++ b/apps/docs-snippets/src/guide/transactions/transaction-request.test.ts @@ -210,7 +210,7 @@ describe('Transaction Request', () => { // #endregion transaction-request-7 expect(transactionId).toBe( - '0x5e12f588de0cbf2ec0f085078880d5eeb3e18cd239a288d4a06ee4247a97e4f2' + '0xf62e682e05fa17455999758d00875449bd6f06cdbe003a6431aa944f2d652642' ); }); }); diff --git a/apps/docs-snippets/test/fixtures/abi/encode-and-decode.jsonc b/apps/docs-snippets/test/fixtures/abi/encode-and-decode.jsonc index 3f907e6b7f..5b2b734de2 100644 --- a/apps/docs-snippets/test/fixtures/abi/encode-and-decode.jsonc +++ b/apps/docs-snippets/test/fixtures/abi/encode-and-decode.jsonc @@ -1,29 +1,25 @@ // #region encode-and-decode-2 { - "encoding": "1", - "types": [ + "programType": "script", + "specVersion": "1", + "encodingVersion": "1", + "concreteTypes": [ { - "typeId": 0, "type": "u32", - "components": null, - "typeParameters": null, + "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc", }, ], + "metadataTypes": [], "functions": [ { "inputs": [ { "name": "inputted_amount", - "type": 0, - "typeArguments": null, + "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc", }, ], "name": "main", - "output": { - "name": "", - "type": 0, - "typeArguments": null, - }, + "output": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc", "attributes": null, }, ], @@ -32,14 +28,9 @@ "configurables": [ { "name": "AMOUNT", - "configurableType": { - "name": "", - "type": 0, - "typeArguments": null, - }, - "offset": 856, + "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc", + "offset": 920, }, ], } - // #endregion encode-and-decode-2 diff --git a/apps/docs-snippets/test/fixtures/forc-projects/predicate-signing/src/main.sw b/apps/docs-snippets/test/fixtures/forc-projects/predicate-signing/src/main.sw index 39c8001dea..4ada28c00d 100644 --- a/apps/docs-snippets/test/fixtures/forc-projects/predicate-signing/src/main.sw +++ b/apps/docs-snippets/test/fixtures/forc-projects/predicate-signing/src/main.sw @@ -4,7 +4,7 @@ predicate; use std::{b512::B512, ecr::ec_recover_address, tx::{tx_id, tx_witness_data}}; fn main(signer: b256) -> bool { - let witness_data: B512 = tx_witness_data(1); + let witness_data: B512 = tx_witness_data(1).unwrap(); let address: b256 = ec_recover_address(witness_data, tx_id()).unwrap().bits(); return address == signer; } diff --git a/apps/docs-snippets/test/fixtures/forc-projects/script-signing/src/main.sw b/apps/docs-snippets/test/fixtures/forc-projects/script-signing/src/main.sw index 15b7e9f828..3d6aa01937 100644 --- a/apps/docs-snippets/test/fixtures/forc-projects/script-signing/src/main.sw +++ b/apps/docs-snippets/test/fixtures/forc-projects/script-signing/src/main.sw @@ -4,7 +4,7 @@ script; use std::{b512::B512, ecr::ec_recover_address, tx::{tx_id, tx_witness_data}}; fn main(signer: b256) -> bool { - let witness_data: B512 = tx_witness_data(1); + let witness_data: B512 = tx_witness_data(1).unwrap(); let address: b256 = ec_recover_address(witness_data, tx_id()).unwrap().bits(); return address == signer; } diff --git a/apps/docs/spell-check-custom-words.txt b/apps/docs/spell-check-custom-words.txt index e4b07dd83d..f8d806e63f 100644 --- a/apps/docs/spell-check-custom-words.txt +++ b/apps/docs/spell-check-custom-words.txt @@ -1,5 +1,6 @@ ABI ABIs +ABI's ASM AssetId IDE diff --git a/apps/docs/src/guide/encoding/encode-and-decode.md b/apps/docs/src/guide/encoding/encode-and-decode.md index 0ed475b8ce..8a6821829c 100644 --- a/apps/docs/src/guide/encoding/encode-and-decode.md +++ b/apps/docs/src/guide/encoding/encode-and-decode.md @@ -1,16 +1,13 @@ # Encode and Decode -In order to interact with the FuelVM, types must be encoded and decoded as per the [argument encoding specification](https://docs.fuel.network/docs/specs/abi/argument-encoding/). The SDK provides the `AbiCoder` class to encode and decode data. +To interact with the FuelVM, types must be encoded and decoded per the [argument encoding specification](https://docs.fuel.network/docs/specs/abi/argument-encoding/). The SDK provides the `Interface` class to encode and decode data. -It has three static methods: +The relevant methods of `Interface` are: -- `encode` -- `decode` -- `getCoder` +- `encodeType` +- `decodeType` -The methods `encode` and `decode` describe the aforementioned process, while `getCoder` returns an instance of the internal coder required to serialize the passed type. This coder is then used internally by the `encode` and `decode` methods. - -All methods expect you to pass the [ABI](https://docs.fuel.network/docs/specs/abi/json-abi-format/) and ABI Argument as function parameters to deduce the specific type coders that will be required to parse the data. +The `Interface` class requires you to pass the [ABI](https://docs.fuel.network/docs/specs/abi/json-abi-format/) on initialization. Both methods accept a `concreteTypeId`, which must exist in the ABI's `concreteTypes` array. After that, a suitable coder will be assigned to encode/decode that type. Imagine we are working with the following script that returns the sum of two `u32` integers: @@ -26,7 +23,7 @@ It will produce the following ABI: <<< @/../../docs-snippets/test/fixtures/abi/encode-and-decode.jsonc#encode-and-decode-2{json:line-numbers} -Now, let's prepare some data to pass to the `main` function to retrieve the combined integer. The function expects and returns a `u32` integer. So here, we will encode the `u32` to pass it to the function and receive the same `u32` back, as bytes, that we'll use for decoding. We can do both of these with the `AbiCoder`. +Now, let's prepare some data to pass to the `main` function to retrieve the combined integer. The function expects and returns a `u32` integer. So here, we will encode the `u32` to pass it to the function and receive the same `u32` back, as bytes, that we'll use for decoding. We can do both of these with the `Interface`. First, let's prepare the transaction: diff --git a/internal/forc/VERSION b/internal/forc/VERSION index 4d74f32383..630f2e0ce6 100644 --- a/internal/forc/VERSION +++ b/internal/forc/VERSION @@ -1 +1 @@ -0.62.0 +0.63.1 diff --git a/internal/forc/lib/shared.js b/internal/forc/lib/shared.js index 3ce890181e..06f6105639 100644 --- a/internal/forc/lib/shared.js +++ b/internal/forc/lib/shared.js @@ -52,18 +52,27 @@ const swayRepoUrl = 'https://github.com/fuellabs/sway.git'; export const buildFromGitBranch = (branchName) => { const swayRepoDir = join(__dirname, '..', 'sway-repo'); - const swayRepoDebugDir = join(swayRepoDir, 'target', 'debug'); + const swayRepoReleaseDir = join(swayRepoDir, 'target', 'release'); const stdioOpts = { stdio: 'inherit' }; if (existsSync(swayRepoDir)) { - execSync(`cd ${swayRepoDir} && git fetch origin && git checkout ${branchName}`, stdioOpts); - execSync(`cd ${swayRepoDir} && cargo build`, stdioOpts); + execSync( + [ + `cd ${swayRepoDir}`, + `git fetch origin`, + `git checkout ${branchName}`, + `git pull origin ${branchName}`, + ].join('&&'), + stdioOpts + ); + + execSync(`cd ${swayRepoDir} && cargo build --release`, stdioOpts); } else { execSync(`git clone --branch ${branchName} ${swayRepoUrl} ${swayRepoDir}`, stdioOpts); - execSync(`cd ${swayRepoDir} && cargo build`, stdioOpts); + execSync(`cd ${swayRepoDir} && cargo build --release`, stdioOpts); } - const [from, to] = [swayRepoDebugDir, forcBinDirPath]; + const [from, to] = [swayRepoReleaseDir, forcBinDirPath]; rmSync(to, { recursive: true, force: true }); mkdirSync(to, { recursive: true }); diff --git a/internal/fuel-core/lib/shared.js b/internal/fuel-core/lib/shared.js index bbae78abf2..8c5e10955c 100644 --- a/internal/fuel-core/lib/shared.js +++ b/internal/fuel-core/lib/shared.js @@ -51,23 +51,23 @@ const fuelCoreRepoUrl = 'https://github.com/fuellabs/fuel-core.git'; export const buildFromGitBranch = (branchName) => { const fuelCoreRepoDir = join(__dirname, '..', 'fuel-core-repo'); - const fuelCoreRepoDebugDir = join(fuelCoreRepoDir, 'target', 'debug'); + const fuelCoreRepoReleaseDir = join(fuelCoreRepoDir, 'target', 'release'); const stdioOpts = { stdio: 'inherit' }; if (existsSync(fuelCoreRepoDir)) { - spawnSync('git', ['pull'], { cwd: fuelCoreRepoDir, ...stdioOpts }); spawnSync('git', ['checkout', branchName], { cwd: fuelCoreRepoDir, ...stdioOpts }); - spawnSync('cargo', ['build'], { cwd: fuelCoreRepoDir, ...stdioOpts }); + spawnSync('git', ['pull'], { cwd: fuelCoreRepoDir, ...stdioOpts }); + spawnSync('cargo', ['build', '--release'], { cwd: fuelCoreRepoDir, ...stdioOpts }); } else { spawnSync( 'git', ['clone', '--branch', branchName, fuelCoreRepoUrl, fuelCoreRepoDir], stdioOpts ); - spawnSync('cargo', ['build'], { cwd: fuelCoreRepoDir, ...stdioOpts }); + spawnSync('cargo', ['build', '--release'], { cwd: fuelCoreRepoDir, ...stdioOpts }); } - const [from, to] = [fuelCoreRepoDebugDir, fuelCoreBinDirPath]; + const [from, to] = [fuelCoreRepoReleaseDir, fuelCoreBinDirPath]; rmSync(to, { recursive: true, force: true }); mkdirSync(to, { recursive: true }); diff --git a/packages/abi-coder/src/AbiCoder.ts b/packages/abi-coder/src/AbiCoder.ts index b7fd369f1d..cec57c6300 100644 --- a/packages/abi-coder/src/AbiCoder.ts +++ b/packages/abi-coder/src/AbiCoder.ts @@ -2,11 +2,11 @@ import { ResolvedAbiType } from './ResolvedAbiType'; import type { DecodedValue, InputValue, Coder } from './encoding/coders/AbstractCoder'; import { getCoderForEncoding } from './encoding/strategies/getCoderForEncoding'; import type { EncodingOptions } from './types/EncodingOptions'; -import type { JsonAbi, JsonAbiArgument } from './types/JsonAbi'; +import type { JsonAbiOld, JsonAbiArgument } from './types/JsonAbi'; export abstract class AbiCoder { static getCoder( - abi: JsonAbi, + abi: JsonAbiOld, argument: JsonAbiArgument, options: EncodingOptions = { padToWordSize: false, @@ -17,7 +17,7 @@ export abstract class AbiCoder { } static encode( - abi: JsonAbi, + abi: JsonAbiOld, argument: JsonAbiArgument, value: InputValue, options?: EncodingOptions @@ -26,7 +26,7 @@ export abstract class AbiCoder { } static decode( - abi: JsonAbi, + abi: JsonAbiOld, argument: JsonAbiArgument, data: Uint8Array, offset: number, diff --git a/packages/abi-coder/src/FunctionFragment.ts b/packages/abi-coder/src/FunctionFragment.ts index addc6eed34..c44c9d2d4e 100644 --- a/packages/abi-coder/src/FunctionFragment.ts +++ b/packages/abi-coder/src/FunctionFragment.ts @@ -10,40 +10,39 @@ import { ResolvedAbiType } from './ResolvedAbiType'; import type { DecodedValue, InputValue } from './encoding/coders/AbstractCoder'; import { StdStringCoder } from './encoding/coders/StdStringCoder'; import { TupleCoder } from './encoding/coders/TupleCoder'; -import type { JsonAbi, JsonAbiFunction, JsonAbiFunctionAttribute } from './types/JsonAbi'; +import type { JsonAbiOld, JsonAbiFunction } from './types/JsonAbi'; +import type { AbiFunction, AbiFunctionAttribute } from './types/JsonAbiNew'; import type { EncodingVersion } from './utils/constants'; import { getFunctionInputs } from './utils/getFunctionInputs'; -import { findFunctionByName, findNonVoidInputs, getEncodingVersion } from './utils/json-abi'; +import { findNonVoidInputs, getEncodingVersion } from './utils/json-abi'; import { padValuesWithUndefined } from './utils/padValuesWithUndefined'; -export class FunctionFragment< - TAbi extends JsonAbi = JsonAbi, - FnName extends TAbi['functions'][number]['name'] = string, -> { +export class FunctionFragment { readonly signature: string; readonly selector: string; readonly selectorBytes: Uint8Array; readonly encoding: EncodingVersion; readonly name: string; - readonly jsonFn: JsonAbiFunction; - readonly attributes: readonly JsonAbiFunctionAttribute[]; - - private readonly jsonAbi: JsonAbi; - - constructor(jsonAbi: JsonAbi, name: FnName) { - this.jsonAbi = jsonAbi; - this.jsonFn = findFunctionByName(this.jsonAbi, name); - - this.name = name; - this.signature = FunctionFragment.getSignature(this.jsonAbi, this.jsonFn); + readonly jsonFn: AbiFunction; + readonly attributes: readonly AbiFunctionAttribute[]; + + private readonly jsonAbiOld: JsonAbiOld; + private readonly jsonFnOld: JsonAbiFunction; + + constructor(jsonAbi: JsonAbiOld, fn: AbiFunction) { + this.jsonFn = fn; + this.jsonAbiOld = jsonAbi; + this.jsonFnOld = jsonAbi.functions.find((f) => f.name === fn.name) as JsonAbiFunction; + this.name = fn.name; + this.signature = FunctionFragment.getSignature(this.jsonAbiOld, this.jsonFnOld); this.selector = FunctionFragment.getFunctionSelector(this.signature); - this.selectorBytes = new StdStringCoder().encode(name); + this.selectorBytes = new StdStringCoder().encode(this.name); this.encoding = getEncodingVersion(jsonAbi.encoding); this.attributes = this.jsonFn.attributes ?? []; } - private static getSignature(abi: JsonAbi, fn: JsonAbiFunction): string { + private static getSignature(abi: JsonAbiOld, fn: JsonAbiFunction): string { const inputsSignatures = fn.inputs.map((input) => new ResolvedAbiType(abi, input).getSignature() ); @@ -57,7 +56,7 @@ export class FunctionFragment< } encodeArguments(values: InputValue[]): Uint8Array { - const inputs = getFunctionInputs({ jsonAbi: this.jsonAbi, inputs: this.jsonFn.inputs }); + const inputs = getFunctionInputs({ jsonAbi: this.jsonAbiOld, inputs: this.jsonFnOld.inputs }); const mandatoryInputLength = inputs.filter((i) => !i.isOptional).length; if (values.length < mandatoryInputLength) { throw new FuelError( @@ -66,8 +65,8 @@ export class FunctionFragment< ); } - const coders = this.jsonFn.inputs.map((t) => - AbiCoder.getCoder(this.jsonAbi, t, { + const coders = this.jsonFnOld.inputs.map((t) => + AbiCoder.getCoder(this.jsonAbiOld, t, { encoding: this.encoding, }) ); @@ -78,7 +77,7 @@ export class FunctionFragment< decodeArguments(data: BytesLike) { const bytes = arrayify(data); - const nonVoidInputs = findNonVoidInputs(this.jsonAbi, this.jsonFn.inputs); + const nonVoidInputs = findNonVoidInputs(this.jsonAbiOld, this.jsonFnOld.inputs); if (nonVoidInputs.length === 0) { // The VM is current return 0x0000000000000000, but we should treat it as undefined / void @@ -103,9 +102,9 @@ export class FunctionFragment< ); } - const result = this.jsonFn.inputs.reduce( + const result = this.jsonFnOld.inputs.reduce( (obj: { decoded: unknown[]; offset: number }, input) => { - const coder = AbiCoder.getCoder(this.jsonAbi, input, { encoding: this.encoding }); + const coder = AbiCoder.getCoder(this.jsonAbiOld, input, { encoding: this.encoding }); const [decodedValue, decodedValueByteSize] = coder.decode(bytes, obj.offset); return { @@ -121,7 +120,7 @@ export class FunctionFragment< decodeOutput(data: BytesLike): [DecodedValue | undefined, number] { const bytes = arrayify(data); - const coder = AbiCoder.getCoder(this.jsonAbi, this.jsonFn.output, { + const coder = AbiCoder.getCoder(this.jsonAbiOld, this.jsonFnOld.output, { encoding: this.encoding, }); @@ -135,6 +134,6 @@ export class FunctionFragment< */ isReadOnly(): boolean { const storageAttribute = this.attributes.find((attr) => attr.name === 'storage'); - return !storageAttribute?.arguments.includes('write'); + return !storageAttribute?.arguments?.includes('write'); } } diff --git a/packages/abi-coder/src/Interface.ts b/packages/abi-coder/src/Interface.ts index c2f9404bb6..be85aa6f7d 100644 --- a/packages/abi-coder/src/Interface.ts +++ b/packages/abi-coder/src/Interface.ts @@ -5,23 +5,26 @@ import { arrayify } from '@fuel-ts/utils'; import { AbiCoder } from './AbiCoder'; import { FunctionFragment } from './FunctionFragment'; -import type { InputValue } from './encoding/coders/AbstractCoder'; -import type { JsonAbi, JsonAbiConfigurable } from './types/JsonAbi'; +import type { DecodedValue, InputValue } from './encoding/coders/AbstractCoder'; +import type { JsonAbiArgument, JsonAbiOld } from './types/JsonAbi'; +import type { Configurable, JsonAbi } from './types/JsonAbiNew'; import { type EncodingVersion } from './utils/constants'; -import { findTypeById, getEncodingVersion } from './utils/json-abi'; +import { getEncodingVersion } from './utils/json-abi'; +import { parseConcreteType, transpileAbi } from './utils/transpile-abi'; -export class Interface { +export class Interface { readonly functions!: Record; - readonly configurables: Record; - readonly jsonAbi: TAbi; + readonly configurables: Record; + readonly jsonAbi: JsonAbi; readonly encoding: EncodingVersion; + private readonly jsonAbiOld: JsonAbiOld; - constructor(jsonAbi: TAbi) { + constructor(jsonAbi: JsonAbi) { this.jsonAbi = jsonAbi; - this.encoding = getEncodingVersion(jsonAbi.encoding); - + this.encoding = getEncodingVersion(jsonAbi.encodingVersion); + this.jsonAbiOld = transpileAbi(jsonAbi) as JsonAbiOld; this.functions = Object.fromEntries( - this.jsonAbi.functions.map((x) => [x.name, new FunctionFragment(this.jsonAbi, x.name)]) + this.jsonAbi.functions.map((fn) => [fn.name, new FunctionFragment(this.jsonAbiOld, fn)]) ); this.configurables = Object.fromEntries(this.jsonAbi.configurables.map((x) => [x.name, x])); @@ -58,7 +61,7 @@ export class Interface { } decodeLog(data: BytesLike, logId: string): any { - const loggedType = this.jsonAbi.loggedTypes.find((type) => type.logId === logId); + const loggedType = this.jsonAbiOld.loggedTypes.find((type) => type.logId === logId); if (!loggedType) { throw new FuelError( ErrorCode.LOG_TYPE_NOT_FOUND, @@ -66,13 +69,13 @@ export class Interface { ); } - return AbiCoder.decode(this.jsonAbi, loggedType.loggedType, arrayify(data), 0, { + return AbiCoder.decode(this.jsonAbiOld, loggedType.loggedType, arrayify(data), 0, { encoding: this.encoding, }); } encodeConfigurable(name: string, value: InputValue) { - const configurable = this.jsonAbi.configurables.find((c) => c.name === name); + const configurable = this.jsonAbiOld.configurables.find((c) => c.name === name); if (!configurable) { throw new FuelError( ErrorCode.CONFIGURABLE_NOT_FOUND, @@ -80,12 +83,31 @@ export class Interface { ); } - return AbiCoder.encode(this.jsonAbi, configurable.configurableType, value, { + return AbiCoder.encode(this.jsonAbiOld, configurable.configurableType, value, { + encoding: this.encoding, + }); + } + + encodeType(concreteTypeId: string, value: InputValue): Uint8Array { + const typeArg = parseConcreteType( + this.jsonAbi, + this.jsonAbiOld.types, + concreteTypeId, + '' + ) as JsonAbiArgument; + return AbiCoder.encode(this.jsonAbiOld, typeArg, value, { encoding: this.encoding, }); } - getTypeById(typeId: number) { - return findTypeById(this.jsonAbi, typeId); + decodeType(concreteTypeId: string, data: Uint8Array): [DecodedValue | undefined, number] { + const typeArg = parseConcreteType( + this.jsonAbi, + this.jsonAbiOld.types, + concreteTypeId, + '' + ) as JsonAbiArgument; + + return AbiCoder.decode(this.jsonAbiOld, typeArg, data, 0, { encoding: this.encoding }); } } diff --git a/packages/abi-coder/src/ResolvedAbiType.ts b/packages/abi-coder/src/ResolvedAbiType.ts index c97e077a67..49e358fce4 100644 --- a/packages/abi-coder/src/ResolvedAbiType.ts +++ b/packages/abi-coder/src/ResolvedAbiType.ts @@ -1,17 +1,17 @@ import { FuelError, ErrorCode } from '@fuel-ts/errors'; -import type { JsonAbi, JsonAbiArgument } from './types/JsonAbi'; +import type { JsonAbiOld, JsonAbiArgument } from './types/JsonAbi'; import { arrayRegEx, enumRegEx, genericRegEx, stringRegEx, structRegEx } from './utils/constants'; import { findTypeById } from './utils/json-abi'; export class ResolvedAbiType { - readonly abi: JsonAbi; + readonly abi: JsonAbiOld; name: string; readonly type: string; readonly originalTypeArguments: readonly JsonAbiArgument[] | null; readonly components: readonly ResolvedAbiType[] | null; - constructor(abi: JsonAbi, argument: JsonAbiArgument) { + constructor(abi: JsonAbiOld, argument: JsonAbiArgument) { this.abi = abi; this.name = argument.name; @@ -37,7 +37,7 @@ export class ResolvedAbiType { } private static getResolvedGenericComponents( - abi: JsonAbi, + abi: JsonAbiOld, arg: JsonAbiArgument, components: readonly JsonAbiArgument[] | null, typeParameters: readonly number[] | null @@ -70,7 +70,7 @@ export class ResolvedAbiType { } private static resolveGenericArgTypes( - abi: JsonAbi, + abi: JsonAbiOld, args: readonly JsonAbiArgument[], typeParametersAndArgsMap: Record ): readonly JsonAbiArgument[] { @@ -108,7 +108,7 @@ export class ResolvedAbiType { } private static getImplicitGenericTypeParameters( - abi: JsonAbi, + abi: JsonAbiOld, args: readonly JsonAbiArgument[] | null, implicitGenericParametersParam?: number[] ) { diff --git a/packages/abi-coder/src/encoding/coders/EnumCoder.ts b/packages/abi-coder/src/encoding/coders/EnumCoder.ts index 0124042bfe..d6ace8c61a 100644 --- a/packages/abi-coder/src/encoding/coders/EnumCoder.ts +++ b/packages/abi-coder/src/encoding/coders/EnumCoder.ts @@ -3,7 +3,7 @@ import { toNumber } from '@fuel-ts/math'; import { concat } from '@fuel-ts/utils'; import type { RequireExactlyOne } from 'type-fest'; -import { OPTION_CODER_TYPE, VOID_TYPE } from '../../utils/constants'; +import { OPTION_CODER_TYPE, optionRegEx, VOID_TYPE } from '../../utils/constants'; import { hasNestedOption } from '../../utils/utilities'; import type { TypesOfCoder } from './AbstractCoder'; @@ -38,7 +38,7 @@ export class EnumCoder> extends Coder< this.coders = coders; this.#caseIndexCoder = caseIndexCoder; this.#encodedValueSize = encodedValueSize; - this.#shouldValidateLength = !(this.type === OPTION_CODER_TYPE || hasNestedOption(coders)); + this.#shouldValidateLength = !(optionRegEx.test(this.type) || hasNestedOption(coders)); } // Checks that we're handling a native enum that is of type void. diff --git a/packages/abi-coder/src/encoding/coders/OptionCoder.test.ts b/packages/abi-coder/src/encoding/coders/OptionCoder.test.ts index 9da3f03a3d..e43ca57921 100644 --- a/packages/abi-coder/src/encoding/coders/OptionCoder.test.ts +++ b/packages/abi-coder/src/encoding/coders/OptionCoder.test.ts @@ -7,7 +7,7 @@ import { VoidCoder } from './VoidCoder'; * @group browser */ describe('OptionCoder', () => { - const coder = new OptionCoder('Option', { + const coder = new OptionCoder('std::option::Option', { Some: new NumberCoder('u8'), None: new VoidCoder(), }); diff --git a/packages/abi-coder/src/encoding/strategies/getCoderV1.ts b/packages/abi-coder/src/encoding/strategies/getCoderV1.ts index 816fc1d393..fb53bbbc6e 100644 --- a/packages/abi-coder/src/encoding/strategies/getCoderV1.ts +++ b/packages/abi-coder/src/encoding/strategies/getCoderV1.ts @@ -23,6 +23,7 @@ import { VOID_TYPE, arrayRegEx, enumRegEx, + fullNameRegExMatch, stringRegEx, structRegEx, tupleRegEx, @@ -126,21 +127,23 @@ export const getCoder: GetCoderFn = ( return new VecCoder(itemCoder as Coder); } - const structMatch = structRegEx.exec(resolvedAbiType.type)?.groups; - if (structMatch) { + // component name + const coderName = resolvedAbiType.type.match(fullNameRegExMatch)?.[0]; + + const structMatch = structRegEx.test(resolvedAbiType.type); + if (structMatch && coderName) { const coders = getCoders(components, { getCoder }); - return new StructCoder(structMatch.name, coders); + return new StructCoder(coderName, coders); } - const enumMatch = enumRegEx.exec(resolvedAbiType.type)?.groups; - if (enumMatch) { + const enumMatch = enumRegEx.test(resolvedAbiType.type); + if (enumMatch && coderName) { const coders = getCoders(components, { getCoder }); - const isOptionEnum = resolvedAbiType.type === OPTION_CODER_TYPE; if (isOptionEnum) { - return new OptionCoder(enumMatch.name, coders); + return new OptionCoder(coderName, coders); } - return new EnumCoder(enumMatch.name, coders); + return new EnumCoder(coderName, coders); } const tupleMatch = tupleRegEx.exec(resolvedAbiType.type)?.groups; diff --git a/packages/abi-coder/src/index.ts b/packages/abi-coder/src/index.ts index 741fcd60b1..ffc8e62a1b 100644 --- a/packages/abi-coder/src/index.ts +++ b/packages/abi-coder/src/index.ts @@ -2,7 +2,7 @@ export { Coder, InputValue, DecodedValue } from './encoding/coders/AbstractCoder export type { FunctionFragment } from './FunctionFragment'; export * from './encoding/coders'; export { Interface } from './Interface'; -export { JsonAbi, JsonAbiArgument } from './types/JsonAbi'; +export type { JsonAbi } from './types/JsonAbiNew'; export { SCRIPT_FIXED_SIZE, INPUT_COIN_FIXED_SIZE, @@ -14,4 +14,3 @@ export { calculateVmTxMemory, ENCODING_V1, } from './utils/constants'; -export { AbiCoder } from './AbiCoder'; diff --git a/packages/abi-coder/src/types/JsonAbi.ts b/packages/abi-coder/src/types/JsonAbi.ts index 2e481d27aa..eed9fee4d4 100644 --- a/packages/abi-coder/src/types/JsonAbi.ts +++ b/packages/abi-coder/src/types/JsonAbi.ts @@ -1,8 +1,8 @@ /** * Types for Fuel JSON ABI Format as defined on: - * https://github.com/FuelLabs/fuel-specs/blob/master/src/abi/json-abi-format.md + * https://github.com/FuelLabs/fuel-specs/blob/b40d87d2515727188b9ae2dd23602316c50519c0/src/abi/json-abi-format.md */ -export interface JsonAbi { +export interface JsonAbiOld { readonly types: readonly JsonAbiType[]; readonly loggedTypes: readonly JsonAbiLoggedType[]; readonly functions: readonly JsonAbiFunction[]; diff --git a/packages/abi-coder/src/types/JsonAbiNew.ts b/packages/abi-coder/src/types/JsonAbiNew.ts new file mode 100644 index 0000000000..4d9481c112 --- /dev/null +++ b/packages/abi-coder/src/types/JsonAbiNew.ts @@ -0,0 +1,101 @@ +/** + * Types for Fuel JSON ABI Format as defined on: + * https://github.com/FuelLabs/fuel-specs/blob/master/src/abi/json-abi-format.md + */ +export interface JsonAbi { + readonly specVersion: string; + readonly encodingVersion: string; + readonly programType: string; + readonly concreteTypes: readonly ConcreteType[]; + readonly metadataTypes: readonly MetadataType[]; + readonly functions: readonly AbiFunction[]; + readonly loggedTypes: readonly LoggedType[]; + readonly messagesTypes: readonly MessageType[]; + readonly configurables: readonly Configurable[]; +} + +export interface ConcreteType { + readonly type: string; + readonly concreteTypeId: string; + readonly metadataTypeId?: number; + readonly typeArguments?: readonly string[]; +} + +export interface MetadataType { + readonly type: string; + readonly metadataTypeId: number; + readonly components?: readonly Component[]; + readonly typeParameters?: readonly number[]; +} + +export interface Component extends TypeArgument { + readonly name: string; +} + +export interface TypeArgument { + readonly typeId: number | string; // the type metadata declaration ID or type concrete declaration hash based ID of the type of the component. + readonly typeArguments?: readonly TypeArgument[]; +} + +export interface AbiFunction { + readonly name: string; + readonly inputs: readonly AbiFunctionInput[]; + readonly output: string; + readonly attributes: readonly AbiFunctionAttribute[] | null; +} + +export interface AbiFunctionInput { + readonly name: string; + readonly concreteTypeId: string; +} + +export type AbiFunctionAttribute = { + readonly name: string; + readonly arguments?: string[]; +}; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +type AbiFunctionAttributeTodo = + | StorageAttr + | PayableAttr + | TestAttr + | InlineAttr + | DocCommentAttr + | DocAttr; + +export interface PayableAttr { + readonly name: 'payable'; +} +export interface StorageAttr { + readonly name: 'storage'; + readonly arguments: readonly ('read' | 'write')[]; +} +export interface TestAttr { + readonly name: 'test'; +} +export interface InlineAttr { + readonly name: 'inline'; + readonly arguments: 'never' | 'always'; +} +export interface DocCommentAttr { + readonly name: 'doc-comment'; + readonly arguments: string[]; +} +export interface DocAttr { + readonly name: 'doc'; +} + +export interface LoggedType { + readonly logId: string; + readonly concreteTypeId: string; // the _type concrete declaration_ hash based ID of the value being logged. +} + +export interface MessageType { + readonly message_id: string; + readonly concreteTypeId: string; +} +export interface Configurable { + readonly name: string; + readonly concreteTypeId: string; + readonly offset: number; +} diff --git a/packages/abi-coder/src/utils/constants.ts b/packages/abi-coder/src/utils/constants.ts index 7deac9d778..62dab90648 100644 --- a/packages/abi-coder/src/utils/constants.ts +++ b/packages/abi-coder/src/utils/constants.ts @@ -10,20 +10,24 @@ export const RAW_PTR_CODER_TYPE = 'raw untyped ptr'; export const RAW_SLICE_CODER_TYPE = 'raw untyped slice'; export const BOOL_CODER_TYPE = 'bool'; export const B256_CODER_TYPE = 'b256'; -export const B512_CODER_TYPE = 'struct B512'; -export const OPTION_CODER_TYPE = 'enum Option'; -export const VEC_CODER_TYPE = 'struct Vec'; -export const BYTES_CODER_TYPE = 'struct Bytes'; -export const STD_STRING_CODER_TYPE = 'struct String'; +export const B512_CODER_TYPE = 'struct std::b512::B512'; +export const OPTION_CODER_TYPE = 'enum std::option::Option'; +export const VEC_CODER_TYPE = 'struct std::vec::Vec'; +export const BYTES_CODER_TYPE = 'struct std::bytes::Bytes'; +export const STD_STRING_CODER_TYPE = 'struct std::string::String'; export const STR_SLICE_CODER_TYPE = 'str'; export const VOID_TYPE = '()'; -export const OPTION_REGEX: RegExp = /^enum (std::option::)?Option$/m; + +export const optionRegEx: RegExp = /^enum (std::option::)?Option$/m; export const stringRegEx = /str\[(?[0-9]+)\]/; export const arrayRegEx = /\[(?[\w\s\\[\]]+);\s*(?[0-9]+)\]/; -export const structRegEx = /^struct (?\w+)$/; -export const enumRegEx = /^enum (?\w+)$/; +export const structRegEx = /struct.+/; +export const enumRegEx = /^enum.+$/; export const tupleRegEx = /^\((?.*)\)$/; -export const genericRegEx = /^generic (?\w+)$/; +export const genericRegEx = /^generic.+$/; + +export const fullNameRegExMatch = /([^\s]+)$/m; + /** * Encoding versions */ diff --git a/packages/abi-coder/src/utils/getFunctionInputs.ts b/packages/abi-coder/src/utils/getFunctionInputs.ts index 784694847b..44c9abcaec 100644 --- a/packages/abi-coder/src/utils/getFunctionInputs.ts +++ b/packages/abi-coder/src/utils/getFunctionInputs.ts @@ -1,6 +1,6 @@ -import type { JsonAbi, JsonAbiArgument } from '../types/JsonAbi'; +import type { JsonAbiOld, JsonAbiArgument } from '../types/JsonAbi'; -import { OPTION_REGEX, VOID_TYPE } from './constants'; +import { optionRegEx, VOID_TYPE } from './constants'; import { findTypeById } from './json-abi'; export type FunctionInput = TArg & { @@ -8,7 +8,7 @@ export type FunctionInput = TArg }; export const getFunctionInputs = (params: { - jsonAbi: JsonAbi; + jsonAbi: JsonAbiOld; inputs: readonly JsonAbiArgument[]; }): Array => { const { jsonAbi, inputs } = params; @@ -16,7 +16,7 @@ export const getFunctionInputs = (params: { return inputs.reduceRight((result, input) => { const type = findTypeById(jsonAbi, input.type); - isMandatory = isMandatory || (type.type !== VOID_TYPE && !OPTION_REGEX.test(type.type)); + isMandatory = isMandatory || (type.type !== VOID_TYPE && !optionRegEx.test(type.type)); return [{ ...input, isOptional: !isMandatory }, ...result]; }, [] as FunctionInput[]); }; diff --git a/packages/abi-coder/src/utils/json-abi.test.ts b/packages/abi-coder/src/utils/json-abi.test.ts index be661e335a..d81d28576a 100644 --- a/packages/abi-coder/src/utils/json-abi.test.ts +++ b/packages/abi-coder/src/utils/json-abi.test.ts @@ -1,5 +1,5 @@ import type { ResolvedAbiType } from '../ResolvedAbiType'; -import type { JsonAbi, JsonAbiArgument } from '../types/JsonAbi'; +import type { JsonAbiOld, JsonAbiArgument } from '../types/JsonAbi'; import { ENCODING_V1 } from './constants'; import { @@ -10,7 +10,7 @@ import { getEncodingVersion, } from './json-abi'; -const MOCK_ABI: JsonAbi = { +const MOCK_ABI: JsonAbiOld = { types: [ { typeId: 1, type: '()', components: [], typeParameters: [] }, { typeId: 2, type: 'u256', components: [], typeParameters: [] }, diff --git a/packages/abi-coder/src/utils/json-abi.ts b/packages/abi-coder/src/utils/json-abi.ts index 1091554c8a..0d168cd522 100644 --- a/packages/abi-coder/src/utils/json-abi.ts +++ b/packages/abi-coder/src/utils/json-abi.ts @@ -1,7 +1,8 @@ import { ErrorCode, FuelError } from '@fuel-ts/errors'; import type { ResolvedAbiType } from '../ResolvedAbiType'; -import type { JsonAbi, JsonAbiArgument, JsonAbiFunction, JsonAbiType } from '../types/JsonAbi'; +import type { JsonAbiOld, JsonAbiArgument, JsonAbiType } from '../types/JsonAbi'; +import type { AbiFunction, JsonAbi } from '../types/JsonAbiNew'; import { ENCODING_V1, VOID_TYPE, type EncodingVersion } from './constants'; @@ -33,7 +34,7 @@ export const getEncodingVersion = (encoding?: string): EncodingVersion => { * @param name - the name of the function to find * @returns the JsonAbi function object */ -export const findFunctionByName = (abi: JsonAbi, name: string): JsonAbiFunction => { +export const findFunctionByName = (abi: JsonAbi, name: string): AbiFunction => { const fn = abi.functions.find((f) => f.name === name); if (!fn) { throw new FuelError( @@ -51,7 +52,7 @@ export const findFunctionByName = (abi: JsonAbi, name: string): JsonAbiFunction * @param typeId - the typeId of the type to find * @returns the JsonAbi type object */ -export const findTypeById = (abi: JsonAbi, typeId: number): JsonAbiType => { +export const findTypeById = (abi: JsonAbiOld, typeId: number): JsonAbiType => { const type = abi.types.find((t) => t.typeId === typeId); if (!type) { throw new FuelError( @@ -71,7 +72,7 @@ export const findTypeById = (abi: JsonAbi, typeId: number): JsonAbiType => { * @returns the list of non-void inputs */ export const findNonVoidInputs = ( - abi: JsonAbi, + abi: JsonAbiOld, inputs: readonly JsonAbiArgument[] ): JsonAbiArgument[] => inputs.filter((input) => findTypeById(abi, input.type).type !== VOID_TYPE); diff --git a/packages/abi-coder/src/utils/transpile-abi.ts b/packages/abi-coder/src/utils/transpile-abi.ts new file mode 100644 index 0000000000..2d1d061d7b --- /dev/null +++ b/packages/abi-coder/src/utils/transpile-abi.ts @@ -0,0 +1,146 @@ +/* eslint-disable no-restricted-globals */ +/* eslint-disable no-param-reassign */ +/* eslint-disable @typescript-eslint/no-use-before-define */ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-nocheck + +const findTypeByConcreteId = (types, id) => types.find((x) => x.concreteTypeId === id); + +const findConcreteTypeById = (abi, id) => abi.concreteTypes.find((x) => x.concreteTypeId === id); + +function finsertTypeIdByConcreteTypeId(abi, types, id) { + const concreteType = findConcreteTypeById(abi, id); + + if (concreteType.metadataTypeId !== undefined) { + return concreteType.metadataTypeId; + } + + const type = findTypeByConcreteId(types, id); + if (type) { + return type.typeId; + } + + types.push({ + typeId: types.length, + type: concreteType.type, + components: parseComponents(concreteType.components), + concreteTypeId: id, + typeParameters: concreteType.typeParameters ?? null, + originalConcreteTypeId: concreteType?.concreteTypeId, + }); + + return types.length - 1; +} + +function parseFunctionTypeArguments(abi, types, concreteType) { + return ( + concreteType.typeArguments?.map((cTypeId) => { + const self = findConcreteTypeById(abi, cTypeId); + const type = !isNaN(cTypeId) ? cTypeId : finsertTypeIdByConcreteTypeId(abi, types, cTypeId); + return { + name: '', + type, + // originalTypeId: cTypeId, + typeArguments: parseFunctionTypeArguments(abi, types, self), + }; + }) ?? null + ); +} + +export function parseConcreteType(abi, types, concreteTypeId, name) { + const type = finsertTypeIdByConcreteTypeId(abi, types, concreteTypeId); + const concrete = findConcreteTypeById(abi, concreteTypeId); + return { + name: name ?? '', + type, + // concreteTypeId, + typeArguments: parseFunctionTypeArguments(abi, types, concrete), + }; +} + +function parseComponents(abi, types, components) { + return ( + components?.map((component) => { + const { typeId, name, typeArguments } = component; + const type = !isNaN(typeId) ? typeId : finsertTypeIdByConcreteTypeId(abi, types, typeId); + return { + name, + type, + // originalTypeId: typeId, + typeArguments: parseComponents(abi, types, typeArguments), + }; + }) ?? null + ); +} + +/** + * This will transpile new ABIs (spec: "1") to the old format. + * + * The new format got these new props: + * - `specVersion`, + * - `concreteTypes` + * - `metadataTypes` + * + * The old format contains only: + * - `types` + */ +export function transpileAbi(abi) { + // do not transpile older versions + if (!abi.specVersion) { + return abi; + } + + // 0. define empty types array + const types = []; + + // 1. root level of metadata types + abi.metadataTypes.forEach((m) => { + const t = { + typeId: m.metadataTypeId, + type: m.type, + components: m.components ?? (m.type === '()' ? [] : null), + typeParameters: m.typeParameters ?? null, + }; + types.push(t); + }); + + // 2. the metadata's components + types.forEach((t) => { + t.components = parseComponents(abi, types, t.components); + }); + + // 3. functions inputs/outputs + const functions = abi.functions.map((fn) => { + const inputs = fn.inputs.map(({ concreteTypeId, name }) => + parseConcreteType(abi, types, concreteTypeId, name) + ); + const output = parseConcreteType(abi, types, fn.output, ''); + return { ...fn, inputs, output }; + }); + + // 4. configurables + const configurables = abi.configurables.map((conf) => ({ + name: conf.name, + configurableType: parseConcreteType(abi, types, conf.concreteTypeId), + offset: conf.offset, + })); + + // 5. loggedTypes + const loggedTypes = abi.loggedTypes.map((log) => ({ + logId: log.logId, + loggedType: parseConcreteType(abi, types, log.concreteTypeId), + })); + + // transpiled ABI + const transpiled = { + encoding: abi.encodingVersion, + types, + functions, + loggedTypes, + messagesTypes: abi.messagesTypes, + configurables, + }; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return transpiled as any; +} diff --git a/packages/abi-coder/src/utils/utilities.test.ts b/packages/abi-coder/src/utils/utilities.test.ts index 81a4bf5e73..91507de900 100644 --- a/packages/abi-coder/src/utils/utilities.test.ts +++ b/packages/abi-coder/src/utils/utilities.test.ts @@ -1,3 +1,4 @@ +import { OPTION_CODER_TYPE } from './constants'; import { hasNestedOption, type TCoders } from './utilities'; /** @@ -15,7 +16,7 @@ describe('findNestedOption', () => { coders: { a: { name: 'tuple', - type: '(boolean, [enum Option; 3])', + type: `(boolean, [${OPTION_CODER_TYPE}; 3])`, encodedLength: 28, coders: [ { @@ -26,12 +27,12 @@ describe('findNestedOption', () => { }, { name: 'array', - type: '[enum Option; 3]', + type: `[${OPTION_CODER_TYPE}; 3]`, encodedLength: 27, // Deeply nested option coder: { name: 'Option', - type: 'enum Option', + type: `${OPTION_CODER_TYPE}`, encodedLength: 9, coders: { None: { name: 'tuple', type: '()', encodedLength: 0, coders: [] }, @@ -65,7 +66,7 @@ describe('findNestedOption', () => { coders: { a: { name: 'tuple', - type: '(boolean, [enum Option; 3])', + type: `(boolean, [${OPTION_CODER_TYPE}; 3])`, encodedLength: 28, coders: [ { @@ -76,7 +77,7 @@ describe('findNestedOption', () => { }, { name: 'array', - type: '[enum Option; 3]', + type: `[${OPTION_CODER_TYPE}; 3]`, encodedLength: 27, coder: { name: 'AnotherEnum', diff --git a/packages/abi-coder/test/Interface.test.ts b/packages/abi-coder/test/Interface.test.ts index b50ed8c23c..4e28fa3762 100644 --- a/packages/abi-coder/test/Interface.test.ts +++ b/packages/abi-coder/test/Interface.test.ts @@ -2,11 +2,11 @@ import type { BN } from '@fuel-ts/math'; import { concat } from '@fuel-ts/utils'; -import { Interface } from '../src'; -/** @knipignore */ -import type { JsonAbiConfigurable } from '../src/json-abi'; +import { Interface } from '../src/Interface'; +import type { JsonAbiConfigurable } from '../src/types/JsonAbi'; +import type { AbiFunction } from '../src/types/JsonAbiNew'; -import exhaustiveExamplesAbi from './fixtures/forc-projects/exhaustive-examples/out/release/exhaustive-examples-abi.json'; +import { AbiCoderProjectsEnum, getCoderForcProject } from './fixtures/forc-projects'; import { B256_DECODED, B256_ENCODED, @@ -35,6 +35,10 @@ import { U8_MIN_ENCODED, } from './utils/constants'; +const exhaustiveExamplesAbi = getCoderForcProject( + AbiCoderProjectsEnum.EXHAUSTIVE_EXAMPLES +).abiContents; + const exhaustiveExamplesInterface = new Interface(exhaustiveExamplesAbi); /** @@ -577,16 +581,30 @@ describe('Abi interface', () => { ])( '$title: $value', ({ fn, title: _title, value, encodedValue, decodedTransformer, offset }) => { - const encoded = Array.isArray(value) - ? fn.encodeArguments(value) - : fn.encodeArguments([value]); + const fnArguments = Array.isArray(value) ? value : [value]; + const encodedArguments = fn.encodeArguments(fnArguments); const encodedVal = encodedValue instanceof Function ? encodedValue(value, offset) : encodedValue; const expectedEncoded = encodedVal instanceof Uint8Array ? encodedVal : concat(encodedVal); - expect(encoded).toEqual(expectedEncoded); + expect(encodedArguments).toEqual(expectedEncoded); + + const jsonFn = exhaustiveExamplesInterface.jsonAbi.functions.find( + (f) => f.name === fn.name + ) as AbiFunction; + + // test Interface.encodeType + const argsEncodedAsSingleTypes = jsonFn.inputs + .map((i) => i.concreteTypeId) + .map((arg, idx) => exhaustiveExamplesInterface.encodeType(arg, fnArguments[idx])); + + argsEncodedAsSingleTypes?.forEach((arg, idx, arr) => { + const argOffset = arr.slice(0, idx).reduce((result, val) => result + val.length, 0); + + expect(arg).toEqual(expectedEncoded.slice(argOffset, argOffset + arg.length)); + }); let decoded = fn.decodeOutput(expectedEncoded)[0]; @@ -597,6 +615,18 @@ describe('Abi interface', () => { const expectedDecoded = Array.isArray(value) && value.length === 1 ? value[0] : value; // the conditional is when the input is a SINGLE array/tuple - then de-nest it expect(decoded).toStrictEqual(expectedDecoded); + + // test Interface.decodeType + let decodedType = exhaustiveExamplesInterface.decodeType( + jsonFn.output, + expectedEncoded + )[0]; + + if (decodedTransformer) { + decodedType = decodedTransformer(decodedType); + } + + expect(decodedType).toEqual(expectedDecoded); } ); }); @@ -725,20 +755,4 @@ describe('Abi interface', () => { }); }); }); - - describe('abi types', () => { - it('should return the correct type when it exists', () => { - const abiType = exhaustiveExamplesInterface.getTypeById(0); - expect(abiType.type).toEqual('()'); - expect(abiType.components).toBeDefined(); - expect(abiType.typeParameters).toBeNull(); - }); - - it('should throw an error when type does not exist', () => { - const id = 999; - expect(() => exhaustiveExamplesInterface.getTypeById(id)).toThrowError( - `Type with typeId '${id}' doesn't exist in the ABI.` - ); - }); - }); }); diff --git a/packages/abi-coder/test/fixtures/forc-projects/index.ts b/packages/abi-coder/test/fixtures/forc-projects/index.ts new file mode 100644 index 0000000000..660c5d345d --- /dev/null +++ b/packages/abi-coder/test/fixtures/forc-projects/index.ts @@ -0,0 +1,18 @@ +import { getForcProject } from '@fuel-ts/utils/test-utils'; +import { join } from 'path'; + +import type { JsonAbi } from '../../../src'; + +export enum AbiCoderProjectsEnum { + EXHAUSTIVE_EXAMPLES = 'exhaustive-examples', +} + +export const getCoderForcProject = ( + project: AbiCoderProjectsEnum, + build: 'release' | 'debug' = 'release' +) => + getForcProject({ + projectDir: join(__dirname, project), + projectName: project, + build, + }); diff --git a/packages/abi-coder/tsconfig.json b/packages/abi-coder/tsconfig.json index b0fced27d7..b22c89a4b3 100644 --- a/packages/abi-coder/tsconfig.json +++ b/packages/abi-coder/tsconfig.json @@ -3,5 +3,5 @@ "compilerOptions": { "outDir": "./dist" }, - "include": ["src"] + "include": ["src", "test"] } diff --git a/packages/abi-typegen/package.json b/packages/abi-typegen/package.json index 7749454c4e..24535136de 100644 --- a/packages/abi-typegen/package.json +++ b/packages/abi-typegen/package.json @@ -43,12 +43,11 @@ "dist" ], "scripts": { - "pretest": "run-s build:forc-callpaths build:forc", + "pretest": "run-s build build:forc", "test": "cd ../.. && pnpm run test:filter packages/abi-typegen", "test:update-fixtures": "UPDATE_FIXTURES=true pnpm run test", "build": "tsup", "build:forc": "pnpm fuels-forc build -p test/fixtures/forc-projects --release", - "build:forc-callpaths": "pnpm fuels-forc build -p test/fixtures/forc-projects --json-abi-with-callpaths", "postbuild": "tsx ../../scripts/postbuild.ts" }, "license": "Apache-2.0", diff --git a/packages/abi-typegen/src/abi/Abi.ts b/packages/abi-typegen/src/abi/Abi.ts index 2a098f653b..f5d40ece69 100644 --- a/packages/abi-typegen/src/abi/Abi.ts +++ b/packages/abi-typegen/src/abi/Abi.ts @@ -5,9 +5,11 @@ import type { ProgramTypeEnum } from '../types/enums/ProgramTypeEnum'; import type { IConfigurable } from '../types/interfaces/IConfigurable'; import type { IFunction } from '../types/interfaces/IFunction'; import type { IType } from '../types/interfaces/IType'; -import type { JsonAbi } from '../types/interfaces/JsonAbi'; +import type { JsonAbiOld } from '../types/interfaces/JsonAbi'; +import type { JsonAbi } from '../types/interfaces/JsonAbiNew'; import { parseFunctions } from '../utils/parseFunctions'; import { parseTypes } from '../utils/parseTypes'; +import { transpileAbi } from '../utils/transpile-abi'; import { Configurable } from './configurable/Configurable'; @@ -81,11 +83,12 @@ export class Abi { } parse() { + const transpiled = transpileAbi(this.rawContents) as JsonAbiOld; const { types: rawAbiTypes, functions: rawAbiFunctions, configurables: rawAbiConfigurables, - } = this.rawContents; + } = transpiled; const types = parseTypes({ rawAbiTypes }); const functions = parseFunctions({ rawAbiFunctions, types }); diff --git a/packages/abi-typegen/src/abi/configurable/Configurable.test.ts b/packages/abi-typegen/src/abi/configurable/Configurable.test.ts index 37d5022084..338bbc890a 100644 --- a/packages/abi-typegen/src/abi/configurable/Configurable.test.ts +++ b/packages/abi-typegen/src/abi/configurable/Configurable.test.ts @@ -43,7 +43,9 @@ describe('Configurable.ts', () => { it('should get configurable declaration with type', () => { const { type, findType } = mockAllDeps(); - const project = getTypegenForcProject(AbiTypegenProjectsEnum.PREDICATE_WITH_CONFIGURABLE); + const project = getTypegenForcProject(AbiTypegenProjectsEnum.PREDICATE_WITH_CONFIGURABLE, { + transpile: true, + }); const { configurables } = project.abiContents; diff --git a/packages/abi-typegen/src/abi/functions/Function.test.ts b/packages/abi-typegen/src/abi/functions/Function.test.ts index 8270f48e98..e08696a814 100644 --- a/packages/abi-typegen/src/abi/functions/Function.test.ts +++ b/packages/abi-typegen/src/abi/functions/Function.test.ts @@ -14,7 +14,7 @@ describe('Function.ts', () => { Method: `getDeclaration` */ test('should properly get function declaration', () => { - const project = getTypegenForcProject(AbiTypegenProjectsEnum.MINIMAL); + const project = getTypegenForcProject(AbiTypegenProjectsEnum.MINIMAL, { transpile: true }); const { types: rawAbiTypes, functions } = project.abiContents; @@ -35,7 +35,9 @@ describe('Function.ts', () => { Inputs / Output */ test('should compute i/o types for Vector', () => { - const project = getTypegenForcProject(AbiTypegenProjectsEnum.VECTOR_SIMPLE); + const project = getTypegenForcProject(AbiTypegenProjectsEnum.VECTOR_SIMPLE, { + transpile: true, + }); const { types: rawAbiTypes, functions } = project.abiContents; @@ -51,7 +53,9 @@ describe('Function.ts', () => { }); test('should build i/o types for Option', () => { - const project = getTypegenForcProject(AbiTypegenProjectsEnum.OPTION_SIMPLE); + const project = getTypegenForcProject(AbiTypegenProjectsEnum.OPTION_SIMPLE, { + transpile: true, + }); const { types: rawAbiTypes, functions } = project.abiContents; diff --git a/packages/abi-typegen/src/abi/types/ArrayType.test.ts b/packages/abi-typegen/src/abi/types/ArrayType.test.ts index 3516400f4d..fb136069f3 100644 --- a/packages/abi-typegen/src/abi/types/ArrayType.test.ts +++ b/packages/abi-typegen/src/abi/types/ArrayType.test.ts @@ -29,7 +29,9 @@ describe('ArrayType.ts', () => { test('should properly parse type attributes: simple', () => { const parseTypeArguments = vi.spyOn(parseTypeArgumentsMod, 'parseTypeArguments'); - const project = getTypegenForcProject(AbiTypegenProjectsEnum.STRUCT_WITH_ARRAY); + const project = getTypegenForcProject(AbiTypegenProjectsEnum.STRUCT_WITH_ARRAY, { + transpile: true, + }); const rawTypes = project.abiContents.types; const types = rawTypes.map((rawAbiType: JsonAbiType) => makeType({ rawAbiType })); @@ -47,12 +49,14 @@ describe('ArrayType.ts', () => { test('should properly parse type attributes: nested', () => { const parseTypeArguments = vi.spyOn(parseTypeArgumentsMod, 'parseTypeArguments'); - const project = getTypegenForcProject(AbiTypegenProjectsEnum.ARRAY_WITH_GENERICS); + const project = getTypegenForcProject(AbiTypegenProjectsEnum.ARRAY_WITH_GENERICS, { + transpile: true, + }); const rawTypes = project.abiContents.types; const types = rawTypes.map((rawAbiType: JsonAbiType) => makeType({ rawAbiType })); - const a = findType({ types, typeId: 1 }) as ArrayType; + const a = findType({ types, typeId: 0 }) as ArrayType; expect(a.attributes.inputLabel).toEqual( '[Generic1Input, string>, Generic1Input, string>]' diff --git a/packages/abi-typegen/src/abi/types/EnumType.test.ts b/packages/abi-typegen/src/abi/types/EnumType.test.ts index 7e462ff837..ee15357833 100644 --- a/packages/abi-typegen/src/abi/types/EnumType.test.ts +++ b/packages/abi-typegen/src/abi/types/EnumType.test.ts @@ -21,7 +21,7 @@ describe('EnumType.ts', () => { function getTypesForContract(project: AbiTypegenProjectsEnum) { const { abiContents: { types: rawTypes }, - } = getTypegenForcProject(project); + } = getTypegenForcProject(project, { transpile: true }); const types = rawTypes.map((rawAbiType: JsonAbiType) => makeType({ rawAbiType })); diff --git a/packages/abi-typegen/src/abi/types/EvmAddressType.test.ts b/packages/abi-typegen/src/abi/types/EvmAddressType.test.ts index 53ec490eb9..8833b5031b 100644 --- a/packages/abi-typegen/src/abi/types/EvmAddressType.test.ts +++ b/packages/abi-typegen/src/abi/types/EvmAddressType.test.ts @@ -18,7 +18,7 @@ describe('EvmAddressType.ts', () => { test('should properly parse type attributes', () => { const parseTypeArguments = vi.spyOn(parseTypeArgumentsMod, 'parseTypeArguments'); - const project = getTypegenForcProject(AbiTypegenProjectsEnum.EVM_ADDRESS); + const project = getTypegenForcProject(AbiTypegenProjectsEnum.EVM_ADDRESS, { transpile: true }); const rawTypes = project.abiContents.types; const types = rawTypes.map((rawAbiType: JsonAbiType) => makeType({ rawAbiType })); @@ -33,7 +33,7 @@ describe('EvmAddressType.ts', () => { parseTypeArguments.mockClear(); - const evmAddress = findType({ types, typeId: 1 }) as EvmAddressType; + const evmAddress = findType({ types, typeId: 0 }) as EvmAddressType; expect(evmAddress.attributes.inputLabel).toEqual('EvmAddress'); expect(evmAddress.attributes.outputLabel).toEqual('EvmAddress'); diff --git a/packages/abi-typegen/src/abi/types/OptionType.test.ts b/packages/abi-typegen/src/abi/types/OptionType.test.ts index c827dea99d..db35d120f6 100644 --- a/packages/abi-typegen/src/abi/types/OptionType.test.ts +++ b/packages/abi-typegen/src/abi/types/OptionType.test.ts @@ -17,7 +17,9 @@ describe('OptionType.ts', () => { Test helpers */ function getTypesForContract() { - const project = getTypegenForcProject(AbiTypegenProjectsEnum.OPTION_SIMPLE); + const project = getTypegenForcProject(AbiTypegenProjectsEnum.OPTION_SIMPLE, { + transpile: true, + }); const rawTypes = project.abiContents.types; const types = rawTypes.map((rawAbiType: JsonAbiType) => makeType({ rawAbiType })); diff --git a/packages/abi-typegen/src/abi/types/ResultType.test.ts b/packages/abi-typegen/src/abi/types/ResultType.test.ts index 80cdf1488a..0016d83454 100644 --- a/packages/abi-typegen/src/abi/types/ResultType.test.ts +++ b/packages/abi-typegen/src/abi/types/ResultType.test.ts @@ -16,10 +16,11 @@ describe('ResultType.ts', () => { Test helpers */ function getResultType() { - const project = getTypegenForcProject(AbiTypegenProjectsEnum.FULL); + const project = getTypegenForcProject(AbiTypegenProjectsEnum.FULL, { transpile: true }); const rawTypes = project.abiContents.types as JsonAbiType[]; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return parseTypes({ rawAbiTypes: [rawTypes.find((t) => t.type === 'enum Result')!] })[0]; + const rawAbiTypes = [rawTypes.find((t) => t.type === 'enum std::result::Result')!]; + return parseTypes({ rawAbiTypes })[0]; } test('should properly evaluate type suitability', () => { diff --git a/packages/abi-typegen/src/abi/types/StructType.test.ts b/packages/abi-typegen/src/abi/types/StructType.test.ts index e3609138a5..32e9119147 100644 --- a/packages/abi-typegen/src/abi/types/StructType.test.ts +++ b/packages/abi-typegen/src/abi/types/StructType.test.ts @@ -21,7 +21,9 @@ describe('StructType.ts', () => { test('should properly parse type attributes', () => { const parseTypeArguments = vi.spyOn(parseTypeArgumentsMod, 'parseTypeArguments'); - const project = getTypegenForcProject(AbiTypegenProjectsEnum.STRUCT_SIMPLE); + const project = getTypegenForcProject(AbiTypegenProjectsEnum.STRUCT_SIMPLE, { + transpile: true, + }); const rawTypes = project.abiContents.types; const types = rawTypes.map((rawAbiType: JsonAbiType) => makeType({ rawAbiType })); diff --git a/packages/abi-typegen/src/abi/types/TupleType.test.ts b/packages/abi-typegen/src/abi/types/TupleType.test.ts index 792b275a96..f9a8e03212 100644 --- a/packages/abi-typegen/src/abi/types/TupleType.test.ts +++ b/packages/abi-typegen/src/abi/types/TupleType.test.ts @@ -17,7 +17,7 @@ describe('TupleType.ts', () => { test('should properly parse type attributes', () => { const parseTypeArguments = vi.spyOn(parseTypeArgumentsMod, 'parseTypeArguments'); - const project = getTypegenForcProject(AbiTypegenProjectsEnum.TUPLE_SIMPLE); + const project = getTypegenForcProject(AbiTypegenProjectsEnum.TUPLE_SIMPLE, { transpile: true }); const rawTypes = project.abiContents.types; const types = rawTypes.map((rawAbiType: JsonAbiType) => makeType({ rawAbiType })); @@ -30,7 +30,7 @@ describe('TupleType.ts', () => { // validating `struct B`, with simple tuples on property `x` parseTypeArguments.mockClear(); - const b = findType({ types, typeId: 0 }) as TupleType; + const b = findType({ types, typeId: 1 }) as TupleType; expect(b.attributes.inputLabel).toEqual('[boolean, BigNumberish]'); expect(b.attributes.outputLabel).toEqual('[boolean, BN]'); @@ -40,7 +40,7 @@ describe('TupleType.ts', () => { // validating `struct C`, with nested (tuple) `typeArguments` on `b` property parseTypeArguments.mockClear(); - const c = findType({ types, typeId: 1 }) as TupleType; + const c = findType({ types, typeId: 0 }) as TupleType; expect(c.attributes.inputLabel).toEqual( '[BigNumberish, StructAInput, string>]' diff --git a/packages/abi-typegen/src/runTypegen.ts b/packages/abi-typegen/src/runTypegen.ts index 2e42c1c012..4ea4428d7c 100644 --- a/packages/abi-typegen/src/runTypegen.ts +++ b/packages/abi-typegen/src/runTypegen.ts @@ -55,10 +55,12 @@ export function runTypegen(params: IGenerateFilesParams) { Assembling file paths x contents */ const abiFiles = filepaths.map((filepath) => { + const contents = readFileSync(filepath, 'utf-8'); const abi: IFile = { path: filepath, - contents: readFileSync(filepath, 'utf-8'), + contents, }; + return abi; }); diff --git a/packages/abi-typegen/src/types/interfaces/JsonAbi.ts b/packages/abi-typegen/src/types/interfaces/JsonAbi.ts index 2e481d27aa..eed9fee4d4 100644 --- a/packages/abi-typegen/src/types/interfaces/JsonAbi.ts +++ b/packages/abi-typegen/src/types/interfaces/JsonAbi.ts @@ -1,8 +1,8 @@ /** * Types for Fuel JSON ABI Format as defined on: - * https://github.com/FuelLabs/fuel-specs/blob/master/src/abi/json-abi-format.md + * https://github.com/FuelLabs/fuel-specs/blob/b40d87d2515727188b9ae2dd23602316c50519c0/src/abi/json-abi-format.md */ -export interface JsonAbi { +export interface JsonAbiOld { readonly types: readonly JsonAbiType[]; readonly loggedTypes: readonly JsonAbiLoggedType[]; readonly functions: readonly JsonAbiFunction[]; diff --git a/packages/abi-typegen/src/types/interfaces/JsonAbiNew.ts b/packages/abi-typegen/src/types/interfaces/JsonAbiNew.ts new file mode 100644 index 0000000000..4d9481c112 --- /dev/null +++ b/packages/abi-typegen/src/types/interfaces/JsonAbiNew.ts @@ -0,0 +1,101 @@ +/** + * Types for Fuel JSON ABI Format as defined on: + * https://github.com/FuelLabs/fuel-specs/blob/master/src/abi/json-abi-format.md + */ +export interface JsonAbi { + readonly specVersion: string; + readonly encodingVersion: string; + readonly programType: string; + readonly concreteTypes: readonly ConcreteType[]; + readonly metadataTypes: readonly MetadataType[]; + readonly functions: readonly AbiFunction[]; + readonly loggedTypes: readonly LoggedType[]; + readonly messagesTypes: readonly MessageType[]; + readonly configurables: readonly Configurable[]; +} + +export interface ConcreteType { + readonly type: string; + readonly concreteTypeId: string; + readonly metadataTypeId?: number; + readonly typeArguments?: readonly string[]; +} + +export interface MetadataType { + readonly type: string; + readonly metadataTypeId: number; + readonly components?: readonly Component[]; + readonly typeParameters?: readonly number[]; +} + +export interface Component extends TypeArgument { + readonly name: string; +} + +export interface TypeArgument { + readonly typeId: number | string; // the type metadata declaration ID or type concrete declaration hash based ID of the type of the component. + readonly typeArguments?: readonly TypeArgument[]; +} + +export interface AbiFunction { + readonly name: string; + readonly inputs: readonly AbiFunctionInput[]; + readonly output: string; + readonly attributes: readonly AbiFunctionAttribute[] | null; +} + +export interface AbiFunctionInput { + readonly name: string; + readonly concreteTypeId: string; +} + +export type AbiFunctionAttribute = { + readonly name: string; + readonly arguments?: string[]; +}; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +type AbiFunctionAttributeTodo = + | StorageAttr + | PayableAttr + | TestAttr + | InlineAttr + | DocCommentAttr + | DocAttr; + +export interface PayableAttr { + readonly name: 'payable'; +} +export interface StorageAttr { + readonly name: 'storage'; + readonly arguments: readonly ('read' | 'write')[]; +} +export interface TestAttr { + readonly name: 'test'; +} +export interface InlineAttr { + readonly name: 'inline'; + readonly arguments: 'never' | 'always'; +} +export interface DocCommentAttr { + readonly name: 'doc-comment'; + readonly arguments: string[]; +} +export interface DocAttr { + readonly name: 'doc'; +} + +export interface LoggedType { + readonly logId: string; + readonly concreteTypeId: string; // the _type concrete declaration_ hash based ID of the value being logged. +} + +export interface MessageType { + readonly message_id: string; + readonly concreteTypeId: string; +} +export interface Configurable { + readonly name: string; + readonly concreteTypeId: string; + readonly offset: number; +} diff --git a/packages/abi-typegen/src/utils/parseTypeArguments.test.ts b/packages/abi-typegen/src/utils/parseTypeArguments.test.ts index dbb7b115f8..8595704bad 100644 --- a/packages/abi-typegen/src/utils/parseTypeArguments.test.ts +++ b/packages/abi-typegen/src/utils/parseTypeArguments.test.ts @@ -12,7 +12,7 @@ import { parseTypeArguments } from './parseTypeArguments'; Sample ABI with components in both fashions: — WITH and WITHOUT `typeArguments` */ -const defautRawTypes: JsonAbiType[] = [ +const defautRawTypes: readonly JsonAbiType[] = [ { typeId: 0, type: 'bool', @@ -106,7 +106,7 @@ describe('parseTypeArguments.ts', () => { }); test('should fallback to void for null outputs', () => { - const project = getTypegenForcProject(AbiTypegenProjectsEnum.FN_VOID); + const project = getTypegenForcProject(AbiTypegenProjectsEnum.FN_VOID, { transpile: true }); const types = bundleTypes(project.abiContents.types); const typeArguments = [project.abiContents.functions[0].output]; diff --git a/packages/abi-typegen/src/utils/transpile-abi.ts b/packages/abi-typegen/src/utils/transpile-abi.ts new file mode 100644 index 0000000000..2d1d061d7b --- /dev/null +++ b/packages/abi-typegen/src/utils/transpile-abi.ts @@ -0,0 +1,146 @@ +/* eslint-disable no-restricted-globals */ +/* eslint-disable no-param-reassign */ +/* eslint-disable @typescript-eslint/no-use-before-define */ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-nocheck + +const findTypeByConcreteId = (types, id) => types.find((x) => x.concreteTypeId === id); + +const findConcreteTypeById = (abi, id) => abi.concreteTypes.find((x) => x.concreteTypeId === id); + +function finsertTypeIdByConcreteTypeId(abi, types, id) { + const concreteType = findConcreteTypeById(abi, id); + + if (concreteType.metadataTypeId !== undefined) { + return concreteType.metadataTypeId; + } + + const type = findTypeByConcreteId(types, id); + if (type) { + return type.typeId; + } + + types.push({ + typeId: types.length, + type: concreteType.type, + components: parseComponents(concreteType.components), + concreteTypeId: id, + typeParameters: concreteType.typeParameters ?? null, + originalConcreteTypeId: concreteType?.concreteTypeId, + }); + + return types.length - 1; +} + +function parseFunctionTypeArguments(abi, types, concreteType) { + return ( + concreteType.typeArguments?.map((cTypeId) => { + const self = findConcreteTypeById(abi, cTypeId); + const type = !isNaN(cTypeId) ? cTypeId : finsertTypeIdByConcreteTypeId(abi, types, cTypeId); + return { + name: '', + type, + // originalTypeId: cTypeId, + typeArguments: parseFunctionTypeArguments(abi, types, self), + }; + }) ?? null + ); +} + +export function parseConcreteType(abi, types, concreteTypeId, name) { + const type = finsertTypeIdByConcreteTypeId(abi, types, concreteTypeId); + const concrete = findConcreteTypeById(abi, concreteTypeId); + return { + name: name ?? '', + type, + // concreteTypeId, + typeArguments: parseFunctionTypeArguments(abi, types, concrete), + }; +} + +function parseComponents(abi, types, components) { + return ( + components?.map((component) => { + const { typeId, name, typeArguments } = component; + const type = !isNaN(typeId) ? typeId : finsertTypeIdByConcreteTypeId(abi, types, typeId); + return { + name, + type, + // originalTypeId: typeId, + typeArguments: parseComponents(abi, types, typeArguments), + }; + }) ?? null + ); +} + +/** + * This will transpile new ABIs (spec: "1") to the old format. + * + * The new format got these new props: + * - `specVersion`, + * - `concreteTypes` + * - `metadataTypes` + * + * The old format contains only: + * - `types` + */ +export function transpileAbi(abi) { + // do not transpile older versions + if (!abi.specVersion) { + return abi; + } + + // 0. define empty types array + const types = []; + + // 1. root level of metadata types + abi.metadataTypes.forEach((m) => { + const t = { + typeId: m.metadataTypeId, + type: m.type, + components: m.components ?? (m.type === '()' ? [] : null), + typeParameters: m.typeParameters ?? null, + }; + types.push(t); + }); + + // 2. the metadata's components + types.forEach((t) => { + t.components = parseComponents(abi, types, t.components); + }); + + // 3. functions inputs/outputs + const functions = abi.functions.map((fn) => { + const inputs = fn.inputs.map(({ concreteTypeId, name }) => + parseConcreteType(abi, types, concreteTypeId, name) + ); + const output = parseConcreteType(abi, types, fn.output, ''); + return { ...fn, inputs, output }; + }); + + // 4. configurables + const configurables = abi.configurables.map((conf) => ({ + name: conf.name, + configurableType: parseConcreteType(abi, types, conf.concreteTypeId), + offset: conf.offset, + })); + + // 5. loggedTypes + const loggedTypes = abi.loggedTypes.map((log) => ({ + logId: log.logId, + loggedType: parseConcreteType(abi, types, log.concreteTypeId), + })); + + // transpiled ABI + const transpiled = { + encoding: abi.encodingVersion, + types, + functions, + loggedTypes, + messagesTypes: abi.messagesTypes, + configurables, + }; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return transpiled as any; +} diff --git a/packages/abi-typegen/test/fixtures/forc-projects/index.ts b/packages/abi-typegen/test/fixtures/forc-projects/index.ts index 062629811a..05fd05d1c3 100644 --- a/packages/abi-typegen/test/fixtures/forc-projects/index.ts +++ b/packages/abi-typegen/test/fixtures/forc-projects/index.ts @@ -1,7 +1,9 @@ import { getForcProject } from '@fuel-ts/utils/test-utils'; import { join } from 'path'; -import type { JsonAbi } from '../../../src/index'; +import type { JsonAbiOld } from '../../../src'; +import type { JsonAbi } from '../../../src/types/interfaces/JsonAbiNew'; +import { transpileAbi } from '../../../src/utils/transpile-abi'; export enum AbiTypegenProjectsEnum { ARRAY_OF_ENUMS = 'array-of-enums', @@ -30,12 +32,19 @@ export enum AbiTypegenProjectsEnum { VECTOR_SIMPLE = 'vector-simple', } -export const getTypegenForcProject = ( +export const getTypegenForcProject = ( project: AbiTypegenProjectsEnum, - build: 'release' | 'debug' = 'release' -) => - getForcProject({ + { transpile }: { transpile: T } = { transpile: false as T } +) => { + const result = getForcProject({ projectDir: join(__dirname, project), projectName: project, - build, + build: 'release', }); + + if (transpile) { + result.abiContents = transpileAbi(result.abiContents); + } + + return result; +}; diff --git a/packages/abi-typegen/test/fixtures/templates/contract-with-configurable/main.hbs b/packages/abi-typegen/test/fixtures/templates/contract-with-configurable/main.hbs index c67a131c9a..172bd0a38c 100644 --- a/packages/abi-typegen/test/fixtures/templates/contract-with-configurable/main.hbs +++ b/packages/abi-typegen/test/fixtures/templates/contract-with-configurable/main.hbs @@ -33,100 +33,108 @@ export type MyContractConfigurables = Partial<{ }>; const abi = { - "encoding": "1", - "types": [ + "programType": "contract", + "specVersion": "1", + "encodingVersion": "1", + "concreteTypes": [ { - "typeId": 0, - "type": "()", - "components": [], - "typeParameters": null + "type": "bool", + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" }, { - "typeId": 1, - "type": "bool", - "components": null, - "typeParameters": null + "type": "enum std::option::Option", + "concreteTypeId": "2da102c46c7263beeed95818cd7bee801716ba8303dddafdcd0f6c9efda4a0f1", + "metadataTypeId": 1, + "typeArguments": [ + "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + ] + }, + { + "type": "str[10]", + "concreteTypeId": "338a25cb65b9251663dcce6362b744fe10aa849758299590f4efed5dd299bf50" + }, + { + "type": "struct GenericStruct,u32>", + "concreteTypeId": "71df88006611ffff852cf617defb70f77adaf507305088cedd41d276c783aab0", + "metadataTypeId": 5, + "typeArguments": [ + "14dc991834d10c7c7207ad065a8f30dd47d2a2554c97749264d18e1bb3fcf7d6", + "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc" + ] + }, + { + "type": "struct GenericStruct", + "concreteTypeId": "14dc991834d10c7c7207ad065a8f30dd47d2a2554c97749264d18e1bb3fcf7d6", + "metadataTypeId": 5, + "typeArguments": [ + "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b", + "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef" + ] + }, + { + "type": "u16", + "concreteTypeId": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef" + }, + { + "type": "u32", + "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc" }, { - "typeId": 2, - "type": "enum Option", + "type": "u8", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + } + ], + "metadataTypes": [ + { + "type": "()", + "metadataTypeId": 0 + }, + { + "type": "enum std::option::Option", + "metadataTypeId": 1, "components": [ { "name": "None", - "type": 0, - "typeArguments": null + "typeId": 0 }, { "name": "Some", - "type": 3, - "typeArguments": null + "typeId": 2 } ], "typeParameters": [ - 3 + 2 ] }, { - "typeId": 3, "type": "generic T", - "components": null, - "typeParameters": null + "metadataTypeId": 2 }, { - "typeId": 4, "type": "generic T1", - "components": null, - "typeParameters": null + "metadataTypeId": 3 }, { - "typeId": 5, "type": "generic T2", - "components": null, - "typeParameters": null - }, - { - "typeId": 6, - "type": "str[10]", - "components": null, - "typeParameters": null + "metadataTypeId": 4 }, { - "typeId": 7, "type": "struct GenericStruct", + "metadataTypeId": 5, "components": [ { "name": "p1", - "type": 4, - "typeArguments": null + "typeId": 3 }, { "name": "p2", - "type": 5, - "typeArguments": null + "typeId": 4 } ], "typeParameters": [ - 4, - 5 + 3, + 4 ] - }, - { - "typeId": 8, - "type": "u16", - "components": null, - "typeParameters": null - }, - { - "typeId": 9, - "type": "u32", - "components": null, - "typeParameters": null - }, - { - "typeId": 10, - "type": "u8", - "components": null, - "typeParameters": null } ], "functions": [ @@ -134,21 +142,15 @@ const abi = { "inputs": [ { "name": "x", - "type": 6, - "typeArguments": null + "concreteTypeId": "338a25cb65b9251663dcce6362b744fe10aa849758299590f4efed5dd299bf50" }, { "name": "y", - "type": 6, - "typeArguments": null + "concreteTypeId": "338a25cb65b9251663dcce6362b744fe10aa849758299590f4efed5dd299bf50" } ], "name": "main", - "output": { - "name": "", - "type": 1, - "typeArguments": null - }, + "output": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", "attributes": null } ], @@ -157,58 +159,18 @@ const abi = { "configurables": [ { "name": "SHOULD_RETURN", - "configurableType": { - "name": "", - "type": 1, - "typeArguments": null - }, - "offset": 2576 + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", + "offset": 2720 }, { "name": "AN_OPTION", - "configurableType": { - "name": "", - "type": 2, - "typeArguments": [ - { - "name": "", - "type": 10, - "typeArguments": null - } - ] - }, - "offset": 2560 + "concreteTypeId": "2da102c46c7263beeed95818cd7bee801716ba8303dddafdcd0f6c9efda4a0f1", + "offset": 2696 }, { "name": "A_GENERIC_STRUCT", - "configurableType": { - "name": "", - "type": 7, - "typeArguments": [ - { - "name": "", - "type": 7, - "typeArguments": [ - { - "name": "", - "type": 10, - "typeArguments": null - }, - { - "name": "", - "type": 8, - "typeArguments": null - } - ] - }, - { - "name": "", - "type": 9, - "typeArguments": null - } - ] - }, - "offset": 2568 + "concreteTypeId": "71df88006611ffff852cf617defb70f77adaf507305088cedd41d276c783aab0", + "offset": 2712 } ] }; diff --git a/packages/abi-typegen/test/fixtures/templates/contract/main.hbs b/packages/abi-typegen/test/fixtures/templates/contract/main.hbs index 0a3b59bffd..c6f627ddab 100644 --- a/packages/abi-typegen/test/fixtures/templates/contract/main.hbs +++ b/packages/abi-typegen/test/fixtures/templates/contract/main.hbs @@ -56,533 +56,598 @@ export type StructWithMultiOptionInput = { multiple: [Option, Opti export type StructWithMultiOptionOutput = { multiple: [Option, Option, Option, Option, Option] }; const abi = { - "encoding": "1", - "types": [ + "programType": "contract", + "specVersion": "1", + "encodingVersion": "1", + "concreteTypes": [ { - "typeId": 0, "type": "()", - "components": [], - "typeParameters": null + "concreteTypeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" }, { - "typeId": 1, + "type": "(u8, u8, u8)", + "concreteTypeId": "79239b6d6f2383e2cfbaf4da7fdf7ee7fb59b7bf517acfff2d9433e9e76e8fc4", + "metadataTypeId": 0 + }, + { + "type": "[u8; 3]", + "concreteTypeId": "2dc21094c0e9d81b843d1c1c308e2d60755d727d0f9b8981389845dd6d8686b2", + "metadataTypeId": 2 + }, + { + "type": "b256", + "concreteTypeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" + }, + { + "type": "bool", + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" + }, + { + "type": "enum EnumWithVector", + "concreteTypeId": "11fe8db04751c1f2572544df9ac6b0659a5c159fecce1236148ed67ccb63f0a4", + "metadataTypeId": 4 + }, + { + "type": "enum GenericEnum", + "concreteTypeId": "ecbb748d034980313898a72ea8a896a31506cfef0f41883bffe50d0b73f0d693", + "metadataTypeId": 5, + "typeArguments": [ + "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b", + "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef" + ] + }, + { + "type": "enum MyEnum", + "concreteTypeId": "f097a9c7cabaa22d324d564b43210e927784b6f73609fe9e55900268b15910f5", + "metadataTypeId": 6 + }, + { + "type": "enum libs-for-testing::ExternalEnum", + "concreteTypeId": "d255d7621a80835aee6d3d0643eaec25fbb2c3215ed140fcf98ceffa69d895bc", + "metadataTypeId": 7 + }, + { + "type": "enum std::identity::Identity", + "concreteTypeId": "ab7cd04e05be58e3fc15d424c2c4a57f824a2a2d97d67252440a3925ebdc1335", + "metadataTypeId": 8 + }, + { + "type": "enum std::option::Option", + "concreteTypeId": "3597e0782bd4dbaf5c8025b40ff3a325845ee34caa713a6d664bda034a31d02a", + "metadataTypeId": 9, + "typeArguments": [ + "392d58c694d2d91f3025f2bccfadacf2a105936f5da881b0899185d49f264522" + ] + }, + { + "type": "enum std::option::Option", + "concreteTypeId": "2da102c46c7263beeed95818cd7bee801716ba8303dddafdcd0f6c9efda4a0f1", + "metadataTypeId": 9, + "typeArguments": [ + "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + ] + }, + { + "type": "enum std::result::Result", + "concreteTypeId": "9891b1ee451eed790368ea3969e3c8f550efa87de489b5d7b933e2290800791b", + "metadataTypeId": 10, + "typeArguments": [ + "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0", + "338a25cb65b9251663dcce6362b744fe10aa849758299590f4efed5dd299bf50" + ] + }, + { + "type": "enum std::result::Result", + "concreteTypeId": "b3131b4c08c16cfa55b3150d587c3afa3e4cdebe0399f3f599fa160baaa64e0c", + "metadataTypeId": 10, + "typeArguments": [ + "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0", + "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc" + ] + }, + { + "type": "raw untyped slice", + "concreteTypeId": "1e1c7c52c1c7a9901681337f8669555f62aac58911332c9ff6b4ea8e73786570" + }, + { + "type": "str", + "concreteTypeId": "8c25cb3686462e9a86d2883c5688a22fe738b0bbc85f458d2d2b5f3f667c6d5a" + }, + { + "type": "str[10]", + "concreteTypeId": "338a25cb65b9251663dcce6362b744fe10aa849758299590f4efed5dd299bf50" + }, + { + "type": "str[5]", + "concreteTypeId": "84877f6e98274b9e4721db68b4c0bdb9e52b8e9572c5bd7811c07a41ced882c7" + }, + { + "type": "struct GenericStructWithEnum", + "concreteTypeId": "1fcf420f386194ee1b5bd6d86346b554e2602516dee0b9f14d3a6a5e8b59ee10", + "metadataTypeId": 16, + "typeArguments": [ + "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b", + "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef" + ] + }, + { + "type": "struct MyStruct", + "concreteTypeId": "392d58c694d2d91f3025f2bccfadacf2a105936f5da881b0899185d49f264522", + "metadataTypeId": 17 + }, + { + "type": "struct StructWithMultiOption", + "concreteTypeId": "c581bcb5682ecd8bc2f011d5f0ebd9b1a158d659e41ef715763c48e0a2dbe33e", + "metadataTypeId": 18 + }, + { + "type": "struct libs-for-testing::ExternalStruct", + "concreteTypeId": "d8b341b0e34229cd4e78f2683daadb4e8f32487b5a8d06420889e23530a0b3a5", + "metadataTypeId": 19 + }, + { + "type": "struct std::address::Address", + "concreteTypeId": "f597b637c3b0f588fb8d7086c6f4735caa3122b85f0423b82e489f9bb58e2308", + "metadataTypeId": 20 + }, + { + "type": "struct std::asset_id::AssetId", + "concreteTypeId": "c0710b6731b1dd59799cf6bef33eee3b3b04a2e40e80a0724090215bbf2ca974", + "metadataTypeId": 21 + }, + { + "type": "struct std::b512::B512", + "concreteTypeId": "745e252e80bec590efc3999ae943f07ccea4d5b45b00bb6575499b64abdd3322", + "metadataTypeId": 22 + }, + { + "type": "struct std::bytes::Bytes", + "concreteTypeId": "cdd87b7d12fe505416570c294c884bca819364863efe3bf539245fa18515fbbb", + "metadataTypeId": 23 + }, + { + "type": "struct std::contract_id::ContractId", + "concreteTypeId": "29c10735d33b5159f0c71ee1dbd17b36a3e69e41f00fab0d42e1bd9f428d8a54", + "metadataTypeId": 25 + }, + { + "type": "struct std::string::String", + "concreteTypeId": "9a7f1d3e963c10e0a4ea70a8e20a4813d1dc5682e28f74cb102ae50d32f7f98c", + "metadataTypeId": 26 + }, + { + "type": "struct std::vec::Vec", + "concreteTypeId": "82a718cca7f57f954a06e7f4016e97f8f5fe2e3544196604d7470c99c9627027", + "metadataTypeId": 28, + "typeArguments": [ + "392d58c694d2d91f3025f2bccfadacf2a105936f5da881b0899185d49f264522" + ] + }, + { + "type": "struct std::vec::Vec", + "concreteTypeId": "7433529a12c0ea55ba489b39a099c831a225e86a5d7319279912df84093dbdba", + "metadataTypeId": 28, + "typeArguments": [ + "c581bcb5682ecd8bc2f011d5f0ebd9b1a158d659e41ef715763c48e0a2dbe33e" + ] + }, + { + "type": "struct std::vec::Vec", + "concreteTypeId": "27a0fb3d3a821e04e7a3f17ab6a617f0eb10f11e6eeb0f2c0ff9e6237207319e", + "metadataTypeId": 28, + "typeArguments": [ + "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + ] + }, + { + "type": "struct std::vm::evm::evm_address::EvmAddress", + "concreteTypeId": "05a44d8c3e00faf7ed545823b7a2b32723545d8715d87a0ab3cf65904948e8d2", + "metadataTypeId": 29 + }, + { + "type": "u16", + "concreteTypeId": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef" + }, + { + "type": "u256", + "concreteTypeId": "1b5759d94094368cfd443019e7ca5ec4074300e544e5ea993a979f5da627261e" + }, + { + "type": "u32", + "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc" + }, + { + "type": "u64", + "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + }, + { + "type": "u8", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + } + ], + "metadataTypes": [ + { "type": "(_, _, _)", + "metadataTypeId": 0, "components": [ { "name": "__tuple_element", - "type": 41, - "typeArguments": null + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" }, { "name": "__tuple_element", - "type": 41, - "typeArguments": null + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" }, { "name": "__tuple_element", - "type": 41, - "typeArguments": null + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" } - ], - "typeParameters": null + ] }, { - "typeId": 2, "type": "[_; 2]", + "metadataTypeId": 1, "components": [ { "name": "__array_element", - "type": 5, - "typeArguments": null + "typeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" } - ], - "typeParameters": null + ] }, { - "typeId": 3, "type": "[_; 3]", + "metadataTypeId": 2, "components": [ { "name": "__array_element", - "type": 41, - "typeArguments": null + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" } - ], - "typeParameters": null + ] }, { - "typeId": 4, "type": "[_; 5]", + "metadataTypeId": 3, "components": [ { "name": "__array_element", - "type": 12, + "typeId": 9, "typeArguments": [ { "name": "", - "type": 41, - "typeArguments": null + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" } ] } - ], - "typeParameters": null - }, - { - "typeId": 5, - "type": "b256", - "components": null, - "typeParameters": null - }, - { - "typeId": 6, - "type": "bool", - "components": null, - "typeParameters": null + ] }, { - "typeId": 7, "type": "enum EnumWithVector", + "metadataTypeId": 4, "components": [ { "name": "num", - "type": 41, - "typeArguments": null + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" }, { "name": "vec", - "type": 36, + "typeId": 28, "typeArguments": [ { "name": "", - "type": 41, - "typeArguments": null + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" } ] } - ], - "typeParameters": null + ] }, { - "typeId": 8, - "type": "enum ExternalEnum", + "type": "enum GenericEnum", + "metadataTypeId": 5, "components": [ { - "name": "A", - "type": 0, - "typeArguments": null + "name": "a", + "typeId": 13 }, { - "name": "B", - "type": 0, - "typeArguments": null + "name": "b", + "typeId": 14 } ], - "typeParameters": null + "typeParameters": [ + 13, + 14 + ] }, { - "typeId": 9, - "type": "enum GenericEnum", + "type": "enum MyEnum", + "metadataTypeId": 6, "components": [ { - "name": "a", - "type": 16, - "typeArguments": null + "name": "Checked", + "typeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" }, { - "name": "b", - "type": 17, - "typeArguments": null + "name": "Pending", + "typeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" } - ], - "typeParameters": [ - 16, - 17 ] }, { - "typeId": 10, - "type": "enum Identity", + "type": "enum libs-for-testing::ExternalEnum", + "metadataTypeId": 7, "components": [ { - "name": "Address", - "type": 23, - "typeArguments": null + "name": "A", + "typeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" }, { - "name": "ContractId", - "type": 27, - "typeArguments": null + "name": "B", + "typeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" } - ], - "typeParameters": null + ] }, { - "typeId": 11, - "type": "enum MyEnum", + "type": "enum std::identity::Identity", + "metadataTypeId": 8, "components": [ { - "name": "Checked", - "type": 0, - "typeArguments": null + "name": "Address", + "typeId": 20 }, { - "name": "Pending", - "type": 0, - "typeArguments": null + "name": "ContractId", + "typeId": 25 } - ], - "typeParameters": null + ] }, { - "typeId": 12, - "type": "enum Option", + "type": "enum std::option::Option", + "metadataTypeId": 9, "components": [ { "name": "None", - "type": 0, - "typeArguments": null + "typeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" }, { "name": "Some", - "type": 15, - "typeArguments": null + "typeId": 12 } ], "typeParameters": [ - 15 + 12 ] }, { - "typeId": 13, - "type": "enum Result", + "type": "enum std::result::Result", + "metadataTypeId": 10, "components": [ { "name": "Ok", - "type": 15, - "typeArguments": null + "typeId": 12 }, { "name": "Err", - "type": 14, - "typeArguments": null + "typeId": 11 } ], "typeParameters": [ - 15, - 14 + 12, + 11 ] }, { - "typeId": 14, "type": "generic E", - "components": null, - "typeParameters": null + "metadataTypeId": 11 }, { - "typeId": 15, "type": "generic T", - "components": null, - "typeParameters": null + "metadataTypeId": 12 }, { - "typeId": 16, "type": "generic T1", - "components": null, - "typeParameters": null + "metadataTypeId": 13 }, { - "typeId": 17, "type": "generic T2", - "components": null, - "typeParameters": null + "metadataTypeId": 14 }, { - "typeId": 18, "type": "raw untyped ptr", - "components": null, - "typeParameters": null - }, - { - "typeId": 19, - "type": "raw untyped slice", - "components": null, - "typeParameters": null + "metadataTypeId": 15 }, { - "typeId": 20, - "type": "str", - "components": null, - "typeParameters": null - }, - { - "typeId": 21, - "type": "str[10]", - "components": null, - "typeParameters": null - }, - { - "typeId": 22, - "type": "str[5]", - "components": null, - "typeParameters": null - }, - { - "typeId": 23, - "type": "struct Address", + "type": "struct GenericStructWithEnum", + "metadataTypeId": 16, "components": [ { - "name": "bits", - "type": 5, - "typeArguments": null - } - ], - "typeParameters": null - }, - { - "typeId": 24, - "type": "struct AssetId", - "components": [ + "name": "a", + "typeId": 13 + }, { - "name": "bits", - "type": 5, - "typeArguments": null + "name": "b", + "typeId": 5, + "typeArguments": [ + { + "name": "", + "typeId": 13 + }, + { + "name": "", + "typeId": 14 + } + ] } ], - "typeParameters": null + "typeParameters": [ + 13, + 14 + ] }, { - "typeId": 25, - "type": "struct B512", + "type": "struct MyStruct", + "metadataTypeId": 17, "components": [ { - "name": "bits", - "type": 2, - "typeArguments": null + "name": "x", + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + }, + { + "name": "y", + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + }, + { + "name": "state", + "typeId": 6 } - ], - "typeParameters": null + ] }, { - "typeId": 26, - "type": "struct Bytes", + "type": "struct StructWithMultiOption", + "metadataTypeId": 18, "components": [ { - "name": "buf", - "type": 32, - "typeArguments": null - }, - { - "name": "len", - "type": 40, - "typeArguments": null + "name": "multiple", + "typeId": 3 } - ], - "typeParameters": null + ] }, { - "typeId": 27, - "type": "struct ContractId", + "type": "struct libs-for-testing::ExternalStruct", + "metadataTypeId": 19, "components": [ { - "name": "bits", - "type": 5, - "typeArguments": null + "name": "value", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" } - ], - "typeParameters": null + ] }, { - "typeId": 28, - "type": "struct EvmAddress", + "type": "struct std::address::Address", + "metadataTypeId": 20, "components": [ { "name": "bits", - "type": 5, - "typeArguments": null + "typeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" } - ], - "typeParameters": null + ] }, { - "typeId": 29, - "type": "struct ExternalStruct", + "type": "struct std::asset_id::AssetId", + "metadataTypeId": 21, "components": [ { - "name": "value", - "type": 40, - "typeArguments": null + "name": "bits", + "typeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" } - ], - "typeParameters": null + ] }, { - "typeId": 30, - "type": "struct GenericStructWithEnum", + "type": "struct std::b512::B512", + "metadataTypeId": 22, "components": [ { - "name": "a", - "type": 16, - "typeArguments": null - }, - { - "name": "b", - "type": 9, - "typeArguments": [ - { - "name": "", - "type": 16, - "typeArguments": null - }, - { - "name": "", - "type": 17, - "typeArguments": null - } - ] + "name": "bits", + "typeId": 1 } - ], - "typeParameters": [ - 16, - 17 ] }, { - "typeId": 31, - "type": "struct MyStruct", + "type": "struct std::bytes::Bytes", + "metadataTypeId": 23, "components": [ { - "name": "x", - "type": 41, - "typeArguments": null - }, - { - "name": "y", - "type": 41, - "typeArguments": null + "name": "buf", + "typeId": 24 }, { - "name": "state", - "type": 11, - "typeArguments": null + "name": "len", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" } - ], - "typeParameters": null + ] }, { - "typeId": 32, - "type": "struct RawBytes", + "type": "struct std::bytes::RawBytes", + "metadataTypeId": 24, "components": [ { "name": "ptr", - "type": 18, - "typeArguments": null + "typeId": 15 }, { "name": "cap", - "type": 40, - "typeArguments": null + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" } - ], - "typeParameters": null + ] }, { - "typeId": 33, - "type": "struct RawVec", + "type": "struct std::contract_id::ContractId", + "metadataTypeId": 25, "components": [ { - "name": "ptr", - "type": 18, - "typeArguments": null - }, - { - "name": "cap", - "type": 40, - "typeArguments": null + "name": "bits", + "typeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" } - ], - "typeParameters": [ - 15 ] }, { - "typeId": 34, - "type": "struct String", + "type": "struct std::string::String", + "metadataTypeId": 26, "components": [ { "name": "bytes", - "type": 26, - "typeArguments": null + "typeId": 23 } - ], - "typeParameters": null + ] }, { - "typeId": 35, - "type": "struct StructWithMultiOption", + "type": "struct std::vec::RawVec", + "metadataTypeId": 27, "components": [ { - "name": "multiple", - "type": 4, - "typeArguments": null + "name": "ptr", + "typeId": 15 + }, + { + "name": "cap", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" } ], - "typeParameters": null + "typeParameters": [ + 12 + ] }, { - "typeId": 36, - "type": "struct Vec", + "type": "struct std::vec::Vec", + "metadataTypeId": 28, "components": [ { "name": "buf", - "type": 33, + "typeId": 27, "typeArguments": [ { "name": "", - "type": 15, - "typeArguments": null + "typeId": 12 } ] }, { "name": "len", - "type": 40, - "typeArguments": null + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" } ], "typeParameters": [ - 15 + 12 ] }, { - "typeId": 37, - "type": "u16", - "components": null, - "typeParameters": null - }, - { - "typeId": 38, - "type": "u256", - "components": null, - "typeParameters": null - }, - { - "typeId": 39, - "type": "u32", - "components": null, - "typeParameters": null - }, - { - "typeId": 40, - "type": "u64", - "components": null, - "typeParameters": null - }, - { - "typeId": 41, - "type": "u8", - "components": null, - "typeParameters": null + "type": "struct std::vm::evm::evm_address::EvmAddress", + "metadataTypeId": 29, + "components": [ + { + "name": "bits", + "typeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" + } + ] } ], "functions": [ @@ -590,769 +655,446 @@ const abi = { "inputs": [ { "name": "x", - "type": 23, - "typeArguments": null + "concreteTypeId": "f597b637c3b0f588fb8d7086c6f4735caa3122b85f0423b82e489f9bb58e2308" } ], "name": "type_address", - "output": { - "name": "", - "type": 23, - "typeArguments": null - }, + "output": "f597b637c3b0f588fb8d7086c6f4735caa3122b85f0423b82e489f9bb58e2308", "attributes": null }, { "inputs": [ { "name": "x", - "type": 27, - "typeArguments": null + "concreteTypeId": "29c10735d33b5159f0c71ee1dbd17b36a3e69e41f00fab0d42e1bd9f428d8a54" } ], "name": "type_contract_id", - "output": { - "name": "", - "type": 27, - "typeArguments": null - }, + "output": "29c10735d33b5159f0c71ee1dbd17b36a3e69e41f00fab0d42e1bd9f428d8a54", "attributes": null }, { "inputs": [ { "name": "x", - "type": 8, - "typeArguments": null + "concreteTypeId": "d255d7621a80835aee6d3d0643eaec25fbb2c3215ed140fcf98ceffa69d895bc" } ], "name": "type_external_enum", - "output": { - "name": "", - "type": 8, - "typeArguments": null - }, + "output": "d255d7621a80835aee6d3d0643eaec25fbb2c3215ed140fcf98ceffa69d895bc", "attributes": null }, { "inputs": [ { "name": "x", - "type": 29, - "typeArguments": null + "concreteTypeId": "d8b341b0e34229cd4e78f2683daadb4e8f32487b5a8d06420889e23530a0b3a5" } ], "name": "type_external_struct", - "output": { - "name": "", - "type": 29, - "typeArguments": null - }, + "output": "d8b341b0e34229cd4e78f2683daadb4e8f32487b5a8d06420889e23530a0b3a5", "attributes": null }, { "inputs": [ { "name": "x", - "type": 10, - "typeArguments": null + "concreteTypeId": "ab7cd04e05be58e3fc15d424c2c4a57f824a2a2d97d67252440a3925ebdc1335" } ], "name": "type_identity", - "output": { - "name": "", - "type": 10, - "typeArguments": null - }, + "output": "ab7cd04e05be58e3fc15d424c2c4a57f824a2a2d97d67252440a3925ebdc1335", "attributes": null }, { "inputs": [ { "name": "x", - "type": 3, - "typeArguments": null + "concreteTypeId": "2dc21094c0e9d81b843d1c1c308e2d60755d727d0f9b8981389845dd6d8686b2" } ], "name": "types_array", - "output": { - "name": "", - "type": 3, - "typeArguments": null - }, + "output": "2dc21094c0e9d81b843d1c1c308e2d60755d727d0f9b8981389845dd6d8686b2", "attributes": null }, { "inputs": [ { "name": "x", - "type": 24, - "typeArguments": null + "concreteTypeId": "c0710b6731b1dd59799cf6bef33eee3b3b04a2e40e80a0724090215bbf2ca974" } ], "name": "types_asset_id", - "output": { - "name": "", - "type": 24, - "typeArguments": null - }, + "output": "c0710b6731b1dd59799cf6bef33eee3b3b04a2e40e80a0724090215bbf2ca974", "attributes": null }, { "inputs": [ { "name": "x", - "type": 5, - "typeArguments": null + "concreteTypeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" } ], "name": "types_b256", - "output": { - "name": "", - "type": 5, - "typeArguments": null - }, + "output": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b", "attributes": null }, { "inputs": [ { "name": "x", - "type": 25, - "typeArguments": null + "concreteTypeId": "745e252e80bec590efc3999ae943f07ccea4d5b45b00bb6575499b64abdd3322" } ], "name": "types_b512", - "output": { - "name": "", - "type": 25, - "typeArguments": null - }, + "output": "745e252e80bec590efc3999ae943f07ccea4d5b45b00bb6575499b64abdd3322", "attributes": null }, { "inputs": [ { "name": "x", - "type": 6, - "typeArguments": null + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" } ], "name": "types_bool", - "output": { - "name": "", - "type": 6, - "typeArguments": null - }, + "output": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", "attributes": null }, { "inputs": [ { "name": "x", - "type": 26, - "typeArguments": null + "concreteTypeId": "cdd87b7d12fe505416570c294c884bca819364863efe3bf539245fa18515fbbb" } ], "name": "types_bytes", - "output": { - "name": "", - "type": 26, - "typeArguments": null - }, + "output": "cdd87b7d12fe505416570c294c884bca819364863efe3bf539245fa18515fbbb", "attributes": null }, { "inputs": [ { "name": "x", - "type": 0, - "typeArguments": null + "concreteTypeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" } ], "name": "types_empty", - "output": { - "name": "", - "type": 0, - "typeArguments": null - }, + "output": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d", "attributes": null }, { "inputs": [ { "name": "x", - "type": 0, - "typeArguments": null + "concreteTypeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" }, { "name": "y", - "type": 41, - "typeArguments": null + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" } ], "name": "types_empty_then_value", - "output": { - "name": "", - "type": 0, - "typeArguments": null - }, + "output": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d", "attributes": null }, { "inputs": [ { "name": "x", - "type": 11, - "typeArguments": null + "concreteTypeId": "f097a9c7cabaa22d324d564b43210e927784b6f73609fe9e55900268b15910f5" } ], "name": "types_enum", - "output": { - "name": "", - "type": 11, - "typeArguments": null - }, + "output": "f097a9c7cabaa22d324d564b43210e927784b6f73609fe9e55900268b15910f5", "attributes": null }, { "inputs": [ { "name": "x", - "type": 7, - "typeArguments": null + "concreteTypeId": "11fe8db04751c1f2572544df9ac6b0659a5c159fecce1236148ed67ccb63f0a4" } ], "name": "types_enum_with_vector", - "output": { - "name": "", - "type": 7, - "typeArguments": null - }, + "output": "11fe8db04751c1f2572544df9ac6b0659a5c159fecce1236148ed67ccb63f0a4", "attributes": null }, { "inputs": [ { "name": "x", - "type": 28, - "typeArguments": null + "concreteTypeId": "05a44d8c3e00faf7ed545823b7a2b32723545d8715d87a0ab3cf65904948e8d2" } ], "name": "types_evm_address", - "output": { - "name": "", - "type": 28, - "typeArguments": null - }, + "output": "05a44d8c3e00faf7ed545823b7a2b32723545d8715d87a0ab3cf65904948e8d2", "attributes": null }, { "inputs": [ { "name": "x", - "type": 9, - "typeArguments": [ - { - "name": "", - "type": 41, - "typeArguments": null - }, - { - "name": "", - "type": 37, - "typeArguments": null - } - ] + "concreteTypeId": "ecbb748d034980313898a72ea8a896a31506cfef0f41883bffe50d0b73f0d693" } ], "name": "types_generic_enum", - "output": { - "name": "", - "type": 9, - "typeArguments": [ - { - "name": "", - "type": 41, - "typeArguments": null - }, - { - "name": "", - "type": 37, - "typeArguments": null - } - ] - }, + "output": "ecbb748d034980313898a72ea8a896a31506cfef0f41883bffe50d0b73f0d693", "attributes": null }, { "inputs": [ { "name": "x", - "type": 30, - "typeArguments": [ - { - "name": "", - "type": 41, - "typeArguments": null - }, - { - "name": "", - "type": 37, - "typeArguments": null - } - ] + "concreteTypeId": "1fcf420f386194ee1b5bd6d86346b554e2602516dee0b9f14d3a6a5e8b59ee10" } ], "name": "types_generic_struct", - "output": { - "name": "", - "type": 30, - "typeArguments": [ - { - "name": "", - "type": 41, - "typeArguments": null - }, - { - "name": "", - "type": 37, - "typeArguments": null - } - ] - }, + "output": "1fcf420f386194ee1b5bd6d86346b554e2602516dee0b9f14d3a6a5e8b59ee10", "attributes": null }, { "inputs": [ { "name": "x", - "type": 12, - "typeArguments": [ - { - "name": "", - "type": 41, - "typeArguments": null - } - ] + "concreteTypeId": "2da102c46c7263beeed95818cd7bee801716ba8303dddafdcd0f6c9efda4a0f1" } ], "name": "types_option", - "output": { - "name": "", - "type": 12, - "typeArguments": [ - { - "name": "", - "type": 41, - "typeArguments": null - } - ] - }, + "output": "2da102c46c7263beeed95818cd7bee801716ba8303dddafdcd0f6c9efda4a0f1", "attributes": null }, { "inputs": [ { "name": "x", - "type": 12, - "typeArguments": [ - { - "name": "", - "type": 31, - "typeArguments": null - } - ] + "concreteTypeId": "3597e0782bd4dbaf5c8025b40ff3a325845ee34caa713a6d664bda034a31d02a" } ], "name": "types_option_geo", - "output": { - "name": "", - "type": 12, - "typeArguments": [ - { - "name": "", - "type": 31, - "typeArguments": null - } - ] - }, + "output": "3597e0782bd4dbaf5c8025b40ff3a325845ee34caa713a6d664bda034a31d02a", "attributes": null }, { "inputs": [ { "name": "x", - "type": 19, - "typeArguments": null + "concreteTypeId": "1e1c7c52c1c7a9901681337f8669555f62aac58911332c9ff6b4ea8e73786570" } ], "name": "types_raw_slice", - "output": { - "name": "", - "type": 19, - "typeArguments": null - }, + "output": "1e1c7c52c1c7a9901681337f8669555f62aac58911332c9ff6b4ea8e73786570", "attributes": null }, { "inputs": [ { "name": "x", - "type": 13, - "typeArguments": [ - { - "name": "", - "type": 40, - "typeArguments": null - }, - { - "name": "", - "type": 39, - "typeArguments": null - } - ] + "concreteTypeId": "b3131b4c08c16cfa55b3150d587c3afa3e4cdebe0399f3f599fa160baaa64e0c" } ], "name": "types_result", - "output": { - "name": "", - "type": 13, - "typeArguments": [ - { - "name": "", - "type": 40, - "typeArguments": null - }, - { - "name": "", - "type": 21, - "typeArguments": null - } - ] - }, + "output": "9891b1ee451eed790368ea3969e3c8f550efa87de489b5d7b933e2290800791b", "attributes": null }, { "inputs": [ { "name": "x", - "type": 34, - "typeArguments": null + "concreteTypeId": "9a7f1d3e963c10e0a4ea70a8e20a4813d1dc5682e28f74cb102ae50d32f7f98c" } ], "name": "types_std_string", - "output": { - "name": "", - "type": 34, - "typeArguments": null - }, + "output": "9a7f1d3e963c10e0a4ea70a8e20a4813d1dc5682e28f74cb102ae50d32f7f98c", "attributes": null }, { "inputs": [ { "name": "x", - "type": 22, - "typeArguments": null + "concreteTypeId": "84877f6e98274b9e4721db68b4c0bdb9e52b8e9572c5bd7811c07a41ced882c7" } ], "name": "types_str", - "output": { - "name": "", - "type": 22, - "typeArguments": null - }, + "output": "84877f6e98274b9e4721db68b4c0bdb9e52b8e9572c5bd7811c07a41ced882c7", "attributes": null }, { "inputs": [ { "name": "x", - "type": 20, - "typeArguments": null + "concreteTypeId": "8c25cb3686462e9a86d2883c5688a22fe738b0bbc85f458d2d2b5f3f667c6d5a" } ], "name": "types_str_slice", - "output": { - "name": "", - "type": 20, - "typeArguments": null - }, + "output": "8c25cb3686462e9a86d2883c5688a22fe738b0bbc85f458d2d2b5f3f667c6d5a", "attributes": null }, { "inputs": [ { "name": "x", - "type": 31, - "typeArguments": null + "concreteTypeId": "392d58c694d2d91f3025f2bccfadacf2a105936f5da881b0899185d49f264522" } ], "name": "types_struct", - "output": { - "name": "", - "type": 31, - "typeArguments": null - }, + "output": "392d58c694d2d91f3025f2bccfadacf2a105936f5da881b0899185d49f264522", "attributes": null }, { "inputs": [ { "name": "x", - "type": 1, - "typeArguments": null + "concreteTypeId": "79239b6d6f2383e2cfbaf4da7fdf7ee7fb59b7bf517acfff2d9433e9e76e8fc4" } ], "name": "types_tuple", - "output": { - "name": "", - "type": 1, - "typeArguments": null - }, + "output": "79239b6d6f2383e2cfbaf4da7fdf7ee7fb59b7bf517acfff2d9433e9e76e8fc4", "attributes": null }, { "inputs": [ { "name": "x", - "type": 37, - "typeArguments": null + "concreteTypeId": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef" } ], "name": "types_u16", - "output": { - "name": "", - "type": 37, - "typeArguments": null - }, + "output": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef", "attributes": null }, { "inputs": [ { "name": "x", - "type": 38, - "typeArguments": null + "concreteTypeId": "1b5759d94094368cfd443019e7ca5ec4074300e544e5ea993a979f5da627261e" } ], "name": "types_u256", - "output": { - "name": "", - "type": 38, - "typeArguments": null - }, + "output": "1b5759d94094368cfd443019e7ca5ec4074300e544e5ea993a979f5da627261e", "attributes": null }, { "inputs": [ { "name": "x", - "type": 39, - "typeArguments": null + "concreteTypeId": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc" } ], "name": "types_u32", - "output": { - "name": "", - "type": 39, - "typeArguments": null - }, + "output": "d7649d428b9ff33d188ecbf38a7e4d8fd167fa01b2e10fe9a8f9308e52f1d7cc", "attributes": null }, { "inputs": [ { "name": "x", - "type": 40, - "typeArguments": null + "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" } ], "name": "types_u64", - "output": { - "name": "", - "type": 40, - "typeArguments": null - }, + "output": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0", "attributes": null }, { "inputs": [ { "name": "x", - "type": 41, - "typeArguments": null + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" } ], "name": "types_u8", - "output": { - "name": "", - "type": 41, - "typeArguments": null - }, + "output": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b", "attributes": null }, { "inputs": [ { "name": "x", - "type": 41, - "typeArguments": null + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" }, { "name": "y", - "type": 0, - "typeArguments": null + "concreteTypeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" } ], "name": "types_value_then_empty", - "output": { - "name": "", - "type": 0, - "typeArguments": null - }, + "output": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d", "attributes": null }, { "inputs": [ { "name": "x", - "type": 41, - "typeArguments": null + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" }, { "name": "y", - "type": 0, - "typeArguments": null + "concreteTypeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" }, { "name": "z", - "type": 41, - "typeArguments": null + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" } ], "name": "types_value_then_empty_then_value", - "output": { - "name": "", - "type": 0, - "typeArguments": null - }, + "output": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d", "attributes": null }, { "inputs": [ { "name": "x", - "type": 41, - "typeArguments": null + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" }, { "name": "y", - "type": 41, - "typeArguments": null + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" }, { "name": "z", - "type": 0, - "typeArguments": null + "concreteTypeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" }, { "name": "a", - "type": 0, - "typeArguments": null + "concreteTypeId": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d" } ], "name": "types_value_then_value_then_empty_then_empty", - "output": { - "name": "", - "type": 0, - "typeArguments": null - }, + "output": "2e38e77b22c314a449e91fafed92a43826ac6aa403ae6a8acb6cf58239fbaf5d", "attributes": null }, { "inputs": [ { "name": "x", - "type": 36, - "typeArguments": [ - { - "name": "", - "type": 31, - "typeArguments": null - } - ] + "concreteTypeId": "82a718cca7f57f954a06e7f4016e97f8f5fe2e3544196604d7470c99c9627027" } ], "name": "types_vector_geo", - "output": { - "name": "", - "type": 36, - "typeArguments": [ - { - "name": "", - "type": 31, - "typeArguments": null - } - ] - }, + "output": "82a718cca7f57f954a06e7f4016e97f8f5fe2e3544196604d7470c99c9627027", "attributes": null }, { "inputs": [ { "name": "x", - "type": 36, - "typeArguments": [ - { - "name": "", - "type": 35, - "typeArguments": null - } - ] + "concreteTypeId": "7433529a12c0ea55ba489b39a099c831a225e86a5d7319279912df84093dbdba" } ], "name": "types_vector_option", - "output": { - "name": "", - "type": 36, - "typeArguments": [ - { - "name": "", - "type": 35, - "typeArguments": null - } - ] - }, + "output": "7433529a12c0ea55ba489b39a099c831a225e86a5d7319279912df84093dbdba", "attributes": null }, { "inputs": [ { "name": "x", - "type": 36, - "typeArguments": [ - { - "name": "", - "type": 41, - "typeArguments": null - } - ] + "concreteTypeId": "27a0fb3d3a821e04e7a3f17ab6a617f0eb10f11e6eeb0f2c0ff9e6237207319e" } ], "name": "types_vector_u8", - "output": { - "name": "", - "type": 36, - "typeArguments": [ - { - "name": "", - "type": 41, - "typeArguments": null - } - ] - }, + "output": "27a0fb3d3a821e04e7a3f17ab6a617f0eb10f11e6eeb0f2c0ff9e6237207319e", "attributes": null } ], diff --git a/packages/abi-typegen/test/fixtures/templates/predicate-with-configurable/main.hbs b/packages/abi-typegen/test/fixtures/templates/predicate-with-configurable/main.hbs index afd2e10c3c..10ede746c7 100644 --- a/packages/abi-typegen/test/fixtures/templates/predicate-with-configurable/main.hbs +++ b/packages/abi-typegen/test/fixtures/templates/predicate-with-configurable/main.hbs @@ -32,47 +32,38 @@ export type MyPredicateParameters = Omit< >; const abi = { - "encoding": "1", - "types": [ + "programType": "predicate", + "specVersion": "1", + "encodingVersion": "1", + "concreteTypes": [ { - "typeId": 0, "type": "b256", - "components": null, - "typeParameters": null + "concreteTypeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" }, { - "typeId": 1, "type": "bool", - "components": null, - "typeParameters": null + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" }, { - "typeId": 2, "type": "u8", - "components": null, - "typeParameters": null + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" } ], + "metadataTypes": [], "functions": [ { "inputs": [ { "name": "fee", - "type": 2, - "typeArguments": null + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" }, { "name": "address", - "type": 0, - "typeArguments": null + "concreteTypeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b" } ], "name": "main", - "output": { - "name": "", - "type": 1, - "typeArguments": null - }, + "output": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", "attributes": null } ], @@ -81,21 +72,13 @@ const abi = { "configurables": [ { "name": "FEE", - "configurableType": { - "name": "", - "type": 2, - "typeArguments": null - }, - "offset": 904 + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b", + "offset": 928 }, { "name": "ADDRESS", - "configurableType": { - "name": "", - "type": 0, - "typeArguments": null - }, - "offset": 872 + "concreteTypeId": "7c5ee1cecf5f8eacd1284feb5f0bf2bdea533a51e2f0c9aabe9236d335989f3b", + "offset": 896 } ] }; diff --git a/packages/abi-typegen/test/fixtures/templates/predicate/main.hbs b/packages/abi-typegen/test/fixtures/templates/predicate/main.hbs index dd6bc168cb..8eaed3fbf4 100644 --- a/packages/abi-typegen/test/fixtures/templates/predicate/main.hbs +++ b/packages/abi-typegen/test/fixtures/templates/predicate/main.hbs @@ -40,189 +40,208 @@ export type MyPredicateParameters = Omit< >; const abi = { - "encoding": "1", - "types": [ + "programType": "predicate", + "specVersion": "1", + "encodingVersion": "1", + "concreteTypes": [ { - "typeId": 0, - "type": "()", - "components": [], - "typeParameters": null + "type": "bool", + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" }, { - "typeId": 1, - "type": "bool", - "components": null, - "typeParameters": null + "type": "enum MyGenericEnum", + "concreteTypeId": "9d8b215a39e5f5f10fc294290b6ea401edbd53056cfe6e0c9331157abdbc87d0", + "metadataTypeId": 1, + "typeArguments": [ + "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef" + ] + }, + { + "type": "enum std::option::Option", + "concreteTypeId": "2da102c46c7263beeed95818cd7bee801716ba8303dddafdcd0f6c9efda4a0f1", + "metadataTypeId": 2, + "typeArguments": [ + "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + ] + }, + { + "type": "enum std::result::Result,u64>", + "concreteTypeId": "85dace7aaa469c8bb476be79ddec34883ef101b3cde470636f47e299bfcdc3da", + "metadataTypeId": 3, + "typeArguments": [ + "c397d34a45fb343f8315bb5af5eed88da9f13347c765e2d86089d99dbf952ef2", + "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + ] + }, + { + "type": "str[4]", + "concreteTypeId": "94f0fa95c830be5e4f711963e83259fe7e8bc723278ab6ec34449e791a99b53a" + }, + { + "type": "struct MyGenericStruct", + "concreteTypeId": "c397d34a45fb343f8315bb5af5eed88da9f13347c765e2d86089d99dbf952ef2", + "metadataTypeId": 7, + "typeArguments": [ + "94f0fa95c830be5e4f711963e83259fe7e8bc723278ab6ec34449e791a99b53a" + ] + }, + { + "type": "struct Validation", + "concreteTypeId": "c7cf8c2be429c961ccb5c32a2951a58f1bb2a4f748ffac2206d4d1761082beaa", + "metadataTypeId": 8 + }, + { + "type": "struct std::vec::Vec", + "concreteTypeId": "9b3ded85b5c6e502acc8b7834d5d6df0460764a7a47837eb2b32d4566c4d477b", + "metadataTypeId": 10, + "typeArguments": [ + "c7cf8c2be429c961ccb5c32a2951a58f1bb2a4f748ffac2206d4d1761082beaa" + ] + }, + { + "type": "u16", + "concreteTypeId": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef" + }, + { + "type": "u64", + "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + }, + { + "type": "u8", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + } + ], + "metadataTypes": [ + { + "type": "()", + "metadataTypeId": 0 }, { - "typeId": 2, "type": "enum MyGenericEnum", + "metadataTypeId": 1, "components": [ { "name": "a", - "type": 6, - "typeArguments": null + "typeId": 5 } ], "typeParameters": [ - 6 + 5 ] }, { - "typeId": 3, - "type": "enum Option", + "type": "enum std::option::Option", + "metadataTypeId": 2, "components": [ { "name": "None", - "type": 0, - "typeArguments": null + "typeId": 0 }, { "name": "Some", - "type": 6, - "typeArguments": null + "typeId": 5 } ], "typeParameters": [ - 6 + 5 ] }, { - "typeId": 4, - "type": "enum Result", + "type": "enum std::result::Result", + "metadataTypeId": 3, "components": [ { "name": "Ok", - "type": 6, - "typeArguments": null + "typeId": 5 }, { "name": "Err", - "type": 5, - "typeArguments": null + "typeId": 4 } ], "typeParameters": [ - 6, - 5 + 5, + 4 ] }, { - "typeId": 5, "type": "generic E", - "components": null, - "typeParameters": null + "metadataTypeId": 4 }, { - "typeId": 6, "type": "generic T", - "components": null, - "typeParameters": null + "metadataTypeId": 5 }, { - "typeId": 7, "type": "raw untyped ptr", - "components": null, - "typeParameters": null + "metadataTypeId": 6 }, { - "typeId": 8, - "type": "str[4]", - "components": null, - "typeParameters": null - }, - { - "typeId": 9, "type": "struct MyGenericStruct", + "metadataTypeId": 7, "components": [ { "name": "a", - "type": 6, - "typeArguments": null + "typeId": 5 } ], "typeParameters": [ - 6 + 5 ] }, { - "typeId": 10, - "type": "struct RawVec", + "type": "struct Validation", + "metadataTypeId": 8, "components": [ { - "name": "ptr", - "type": 7, - "typeArguments": null + "name": "has_account", + "typeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" }, { - "name": "cap", - "type": 14, - "typeArguments": null + "name": "total_complete", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" } - ], - "typeParameters": [ - 6 ] }, { - "typeId": 11, - "type": "struct Validation", + "type": "struct std::vec::RawVec", + "metadataTypeId": 9, "components": [ { - "name": "has_account", - "type": 1, - "typeArguments": null + "name": "ptr", + "typeId": 6 }, { - "name": "total_complete", - "type": 14, - "typeArguments": null + "name": "cap", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" } ], - "typeParameters": null + "typeParameters": [ + 5 + ] }, { - "typeId": 12, - "type": "struct Vec", + "type": "struct std::vec::Vec", + "metadataTypeId": 10, "components": [ { "name": "buf", - "type": 10, + "typeId": 9, "typeArguments": [ { "name": "", - "type": 6, - "typeArguments": null + "typeId": 5 } ] }, { "name": "len", - "type": 14, - "typeArguments": null + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" } ], "typeParameters": [ - 6 + 5 ] - }, - { - "typeId": 13, - "type": "u16", - "components": null, - "typeParameters": null - }, - { - "typeId": 14, - "type": "u64", - "components": null, - "typeParameters": null - }, - { - "typeId": 15, - "type": "u8", - "components": null, - "typeParameters": null } ], "functions": [ @@ -230,66 +249,23 @@ const abi = { "inputs": [ { "name": "vec", - "type": 12, - "typeArguments": [ - { - "name": "", - "type": 11, - "typeArguments": null - } - ] + "concreteTypeId": "9b3ded85b5c6e502acc8b7834d5d6df0460764a7a47837eb2b32d4566c4d477b" }, { "name": "enm", - "type": 2, - "typeArguments": [ - { - "name": "", - "type": 13, - "typeArguments": null - } - ] + "concreteTypeId": "9d8b215a39e5f5f10fc294290b6ea401edbd53056cfe6e0c9331157abdbc87d0" }, { "name": "opt", - "type": 3, - "typeArguments": [ - { - "name": "", - "type": 15, - "typeArguments": null - } - ] + "concreteTypeId": "2da102c46c7263beeed95818cd7bee801716ba8303dddafdcd0f6c9efda4a0f1" }, { "name": "res", - "type": 4, - "typeArguments": [ - { - "name": "", - "type": 9, - "typeArguments": [ - { - "name": "", - "type": 8, - "typeArguments": null - } - ] - }, - { - "name": "", - "type": 14, - "typeArguments": null - } - ] + "concreteTypeId": "85dace7aaa469c8bb476be79ddec34883ef101b3cde470636f47e299bfcdc3da" } ], "name": "main", - "output": { - "name": "", - "type": 1, - "typeArguments": null - }, + "output": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", "attributes": null } ], diff --git a/packages/abi-typegen/test/fixtures/templates/script-with-configurable/main.hbs b/packages/abi-typegen/test/fixtures/templates/script-with-configurable/main.hbs index c9d6be8b7c..704006dd62 100644 --- a/packages/abi-typegen/test/fixtures/templates/script-with-configurable/main.hbs +++ b/packages/abi-typegen/test/fixtures/templates/script-with-configurable/main.hbs @@ -28,36 +28,38 @@ export type MyScriptConfigurables = Partial<{ }>; const abi = { - "encoding": "1", - "types": [ + "programType": "script", + "specVersion": "1", + "encodingVersion": "1", + "concreteTypes": [ { - "typeId": 0, "type": "bool", - "components": null, - "typeParameters": null + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903" }, { - "typeId": 1, "type": "struct Score", + "concreteTypeId": "bd5dbfd643b808e6ef22f73778cc8277cc5f01a4f974359b3169caa06e661d7e", + "metadataTypeId": 0 + } + ], + "metadataTypes": [ + { + "type": "struct Score", + "metadataTypeId": 0, "components": [ { "name": "user", - "type": 2, - "typeArguments": null + "typeId": 1 }, { "name": "points", - "type": 2, - "typeArguments": null + "typeId": 1 } - ], - "typeParameters": null + ] }, { - "typeId": 2, "type": "u8", - "components": null, - "typeParameters": null + "metadataTypeId": 1 } ], "functions": [ @@ -65,16 +67,11 @@ const abi = { "inputs": [ { "name": "score", - "type": 1, - "typeArguments": null + "concreteTypeId": "bd5dbfd643b808e6ef22f73778cc8277cc5f01a4f974359b3169caa06e661d7e" } ], "name": "main", - "output": { - "name": "", - "type": 0, - "typeArguments": null - }, + "output": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", "attributes": null } ], @@ -83,12 +80,8 @@ const abi = { "configurables": [ { "name": "SHOULD_RETURN", - "configurableType": { - "name": "", - "type": 0, - "typeArguments": null - }, - "offset": 640 + "concreteTypeId": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", + "offset": 704 } ] }; diff --git a/packages/abi-typegen/test/fixtures/templates/script/main.hbs b/packages/abi-typegen/test/fixtures/templates/script/main.hbs index c99d231960..aa93e95114 100644 --- a/packages/abi-typegen/test/fixtures/templates/script/main.hbs +++ b/packages/abi-typegen/test/fixtures/templates/script/main.hbs @@ -32,189 +32,208 @@ export type MyScriptInputs = [vec: Vec, enm: MyGenericEnumInput", + "concreteTypeId": "9d8b215a39e5f5f10fc294290b6ea401edbd53056cfe6e0c9331157abdbc87d0", + "metadataTypeId": 1, + "typeArguments": [ + "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef" + ] + }, + { + "type": "enum std::option::Option", + "concreteTypeId": "2da102c46c7263beeed95818cd7bee801716ba8303dddafdcd0f6c9efda4a0f1", + "metadataTypeId": 2, + "typeArguments": [ + "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + ] + }, + { + "type": "enum std::result::Result,u64>", + "concreteTypeId": "85dace7aaa469c8bb476be79ddec34883ef101b3cde470636f47e299bfcdc3da", + "metadataTypeId": 3, + "typeArguments": [ + "c397d34a45fb343f8315bb5af5eed88da9f13347c765e2d86089d99dbf952ef2", + "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + ] + }, + { + "type": "str[4]", + "concreteTypeId": "94f0fa95c830be5e4f711963e83259fe7e8bc723278ab6ec34449e791a99b53a" + }, + { + "type": "struct MyGenericStruct", + "concreteTypeId": "c397d34a45fb343f8315bb5af5eed88da9f13347c765e2d86089d99dbf952ef2", + "metadataTypeId": 7, + "typeArguments": [ + "94f0fa95c830be5e4f711963e83259fe7e8bc723278ab6ec34449e791a99b53a" + ] + }, + { + "type": "struct Score", + "concreteTypeId": "bd5dbfd643b808e6ef22f73778cc8277cc5f01a4f974359b3169caa06e661d7e", + "metadataTypeId": 8 + }, + { + "type": "struct std::vec::Vec", + "concreteTypeId": "e84db1295c0b56a640e39ac72b9d47c1c149e52e6d6a910576e488de934cdc97", + "metadataTypeId": 10, + "typeArguments": [ + "bd5dbfd643b808e6ef22f73778cc8277cc5f01a4f974359b3169caa06e661d7e" + ] + }, + { + "type": "u16", + "concreteTypeId": "29881aad8730c5ab11d275376323d8e4ff4179aae8ccb6c13fe4902137e162ef" + }, + { + "type": "u64", + "concreteTypeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" + }, + { + "type": "u8", + "concreteTypeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" + } + ], + "metadataTypes": [ + { + "type": "()", + "metadataTypeId": 0 }, { - "typeId": 2, "type": "enum MyGenericEnum", + "metadataTypeId": 1, "components": [ { "name": "a", - "type": 6, - "typeArguments": null + "typeId": 5 } ], "typeParameters": [ - 6 + 5 ] }, { - "typeId": 3, - "type": "enum Option", + "type": "enum std::option::Option", + "metadataTypeId": 2, "components": [ { "name": "None", - "type": 0, - "typeArguments": null + "typeId": 0 }, { "name": "Some", - "type": 6, - "typeArguments": null + "typeId": 5 } ], "typeParameters": [ - 6 + 5 ] }, { - "typeId": 4, - "type": "enum Result", + "type": "enum std::result::Result", + "metadataTypeId": 3, "components": [ { "name": "Ok", - "type": 6, - "typeArguments": null + "typeId": 5 }, { "name": "Err", - "type": 5, - "typeArguments": null + "typeId": 4 } ], "typeParameters": [ - 6, - 5 + 5, + 4 ] }, { - "typeId": 5, "type": "generic E", - "components": null, - "typeParameters": null + "metadataTypeId": 4 }, { - "typeId": 6, "type": "generic T", - "components": null, - "typeParameters": null + "metadataTypeId": 5 }, { - "typeId": 7, "type": "raw untyped ptr", - "components": null, - "typeParameters": null + "metadataTypeId": 6 }, { - "typeId": 8, - "type": "str[4]", - "components": null, - "typeParameters": null - }, - { - "typeId": 9, "type": "struct MyGenericStruct", + "metadataTypeId": 7, "components": [ { "name": "a", - "type": 6, - "typeArguments": null + "typeId": 5 } ], "typeParameters": [ - 6 + 5 ] }, { - "typeId": 10, - "type": "struct RawVec", + "type": "struct Score", + "metadataTypeId": 8, "components": [ { - "name": "ptr", - "type": 7, - "typeArguments": null + "name": "user", + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" }, { - "name": "cap", - "type": 14, - "typeArguments": null + "name": "points", + "typeId": "c89951a24c6ca28c13fd1cfdc646b2b656d69e61a92b91023be7eb58eb914b6b" } - ], - "typeParameters": [ - 6 ] }, { - "typeId": 11, - "type": "struct Score", + "type": "struct std::vec::RawVec", + "metadataTypeId": 9, "components": [ { - "name": "user", - "type": 15, - "typeArguments": null + "name": "ptr", + "typeId": 6 }, { - "name": "points", - "type": 15, - "typeArguments": null + "name": "cap", + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" } ], - "typeParameters": null + "typeParameters": [ + 5 + ] }, { - "typeId": 12, - "type": "struct Vec", + "type": "struct std::vec::Vec", + "metadataTypeId": 10, "components": [ { "name": "buf", - "type": 10, + "typeId": 9, "typeArguments": [ { "name": "", - "type": 6, - "typeArguments": null + "typeId": 5 } ] }, { "name": "len", - "type": 14, - "typeArguments": null + "typeId": "1506e6f44c1d6291cdf46395a8e573276a4fa79e8ace3fc891e092ef32d1b0a0" } ], "typeParameters": [ - 6 + 5 ] - }, - { - "typeId": 13, - "type": "u16", - "components": null, - "typeParameters": null - }, - { - "typeId": 14, - "type": "u64", - "components": null, - "typeParameters": null - }, - { - "typeId": 15, - "type": "u8", - "components": null, - "typeParameters": null } ], "functions": [ @@ -222,66 +241,23 @@ const abi = { "inputs": [ { "name": "vec", - "type": 12, - "typeArguments": [ - { - "name": "", - "type": 11, - "typeArguments": null - } - ] + "concreteTypeId": "e84db1295c0b56a640e39ac72b9d47c1c149e52e6d6a910576e488de934cdc97" }, { "name": "enm", - "type": 2, - "typeArguments": [ - { - "name": "", - "type": 13, - "typeArguments": null - } - ] + "concreteTypeId": "9d8b215a39e5f5f10fc294290b6ea401edbd53056cfe6e0c9331157abdbc87d0" }, { "name": "opt", - "type": 3, - "typeArguments": [ - { - "name": "", - "type": 15, - "typeArguments": null - } - ] + "concreteTypeId": "2da102c46c7263beeed95818cd7bee801716ba8303dddafdcd0f6c9efda4a0f1" }, { "name": "res", - "type": 4, - "typeArguments": [ - { - "name": "", - "type": 9, - "typeArguments": [ - { - "name": "", - "type": 8, - "typeArguments": null - } - ] - }, - { - "name": "", - "type": 14, - "typeArguments": null - } - ] + "concreteTypeId": "85dace7aaa469c8bb476be79ddec34883ef101b3cde470636f47e299bfcdc3da" } ], "name": "main", - "output": { - "name": "", - "type": 1, - "typeArguments": null - }, + "output": "b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903", "attributes": null } ], diff --git a/packages/account/test/fixtures/predicate-abi.ts b/packages/account/test/fixtures/predicate-abi.ts index c1f6d09223..91bf0b52c0 100644 --- a/packages/account/test/fixtures/predicate-abi.ts +++ b/packages/account/test/fixtures/predicate-abi.ts @@ -1,35 +1,30 @@ import type { JsonAbi } from '@fuel-ts/abi-coder'; export const predicateAbi: JsonAbi = { - types: [ + programType: 'predicate', + specVersion: '1', + encodingVersion: '1', + concreteTypes: [ { - typeId: 0, type: 'bool', - components: null, - typeParameters: null, + concreteTypeId: 'b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903', }, { - typeId: 1, type: 'b256', - components: null, - typeParameters: null, + concreteTypeId: 'a760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903', }, ], + metadataTypes: [], functions: [ { inputs: [ { name: 'data', - type: 1, - typeArguments: null, + concreteTypeId: 'a760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903', }, ], name: 'main', - output: { - name: '', - type: 0, - typeArguments: null, - }, + output: 'b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903', attributes: null, }, ], diff --git a/packages/account/test/fixtures/transaction-summary.ts b/packages/account/test/fixtures/transaction-summary.ts index 1b0b3e8c2a..04660b3b57 100644 --- a/packages/account/test/fixtures/transaction-summary.ts +++ b/packages/account/test/fixtures/transaction-summary.ts @@ -1,3 +1,4 @@ +import type { JsonAbi } from '@fuel-ts/abi-coder'; import { bn } from '@fuel-ts/math'; import type { InputCoin, @@ -258,7 +259,10 @@ export const MOCK_ABI_MAP: AbiMap = { loggedTypes: [], messagesTypes: [], configurables: [], - }, + } as unknown as JsonAbi, // used in skipped test + // packages/account/src/providers/transaction-summary/operations.test.ts + // "should ensure getContractCallOperations return contract call operations with calls details" + // when the test is unskipped, it'll fail and this mock can be adjusted or deleted }; export const CONTRACT_CALL_ABI = diff --git a/packages/account/test/fuel-wallet-connector.test.ts b/packages/account/test/fuel-wallet-connector.test.ts index 88befc25e2..70b40da4b9 100644 --- a/packages/account/test/fuel-wallet-connector.test.ts +++ b/packages/account/test/fuel-wallet-connector.test.ts @@ -283,7 +283,11 @@ describe('Fuel Connector', () => { connectors: [new MockConnector()], }); const isAdded = await fuel.addABI('0x001123', { - types: [], + concreteTypes: [], + metadataTypes: [], + encodingVersion: '1', + programType: 'contract', + specVersion: '1', loggedTypes: [], functions: [], messagesTypes: [], diff --git a/packages/fuel-gauge/test/fixtures/forc-projects/predicate-input-data/src/main.sw b/packages/fuel-gauge/test/fixtures/forc-projects/predicate-input-data/src/main.sw index 0a840e2984..b4c9f2ff70 100644 --- a/packages/fuel-gauge/test/fixtures/forc-projects/predicate-input-data/src/main.sw +++ b/packages/fuel-gauge/test/fixtures/forc-projects/predicate-input-data/src/main.sw @@ -3,6 +3,6 @@ predicate; use std::inputs::input_predicate_data; fn main() -> bool { - let input: bool = input_predicate_data::(0); + let input: bool = input_predicate_data::(0).unwrap(); input == true } diff --git a/packages/fuels/test/features/build.test.ts b/packages/fuels/test/features/build.test.ts index 7743bc2101..98af3bd6d3 100644 --- a/packages/fuels/test/features/build.test.ts +++ b/packages/fuels/test/features/build.test.ts @@ -14,144 +14,139 @@ import { /** * @group node */ -describe( - 'build', - () => { - const paths = bootstrapProject(__filename); +describe('build', { timeout: 180000 }, () => { + const paths = bootstrapProject(__filename); - afterEach(() => { - resetConfigAndMocks(paths.fuelsConfigPath); - }); + afterEach(() => { + resetConfigAndMocks(paths.fuelsConfigPath); + }); - afterAll(() => { - resetDiskAndMocks(paths.root); - }); + afterAll(() => { + resetDiskAndMocks(paths.root); + }); - function mockAll() { - const { autoStartFuelCore, killChildProcess } = mockStartFuelCore(); - const deploy = vi.spyOn(deployMod, 'deploy').mockResolvedValue([]); - - return { autoStartFuelCore, killChildProcess, deploy }; - } - - it('should run `build` command', async () => { - const { autoStartFuelCore, killChildProcess, deploy } = mockAll(); - - await runInit({ - root: paths.root, - workspace: paths.workspaceDir, - output: paths.outputDir, - forcPath: paths.forcPath, - fuelCorePath: paths.fuelCorePath, - }); - - await runBuild({ root: paths.root }); - - const files = [ - 'predicates/PredicateTrue.ts', - 'predicates/index.ts', - 'contracts/BarFoo.ts', - 'contracts/FooBar.ts', - 'contracts/FooBarFactory.ts', - 'contracts/BarFooFactory.ts', - 'contracts/index.ts', - 'scripts/ScriptTrue.ts', - 'scripts/index.ts', - 'index.ts', - ].map((f) => join(paths.outputDir, f)); - - files.forEach((file) => { - expect(existsSync(file)).toBeTruthy(); - }); - - expect(autoStartFuelCore).toHaveBeenCalledTimes(0); - expect(deploy).toHaveBeenCalledTimes(0); - expect(killChildProcess).toHaveBeenCalledTimes(0); - }); + function mockAll() { + const { autoStartFuelCore, killChildProcess } = mockStartFuelCore(); + const deploy = vi.spyOn(deployMod, 'deploy').mockResolvedValue([]); - it('should run `build` command with contracts-only', async () => { - const { autoStartFuelCore, killChildProcess, deploy } = mockAll(); + return { autoStartFuelCore, killChildProcess, deploy }; + } - await runInit({ - root: paths.root, - contracts: paths.contractsDir, - output: paths.outputDir, - forcPath: paths.forcPath, - fuelCorePath: paths.fuelCorePath, - }); + it('should run `build` command', async () => { + const { autoStartFuelCore, killChildProcess, deploy } = mockAll(); - await runBuild({ root: paths.root }); + await runInit({ + root: paths.root, + workspace: paths.workspaceDir, + output: paths.outputDir, + forcPath: paths.forcPath, + fuelCorePath: paths.fuelCorePath, + }); + + await runBuild({ root: paths.root }); + + const files = [ + 'predicates/PredicateTrue.ts', + 'predicates/index.ts', + 'contracts/BarFoo.ts', + 'contracts/FooBar.ts', + 'contracts/FooBarFactory.ts', + 'contracts/BarFooFactory.ts', + 'contracts/index.ts', + 'scripts/ScriptTrue.ts', + 'scripts/index.ts', + 'index.ts', + ].map((f) => join(paths.outputDir, f)); + + files.forEach((file) => { + expect(existsSync(file)).toBeTruthy(); + }); - const files = [ - 'contracts/FooBar.ts', - 'contracts/FooBarFactory.ts', - 'contracts/index.ts', - 'index.ts', - ].map((f) => join(paths.outputDir, f)); + expect(autoStartFuelCore).toHaveBeenCalledTimes(0); + expect(deploy).toHaveBeenCalledTimes(0); + expect(killChildProcess).toHaveBeenCalledTimes(0); + }); - files.forEach((file) => expect(existsSync(file)).toBeTruthy()); + it('should run `build` command with contracts-only', async () => { + const { autoStartFuelCore, killChildProcess, deploy } = mockAll(); - expect(autoStartFuelCore).toHaveBeenCalledTimes(0); - expect(deploy).toHaveBeenCalledTimes(0); - expect(killChildProcess).toHaveBeenCalledTimes(0); + await runInit({ + root: paths.root, + contracts: paths.contractsDir, + output: paths.outputDir, + forcPath: paths.forcPath, + fuelCorePath: paths.fuelCorePath, }); - it('should run `build` command with `--deploy` flag', async () => { - const { autoStartFuelCore, killChildProcess, deploy } = mockAll(); + await runBuild({ root: paths.root }); - await runInit({ - root: paths.root, - workspace: paths.workspaceDir, - output: paths.outputDir, - forcPath: paths.forcPath, - fuelCorePath: paths.fuelCorePath, - }); + const files = [ + 'contracts/FooBar.ts', + 'contracts/FooBarFactory.ts', + 'contracts/index.ts', + 'index.ts', + ].map((f) => join(paths.outputDir, f)); - await runBuild({ root: paths.root, deploy: true }); + files.forEach((file) => expect(existsSync(file)).toBeTruthy()); - expect(autoStartFuelCore).toHaveBeenCalledTimes(1); - expect(deploy).toHaveBeenCalledTimes(1); - expect(killChildProcess).toHaveBeenCalledTimes(1); + expect(autoStartFuelCore).toHaveBeenCalledTimes(0); + expect(deploy).toHaveBeenCalledTimes(0); + expect(killChildProcess).toHaveBeenCalledTimes(0); + }); + + it('should run `build` command with `--deploy` flag', async () => { + const { autoStartFuelCore, killChildProcess, deploy } = mockAll(); + + await runInit({ + root: paths.root, + workspace: paths.workspaceDir, + output: paths.outputDir, + forcPath: paths.forcPath, + fuelCorePath: paths.fuelCorePath, }); - it("should run `build` with `forcBuildFlags: ['--release']`", async () => { - const { autoStartFuelCore, killChildProcess, deploy } = mockAll(); + await runBuild({ root: paths.root, deploy: true }); - await runInit({ - root: paths.root, - workspace: paths.workspaceDir, - output: paths.outputDir, - forcPath: paths.forcPath, - fuelCorePath: paths.fuelCorePath, - }); + expect(autoStartFuelCore).toHaveBeenCalledTimes(1); + expect(deploy).toHaveBeenCalledTimes(1); + expect(killChildProcess).toHaveBeenCalledTimes(1); + }); - // inject `forcBuildFlags: ['--release']` in config file - const configFilepath = join(paths.root, 'fuels.config.ts'); - const configContents = readFileSync(configFilepath, 'utf-8'); + it("should run `build` with `forcBuildFlags: ['--release']`", async () => { + const { autoStartFuelCore, killChildProcess, deploy } = mockAll(); - const search = " output: './output',"; - const replace = [search, " forcBuildFlags: ['--release'],"].join('\n'); - const configContentsNew = configContents.replace(search, replace); + await runInit({ + root: paths.root, + workspace: paths.workspaceDir, + output: paths.outputDir, + forcPath: paths.forcPath, + fuelCorePath: paths.fuelCorePath, + }); - writeFileSync(configFilepath, configContentsNew); + // inject `forcBuildFlags: ['--release']` in config file + const configFilepath = join(paths.root, 'fuels.config.ts'); + const configContents = readFileSync(configFilepath, 'utf-8'); - // moving on - await runBuild({ root: paths.root }); + const search = " output: './output',"; + const replace = [search, " forcBuildFlags: ['--release'],"].join('\n'); + const configContentsNew = configContents.replace(search, replace); - const files = [ - 'contracts/FooBar.ts', - 'contracts/FooBarFactory.ts', - 'contracts/index.ts', - 'index.ts', - ].map((f) => join(paths.outputDir, f)); + writeFileSync(configFilepath, configContentsNew); - files.forEach((file) => expect(existsSync(file)).toBeTruthy()); + // moving on + await runBuild({ root: paths.root }); - expect(autoStartFuelCore).toHaveBeenCalledTimes(0); - expect(deploy).toHaveBeenCalledTimes(0); - expect(killChildProcess).toHaveBeenCalledTimes(0); - }); - }, + const files = [ + 'contracts/FooBar.ts', + 'contracts/FooBarFactory.ts', + 'contracts/index.ts', + 'index.ts', + ].map((f) => join(paths.outputDir, f)); + + files.forEach((file) => expect(existsSync(file)).toBeTruthy()); - { timeout: 180000 } -); + expect(autoStartFuelCore).toHaveBeenCalledTimes(0); + expect(deploy).toHaveBeenCalledTimes(0); + expect(killChildProcess).toHaveBeenCalledTimes(0); + }); +}); diff --git a/packages/fuels/test/features/deploy.test.ts b/packages/fuels/test/features/deploy.test.ts index 0027113bfa..b71b243dd5 100644 --- a/packages/fuels/test/features/deploy.test.ts +++ b/packages/fuels/test/features/deploy.test.ts @@ -14,25 +14,19 @@ import { * @group node */ describe('deploy', { timeout: 180000 }, () => { - let destroy: () => void; const paths = bootstrapProject(__filename); - beforeAll(async () => { - const { cleanup } = await launchTestNode({ - nodeOptions: { - port: '4000', - }, - }); - destroy = cleanup; - }); - afterAll(() => { resetConfigAndMocks(paths.fuelsConfigPath); resetDiskAndMocks(paths.root); - destroy(); }); it('should run `deploy` command', async () => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + using launched = await launchTestNode({ + nodeOptions: { port: '4000' }, + }); + await runInit({ root: paths.root, workspace: paths.workspaceDir, diff --git a/packages/program/src/contract.test.ts b/packages/program/src/contract.test.ts index dc7693ab16..a99ab1dc60 100644 --- a/packages/program/src/contract.test.ts +++ b/packages/program/src/contract.test.ts @@ -6,12 +6,10 @@ import Contract from './contract'; const CONTRACT_ID = '0x0101010101010101010101010101010101010101010101010101010101010101'; const ABI: JsonAbi = { - types: [ + concreteTypes: [ { - typeId: 0, + concreteTypeId: 'asdf', type: 'u64', - typeParameters: null, - components: null, }, ], functions: [ @@ -19,22 +17,21 @@ const ABI: JsonAbi = { inputs: [ { name: 'input', - type: 0, - typeArguments: null, + concreteTypeId: 'asdf', }, ], name: 'foo', - output: { - type: 0, - typeArguments: null, - name: '', - }, + output: 'asdf', attributes: null, }, ], loggedTypes: [], messagesTypes: [], configurables: [], + encodingVersion: '1', + metadataTypes: [], + programType: 'contract', + specVersion: '1', }; /** diff --git a/packages/script/src/script.test.ts b/packages/script/src/script.test.ts index bc462d7a52..fb4b160162 100644 --- a/packages/script/src/script.test.ts +++ b/packages/script/src/script.test.ts @@ -13,7 +13,7 @@ import { ReceiptType } from '@fuel-ts/transactions'; import { arrayify } from '@fuel-ts/utils'; import { getScriptForcProject, ScriptProjectsEnum } from '../test/fixtures'; -import { jsonAbiMock, jsonAbiFragmentMock } from '../test/mocks'; +import { jsonAbiMock } from '../test/mocks'; import { Script } from './index'; @@ -132,7 +132,7 @@ describe('Script', () => { wallets: [wallet], } = launched; - const newScript = new Script(scriptBin, jsonAbiFragmentMock, wallet); + const newScript = new Script(scriptBin, jsonAbiMock, wallet); await expectToThrowFuelError( () => newScript.setConfigurableConstants({ FEE: 8 }), @@ -155,11 +155,7 @@ describe('Script', () => { configurables: [ { name: 'FEE', - configurableType: { - name: '', - type: 1, - typeArguments: null, - }, + concreteTypeId: 'a760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903', offset: 44, }, ], diff --git a/packages/script/test/mocks.ts b/packages/script/test/mocks.ts index 6c7b8a9516..61df118fbb 100644 --- a/packages/script/test/mocks.ts +++ b/packages/script/test/mocks.ts @@ -1,90 +1,30 @@ import type { JsonAbi } from '@fuel-ts/abi-coder'; -export const jsonAbiFragmentMock: JsonAbi = { - configurables: [], - loggedTypes: [], - messagesTypes: [], - types: [ - { - typeId: 0, - type: 'bool', - components: null, - typeParameters: null, - }, - { - typeId: 1, - type: 'u64', - components: null, - typeParameters: null, - }, - { - typeId: 2, - type: 'struct MyStruct', - components: [ - { - type: 0, - name: 'arg_one', - typeArguments: null, - }, - { - type: 1, - name: 'arg_two', - typeArguments: null, - }, - ], - typeParameters: null, - }, - ], - functions: [ - { - name: 'main', - inputs: [ - { - name: 'my_struct', - type: 2, - typeArguments: null, - }, - ], - output: { - name: 'my_struct', - type: 2, - typeArguments: null, - }, - attributes: [], - }, - ], -}; - export const jsonAbiMock: JsonAbi = { - types: [ + programType: 'script', + specVersion: '1', + encodingVersion: '1', + concreteTypes: [ { - typeId: 0, type: 'bool', - components: null, - typeParameters: null, + concreteTypeId: 'b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903', }, { - typeId: 1, type: 'u8', - components: null, - typeParameters: null, + concreteTypeId: 'a760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903', }, ], + metadataTypes: [], functions: [ { inputs: [ { name: 'inputed_fee', - type: 1, - typeArguments: null, + concreteTypeId: 'a760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903', }, ], name: 'main', - output: { - name: '', - type: 0, - typeArguments: null, - }, + output: 'b760f44fa5965c2474a3b471467a22c43185152129295af588b022ae50b50903', attributes: null, }, ], diff --git a/packages/versions/src/lib/getBuiltinVersions.ts b/packages/versions/src/lib/getBuiltinVersions.ts index 587e156c74..e74d04e7fe 100644 --- a/packages/versions/src/lib/getBuiltinVersions.ts +++ b/packages/versions/src/lib/getBuiltinVersions.ts @@ -2,7 +2,7 @@ import type { Versions } from './types'; export function getBuiltinVersions(): Versions { return { - FORC: '0.62.0', + FORC: '0.63.1', FUEL_CORE: '0.33.0', FUELS: '0.93.0', }; diff --git a/scripts/forc-check.sh b/scripts/forc-check.sh index e8c412b9b8..bf090ec15e 100755 --- a/scripts/forc-check.sh +++ b/scripts/forc-check.sh @@ -1,7 +1,7 @@ #!/bin/bash main_dir=$(pwd) -forc_tomls=$(find . -type f -name "Forc.toml") +forc_tomls=$(find . -type f -name "Forc.toml" -not -path "*/internal/forc/sway-repo/*") forc_fmt=$(realpath ./internal/forc/forc-binaries/forc-fmt) expected_authors="authors = [\"Fuel Labs \"]" diff --git a/scripts/lint-md-links.ts b/scripts/lint-md-links.ts index 5537aab302..6bcd879fb9 100644 --- a/scripts/lint-md-links.ts +++ b/scripts/lint-md-links.ts @@ -14,6 +14,8 @@ import { globSync } from 'glob'; 'templates/**', 'apps/demo-wallet-sdk-react/**', 'apps/create-fuels-counter-guide/**', + 'internal/forc/sway-repo/**', + 'internal/fuel-core/fuel-core-repo/**', ], }); diff --git a/templates/nextjs/sway-programs/fuel-toolchain.toml b/templates/nextjs/sway-programs/fuel-toolchain.toml index 787f2b322d..6fafdf6086 100644 --- a/templates/nextjs/sway-programs/fuel-toolchain.toml +++ b/templates/nextjs/sway-programs/fuel-toolchain.toml @@ -2,5 +2,5 @@ channel = "testnet" [components] -forc = "0.62.0" +forc = "0.63.1" fuel-core = "0.33.0"