From 17971b41d32ac8988461e089e244f83f08cde947 Mon Sep 17 00:00:00 2001 From: AurelienFT <32803821+AurelienFT@users.noreply.github.com> Date: Wed, 11 Sep 2024 09:55:02 +0200 Subject: [PATCH 1/2] chore!: Move `get_asset_outputs_for_amount`, `get_asset_inputs_for_amount` and `adjust_for_fee` from `Account` to `ViewOnlyAccount` (#1498) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # 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 Co-authored-by: Rodrigo Araújo Co-authored-by: MujkicA --- .../transaction-builders.md | 2 +- examples/cookbook/src/lib.rs | 2 +- packages/fuels-accounts/src/account.rs | 26 +++++++------- .../src/impersonated_account.rs | 8 ++--- packages/fuels-accounts/src/predicate.rs | 8 ++--- packages/fuels-accounts/src/wallet.rs | 34 ++++++++++++------- 6 files changed, 42 insertions(+), 38 deletions(-) diff --git a/docs/src/custom-transactions/transaction-builders.md b/docs/src/custom-transactions/transaction-builders.md index 629f96b16f..03cfbbe826 100644 --- a/docs/src/custom-transactions/transaction-builders.md +++ b/docs/src/custom-transactions/transaction-builders.md @@ -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}} diff --git a/examples/cookbook/src/lib.rs b/examples/cookbook/src/lib.rs index 8a153214c4..e8e68f14cb 100644 --- a/examples/cookbook/src/lib.rs +++ b/examples/cookbook/src/lib.rs @@ -3,7 +3,7 @@ mod tests { use std::str::FromStr; 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::{ diff --git a/packages/fuels-accounts/src/account.rs b/packages/fuels-accounts/src/account.rs index 8fb7c31d62..8e1c463971 100644 --- a/packages/fuels-accounts/src/account.rs +++ b/packages/fuels-accounts/src/account.rs @@ -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>, - ) -> Result>; /// Returns a vector containing the output coin and change output given an asset and amount fn get_asset_outputs_for_amount( @@ -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>, + ) -> Result>; + /// 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 @@ -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(&self, _tb: &mut Tb) -> Result<()> { Ok(()) diff --git a/packages/fuels-accounts/src/impersonated_account.rs b/packages/fuels-accounts/src/impersonated_account.rs index 77e4f19948..10f3759dfd 100644 --- a/packages/fuels-accounts/src/impersonated_account.rs +++ b/packages/fuels-accounts/src/impersonated_account.rs @@ -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() @@ -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, @@ -56,7 +52,9 @@ impl Account for ImpersonatedAccount { .map(Input::resource_signed) .collect::>()) } +} +impl Account for ImpersonatedAccount { fn add_witnesses(&self, tb: &mut Tb) -> Result<()> { tb.add_signer(self.clone())?; diff --git a/packages/fuels-accounts/src/predicate.rs b/packages/fuels-accounts/src/predicate.rs index c623d053a9..6fc1262eff 100644 --- a/packages/fuels-accounts/src/predicate.rs +++ b/packages/fuels-accounts/src/predicate.rs @@ -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() @@ -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, @@ -130,3 +127,6 @@ impl Account for Predicate { .collect::>()) } } + +#[cfg(feature = "std")] +impl Account for Predicate {} diff --git a/packages/fuels-accounts/src/wallet.rs b/packages/fuels-accounts/src/wallet.rs index fe124f58e5..45fec01d2b 100644 --- a/packages/fuels-accounts/src/wallet.rs +++ b/packages/fuels-accounts/src/wallet.rs @@ -78,6 +78,7 @@ impl Wallet { } } +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] impl ViewOnlyAccount for Wallet { fn address(&self) -> &Bech32Address { self.address() @@ -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>, + ) -> Result> { + Ok(self + .get_spendable_resources(asset_id, amount, excluded_coins) + .await? + .into_iter() + .map(Input::resource_signed) + .collect::>()) + } } impl WalletUnlocked { @@ -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() @@ -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>, ) -> Result> { - Ok(self - .get_spendable_resources(asset_id, amount, excluded_coins) - .await? - .into_iter() - .map(Input::resource_signed) - .collect::>()) + self.wallet + .get_asset_inputs_for_amount(asset_id, amount, excluded_coins) + .await } +} +impl Account for WalletUnlocked { fn add_witnesses(&self, tb: &mut Tb) -> Result<()> { tb.add_signer(self.clone())?; From 278b2a4ff0ec0948967d1452818b29eba45771b2 Mon Sep 17 00:00:00 2001 From: hal3e Date: Wed, 6 Nov 2024 10:31:25 +0100 Subject: [PATCH 2/2] fix wasm --- wasm-tests/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wasm-tests/Cargo.toml b/wasm-tests/Cargo.toml index 4d13e5d1a7..0a360e28a1 100644 --- a/wasm-tests/Cargo.toml +++ b/wasm-tests/Cargo.toml @@ -16,4 +16,4 @@ crate-type = ['cdylib'] fuels = { workspace = true } fuels-core = { workspace = true } getrandom = { version = "0.2.11", features = ["js"] } -wasm-bindgen-test = "0.3.39" +wasm-bindgen-test = "0.3.45"