Interacting With Predicates
The Predicate
class extends the 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
getBalances
This will return the balances of all assets owned by the predicate.
See also: Checking Wallet Balances
getResourcesToSpend
This will return the resources owned by a predicate so that they can be added to a transaction request.
This method is called under the hood when using transfer
or createTransfer
.
You may want to use this method when using a predicate in an existing transaction request.
// 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);
Transactions
sendTransaction
This is used to send a transaction to the node.
const result = await predicate.sendTransaction(transactionRequest);
await result.waitForResult();
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.
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);
Transfers
createTransfer
The createTransfer
method creates a transaction request with all the necessary transfer details. It automatically estimates the transaction costs via a dry-run call and funds the request with the required predicate resources. After this, one can submit the returned transaction request with greater certainty that it will succeed.
However, please remember that you can still modify the transfer request details and use its properties before submitting it to the node.
const transactionRequest = await predicate.createTransfer(
receiverWallet.address,
amountToReceiver,
provider.getBaseAssetId(),
{
gasLimit: 1000,
}
);
/*
You can retrieve the transaction ID before actually submitting it to the node
like this:
*/
const chainId = provider.getChainId();
const txId = transactionRequest.getTransactionId(chainId);
const res = await predicate.sendTransaction(transactionRequest);
await res.waitForResult();
transfer
You can send funds to another address using the transfer
method.
import { BN, Wallet } from 'fuels';
const sender = Wallet.fromPrivateKey('...');
const destination = Wallet.generate({
provider: sender.provider,
});
const amountToTransfer = 500;
const baseAssetId = sender.provider.getBaseAssetId();
const response = await sender.transfer(destination.address, amountToTransfer, baseAssetId);
await response.wait();
// Retrieve balances
const receiverBalance = await destination.getBalance(baseAssetId);
// Validate new balance
expect(new BN(receiverBalance).toNumber()).toEqual(amountToTransfer);