From 1e148cb911398edfedf78119201661f154d8835a Mon Sep 17 00:00:00 2001 From: YaTut1901 Date: Fri, 29 Nov 2024 11:25:25 +0200 Subject: [PATCH 01/14] chore: added static method to duplicate predicate --- packages/account/src/predicate/predicate.ts | 42 ++ .../predicate/predicate-duplication.test.ts | 431 ++++++++++++++++++ .../utils/predicate/processPredicateData.ts | 70 +++ 3 files changed, 543 insertions(+) create mode 100644 packages/fuel-gauge/src/predicate/predicate-duplication.test.ts create mode 100644 packages/fuel-gauge/src/predicate/utils/predicate/processPredicateData.ts diff --git a/packages/account/src/predicate/predicate.ts b/packages/account/src/predicate/predicate.ts index 1bc90f4a05e..c01e3b442d4 100644 --- a/packages/account/src/predicate/predicate.ts +++ b/packages/account/src/predicate/predicate.ts @@ -48,6 +48,7 @@ export class Predicate< bytes: Uint8Array; predicateData: TData = [] as unknown as TData; interface: Interface; + initialBytecode: Uint8Array; /** * Creates an instance of the Predicate class. @@ -73,6 +74,7 @@ export class Predicate< const address = Address.fromB256(getPredicateRoot(predicateBytes)); super(address, provider); + this.initialBytecode = arrayify(bytecode); this.bytes = predicateBytes; this.interface = predicateInterface; if (data !== undefined && data.length > 0) { @@ -147,6 +149,46 @@ export class Predicate< return mainFn?.encodeArguments(this.predicateData) || new Uint8Array(); } + /** + * Creates a new Predicate instance from an existing Predicate instance. + * @param instance - The existing Predicate instance. + * @returns A new Predicate instance with the same bytecode, ABI and provider but with the ability to set the data and configurable constants. + */ + static fromInstance< + TData extends InputValue[] = InputValue[], + TConfigurables extends { [name: string]: unknown } | undefined = { [name: string]: unknown }, + >(instance: Predicate) { + return new (class { + data: TData; + configurableConstants: TConfigurables; + + constructor() { + this.data = instance.predicateData; + this.configurableConstants = {} as TConfigurables; + } + + withData(data: TData): this { + this.data = data; + return this; + } + + withConfigurableConstants(configurableConstants: TConfigurables): this { + this.configurableConstants = configurableConstants; + return this; + } + + build(): Predicate { + return new Predicate({ + bytecode: instance.initialBytecode, + abi: instance.interface.jsonAbi, + provider: instance.provider, + data: this.data, + configurableConstants: this.configurableConstants, + }); + } + })(); + } + /** * Processes the predicate data and returns the altered bytecode and interface. * diff --git a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts new file mode 100644 index 00000000000..c7090120211 --- /dev/null +++ b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts @@ -0,0 +1,431 @@ +import { Predicate, Provider, TransactionResponse, WalletUnlocked } from '@fuel-ts/account'; +import { launchTestNode } from 'fuels/test-utils'; +import { PredicateWithConfigurable } from '../../test/typegen'; +import { processPredicateData } from './utils/predicate/processPredicateData'; +import { + PredicateWithConfigurableConfigurables, + PredicateWithConfigurableInputs, +} from '../../test/typegen/predicates/PredicateWithConfigurable'; +import { fundPredicate, assertBalance } from './utils/predicate'; +import { getRandomB256 } from 'fuels'; + +/** + * @group node + * @group browser + * @group unit + */ +describe('Predicate.fromInstance', () => { + const amountToPredicate = 300_000; + + const defaultValues = { + FEE: 10, + ADDRESS: '0x38966262edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + }; + + describe('Basic Instance Operations', () => { + it('creates new predicate instance from existing one with default values', async () => { + using launched = await launchTestNode(); + + const provider = launched.provider; + const basePredicate = new PredicateWithConfigurable({ + provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, + }); + + const newPredicate: PredicateWithConfigurable = Predicate.fromInstance(basePredicate).build(); + + expect(newPredicate.predicateData).toEqual(basePredicate.predicateData); + expect(newPredicate.interface).toEqual(basePredicate.interface); + expect(newPredicate.provider).toEqual(basePredicate.provider); + expect(newPredicate.bytes).toEqual( + processPredicateData(basePredicate.initialBytecode, basePredicate.interface.jsonAbi, {}) + .predicateBytes + ); + }); + + it('creates new predicate instance with custom data', async () => { + using launched = await launchTestNode(); + + const provider = launched.provider; + const basePredicate = new PredicateWithConfigurable({ + provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, + }); + + const data: PredicateWithConfigurableInputs = [ + 13, + '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + ]; + const newPredicate: PredicateWithConfigurable = Predicate.fromInstance(basePredicate) + .withData(data) + .build(); + + expect(newPredicate.predicateData).toEqual(data); + expect(newPredicate.interface).toEqual(basePredicate.interface); + expect(newPredicate.provider).toEqual(basePredicate.provider); + expect(newPredicate.bytes).toEqual( + processPredicateData(basePredicate.initialBytecode, basePredicate.interface.jsonAbi, {}) + .predicateBytes + ); + }); + + it('creates new predicate instance with configurable constants', async () => { + using launched = await launchTestNode(); + + const provider = launched.provider; + const basePredicate = new PredicateWithConfigurable({ + provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, + }); + + const configurableConstants: PredicateWithConfigurableConfigurables = { + FEE: 13, + ADDRESS: '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + }; + const newPredicate: PredicateWithConfigurable = Predicate.fromInstance(basePredicate) + .withConfigurableConstants(configurableConstants) + .build(); + + expect(newPredicate.predicateData).toEqual(basePredicate.predicateData); + expect(newPredicate.interface).toEqual(basePredicate.interface); + expect(newPredicate.provider).toEqual(basePredicate.provider); + expect(newPredicate.bytes).toEqual( + processPredicateData( + basePredicate.initialBytecode, + basePredicate.interface.jsonAbi, + configurableConstants + ).predicateBytes + ); + }); + + it('supports chaining withData and withConfigurableConstants', async () => { + using launched = await launchTestNode(); + + const provider = launched.provider; + const basePredicate = new PredicateWithConfigurable({ + provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, + }); + + const data: PredicateWithConfigurableInputs = [ + 13, + '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + ]; + const configurableConstants: PredicateWithConfigurableConfigurables = { + FEE: 13, + ADDRESS: '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + }; + const newPredicate: PredicateWithConfigurable = Predicate.fromInstance(basePredicate) + .withData(data) + .withConfigurableConstants(configurableConstants) + .build(); + + expect(newPredicate.predicateData).toEqual(data); + expect(newPredicate.interface).toEqual(basePredicate.interface); + expect(newPredicate.provider).toEqual(basePredicate.provider); + expect(newPredicate.bytes).toEqual( + processPredicateData( + basePredicate.initialBytecode, + basePredicate.interface.jsonAbi, + configurableConstants + ).predicateBytes + ); + }); + + it('can create multiple different instances from same source, same bytecode', async () => { + using launched = await launchTestNode(); + + const provider = launched.provider; + const basePredicate = new PredicateWithConfigurable({ + provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, + }); + + const newPredicate1 = Predicate.fromInstance(basePredicate).build(); + const newPredicate2 = Predicate.fromInstance(basePredicate).build(); + + expect(newPredicate1.bytes).toEqual(newPredicate2.bytes); + }); + + it('can create multiple different instances from same source, different bytecode', async () => { + using launched = await launchTestNode(); + + const provider = launched.provider; + const basePredicate = new PredicateWithConfigurable({ + provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, + }); + + const configurableConstants: PredicateWithConfigurableConfigurables = { + FEE: 13, + ADDRESS: '0x38966262edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + }; + const newPredicate1 = Predicate.fromInstance(basePredicate).build(); + const newPredicate2 = Predicate.fromInstance(basePredicate) + .withConfigurableConstants(configurableConstants) + .build(); + + expect(newPredicate1.bytes).not.toEqual(newPredicate2.bytes); + }); + + it('does not modify original instance', async () => { + using launched = await launchTestNode(); + + const provider = launched.provider; + const basePredicate = new PredicateWithConfigurable({ + provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, + }); + + const bytes = basePredicate.bytes; + Predicate.fromInstance(basePredicate).build(); + + expect(basePredicate.bytes).toEqual(bytes); + }); + }); + + describe('End-to-End Scenarios', () => { + it('can transfer funds using duplicated predicate with same data and configurable constants', async () => { + using launched = await launchTestNode(); + + const { + provider, + wallets: [wallet], + } = launched; + + const basePredicate = new PredicateWithConfigurable({ + provider: wallet.provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, + }); + + const predicate = Predicate.fromInstance(basePredicate).build(); + + const amountToTransfer = 200; + + await fundPredicate(wallet, predicate, amountToPredicate); + + const destination = WalletUnlocked.generate({ + provider: wallet.provider, + }); + + await assertBalance(destination, 0, provider.getBaseAssetId()); + + const tx = await predicate.transfer( + destination.address, + amountToTransfer, + provider.getBaseAssetId(), + { + gasLimit: 1000, + } + ); + + await tx.waitForResult(); + + await assertBalance(destination, amountToTransfer, provider.getBaseAssetId()); + }); + + it('can transfer funds using duplicated predicate with different data and same configurable constants', async () => { + using launched = await launchTestNode(); + + const { + provider, + wallets: [wallet], + } = launched; + + const basePredicate = new PredicateWithConfigurable({ + provider: wallet.provider, + data: [13, '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96'], + configurableConstants: defaultValues, + }); + + const predicate = Predicate.fromInstance(basePredicate) + .withData([defaultValues.FEE, defaultValues.ADDRESS]) + .build(); + + const amountToTransfer = 200; + + await fundPredicate(wallet, predicate, amountToPredicate); + + const destination = WalletUnlocked.generate({ + provider: wallet.provider, + }); + + await assertBalance(destination, 0, provider.getBaseAssetId()); + + const tx = await predicate.transfer( + destination.address, + amountToTransfer, + provider.getBaseAssetId(), + { + gasLimit: 1000, + } + ); + + await tx.waitForResult(); + + await assertBalance(destination, amountToTransfer, provider.getBaseAssetId()); + }); + + it('can transfer funds using duplicated predicate with same data and different configurable constants', async () => { + using launched = await launchTestNode(); + + const { + provider, + wallets: [wallet], + } = launched; + + const basePredicate = new PredicateWithConfigurable({ + provider: wallet.provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: { + FEE: 13, + ADDRESS: '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + }, + }); + + const predicate = Predicate.fromInstance(basePredicate) + .withConfigurableConstants(defaultValues) + .build(); + + const amountToTransfer = 200; + + await fundPredicate(wallet, predicate, amountToPredicate); + + const destination = WalletUnlocked.generate({ + provider: wallet.provider, + }); + + await assertBalance(destination, 0, provider.getBaseAssetId()); + + const tx = await predicate.transfer( + destination.address, + amountToTransfer, + provider.getBaseAssetId(), + { + gasLimit: 1000, + } + ); + + await tx.waitForResult(); + + await assertBalance(destination, amountToTransfer, provider.getBaseAssetId()); + }); + + it('can transfer funds using duplicated predicate with different data and configurable constants', async () => { + using launched = await launchTestNode(); + + const { + provider, + wallets: [wallet], + } = launched; + + const basePredicate = new PredicateWithConfigurable({ + provider: wallet.provider, + data: [13, '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96'], + configurableConstants: { + FEE: 15, + ADDRESS: '0x38966262edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + }, + }); + + const predicate = Predicate.fromInstance(basePredicate) + .withData([defaultValues.FEE, defaultValues.ADDRESS]) + .withConfigurableConstants(defaultValues) + .build(); + + const amountToTransfer = 200; + + await fundPredicate(wallet, predicate, amountToPredicate); + + const destination = WalletUnlocked.generate({ + provider: wallet.provider, + }); + + await assertBalance(destination, 0, provider.getBaseAssetId()); + + const tx = await predicate.transfer( + destination.address, + amountToTransfer, + provider.getBaseAssetId(), + { + gasLimit: 1000, + } + ); + + await tx.waitForResult(); + + await assertBalance(destination, amountToTransfer, provider.getBaseAssetId()); + }); + + it('can reuse same factory to create multiple working predicates', async () => { + using launched = await launchTestNode(); + + const { + provider, + wallets: [wallet], + } = launched; + + const basePredicate = new PredicateWithConfigurable({ + provider: wallet.provider, + data: [13, '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96'], + configurableConstants: { + FEE: 15, + ADDRESS: '0x38966262edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + }, + }); + + const factory = Predicate.fromInstance(basePredicate); + + const predicate1 = factory + .withConfigurableConstants(defaultValues) + .withData([defaultValues.FEE, defaultValues.ADDRESS]) + .build(); + + const configurableConstants2 = { + FEE: 20, + ADDRESS: getRandomB256(), + }; + + const predicate2 = factory + .withConfigurableConstants(configurableConstants2) + .withData([configurableConstants2.FEE, configurableConstants2.ADDRESS]) + .build(); + + const configurableConstants3 = { + FEE: 30, + ADDRESS: getRandomB256(), + }; + + const predicate3 = factory + .withConfigurableConstants(configurableConstants3) + .withData([configurableConstants3.FEE, configurableConstants3.ADDRESS]) + .build(); + + const amountToTransfer = 200; + const destination = WalletUnlocked.generate({ provider: wallet.provider }); + + for (const predicate of [predicate1, predicate2, predicate3]) { + await fundPredicate(wallet, predicate, amountToPredicate); + + const tx = await predicate.transfer( + destination.address, + amountToTransfer, + provider.getBaseAssetId(), + { gasLimit: 1000 } + ); + + await tx.waitForResult(); + } + + await assertBalance(destination, amountToTransfer * 3, provider.getBaseAssetId()); + }); + }); +}); diff --git a/packages/fuel-gauge/src/predicate/utils/predicate/processPredicateData.ts b/packages/fuel-gauge/src/predicate/utils/predicate/processPredicateData.ts new file mode 100644 index 00000000000..2b0093888db --- /dev/null +++ b/packages/fuel-gauge/src/predicate/utils/predicate/processPredicateData.ts @@ -0,0 +1,70 @@ +import { InputValue, Predicate } from 'fuels'; + +import { arrayify } from 'fuels'; + +import { BytesLike, Interface, JsonAbi } from 'fuels'; +import { FuelError, ErrorCode } from '@fuel-ts/errors'; + +export function processPredicateData( + bytes: BytesLike, + jsonAbi: JsonAbi, + configurableConstants?: { [name: string]: unknown } +) { + let predicateBytes = arrayify(bytes); + const abiInterface: Interface = new Interface(jsonAbi); + + if (abiInterface.functions.main === undefined) { + throw new FuelError( + ErrorCode.ABI_MAIN_METHOD_MISSING, + 'Cannot use ABI without "main" function.' + ); + } + + if (configurableConstants && Object.keys(configurableConstants).length) { + predicateBytes = setConfigurableConstants(predicateBytes, configurableConstants, abiInterface); + } + + return { + predicateBytes, + predicateInterface: abiInterface, + }; +} + +function setConfigurableConstants( + bytes: Uint8Array, + configurableConstants: { [name: string]: unknown }, + abiInterface: Interface +) { + const mutatedBytes = bytes; + + try { + if (Object.keys(abiInterface.configurables).length === 0) { + throw new FuelError( + ErrorCode.INVALID_CONFIGURABLE_CONSTANTS, + 'Predicate has no configurable constants to be set' + ); + } + + Object.entries(configurableConstants).forEach(([key, value]) => { + if (!abiInterface?.configurables[key]) { + throw new FuelError( + ErrorCode.CONFIGURABLE_NOT_FOUND, + `No configurable constant named '${key}' found in the Predicate` + ); + } + + const { offset } = abiInterface.configurables[key]; + + const encoded = abiInterface.encodeConfigurable(key, value as InputValue); + + mutatedBytes.set(encoded, offset); + }); + } catch (err) { + throw new FuelError( + ErrorCode.INVALID_CONFIGURABLE_CONSTANTS, + `Error setting configurable constants: ${(err).message}.` + ); + } + + return mutatedBytes; +} From bac1e98dafbfc2136076bb97de2264fb7cba4c49 Mon Sep 17 00:00:00 2001 From: YaTut1901 Date: Thu, 5 Dec 2024 12:52:11 +0200 Subject: [PATCH 02/14] chore: refactored toNewInstance method --- packages/account/src/predicate/predicate.ts | 48 ++----- .../predicate/predicate-duplication.test.ts | 121 ++++-------------- templates/nextjs/src/components/Predicate.tsx | 2 +- templates/vite/src/components/Predicate.tsx | 2 +- 4 files changed, 40 insertions(+), 133 deletions(-) diff --git a/packages/account/src/predicate/predicate.ts b/packages/account/src/predicate/predicate.ts index c01e3b442d4..6193df8801a 100644 --- a/packages/account/src/predicate/predicate.ts +++ b/packages/account/src/predicate/predicate.ts @@ -49,7 +49,7 @@ export class Predicate< predicateData: TData = [] as unknown as TData; interface: Interface; initialBytecode: Uint8Array; - + configurableConstants: TConfigurables | undefined; /** * Creates an instance of the Predicate class. * @@ -77,6 +77,7 @@ export class Predicate< this.initialBytecode = arrayify(bytecode); this.bytes = predicateBytes; this.interface = predicateInterface; + this.configurableConstants = configurableConstants; if (data !== undefined && data.length > 0) { this.predicateData = data; } @@ -151,42 +152,19 @@ export class Predicate< /** * Creates a new Predicate instance from an existing Predicate instance. - * @param instance - The existing Predicate instance. + * @overrides - The data and configurable constants to override. * @returns A new Predicate instance with the same bytecode, ABI and provider but with the ability to set the data and configurable constants. */ - static fromInstance< - TData extends InputValue[] = InputValue[], - TConfigurables extends { [name: string]: unknown } | undefined = { [name: string]: unknown }, - >(instance: Predicate) { - return new (class { - data: TData; - configurableConstants: TConfigurables; - - constructor() { - this.data = instance.predicateData; - this.configurableConstants = {} as TConfigurables; - } - - withData(data: TData): this { - this.data = data; - return this; - } - - withConfigurableConstants(configurableConstants: TConfigurables): this { - this.configurableConstants = configurableConstants; - return this; - } - - build(): Predicate { - return new Predicate({ - bytecode: instance.initialBytecode, - abi: instance.interface.jsonAbi, - provider: instance.provider, - data: this.data, - configurableConstants: this.configurableConstants, - }); - } - })(); + toNewInstance( + overrides: Pick, 'data' | 'configurableConstants'> = {} + ) { + return new Predicate({ + bytecode: this.initialBytecode, + abi: this.interface.jsonAbi, + provider: this.provider, + data: overrides.data ?? this.predicateData, + configurableConstants: overrides.configurableConstants ?? this.configurableConstants, + }); } /** diff --git a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts index c7090120211..85c678c4236 100644 --- a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts @@ -1,4 +1,4 @@ -import { Predicate, Provider, TransactionResponse, WalletUnlocked } from '@fuel-ts/account'; +import { WalletUnlocked } from '@fuel-ts/account'; import { launchTestNode } from 'fuels/test-utils'; import { PredicateWithConfigurable } from '../../test/typegen'; import { processPredicateData } from './utils/predicate/processPredicateData'; @@ -7,12 +7,10 @@ import { PredicateWithConfigurableInputs, } from '../../test/typegen/predicates/PredicateWithConfigurable'; import { fundPredicate, assertBalance } from './utils/predicate'; -import { getRandomB256 } from 'fuels'; /** * @group node * @group browser - * @group unit */ describe('Predicate.fromInstance', () => { const amountToPredicate = 300_000; @@ -33,7 +31,7 @@ describe('Predicate.fromInstance', () => { configurableConstants: defaultValues, }); - const newPredicate: PredicateWithConfigurable = Predicate.fromInstance(basePredicate).build(); + const newPredicate: PredicateWithConfigurable = basePredicate.toNewInstance(); expect(newPredicate.predicateData).toEqual(basePredicate.predicateData); expect(newPredicate.interface).toEqual(basePredicate.interface); @@ -58,9 +56,7 @@ describe('Predicate.fromInstance', () => { 13, '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', ]; - const newPredicate: PredicateWithConfigurable = Predicate.fromInstance(basePredicate) - .withData(data) - .build(); + const newPredicate: PredicateWithConfigurable = basePredicate.toNewInstance({ data }); expect(newPredicate.predicateData).toEqual(data); expect(newPredicate.interface).toEqual(basePredicate.interface); @@ -85,9 +81,9 @@ describe('Predicate.fromInstance', () => { FEE: 13, ADDRESS: '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', }; - const newPredicate: PredicateWithConfigurable = Predicate.fromInstance(basePredicate) - .withConfigurableConstants(configurableConstants) - .build(); + const newPredicate: PredicateWithConfigurable = basePredicate.toNewInstance({ + configurableConstants, + }); expect(newPredicate.predicateData).toEqual(basePredicate.predicateData); expect(newPredicate.interface).toEqual(basePredicate.interface); @@ -119,10 +115,10 @@ describe('Predicate.fromInstance', () => { FEE: 13, ADDRESS: '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', }; - const newPredicate: PredicateWithConfigurable = Predicate.fromInstance(basePredicate) - .withData(data) - .withConfigurableConstants(configurableConstants) - .build(); + const newPredicate: PredicateWithConfigurable = basePredicate.toNewInstance({ + data, + configurableConstants, + }); expect(newPredicate.predicateData).toEqual(data); expect(newPredicate.interface).toEqual(basePredicate.interface); @@ -146,8 +142,8 @@ describe('Predicate.fromInstance', () => { configurableConstants: defaultValues, }); - const newPredicate1 = Predicate.fromInstance(basePredicate).build(); - const newPredicate2 = Predicate.fromInstance(basePredicate).build(); + const newPredicate1 = basePredicate.toNewInstance(); + const newPredicate2 = basePredicate.toNewInstance(); expect(newPredicate1.bytes).toEqual(newPredicate2.bytes); }); @@ -166,10 +162,8 @@ describe('Predicate.fromInstance', () => { FEE: 13, ADDRESS: '0x38966262edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', }; - const newPredicate1 = Predicate.fromInstance(basePredicate).build(); - const newPredicate2 = Predicate.fromInstance(basePredicate) - .withConfigurableConstants(configurableConstants) - .build(); + const newPredicate1 = basePredicate.toNewInstance(); + const newPredicate2 = basePredicate.toNewInstance({ configurableConstants }); expect(newPredicate1.bytes).not.toEqual(newPredicate2.bytes); }); @@ -185,9 +179,9 @@ describe('Predicate.fromInstance', () => { }); const bytes = basePredicate.bytes; - Predicate.fromInstance(basePredicate).build(); + const newPredicate = basePredicate.toNewInstance(); - expect(basePredicate.bytes).toEqual(bytes); + expect(newPredicate.bytes).toEqual(bytes); }); }); @@ -206,7 +200,7 @@ describe('Predicate.fromInstance', () => { configurableConstants: defaultValues, }); - const predicate = Predicate.fromInstance(basePredicate).build(); + const predicate = basePredicate.toNewInstance(); const amountToTransfer = 200; @@ -246,9 +240,9 @@ describe('Predicate.fromInstance', () => { configurableConstants: defaultValues, }); - const predicate = Predicate.fromInstance(basePredicate) - .withData([defaultValues.FEE, defaultValues.ADDRESS]) - .build(); + const predicate = basePredicate.toNewInstance({ + data: [defaultValues.FEE, defaultValues.ADDRESS], + }); const amountToTransfer = 200; @@ -291,9 +285,7 @@ describe('Predicate.fromInstance', () => { }, }); - const predicate = Predicate.fromInstance(basePredicate) - .withConfigurableConstants(defaultValues) - .build(); + const predicate = basePredicate.toNewInstance({ configurableConstants: defaultValues }); const amountToTransfer = 200; @@ -336,10 +328,10 @@ describe('Predicate.fromInstance', () => { }, }); - const predicate = Predicate.fromInstance(basePredicate) - .withData([defaultValues.FEE, defaultValues.ADDRESS]) - .withConfigurableConstants(defaultValues) - .build(); + const predicate = basePredicate.toNewInstance({ + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, + }); const amountToTransfer = 200; @@ -364,68 +356,5 @@ describe('Predicate.fromInstance', () => { await assertBalance(destination, amountToTransfer, provider.getBaseAssetId()); }); - - it('can reuse same factory to create multiple working predicates', async () => { - using launched = await launchTestNode(); - - const { - provider, - wallets: [wallet], - } = launched; - - const basePredicate = new PredicateWithConfigurable({ - provider: wallet.provider, - data: [13, '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96'], - configurableConstants: { - FEE: 15, - ADDRESS: '0x38966262edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', - }, - }); - - const factory = Predicate.fromInstance(basePredicate); - - const predicate1 = factory - .withConfigurableConstants(defaultValues) - .withData([defaultValues.FEE, defaultValues.ADDRESS]) - .build(); - - const configurableConstants2 = { - FEE: 20, - ADDRESS: getRandomB256(), - }; - - const predicate2 = factory - .withConfigurableConstants(configurableConstants2) - .withData([configurableConstants2.FEE, configurableConstants2.ADDRESS]) - .build(); - - const configurableConstants3 = { - FEE: 30, - ADDRESS: getRandomB256(), - }; - - const predicate3 = factory - .withConfigurableConstants(configurableConstants3) - .withData([configurableConstants3.FEE, configurableConstants3.ADDRESS]) - .build(); - - const amountToTransfer = 200; - const destination = WalletUnlocked.generate({ provider: wallet.provider }); - - for (const predicate of [predicate1, predicate2, predicate3]) { - await fundPredicate(wallet, predicate, amountToPredicate); - - const tx = await predicate.transfer( - destination.address, - amountToTransfer, - provider.getBaseAssetId(), - { gasLimit: 1000 } - ); - - await tx.waitForResult(); - } - - await assertBalance(destination, amountToTransfer * 3, provider.getBaseAssetId()); - }); }); }); diff --git a/templates/nextjs/src/components/Predicate.tsx b/templates/nextjs/src/components/Predicate.tsx index bbc5ca23435..4fa1223b7cd 100644 --- a/templates/nextjs/src/components/Predicate.tsx +++ b/templates/nextjs/src/components/Predicate.tsx @@ -16,7 +16,7 @@ export default function Predicate() { successNotification, } = useNotification(); useNotification(); - const [predicate, setPredicate] = useState>(); + const [predicate, setPredicate] = useState(); const [predicatePin, setPredicatePin] = useState(); const [isLoading, setIsLoading] = useState(false); diff --git a/templates/vite/src/components/Predicate.tsx b/templates/vite/src/components/Predicate.tsx index 0bc92492dad..a4f74f770e2 100644 --- a/templates/vite/src/components/Predicate.tsx +++ b/templates/vite/src/components/Predicate.tsx @@ -15,7 +15,7 @@ export default function Predicate() { transactionSuccessNotification, successNotification, } = useNotification(); - const [predicate, setPredicate] = useState>(); + const [predicate, setPredicate] = useState(); const [predicatePin, setPredicatePin] = useState(); const [isLoading, setIsLoading] = useState(false); From 8c2e49c03a57ab97a8bf758bfbc26fc2aaebc9ff Mon Sep 17 00:00:00 2001 From: YaTut1901 Date: Mon, 9 Dec 2024 10:31:35 +0200 Subject: [PATCH 03/14] chore: fixed some lint errors --- packages/account/src/predicate/predicate.ts | 2 +- .../predicate/predicate-duplication.test.ts | 6 +- .../utils/predicate/fundPredicate.ts | 7 ++- .../utils/predicate/processPredicateData.ts | 57 +++++++++---------- 4 files changed, 37 insertions(+), 35 deletions(-) diff --git a/packages/account/src/predicate/predicate.ts b/packages/account/src/predicate/predicate.ts index 6193df8801a..2e9dacdb4c0 100644 --- a/packages/account/src/predicate/predicate.ts +++ b/packages/account/src/predicate/predicate.ts @@ -152,7 +152,7 @@ export class Predicate< /** * Creates a new Predicate instance from an existing Predicate instance. - * @overrides - The data and configurable constants to override. + * @param overrides - The data and configurable constants to override. * @returns A new Predicate instance with the same bytecode, ABI and provider but with the ability to set the data and configurable constants. */ toNewInstance( diff --git a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts index 85c678c4236..b94c1ee4022 100644 --- a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts @@ -1,12 +1,14 @@ import { WalletUnlocked } from '@fuel-ts/account'; import { launchTestNode } from 'fuels/test-utils'; + import { PredicateWithConfigurable } from '../../test/typegen'; -import { processPredicateData } from './utils/predicate/processPredicateData'; -import { +import type { PredicateWithConfigurableConfigurables, PredicateWithConfigurableInputs, } from '../../test/typegen/predicates/PredicateWithConfigurable'; + import { fundPredicate, assertBalance } from './utils/predicate'; +import { processPredicateData } from './utils/predicate/processPredicateData'; /** * @group node diff --git a/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts b/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts index 8d092e444a0..8708a60e846 100644 --- a/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts +++ b/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts @@ -1,9 +1,12 @@ import type { InputValue, BigNumberish, WalletUnlocked, Predicate } from 'fuels'; import { ScriptTransactionRequest, BN } from 'fuels'; -export const fundPredicate = async ( +export const fundPredicate = async < + T extends InputValue[] = InputValue[], + C extends { [name: string]: unknown } | undefined = { [name: string]: unknown }, +>( wallet: WalletUnlocked, - predicate: Predicate, + predicate: Predicate, amountToPredicate: BigNumberish, utxosAmount: number = 1 ): Promise => { diff --git a/packages/fuel-gauge/src/predicate/utils/predicate/processPredicateData.ts b/packages/fuel-gauge/src/predicate/utils/predicate/processPredicateData.ts index 2b0093888db..27073611aaf 100644 --- a/packages/fuel-gauge/src/predicate/utils/predicate/processPredicateData.ts +++ b/packages/fuel-gauge/src/predicate/utils/predicate/processPredicateData.ts @@ -1,34 +1,6 @@ -import { InputValue, Predicate } from 'fuels'; - -import { arrayify } from 'fuels'; - -import { BytesLike, Interface, JsonAbi } from 'fuels'; import { FuelError, ErrorCode } from '@fuel-ts/errors'; - -export function processPredicateData( - bytes: BytesLike, - jsonAbi: JsonAbi, - configurableConstants?: { [name: string]: unknown } -) { - let predicateBytes = arrayify(bytes); - const abiInterface: Interface = new Interface(jsonAbi); - - if (abiInterface.functions.main === undefined) { - throw new FuelError( - ErrorCode.ABI_MAIN_METHOD_MISSING, - 'Cannot use ABI without "main" function.' - ); - } - - if (configurableConstants && Object.keys(configurableConstants).length) { - predicateBytes = setConfigurableConstants(predicateBytes, configurableConstants, abiInterface); - } - - return { - predicateBytes, - predicateInterface: abiInterface, - }; -} +import { arrayify, Interface } from 'fuels'; +import type { BytesLike, JsonAbi, InputValue } from 'fuels'; function setConfigurableConstants( bytes: Uint8Array, @@ -68,3 +40,28 @@ function setConfigurableConstants( return mutatedBytes; } + +export function processPredicateData( + bytes: BytesLike, + jsonAbi: JsonAbi, + configurableConstants?: { [name: string]: unknown } +) { + let predicateBytes = arrayify(bytes); + const abiInterface: Interface = new Interface(jsonAbi); + + if (abiInterface.functions.main === undefined) { + throw new FuelError( + ErrorCode.ABI_MAIN_METHOD_MISSING, + 'Cannot use ABI without "main" function.' + ); + } + + if (configurableConstants && Object.keys(configurableConstants).length) { + predicateBytes = setConfigurableConstants(predicateBytes, configurableConstants, abiInterface); + } + + return { + predicateBytes, + predicateInterface: abiInterface, + }; +} From 486d942b00c67174249d813b92d2fd4a79f9ece5 Mon Sep 17 00:00:00 2001 From: YaTut1901 Date: Mon, 9 Dec 2024 10:32:54 +0200 Subject: [PATCH 04/14] chore: added changeset --- .changeset/gentle-toes-play.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/gentle-toes-play.md diff --git a/.changeset/gentle-toes-play.md b/.changeset/gentle-toes-play.md new file mode 100644 index 00000000000..0e50d5619c1 --- /dev/null +++ b/.changeset/gentle-toes-play.md @@ -0,0 +1,5 @@ +--- +"@fuel-ts/account": patch +--- + +chore: added static method to duplicate predicate From d8979d64fd07509b3eebc7db3eb68155690fb21c Mon Sep 17 00:00:00 2001 From: Ivan Oberemok Date: Tue, 10 Dec 2024 10:01:01 +0200 Subject: [PATCH 05/14] Update packages/fuel-gauge/src/predicate/predicate-duplication.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sérgio Torres <30977845+Torres-ssf@users.noreply.github.com> --- .../fuel-gauge/src/predicate/predicate-duplication.test.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts index b94c1ee4022..d1c56077c74 100644 --- a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts @@ -38,10 +38,7 @@ describe('Predicate.fromInstance', () => { expect(newPredicate.predicateData).toEqual(basePredicate.predicateData); expect(newPredicate.interface).toEqual(basePredicate.interface); expect(newPredicate.provider).toEqual(basePredicate.provider); - expect(newPredicate.bytes).toEqual( - processPredicateData(basePredicate.initialBytecode, basePredicate.interface.jsonAbi, {}) - .predicateBytes - ); + expect(newPredicate.bytes).toEqual(basePredicate.bytes); }); it('creates new predicate instance with custom data', async () => { From da551bab9f73f0dfc1732a864def240f49b5dcb4 Mon Sep 17 00:00:00 2001 From: Ivan Oberemok Date: Tue, 10 Dec 2024 10:01:13 +0200 Subject: [PATCH 06/14] Update packages/fuel-gauge/src/predicate/predicate-duplication.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sérgio Torres <30977845+Torres-ssf@users.noreply.github.com> --- .../fuel-gauge/src/predicate/predicate-duplication.test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts index d1c56077c74..a01fdc00caa 100644 --- a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts @@ -60,10 +60,8 @@ describe('Predicate.fromInstance', () => { expect(newPredicate.predicateData).toEqual(data); expect(newPredicate.interface).toEqual(basePredicate.interface); expect(newPredicate.provider).toEqual(basePredicate.provider); - expect(newPredicate.bytes).toEqual( - processPredicateData(basePredicate.initialBytecode, basePredicate.interface.jsonAbi, {}) - .predicateBytes - ); + expect(newPredicate.bytes).toEqual(basePredicate.bytes); + expect(newPredicate.predicateData).not.toEqual(basePredicate.predicateData); }); it('creates new predicate instance with configurable constants', async () => { From 33d79a4e89e5e0d360c573a5532661d8faa22736 Mon Sep 17 00:00:00 2001 From: Ivan Oberemok Date: Tue, 10 Dec 2024 10:01:29 +0200 Subject: [PATCH 07/14] Update packages/fuel-gauge/src/predicate/predicate-duplication.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sérgio Torres <30977845+Torres-ssf@users.noreply.github.com> --- .../src/predicate/predicate-duplication.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts index a01fdc00caa..d27bbe51e72 100644 --- a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts @@ -86,11 +86,11 @@ describe('Predicate.fromInstance', () => { expect(newPredicate.interface).toEqual(basePredicate.interface); expect(newPredicate.provider).toEqual(basePredicate.provider); expect(newPredicate.bytes).toEqual( - processPredicateData( - basePredicate.initialBytecode, - basePredicate.interface.jsonAbi, - configurableConstants - ).predicateBytes + new PredicateWithConfigurable({ + provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants, + }).bytes ); }); From 1c55a2e6fe386a17e14961c1ac58d21e56ca9adc Mon Sep 17 00:00:00 2001 From: Ivan Oberemok Date: Tue, 10 Dec 2024 10:01:40 +0200 Subject: [PATCH 08/14] Update packages/fuel-gauge/src/predicate/predicate-duplication.test.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sérgio Torres <30977845+Torres-ssf@users.noreply.github.com> --- .../src/predicate/predicate-duplication.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts index d27bbe51e72..f1de508a075 100644 --- a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts @@ -121,11 +121,11 @@ describe('Predicate.fromInstance', () => { expect(newPredicate.interface).toEqual(basePredicate.interface); expect(newPredicate.provider).toEqual(basePredicate.provider); expect(newPredicate.bytes).toEqual( - processPredicateData( - basePredicate.initialBytecode, - basePredicate.interface.jsonAbi, - configurableConstants - ).predicateBytes + new PredicateWithConfigurable({ + provider, + data, + configurableConstants, + }).bytes ); }); From d3b488a678647c2df29af7eba08e375c49951262 Mon Sep 17 00:00:00 2001 From: Ivan Oberemok Date: Tue, 10 Dec 2024 10:01:48 +0200 Subject: [PATCH 09/14] Update packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sérgio Torres <30977845+Torres-ssf@users.noreply.github.com> --- .../src/predicate/utils/predicate/fundPredicate.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts b/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts index 8708a60e846..1220e9648ed 100644 --- a/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts +++ b/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts @@ -1,10 +1,7 @@ import type { InputValue, BigNumberish, WalletUnlocked, Predicate } from 'fuels'; import { ScriptTransactionRequest, BN } from 'fuels'; -export const fundPredicate = async < - T extends InputValue[] = InputValue[], - C extends { [name: string]: unknown } | undefined = { [name: string]: unknown }, ->( +export const fundPredicate = async ( wallet: WalletUnlocked, predicate: Predicate, amountToPredicate: BigNumberish, From dd87424543f8ba18d5a170e927e3058d5a6c6d22 Mon Sep 17 00:00:00 2001 From: Ivan Oberemok Date: Tue, 10 Dec 2024 10:01:56 +0200 Subject: [PATCH 10/14] Update packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Sérgio Torres <30977845+Torres-ssf@users.noreply.github.com> --- .../fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts b/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts index 1220e9648ed..b8f090393fe 100644 --- a/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts +++ b/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts @@ -3,7 +3,7 @@ import { ScriptTransactionRequest, BN } from 'fuels'; export const fundPredicate = async ( wallet: WalletUnlocked, - predicate: Predicate, + predicate: Predicate, amountToPredicate: BigNumberish, utxosAmount: number = 1 ): Promise => { From 3a324b5cc4c4e4a9fc04f237fd85ba49d2d33e8a Mon Sep 17 00:00:00 2001 From: YaTut1901 Date: Tue, 10 Dec 2024 10:04:07 +0200 Subject: [PATCH 11/14] chore: removed helpers --- .../predicate/predicate-duplication.test.ts | 1 - .../utils/predicate/processPredicateData.ts | 67 ------------------- 2 files changed, 68 deletions(-) delete mode 100644 packages/fuel-gauge/src/predicate/utils/predicate/processPredicateData.ts diff --git a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts index f1de508a075..31233ed54e4 100644 --- a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts @@ -8,7 +8,6 @@ import type { } from '../../test/typegen/predicates/PredicateWithConfigurable'; import { fundPredicate, assertBalance } from './utils/predicate'; -import { processPredicateData } from './utils/predicate/processPredicateData'; /** * @group node diff --git a/packages/fuel-gauge/src/predicate/utils/predicate/processPredicateData.ts b/packages/fuel-gauge/src/predicate/utils/predicate/processPredicateData.ts deleted file mode 100644 index 27073611aaf..00000000000 --- a/packages/fuel-gauge/src/predicate/utils/predicate/processPredicateData.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { FuelError, ErrorCode } from '@fuel-ts/errors'; -import { arrayify, Interface } from 'fuels'; -import type { BytesLike, JsonAbi, InputValue } from 'fuels'; - -function setConfigurableConstants( - bytes: Uint8Array, - configurableConstants: { [name: string]: unknown }, - abiInterface: Interface -) { - const mutatedBytes = bytes; - - try { - if (Object.keys(abiInterface.configurables).length === 0) { - throw new FuelError( - ErrorCode.INVALID_CONFIGURABLE_CONSTANTS, - 'Predicate has no configurable constants to be set' - ); - } - - Object.entries(configurableConstants).forEach(([key, value]) => { - if (!abiInterface?.configurables[key]) { - throw new FuelError( - ErrorCode.CONFIGURABLE_NOT_FOUND, - `No configurable constant named '${key}' found in the Predicate` - ); - } - - const { offset } = abiInterface.configurables[key]; - - const encoded = abiInterface.encodeConfigurable(key, value as InputValue); - - mutatedBytes.set(encoded, offset); - }); - } catch (err) { - throw new FuelError( - ErrorCode.INVALID_CONFIGURABLE_CONSTANTS, - `Error setting configurable constants: ${(err).message}.` - ); - } - - return mutatedBytes; -} - -export function processPredicateData( - bytes: BytesLike, - jsonAbi: JsonAbi, - configurableConstants?: { [name: string]: unknown } -) { - let predicateBytes = arrayify(bytes); - const abiInterface: Interface = new Interface(jsonAbi); - - if (abiInterface.functions.main === undefined) { - throw new FuelError( - ErrorCode.ABI_MAIN_METHOD_MISSING, - 'Cannot use ABI without "main" function.' - ); - } - - if (configurableConstants && Object.keys(configurableConstants).length) { - predicateBytes = setConfigurableConstants(predicateBytes, configurableConstants, abiInterface); - } - - return { - predicateBytes, - predicateInterface: abiInterface, - }; -} From 47b01ad380b43314f4d843183427748742922e58 Mon Sep 17 00:00:00 2001 From: YaTut1901 Date: Tue, 10 Dec 2024 10:23:26 +0200 Subject: [PATCH 12/14] chore: typing in fund function --- .../src/predicate/utils/predicate/fundPredicate.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts b/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts index b8f090393fe..8708a60e846 100644 --- a/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts +++ b/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts @@ -1,9 +1,12 @@ import type { InputValue, BigNumberish, WalletUnlocked, Predicate } from 'fuels'; import { ScriptTransactionRequest, BN } from 'fuels'; -export const fundPredicate = async ( +export const fundPredicate = async < + T extends InputValue[] = InputValue[], + C extends { [name: string]: unknown } | undefined = { [name: string]: unknown }, +>( wallet: WalletUnlocked, - predicate: Predicate, + predicate: Predicate, amountToPredicate: BigNumberish, utxosAmount: number = 1 ): Promise => { From bf2c404d567c00a02eb0d1a693f3173bff511e2c Mon Sep 17 00:00:00 2001 From: YaTut1901 Date: Tue, 10 Dec 2024 16:59:34 +0200 Subject: [PATCH 13/14] chore: refactored fundPredicate function to fundAccount --- .../src/predicate/predicate-arguments.test.ts | 20 +++++------ .../predicate/predicate-configurables.test.ts | 14 ++++---- .../predicate/predicate-duplication.test.ts | 10 +++--- .../predicate/predicate-estimations.test.ts | 16 ++++----- .../predicate/predicate-evaluations.test.ts | 6 ++-- .../predicate/predicate-input-data.test.ts | 4 +-- .../predicate/predicate-invalidations.test.ts | 6 ++-- .../predicate-populate-witness.test.ts | 20 +++++------ .../predicate/predicate-with-contract.test.ts | 6 ++-- .../predicate/predicate-with-script.test.ts | 4 +-- .../predicate/utils/predicate/fundAccount.ts | 26 +++++++++++++++ .../utils/predicate/fundPredicate.ts | 33 ------------------- .../src/predicate/utils/predicate/index.ts | 2 +- 13 files changed, 80 insertions(+), 87 deletions(-) create mode 100644 packages/fuel-gauge/src/predicate/utils/predicate/fundAccount.ts delete mode 100644 packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts diff --git a/packages/fuel-gauge/src/predicate/predicate-arguments.test.ts b/packages/fuel-gauge/src/predicate/predicate-arguments.test.ts index d9c6d2f8ee9..84e0ddd80c9 100644 --- a/packages/fuel-gauge/src/predicate/predicate-arguments.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-arguments.test.ts @@ -9,7 +9,7 @@ import { PredicateU32, } from '../../test/typegen'; -import { fundPredicate, assertBalances } from './utils/predicate'; +import { fundAccount, assertBalances } from './utils/predicate'; /** * @group node @@ -34,7 +34,7 @@ describe('Predicate', () => { }); // transfer funds to predicate - await fundPredicate(fundingWallet, predicate, amountToPredicate, 3); + await fundAccount(fundingWallet, predicate, amountToPredicate, 3); const receiver = Wallet.generate({ provider }); const initialReceiverBalance = await receiver.getBalance(); @@ -67,7 +67,7 @@ describe('Predicate', () => { }); // fund predicate - await fundPredicate(fundingWallet, predicate, amountToPredicate); + await fundAccount(fundingWallet, predicate, amountToPredicate); const receiver = Wallet.generate({ provider }); @@ -91,7 +91,7 @@ describe('Predicate', () => { const initialReceiverBalance = await receiver.getBalance(); // fund predicate - await fundPredicate(fundingWallet, predicate, amountToPredicate); + await fundAccount(fundingWallet, predicate, amountToPredicate); const tx = await predicate.transfer( receiver.address, @@ -118,7 +118,7 @@ describe('Predicate', () => { const predicate = new PredicateU32({ provider, data: [100] }); // fund predicate - await fundPredicate(fundingWallet, predicate, 90_000_00, 3); + await fundAccount(fundingWallet, predicate, 90_000_00, 3); const receiver = Wallet.generate({ provider }); const initialReceiverBalance = await receiver.getBalance(); @@ -191,7 +191,7 @@ describe('Predicate', () => { const receiver = Wallet.generate({ provider }); // fund predicate - await fundPredicate(fundingWallet, predicate, amountToPredicate); + await fundAccount(fundingWallet, predicate, amountToPredicate); await expect( predicate.transfer(receiver.address, 50, provider.getBaseAssetId(), { gasLimit: 1000 }) @@ -212,7 +212,7 @@ describe('Predicate', () => { const initialReceiverBalance = await receiver.getBalance(); // fund predicate - await fundPredicate(fundingWallet, predicate, amountToPredicate); + await fundAccount(fundingWallet, predicate, amountToPredicate); const tx = await predicate.transfer( receiver.address, @@ -242,7 +242,7 @@ describe('Predicate', () => { const predicate = new PredicateMultiArgs({ provider, data: [20, 30] }); // fund the predicate - await fundPredicate(fundingWallet, predicate, amountToPredicate); + await fundAccount(fundingWallet, predicate, amountToPredicate); const tx = await predicate.transfer( receiver.address, @@ -272,7 +272,7 @@ describe('Predicate', () => { const predicate = new PredicateMultiArgs({ provider, data: [20, 30] }); // fund predicate - await fundPredicate(fundingWallet, predicate, amountToPredicate); + await fundAccount(fundingWallet, predicate, amountToPredicate); const tx = await predicate.transfer( receiver.address, @@ -299,7 +299,7 @@ describe('Predicate', () => { const predicate = new PredicateMultiArgs({ provider, data: [20, 20] }); // fund predicate - await fundPredicate(fundingWallet, predicate, amountToPredicate); + await fundAccount(fundingWallet, predicate, amountToPredicate); const receiver = Wallet.generate({ provider }); diff --git a/packages/fuel-gauge/src/predicate/predicate-configurables.test.ts b/packages/fuel-gauge/src/predicate/predicate-configurables.test.ts index 582f757e1a2..2a409c3d651 100644 --- a/packages/fuel-gauge/src/predicate/predicate-configurables.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-configurables.test.ts @@ -3,7 +3,7 @@ import { expectToThrowFuelError, launchTestNode } from 'fuels/test-utils'; import { PredicateTrue, PredicateWithConfigurable } from '../../test/typegen'; -import { fundPredicate, assertBalance } from './utils/predicate'; +import { fundAccount, assertBalance } from './utils/predicate'; /** * @group node @@ -33,7 +33,7 @@ describe('Predicate', () => { const amountToTransfer = 200; - await fundPredicate(wallet, predicate, amountToPredicate); + await fundAccount(wallet, predicate, amountToPredicate); // create destination wallet const destination = WalletUnlocked.generate({ @@ -82,7 +82,7 @@ describe('Predicate', () => { await assertBalance(destination, 0, provider.getBaseAssetId()); // transfer funds to predicate - await fundPredicate(wallet, predicate, amountToPredicate); + await fundAccount(wallet, predicate, amountToPredicate); // executing predicate transfer const tx = await predicate.transfer( @@ -125,7 +125,7 @@ describe('Predicate', () => { await assertBalance(destination, 0, provider.getBaseAssetId()); // transfer funds to predicate - await fundPredicate(wallet, predicate, amountToPredicate); + await fundAccount(wallet, predicate, amountToPredicate); // executing predicate transfer const tx = await predicate.transfer( @@ -171,7 +171,7 @@ describe('Predicate', () => { await assertBalance(destination, 0, provider.getBaseAssetId()); - await fundPredicate(wallet, predicate, amountToPredicate); + await fundAccount(wallet, predicate, amountToPredicate); const tx = await predicate.transfer( destination.address, @@ -213,7 +213,7 @@ describe('Predicate', () => { await assertBalance(destination, 0, provider.getBaseAssetId()); - await fundPredicate(wallet, predicate, amountToPredicate); + await fundAccount(wallet, predicate, amountToPredicate); const tx = await predicate.transfer( destination.address, @@ -245,7 +245,7 @@ describe('Predicate', () => { provider: wallet.provider, }); - await fundPredicate(wallet, predicate, amountToPredicate); + await fundAccount(wallet, predicate, amountToPredicate); await expect( predicate.transfer(destination.address, 300, provider.getBaseAssetId(), { gasLimit: 1000 }) diff --git a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts index 31233ed54e4..156e0cace83 100644 --- a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts @@ -7,7 +7,7 @@ import type { PredicateWithConfigurableInputs, } from '../../test/typegen/predicates/PredicateWithConfigurable'; -import { fundPredicate, assertBalance } from './utils/predicate'; +import { fundAccount, assertBalance } from './utils/predicate'; /** * @group node @@ -200,7 +200,7 @@ describe('Predicate.fromInstance', () => { const amountToTransfer = 200; - await fundPredicate(wallet, predicate, amountToPredicate); + await fundAccount(wallet, predicate, amountToPredicate); const destination = WalletUnlocked.generate({ provider: wallet.provider, @@ -242,7 +242,7 @@ describe('Predicate.fromInstance', () => { const amountToTransfer = 200; - await fundPredicate(wallet, predicate, amountToPredicate); + await fundAccount(wallet, predicate, amountToPredicate); const destination = WalletUnlocked.generate({ provider: wallet.provider, @@ -285,7 +285,7 @@ describe('Predicate.fromInstance', () => { const amountToTransfer = 200; - await fundPredicate(wallet, predicate, amountToPredicate); + await fundAccount(wallet, predicate, amountToPredicate); const destination = WalletUnlocked.generate({ provider: wallet.provider, @@ -331,7 +331,7 @@ describe('Predicate.fromInstance', () => { const amountToTransfer = 200; - await fundPredicate(wallet, predicate, amountToPredicate); + await fundAccount(wallet, predicate, amountToPredicate); const destination = WalletUnlocked.generate({ provider: wallet.provider, diff --git a/packages/fuel-gauge/src/predicate/predicate-estimations.test.ts b/packages/fuel-gauge/src/predicate/predicate-estimations.test.ts index f37a0d06943..3919c0c9b9f 100644 --- a/packages/fuel-gauge/src/predicate/predicate-estimations.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-estimations.test.ts @@ -22,7 +22,7 @@ import { } from '../../test/typegen'; import type { Validation } from '../types/predicate'; -import { fundPredicate } from './utils/predicate'; +import { fundAccount } from './utils/predicate'; /** * @group node @@ -48,7 +48,7 @@ describe('Predicate', () => { provider, }); - await fundPredicate(wallet, predicateStruct, fundingAmount); + await fundAccount(wallet, predicateStruct, fundingAmount); const tx = new ScriptTransactionRequest(); @@ -138,7 +138,7 @@ describe('Predicate', () => { const predicateTrue = new PredicateTrue({ provider }); - await fundPredicate(wallet, predicateTrue, fundingAmount); + await fundAccount(wallet, predicateTrue, fundingAmount); const resources = await predicateTrue.getResourcesToSpend([[1, provider.getBaseAssetId()]]); tx.addResources(resources); @@ -167,8 +167,8 @@ describe('Predicate', () => { provider, }); - await fundPredicate(wallet, predicateTrue, fundingAmount); - await fundPredicate(wallet, predicateStruct, fundingAmount); + await fundAccount(wallet, predicateTrue, fundingAmount); + await fundAccount(wallet, predicateStruct, fundingAmount); const tx = new ScriptTransactionRequest(); const trueResources = await predicateTrue.getResourcesToSpend([ @@ -210,7 +210,7 @@ describe('Predicate', () => { data: [bn(amountToPredicate)], }); - await fundPredicate(wallet, predicateValidateTransfer, amountToPredicate); + await fundAccount(wallet, predicateValidateTransfer, amountToPredicate); const receiverWallet = WalletUnlocked.generate({ provider, @@ -252,7 +252,7 @@ describe('Predicate', () => { provider, }); - await fundPredicate(wallet, predicateStruct, fundingAmount); + await fundAccount(wallet, predicateStruct, fundingAmount); const transactionRequest = new ScriptTransactionRequest(); @@ -286,7 +286,7 @@ describe('Predicate', () => { provider, }); - await fundPredicate(wallet, predicateStruct, fundingAmount); + await fundAccount(wallet, predicateStruct, fundingAmount); const transactionRequest = new ScriptTransactionRequest(); diff --git a/packages/fuel-gauge/src/predicate/predicate-evaluations.test.ts b/packages/fuel-gauge/src/predicate/predicate-evaluations.test.ts index eab569adbc2..14bbbc60997 100644 --- a/packages/fuel-gauge/src/predicate/predicate-evaluations.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-evaluations.test.ts @@ -3,7 +3,7 @@ import { launchTestNode } from 'fuels/test-utils'; import { PredicateTrue, PredicateFalse } from '../../test/typegen/predicates'; -import { assertBalances, fundPredicate } from './utils/predicate'; +import { assertBalances, fundAccount } from './utils/predicate'; /** * @group node @@ -24,7 +24,7 @@ describe('Predicate', () => { const predicate = new PredicateTrue({ provider }); - await fundPredicate(wallet, predicate, 200_000); + await fundAccount(wallet, predicate, 200_000); const amountToReceiver = 50; @@ -55,7 +55,7 @@ describe('Predicate', () => { const predicate = new PredicateFalse({ provider }); - await fundPredicate(wallet, predicate, 200_000); + await fundAccount(wallet, predicate, 200_000); await expect( predicate.transfer(receiver.address, 50, provider.getBaseAssetId(), { diff --git a/packages/fuel-gauge/src/predicate/predicate-input-data.test.ts b/packages/fuel-gauge/src/predicate/predicate-input-data.test.ts index 6e80bc22a35..a804b0af70c 100644 --- a/packages/fuel-gauge/src/predicate/predicate-input-data.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-input-data.test.ts @@ -3,7 +3,7 @@ import { launchTestNode } from 'fuels/test-utils'; import { PredicateInputData } from '../../test/typegen'; -import { fundPredicate } from './utils/predicate'; +import { fundAccount } from './utils/predicate'; /** * @group node @@ -24,7 +24,7 @@ describe('Predicate', () => { const predicate = new PredicateInputData({ provider }); - await fundPredicate(wallet, predicate, amountToPredicate); + await fundAccount(wallet, predicate, amountToPredicate); const receiver = Wallet.generate({ provider }); diff --git a/packages/fuel-gauge/src/predicate/predicate-invalidations.test.ts b/packages/fuel-gauge/src/predicate/predicate-invalidations.test.ts index a1fb59388e0..ca812be9fee 100644 --- a/packages/fuel-gauge/src/predicate/predicate-invalidations.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-invalidations.test.ts @@ -4,7 +4,7 @@ import { expectToThrowFuelError, launchTestNode } from 'fuels/test-utils'; import { PredicateMainArgsStruct } from '../../test/typegen'; import type { Validation } from '../types/predicate'; -import { fundPredicate } from './utils/predicate'; +import { fundAccount } from './utils/predicate'; /** * @group node @@ -25,7 +25,7 @@ describe('Predicate', () => { provider, }); - await fundPredicate(wallet, predicate, 1000); + await fundAccount(wallet, predicate, 1000); const receiver = Wallet.generate({ provider }); @@ -59,7 +59,7 @@ describe('Predicate', () => { provider, }); - await fundPredicate(wallet, predicate, 1000); + await fundAccount(wallet, predicate, 1000); const receiver = Wallet.generate({ provider }); diff --git a/packages/fuel-gauge/src/predicate/predicate-populate-witness.test.ts b/packages/fuel-gauge/src/predicate/predicate-populate-witness.test.ts index 827ab20aa8d..162d5c4f67d 100644 --- a/packages/fuel-gauge/src/predicate/predicate-populate-witness.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-populate-witness.test.ts @@ -4,7 +4,7 @@ import { launchTestNode } from 'fuels/test-utils'; import { PredicateAssertNumber, PredicateAssertValue } from '../../test/typegen'; -import { fundPredicate } from './utils/predicate'; +import { fundAccount } from './utils/predicate'; /** * @group node @@ -46,7 +46,7 @@ describe('Predicate', () => { data: [11], }); - await fundPredicate(wallet, predicateAssertNumber, 500_000); + await fundAccount(wallet, predicateAssertNumber, 500_000); let transactionRequest = new ScriptTransactionRequest(); const receiver = Wallet.generate({ provider }); @@ -101,7 +101,7 @@ describe('Predicate', () => { data: [11], }); - await fundPredicate(fundingWallet, predicateAssertNumber, 500_000); + await fundAccount(fundingWallet, predicateAssertNumber, 500_000); const resources1 = await wallet1.getResourcesToSpend(quantity); const predicateAssertNumberWrongResources = await provider.getResourcesToSpend( @@ -156,7 +156,7 @@ describe('Predicate', () => { data: [11], }); - await fundPredicate(fundingWallet, predicateAssertNumber, 500_000, UTXOS_AMOUNT); + await fundAccount(fundingWallet, predicateAssertNumber, 500_000, UTXOS_AMOUNT); const receiver = Wallet.generate({ provider }); @@ -234,7 +234,7 @@ describe('Predicate', () => { data: [11], }); - await fundPredicate(fundingWallet, predicateAssertNumber, 500_000, UTXOS_AMOUNT); + await fundAccount(fundingWallet, predicateAssertNumber, 500_000, UTXOS_AMOUNT); const predicateAssertValue = new Predicate<[boolean]>({ abi: PredicateAssertValue.abi, @@ -243,7 +243,7 @@ describe('Predicate', () => { data: [true], }); - await fundPredicate(fundingWallet, predicateAssertValue, 500_000, UTXOS_AMOUNT); + await fundAccount(fundingWallet, predicateAssertValue, 500_000, UTXOS_AMOUNT); // predicate resources fetched as non predicate resources const predicateAssertNumberWrongResources = await provider.getResourcesToSpend( @@ -325,7 +325,7 @@ describe('Predicate', () => { data: [11], }); - await fundPredicate(fundingWallet, predicateAssertNumber, 500_000, UTXOS_AMOUNT); + await fundAccount(fundingWallet, predicateAssertNumber, 500_000, UTXOS_AMOUNT); const predicateAssertValue = new Predicate<[boolean]>({ abi: PredicateAssertValue.abi, @@ -334,7 +334,7 @@ describe('Predicate', () => { data: [true], }); - await fundPredicate(fundingWallet, predicateAssertValue, 500_000, UTXOS_AMOUNT); + await fundAccount(fundingWallet, predicateAssertValue, 500_000, UTXOS_AMOUNT); const resources1 = await wallet1.getResourcesToSpend(quantity); const resources2 = await wallet2.getResourcesToSpend(quantity); @@ -411,7 +411,7 @@ describe('Predicate', () => { data: [11], }); - await fundPredicate(fundingWallet, predicateAssertNumber, 500_000, UTXOS_AMOUNT); + await fundAccount(fundingWallet, predicateAssertNumber, 500_000, UTXOS_AMOUNT); const predicateAssertNumberWrongResources = await provider.getResourcesToSpend( predicateAssertNumber.address, @@ -429,7 +429,7 @@ describe('Predicate', () => { data: [true], }); - await fundPredicate(fundingWallet, predicateAssertValue, 500_000, UTXOS_AMOUNT); + await fundAccount(fundingWallet, predicateAssertValue, 500_000, UTXOS_AMOUNT); const predicateAssertValueWrongResources = await provider.getResourcesToSpend( predicateAssertValue.address, diff --git a/packages/fuel-gauge/src/predicate/predicate-with-contract.test.ts b/packages/fuel-gauge/src/predicate/predicate-with-contract.test.ts index 89cc08ed1d9..ff9976d3477 100644 --- a/packages/fuel-gauge/src/predicate/predicate-with-contract.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-with-contract.test.ts @@ -4,7 +4,7 @@ import { expectToThrowFuelError, launchTestNode } from 'fuels/test-utils'; import { CallTestContractFactory, TokenContractFactory } from '../../test/typegen/contracts'; import { PredicateMainArgsStruct, PredicateTrue } from '../../test/typegen/predicates'; -import { fundPredicate } from './utils/predicate'; +import { fundAccount } from './utils/predicate'; /** * @group node @@ -28,7 +28,7 @@ describe('Predicate', () => { // Create a instance of the contract with the predicate as the caller Account const contractPredicate = new Contract(contract.id, contract.interface, predicate); - await fundPredicate(wallet, predicate, amountToPredicate); + await fundAccount(wallet, predicate, amountToPredicate); const { waitForResult } = await contractPredicate.functions .return_context_amount() @@ -81,7 +81,7 @@ describe('Predicate', () => { ], }); - await fundPredicate(wallet, predicate, amountToPredicate); + await fundAccount(wallet, predicate, amountToPredicate); // executing predicate to transfer resources to receiver const tx = await predicate.transfer( diff --git a/packages/fuel-gauge/src/predicate/predicate-with-script.test.ts b/packages/fuel-gauge/src/predicate/predicate-with-script.test.ts index 10b9e5d72a1..cd002879999 100644 --- a/packages/fuel-gauge/src/predicate/predicate-with-script.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-with-script.test.ts @@ -5,7 +5,7 @@ import { expectToThrowFuelError, launchTestNode } from 'fuels/test-utils'; import { PredicateMainArgsStruct, ScriptMainArgs } from '../../test/typegen'; import type { Validation } from '../types/predicate'; -import { fundPredicate } from './utils/predicate'; +import { fundAccount } from './utils/predicate'; /** * @group node @@ -56,7 +56,7 @@ describe('Predicate', () => { ], }); - await fundPredicate(wallet, predicate, amountToPredicate); + await fundAccount(wallet, predicate, amountToPredicate); // executing predicate to transfer resources to receiver const tx = await predicate.transfer( diff --git a/packages/fuel-gauge/src/predicate/utils/predicate/fundAccount.ts b/packages/fuel-gauge/src/predicate/utils/predicate/fundAccount.ts new file mode 100644 index 00000000000..26587ab0de7 --- /dev/null +++ b/packages/fuel-gauge/src/predicate/utils/predicate/fundAccount.ts @@ -0,0 +1,26 @@ +import type { BigNumberish, Account } from 'fuels'; +import { ScriptTransactionRequest, BN } from 'fuels'; + +export const fundAccount = async ( + fundedAccount: Account, + accountToBeFunded: Account, + amount: BigNumberish, + utxosAmount: number = 1 +): Promise => { + const baseAssetId = fundedAccount.provider.getBaseAssetId(); + const request = new ScriptTransactionRequest(); + + for (let i = 0; i < utxosAmount; i++) { + request.addCoinOutput(accountToBeFunded.address, new BN(amount).div(utxosAmount), baseAssetId); + } + + const txCost = await fundedAccount.getTransactionCost(request); + request.gasLimit = txCost.gasUsed; + request.maxFee = txCost.maxFee; + await fundedAccount.fund(request, txCost); + + const submit = await fundedAccount.sendTransaction(request); + await submit.waitForResult(); + + return accountToBeFunded.getBalance(); +}; diff --git a/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts b/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts deleted file mode 100644 index 8708a60e846..00000000000 --- a/packages/fuel-gauge/src/predicate/utils/predicate/fundPredicate.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { InputValue, BigNumberish, WalletUnlocked, Predicate } from 'fuels'; -import { ScriptTransactionRequest, BN } from 'fuels'; - -export const fundPredicate = async < - T extends InputValue[] = InputValue[], - C extends { [name: string]: unknown } | undefined = { [name: string]: unknown }, ->( - wallet: WalletUnlocked, - predicate: Predicate, - amountToPredicate: BigNumberish, - utxosAmount: number = 1 -): Promise => { - const baseAssetId = wallet.provider.getBaseAssetId(); - const request = new ScriptTransactionRequest(); - - for (let i = 0; i < utxosAmount; i++) { - request.addCoinOutput( - predicate.address, - new BN(amountToPredicate).div(utxosAmount), - baseAssetId - ); - } - - const txCost = await wallet.getTransactionCost(request); - request.gasLimit = txCost.gasUsed; - request.maxFee = txCost.maxFee; - await wallet.fund(request, txCost); - - const submit = await wallet.sendTransaction(request); - await submit.waitForResult(); - - return predicate.getBalance(); -}; diff --git a/packages/fuel-gauge/src/predicate/utils/predicate/index.ts b/packages/fuel-gauge/src/predicate/utils/predicate/index.ts index c538f8abb17..0c6b6db67e3 100644 --- a/packages/fuel-gauge/src/predicate/utils/predicate/index.ts +++ b/packages/fuel-gauge/src/predicate/utils/predicate/index.ts @@ -1,3 +1,3 @@ export * from './assertBalance'; export * from './assertBalances'; -export * from './fundPredicate'; +export * from './fundAccount'; From 81c8cdf638c986705064cd1fad39c3d8a7e01103 Mon Sep 17 00:00:00 2001 From: YaTut1901 Date: Fri, 13 Dec 2024 09:07:25 +0200 Subject: [PATCH 14/14] feat: added method to duplicate predicate --- .changeset/gentle-toes-play.md | 2 +- .../predicate/predicate-duplication.test.ts | 502 +++++++++--------- 2 files changed, 250 insertions(+), 254 deletions(-) diff --git a/.changeset/gentle-toes-play.md b/.changeset/gentle-toes-play.md index 0e50d5619c1..98b9a4d469b 100644 --- a/.changeset/gentle-toes-play.md +++ b/.changeset/gentle-toes-play.md @@ -2,4 +2,4 @@ "@fuel-ts/account": patch --- -chore: added static method to duplicate predicate +feat: added method to duplicate predicate diff --git a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts index 156e0cace83..54cec443091 100644 --- a/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-duplication.test.ts @@ -21,336 +21,332 @@ describe('Predicate.fromInstance', () => { ADDRESS: '0x38966262edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', }; - describe('Basic Instance Operations', () => { - it('creates new predicate instance from existing one with default values', async () => { - using launched = await launchTestNode(); + it('creates new predicate instance from existing one with default values', async () => { + using launched = await launchTestNode(); + + const provider = launched.provider; + const basePredicate = new PredicateWithConfigurable({ + provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, + }); - const provider = launched.provider; - const basePredicate = new PredicateWithConfigurable({ - provider, - data: [defaultValues.FEE, defaultValues.ADDRESS], - configurableConstants: defaultValues, - }); + const newPredicate: PredicateWithConfigurable = basePredicate.toNewInstance(); + + expect(newPredicate.predicateData).toEqual(basePredicate.predicateData); + expect(newPredicate.interface).toEqual(basePredicate.interface); + expect(newPredicate.provider).toEqual(basePredicate.provider); + expect(newPredicate.bytes).toEqual(basePredicate.bytes); + }); - const newPredicate: PredicateWithConfigurable = basePredicate.toNewInstance(); + it('creates new predicate instance with custom data', async () => { + using launched = await launchTestNode(); - expect(newPredicate.predicateData).toEqual(basePredicate.predicateData); - expect(newPredicate.interface).toEqual(basePredicate.interface); - expect(newPredicate.provider).toEqual(basePredicate.provider); - expect(newPredicate.bytes).toEqual(basePredicate.bytes); + const provider = launched.provider; + const basePredicate = new PredicateWithConfigurable({ + provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, }); - it('creates new predicate instance with custom data', async () => { - using launched = await launchTestNode(); + const data: PredicateWithConfigurableInputs = [ + 13, + '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + ]; + const newPredicate: PredicateWithConfigurable = basePredicate.toNewInstance({ data }); + + expect(newPredicate.predicateData).toEqual(data); + expect(newPredicate.interface).toEqual(basePredicate.interface); + expect(newPredicate.provider).toEqual(basePredicate.provider); + expect(newPredicate.bytes).toEqual(basePredicate.bytes); + expect(newPredicate.predicateData).not.toEqual(basePredicate.predicateData); + }); - const provider = launched.provider; - const basePredicate = new PredicateWithConfigurable({ - provider, - data: [defaultValues.FEE, defaultValues.ADDRESS], - configurableConstants: defaultValues, - }); - - const data: PredicateWithConfigurableInputs = [ - 13, - '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', - ]; - const newPredicate: PredicateWithConfigurable = basePredicate.toNewInstance({ data }); - - expect(newPredicate.predicateData).toEqual(data); - expect(newPredicate.interface).toEqual(basePredicate.interface); - expect(newPredicate.provider).toEqual(basePredicate.provider); - expect(newPredicate.bytes).toEqual(basePredicate.bytes); - expect(newPredicate.predicateData).not.toEqual(basePredicate.predicateData); + it('creates new predicate instance with configurable constants', async () => { + using launched = await launchTestNode(); + + const provider = launched.provider; + const basePredicate = new PredicateWithConfigurable({ + provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, }); - it('creates new predicate instance with configurable constants', async () => { - using launched = await launchTestNode(); + const configurableConstants: PredicateWithConfigurableConfigurables = { + FEE: 13, + ADDRESS: '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + }; + const newPredicate: PredicateWithConfigurable = basePredicate.toNewInstance({ + configurableConstants, + }); - const provider = launched.provider; - const basePredicate = new PredicateWithConfigurable({ + expect(newPredicate.predicateData).toEqual(basePredicate.predicateData); + expect(newPredicate.interface).toEqual(basePredicate.interface); + expect(newPredicate.provider).toEqual(basePredicate.provider); + expect(newPredicate.bytes).toEqual( + new PredicateWithConfigurable({ provider, data: [defaultValues.FEE, defaultValues.ADDRESS], - configurableConstants: defaultValues, - }); - - const configurableConstants: PredicateWithConfigurableConfigurables = { - FEE: 13, - ADDRESS: '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', - }; - const newPredicate: PredicateWithConfigurable = basePredicate.toNewInstance({ configurableConstants, - }); - - expect(newPredicate.predicateData).toEqual(basePredicate.predicateData); - expect(newPredicate.interface).toEqual(basePredicate.interface); - expect(newPredicate.provider).toEqual(basePredicate.provider); - expect(newPredicate.bytes).toEqual( - new PredicateWithConfigurable({ - provider, - data: [defaultValues.FEE, defaultValues.ADDRESS], - configurableConstants, - }).bytes - ); + }).bytes + ); + }); + + it('supports chaining withData and withConfigurableConstants', async () => { + using launched = await launchTestNode(); + + const provider = launched.provider; + const basePredicate = new PredicateWithConfigurable({ + provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, }); - it('supports chaining withData and withConfigurableConstants', async () => { - using launched = await launchTestNode(); + const data: PredicateWithConfigurableInputs = [ + 13, + '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + ]; + const configurableConstants: PredicateWithConfigurableConfigurables = { + FEE: 13, + ADDRESS: '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + }; + const newPredicate: PredicateWithConfigurable = basePredicate.toNewInstance({ + data, + configurableConstants, + }); - const provider = launched.provider; - const basePredicate = new PredicateWithConfigurable({ + expect(newPredicate.predicateData).toEqual(data); + expect(newPredicate.interface).toEqual(basePredicate.interface); + expect(newPredicate.provider).toEqual(basePredicate.provider); + expect(newPredicate.bytes).toEqual( + new PredicateWithConfigurable({ provider, - data: [defaultValues.FEE, defaultValues.ADDRESS], - configurableConstants: defaultValues, - }); - - const data: PredicateWithConfigurableInputs = [ - 13, - '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', - ]; - const configurableConstants: PredicateWithConfigurableConfigurables = { - FEE: 13, - ADDRESS: '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', - }; - const newPredicate: PredicateWithConfigurable = basePredicate.toNewInstance({ data, configurableConstants, - }); - - expect(newPredicate.predicateData).toEqual(data); - expect(newPredicate.interface).toEqual(basePredicate.interface); - expect(newPredicate.provider).toEqual(basePredicate.provider); - expect(newPredicate.bytes).toEqual( - new PredicateWithConfigurable({ - provider, - data, - configurableConstants, - }).bytes - ); + }).bytes + ); + }); + + it('can create multiple different instances from same source, same bytecode', async () => { + using launched = await launchTestNode(); + + const provider = launched.provider; + const basePredicate = new PredicateWithConfigurable({ + provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, }); - it('can create multiple different instances from same source, same bytecode', async () => { - using launched = await launchTestNode(); + const newPredicate1 = basePredicate.toNewInstance(); + const newPredicate2 = basePredicate.toNewInstance(); - const provider = launched.provider; - const basePredicate = new PredicateWithConfigurable({ - provider, - data: [defaultValues.FEE, defaultValues.ADDRESS], - configurableConstants: defaultValues, - }); + expect(newPredicate1.bytes).toEqual(newPredicate2.bytes); + }); - const newPredicate1 = basePredicate.toNewInstance(); - const newPredicate2 = basePredicate.toNewInstance(); + it('can create multiple different instances from same source, different bytecode', async () => { + using launched = await launchTestNode(); - expect(newPredicate1.bytes).toEqual(newPredicate2.bytes); + const provider = launched.provider; + const basePredicate = new PredicateWithConfigurable({ + provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, }); - it('can create multiple different instances from same source, different bytecode', async () => { - using launched = await launchTestNode(); + const configurableConstants: PredicateWithConfigurableConfigurables = { + FEE: 13, + ADDRESS: '0x38966262edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + }; + const newPredicate1 = basePredicate.toNewInstance(); + const newPredicate2 = basePredicate.toNewInstance({ configurableConstants }); - const provider = launched.provider; - const basePredicate = new PredicateWithConfigurable({ - provider, - data: [defaultValues.FEE, defaultValues.ADDRESS], - configurableConstants: defaultValues, - }); + expect(newPredicate1.bytes).not.toEqual(newPredicate2.bytes); + }); - const configurableConstants: PredicateWithConfigurableConfigurables = { - FEE: 13, - ADDRESS: '0x38966262edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', - }; - const newPredicate1 = basePredicate.toNewInstance(); - const newPredicate2 = basePredicate.toNewInstance({ configurableConstants }); + it('does not modify original instance', async () => { + using launched = await launchTestNode(); - expect(newPredicate1.bytes).not.toEqual(newPredicate2.bytes); + const provider = launched.provider; + const basePredicate = new PredicateWithConfigurable({ + provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, }); - it('does not modify original instance', async () => { - using launched = await launchTestNode(); + const bytes = basePredicate.bytes; + const newPredicate = basePredicate.toNewInstance(); - const provider = launched.provider; - const basePredicate = new PredicateWithConfigurable({ - provider, - data: [defaultValues.FEE, defaultValues.ADDRESS], - configurableConstants: defaultValues, - }); + expect(newPredicate.bytes).toEqual(bytes); + }); + + it('can transfer funds using duplicated predicate with same data and configurable constants', async () => { + using launched = await launchTestNode(); - const bytes = basePredicate.bytes; - const newPredicate = basePredicate.toNewInstance(); + const { + provider, + wallets: [wallet], + } = launched; - expect(newPredicate.bytes).toEqual(bytes); + const basePredicate = new PredicateWithConfigurable({ + provider: wallet.provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, }); - }); - describe('End-to-End Scenarios', () => { - it('can transfer funds using duplicated predicate with same data and configurable constants', async () => { - using launched = await launchTestNode(); + const predicate = basePredicate.toNewInstance(); - const { - provider, - wallets: [wallet], - } = launched; + const amountToTransfer = 200; - const basePredicate = new PredicateWithConfigurable({ - provider: wallet.provider, - data: [defaultValues.FEE, defaultValues.ADDRESS], - configurableConstants: defaultValues, - }); + await fundAccount(wallet, predicate, amountToPredicate); - const predicate = basePredicate.toNewInstance(); + const destination = WalletUnlocked.generate({ + provider: wallet.provider, + }); - const amountToTransfer = 200; + await assertBalance(destination, 0, provider.getBaseAssetId()); - await fundAccount(wallet, predicate, amountToPredicate); + const tx = await predicate.transfer( + destination.address, + amountToTransfer, + provider.getBaseAssetId(), + { + gasLimit: 1000, + } + ); - const destination = WalletUnlocked.generate({ - provider: wallet.provider, - }); + await tx.waitForResult(); - await assertBalance(destination, 0, provider.getBaseAssetId()); + await assertBalance(destination, amountToTransfer, provider.getBaseAssetId()); + }); - const tx = await predicate.transfer( - destination.address, - amountToTransfer, - provider.getBaseAssetId(), - { - gasLimit: 1000, - } - ); + it('can transfer funds using duplicated predicate with different data and same configurable constants', async () => { + using launched = await launchTestNode(); - await tx.waitForResult(); + const { + provider, + wallets: [wallet], + } = launched; - await assertBalance(destination, amountToTransfer, provider.getBaseAssetId()); + const basePredicate = new PredicateWithConfigurable({ + provider: wallet.provider, + data: [13, '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96'], + configurableConstants: defaultValues, }); - it('can transfer funds using duplicated predicate with different data and same configurable constants', async () => { - using launched = await launchTestNode(); + const predicate = basePredicate.toNewInstance({ + data: [defaultValues.FEE, defaultValues.ADDRESS], + }); - const { - provider, - wallets: [wallet], - } = launched; + const amountToTransfer = 200; - const basePredicate = new PredicateWithConfigurable({ - provider: wallet.provider, - data: [13, '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96'], - configurableConstants: defaultValues, - }); + await fundAccount(wallet, predicate, amountToPredicate); - const predicate = basePredicate.toNewInstance({ - data: [defaultValues.FEE, defaultValues.ADDRESS], - }); + const destination = WalletUnlocked.generate({ + provider: wallet.provider, + }); - const amountToTransfer = 200; + await assertBalance(destination, 0, provider.getBaseAssetId()); - await fundAccount(wallet, predicate, amountToPredicate); + const tx = await predicate.transfer( + destination.address, + amountToTransfer, + provider.getBaseAssetId(), + { + gasLimit: 1000, + } + ); - const destination = WalletUnlocked.generate({ - provider: wallet.provider, - }); + await tx.waitForResult(); - await assertBalance(destination, 0, provider.getBaseAssetId()); + await assertBalance(destination, amountToTransfer, provider.getBaseAssetId()); + }); - const tx = await predicate.transfer( - destination.address, - amountToTransfer, - provider.getBaseAssetId(), - { - gasLimit: 1000, - } - ); + it('can transfer funds using duplicated predicate with same data and different configurable constants', async () => { + using launched = await launchTestNode(); - await tx.waitForResult(); + const { + provider, + wallets: [wallet], + } = launched; - await assertBalance(destination, amountToTransfer, provider.getBaseAssetId()); + const basePredicate = new PredicateWithConfigurable({ + provider: wallet.provider, + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: { + FEE: 13, + ADDRESS: '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + }, }); - it('can transfer funds using duplicated predicate with same data and different configurable constants', async () => { - using launched = await launchTestNode(); + const predicate = basePredicate.toNewInstance({ configurableConstants: defaultValues }); - const { - provider, - wallets: [wallet], - } = launched; + const amountToTransfer = 200; - const basePredicate = new PredicateWithConfigurable({ - provider: wallet.provider, - data: [defaultValues.FEE, defaultValues.ADDRESS], - configurableConstants: { - FEE: 13, - ADDRESS: '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', - }, - }); + await fundAccount(wallet, predicate, amountToPredicate); - const predicate = basePredicate.toNewInstance({ configurableConstants: defaultValues }); + const destination = WalletUnlocked.generate({ + provider: wallet.provider, + }); - const amountToTransfer = 200; + await assertBalance(destination, 0, provider.getBaseAssetId()); - await fundAccount(wallet, predicate, amountToPredicate); + const tx = await predicate.transfer( + destination.address, + amountToTransfer, + provider.getBaseAssetId(), + { + gasLimit: 1000, + } + ); - const destination = WalletUnlocked.generate({ - provider: wallet.provider, - }); + await tx.waitForResult(); - await assertBalance(destination, 0, provider.getBaseAssetId()); + await assertBalance(destination, amountToTransfer, provider.getBaseAssetId()); + }); - const tx = await predicate.transfer( - destination.address, - amountToTransfer, - provider.getBaseAssetId(), - { - gasLimit: 1000, - } - ); + it('can transfer funds using duplicated predicate with different data and configurable constants', async () => { + using launched = await launchTestNode(); - await tx.waitForResult(); + const { + provider, + wallets: [wallet], + } = launched; - await assertBalance(destination, amountToTransfer, provider.getBaseAssetId()); + const basePredicate = new PredicateWithConfigurable({ + provider: wallet.provider, + data: [13, '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96'], + configurableConstants: { + FEE: 15, + ADDRESS: '0x38966262edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', + }, }); - it('can transfer funds using duplicated predicate with different data and configurable constants', async () => { - using launched = await launchTestNode(); - - const { - provider, - wallets: [wallet], - } = launched; - - const basePredicate = new PredicateWithConfigurable({ - provider: wallet.provider, - data: [13, '0x48966232edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96'], - configurableConstants: { - FEE: 15, - ADDRESS: '0x38966262edb5997574be45f94c665aedb41a1663f5b0528e765f355086eebf96', - }, - }); - - const predicate = basePredicate.toNewInstance({ - data: [defaultValues.FEE, defaultValues.ADDRESS], - configurableConstants: defaultValues, - }); + const predicate = basePredicate.toNewInstance({ + data: [defaultValues.FEE, defaultValues.ADDRESS], + configurableConstants: defaultValues, + }); - const amountToTransfer = 200; + const amountToTransfer = 200; - await fundAccount(wallet, predicate, amountToPredicate); + await fundAccount(wallet, predicate, amountToPredicate); - const destination = WalletUnlocked.generate({ - provider: wallet.provider, - }); + const destination = WalletUnlocked.generate({ + provider: wallet.provider, + }); - await assertBalance(destination, 0, provider.getBaseAssetId()); + await assertBalance(destination, 0, provider.getBaseAssetId()); - const tx = await predicate.transfer( - destination.address, - amountToTransfer, - provider.getBaseAssetId(), - { - gasLimit: 1000, - } - ); + const tx = await predicate.transfer( + destination.address, + amountToTransfer, + provider.getBaseAssetId(), + { + gasLimit: 1000, + } + ); - await tx.waitForResult(); + await tx.waitForResult(); - await assertBalance(destination, amountToTransfer, provider.getBaseAssetId()); - }); + await assertBalance(destination, amountToTransfer, provider.getBaseAssetId()); }); });