diff --git a/.changeset/gold-falcons-nail.md b/.changeset/gold-falcons-nail.md new file mode 100644 index 00000000000..3aab47d4556 --- /dev/null +++ b/.changeset/gold-falcons-nail.md @@ -0,0 +1,5 @@ +--- +"@fuel-ts/program": patch +--- + +Add transaction id helper function to base invocation scope diff --git a/apps/docs-snippets/src/guide/scripts/script-with-configurable.test.ts b/apps/docs-snippets/src/guide/scripts/script-with-configurable.test.ts index 63806679a67..8cc7a492cef 100644 --- a/apps/docs-snippets/src/guide/scripts/script-with-configurable.test.ts +++ b/apps/docs-snippets/src/guide/scripts/script-with-configurable.test.ts @@ -1,18 +1,23 @@ -import type { WalletUnlocked } from 'fuels'; +import type { WalletUnlocked, Provider } from 'fuels'; import { Script, BN } from 'fuels'; -import { DocSnippetProjectsEnum, getDocsSnippetsForcProject } from '../../../test/fixtures/forc-projects'; +import { + DocSnippetProjectsEnum, + getDocsSnippetsForcProject, +} from '../../../test/fixtures/forc-projects'; import { getTestWallet } from '../../utils'; describe(__filename, () => { let wallet: WalletUnlocked; let gasPrice: BN; + let provider: Provider; const { abiContents, binHexlified } = getDocsSnippetsForcProject( DocSnippetProjectsEnum.SUM_SCRIPT ); beforeAll(async () => { wallet = await getTestWallet(); + provider = wallet.provider; ({ minGasPrice: gasPrice } = wallet.provider.getGasConfig()); }); @@ -35,4 +40,35 @@ describe(__filename, () => { expect(new BN(value as number).toNumber()).toEqual(expectedTotal); // #endregion script-with-configurable-contants-2 }); + + it('prepares a script and retrieves the id before submission', async () => { + const argument = 10; + const expected = 20; + + // #region preparing-scripts + const script = new Script(binHexlified, abiContents, wallet); + const { minGasPrice, maxGasPerTx } = provider.getGasConfig(); + + const tx = await script.functions.main(argument); + + // Set the call parameters + tx.callParams({ gasLimit: 100 }); + + // Set the transaction parameters + tx.txParams({ gasPrice: minGasPrice, gasLimit: maxGasPerTx }); + + // Get the entire transaction request prior to + const txRequest = await tx.getTransactionRequest(); + + // Get the transaction ID + const txId = await tx.getTransactionId(); + + // Retrieve the value of the call and the actual gas used + const { value, gasUsed } = await tx.call(); + // #endregion preparing-scripts + expect(txRequest).toBeDefined(); + expect(txId).toBeDefined(); + expect(new BN(value as number).toNumber()).toEqual(expected); + expect(new BN(gasUsed).toNumber()).toBeGreaterThan(0); + }); }); diff --git a/apps/docs/.vitepress/config.ts b/apps/docs/.vitepress/config.ts index f0368c11247..9bf9a9b0ab2 100644 --- a/apps/docs/.vitepress/config.ts +++ b/apps/docs/.vitepress/config.ts @@ -363,6 +363,10 @@ export default defineConfig({ text: 'Calling A Script', link: '/guide/scripts/calling-a-script', }, + { + text: 'Preparing A Script', + link: '/guide/scripts/preparing-a-script', + }, { text: 'Script With Configurable Constants', link: '/guide/scripts/script-with-configurable-constants', diff --git a/apps/docs/src/guide/scripts/preparing-a-script.md b/apps/docs/src/guide/scripts/preparing-a-script.md new file mode 100644 index 00000000000..9595f9bf8b1 --- /dev/null +++ b/apps/docs/src/guide/scripts/preparing-a-script.md @@ -0,0 +1,5 @@ +# Preparing a Script Transaction + +Akin to Contracts, we can configure the [call parameters](../contracts/call-parameters.md) and [transaction parameters](../contracts/transaction-parameters.md) for Scripts, as well as retrieve the entire transaction request or transaction ID prior to submission. + +<<< @/../../docs-snippets/src/guide/scripts/script-with-configurable.test.ts#preparing-scripts{ts:line-numbers} \ No newline at end of file diff --git a/packages/program/package.json b/packages/program/package.json index 8efd172bae4..9bea56f7ebb 100644 --- a/packages/program/package.json +++ b/packages/program/package.json @@ -39,14 +39,15 @@ "dependencies": { "@fuel-ts/abi-coder": "workspace:*", "@fuel-ts/address": "workspace:*", + "@fuel-ts/errors": "workspace:*", + "@fuel-ts/hasher": "workspace:^", "@fuel-ts/interfaces": "workspace:*", "@fuel-ts/math": "workspace:*", "@fuel-ts/providers": "workspace:*", "@fuel-ts/transactions": "workspace:*", + "@fuel-ts/utils": "workspace:*", "@fuel-ts/versions": "workspace:*", "@fuel-ts/wallet": "workspace:*", - "@fuel-ts/errors": "workspace:*", - "@fuel-ts/utils": "workspace:*", "@fuels/vm-asm": "0.36.1", "ethers": "^6.7.1" }, diff --git a/packages/program/src/functions/base-invocation-scope.ts b/packages/program/src/functions/base-invocation-scope.ts index 85ec87d1134..a2b94631704 100644 --- a/packages/program/src/functions/base-invocation-scope.ts +++ b/packages/program/src/functions/base-invocation-scope.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import type { InputValue } from '@fuel-ts/abi-coder'; import { ErrorCode, FuelError } from '@fuel-ts/errors'; +import { hashTransaction } from '@fuel-ts/hasher'; import type { AbstractContract, AbstractProgram } from '@fuel-ts/interfaces'; import type { BN } from '@fuel-ts/math'; import { bn, toNumber } from '@fuel-ts/math'; @@ -372,4 +373,17 @@ export class BaseInvocationScope { return provider; } + + /** + * Obtains the ID of a transaction. + * + * @param chainId - the chainId to use to hash the transaction with + * @returns the ID of the transaction. + */ + async getTransactionId(chainId?: number): Promise { + const chainIdToHash = chainId ?? (await this.getProvider().getChainId()); + + const transactionRequest = await this.getTransactionRequest(); + return hashTransaction(transactionRequest, chainIdToHash); + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 29cb1774544..b3e238b9cd2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -904,6 +904,9 @@ importers: '@fuel-ts/errors': specifier: workspace:* version: link:../errors + '@fuel-ts/hasher': + specifier: workspace:^ + version: link:../hasher '@fuel-ts/interfaces': specifier: workspace:* version: link:../interfaces