Predicate data
Let's consider the following predicate example:
predicate;
fn main(a: u32, b: u64) -> bool {
a == b
}
Similarly to contracts and scripts, the abigen!
generates a function that will conveniently encode all the arguments of the main function for us. This function is called encode_data
, and it is accessed through the predicate instance as shown below:
let predicate = predicate.encode_data(4096, 4096);
Next, we will look at a complete example of using the SDK to send and receive funds from a predicate.
First, we set up the wallets, node, and a predicate instance:
let asset_id = AssetId::default();
let wallets_config = WalletsConfig::new_multiple_assets(
2,
vec![AssetConfig {
id: asset_id,
num_coins: 1,
coin_amount: 1_000,
}],
);
let wallets = &launch_custom_provider_and_get_wallets(wallets_config, None, None).await;
let first_wallet = &wallets[0];
let second_wallet = &wallets[1];
abigen!(Predicate(name="MyPredicate", abi="packages/fuels/tests/predicates/predicate_basic/out/debug/predicate_basic-abi.json"));
let predicate = MyPredicate::load_from(
"../../packages/fuels/tests/predicates/predicate_basic/out/debug/predicate_basic.bin",
)?;
Next, we lock some assets in this predicate using the first wallet:
// First wallet transfers amount to predicate.
predicate.receive(first_wallet, 500, asset_id, None).await?;
// Check predicate balance.
let balance = first_wallet
.get_provider()?
.get_asset_balance(predicate.address(), asset_id)
.await?;
assert_eq!(balance, 500);
Then, we try to unlock the amount and spend it using the second wallet, effectively sending the previously locked value to itself.
The predicate expects the data sent to it to be two numbers (u32
and u64
) with matching values.
// We use the Predicate's `encode_data()` to encode the data we want to
// send to the predicate. This is a builder pattern and the function
// returns a new predicate.
let amount_to_unlock = 500;
predicate
.encode_data(4096, 4096)
.spend(second_wallet, amount_to_unlock, asset_id, None)
.await?;
// Predicate balance is zero.
let balance = first_wallet
.get_provider()?
.get_asset_balance(predicate.address(), AssetId::default())
.await?;
assert_eq!(balance, 0);
// Second wallet balance is updated.
let balance = second_wallet.get_asset_balance(&AssetId::default()).await?;
assert_eq!(balance, 1500);