From 638a54847b9aa156fa352c1edeeaa2e05ce7720d Mon Sep 17 00:00:00 2001 From: iqdecay Date: Mon, 8 Jan 2024 11:04:01 +0100 Subject: [PATCH] refactor!: use `submit_and_await_commit` API (#1187) Closes #1180, #1128. This PR uses the correct API for sending a transaction and ensuring that we wait for the commit of the transaction before returning. This is needed because otherwise there might be a disconnect between submitting the transaction and awaiting for its commit, if it is done using the two separate APIs as before. BREAKING CHANGE: - `send_transaction_and_await_commit` function now returns a `TxStatus` instead of `TxId`. --------- Co-authored-by: MujkicA <32431923+MujkicA@users.noreply.github.com> Co-authored-by: hal3e --- packages/fuels-accounts/src/account.rs | 28 ++++++------- packages/fuels-accounts/src/provider.rs | 39 ++++++++++++------- .../src/provider/retryable_client.rs | 5 +++ packages/fuels-programs/src/contract.rs | 12 +++--- packages/fuels-programs/src/script_calls.rs | 3 +- packages/fuels/tests/predicates.rs | 8 ++-- packages/fuels/tests/providers.rs | 6 +-- 7 files changed, 57 insertions(+), 44 deletions(-) diff --git a/packages/fuels-accounts/src/account.rs b/packages/fuels-accounts/src/account.rs index 69509e3f74..1c0b1fceb1 100644 --- a/packages/fuels-accounts/src/account.rs +++ b/packages/fuels-accounts/src/account.rs @@ -16,7 +16,7 @@ use fuels_core::{ errors::{Error, Result}, input::Input, message::Message, - transaction::TxPolicies, + transaction::{Transaction, TxPolicies}, transaction_builders::{ BuildableTransaction, ScriptTransactionBuilder, TransactionBuilder, }, @@ -219,12 +219,11 @@ pub trait Account: ViewOnlyAccount { .await?; let tx = tx_builder.build(provider).await?; - let tx_id = provider.send_transaction_and_await_commit(tx).await?; + let tx_id = tx.id(provider.chain_id()); - let receipts = provider - .tx_status(&tx_id) - .await? - .take_receipts_checked(None)?; + let tx_status = provider.send_transaction_and_await_commit(tx).await?; + + let receipts = tx_status.take_receipts_checked(None)?; Ok((tx_id, receipts)) } @@ -279,12 +278,10 @@ pub trait Account: ViewOnlyAccount { self.adjust_for_fee(&mut tb, balance).await?; let tx = tb.build(provider).await?; - let tx_id = provider.send_transaction_and_await_commit(tx).await?; + let tx_id = tx.id(provider.chain_id()); + let tx_status = provider.send_transaction_and_await_commit(tx).await?; - let receipts = provider - .tx_status(&tx_id) - .await? - .take_receipts_checked(None)?; + let receipts = tx_status.take_receipts_checked(None)?; Ok((tx_id.to_string(), receipts)) } @@ -314,12 +311,11 @@ pub trait Account: ViewOnlyAccount { self.add_witnessses(&mut tb); self.adjust_for_fee(&mut tb, amount).await?; let tx = tb.build(provider).await?; - let tx_id = provider.send_transaction_and_await_commit(tx).await?; - let receipts = provider - .tx_status(&tx_id) - .await? - .take_receipts_checked(None)?; + let tx_id = tx.id(provider.chain_id()); + let tx_status = provider.send_transaction_and_await_commit(tx).await?; + + let receipts = tx_status.take_receipts_checked(None)?; let nonce = extract_message_nonce(&receipts) .expect("MessageId could not be retrieved from tx receipts."); diff --git a/packages/fuels-accounts/src/provider.rs b/packages/fuels-accounts/src/provider.rs index 88413c67a7..8262bf8026 100644 --- a/packages/fuels-accounts/src/provider.rs +++ b/packages/fuels-accounts/src/provider.rs @@ -8,8 +8,6 @@ mod supported_versions; use std::sync::Arc; use chrono::{DateTime, Utc}; -#[cfg(feature = "coin-cache")] -use fuel_core_client::client::types::TransactionStatus; use fuel_core_client::client::{ pagination::{PageDirection, PaginatedResult, PaginationRequest}, types::{balance::Balance, contract::ContractBalance}, @@ -197,24 +195,29 @@ impl Provider { } /// Sends a transaction to the underlying Provider's client. - pub async fn send_transaction_and_await_commit(&self, tx: T) -> Result { - let tx_id = self.send_transaction(tx.clone()).await?; - let _status = self.client.await_transaction_commit(&tx_id).await?; + pub async fn send_transaction_and_await_commit( + &self, + mut tx: T, + ) -> Result { + self.prepare_transaction_for_sending(&mut tx).await?; + let tx_status = self + .client + .submit_and_await_commit(&tx.clone().into()) + .await? + .into(); #[cfg(feature = "coin-cache")] - { - if matches!( - _status, - TransactionStatus::SqueezedOut { .. } | TransactionStatus::Failure { .. } - ) { - self.cache.lock().await.remove_items(tx.used_coins()) - } + if matches!( + tx_status, + TxStatus::SqueezedOut { .. } | TxStatus::Revert { .. } + ) { + self.cache.lock().await.remove_items(tx.used_coins()) } - Ok(tx_id) + Ok(tx_status) } - pub async fn send_transaction(&self, mut tx: T) -> Result { + async fn prepare_transaction_for_sending(&self, tx: &mut T) -> Result<()> { tx.precompute(&self.chain_id())?; let chain_info = self.chain_info().await?; @@ -228,10 +231,18 @@ impl Provider { } self.validate_transaction(tx.clone()).await?; + Ok(()) + } + pub async fn send_transaction(&self, mut tx: T) -> Result { + self.prepare_transaction_for_sending(&mut tx).await?; self.submit(tx).await } + pub async fn await_transaction_commit(&self, id: TxId) -> Result { + Ok(self.client.await_transaction_commit(&id).await?.into()) + } + async fn validate_transaction(&self, tx: T) -> Result<()> { let tolerance = 0.0; let TransactionCost { diff --git a/packages/fuels-accounts/src/provider/retryable_client.rs b/packages/fuels-accounts/src/provider/retryable_client.rs index 4c9c7ee1cb..450652fb14 100644 --- a/packages/fuels-accounts/src/provider/retryable_client.rs +++ b/packages/fuels-accounts/src/provider/retryable_client.rs @@ -63,6 +63,11 @@ impl RetryableClient { .await } + pub async fn submit_and_await_commit(&self, tx: &Transaction) -> io::Result { + self.our_retry(|| self.client.submit_and_await_commit(tx)) + .await + } + pub async fn submit(&self, tx: &Transaction) -> io::Result { self.our_retry(|| self.client.submit(tx)).await } diff --git a/packages/fuels-programs/src/contract.rs b/packages/fuels-programs/src/contract.rs index b6d8d65246..5dad738bc3 100644 --- a/packages/fuels-programs/src/contract.rs +++ b/packages/fuels-programs/src/contract.rs @@ -317,8 +317,10 @@ impl Contract { let provider = account.try_provider()?; - let tx_id = provider.send_transaction_and_await_commit(tx).await?; - provider.tx_status(&tx_id).await?.check(None)?; + provider + .send_transaction_and_await_commit(tx) + .await? + .check(None)?; Ok(self.contract_id.into()) } @@ -629,8 +631,7 @@ where let tx_status = if simulate { provider.checked_dry_run(tx).await? } else { - let tx_id = provider.send_transaction_and_await_commit(tx).await?; - provider.tx_status(&tx_id).await? + provider.send_transaction_and_await_commit(tx).await? }; let receipts = tx_status.take_receipts_checked(Some(&self.log_decoder))?; @@ -935,8 +936,7 @@ impl MultiContractCallHandler { let tx_status = if simulate { provider.checked_dry_run(tx).await? } else { - let tx_id = provider.send_transaction_and_await_commit(tx).await?; - provider.tx_status(&tx_id).await? + provider.send_transaction_and_await_commit(tx).await? }; let receipts = tx_status.take_receipts_checked(Some(&self.log_decoder))?; diff --git a/packages/fuels-programs/src/script_calls.rs b/packages/fuels-programs/src/script_calls.rs index 6e8a415949..97f2aa490a 100644 --- a/packages/fuels-programs/src/script_calls.rs +++ b/packages/fuels-programs/src/script_calls.rs @@ -233,8 +233,7 @@ where let tx_status = if simulate { self.provider.checked_dry_run(tx).await? } else { - let tx_id = self.provider.send_transaction_and_await_commit(tx).await?; - self.provider.tx_status(&tx_id).await? + self.provider.send_transaction_and_await_commit(tx).await? }; let receipts = tx_status.take_receipts_checked(Some(&self.log_decoder))?; diff --git a/packages/fuels/tests/predicates.rs b/packages/fuels/tests/predicates.rs index 05a87d7932..209128c8b2 100644 --- a/packages/fuels/tests/predicates.rs +++ b/packages/fuels/tests/predicates.rs @@ -749,8 +749,10 @@ async fn predicate_transfer_non_base_asset() -> Result<()> { wallet.adjust_for_fee(&mut tb, 0).await?; let tx = tb.build(&provider).await?; - let tx_id = provider.send_transaction_and_await_commit(tx).await?; - provider.tx_status(&tx_id).await?.check(None)?; + provider + .send_transaction_and_await_commit(tx) + .await? + .check(None)?; let wallet_balance = wallet.get_asset_balance(&non_base_asset_id).await?; @@ -871,7 +873,7 @@ async fn tx_id_not_changed_after_adding_witnesses() -> Result<()> { tx.append_witness(witness2.into())?; let tx_id_after_witnesses = tx.id(provider.chain_id()); - let tx_id_from_provider = provider.send_transaction_and_await_commit(tx).await?; + let tx_id_from_provider = provider.send_transaction(tx).await?; assert_eq!(tx_id, tx_id_after_witnesses); assert_eq!(tx_id, tx_id_from_provider); diff --git a/packages/fuels/tests/providers.rs b/packages/fuels/tests/providers.rs index d9fdc266fd..3eb8340ea3 100644 --- a/packages/fuels/tests/providers.rs +++ b/packages/fuels/tests/providers.rs @@ -909,9 +909,9 @@ async fn test_cache_invalidation_on_await() -> Result<()> { tokio::time::pause(); // tx inputs should be cached and then invalidated due to the tx failing - let tx_id = provider.send_transaction_and_await_commit(tx).await?; - let status = provider.tx_status(&tx_id).await?; - assert!(matches!(status, TxStatus::Revert { .. })); + let tx_status = provider.send_transaction_and_await_commit(tx).await?; + + assert!(matches!(tx_status, TxStatus::Revert { .. })); let coins = wallet.get_spendable_resources(BASE_ASSET_ID, 1).await?; assert_eq!(coins.len(), 1);