diff --git a/.changeset/cold-bikes-count.md b/.changeset/cold-bikes-count.md new file mode 100644 index 00000000000..1ae6fcdec71 --- /dev/null +++ b/.changeset/cold-bikes-count.md @@ -0,0 +1,4 @@ +--- +--- + +docs: migrated `predicate` docs snippets diff --git a/apps/docs-snippets/src/guide/predicates/deploying-predicates.test.ts b/apps/docs-snippets/src/guide/predicates/deploying-predicates.test.ts deleted file mode 100644 index 8e5cc8755cd..00000000000 --- a/apps/docs-snippets/src/guide/predicates/deploying-predicates.test.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { ContractFactory, Provider, Wallet, hexlify } from 'fuels'; -import { launchTestNode } from 'fuels/test-utils'; - -import { - ConfigurablePin as TypegenPredicate, - ConfigurablePinLoader as TypegenPredicateLoader, -} from '../../../test/typegen'; - -/** - * @group browser - * @group node - */ -describe('Deploying Predicates', () => { - it('deploys a predicate via loader and calls', async () => { - using launched = await launchTestNode(); - - const { - provider: testProvider, - wallets: [testWallet, receiver], - } = launched; - - const recieverInitialBalance = await receiver.getBalance(); - - const providerUrl = testProvider.url; - const WALLET_PVT_KEY = hexlify(testWallet.privateKey); - - const factory = new ContractFactory( - TypegenPredicate.bytecode, - TypegenPredicate.abi, - testWallet - ); - const { waitForResult: waitForDeploy } = await factory.deployAsBlobTxForScript(); - await waitForDeploy(); - - // #region deploying-predicates - // #import { Provider, Wallet }; - // #context import { WALLET_PVT_KEY } from 'path/to/my/env/file'; - // #context import { TypegenPredicateLoader } from 'path/to/typegen/outputs'; - - const provider = await Provider.create(providerUrl); - const wallet = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); - const baseAssetId = provider.getBaseAssetId(); - - // First, we will need to instantiate the script via it's loader bytecode. - // This can be imported from the typegen outputs that were created on `fuels deploy`. - // Then we can use the predicate as we would normally, such as overriding the configurables. - const predicate = new TypegenPredicateLoader({ - data: [23], - provider, - configurableConstants: { - PIN: 23, - }, - }); - - // Now, let's fund the predicate - const fundTx = await wallet.transfer(predicate.address, 100_000, baseAssetId); - await fundTx.waitForResult(); - - // Then we'll execute the transfer and validate the predicate - const transferTx = await predicate.transfer(receiver.address, 1000, baseAssetId); - const { gasUsed } = await transferTx.waitForResult(); - // #endregion deploying-predicates - - const anotherPredicate = new TypegenPredicate({ - data: [23], - provider, - configurableConstants: { - PIN: 23, - }, - }); - - const anotherFundTx = await wallet.transfer(anotherPredicate.address, 100_000); - await anotherFundTx.waitForResult(); - - const anotherTransferTx = await anotherPredicate.transfer(receiver.address, 1000); - const { gasUsed: anotherGasUsed } = await anotherTransferTx.waitForResult(); - - expect(recieverInitialBalance.toNumber()).toBeLessThan( - (await receiver.getBalance()).toNumber() - ); - expect(gasUsed.toNumber()).toBeLessThanOrEqual(anotherGasUsed.toNumber()); - }); -}); diff --git a/apps/docs-snippets/src/guide/predicates/index.test.ts b/apps/docs-snippets/src/guide/predicates/index.test.ts deleted file mode 100644 index 42d137499a5..00000000000 --- a/apps/docs-snippets/src/guide/predicates/index.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { PredicateParams } from 'fuels'; -import { Predicate } from 'fuels'; -import { launchTestNode } from 'fuels/test-utils'; - -import { - DocSnippetProjectsEnum, - getDocsSnippetsForcProject, -} from '../../../test/fixtures/forc-projects'; - -/** - * @group node - */ -describe(__filename, () => { - const { abiContents: jsonAbi, binHexlified: binary } = getDocsSnippetsForcProject( - DocSnippetProjectsEnum.RETURN_TRUE_PREDICATE - ); - - it('should successfully instantiate a predicate', async () => { - using launched = await launchTestNode(); - const { provider } = launched; - - // #region predicate-index-2 - // #import { Predicate, PredicateParams }; - const predicateParams: PredicateParams = { - bytecode: binary, - provider, - abi: jsonAbi, - }; - const predicate = new Predicate(predicateParams); - // #endregion predicate-index-2 - - expect(predicate).toBeTruthy(); - }); -}); diff --git a/apps/docs-snippets/src/guide/predicates/interacting-with-predicates.test.ts b/apps/docs-snippets/src/guide/predicates/interacting-with-predicates.test.ts deleted file mode 100644 index a67d92b7a2a..00000000000 --- a/apps/docs-snippets/src/guide/predicates/interacting-with-predicates.test.ts +++ /dev/null @@ -1,160 +0,0 @@ -import type { BytesLike, JsonAbi, Provider, WalletUnlocked } from 'fuels'; -import { ScriptTransactionRequest, bn, Predicate, BN, Wallet } from 'fuels'; -import { launchTestNode } from 'fuels/test-utils'; - -import { SimplePredicate } from '../../../test/typegen'; - -/** - * @group node - * @group browser - */ -describe('Interacting with Predicates', () => { - const inputAddress = '0xfc05c23a8f7f66222377170ddcbfea9c543dff0dd2d2ba4d0478a4521423a9d4'; - - async function createAndFundPredicate( - provider: Provider, - fundedWallet: WalletUnlocked, - inputData: [string], - abi: JsonAbi, - bytecode: BytesLike, - configurableConstants?: Record - ): Promise> { - const predicate = new Predicate({ - bytecode, - provider, - abi, - data: [inputAddress], - configurableConstants, - }); - - const tx1 = await fundedWallet.transfer( - predicate.address, - 100_000_000, - provider.getBaseAssetId() - ); - await tx1.waitForResult(); - return predicate; - } - - it('should get predicate resources and add them to the predicate data', async () => { - using launched = await launchTestNode(); - const { - provider, - wallets: [fundedWallet], - } = launched; - - const predicate = await createAndFundPredicate( - provider, - fundedWallet, - [inputAddress], - SimplePredicate.abi, - SimplePredicate.bytecode - ); - - // #region interacting-with-predicates-1 - - // Instantiate the transaction request - const transactionRequest = new ScriptTransactionRequest({ - gasLimit: 2000, - maxFee: bn(0), - }); - - const predicateCoins = await predicate.getResourcesToSpend([ - { amount: 2000, assetId: provider.getBaseAssetId() }, - ]); - - // Add the predicate input and resources - transactionRequest.addResources(predicateCoins); - // #endregion interacting-with-predicates-1 - - expect(transactionRequest.inputs.length).toBeGreaterThanOrEqual(1); - expect(transactionRequest.outputs.length).toEqual(1); - }); - - it('should successfully transfer funds to the predicate', async () => { - using launched = await launchTestNode(); - const { - provider, - wallets: [fundedWallet], - } = launched; - - const predicate = await createAndFundPredicate( - provider, - fundedWallet, - [inputAddress], - SimplePredicate.abi, - SimplePredicate.bytecode - ); - - const receiver = Wallet.generate({ provider }); - - const transactionRequest = new ScriptTransactionRequest({ gasLimit: 2000, maxFee: bn(0) }); - transactionRequest.addCoinOutput(receiver.address, 100, provider.getBaseAssetId()); - - const txCost = await predicate.getTransactionCost(transactionRequest); - - transactionRequest.gasLimit = txCost.gasUsed; - transactionRequest.maxFee = txCost.maxFee; - - await predicate.fund(transactionRequest, txCost); - - // #region interacting-with-predicates-2 - - const result = await predicate.sendTransaction(transactionRequest); - - await result.waitForResult(); - // #endregion interacting-with-predicates-2 - - const { isStatusSuccess } = await result.waitForResult(); - - expect(isStatusSuccess).toBeTruthy(); - }); - - it('should successfully simulate a transaction with predicate', async () => { - using launched = await launchTestNode(); - const { - provider, - wallets: [fundedWallet], - } = launched; - - const predicate = await createAndFundPredicate( - provider, - fundedWallet, - [inputAddress], - SimplePredicate.abi, - SimplePredicate.bytecode - ); - - const receiver = Wallet.generate({ provider }); - - // #region interacting-with-predicates-3 - const transactionRequest = new ScriptTransactionRequest({ gasLimit: 2000, maxFee: bn(0) }); - transactionRequest.addCoinOutput(receiver.address, 1000000, provider.getBaseAssetId()); - - const txCost = await predicate.getTransactionCost(transactionRequest); - - transactionRequest.gasLimit = txCost.gasUsed; - transactionRequest.maxFee = txCost.maxFee; - - await predicate.fund(transactionRequest, txCost); - - const result = await predicate.simulateTransaction(transactionRequest); - - // #endregion interacting-with-predicates-3 - - expect(result.receipts).toEqual([ - { - type: 1, - id: expect.any(String), - val: expect.any(BN), - pc: expect.any(BN), - is: expect.any(BN), - }, - { - type: 9, - gasUsed: expect.any(BN), - result: expect.any(BN), - }, - ]); - }); -}); diff --git a/apps/docs-snippets/src/guide/predicates/predicate-custom-transactions.test.ts b/apps/docs-snippets/src/guide/predicates/predicate-custom-transactions.test.ts deleted file mode 100644 index e6727d1bde6..00000000000 --- a/apps/docs-snippets/src/guide/predicates/predicate-custom-transactions.test.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { Provider, ScriptTransactionRequest, Wallet } from 'fuels'; -import { launchTestNode } from 'fuels/test-utils'; - -import { ConfigurablePin as PredicateFactory } from '../../../test/typegen'; -import type { ConfigurablePinInputs as PredicateInputs } from '../../../test/typegen/predicates/ConfigurablePin'; - -/** - * @group node - * @group browser - */ -describe('Predicate Custom Transactions', () => { - it('uses a predicate in a custom transaction', async () => { - using launched = await launchTestNode(); - const { - wallets: [testSender, testReceiver], - provider: testProvider, - } = launched; - - const SENDER_PVT_KEY = testSender.privateKey; - const RECEIVER_ADDRESS = testReceiver.address; - - const providerUrl = testProvider.url; - - const initialRecieverBalance = await testReceiver.getBalance(testProvider.getBaseAssetId()); - - // #region predicate-custom-transaction - // #import { Provider, ScriptTransactionRequest, Wallet }; - // #context import { PredicateFactory } from 'path/to/typegen/outputs'; - // #context import type { PredicateInputs } from 'path/to/typegen/outputs'; - // #context import { SENDER_PVT_KEY, RECEIVER_ADDRESS } from 'path/to/my/env/file'; - - // Setup - const provider = await Provider.create(providerUrl); - const sender = Wallet.fromPrivateKey(SENDER_PVT_KEY, provider); - const receiver = Wallet.fromAddress(RECEIVER_ADDRESS, provider); - const assetId = provider.getBaseAssetId(); - const amountToFundPredicate = 300_000; - const amountToReceiver = 100_000; - - // Instantiate the predicate using valid predicate data, aka the pin we need - // to send the funds to the receiver - const data: PredicateInputs = [1337]; - const predicate = new PredicateFactory({ provider, data }); - - // Fund the predicate, so that we can send these funds via predicate logic - // to the receiver - const fundPredicateTx = await sender.transfer( - predicate.address, - amountToFundPredicate, - assetId - ); - await fundPredicateTx.waitForResult(); - const initialPredicateBalance = await predicate.getBalance(assetId); - - // Instantiate the script request - const customRequest = new ScriptTransactionRequest(); - - // Get the predicate resources that we would like to transfer - const predicateResources = await predicate.getResourcesToSpend([ - { assetId, amount: amountToReceiver }, - ]); - - // Add the resources for the transfer of the asset to the receiver. The resources - // adds the required inputs, and the output is for the transfer to the receiver address - customRequest.addResources(predicateResources); - customRequest.addCoinOutput(receiver.address, amountToReceiver, assetId); - - // Estimate the transaction cost and fund accordingly - const txCost = await predicate.getTransactionCost(customRequest); - customRequest.gasLimit = txCost.gasUsed; - customRequest.maxFee = txCost.maxFee; - await predicate.fund(customRequest, txCost); - - // Submit the transaction and await it's result - const predicateTx = await predicate.sendTransaction(customRequest); - await predicateTx.waitForResult(); - // #endregion predicate-custom-transaction - - expect(initialPredicateBalance.toNumber()).toEqual(amountToFundPredicate); - const { isStatusSuccess } = await predicateTx.waitForResult(); - expect(isStatusSuccess).toBe(true); - const finalReceiverBalance = await receiver.getBalance(assetId); - expect(finalReceiverBalance.toNumber()).toEqual( - initialRecieverBalance.add(amountToReceiver).toNumber() - ); - }); -}); diff --git a/apps/docs-snippets/src/guide/predicates/predicate-with-configurable.test.ts b/apps/docs-snippets/src/guide/predicates/predicate-with-configurable.test.ts deleted file mode 100644 index d7e8d7d623e..00000000000 --- a/apps/docs-snippets/src/guide/predicates/predicate-with-configurable.test.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { WalletUnlocked, Predicate, BN, getRandomB256 } from 'fuels'; -import { launchTestNode } from 'fuels/test-utils'; - -import { WhitelistedAddressPredicate } from '../../../test/typegen'; - -/** - * @group node - * @group browser - */ - -describe('Predicate With Configurables', () => { - it('should successfully transfer to setted whitelisted address', async () => { - using launched = await launchTestNode(); - const { - provider, - wallets: [wallet], - } = launched; - - // #region predicate-with-configurable-constants-2 - const newWhitelistedAddress = getRandomB256(); - - const configurable = { WHITELISTED: newWhitelistedAddress }; - // instantiate predicate with configurable constants - const predicate = new Predicate<[string]>({ - bytecode: WhitelistedAddressPredicate.bytecode, - provider: wallet.provider, - abi: WhitelistedAddressPredicate.abi, - data: [configurable.WHITELISTED], - configurableConstants: configurable, - }); - - // transferring funds to the predicate - const tx1 = await wallet.transfer(predicate.address, 200_000, provider.getBaseAssetId(), { - gasLimit: 1000, - }); - - await tx1.waitForResult(); - - const destinationWallet = WalletUnlocked.generate({ - provider: wallet.provider, - }); - - const amountToTransfer = 100; - - // transferring funds from the predicate to destination if predicate returns true - const tx2 = await predicate.transfer( - destinationWallet.address, - amountToTransfer, - provider.getBaseAssetId(), - { - gasLimit: 1000, - } - ); - - await tx2.waitForResult(); - // #endregion predicate-with-configurable-constants-2 - - const destinationBalance = await destinationWallet.getBalance(provider.getBaseAssetId()); - - expect(new BN(destinationBalance).toNumber()).toEqual(amountToTransfer); - }); - - it('should successfully transfer to default whitelisted address', async () => { - using launched = await launchTestNode(); - const { - provider, - wallets: [wallet], - } = launched; - - // #region predicate-with-configurable-constants-3 - const predicate = new Predicate({ - bytecode: WhitelistedAddressPredicate.bytecode, - provider, - abi: WhitelistedAddressPredicate.abi, - data: ['0xa703b26833939dabc41d3fcaefa00e62cee8e1ac46db37e0fa5d4c9fe30b4132'], - }); - - // transferring funds to the predicate - const tx1 = await wallet.transfer(predicate.address, 200_000, provider.getBaseAssetId(), { - gasLimit: 1000, - }); - - await tx1.waitForResult(); - - const destinationWallet = WalletUnlocked.generate({ - provider: wallet.provider, - }); - - const amountToTransfer = 100; - - // transferring funds from the predicate to destination if predicate returns true - const tx2 = await predicate.transfer( - destinationWallet.address, - amountToTransfer, - provider.getBaseAssetId(), - { - gasLimit: 1000, - } - ); - - await tx2.waitForResult(); - // #endregion predicate-with-configurable-constants-3 - - const destinationBalance = await destinationWallet.getBalance(provider.getBaseAssetId()); - - expect(new BN(destinationBalance).toNumber()).toEqual(amountToTransfer); - }); -}); diff --git a/apps/docs-snippets/src/guide/predicates/send-and-spend-funds-from-predicates.test.ts b/apps/docs-snippets/src/guide/predicates/send-and-spend-funds-from-predicates.test.ts index d6f9dbc64e2..53e6e4b3c00 100644 --- a/apps/docs-snippets/src/guide/predicates/send-and-spend-funds-from-predicates.test.ts +++ b/apps/docs-snippets/src/guide/predicates/send-and-spend-funds-from-predicates.test.ts @@ -195,6 +195,7 @@ describe('Send and Spend Funds from Predicates', () => { const amountToReceiver = 200; // #region send-and-spend-funds-from-predicates-8 + // Create the transaction for transferring funds from the predicate. const transactionRequest = await predicate.createTransfer( receiverWallet.address, amountToReceiver, @@ -204,74 +205,16 @@ describe('Send and Spend Funds from Predicates', () => { } ); - /* - You can retrieve the transaction ID before actually submitting it to the node - like this: - */ - + // We can obtain the transaction ID before submitting the transaction. const chainId = provider.getChainId(); - const txId = transactionRequest.getTransactionId(chainId); - - const res = await predicate.sendTransaction(transactionRequest); + const transactionId = transactionRequest.getTransactionId(chainId); - await res.waitForResult(); + // We can submit the transaction and wait for the result. + const response = await predicate.sendTransaction(transactionRequest); + await response.waitForResult(); // #endregion send-and-spend-funds-from-predicates-8 - const txIdFromExecutedTx = res.id; - - expect(txId).toEqual(txIdFromExecutedTx); - }); - - it('should be able to pre-stage a transaction, get TX ID, and then send the transaction', async () => { - using launched = await launchTestNode(); - const { - provider, - wallets: [walletWithFunds], - } = launched; - - const predicate = new Predicate({ - bytecode: SimplePredicate.bytecode, - abi: SimplePredicate.abi, - provider, - data: [inputAddress], - }); - - const amountToPredicate = 300_000; - - const tx = await walletWithFunds.transfer( - predicate.address, - amountToPredicate, - provider.getBaseAssetId(), - { - gasLimit: 1_000, - } - ); - - await tx.waitForResult(); - - const receiverWallet = WalletUnlocked.generate({ - provider, - }); - - const transferAmount = 1000; - - // #region predicates-prestage-transaction - // Prepare the transaction - const preparedTx = await predicate.createTransfer( - receiverWallet.address, - transferAmount, - provider.getBaseAssetId() - ); - - // Get the transaction ID before sending the transaction - const txId = preparedTx.getTransactionId(provider.getChainId()); - - // Send the transaction - const res = await predicate.sendTransaction(preparedTx); - await res.waitForResult(); - // #endregion predicates-prestage-transaction - - const txIdFromExecutedTx = res.id; + const txIdFromExecutedTx = response.id; - expect(txId).toEqual(txIdFromExecutedTx); + expect(transactionId).toEqual(txIdFromExecutedTx); }); }); diff --git a/apps/docs-snippets2/src/predicates/configurables/configurable-default.ts b/apps/docs-snippets2/src/predicates/configurables/configurable-default.ts new file mode 100644 index 00000000000..0d59866d4d5 --- /dev/null +++ b/apps/docs-snippets2/src/predicates/configurables/configurable-default.ts @@ -0,0 +1,52 @@ +// #region full +import { Wallet, Provider } from 'fuels'; + +import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../../env'; +import { WhitelistedAddressPredicate } from '../../typegend/predicates/WhitelistedAddressPredicate'; + +const provider = await Provider.create(LOCAL_NETWORK_URL); + +const sender = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); +const recipient = Wallet.generate({ provider }); + +// Instantiate predicate without configurable constants (will use the address defined in Sway) +const predicate = new WhitelistedAddressPredicate({ + provider, + data: ['0xa703b26833939dabc41d3fcaefa00e62cee8e1ac46db37e0fa5d4c9fe30b4132'], +}); + +// Transferring funds to the predicate +const tx1 = await sender.transfer( + predicate.address, + 200_000, + provider.getBaseAssetId(), + { + gasLimit: 1000, + } +); + +await tx1.waitForResult(); + +const amountToTransfer = 100; + +// Transferring funds from the predicate to destination if predicate returns true +const tx2 = await predicate.transfer( + recipient.address, + amountToTransfer, + provider.getBaseAssetId(), + { + gasLimit: 1000, + } +); + +await tx2.waitForResult(); +// #endregion full + +const destinationBalance = await recipient.getBalance( + provider.getBaseAssetId() +); + +console.log( + 'Destination balance should equal amount to transfer', + destinationBalance.eq(amountToTransfer) +); diff --git a/apps/docs-snippets2/src/predicates/configurables/configurable-set-data.ts b/apps/docs-snippets2/src/predicates/configurables/configurable-set-data.ts new file mode 100644 index 00000000000..61359f4809d --- /dev/null +++ b/apps/docs-snippets2/src/predicates/configurables/configurable-set-data.ts @@ -0,0 +1,56 @@ +// #region full +import { Wallet, Provider } from 'fuels'; + +import { LOCAL_NETWORK_URL, WALLET_ADDRESS, WALLET_PVT_KEY_2 } from '../../env'; +import { WhitelistedAddressPredicate } from '../../typegend/predicates/WhitelistedAddressPredicate'; + +const provider = await Provider.create(LOCAL_NETWORK_URL); + +const whitelisted = Wallet.fromAddress(WALLET_ADDRESS, provider); +const sender = Wallet.fromPrivateKey(WALLET_PVT_KEY_2, provider); +const recipient = Wallet.generate({ provider }); + +const configurable = { WHITELISTED: whitelisted.address.toB256() }; + +// Instantiate predicate with configurable constants +const predicate = new WhitelistedAddressPredicate({ + provider, + data: [configurable.WHITELISTED], + configurableConstants: configurable, +}); + +// Transferring funds to the predicate +const tx1 = await sender.transfer( + predicate.address, + 200_000, + provider.getBaseAssetId(), + { + gasLimit: 1000, + } +); + +await tx1.waitForResult(); + +const amountToTransfer = 100; + +// Transferring funds from the predicate to destination if predicate returns true +const tx2 = await predicate.transfer( + recipient.address, + amountToTransfer, + provider.getBaseAssetId(), + { + gasLimit: 1000, + } +); + +await tx2.waitForResult(); +// #endregion full + +const destinationBalance = await recipient.getBalance( + provider.getBaseAssetId() +); + +console.log( + 'Destination balance should equal amount to transfer', + destinationBalance.eq(amountToTransfer) +); diff --git a/apps/docs-snippets2/src/predicates/cookbook/failure-not-enough-funds.ts b/apps/docs-snippets2/src/predicates/cookbook/failure-not-enough-funds.ts new file mode 100644 index 00000000000..35bc6136a7b --- /dev/null +++ b/apps/docs-snippets2/src/predicates/cookbook/failure-not-enough-funds.ts @@ -0,0 +1,35 @@ +import { Provider, Wallet } from 'fuels'; +import { safeExec } from 'fuels/test-utils'; + +import { LOCAL_NETWORK_URL } from '../../env'; +import { SimplePredicate } from '../../typegend'; + +const provider = await Provider.create(LOCAL_NETWORK_URL); +const receiver = Wallet.generate({ provider }); + +const inputAddress = + '0xfc05c23a8f7f66222377170ddcbfea9c543dff0dd2d2ba4d0478a4521423a9d4'; +const predicate = new SimplePredicate({ + provider, + data: [inputAddress], +}); + +// Any amount coins will fail as the predicate is unfunded +const amountOfCoinsToFail = 1000; +const { error } = await safeExec(async () => + predicate.transfer( + receiver.address, + amountOfCoinsToFail, + provider.getBaseAssetId() + ) +); + +// #region send-and-spend-funds-from-predicates-6 +const errorMessage = `The account(s) sending the transaction don't have enough funds to cover the transaction.`; +// #endregion send-and-spend-funds-from-predicates-6 + +const actualErrorMessage = (error).message; +console.log( + 'Error message should match expected', + actualErrorMessage === errorMessage +); diff --git a/apps/docs-snippets2/src/predicates/cookbook/failure-returns-false.ts b/apps/docs-snippets2/src/predicates/cookbook/failure-returns-false.ts new file mode 100644 index 00000000000..63a3a8f58bd --- /dev/null +++ b/apps/docs-snippets2/src/predicates/cookbook/failure-returns-false.ts @@ -0,0 +1,42 @@ +import { getRandomB256, Provider, Wallet } from 'fuels'; +import { safeExec } from 'fuels/test-utils'; + +import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../../env'; +import { SimplePredicate } from '../../typegend'; + +const provider = await Provider.create(LOCAL_NETWORK_URL); +const sender = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); +const receiver = Wallet.generate({ provider }); + +const inputAddress = getRandomB256(); +const predicate = new SimplePredicate({ + provider, + data: [inputAddress], +}); + +const amountToPredicate = 10_000_000; +const tx = await sender.transfer( + predicate.address, + amountToPredicate, + provider.getBaseAssetId(), + { + gasLimit: 1_000, + } +); +const { isStatusSuccess } = await tx.waitForResult(); +console.log('Transfer to predicate should be successful', isStatusSuccess); + +const amountOfCoins = 100; +const { error } = await safeExec(async () => + predicate.transfer(receiver.address, amountOfCoins, provider.getBaseAssetId()) +); + +// #region send-and-spend-funds-from-predicates-7 +const errorMessage = `PredicateVerificationFailed`; +// #endregion send-and-spend-funds-from-predicates-7 + +const actualErrorMessage = (error).message; +console.log( + `Error message should match expected ${actualErrorMessage}`, + actualErrorMessage.includes(errorMessage) +); diff --git a/apps/docs-snippets2/src/predicates/cookbook/pre-stage.ts b/apps/docs-snippets2/src/predicates/cookbook/pre-stage.ts new file mode 100644 index 00000000000..55960c2223b --- /dev/null +++ b/apps/docs-snippets2/src/predicates/cookbook/pre-stage.ts @@ -0,0 +1,61 @@ +import { Provider, Wallet } from 'fuels'; + +import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../../env'; +import { SimplePredicate } from '../../typegend'; + +const provider = await Provider.create(LOCAL_NETWORK_URL); +const sender = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); +const receiver = Wallet.generate({ provider }); + +const inputAddress = + '0xfc05c23a8f7f66222377170ddcbfea9c543dff0dd2d2ba4d0478a4521423a9d4'; + +const predicate = new SimplePredicate({ + provider, + data: [inputAddress], +}); + +const amountToPredicate = 10_000_000; +const tx = await sender.transfer( + predicate.address, + amountToPredicate, + provider.getBaseAssetId(), + { + gasLimit: 1_000, + } +); +const { isStatusSuccess } = await tx.waitForResult(); +console.log('Transfer to predicate should be successful', isStatusSuccess); + +const amountToReceiver = 200; + +// #region send-and-spend-funds-from-predicates-8 +// Create the transaction for transferring funds from the predicate. +const transactionRequest = await predicate.createTransfer( + receiver.address, + amountToReceiver, + provider.getBaseAssetId(), + { + gasLimit: 1000, + } +); + +// We can obtain the transaction ID before submitting the transaction. +const chainId = provider.getChainId(); +const transactionId = transactionRequest.getTransactionId(chainId); + +// We can submit the transaction and wait for the result. +const submitTransaction = await predicate.sendTransaction(transactionRequest); +await submitTransaction.waitForResult(); +// #endregion send-and-spend-funds-from-predicates-8 + +const { isStatusSuccess: isTransferFromPredicateSucessful } = + await submitTransaction.waitForResult(); +console.log( + 'Transfer from predicate should be successful', + isTransferFromPredicateSucessful +); +console.log( + 'Transaction ID should be equal', + transactionId === submitTransaction.id +); diff --git a/apps/docs-snippets2/src/predicates/cookbook/transferring-assets.ts b/apps/docs-snippets2/src/predicates/cookbook/transferring-assets.ts new file mode 100644 index 00000000000..d1e7d150eb5 --- /dev/null +++ b/apps/docs-snippets2/src/predicates/cookbook/transferring-assets.ts @@ -0,0 +1,64 @@ +// #region send-and-spend-funds-from-predicates-2 +import { Provider, Wallet } from 'fuels'; + +import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../../env'; +import { SimplePredicate } from '../../typegend'; + +const provider = await Provider.create(LOCAL_NETWORK_URL); +const sender = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); +const receiver = Wallet.generate({ provider }); + +const inputAddress = + '0xfc05c23a8f7f66222377170ddcbfea9c543dff0dd2d2ba4d0478a4521423a9d4'; + +const predicate = new SimplePredicate({ + provider, + data: [inputAddress], +}); +// #endregion send-and-spend-funds-from-predicates-2 +console.log('Predicate should be defined', predicate); + +// #region send-and-spend-funds-from-predicates-3 +// The amount of coins to send to the predicate +const amountToPredicate = 10_000_000; + +// Fund the predicate with some funds from our wallet (sender) +const fundPredicateTx = await sender.transfer( + predicate.address, + amountToPredicate, + provider.getBaseAssetId(), + { + gasLimit: 1000, + } +); + +// Wait for the transaction +await fundPredicateTx.waitForResult(); +// #endregion send-and-spend-funds-from-predicates-3 +const { isStatusSuccess } = await fundPredicateTx.waitForResult(); +console.log( + 'Funding predicate transaction should be successful', + isStatusSuccess +); + +// #region send-and-spend-funds-from-predicates-5 +// The amount of coins to send from the predicate, to our receiver wallet. +const amountToReceiver = 200; + +// Transfer funds from the predicate, to our receiver wallet +const transferFromPredicateTx = await predicate.transfer( + receiver.address, + amountToReceiver, + provider.getBaseAssetId() +); + +// Wait for the transaction +await transferFromPredicateTx.waitForResult(); +// #endregion send-and-spend-funds-from-predicates-5 + +const { isStatusSuccess: isTransferFromPredicateSuccessful } = + await transferFromPredicateTx.waitForResult(); +console.log( + 'Transfer from predicate (to receiver) transaction should be successful', + isTransferFromPredicateSuccessful +); diff --git a/apps/docs-snippets2/src/predicates/custom-transactions.ts b/apps/docs-snippets2/src/predicates/custom-transactions.ts new file mode 100644 index 00000000000..0ac262c4a7e --- /dev/null +++ b/apps/docs-snippets2/src/predicates/custom-transactions.ts @@ -0,0 +1,60 @@ +// #region predicate-custom-transaction +import { Provider, ScriptTransactionRequest, Wallet } from 'fuels'; + +import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../env'; +import { ConfigurablePin } from '../typegend'; +import type { ConfigurablePinInputs } from '../typegend/predicates/ConfigurablePin'; + +// Setup +const provider = await Provider.create(LOCAL_NETWORK_URL); +const sender = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); +const receiver = Wallet.generate({ provider }); +const assetId = provider.getBaseAssetId(); +const amountToFundPredicate = 300_000; +const amountToReceiver = 100_000; + +// Instantiate the predicate using valid predicate data, aka the pin we need +// to send the funds to the receiver +const data: ConfigurablePinInputs = [1337]; +const predicate = new ConfigurablePin({ provider, data }); + +// Fund the predicate, so that we can send these funds via predicate logic +// to the receiver +const fundPredicateTx = await sender.transfer( + predicate.address, + amountToFundPredicate, + assetId +); +await fundPredicateTx.waitForResult(); +const initialPredicateBalance = await predicate.getBalance(assetId); + +// Instantiate the script request +const customRequest = new ScriptTransactionRequest(); + +// Get the predicate resources that we would like to transfer +const predicateResources = await predicate.getResourcesToSpend([ + { assetId, amount: amountToReceiver }, +]); + +// Add the resources for the transfer of the asset to the receiver. The resources +// adds the required inputs, and the output is for the transfer to the receiver address +customRequest.addResources(predicateResources); +customRequest.addCoinOutput(receiver.address, amountToReceiver, assetId); + +// Estimate the transaction cost and fund accordingly +const txCost = await predicate.getTransactionCost(customRequest); +customRequest.gasLimit = txCost.gasUsed; +customRequest.maxFee = txCost.maxFee; +await predicate.fund(customRequest, txCost); + +// Submit the transaction and await it's result +const predicateTx = await predicate.sendTransaction(customRequest); +await predicateTx.waitForResult(); +// #endregion predicate-custom-transaction + +console.log( + 'initialPredicateBalance to equal amountToFundPredicate', + initialPredicateBalance.toNumber() === amountToFundPredicate +); +const { isStatusSuccess } = await predicateTx.waitForResult(); +console.log('Predicate TX has been successful', isStatusSuccess); diff --git a/apps/docs-snippets2/src/predicates/deploying-predicates.ts b/apps/docs-snippets2/src/predicates/deploying-predicates.ts new file mode 100644 index 00000000000..6df4e5b1a46 --- /dev/null +++ b/apps/docs-snippets2/src/predicates/deploying-predicates.ts @@ -0,0 +1,48 @@ +// #region full +import { Provider, Wallet, ContractFactory } from 'fuels'; + +import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../env'; +import { ConfigurablePin, ConfigurablePinLoader } from '../typegend/predicates'; + +const provider = await Provider.create(LOCAL_NETWORK_URL); + +const wallet = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); +const receiver = Wallet.generate({ provider }); +const baseAssetId = provider.getBaseAssetId(); + +// We can deploy dyanmically or via `fuels deploy` +const factory = new ContractFactory( + ConfigurablePin.bytecode, + ConfigurablePin.abi, + wallet +); +const { waitForResult: waitForDeploy } = + await factory.deployAsBlobTxForScript(); +await waitForDeploy(); + +// First, we will need to instantiate the script via it's loader bytecode. +// This can be imported from the typegen outputs that were created on `fuels deploy`. +// Then we can use the predicate as we would normally, such as overriding the configurables. +const predicate = new ConfigurablePinLoader({ + data: [23], + provider, + configurableConstants: { + PIN: 23, + }, +}); + +// Now, let's fund the predicate +const fundTx = await wallet.transfer(predicate.address, 100_000, baseAssetId); +await fundTx.waitForResult(); + +// Then we'll execute the transfer and validate the predicate +const transferTx = await predicate.transfer( + receiver.address, + 1000, + baseAssetId +); +const { isStatusSuccess } = await transferTx.waitForResult(); +// #endregion full + +console.log('Predicate defined', predicate); +console.log('Should fund predicate successfully', isStatusSuccess); diff --git a/apps/docs-snippets2/src/predicates/instantiation/multi-args.ts b/apps/docs-snippets2/src/predicates/instantiation/multi-args.ts new file mode 100644 index 00000000000..cdf90b282ed --- /dev/null +++ b/apps/docs-snippets2/src/predicates/instantiation/multi-args.ts @@ -0,0 +1,12 @@ +// #region predicate-multi-args-2 +import { Provider } from 'fuels'; + +import { LOCAL_NETWORK_URL } from '../../env'; +import { PredicateMultiArgs } from '../../typegend'; + +const provider = await Provider.create(LOCAL_NETWORK_URL); + +const predicate = new PredicateMultiArgs({ provider, data: [20, 30] }); +// #endregion predicate-multi-args-2 + +console.log('Predicate should be defined', predicate); diff --git a/apps/docs-snippets2/src/predicates/instantiation/simple.ts b/apps/docs-snippets2/src/predicates/instantiation/simple.ts new file mode 100644 index 00000000000..0f6229df843 --- /dev/null +++ b/apps/docs-snippets2/src/predicates/instantiation/simple.ts @@ -0,0 +1,14 @@ +// #region predicate-simple-2 +import { Provider } from 'fuels'; + +import { LOCAL_NETWORK_URL } from '../../env'; +import { ReturnTruePredicate } from '../../typegend'; + +const provider = await Provider.create(LOCAL_NETWORK_URL); + +const predicate = new ReturnTruePredicate({ + provider, +}); +// #endregion predicate-simple-2 + +console.log('Predicate should be defined', predicate); diff --git a/apps/docs-snippets2/src/predicates/instantiation/struct-arg.ts b/apps/docs-snippets2/src/predicates/instantiation/struct-arg.ts new file mode 100644 index 00000000000..b7c401d3e2b --- /dev/null +++ b/apps/docs-snippets2/src/predicates/instantiation/struct-arg.ts @@ -0,0 +1,16 @@ +// #region predicate-main-args-struct-2 +import { Provider } from 'fuels'; + +import { LOCAL_NETWORK_URL } from '../../env'; +import { PredicateMainArgsStruct } from '../../typegend'; + +const provider = await Provider.create(LOCAL_NETWORK_URL); + +const predicate = new PredicateMainArgsStruct({ + provider, + data: [{ has_account: true, total_complete: 100 }], +}); + +// #endregion predicate-main-args-struct-2 + +console.log('Predicate should be defined', predicate); diff --git a/apps/docs-snippets2/src/predicates/methods/create-transfer.ts b/apps/docs-snippets2/src/predicates/methods/create-transfer.ts new file mode 100644 index 00000000000..e9bee442448 --- /dev/null +++ b/apps/docs-snippets2/src/predicates/methods/create-transfer.ts @@ -0,0 +1,43 @@ +// #region createTransfer +import { Provider, Wallet } from 'fuels'; + +import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../../env'; +import { ReturnTruePredicate } from '../../typegend'; + +const provider = await Provider.create(LOCAL_NETWORK_URL); +const funder = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); + +const predicate = new ReturnTruePredicate({ + provider, +}); + +// Fund the predicate +const fundPredicate = await funder.transfer( + predicate.address, + 100_000_000, + provider.getBaseAssetId() +); +await fundPredicate.waitForResult(); + +const receiver = Wallet.generate({ provider }); +const amountToReceiver = 1000; + +const transactionRequest = await predicate.createTransfer( + receiver.address, + amountToReceiver, + provider.getBaseAssetId(), + { + gasLimit: 1000, + } +); + +const sendFromPredicate = await predicate.sendTransaction(transactionRequest); + +await sendFromPredicate.waitForResult(); +// #endregion createTransfer + +const { isStatusSuccess } = await sendFromPredicate.waitForResult(); +console.log( + 'Predicate fund transfer transaction should be successful', + isStatusSuccess +); diff --git a/apps/docs-snippets2/src/predicates/methods/get-resources-to-spend.ts b/apps/docs-snippets2/src/predicates/methods/get-resources-to-spend.ts new file mode 100644 index 00000000000..3c70ab1e9e4 --- /dev/null +++ b/apps/docs-snippets2/src/predicates/methods/get-resources-to-spend.ts @@ -0,0 +1,45 @@ +// #region getResourcesToSpend +import { bn, Provider, ScriptTransactionRequest, Wallet } from 'fuels'; + +import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../../env'; +import { ReturnTruePredicate } from '../../typegend'; + +const provider = await Provider.create(LOCAL_NETWORK_URL); +const funder = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); + +const predicate = new ReturnTruePredicate({ + provider, +}); + +// Fund the predicate +const fundPredicate = await funder.transfer( + predicate.address, + 100_000_000, + provider.getBaseAssetId() +); +await fundPredicate.waitForResult(); + +// Instantiate the transaction request. +const transactionRequest = new ScriptTransactionRequest({ + gasLimit: 2000, + maxFee: bn(0), +}); + +// Get the resources available to send from the predicate. +const predicateCoins = await predicate.getResourcesToSpend([ + { amount: 2000, assetId: provider.getBaseAssetId() }, +]); + +// Add the predicate input and resources. +transactionRequest.addResources(predicateCoins); +// #endregion getResourcesToSpend + +console.log( + 'Transaction should have more than one input', + transactionRequest.inputs.length >= 1 +); + +console.log( + 'Transaction should have a single output', + transactionRequest.outputs.length === 1 +); diff --git a/apps/docs-snippets2/src/predicates/methods/send-transaction.ts b/apps/docs-snippets2/src/predicates/methods/send-transaction.ts new file mode 100644 index 00000000000..bf727821646 --- /dev/null +++ b/apps/docs-snippets2/src/predicates/methods/send-transaction.ts @@ -0,0 +1,51 @@ +// #region sendTransaction +import { bn, Provider, ScriptTransactionRequest, Wallet } from 'fuels'; + +import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../../env'; +import { ReturnTruePredicate } from '../../typegend'; + +const provider = await Provider.create(LOCAL_NETWORK_URL); +const funder = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); + +const predicate = new ReturnTruePredicate({ + provider, +}); + +// Fund the predicate +const fundPredicate = await funder.transfer( + predicate.address, + 100_000_000, + provider.getBaseAssetId() +); +await fundPredicate.waitForResult(); + +// Instantiate the transaction request. +const transactionRequest = new ScriptTransactionRequest({ + gasLimit: 2000, + maxFee: bn(100), +}); + +// Get the resources available to send from the predicate. +const predicateCoins = await predicate.getResourcesToSpend([ + { amount: 2000, assetId: provider.getBaseAssetId() }, +]); + +// Add the predicate input and resources. +transactionRequest.addResources(predicateCoins); + +const txCost = await predicate.getTransactionCost(transactionRequest); + +transactionRequest.gasLimit = txCost.gasUsed; +transactionRequest.maxFee = txCost.maxFee; + +await predicate.fund(transactionRequest, txCost); + +// Send the transaction using the predicate +const result = await predicate.sendTransaction(transactionRequest); + +await result.waitForResult(); +// #endregion sendTransaction + +const { isStatusSuccess } = await result.waitForResult(); + +console.log('Send transaction to be successful', isStatusSuccess); diff --git a/apps/docs-snippets2/src/predicates/methods/simulate-transaction.ts b/apps/docs-snippets2/src/predicates/methods/simulate-transaction.ts new file mode 100644 index 00000000000..e2a5c0be851 --- /dev/null +++ b/apps/docs-snippets2/src/predicates/methods/simulate-transaction.ts @@ -0,0 +1,59 @@ +// #region simulateTransaction +import { + bn, + Provider, + ReceiptType, + ScriptTransactionRequest, + Wallet, +} from 'fuels'; + +import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../../env'; +import { ReturnTruePredicate } from '../../typegend'; + +const provider = await Provider.create(LOCAL_NETWORK_URL); +const funder = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); +const receiver = Wallet.generate({ provider }); + +const predicate = new ReturnTruePredicate({ + provider, +}); + +const fundPredicate = await funder.transfer( + predicate.address, + 100_000_000, + provider.getBaseAssetId() +); +await fundPredicate.waitForResult(); + +// Instantiate the transaction request. +const transactionRequest = new ScriptTransactionRequest({ + gasLimit: 2000, + maxFee: bn(0), +}); + +transactionRequest.addCoinOutput( + receiver.address, + 1000000, + provider.getBaseAssetId() +); + +const txCost = await predicate.getTransactionCost(transactionRequest); + +transactionRequest.gasLimit = txCost.gasUsed; +transactionRequest.maxFee = txCost.maxFee; + +await predicate.fund(transactionRequest, txCost); + +const result = await predicate.simulateTransaction(transactionRequest); + +// #endregion simulateTransaction + +const hasReturnReceipt = result.receipts.some( + (receipt) => receipt.type === ReceiptType.Return +); +const hasScriptResultReceipt = result.receipts.some( + (receipt) => receipt.type === ReceiptType.ScriptResult +); + +console.log('Should have return receipt', hasReturnReceipt); +console.log('Should have script result receipt', hasScriptResultReceipt); diff --git a/apps/docs-snippets2/src/predicates/methods/transfer.ts b/apps/docs-snippets2/src/predicates/methods/transfer.ts new file mode 100644 index 00000000000..147131c4c90 --- /dev/null +++ b/apps/docs-snippets2/src/predicates/methods/transfer.ts @@ -0,0 +1,41 @@ +// #region transfer +import { Provider, Wallet } from 'fuels'; + +import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../../env'; +import { ReturnTruePredicate } from '../../typegend'; + +const provider = await Provider.create(LOCAL_NETWORK_URL); +const funder = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); + +const predicate = new ReturnTruePredicate({ + provider, +}); + +const fundPredicate = await funder.transfer( + predicate.address, + 100_000_000, + provider.getBaseAssetId() +); +await fundPredicate.waitForResult(); + +const receiver = Wallet.generate({ provider }); +const amountToReceiver = 1000; + +const transferPredicateCoins = await predicate.transfer( + receiver.address, + amountToReceiver, + provider.getBaseAssetId(), + { + gasLimit: 1000, + } +); + +await transferPredicateCoins.waitForResult(); +// #endregion transfer + +const { isStatusSuccess } = await transferPredicateCoins.waitForResult(); + +console.log( + 'Predicate fund transfer transaction should be successful', + isStatusSuccess +); diff --git a/apps/docs-snippets2/sway/Forc.toml b/apps/docs-snippets2/sway/Forc.toml index 14d655d41ca..e93d927a97c 100644 --- a/apps/docs-snippets2/sway/Forc.toml +++ b/apps/docs-snippets2/sway/Forc.toml @@ -1,6 +1,7 @@ [workspace] members = [ "bytecode-input", + "configurable-pin", "counter", "echo-values", "script-transfer-to-contract", @@ -13,7 +14,11 @@ members = [ "echo-std-string", "employee-data", "input-output-types", + "predicate-main-args-struct", + "predicate-multi-args", + "return-true-predicate", "script-sum", "simple-predicate", "sum-option-u8", + "whitelisted-address-predicate", ] diff --git a/apps/docs-snippets2/sway/configurable-pin/Forc.toml b/apps/docs-snippets2/sway/configurable-pin/Forc.toml new file mode 100644 index 00000000000..9cee609fe4b --- /dev/null +++ b/apps/docs-snippets2/sway/configurable-pin/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "configurable-pin" + +[dependencies] diff --git a/apps/docs-snippets2/sway/configurable-pin/src/main.sw b/apps/docs-snippets2/sway/configurable-pin/src/main.sw new file mode 100644 index 00000000000..2821f17a282 --- /dev/null +++ b/apps/docs-snippets2/sway/configurable-pin/src/main.sw @@ -0,0 +1,12 @@ +// #region full +predicate; + +configurable { + PIN: u64 = 1337, +} + +fn main(pin: u64) -> bool { + return PIN == pin; +} + +// #endregion full diff --git a/apps/docs-snippets2/sway/predicate-main-args-struct/Forc.toml b/apps/docs-snippets2/sway/predicate-main-args-struct/Forc.toml new file mode 100644 index 00000000000..9d7a156a8be --- /dev/null +++ b/apps/docs-snippets2/sway/predicate-main-args-struct/Forc.toml @@ -0,0 +1,6 @@ +[project] +authors = ["Fuel Labs "] +license = "Apache-2.0" +name = "predicate-main-args-struct" + +[dependencies] diff --git a/apps/docs-snippets2/sway/predicate-main-args-struct/src/main.sw b/apps/docs-snippets2/sway/predicate-main-args-struct/src/main.sw new file mode 100644 index 00000000000..4550a28d9c5 --- /dev/null +++ b/apps/docs-snippets2/sway/predicate-main-args-struct/src/main.sw @@ -0,0 +1,15 @@ +// #region predicate-main-args-struct-1 +predicate; + +struct Validation { + has_account: bool, + total_complete: u64, +} + +fn main(received: Validation) -> bool { + let expected_has_account: bool = true; + let expected_total_complete: u64 = 100; + + received.has_account == expected_has_account && received.total_complete == expected_total_complete +} +// #endregion predicate-main-args-struct-1 diff --git a/apps/docs-snippets2/sway/predicate-multi-args/Forc.toml b/apps/docs-snippets2/sway/predicate-multi-args/Forc.toml new file mode 100644 index 00000000000..41888240015 --- /dev/null +++ b/apps/docs-snippets2/sway/predicate-multi-args/Forc.toml @@ -0,0 +1,6 @@ +[project] +authors = ["Fuel Labs "] +license = "Apache-2.0" +name = "predicate-multi-args" + +[dependencies] diff --git a/apps/docs-snippets2/sway/predicate-multi-args/src/main.sw b/apps/docs-snippets2/sway/predicate-multi-args/src/main.sw new file mode 100644 index 00000000000..cedd3d26aec --- /dev/null +++ b/apps/docs-snippets2/sway/predicate-multi-args/src/main.sw @@ -0,0 +1,7 @@ +// #region predicate-multi-args-1 +predicate; + +fn main(arg1: u64, arg2: u64) -> bool { + return arg1 != arg2; +} +// #endregion predicate-multi-args-1 diff --git a/apps/docs-snippets2/sway/return-true-predicate/Forc.toml b/apps/docs-snippets2/sway/return-true-predicate/Forc.toml new file mode 100644 index 00000000000..12db8eb7f97 --- /dev/null +++ b/apps/docs-snippets2/sway/return-true-predicate/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "return-true-predicate" + +[dependencies] diff --git a/apps/docs-snippets2/sway/return-true-predicate/src/main.sw b/apps/docs-snippets2/sway/return-true-predicate/src/main.sw new file mode 100644 index 00000000000..241773a275f --- /dev/null +++ b/apps/docs-snippets2/sway/return-true-predicate/src/main.sw @@ -0,0 +1,7 @@ +// #region predicate-simple-1 +predicate; + +fn main() -> bool { + true +} +// #endregion predicate-simple-1 diff --git a/apps/docs-snippets2/sway/whitelisted-address-predicate/Forc.toml b/apps/docs-snippets2/sway/whitelisted-address-predicate/Forc.toml new file mode 100644 index 00000000000..8ff533bcc2b --- /dev/null +++ b/apps/docs-snippets2/sway/whitelisted-address-predicate/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "whitelisted-address-predicate" + +[dependencies] diff --git a/apps/docs-snippets2/sway/whitelisted-address-predicate/src/main.sw b/apps/docs-snippets2/sway/whitelisted-address-predicate/src/main.sw new file mode 100644 index 00000000000..ada8ddd8cd5 --- /dev/null +++ b/apps/docs-snippets2/sway/whitelisted-address-predicate/src/main.sw @@ -0,0 +1,11 @@ +// #region full +predicate; + +configurable { + WHITELISTED: b256 = 0xa703b26833939dabc41d3fcaefa00e62cee8e1ac46db37e0fa5d4c9fe30b4132, +} + +fn main(address: b256) -> bool { + WHITELISTED == address +} +// #endregion full diff --git a/apps/docs/src/guide/creating-a-fuel-dapp/working-with-predicates.md b/apps/docs/src/guide/creating-a-fuel-dapp/working-with-predicates.md index dd9b1b84ee4..6af0a39bce3 100644 --- a/apps/docs/src/guide/creating-a-fuel-dapp/working-with-predicates.md +++ b/apps/docs/src/guide/creating-a-fuel-dapp/working-with-predicates.md @@ -16,7 +16,7 @@ The current predicate functionality we have is a simple one that checks if the u The first step is to modify the predicate contract to accept a configurable pin. We will use the [`configurable`](https://docs.fuel.network/guides/intro-to-predicates/configurables/#configurables) keyword to create an updatable constant to store the pin. We will also modify the main function to check this constant instead of a hardcoded pin. -<<< @/../../docs-snippets/test/fixtures/forc-projects/configurable-pin/src/main.sw#predicate-with-configurable-pin-1{rust:line-numbers} +<<< @/../../docs-snippets2/sway/configurable-pin/src/main.sw#full{rust:line-numbers} 2. Modifying the Frontend diff --git a/apps/docs/src/guide/predicates/configurable-constants.md b/apps/docs/src/guide/predicates/configurable-constants.md index 6ac910e820f..82153c7e148 100644 --- a/apps/docs/src/guide/predicates/configurable-constants.md +++ b/apps/docs/src/guide/predicates/configurable-constants.md @@ -8,7 +8,7 @@ Let's consider an example where a predicate is used to validate an asset transfe The following snippet illustrates how this could be implemented: -<<< @/../../docs-snippets/test/fixtures/forc-projects/whitelisted-address-predicate/src/main.sw#predicate-with-configurable-constants-1{rust:line-numbers} +<<< @/../../docs-snippets2/sway/whitelisted-address-predicate/src/main.sw#full{rust:line-numbers} In this example, you'll notice the use of a configurable constant named `WHITELISTED`. This constant has a default value that represents the default approved address. @@ -16,7 +16,7 @@ In this example, you'll notice the use of a configurable constant named `WHITELI If there is a need to whitelist another address, the `WHITELISTED` constant can be easily updated. The following snippet demonstrates how to set a new value for the `WHITELISTED` constant and to make the predicate execute the transfer: -<<< @/../../docs-snippets/src/guide/predicates/predicate-with-configurable.test.ts#predicate-with-configurable-constants-2{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/configurables/configurable-set-data.ts#full{ts:line-numbers} By ensuring that the updated `WHITELISTED` address matches the intended recipient's address, the predicate will validate the transfer successfully. @@ -24,7 +24,7 @@ By ensuring that the updated `WHITELISTED` address matches the intended recipien In scenarios where the default whitelisted address is already the intended recipient, there's no need to update the `WHITELISTED` constant. The predicate will validate the transfer based on the default value. Here's how this scenario might look: -<<< @/../../docs-snippets/src/guide/predicates/predicate-with-configurable.test.ts#predicate-with-configurable-constants-3{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/configurables/configurable-default.ts#full{ts:line-numbers} This ability to configure constants within predicates provides a flexible mechanism for customizing their behavior, thereby enhancing the robustness and versatility of our asset transfer process. diff --git a/apps/docs/src/guide/predicates/custom-transactions.md b/apps/docs/src/guide/predicates/custom-transactions.md index 973517896d7..f3882a5a16d 100644 --- a/apps/docs/src/guide/predicates/custom-transactions.md +++ b/apps/docs/src/guide/predicates/custom-transactions.md @@ -6,8 +6,8 @@ Custom transactions can be shaped via a `ScriptTransactionRequest` instance. For However, this guide will demonstrate how to use a predicate in a custom transaction. Consider the following predicate, where a configurable pin must be used to validate the predicate and unlock the funds: -<<< @/../../docs-snippets/test/fixtures/forc-projects/configurable-pin/src/main.sw#predicate-with-configurable-pin-1{rust:line-numbers} +<<< @/../../docs-snippets2/sway/configurable-pin/src/main.sw#full{rust:line-numbers} We can interact with the above and include it in a custom transaction like so: -<<< @/../../docs-snippets/src/guide/predicates/predicate-custom-transactions.test.ts#predicate-custom-transaction{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/custom-transactions.ts#predicate-custom-transaction{ts:line-numbers} diff --git a/apps/docs/src/guide/predicates/deploying-predicates.md b/apps/docs/src/guide/predicates/deploying-predicates.md index 54c2d3d4c43..a1f4b325027 100644 --- a/apps/docs/src/guide/predicates/deploying-predicates.md +++ b/apps/docs/src/guide/predicates/deploying-predicates.md @@ -17,4 +17,4 @@ This will perform the following actions: We can then utilize the above generated types like so: -<<< @/../../docs-snippets/src/guide/predicates/deploying-predicates.test.ts#deploying-predicates{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/deploying-predicates.ts#full{ts:line-numbers} diff --git a/apps/docs/src/guide/predicates/instantiating-a-predicate.md b/apps/docs/src/guide/predicates/instantiating-a-predicate.md index 2af73ab2df1..86fc9929f55 100644 --- a/apps/docs/src/guide/predicates/instantiating-a-predicate.md +++ b/apps/docs/src/guide/predicates/instantiating-a-predicate.md @@ -2,7 +2,7 @@ A predicate in Sway can be as simple as the following: -<<< @/../../docs-snippets/test/fixtures/forc-projects/return-true-predicate/src/main.sw#predicate-index-1{rust:line-numbers} +<<< @/../../docs-snippets2/sway/return-true-predicate/src/main.sw#predicate-simple-1{rust:line-numbers} In this minimal example, the `main` function does not accept any parameters and simply returns true. @@ -10,7 +10,7 @@ Just like contracts in Sway, once you've created a predicate, you can compile it After compiling, you will obtain the binary of the predicate and its JSON ABI (Application Binary Interface). Using these, you can instantiate a predicate in TypeScript as shown in the code snippet below: -<<< @/../../docs-snippets/src/guide/predicates/index.test.ts#predicate-index-2{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/instantiation/simple.ts#predicate-simple-2{ts:line-numbers} The created [`Predicate`](../../api/Account/Predicate.md) instance, among other things, has three important properties: the predicate `bytes` (byte code), the `chainId`, and the predicate `address`. @@ -20,18 +20,18 @@ This address, generated from the byte code, corresponds to the Pay-to-Script-Has You can pass more than one argument to a predicate. For example, this is a predicate that evaluates to `true` if the two arguments are not equal: -<<< @/../../../packages/fuel-gauge/test/fixtures/forc-projects/predicate-multi-args/src/main.sw#predicate-multi-args-sw{rust:line-numbers} +<<< @/../../docs-snippets2/sway/predicate-multi-args/src/main.sw#predicate-multi-args-1{rust:line-numbers} You can pass the two arguments to this predicate like this: -<<< @/../../../packages/fuel-gauge/src/predicate/predicate-arguments.test.ts#predicate-multi-args{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/instantiation/multi-args.ts#predicate-multi-args-2{rust:line-numbers} ## Predicate with a Struct argument You can also pass a struct as an argument to a predicate. This is one such predicate that expects a struct as an argument: -<<< @/../../../packages/fuel-gauge/test/fixtures/forc-projects/predicate-main-args-struct/src/main.sw#Predicate-main-args{rust:line-numbers} +<<< @/../../docs-snippets2/sway/predicate-main-args-struct/src/main.sw#predicate-main-args-struct-1{rust:line-numbers} You can pass a struct as an argument to this predicate like this: -<<< @/../../../packages/fuel-gauge/src/predicate/predicate-arguments.test.ts#predicate-struct-arg{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/instantiation/struct-arg.ts#predicate-main-args-struct-2{ts:line-numbers} diff --git a/apps/docs/src/guide/predicates/methods.md b/apps/docs/src/guide/predicates/methods.md index a9803ef5657..06bba43dcae 100644 --- a/apps/docs/src/guide/predicates/methods.md +++ b/apps/docs/src/guide/predicates/methods.md @@ -1,10 +1,10 @@ # Interacting With Predicates The `Predicate` class extends the [`Account`](https://docs.fuel.network/docs/fuels-ts/account/) class, inheriting all its methods. Therefore, there are multiple ways to interact with predicates, but broadly speaking, we can think about three: - - `Checking Balances` - - `Transactions` - - `Transfers` +- `Checking Balances` +- `Transactions` +- `Transfers` ## Checking Balances @@ -22,7 +22,7 @@ This method is called under the hood when using [`transfer`](./methods.md#transf You may want to use this method when using a predicate in an existing transaction request. -<<< @/../../docs-snippets/src/guide/predicates/interacting-with-predicates.test.ts#interacting-with-predicates-1{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/methods/get-resources-to-spend.ts#getResourcesToSpend{ts:line-numbers} ## Transactions @@ -30,13 +30,13 @@ You may want to use this method when using a predicate in an existing transactio This is used to send a transaction to the node. -<<< @/../../docs-snippets/src/guide/predicates/interacting-with-predicates.test.ts#interacting-with-predicates-2{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/methods/send-transaction.ts#sendTransaction{ts:line-numbers} ### `simulateTransaction` You can use the `simulateTransaction` method to dry-run a predicate call without consuming resources. A typical use case of a dry-run call is to validate that sufficient funds are available to cover the transaction fees. -<<< @/../../docs-snippets/src/guide/predicates/interacting-with-predicates.test.ts#interacting-with-predicates-3{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/methods/simulate-transaction.ts#simulateTransaction{ts:line-numbers} ## Transfers @@ -46,10 +46,10 @@ The `createTransfer` method creates a transaction request with all the necessary However, please remember that you can still modify the transfer request details and use its properties before submitting it to the node. -<<< @/../../docs-snippets/src/guide/predicates/send-and-spend-funds-from-predicates.test.ts#send-and-spend-funds-from-predicates-8{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/methods/create-transfer.ts#createTransfer{ts:line-numbers} ### `transfer` You can send funds to another address using the `transfer` method. -<<< @/../../docs-snippets/src/guide/cookbook/transferring-assets.test.ts#transferring-assets-1{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/methods/transfer.ts#transfer{ts:line-numbers} diff --git a/apps/docs/src/guide/predicates/send-and-spend-funds-from-predicates.md b/apps/docs/src/guide/predicates/send-and-spend-funds-from-predicates.md index a20025005b2..554dc5a2598 100644 --- a/apps/docs/src/guide/predicates/send-and-spend-funds-from-predicates.md +++ b/apps/docs/src/guide/predicates/send-and-spend-funds-from-predicates.md @@ -8,7 +8,7 @@ This guide will demonstrate how to send and spend funds using a predicate. Consider the following predicate: -<<< @/../../docs-snippets/test/fixtures/forc-projects/simple-predicate/src/main.sw#send-and-spend-funds-from-predicates-1{rust:line-numbers} +<<< @/../../docs-snippets2/sway/simple-predicate/src/main.sw#send-and-spend-funds-from-predicates-1{rust:line-numbers} This predicate accepts an address of type `b256` and compares it with a hard-coded address of the same type. If both addresses are equal, the predicate returns true, otherwise it will return false. @@ -20,17 +20,17 @@ Once you've compiled the predicate (`forc build`), you'll obtain two important a This is where we also pass in the predicate's data. Note that the `main` function in our predicate example requires a parameter called `input_address` of type `b256`. We will pass this parameter to the `Predicate` constructor along with the bytecode and the JSON ABI. -<<< @/../../docs-snippets/src/guide/predicates/send-and-spend-funds-from-predicates.test.ts#send-and-spend-funds-from-predicates-2{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/cookbook/transferring-assets.ts#send-and-spend-funds-from-predicates-2{ts:line-numbers} > Note: If you want to pass in the predicate data _after_ instantiating the `Predicate` or if you want to use a different data than the one passed in the constructor, you will have to create a new `Predicate` instance. With the predicate instantiated, we can transfer funds to its address. This requires us to have a wallet with sufficient funds. If you're unsure about using wallets with the SDK, we recommend checking out our [wallet](../wallets/) guide. -<<< @/../../docs-snippets/src/guide/predicates/send-and-spend-funds-from-predicates.test.ts#send-and-spend-funds-from-predicates-3{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/cookbook/transferring-assets.ts#send-and-spend-funds-from-predicates-3{ts:line-numbers} Now that our predicate holds funds, we can use it to validate a transaction and hence execute our transfer. We can achieve that by doing the following: -<<< @/../../docs-snippets/src/guide/predicates/send-and-spend-funds-from-predicates.test.ts#send-and-spend-funds-from-predicates-5{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/cookbook/transferring-assets.ts#send-and-spend-funds-from-predicates-5{ts:line-numbers} Note the method transfer has two parameters: the recipient's address and the intended transfer amount. @@ -40,13 +40,15 @@ Once the predicate resolves with a return value `true` based on its predefined c In a similar approach, you can use the `createTransfer` method, which returns a [`ScriptTransactionRequest`](../../api/Account/ScriptTransactionRequest.md). Then, we can submit this transaction request by calling the `sendTransaction` method. -<<< @/../../docs-snippets/src/guide/predicates/send-and-spend-funds-from-predicates.test.ts#send-and-spend-funds-from-predicates-8{ts:line-numbers} +The following example, we are pre-staging a transaction and therefore we are able to know the transaction ID without actually submitting the transaction. + +<<< @/../../docs-snippets2/src/predicates/cookbook/pre-stage.ts#send-and-spend-funds-from-predicates-8{ts:line-numbers} ## Spending Entire Predicate Held Amount Trying to forward the entire amount held by the predicate results in an error because no funds are left to cover the transaction fees. Attempting this will result in an error message like: -<<< @/../../docs-snippets/src/guide/predicates/send-and-spend-funds-from-predicates.test.ts#send-and-spend-funds-from-predicates-6{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/cookbook/failure-not-enough-funds.ts#send-and-spend-funds-from-predicates-6{ts:line-numbers} ## Predicate Validation Failure @@ -54,12 +56,4 @@ What happens when a predicate fails to validate? Recall our predicate only valid When a predicate fails to validate, the SDK throws an error that starts like this: -<<< @/../../docs-snippets/src/guide/predicates/send-and-spend-funds-from-predicates.test.ts#send-and-spend-funds-from-predicates-7{ts:line-numbers} - -## Pre-staging a Transaction - -In some cases, you may want to pre-stage a predicate transaction before submitting it for execution. To do this, you can use the `createTransfer` method on the `Predicate` class. - -In the following example, we are pre-staging a transaction to be able to know the transaction ID without actually submitting the transaction. - -<<< @/../../docs-snippets/src/guide/predicates/send-and-spend-funds-from-predicates.test.ts#predicates-prestage-transaction{ts:line-numbers} +<<< @/../../docs-snippets2/src/predicates/cookbook/failure-returns-false.ts#send-and-spend-funds-from-predicates-7{ts:line-numbers} diff --git a/packages/fuel-gauge/src/predicate/predicate-arguments.test.ts b/packages/fuel-gauge/src/predicate/predicate-arguments.test.ts index 91c797f8945..d9c6d2f8ee9 100644 --- a/packages/fuel-gauge/src/predicate/predicate-arguments.test.ts +++ b/packages/fuel-gauge/src/predicate/predicate-arguments.test.ts @@ -156,7 +156,6 @@ describe('Predicate', () => { ); await fundTx.waitForResult(); - // #region predicate-struct-arg const predicate = new PredicateMainArgsStruct({ provider, data: [{ has_account: true, total_complete: 100 }], @@ -171,7 +170,6 @@ describe('Predicate', () => { } ); const { isStatusSuccess } = await tx.waitForResult(); - // #endregion predicate-struct-arg await assertBalances(receiver, initialReceiverBalance, amountToReceiver); expect(isStatusSuccess).toBeTruthy(); @@ -241,7 +239,6 @@ describe('Predicate', () => { const receiver = Wallet.generate({ provider }); const initialReceiverBalance = await receiver.getBalance(); - // #region predicate-multi-args const predicate = new PredicateMultiArgs({ provider, data: [20, 30] }); // fund the predicate @@ -256,7 +253,6 @@ describe('Predicate', () => { } ); const { isStatusSuccess } = await tx.waitForResult(); - // #endregion predicate-multi-args await assertBalances(receiver, initialReceiverBalance, amountToReceiver); expect(isStatusSuccess).toBeTruthy(); diff --git a/packages/fuel-gauge/test/fixtures/forc-projects/predicate-main-args-struct/src/main.sw b/packages/fuel-gauge/test/fixtures/forc-projects/predicate-main-args-struct/src/main.sw index 2439e988d9b..b3e0856d28c 100644 --- a/packages/fuel-gauge/test/fixtures/forc-projects/predicate-main-args-struct/src/main.sw +++ b/packages/fuel-gauge/test/fixtures/forc-projects/predicate-main-args-struct/src/main.sw @@ -1,4 +1,3 @@ -// #region Predicate-main-args predicate; struct Validation { @@ -12,4 +11,3 @@ fn main(received: Validation) -> bool { received.has_account == expected_has_account && received.total_complete == expected_total_complete } -// #endregion Predicate-main-args diff --git a/packages/fuel-gauge/test/fixtures/forc-projects/predicate-multi-args/src/main.sw b/packages/fuel-gauge/test/fixtures/forc-projects/predicate-multi-args/src/main.sw index f982c8f82fe..4f31b5e3510 100644 --- a/packages/fuel-gauge/test/fixtures/forc-projects/predicate-multi-args/src/main.sw +++ b/packages/fuel-gauge/test/fixtures/forc-projects/predicate-multi-args/src/main.sw @@ -1,7 +1,5 @@ -// #region predicate-multi-args-sw predicate; fn main(arg1: u64, arg2: u64) -> bool { return arg1 != arg2; } -// #endregion predicate-multi-args-sw