Skip to content

Commit

Permalink
chore!: Move get_asset_outputs_for_amount, `get_asset_inputs_for_am…
Browse files Browse the repository at this point in the history
…ount` and `adjust_for_fee` from `Account` to `ViewOnlyAccount` (#1498)

# Release notes

In this release, we:

- Move `get_asset_outputs_for_amount` and `adjust_for_fee` from
`Account` to `ViewOnlyAccount`

# Summary

This PR moves `get_asset_outputs_for_amount`,
`get_asset_inputs_for_amount` and `adjust_for_fee` from `Account` to
`ViewOnlyAccount` trait. It seem that these two methods doesn't require
a full `Account` and so it give more flexibility in order to implement
them in other structures such as `Wallet`.

Now `Wallet` also implement these two methods. Before you were forced to
build a `WalletUnlocked` even if you don't use the `secret_key`.

# Breaking changes

This contains an API breaking change as some public trait as been
edited:

# Breaking Changes

The provider option flag `cacheUtxo` was renamed to `resourceCacheTTL`

```rust
// before
use fuels::acounts::Account;

wallet.get_asset_outputs_for_amount(...);
```

```rust
// after
use fuels::acounts::ViewOnlyAccount;

wallet.get_asset_outputs_for_amount(...);
```

# Checklist

- [x] All **changes** are **covered** by **tests** (or not applicable)
- [x] All **changes** are **documented** (or not applicable)
- [x] I **reviewed** the **entire PR** myself (preferably, on GH UI)
- [x] I **described** all **Breaking Changes** (or there's none)

---------

Co-authored-by: hal3e <[email protected]>
Co-authored-by: Rodrigo Araújo <[email protected]>
Co-authored-by: MujkicA <[email protected]>
  • Loading branch information
4 people committed Nov 22, 2024
1 parent 1d06f47 commit 6d66390
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 38 deletions.
2 changes: 1 addition & 1 deletion docs/src/custom-transactions/transaction-builders.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ As we have used coins that require a signature, we have to add the signer to the

> **Note** The signature is not created until the transaction is finalized with `build(&provider)`
We need to do one more thing before we stop thinking about transaction inputs. Executing the transaction also incurs a fee that is paid with the base asset. Our base asset inputs need to be large enough so that the total amount covers the transaction fee and any other operations we are doing. The `Account` trait lets us use `adjust_for_fee()` for adjusting the transaction inputs if needed to cover the fee. The second argument to `adjust_for_fee()` is the total amount of the base asset that we expect our transaction to spend regardless of fees. In our case, this is the **ask_amount** we are transferring to the predicate.
We need to do one more thing before we stop thinking about transaction inputs. Executing the transaction also incurs a fee that is paid with the base asset. Our base asset inputs need to be large enough so that the total amount covers the transaction fee and any other operations we are doing. The `ViewOnlyAccount` trait lets us use `adjust_for_fee()` for adjusting the transaction inputs if needed to cover the fee. The second argument to `adjust_for_fee()` is the total amount of the base asset that we expect our transaction to spend regardless of fees. In our case, this is the **ask_amount** we are transferring to the predicate.

```rust,ignore
{{#include ../../../examples/cookbook/src/lib.rs:custom_tx_adjust}}
Expand Down
2 changes: 1 addition & 1 deletion examples/cookbook/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ mod tests {
use std::{str::FromStr, time::Duration};

use fuels::{
accounts::{predicate::Predicate, wallet::WalletUnlocked, Account, ViewOnlyAccount},
accounts::{predicate::Predicate, wallet::WalletUnlocked, ViewOnlyAccount},
prelude::Result,
test_helpers::{setup_single_asset_coins, setup_test_provider},
types::{
Expand Down
26 changes: 12 additions & 14 deletions packages/fuels-accounts/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,6 @@ pub trait ViewOnlyAccount: std::fmt::Debug + Send + Sync + Clone {

self.try_provider()?.get_spendable_resources(filter).await
}
}

#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait Account: ViewOnlyAccount {
/// Returns a vector consisting of `Input::Coin`s and `Input::Message`s for the given
/// asset ID and amount. The `witness_index` is the position of the witness (signature)
/// in the transaction's list of witnesses. In the validation process, the node will
/// use the witness at this index to validate the coins returned by this method.
async fn get_asset_inputs_for_amount(
&self,
asset_id: AssetId,
amount: u64,
excluded_coins: Option<Vec<CoinTypeId>>,
) -> Result<Vec<Input>>;

/// Returns a vector containing the output coin and change output given an asset and amount
fn get_asset_outputs_for_amount(
Expand All @@ -122,6 +108,15 @@ pub trait Account: ViewOnlyAccount {
]
}

/// Returns a vector consisting of `Input::Coin`s and `Input::Message`s for the given
/// asset ID and amount.
async fn get_asset_inputs_for_amount(
&self,
asset_id: AssetId,
amount: u64,
excluded_coins: Option<Vec<CoinTypeId>>,
) -> Result<Vec<Input>>;

/// Add base asset inputs to the transaction to cover the estimated fee.
/// Requires contract inputs to be at the start of the transactions inputs vec
/// so that their indexes are retained
Expand Down Expand Up @@ -155,7 +150,10 @@ pub trait Account: ViewOnlyAccount {

Ok(())
}
}

#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
pub trait Account: ViewOnlyAccount {
// Add signatures to the builder if the underlying account is a wallet
fn add_witnesses<Tb: TransactionBuilder>(&self, _tb: &mut Tb) -> Result<()> {
Ok(())
Expand Down
8 changes: 3 additions & 5 deletions packages/fuels-accounts/src/impersonated_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ impl ImpersonatedAccount {
}
}

#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
impl ViewOnlyAccount for ImpersonatedAccount {
fn address(&self) -> &Bech32Address {
self.address()
Expand All @@ -37,12 +38,7 @@ impl ViewOnlyAccount for ImpersonatedAccount {
fn try_provider(&self) -> Result<&Provider> {
self.provider.as_ref().ok_or_else(try_provider_error)
}
}

#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
impl Account for ImpersonatedAccount {
/// Returns a vector consisting of `Input::Coin`s and `Input::Message`s for the given
/// asset ID and amount.
async fn get_asset_inputs_for_amount(
&self,
asset_id: AssetId,
Expand All @@ -56,7 +52,9 @@ impl Account for ImpersonatedAccount {
.map(Input::resource_signed)
.collect::<Vec<Input>>())
}
}

impl Account for ImpersonatedAccount {
fn add_witnesses<Tb: TransactionBuilder>(&self, tb: &mut Tb) -> Result<()> {
tb.add_signer(self.clone())?;

Expand Down
8 changes: 4 additions & 4 deletions packages/fuels-accounts/src/predicate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ impl Predicate {
}

#[cfg(feature = "std")]
#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
impl ViewOnlyAccount for Predicate {
fn address(&self) -> &Bech32Address {
self.address()
Expand All @@ -109,11 +110,7 @@ impl ViewOnlyAccount for Predicate {
fn try_provider(&self) -> Result<&Provider> {
self.provider.as_ref().ok_or_else(try_provider_error)
}
}

#[cfg(feature = "std")]
#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
impl Account for Predicate {
async fn get_asset_inputs_for_amount(
&self,
asset_id: AssetId,
Expand All @@ -130,3 +127,6 @@ impl Account for Predicate {
.collect::<Vec<Input>>())
}
}

#[cfg(feature = "std")]
impl Account for Predicate {}
34 changes: 21 additions & 13 deletions packages/fuels-accounts/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ impl Wallet {
}
}

#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl ViewOnlyAccount for Wallet {
fn address(&self) -> &Bech32Address {
self.address()
Expand All @@ -86,6 +87,20 @@ impl ViewOnlyAccount for Wallet {
fn try_provider(&self) -> Result<&Provider> {
self.provider.as_ref().ok_or_else(try_provider_error)
}

async fn get_asset_inputs_for_amount(
&self,
asset_id: AssetId,
amount: u64,
excluded_coins: Option<Vec<CoinTypeId>>,
) -> Result<Vec<Input>> {
Ok(self
.get_spendable_resources(asset_id, amount, excluded_coins)
.await?
.into_iter()
.map(Input::resource_signed)
.collect::<Vec<Input>>())
}
}

impl WalletUnlocked {
Expand Down Expand Up @@ -190,6 +205,7 @@ impl WalletUnlocked {
}
}

#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
impl ViewOnlyAccount for WalletUnlocked {
fn address(&self) -> &Bech32Address {
self.wallet.address()
Expand All @@ -198,28 +214,20 @@ impl ViewOnlyAccount for WalletUnlocked {
fn try_provider(&self) -> Result<&Provider> {
self.provider.as_ref().ok_or_else(try_provider_error)
}
}

#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
impl Account for WalletUnlocked {
/// Returns a vector consisting of `Input::Coin`s and `Input::Message`s for the given
/// asset ID and amount. The `witness_index` is the position of the witness (signature)
/// in the transaction's list of witnesses. In the validation process, the node will
/// use the witness at this index to validate the coins returned by this method.
async fn get_asset_inputs_for_amount(
&self,
asset_id: AssetId,
amount: u64,
excluded_coins: Option<Vec<CoinTypeId>>,
) -> Result<Vec<Input>> {
Ok(self
.get_spendable_resources(asset_id, amount, excluded_coins)
.await?
.into_iter()
.map(Input::resource_signed)
.collect::<Vec<Input>>())
self.wallet
.get_asset_inputs_for_amount(asset_id, amount, excluded_coins)
.await
}
}

impl Account for WalletUnlocked {
fn add_witnesses<Tb: TransactionBuilder>(&self, tb: &mut Tb) -> Result<()> {
tb.add_signer(self.clone())?;

Expand Down

0 comments on commit 6d66390

Please sign in to comment.