From 6be7e79d94cc9981ab1557e50297e65ba3329d2f Mon Sep 17 00:00:00 2001 From: Oleksii Filonenko Date: Mon, 10 Apr 2023 15:50:18 +0300 Subject: [PATCH 1/6] refactor: cache tx id in call handler --- packages/fuels-programs/src/call_response.rs | 11 +++++++++-- packages/fuels-programs/src/contract.rs | 20 ++++++++++++++------ packages/fuels-programs/src/script_calls.rs | 12 ++++++++---- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/packages/fuels-programs/src/call_response.rs b/packages/fuels-programs/src/call_response.rs index 9ee2e9de92..4e5e9d8aeb 100644 --- a/packages/fuels-programs/src/call_response.rs +++ b/packages/fuels-programs/src/call_response.rs @@ -1,4 +1,4 @@ -use fuel_tx::Receipt; +use fuel_tx::{Bytes32, Receipt}; use fuels_types::{ errors::Result, traits::{Parameterize, Tokenizable}, @@ -18,6 +18,7 @@ pub struct FuelCallResponse { pub receipts: Vec, pub gas_used: u64, pub log_decoder: LogDecoder, + pub tx_id: Option, } // ANCHOR_END: fuel_call_response @@ -32,12 +33,18 @@ impl FuelCallResponse { .expect("could not retrieve gas used from ScriptResult") } - pub fn new(value: D, receipts: Vec, log_decoder: LogDecoder) -> Self { + pub fn new( + value: D, + receipts: Vec, + log_decoder: LogDecoder, + tx_id: Option, + ) -> Self { Self { value, gas_used: Self::get_gas_used(&receipts), receipts, log_decoder, + tx_id, } } diff --git a/packages/fuels-programs/src/contract.rs b/packages/fuels-programs/src/contract.rs index 5a4ccac989..f5e700763a 100644 --- a/packages/fuels-programs/src/contract.rs +++ b/packages/fuels-programs/src/contract.rs @@ -507,6 +507,7 @@ fn extract_vec_data<'a>( pub struct ContractCallHandler { pub contract_call: ContractCall, pub tx_parameters: TxParameters, + cached_tx_id: Option, pub account: T, pub datatype: PhantomData, pub log_decoder: LogDecoder, @@ -659,7 +660,7 @@ where } /// Call a contract's method on the node, in a state-modifying manner. - pub async fn call(self) -> Result> { + pub async fn call(mut self) -> Result> { self.call_or_simulate(false) .await .map_err(|err| map_revert_error(err, &self.log_decoder)) @@ -668,14 +669,15 @@ where /// Call a contract's method on the node, in a simulated manner, meaning the state of the /// blockchain is *not* modified but simulated. /// - pub async fn simulate(&self) -> Result> { + pub async fn simulate(&mut self) -> Result> { self.call_or_simulate(true) .await .map_err(|err| map_revert_error(err, &self.log_decoder)) } - async fn call_or_simulate(&self, simulate: bool) -> Result> { + async fn call_or_simulate(&mut self, simulate: bool) -> Result> { let tx = self.build_tx().await?; + self.cached_tx_id = Some(tx.id()); let provider = self.account.try_provider()?; let receipts = if simulate { @@ -752,6 +754,7 @@ where D::from_token(token)?, receipts, self.log_decoder.clone(), + self.cached_tx_id, )) } } @@ -808,6 +811,7 @@ pub fn method_hash( Ok(ContractCallHandler { contract_call, tx_parameters, + cached_tx_id: None, account, datatype: PhantomData, log_decoder, @@ -842,6 +846,7 @@ pub struct MultiContractCallHandler { pub contract_calls: Vec, pub log_decoder: LogDecoder, pub tx_parameters: TxParameters, + cached_tx_id: Option, pub account: T, } @@ -850,6 +855,7 @@ impl MultiContractCallHandler { Self { contract_calls: vec![], tx_parameters: TxParameters::default(), + cached_tx_id: None, account, log_decoder: LogDecoder { log_formatters: Default::default(), @@ -885,7 +891,7 @@ impl MultiContractCallHandler { } /// Call contract methods on the node, in a state-modifying manner. - pub async fn call(&self) -> Result> { + pub async fn call(&mut self) -> Result> { self.call_or_simulate(false) .await .map_err(|err| map_revert_error(err, &self.log_decoder)) @@ -896,18 +902,19 @@ impl MultiContractCallHandler { /// It is the same as the [call] method because the API is more user-friendly this way. /// /// [call]: Self::call - pub async fn simulate(&self) -> Result> { + pub async fn simulate(&mut self) -> Result> { self.call_or_simulate(true) .await .map_err(|err| map_revert_error(err, &self.log_decoder)) } async fn call_or_simulate( - &self, + &mut self, simulate: bool, ) -> Result> { let provider = self.account.try_provider()?; let tx = self.build_tx().await?; + self.cached_tx_id = Some(tx.id()); let receipts = if simulate { provider.checked_dry_run(&tx).await? @@ -1015,6 +1022,7 @@ impl MultiContractCallHandler { D::from_token(tokens_as_tuple)?, receipts, self.log_decoder.clone(), + self.cached_tx_id, ); Ok(response) diff --git a/packages/fuels-programs/src/script_calls.rs b/packages/fuels-programs/src/script_calls.rs index 4b35f138a7..b3ad56fc59 100644 --- a/packages/fuels-programs/src/script_calls.rs +++ b/packages/fuels-programs/src/script_calls.rs @@ -1,6 +1,6 @@ use std::{collections::HashSet, fmt::Debug, marker::PhantomData}; -use fuel_tx::{ContractId, Output, Receipt}; +use fuel_tx::{Bytes32, ContractId, Output, Receipt}; use fuel_types::bytes::padded_len_usize; use fuels_accounts::{provider::Provider, Account}; use fuels_types::{ @@ -57,6 +57,7 @@ impl ScriptCall { pub struct ScriptCallHandler { pub script_call: ScriptCall, pub tx_parameters: TxParameters, + cached_tx_id: Option, pub account: T, pub provider: Provider, pub datatype: PhantomData, @@ -84,6 +85,7 @@ where Self { script_call, tx_parameters: TxParameters::default(), + cached_tx_id: None, account, provider, datatype: PhantomData, @@ -172,10 +174,11 @@ where /// in its `value` field as an actual typed value `D` (if your method returns `bool`, /// it will be a bool, works also for structs thanks to the `abigen!()`). /// The other field of [`FuelCallResponse`], `receipts`, contains the receipts of the transaction. - async fn call_or_simulate(&self, simulate: bool) -> Result> { + async fn call_or_simulate(&mut self, simulate: bool) -> Result> { let chain_info = self.provider.chain_info().await?; let tb = self.prepare_builder().await?; let tx = self.account.add_fee_resources(tb, 0, None).await?; + self.cached_tx_id = Some(tx.id()); tx.check_without_signatures( chain_info.latest_block.header.height, @@ -191,7 +194,7 @@ where } /// Call a script on the node, in a state-modifying manner. - pub async fn call(self) -> Result> { + pub async fn call(mut self) -> Result> { self.call_or_simulate(false) .await .map_err(|err| map_revert_error(err, &self.log_decoder)) @@ -202,7 +205,7 @@ where /// It is the same as the [`call`] method because the API is more user-friendly this way. /// /// [`call`]: Self::call - pub async fn simulate(self) -> Result> { + pub async fn simulate(mut self) -> Result> { self.call_or_simulate(true) .await .map_err(|err| map_revert_error(err, &self.log_decoder)) @@ -215,6 +218,7 @@ where D::from_token(token)?, receipts, self.log_decoder.clone(), + self.cached_tx_id, )) } } From df3ce957d45c2d7dc7aaf349d23d4d1f36509265 Mon Sep 17 00:00:00 2001 From: Oleksii Filonenko Date: Mon, 8 May 2023 13:23:55 +0300 Subject: [PATCH 2/6] refactor: add docs and (kinda) tests --- packages/fuels-programs/src/contract.rs | 2 ++ packages/fuels-programs/src/script_calls.rs | 1 + packages/fuels/tests/scripts.rs | 17 +++++------------ 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/packages/fuels-programs/src/contract.rs b/packages/fuels-programs/src/contract.rs index f5e700763a..1cbf72bc52 100644 --- a/packages/fuels-programs/src/contract.rs +++ b/packages/fuels-programs/src/contract.rs @@ -507,6 +507,7 @@ fn extract_vec_data<'a>( pub struct ContractCallHandler { pub contract_call: ContractCall, pub tx_parameters: TxParameters, + /// Initially `None`, this gets set after the transaction is submitted cached_tx_id: Option, pub account: T, pub datatype: PhantomData, @@ -846,6 +847,7 @@ pub struct MultiContractCallHandler { pub contract_calls: Vec, pub log_decoder: LogDecoder, pub tx_parameters: TxParameters, + /// Initially `None`, this gets set after the transaction is submitted cached_tx_id: Option, pub account: T, } diff --git a/packages/fuels-programs/src/script_calls.rs b/packages/fuels-programs/src/script_calls.rs index b3ad56fc59..cedba099b8 100644 --- a/packages/fuels-programs/src/script_calls.rs +++ b/packages/fuels-programs/src/script_calls.rs @@ -57,6 +57,7 @@ impl ScriptCall { pub struct ScriptCallHandler { pub script_call: ScriptCall, pub tx_parameters: TxParameters, + /// Initially `None`, this gets set after the transaction is submitted cached_tx_id: Option, pub account: T, pub provider: Provider, diff --git a/packages/fuels/tests/scripts.rs b/packages/fuels/tests/scripts.rs index f7a43c5a8f..f497a3a575 100644 --- a/packages/fuels/tests/scripts.rs +++ b/packages/fuels/tests/scripts.rs @@ -17,11 +17,8 @@ async fn test_transaction_script_workflow() -> Result<()> { let call_handler = contract_instance.methods().initialize_counter(42); - let tx = call_handler.build_tx().await?; - let provider = wallet.try_provider()?; - let receipts = provider.send_transaction(&tx).await?; - - let response = call_handler.get_response(receipts)?; + let response = call_handler.call().await?; + assert!(response.tx_id.is_some()); assert_eq!(response.value, 42); Ok(()) } @@ -51,13 +48,9 @@ async fn test_multi_call_script_workflow() -> Result<()> { .add_call(call_handler_1) .add_call(call_handler_2); - let provider = wallet.try_provider()?; - let tx = multi_call_handler.build_tx().await?; - let receipts = provider.send_transaction(&tx).await?; - let (counter, array) = multi_call_handler - .get_response::<(u64, [u64; 2])>(receipts)? - .value; - + let response = multi_call_handler.call::<(u64, [u64; 2])>().await?; + assert!(response.tx_id.is_some()); + let (counter, array) = response.value; assert_eq!(counter, 42); assert_eq!(array, [42; 2]); Ok(()) From 78ddbf20f2cf54e6e6d7c03bca79cd191040d253 Mon Sep 17 00:00:00 2001 From: Oleksii Filonenko Date: Mon, 15 May 2023 16:34:39 +0300 Subject: [PATCH 3/6] docs: add FuelCallResponse.tx_id to book --- docs/src/calling-contracts/call-response.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/src/calling-contracts/call-response.md b/docs/src/calling-contracts/call-response.md index 02fa03b63e..794248f782 100644 --- a/docs/src/calling-contracts/call-response.md +++ b/docs/src/calling-contracts/call-response.md @@ -16,6 +16,7 @@ Where `value` will hold the value returned by its respective contract method, re - `receipts` will hold all [receipts](https://specs.fuel.network/master/protocol/abi/receipts.html) generated by that specific contract call. - `gas_used` is the amount of gas it consumed by the contract call. +- `tx_id` will hold the ID of the corresponding submitted transaction. ## Error handling From ed2ff7130428995bb0db9511d7ca1c2bdd5b9da2 Mon Sep 17 00:00:00 2001 From: Oleksii Filonenko Date: Mon, 15 May 2023 17:15:46 +0300 Subject: [PATCH 4/6] fix: update expected_gas_used --- packages/fuels/tests/contracts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index 2fba53d8f4..6bc4d79a6f 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -275,7 +275,7 @@ async fn test_contract_call_fee_estimation() -> Result<()> { let tolerance = 0.2; let expected_min_gas_price = 0; // This is the default min_gas_price from the ConsensusParameters - let expected_gas_used = 606; + let expected_gas_used = 714; let expected_metered_bytes_size = 720; let expected_total_fee = 368; From 5bed33f4f9e18f3f5e5d83b3019626b2a95be039 Mon Sep 17 00:00:00 2001 From: Oleksii Filonenko Date: Mon, 15 May 2023 17:45:27 +0300 Subject: [PATCH 5/6] Revert "fix: update expected_gas_used" This reverts commit ed2ff7130428995bb0db9511d7ca1c2bdd5b9da2. --- packages/fuels/tests/contracts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index 6bc4d79a6f..2fba53d8f4 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -275,7 +275,7 @@ async fn test_contract_call_fee_estimation() -> Result<()> { let tolerance = 0.2; let expected_min_gas_price = 0; // This is the default min_gas_price from the ConsensusParameters - let expected_gas_used = 714; + let expected_gas_used = 606; let expected_metered_bytes_size = 720; let expected_total_fee = 368; From 5460be3c30858411f0c1b4537ee388d71f2ac659 Mon Sep 17 00:00:00 2001 From: Oleksii Filonenko Date: Fri, 19 May 2023 13:58:47 +0300 Subject: [PATCH 6/6] Apply suggestions from code review Co-authored-by: iqdecay --- packages/fuels-programs/src/contract.rs | 4 ++-- packages/fuels-programs/src/script_calls.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/fuels-programs/src/contract.rs b/packages/fuels-programs/src/contract.rs index 2758c8b26c..6439547338 100644 --- a/packages/fuels-programs/src/contract.rs +++ b/packages/fuels-programs/src/contract.rs @@ -420,7 +420,7 @@ impl ContractCall { pub struct ContractCallHandler { pub contract_call: ContractCall, pub tx_parameters: TxParameters, - /// Initially `None`, this gets set after the transaction is submitted + // Initially `None`, gets set to the right tx id after the transaction is submitted cached_tx_id: Option, pub account: T, pub datatype: PhantomData, @@ -759,7 +759,7 @@ pub struct MultiContractCallHandler { pub contract_calls: Vec, pub log_decoder: LogDecoder, pub tx_parameters: TxParameters, - /// Initially `None`, this gets set after the transaction is submitted + // Initially `None`, gets set to the right tx id after the transaction is submitted cached_tx_id: Option, pub account: T, } diff --git a/packages/fuels-programs/src/script_calls.rs b/packages/fuels-programs/src/script_calls.rs index 544c97d044..5b28b5d90b 100644 --- a/packages/fuels-programs/src/script_calls.rs +++ b/packages/fuels-programs/src/script_calls.rs @@ -58,7 +58,7 @@ impl ScriptCall { pub struct ScriptCallHandler { pub script_call: ScriptCall, pub tx_parameters: TxParameters, - /// Initially `None`, this gets set after the transaction is submitted + // Initially `None`, gets set to the right tx id after the transaction is submitted cached_tx_id: Option, pub account: T, pub provider: Provider,