diff --git a/docs/src/calling-contracts/cost-estimation.md b/docs/src/calling-contracts/cost-estimation.md index 696cea4341..10eca39fa6 100644 --- a/docs/src/calling-contracts/cost-estimation.md +++ b/docs/src/calling-contracts/cost-estimation.md @@ -6,6 +6,8 @@ With the function `estimate_transaction_cost(tolerance: Option, block_horiz {{#include ../../../packages/fuels-accounts/src/provider.rs:transaction_cost}} ``` +> **Note** `script_gas` refers to the part of the gas spent on the script execution. + Below are examples that show how to get the estimated transaction cost from single and multi call transactions. ```rust,ignore diff --git a/e2e/tests/configurables.rs b/e2e/tests/configurables.rs index d9a002d56b..3bfb29997b 100644 --- a/e2e/tests/configurables.rs +++ b/e2e/tests/configurables.rs @@ -18,7 +18,8 @@ async fn contract_default_configurables() -> Result<()> { LoadConfiguration::default(), )? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_instance = MyContract::new(contract_id, wallet.clone()); @@ -130,7 +131,8 @@ async fn contract_configurables() -> Result<()> { LoadConfiguration::default().with_configurables(configurables), )? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_instance = MyContract::new(contract_id, wallet.clone()); // ANCHOR_END: contract_configurables @@ -198,7 +200,8 @@ async fn contract_manual_configurables() -> Result<()> { )? .with_configurables(configurables) .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_instance = MyContract::new(contract_id, wallet.clone()); diff --git a/e2e/tests/contracts.rs b/e2e/tests/contracts.rs index 7720701a02..187bf07d2a 100644 --- a/e2e/tests/contracts.rs +++ b/e2e/tests/contracts.rs @@ -292,7 +292,8 @@ async fn test_contract_call_fee_estimation() -> Result<()> { let gas_limit = 800; let tolerance = Some(0.2); let block_horizon = Some(1); - let expected_gas_used = 960; + let expected_script_gas = 800; + let expected_total_gas = 8463; let expected_metered_bytes_size = 824; let estimated_transaction_cost = contract_instance @@ -302,7 +303,8 @@ async fn test_contract_call_fee_estimation() -> Result<()> { .estimate_transaction_cost(tolerance, block_horizon) .await?; - assert_eq!(estimated_transaction_cost.gas_used, expected_gas_used); + assert_eq!(estimated_transaction_cost.script_gas, expected_script_gas); + assert_eq!(estimated_transaction_cost.total_gas, expected_total_gas); assert_eq!( estimated_transaction_cost.metered_bytes_size, expected_metered_bytes_size @@ -331,19 +333,20 @@ async fn contract_call_has_same_estimated_and_used_gas() -> Result<()> { let tolerance = Some(0.0); let block_horizon = Some(1); - let estimated_gas_used = contract_methods + let estimated_total_gas = contract_methods .initialize_counter(42) .estimate_transaction_cost(tolerance, block_horizon) .await? - .gas_used; + .total_gas; let gas_used = contract_methods .initialize_counter(42) .call() .await? - .gas_used; + .tx_status + .total_gas; - assert_eq!(estimated_gas_used, gas_used); + assert_eq!(estimated_total_gas, gas_used); Ok(()) } @@ -373,14 +376,19 @@ async fn mult_call_has_same_estimated_and_used_gas() -> Result<()> { let tolerance = Some(0.0); let block_horizon = Some(1); - let estimated_gas_used = multi_call_handler + let estimated_total_gas = multi_call_handler .estimate_transaction_cost(tolerance, block_horizon) .await? - .gas_used; + .total_gas; - let gas_used = multi_call_handler.call::<(u64, [u64; 2])>().await?.gas_used; + let total_gas = multi_call_handler + .call::<(u64, [u64; 2])>() + .await? + .tx_status + .total_gas; + + assert_eq!(estimated_total_gas, total_gas); - assert_eq!(estimated_gas_used, gas_used); Ok(()) } @@ -703,7 +711,8 @@ async fn setup_output_variable_estimation_test() -> Result<( LoadConfiguration::default(), )? .deploy_if_not_exists(&wallets[0], TxPolicies::default()) - .await?; + .await? + .contract_id; let mint_asset_id = contract_id.asset_id(&Bits256::zeroed()); let addresses = wallets @@ -1754,7 +1763,7 @@ async fn contract_custom_call_no_signatures_strategy() -> Result<()> { let tx_status = provider.tx_status(&tx_id).await?; - let response = call_handler.get_response_from(tx_status)?; + let response = call_handler.get_response(tx_status)?; assert_eq!(counter, response.value); @@ -1775,7 +1784,8 @@ async fn contract_encoder_config_is_applied() -> Result<()> { LoadConfiguration::default(), )? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let instance = TestContract::new(contract_id.clone(), wallet.clone()); @@ -1984,7 +1994,8 @@ async fn simulations_can_be_made_without_coins() -> Result<()> { LoadConfiguration::default(), )? .deploy_if_not_exists(wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let provider = wallet.provider().cloned(); let no_funds_wallet = WalletUnlocked::new_random(provider); @@ -2015,7 +2026,8 @@ async fn simulations_can_be_made_without_coins_multicall() -> Result<()> { LoadConfiguration::default(), )? .deploy_if_not_exists(wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let provider = wallet.provider().cloned(); let no_funds_wallet = WalletUnlocked::new_random(provider); @@ -2074,7 +2086,8 @@ async fn contract_call_with_non_zero_base_asset_id_and_tip() -> Result<()> { LoadConfiguration::default(), )? .deploy_if_not_exists(wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_instance = MyContract::new(contract_id, wallet.clone()); @@ -2250,7 +2263,8 @@ async fn blob_contract_deployment() -> Result<()> { let contract_id = contract .convert_to_loader(100_000)? .deploy_if_not_exists(&wallets[0], TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_instance = MyContract::new(contract_id, wallets[0].clone()); @@ -2277,7 +2291,8 @@ async fn regular_contract_can_be_deployed() -> Result<()> { // when let contract_id = Contract::load_from(contract_binary, LoadConfiguration::default())? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; // then let contract_instance = MyContract::new(contract_id, wallet); @@ -2309,7 +2324,8 @@ async fn unuploaded_loader_can_be_deployed_directly() -> Result<()> { let contract_id = Contract::load_from(contract_binary, LoadConfiguration::default())? .convert_to_loader(1024)? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_instance = MyContract::new(contract_id, wallet); @@ -2342,13 +2358,15 @@ async fn unuploaded_loader_can_upload_blobs_separately_then_deploy() -> Result<( // if this were an example for the user we'd just call `deploy` on the contract above // this way we are testing that the blobs were really deployed above, otherwise the following // would fail + let contract_id = Contract::loader_from_blob_ids( blob_ids.to_vec(), contract.salt(), contract.storage_slots().to_vec(), )? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_instance = MyContract::new(contract_id, wallet); let response = contract_instance.methods().something().call().await?.value; @@ -2380,7 +2398,8 @@ async fn loader_blob_already_uploaded_not_an_issue() -> Result<()> { // this will try to upload the blobs but skip upon encountering an error let contract_id = contract .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_instance = MyContract::new(contract_id, wallet); let response = contract_instance.methods().something().call().await?.value; @@ -2411,13 +2430,15 @@ async fn loader_works_via_proxy() -> Result<()> { let contract_id = contract .convert_to_loader(100)? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_binary = "sway/contracts/proxy/out/release/proxy.bin"; let proxy_id = Contract::load_from(contract_binary, LoadConfiguration::default())? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let proxy = MyProxy::new(proxy_id, wallet.clone()); proxy @@ -2462,7 +2483,8 @@ async fn loader_storage_works_via_proxy() -> Result<()> { let contract_id = contract .convert_to_loader(100)? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_binary = "sway/contracts/proxy/out/release/proxy.bin"; let proxy_contract = Contract::load_from(contract_binary, LoadConfiguration::default())?; @@ -2472,7 +2494,8 @@ async fn loader_storage_works_via_proxy() -> Result<()> { let proxy_id = proxy_contract .with_storage_slots(combined_storage_slots) .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let proxy = MyProxy::new(proxy_id, wallet.clone()); proxy diff --git a/e2e/tests/logs.rs b/e2e/tests/logs.rs index 664333c0a9..676b674fb0 100644 --- a/e2e/tests/logs.rs +++ b/e2e/tests/logs.rs @@ -387,7 +387,8 @@ async fn test_multi_call_contract_with_contract_logs() -> Result<()> { LoadConfiguration::default(), )? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_instance = MyContract::new(contract_id.clone(), wallet.clone()); @@ -742,7 +743,8 @@ async fn test_contract_with_contract_logs() -> Result<()> { LoadConfiguration::default(), )? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_instance = MyContract::new(contract_id.clone(), wallet.clone()); @@ -828,6 +830,7 @@ async fn test_script_logs_with_contract_logs() -> Result<()> { { let num_contract_logs = response + .tx_status .receipts .iter() .filter(|receipt| matches!(receipt, Receipt::LogData { id, .. } | Receipt::Log { id, .. } if *id == contract_id)) @@ -1025,7 +1028,8 @@ async fn test_contract_require_from_contract() -> Result<()> { LoadConfiguration::default(), )? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_instance = MyContract::new(contract_id.clone(), wallet.clone()); @@ -1079,7 +1083,8 @@ async fn test_multi_call_contract_require_from_contract() -> Result<()> { LoadConfiguration::default(), )? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let lib_contract_instance = MyContract::new(contract_id.clone(), wallet.clone()); @@ -1169,7 +1174,8 @@ async fn test_loader_script_require_from_loader_contract() -> Result<()> { let contract_id = contract .convert_to_loader(100_000)? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_instance = MyContract::new(contract_id, wallet); let mut script_instance = script_instance; diff --git a/e2e/tests/predicates.rs b/e2e/tests/predicates.rs index e68b994e48..3c11e72c9b 100644 --- a/e2e/tests/predicates.rs +++ b/e2e/tests/predicates.rs @@ -115,7 +115,7 @@ async fn transfer_coins_and_messages_to_predicate() -> Result<()> { let num_coins = 16; let num_messages = 32; let amount = 64; - let total_balance = (num_coins + num_messages) * amount; + let balance_to_send = 42; let mut wallet = WalletUnlocked::new_random(None); @@ -130,25 +130,18 @@ async fn transfer_coins_and_messages_to_predicate() -> Result<()> { Predicate::load_from("sway/predicates/basic_predicate/out/release/basic_predicate.bin")? .with_provider(provider.clone()); - // TODO: https://github.com/FuelLabs/fuels-rs/issues/1394 - let expected_fee = 1; wallet .transfer( predicate.address(), - total_balance - expected_fee, + balance_to_send, asset_id, TxPolicies::default(), ) .await?; // The predicate has received the funds - assert_address_balance( - predicate.address(), - &provider, - asset_id, - total_balance - expected_fee, - ) - .await; + assert_address_balance(predicate.address(), &provider, asset_id, balance_to_send).await; + Ok(()) } @@ -173,26 +166,34 @@ async fn spend_predicate_coins_messages_basic() -> Result<()> { predicate.set_provider(provider.clone()); - // TODO: https://github.com/FuelLabs/fuels-rs/issues/1394 - let expected_fee = 1; - predicate + let amount_to_send = 128; + let fee = predicate .transfer( receiver.address(), - predicate_balance - expected_fee, + amount_to_send, asset_id, TxPolicies::default(), ) - .await?; + .await? + .tx_status + .total_fee; // The predicate has spent the funds - assert_address_balance(predicate.address(), &provider, asset_id, 0).await; + let predicate_current_balance = predicate_balance - amount_to_send - fee; + assert_address_balance( + predicate.address(), + &provider, + asset_id, + predicate_current_balance, + ) + .await; // Funds were transferred assert_address_balance( receiver.address(), &provider, asset_id, - receiver_balance + predicate_balance - expected_fee, + receiver_balance + amount_to_send, ) .await; @@ -221,47 +222,41 @@ async fn pay_with_predicate() -> Result<()> { let num_coins = 4; let num_messages = 8; let amount = 16; - let (provider, _predicate_balance, _receiver, _receiver_balance, _asset_id, _) = + let (provider, predicate_balance, _receiver, _receiver_balance, _asset_id, _) = setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?; predicate.set_provider(provider.clone()); - let contract_id = Contract::load_from( + let deploy_response = Contract::load_from( "sway/contracts/contract_test/out/release/contract_test.bin", LoadConfiguration::default(), )? .deploy_if_not_exists(&predicate, TxPolicies::default()) .await?; - let contract_methods = MyContract::new(contract_id.clone(), predicate.clone()).methods(); - let tx_policies = TxPolicies::default() - .with_tip(1) - .with_script_gas_limit(1_000_000); + let contract_methods = + MyContract::new(deploy_response.contract_id.clone(), predicate.clone()).methods(); - // TODO: https://github.com/FuelLabs/fuels-rs/issues/1394 - let expected_fee = 1; let consensus_parameters = provider.consensus_parameters().await?; + let deploy_fee = deploy_response.tx_status.unwrap().total_fee; assert_eq!( predicate .get_asset_balance(consensus_parameters.base_asset_id()) .await?, - 192 - expected_fee + predicate_balance - deploy_fee ); let response = contract_methods .initialize_counter(42) // Build the ABI call - .with_tx_policies(tx_policies) .call() .await?; assert_eq!(42, response.value); - // TODO: https://github.com/FuelLabs/fuels-rs/issues/1394 - let expected_fee = 2; assert_eq!( predicate .get_asset_balance(consensus_parameters.base_asset_id()) .await?, - 191 - expected_fee + predicate_balance - deploy_fee - response.tx_status.total_fee ); Ok(()) @@ -291,47 +286,38 @@ async fn pay_with_predicate_vector_data() -> Result<()> { let num_coins = 4; let num_messages = 8; let amount = 16; - let (provider, _predicate_balance, _receiver, _receiver_balance, _asset_id, _) = + let (provider, predicate_balance, _receiver, _receiver_balance, _asset_id, _) = setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?; predicate.set_provider(provider.clone()); - let contract_id = Contract::load_from( + let deploy_response = Contract::load_from( "sway/contracts/contract_test/out/release/contract_test.bin", LoadConfiguration::default(), )? .deploy_if_not_exists(&predicate, TxPolicies::default()) .await?; - let contract_methods = MyContract::new(contract_id.clone(), predicate.clone()).methods(); - let tx_policies = TxPolicies::default() - .with_tip(1) - .with_script_gas_limit(1_000_000); + let contract_methods = + MyContract::new(deploy_response.contract_id.clone(), predicate.clone()).methods(); - // TODO: https://github.com/FuelLabs/fuels-rs/issues/1394 - let expected_fee = 1; let consensus_parameters = provider.consensus_parameters().await?; + let deploy_fee = deploy_response.tx_status.unwrap().total_fee; assert_eq!( predicate .get_asset_balance(consensus_parameters.base_asset_id()) .await?, - 192 - expected_fee + predicate_balance - deploy_fee ); - let response = contract_methods - .initialize_counter(42) - .with_tx_policies(tx_policies) - .call() - .await?; + let response = contract_methods.initialize_counter(42).call().await?; - // TODO: https://github.com/FuelLabs/fuels-rs/issues/1394 - let expected_fee = 2; assert_eq!(42, response.value); assert_eq!( predicate .get_asset_balance(consensus_parameters.base_asset_id()) .await?, - 191 - expected_fee + predicate_balance - deploy_fee - response.tx_status.total_fee ); Ok(()) @@ -364,7 +350,8 @@ async fn predicate_contract_transfer() -> Result<()> { LoadConfiguration::default(), )? .deploy_if_not_exists(&predicate, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_balances = provider.get_contract_balances(&contract_id).await?; assert!(contract_balances.is_empty()); @@ -420,7 +407,7 @@ async fn predicate_transfer_to_base_layer() -> Result<()> { Address::from_str("0x4710162c2e3a95a6faff05139150017c9e38e5e280432d546fae345d6ce6d8fe")?; let base_layer_address = Bech32Address::from(base_layer_address); - let (tx_id, msg_nonce, _receipts) = predicate + let withdraw_response = predicate .withdraw_to_base_layer(&base_layer_address, amount, TxPolicies::default()) .await?; @@ -429,7 +416,12 @@ async fn predicate_transfer_to_base_layer() -> Result<()> { let proof = predicate .try_provider()? - .get_message_proof(&tx_id, &msg_nonce, None, Some(2)) + .get_message_proof( + &withdraw_response.tx_id, + &withdraw_response.nonce, + None, + Some(2), + ) .await?; assert_eq!(proof.amount, amount); @@ -500,15 +492,13 @@ async fn predicate_transfer_with_signed_resources() -> Result<()> { let tx = tb.build(&provider).await?; - provider.send_transaction_and_await_commit(tx).await?; + let tx_status = provider.send_transaction_and_await_commit(tx).await?; - // TODO: https://github.com/FuelLabs/fuels-rs/issues/1394 - let expected_fee = 1; assert_address_balance( predicate.address(), &provider, asset_id, - predicate_balance + wallet_balance - expected_fee, + predicate_balance + wallet_balance - tx_status.total_fee(), ) .await; @@ -542,20 +532,20 @@ async fn contract_tx_and_call_params_with_predicate() -> Result<()> { let num_coins = 1; let num_messages = 1; let amount = 1000; - let (provider, _predicate_balance, _receiver, _receiver_balance, _asset_id, _) = + let (provider, predicate_balance, _receiver, _receiver_balance, _asset_id, _) = setup_predicate_test(predicate.address(), num_coins, num_messages, amount).await?; predicate.set_provider(provider.clone()); - let contract_id = Contract::load_from( + let deploy_response = Contract::load_from( "./sway/contracts/contract_test/out/release/contract_test.bin", LoadConfiguration::default(), )? .deploy_if_not_exists(&predicate, TxPolicies::default()) .await?; - println!("Contract deployed @ {contract_id}"); - let contract_methods = MyContract::new(contract_id.clone(), predicate.clone()).methods(); + let contract_methods = + MyContract::new(deploy_response.contract_id.clone(), predicate.clone()).methods(); let tx_policies = TxPolicies::default().with_tip(100); @@ -565,18 +555,18 @@ async fn contract_tx_and_call_params_with_predicate() -> Result<()> { .with_asset_id(AssetId::zeroed()); { - let response = contract_methods + let call_response = contract_methods .get_msg_amount() .with_tx_policies(tx_policies) .call_params(call_params.clone())? .call() .await?; - // TODO: https://github.com/FuelLabs/fuels-rs/issues/1394 - let expected_fee = 2; + let deploy_fee = deploy_response.tx_status.unwrap().total_fee; + let call_fee = call_response.tx_status.total_fee; assert_eq!( predicate.get_asset_balance(&AssetId::zeroed()).await?, - 1800 - expected_fee + predicate_balance - deploy_fee - call_params_amount - call_fee ); } { @@ -632,7 +622,8 @@ async fn diff_asset_predicate_payment() -> Result<()> { LoadConfiguration::default(), )? .deploy_if_not_exists(&predicate, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_methods = MyContract::new(contract_id.clone(), predicate.clone()).methods(); @@ -684,12 +675,11 @@ async fn predicate_default_configurables() -> Result<()> { predicate.set_provider(provider.clone()); - // TODO: https://github.com/FuelLabs/fuels-rs/issues/1394 - let expected_fee = 1; + let amount_to_send = predicate_balance - 1; predicate .transfer( receiver.address(), - predicate_balance - expected_fee, + amount_to_send, asset_id, TxPolicies::default(), ) @@ -703,7 +693,7 @@ async fn predicate_default_configurables() -> Result<()> { receiver.address(), &provider, asset_id, - receiver_balance + predicate_balance - expected_fee, + receiver_balance + amount_to_send, ) .await; @@ -751,16 +741,17 @@ async fn predicate_configurables() -> Result<()> { predicate.set_provider(provider.clone()); - // TODO: https://github.com/FuelLabs/fuels-rs/issues/1394 - let expected_fee = 1; - predicate + let amount_to_send = predicate_balance - 1; + let fee = predicate .transfer( receiver.address(), - predicate_balance - expected_fee, + amount_to_send, asset_id, TxPolicies::default(), ) - .await?; + .await? + .tx_status + .total_fee; // The predicate has spent the funds assert_address_balance(predicate.address(), &provider, asset_id, 0).await; @@ -770,7 +761,7 @@ async fn predicate_configurables() -> Result<()> { receiver.address(), &provider, asset_id, - receiver_balance + predicate_balance - expected_fee, + receiver_balance + predicate_balance - fee, ) .await; @@ -927,16 +918,15 @@ async fn predicate_can_access_manually_added_witnesses() -> Result<()> { tx.append_witness(witness.into())?; tx.append_witness(witness2.into())?; - provider.send_transaction_and_await_commit(tx).await?; + let tx_status = provider.send_transaction_and_await_commit(tx).await?; - // TODO: https://github.com/FuelLabs/fuels-rs/issues/1394 - let expected_fee = 1; + let fee = tx_status.total_fee(); // The predicate has spent the funds assert_address_balance( predicate.address(), &provider, asset_id, - predicate_balance - amount_to_send - expected_fee, + predicate_balance - amount_to_send - fee, ) .await; @@ -1218,14 +1208,16 @@ async fn predicate_configurables_in_blobs() -> Result<()> { predicate.set_provider(provider.clone()); - loader.upload_blob(extra_wallet).await?; + loader + .upload_blob(extra_wallet) + .await? + .expect("has tx_status"); - // TODO: https://github.com/FuelLabs/fuels-rs/issues/1394 - let expected_fee = 1; + let amount_to_send = predicate_balance - 1; predicate .transfer( receiver.address(), - predicate_balance - expected_fee, + amount_to_send, asset_id, TxPolicies::default(), ) @@ -1239,7 +1231,7 @@ async fn predicate_configurables_in_blobs() -> Result<()> { receiver.address(), &provider, asset_id, - receiver_balance + predicate_balance - expected_fee, + receiver_balance + amount_to_send, ) .await; diff --git a/e2e/tests/providers.rs b/e2e/tests/providers.rs index 9906c1d4ee..6663588b4d 100644 --- a/e2e/tests/providers.rs +++ b/e2e/tests/providers.rs @@ -12,7 +12,7 @@ use fuels::{ coin_type::CoinType, message::Message, transaction_builders::{BuildableTransaction, ScriptTransactionBuilder}, - tx_status::TxStatus, + tx_status::{Success, TxStatus}, Bits256, }, }; @@ -40,7 +40,8 @@ async fn test_provider_launch_and_connect() -> Result<()> { LoadConfiguration::default(), )? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_instance_connected = MyContract::new(contract_id.clone(), wallet.clone()); @@ -176,27 +177,27 @@ async fn test_input_message_pays_fee() -> Result<()> { abi = "e2e/sway/contracts/contract_test/out/release/contract_test-abi.json" )); - let contract_id = Contract::load_from( + let deploy_response = Contract::load_from( "sway/contracts/contract_test/out/release/contract_test.bin", LoadConfiguration::default(), )? .deploy_if_not_exists(&wallet, TxPolicies::default()) .await?; - let contract_instance = MyContract::new(contract_id, wallet.clone()); + let contract_instance = MyContract::new(deploy_response.contract_id, wallet.clone()); - let response = contract_instance + let call_response = contract_instance .methods() .initialize_counter(42) .call() .await?; - assert_eq!(42, response.value); + assert_eq!(42, call_response.value); let balance = wallet.get_asset_balance(base_asset_id).await?; - // TODO: https://github.com/FuelLabs/fuels-rs/issues/1394 - let expected_fee = 2; - assert_eq!(balance, DEFAULT_COIN_AMOUNT - expected_fee); + let deploy_fee = deploy_response.tx_status.unwrap().total_fee; + let call_fee = call_response.tx_status.total_fee; + assert_eq!(balance, DEFAULT_COIN_AMOUNT - deploy_fee - call_fee); Ok(()) } @@ -263,6 +264,7 @@ async fn can_set_custom_block_time() -> Result<()> { assert_eq!(blocks[1].header.time.unwrap().timestamp(), 20); assert_eq!(blocks[2].header.time.unwrap().timestamp(), 40); assert_eq!(blocks[3].header.time.unwrap().timestamp(), 60); + Ok(()) } @@ -359,6 +361,7 @@ async fn test_gas_forwarded_defaults_to_tx_limit() -> Result<()> { .await?; let gas_forwarded = response + .tx_status .receipts .iter() .find(|r| matches!(r, Receipt::Call { .. })) @@ -419,6 +422,7 @@ async fn test_amount_and_asset_forwarding() -> Result<()> { assert_eq!(response.value, 1_000_000); let call_response = response + .tx_status .receipts .iter() .find(|&r| matches!(r, Receipt::Call { .. })); @@ -456,6 +460,7 @@ async fn test_amount_and_asset_forwarding() -> Result<()> { assert_eq!(response.value, 0); let call_response = response + .tx_status .receipts .iter() .find(|&r| matches!(r, Receipt::Call { .. })); @@ -500,18 +505,18 @@ async fn test_gas_errors() -> Result<()> { ); // Test running out of gas. Gas price as `None` will be 0. - let gas_limit = 100; + let gas_limit = 42; let contract_instance_call = contract_instance .methods() .initialize_counter(42) // Build the ABI call .with_tx_policies(TxPolicies::default().with_script_gas_limit(gas_limit)); // Test that the call will use more gas than the gas limit - let gas_used = contract_instance_call + let total_gas = contract_instance_call .estimate_transaction_cost(None, None) .await? - .gas_used; - assert!(gas_used > gas_limit); + .total_gas; + assert!(total_gas > gas_limit); let response = contract_instance_call .call() @@ -594,14 +599,16 @@ async fn test_get_gas_used() -> Result<()> { ), ); - let gas_used = contract_instance + let total_gas = contract_instance .methods() .initialize_counter(42) .call() .await? - .gas_used; + .tx_status + .total_gas; + + assert!(total_gas > 0); - assert!(gas_used > 0); Ok(()) } @@ -615,13 +622,13 @@ async fn test_parse_block_time() -> Result<()> { let tx_policies = TxPolicies::default().with_script_gas_limit(2000); let wallet_2 = WalletUnlocked::new_random(None).lock(); - let (tx_id, _) = wallet + let tx_response = wallet .transfer(wallet_2.address(), 100, asset_id, tx_policies) .await?; let tx_response = wallet .try_provider()? - .get_transaction_by_id(&tx_id) + .get_transaction_by_id(&tx_response.tx_id) .await? .unwrap(); assert!(tx_response.time.is_some()); @@ -1222,7 +1229,7 @@ async fn tx_with_witness_data() -> Result<()> { let status = provider.send_transaction_and_await_commit(tx).await?; match status { - TxStatus::Success { receipts } => { + TxStatus::Success(Success { receipts, .. }) => { let ret: u64 = receipts .into_iter() .find_map(|receipt| match receipt { @@ -1266,7 +1273,8 @@ async fn contract_call_with_impersonation() -> Result<()> { LoadConfiguration::default(), )? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_instance = MyContract::new(contract_id, impersonator.clone()); diff --git a/e2e/tests/scripts.rs b/e2e/tests/scripts.rs index 3a7d2fbce4..7f262b3437 100644 --- a/e2e/tests/scripts.rs +++ b/e2e/tests/scripts.rs @@ -59,15 +59,15 @@ async fn script_call_has_same_estimated_and_used_gas() -> Result<()> { let a = 4u64; let b = 2u32; - let estimated_gas_used = script_instance + let estimated_total_gas = script_instance .main(a, b) .estimate_transaction_cost(tolerance, block_horizon) .await? - .gas_used; + .total_gas; - let gas_used = script_instance.main(a, b).call().await?.gas_used; + let total_gas = script_instance.main(a, b).call().await?.tx_status.total_gas; - assert_eq!(estimated_gas_used, gas_used); + assert_eq!(estimated_total_gas, total_gas); Ok(()) } @@ -326,7 +326,7 @@ async fn test_script_transaction_builder() -> Result<()> { tokio::time::sleep(Duration::from_millis(500)).await; let tx_status = provider.tx_status(&tx_id).await?; - let response = script_call_handler.get_response_from(tx_status)?; + let response = script_call_handler.get_response(tx_status)?; assert_eq!(response.value, "hello"); // ANCHOR_END: script_call_tb @@ -598,14 +598,16 @@ async fn loader_script_calling_loader_proxy() -> Result<()> { let contract_id = contract .convert_to_loader(100)? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_binary = "sway/contracts/proxy/out/release/proxy.bin"; let proxy_id = Contract::load_from(contract_binary, LoadConfiguration::default())? .convert_to_loader(100)? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let proxy = MyProxy::new(proxy_id.clone(), wallet.clone()); proxy diff --git a/e2e/tests/storage.rs b/e2e/tests/storage.rs index 554b7123a1..8dbf21c3d9 100644 --- a/e2e/tests/storage.rs +++ b/e2e/tests/storage.rs @@ -24,7 +24,8 @@ async fn test_storage_initialization() -> Result<()> { LoadConfiguration::default().with_storage_configuration(storage_configuration), )? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_instance = MyContract::new(contract_id, wallet.clone()); @@ -53,7 +54,8 @@ async fn test_init_storage_automatically() -> Result<()> { LoadConfiguration::default(), )? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_methods = MyContract::new(contract_id, wallet.clone()).methods(); { diff --git a/e2e/tests/types_contracts.rs b/e2e/tests/types_contracts.rs index e4e7dd3aba..cd2809bba7 100644 --- a/e2e/tests/types_contracts.rs +++ b/e2e/tests/types_contracts.rs @@ -81,7 +81,8 @@ async fn call_with_structs() -> Result<()> { LoadConfiguration::default(), )? .deploy_if_not_exists(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_methods = MyContract::new(contract_id, wallet).methods(); diff --git a/e2e/tests/types_predicates.rs b/e2e/tests/types_predicates.rs index 3ea61c5c4f..aae9c4e10f 100644 --- a/e2e/tests/types_predicates.rs +++ b/e2e/tests/types_predicates.rs @@ -13,20 +13,31 @@ async fn assert_predicate_spendable(data: Vec, project_path: impl AsRef Result<()> { wallet_1.set_provider(provider.clone()); wallet_2.set_provider(provider); - let _receipts = wallet_1 + let _ = wallet_1 .transfer( wallet_2.address(), amount / 2, @@ -256,8 +256,8 @@ async fn test_transfer() -> Result<()> { #[tokio::test] async fn send_transfer_transactions() -> Result<()> { - const AMOUNT: u64 = 5; - let (wallet_1, wallet_2) = setup_transfer_test(AMOUNT).await?; + let amount = 5; + let (wallet_1, wallet_2) = setup_transfer_test(amount).await?; // Configure transaction policies let tip = 2; @@ -270,11 +270,17 @@ async fn send_transfer_transactions() -> Result<()> { .with_script_gas_limit(script_gas_limit); // Transfer 1 from wallet 1 to wallet 2. - const SEND_AMOUNT: u64 = 1; + let amount_to_send = 1; let base_asset_id = AssetId::zeroed(); - let (tx_id, _receipts) = wallet_1 - .transfer(wallet_2.address(), SEND_AMOUNT, base_asset_id, tx_policies) - .await?; + let tx_id = wallet_1 + .transfer( + wallet_2.address(), + amount_to_send, + base_asset_id, + tx_policies, + ) + .await? + .tx_id; // Assert that the transaction was properly configured. let res = wallet_1 @@ -317,28 +323,25 @@ async fn transfer_coins_with_change() -> Result<()> { // Transfer 2 from wallet 1 to wallet 2. const SEND_AMOUNT: u64 = 2; - let _receipts = wallet_1 + let fee = wallet_1 .transfer( wallet_2.address(), SEND_AMOUNT, AssetId::zeroed(), TxPolicies::default(), ) - .await?; + .await? + .tx_status + .total_fee; let base_asset_id = AssetId::zeroed(); let wallet_1_final_coins = wallet_1 .get_spendable_resources(base_asset_id, 1, None) .await?; - // TODO: https://github.com/FuelLabs/fuels-rs/issues/1394 - let expected_fee = 1; // Assert that we've sent 2 from wallet 1, resulting in an amount of 3 in wallet 1. let resulting_amount = wallet_1_final_coins.first().unwrap(); - assert_eq!( - resulting_amount.amount(), - AMOUNT - SEND_AMOUNT - expected_fee - ); + assert_eq!(resulting_amount.amount(), AMOUNT - SEND_AMOUNT - fee); let wallet_2_final_coins = wallet_2.get_coins(base_asset_id).await?; assert_eq!(wallet_2_final_coins.len(), 1); @@ -425,7 +428,7 @@ async fn transfer_coins_of_non_base_asset() -> Result<()> { wallet_2.set_provider(provider); const SEND_AMOUNT: u64 = 200; - let _receipts = wallet_1 + let _ = wallet_1 .transfer( wallet_2.address(), SEND_AMOUNT, diff --git a/examples/contracts/src/lib.rs b/examples/contracts/src/lib.rs index b1f067f4a8..09ca507801 100644 --- a/examples/contracts/src/lib.rs +++ b/examples/contracts/src/lib.rs @@ -50,7 +50,8 @@ mod tests { LoadConfiguration::default(), )? .deploy(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; println!("Contract deployed @ {contract_id}"); // ANCHOR_END: deploy_contract @@ -104,7 +105,8 @@ mod tests { LoadConfiguration::default(), )? .deploy(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; // ANCHOR: contract_call_cost_estimation let contract_instance = MyContract::new(contract_id, wallet); @@ -118,9 +120,11 @@ mod tests { .await?; // ANCHOR_END: contract_call_cost_estimation - let expected_gas = 2596; + let expected_script_gas = 2596; + let expected_total_gas = 8848; - assert_eq!(transaction_cost.gas_used, expected_gas); + assert_eq!(transaction_cost.script_gas, expected_script_gas); + assert_eq!(transaction_cost.total_gas, expected_total_gas); Ok(()) } @@ -137,9 +141,8 @@ mod tests { LoadConfiguration::default(), )? .deploy(&wallet, TxPolicies::default()) - .await?; - - println!("Contract deployed @ {contract_id_1}"); + .await? + .contract_id; // ANCHOR: deploy_with_parameters // Optional: Add `Salt` @@ -168,7 +171,8 @@ mod tests { configuration, )? .deploy(&wallet, tx_policies) - .await?; + .await? + .contract_id; println!("Contract deployed @ {contract_id_2}"); // ANCHOR_END: deploy_with_parameters @@ -239,9 +243,9 @@ mod tests { LoadConfiguration::default(), )? .deploy(&wallets[0], TxPolicies::default()) - .await?; + .await? + .contract_id; - println!("Contract deployed @ {contract_id_1}"); let contract_instance_1 = MyContract::new(contract_id_1, wallets[0].clone()); let response = contract_instance_1 @@ -257,9 +261,9 @@ mod tests { LoadConfiguration::default().with_salt([1; 32]), )? .deploy(&wallets[1], TxPolicies::default()) - .await?; + .await? + .contract_id; - println!("Contract deployed @ {contract_id_2}"); let contract_instance_2 = MyContract::new(contract_id_2, wallets[1].clone()); let response = contract_instance_2 @@ -289,9 +293,9 @@ mod tests { LoadConfiguration::default(), )? .deploy(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; - println!("Contract deployed @ {contract_id}"); // ANCHOR: tx_policies let contract_methods = MyContract::new(contract_id.clone(), wallet.clone()).methods(); @@ -360,9 +364,9 @@ mod tests { LoadConfiguration::default(), )? .deploy(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; - println!("Contract deployed @ {contract_id}"); let contract_methods = MyContract::new(contract_id.clone(), wallet.clone()).methods(); // ANCHOR: simulate // you would mint 100 coins if the transaction wasn't simulated @@ -416,13 +420,15 @@ mod tests { )? .deploy(&wallet, TxPolicies::default()) .await? + .contract_id .into(); let bin_path = "../../e2e/sway/contracts/lib_contract_caller/out/release/lib_contract_caller.bin"; let caller_contract_id = Contract::load_from(bin_path, LoadConfiguration::default())? .deploy(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_methods = MyContract::new(caller_contract_id.clone(), wallet.clone()).methods(); @@ -520,7 +526,8 @@ mod tests { LoadConfiguration::default(), )? .deploy(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_methods = MyContract::new(contract_id, wallet.clone()).methods(); @@ -558,7 +565,8 @@ mod tests { LoadConfiguration::default(), )? .deploy(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; // ANCHOR: multi_call_prepare let contract_methods = MyContract::new(contract_id, wallet.clone()).methods(); @@ -617,7 +625,8 @@ mod tests { LoadConfiguration::default(), )? .deploy(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_methods = MyContract::new(contract_id, wallet.clone()).methods(); @@ -636,9 +645,11 @@ mod tests { .await?; // ANCHOR_END: multi_call_cost_estimation - let expected_gas = 4200; + let expected_script_gas = 4200; + let expected_total_gas = 11029; - assert_eq!(transaction_cost.gas_used, expected_gas); + assert_eq!(transaction_cost.script_gas, expected_script_gas); + assert_eq!(transaction_cost.total_gas, expected_total_gas); Ok(()) } @@ -662,7 +673,8 @@ mod tests { LoadConfiguration::default(), )? .deploy(&wallet_1, TxPolicies::default()) - .await?; + .await? + .contract_id; // ANCHOR: connect_wallet // Create contract instance with wallet_1 @@ -896,7 +908,7 @@ mod tests { let tx_status = provider.tx_status(&tx_id).await?; - let response = call_handler.get_response_from(tx_status)?; + let response = call_handler.get_response(tx_status)?; assert_eq!(counter, response.value); // ANCHOR_END: contract_call_tb @@ -971,7 +983,8 @@ mod tests { LoadConfiguration::default(), )? .deploy(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; // ANCHOR: contract_call_impersonation // create impersonator for an address @@ -1065,7 +1078,8 @@ mod tests { let contract_id = Contract::loader_from_blob_ids(all_blob_ids, random_salt(), vec![])? .deploy(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; // ANCHOR_END: manual_blob_upload_then_deploy // ANCHOR: deploy_via_loader @@ -1076,7 +1090,8 @@ mod tests { )? .convert_to_loader(max_words_per_blob)? .deploy(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; // ANCHOR_END: deploy_via_loader // ANCHOR: auto_convert_to_loader @@ -1086,7 +1101,8 @@ mod tests { LoadConfiguration::default().with_salt(random_salt()), )? .smart_deploy(&wallet, TxPolicies::default(), max_words_per_blob) - .await?; + .await? + .contract_id; // ANCHOR_END: auto_convert_to_loader // ANCHOR: upload_blobs_then_deploy @@ -1098,7 +1114,8 @@ mod tests { .upload_blobs(&wallet, TxPolicies::default()) .await? .deploy(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; // ANCHOR_END: upload_blobs_then_deploy let wallet = main_wallet.clone(); @@ -1139,7 +1156,8 @@ mod tests { let contract_id = Contract::loader_from_blobs(blobs, random_salt(), vec![])? .deploy(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; // ANCHOR_END: manual_blobs_then_deploy // ANCHOR: estimate_max_blob_size diff --git a/examples/cookbook/src/lib.rs b/examples/cookbook/src/lib.rs index 1083b845a8..8817230935 100644 --- a/examples/cookbook/src/lib.rs +++ b/examples/cookbook/src/lib.rs @@ -56,7 +56,8 @@ mod tests { LoadConfiguration::default(), )? .deploy(wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; let contract_methods = MyContract::new(contract_id.clone(), wallet.clone()).methods(); // ANCHOR_END: liquidity_deploy diff --git a/examples/wallets/src/lib.rs b/examples/wallets/src/lib.rs index eb4551398f..398faf1687 100644 --- a/examples/wallets/src/lib.rs +++ b/examples/wallets/src/lib.rs @@ -135,7 +135,7 @@ mod tests { // Transfer the base asset with amount 1 from wallet 1 to wallet 2 let transfer_amount = 1; let asset_id = Default::default(); - let (_tx_id, _receipts) = wallets[0] + let _res = wallets[0] .transfer( wallets[1].address(), transfer_amount, @@ -185,7 +185,8 @@ mod tests { LoadConfiguration::default(), )? .deploy(&wallet, TxPolicies::default()) - .await?; + .await? + .contract_id; // ANCHOR: wallet_contract_transfer // Check the current balance of the contract with id 'contract_id' @@ -198,7 +199,7 @@ mod tests { // Transfer an amount of 300 to the contract let amount = 300; let asset_id = random_asset_id; - let (_tx_id, _receipts) = wallet + let _res = wallet .force_transfer_to_contract(&contract_id, amount, asset_id, TxPolicies::default()) .await?; @@ -369,7 +370,7 @@ mod tests { )?; let base_layer_address = Bech32Address::from(base_layer_address); // Transfer an amount of 1000 to the specified base layer address - let (tx_id, msg_id, _receipts) = wallet + let response = wallet .withdraw_to_base_layer(&base_layer_address, amount, TxPolicies::default()) .await?; @@ -378,7 +379,7 @@ mod tests { // Retrieve a message proof from the provider let proof = wallet .try_provider()? - .get_message_proof(&tx_id, &msg_id, None, Some(2)) + .get_message_proof(&response.tx_id, &response.nonce, None, Some(2)) .await?; // Verify the amount and recipient diff --git a/packages/fuels-accounts/src/account.rs b/packages/fuels-accounts/src/account.rs index dded620dc1..2fd537252b 100644 --- a/packages/fuels-accounts/src/account.rs +++ b/packages/fuels-accounts/src/account.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use async_trait::async_trait; use fuel_core_client::client::pagination::{PaginatedResult, PaginationRequest}; -use fuel_tx::{Output, Receipt, TxId, TxPointer, UtxoId}; +use fuel_tx::{Output, TxId, TxPointer, UtxoId}; use fuel_types::{AssetId, Bytes32, ContractId, Nonce}; use fuels_core::types::{ bech32::{Bech32Address, Bech32ContractId}, @@ -15,6 +15,8 @@ use fuels_core::types::{ transaction::{Transaction, TxPolicies}, transaction_builders::{BuildableTransaction, ScriptTransactionBuilder, TransactionBuilder}, transaction_response::TransactionResponse, + tx_response::TxResponse, + tx_status::Success, }; use crate::{ @@ -25,6 +27,13 @@ use crate::{ provider::{Provider, ResourceFilter}, }; +#[derive(Clone, Debug)] +pub struct WithdrawToBaseResponse { + pub tx_status: Success, + pub tx_id: TxId, + pub nonce: Nonce, +} + #[cfg_attr(not(target_arch = "wasm32"), async_trait)] pub trait ViewOnlyAccount: std::fmt::Debug + Send + Sync + Clone { fn address(&self) -> &Bech32Address; @@ -169,7 +178,7 @@ pub trait Account: ViewOnlyAccount { amount: u64, asset_id: AssetId, tx_policies: TxPolicies, - ) -> Result<(TxId, Vec)> { + ) -> Result { let provider = self.try_provider()?; let inputs = self @@ -196,9 +205,10 @@ pub trait Account: ViewOnlyAccount { let tx_status = provider.send_transaction_and_await_commit(tx).await?; - let receipts = tx_status.take_receipts_checked(None)?; - - Ok((tx_id, receipts)) + Ok(TxResponse { + tx_status: tx_status.take_success_checked(None)?, + tx_id, + }) } /// Unconditionally transfers `balance` of type `asset_id` to @@ -216,7 +226,7 @@ pub trait Account: ViewOnlyAccount { balance: u64, asset_id: AssetId, tx_policies: TxPolicies, - ) -> Result<(String, Vec)> { + ) -> Result { let provider = self.try_provider()?; let zeroes = Bytes32::zeroed(); @@ -257,11 +267,13 @@ pub trait Account: ViewOnlyAccount { let consensus_parameters = provider.consensus_parameters().await?; let tx_id = tx.id(consensus_parameters.chain_id()); - let tx_status = provider.send_transaction_and_await_commit(tx).await?; - let receipts = tx_status.take_receipts_checked(None)?; + let tx_status = provider.send_transaction_and_await_commit(tx).await?; - Ok((tx_id.to_string(), receipts)) + Ok(TxResponse { + tx_status: tx_status.take_success_checked(None)?, + tx_id, + }) } /// Withdraws an amount of the base asset to @@ -272,7 +284,7 @@ pub trait Account: ViewOnlyAccount { to: &Bech32Address, amount: u64, tx_policies: TxPolicies, - ) -> Result<(TxId, Nonce, Vec)> { + ) -> Result { let provider = self.try_provider()?; let consensus_parameters = provider.consensus_parameters().await?; @@ -292,16 +304,19 @@ pub trait Account: ViewOnlyAccount { self.adjust_for_fee(&mut tb, amount).await?; let tx = tb.build(provider).await?; - let tx_id = tx.id(consensus_parameters.chain_id()); - let tx_status = provider.send_transaction_and_await_commit(tx).await?; - let receipts = tx_status.take_receipts_checked(None)?; + let tx_status = provider.send_transaction_and_await_commit(tx).await?; + let success = tx_status.take_success_checked(None)?; - let nonce = extract_message_nonce(&receipts) + let nonce = extract_message_nonce(&success.receipts) .expect("MessageId could not be retrieved from tx receipts."); - Ok((tx_id, nonce, receipts)) + Ok(WithdrawToBaseResponse { + tx_status: success, + tx_id, + nonce, + }) } } diff --git a/packages/fuels-accounts/src/provider.rs b/packages/fuels-accounts/src/provider.rs index 13668ed804..e3b21fb853 100644 --- a/packages/fuels-accounts/src/provider.rs +++ b/packages/fuels-accounts/src/provider.rs @@ -62,9 +62,10 @@ const NUM_RESULTS_PER_REQUEST: i32 = 100; // ANCHOR: transaction_cost pub struct TransactionCost { pub gas_price: u64, - pub gas_used: u64, pub metered_bytes_size: u64, pub total_fee: u64, + pub script_gas: u64, + pub total_gas: u64, } // ANCHOR_END: transaction_cost @@ -225,8 +226,6 @@ impl Provider { .validate_predicates(&consensus_parameters, latest_block_height)?; } - self.validate_transaction(tx.clone()).await?; - Ok(tx) } @@ -243,17 +242,6 @@ impl Provider { .into()) } - async fn validate_transaction(&self, tx: T) -> Result<()> { - let tolerance = 0.0; - let TransactionCost { gas_used, .. } = self - .estimate_transaction_cost(tx.clone(), Some(tolerance), None) - .await?; - - tx.validate_gas(gas_used)?; - - Ok(()) - } - #[cfg(not(feature = "coin-cache"))] async fn submit(&self, tx: T) -> Result { Ok(self.uncached_client().submit(&tx.into()).await?) @@ -719,7 +707,7 @@ impl Provider { pub async fn estimate_transaction_cost( &self, - mut tx: T, + tx: T, tolerance: Option, block_horizon: Option, ) -> Result { @@ -727,41 +715,27 @@ impl Provider { let tolerance = tolerance.unwrap_or(DEFAULT_GAS_ESTIMATION_TOLERANCE); let EstimateGasPrice { gas_price, .. } = self.estimate_gas_price(block_horizon).await?; + let tx_status = self.dry_run_opt(tx.clone(), false, None).await?; - let gas_used = self - .get_gas_used_with_tolerance(tx.clone(), tolerance) - .await?; - - if tx.is_using_predicates() { - tx.estimate_predicates(self, None).await?; - } + let total_gas = Self::apply_tolerance(tx_status.total_gas(), tolerance); + let total_fee = Self::apply_tolerance(tx_status.total_fee(), tolerance); - let transaction_fee = tx - .clone() - .fee_checked_from_tx(&self.consensus_parameters().await?, gas_price) - .expect("Error calculating TransactionFee"); + let receipts = tx_status.take_receipts(); Ok(TransactionCost { gas_price, - gas_used, metered_bytes_size: tx.metered_bytes_size() as u64, - total_fee: transaction_fee.max_fee(), + total_fee, + total_gas, + script_gas: Self::get_script_gas_used(&receipts), }) } - // Increase estimated gas by the provided tolerance - async fn get_gas_used_with_tolerance( - &self, - tx: T, - tolerance: f64, - ) -> Result { - let receipts = self.dry_run_opt(tx, false, None).await?.take_receipts(); - let gas_used = self.get_script_gas_used(&receipts); - - Ok((gas_used as f64 * (1.0 + tolerance)).ceil() as u64) + fn apply_tolerance(value: u64, tolerance: f64) -> u64 { + (value as f64 * (1.0 + tolerance)).ceil() as u64 } - fn get_script_gas_used(&self, receipts: &[Receipt]) -> u64 { + fn get_script_gas_used(receipts: &[Receipt]) -> u64 { receipts .iter() .rfind(|r| matches!(r, Receipt::ScriptResult { .. })) @@ -859,7 +833,7 @@ impl DryRunner for Provider { .expect("should have only one element"); let receipts = tx_execution_status.result.receipts(); - let script_gas = self.get_script_gas_used(receipts); + let script_gas = Self::get_script_gas_used(receipts); let variable_outputs = receipts .iter() diff --git a/packages/fuels-core/src/types.rs b/packages/fuels-core/src/types.rs index 484fd12399..512695330c 100644 --- a/packages/fuels-core/src/types.rs +++ b/packages/fuels-core/src/types.rs @@ -14,6 +14,7 @@ pub mod errors; pub mod param_types; mod token; pub mod transaction_builders; +pub mod tx_response; pub mod tx_status; mod wrappers; pub use dry_runner::*; diff --git a/packages/fuels-core/src/types/tx_response.rs b/packages/fuels-core/src/types/tx_response.rs new file mode 100644 index 0000000000..e298fd4f41 --- /dev/null +++ b/packages/fuels-core/src/types/tx_response.rs @@ -0,0 +1,8 @@ +use super::tx_status::Success; +use fuel_tx::TxId; + +#[derive(Clone, Debug)] +pub struct TxResponse { + pub tx_status: Success, + pub tx_id: TxId, +} diff --git a/packages/fuels-core/src/types/tx_status.rs b/packages/fuels-core/src/types/tx_status.rs index c5dff11402..daf65addb3 100644 --- a/packages/fuels-core/src/types/tx_status.rs +++ b/packages/fuels-core/src/types/tx_status.rs @@ -15,43 +15,91 @@ use crate::{ types::errors::{transaction::Reason, Error, Result}, }; +#[derive(Debug, Clone)] +pub struct Success { + pub receipts: Vec, + pub total_fee: u64, + pub total_gas: u64, +} + +#[derive(Debug, Clone)] +pub struct SqueezedOut { + pub reason: String, +} + +#[derive(Debug, Clone)] +pub struct Revert { + pub reason: String, + pub receipts: Vec, + pub revert_id: u64, + pub total_fee: u64, + pub total_gas: u64, +} + #[derive(Debug, Clone)] pub enum TxStatus { - Success { - receipts: Vec, - }, + Success(Success), Submitted, - SqueezedOut { - reason: String, - }, - Revert { - receipts: Vec, - reason: String, - revert_id: u64, - }, + SqueezedOut(SqueezedOut), + Revert(Revert), } impl TxStatus { pub fn check(&self, log_decoder: Option<&LogDecoder>) -> Result<()> { match self { - Self::SqueezedOut { reason } => { + Self::SqueezedOut(SqueezedOut { reason }) => { Err(Error::Transaction(Reason::SqueezedOut(reason.clone()))) } - Self::Revert { + Self::Revert(Revert { receipts, reason, revert_id: id, - } => Self::map_revert_error(receipts, reason, *id, log_decoder), + .. + }) => Err(Self::map_revert_error(receipts, reason, *id, log_decoder)), _ => Ok(()), } } + pub fn take_success_checked(self, log_decoder: Option<&LogDecoder>) -> Result { + match self { + Self::SqueezedOut(SqueezedOut { reason }) => { + Err(Error::Transaction(Reason::SqueezedOut(reason.clone()))) + } + Self::Revert(Revert { + receipts, + reason, + revert_id: id, + .. + }) => Err(Self::map_revert_error(&receipts, &reason, id, log_decoder)), + Self::Submitted => Err(Error::Transaction(Reason::Other( + "transactions was not yet included".to_owned(), + ))), + Self::Success(success) => Ok(success), + } + } + + pub fn total_gas(&self) -> u64 { + match self { + TxStatus::Success(Success { total_gas, .. }) + | TxStatus::Revert(Revert { total_gas, .. }) => *total_gas, + _ => 0, + } + } + + pub fn total_fee(&self) -> u64 { + match self { + TxStatus::Success(Success { total_fee, .. }) + | TxStatus::Revert(Revert { total_fee, .. }) => *total_fee, + _ => 0, + } + } + fn map_revert_error( receipts: &[Receipt], reason: &str, id: u64, log_decoder: Option<&LogDecoder>, - ) -> Result<()> { + ) -> Error { let reason = match (id, log_decoder) { (FAILED_REQUIRE_SIGNAL, Some(log_decoder)) => log_decoder .decode_last_log(receipts) @@ -85,11 +133,11 @@ impl TxStatus { _ => reason.to_string(), }; - Err(Error::Transaction(Reason::Reverted { + Error::Transaction(Reason::Reverted { reason, revert_id: id, receipts: receipts.to_vec(), - })) + }) } pub fn take_receipts_checked(self, log_decoder: Option<&LogDecoder>) -> Result> { @@ -99,7 +147,8 @@ impl TxStatus { pub fn take_receipts(self) -> Vec { match self { - TxStatus::Success { receipts } | TxStatus::Revert { receipts, .. } => receipts, + TxStatus::Success(Success { receipts, .. }) + | TxStatus::Revert(Revert { receipts, .. }) => receipts, _ => vec![], } } @@ -110,11 +159,22 @@ impl From for TxStatus { fn from(client_status: ClientTransactionStatus) -> Self { match client_status { ClientTransactionStatus::Submitted { .. } => TxStatus::Submitted {}, - ClientTransactionStatus::Success { receipts, .. } => TxStatus::Success { receipts }, + ClientTransactionStatus::Success { + receipts, + total_gas, + total_fee, + .. + } => TxStatus::Success(Success { + receipts, + total_gas, + total_fee, + }), ClientTransactionStatus::Failure { reason, program_state, receipts, + total_gas, + total_fee, .. } => { let revert_id = program_state @@ -123,13 +183,17 @@ impl From for TxStatus { _ => None, }) .expect("Transaction failed without a `revert_id`"); - TxStatus::Revert { + TxStatus::Revert(Revert { receipts, reason, revert_id, - } + total_gas, + total_fee, + }) + } + ClientTransactionStatus::SqueezedOut { reason } => { + TxStatus::SqueezedOut(SqueezedOut { reason }) } - ClientTransactionStatus::SqueezedOut { reason } => TxStatus::SqueezedOut { reason }, } } } @@ -138,9 +202,22 @@ impl From for TxStatus { impl From for TxStatus { fn from(value: TransactionExecutionStatus) -> Self { match value.result { - TransactionExecutionResult::Success { receipts, .. } => Self::Success { receipts }, + TransactionExecutionResult::Success { + receipts, + total_gas, + total_fee, + .. + } => Self::Success(Success { + receipts, + total_gas, + total_fee, + }), TransactionExecutionResult::Failed { - result, receipts, .. + result, + receipts, + total_gas, + total_fee, + .. } => { let revert_id = result .and_then(|result| match result { @@ -149,11 +226,13 @@ impl From for TxStatus { }) .expect("Transaction failed without a `revert_id`"); let reason = TransactionExecutionResult::reason(&receipts, &result); - Self::Revert { + Self::Revert(Revert { receipts, reason, revert_id, - } + total_gas, + total_fee, + }) } } } diff --git a/packages/fuels-core/src/types/wrappers/transaction.rs b/packages/fuels-core/src/types/wrappers/transaction.rs index 6d673bf822..6f9bc75df2 100644 --- a/packages/fuels-core/src/types/wrappers/transaction.rs +++ b/packages/fuels-core/src/types/wrappers/transaction.rs @@ -215,10 +215,6 @@ pub trait EstimablePredicates: sealed::Sealed { ) -> Result<()>; } -pub trait GasValidation: sealed::Sealed { - fn validate_gas(&self, _gas_used: u64) -> Result<()>; -} - pub trait ValidatablePredicates: sealed::Sealed { /// If a transaction contains predicates, we can verify that these predicates validate, ie /// that they return `true` @@ -236,7 +232,6 @@ pub trait Transaction: + Into + EstimablePredicates + ValidatablePredicates - + GasValidation + Clone + Debug + sealed::Sealed @@ -660,45 +655,6 @@ impl EstimablePredicates for BlobTransaction { } } -impl GasValidation for CreateTransaction { - fn validate_gas(&self, _gas_used: u64) -> Result<()> { - Ok(()) - } -} - -impl GasValidation for UploadTransaction { - fn validate_gas(&self, _gas_used: u64) -> Result<()> { - Ok(()) - } -} - -impl GasValidation for UpgradeTransaction { - fn validate_gas(&self, _gas_used: u64) -> Result<()> { - Ok(()) - } -} - -impl GasValidation for BlobTransaction { - fn validate_gas(&self, _gas_used: u64) -> Result<()> { - Ok(()) - } -} - -impl GasValidation for ScriptTransaction { - fn validate_gas(&self, gas_used: u64) -> Result<()> { - if gas_used > *self.tx.script_gas_limit() { - return Err(error_transaction!( - Validation, - "script_gas_limit({}) is lower than the estimated gas_used({})", - self.tx.script_gas_limit(), - gas_used - )); - } - - Ok(()) - } -} - impl ScriptTransaction { pub fn script(&self) -> &Vec { self.tx.script() diff --git a/packages/fuels-macros/src/setup_program_test/code_gen.rs b/packages/fuels-macros/src/setup_program_test/code_gen.rs index a98a2911c2..b651918ee0 100644 --- a/packages/fuels-macros/src/setup_program_test/code_gen.rs +++ b/packages/fuels-macros/src/setup_program_test/code_gen.rs @@ -154,14 +154,14 @@ fn contract_deploying_code( ) .expect("Failed to load the contract"); - let contract_id = loaded_contract.deploy_if_not_exists( + let response = loaded_contract.deploy_if_not_exists( &#wallet_name, ::fuels::types::transaction::TxPolicies::default() ) .await .expect("Failed to deploy the contract"); - #contract_struct_name::new(contract_id, #wallet_name.clone()) + #contract_struct_name::new(response.contract_id, #wallet_name.clone()) }; } }) diff --git a/packages/fuels-programs/src/calls/call_handler.rs b/packages/fuels-programs/src/calls/call_handler.rs index 21d0302b6f..3b4c7469b8 100644 --- a/packages/fuels-programs/src/calls/call_handler.rs +++ b/packages/fuels-programs/src/calls/call_handler.rs @@ -1,6 +1,6 @@ use core::{fmt::Debug, marker::PhantomData}; -use fuel_tx::{AssetId, Bytes32, Receipt}; +use fuel_tx::{AssetId, Bytes32}; use fuels_accounts::{provider::TransactionCost, Account}; use fuels_core::{ codec::{ABIEncoder, DecoderConfig, EncoderConfig, LogDecoder}, @@ -172,9 +172,7 @@ where let tx_status = provider.send_transaction_and_await_commit(tx).await?; - let receipts = tx_status.take_receipts_checked(Some(&self.log_decoder))?; - - self.get_response(receipts) + self.get_response(tx_status) } pub async fn submit(mut self) -> Result> { @@ -205,30 +203,24 @@ where let tx = self.build_tx().await?; provider.dry_run(tx).await? }; - let receipts = tx_status.take_receipts_checked(Some(&self.log_decoder))?; - - self.get_response(receipts) - } - /// Create a [`CallResponse`] from call receipts - pub fn get_response(&self, receipts: Vec) -> Result> { - let token = self - .call - .parse_call(&receipts, self.decoder_config, &T::param_type())?; - - Ok(CallResponse::new( - T::from_token(token)?, - receipts, - self.log_decoder.clone(), - self.cached_tx_id, - )) + self.get_response(tx_status) } /// Create a [`CallResponse`] from `TxStatus` - pub fn get_response_from(&self, tx_status: TxStatus) -> Result> { - let receipts = tx_status.take_receipts_checked(Some(&self.log_decoder))?; - - self.get_response(receipts) + pub fn get_response(&self, tx_status: TxStatus) -> Result> { + let success = tx_status.take_success_checked(Some(&self.log_decoder))?; + + let token = + self.call + .parse_call(&success.receipts, self.decoder_config, &T::param_type())?; + + Ok(CallResponse { + value: T::from_token(token)?, + log_decoder: self.log_decoder.clone(), + tx_id: self.cached_tx_id, + tx_status: success, + }) } pub async fn determine_missing_contracts(mut self, max_attempts: Option) -> Result { @@ -434,8 +426,7 @@ where let tx_status = provider.send_transaction_and_await_commit(tx).await?; - let receipts = tx_status.take_receipts_checked(Some(&self.log_decoder))?; - self.get_response(receipts) + self.get_response(tx_status) } pub async fn submit(mut self) -> Result, ()>> { @@ -472,9 +463,8 @@ where let tx = self.build_tx().await?; provider.dry_run(tx).await? }; - let receipts = tx_status.take_receipts_checked(Some(&self.log_decoder))?; - self.get_response(receipts) + self.get_response(tx_status) } /// Simulates a call without needing to resolve the generic for the return type @@ -487,12 +477,13 @@ where Ok(()) } - /// Create a [`CallResponse`] from call receipts + /// Create a [`CallResponse`] from `TxStatus` pub fn get_response( &self, - receipts: Vec, + tx_status: TxStatus, ) -> Result> { - let mut receipt_parser = ReceiptParser::new(&receipts, self.decoder_config); + let success = tx_status.take_success_checked(Some(&self.log_decoder))?; + let mut receipt_parser = ReceiptParser::new(&success.receipts, self.decoder_config); let final_tokens = self .call @@ -501,14 +492,13 @@ where .collect::>>()?; let tokens_as_tuple = Token::Tuple(final_tokens); - let response = CallResponse::::new( - T::from_token(tokens_as_tuple)?, - receipts, - self.log_decoder.clone(), - self.cached_tx_id, - ); - - Ok(response) + + Ok(CallResponse { + value: T::from_token(tokens_as_tuple)?, + log_decoder: self.log_decoder.clone(), + tx_id: self.cached_tx_id, + tx_status: success, + }) } /// Simulates the call and attempts to resolve missing contract outputs. diff --git a/packages/fuels-programs/src/contract/loader.rs b/packages/fuels-programs/src/contract/loader.rs index 963c817417..efa8087a13 100644 --- a/packages/fuels-programs/src/contract/loader.rs +++ b/packages/fuels-programs/src/contract/loader.rs @@ -5,7 +5,6 @@ use fuels_accounts::Account; use fuels_core::{ constants::WORD_SIZE, types::{ - bech32::Bech32ContractId, errors::{error, Result}, transaction::TxPolicies, transaction_builders::{Blob, BlobId, BlobTransactionBuilder, TransactionBuilder}, @@ -14,7 +13,7 @@ use fuels_core::{ use crate::{assembly::contract_call::loader_contract_asm, DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE}; -use super::{compute_contract_id_and_state_root, Contract, Regular}; +use super::{compute_contract_id_and_state_root, Contract, DeployResponse, Regular}; #[derive(Debug, Clone)] pub struct BlobsUploaded { @@ -159,7 +158,7 @@ impl Contract> { self, account: &impl Account, tx_policies: TxPolicies, - ) -> Result { + ) -> Result { self.upload_blobs(account, tx_policies) .await? .deploy(account, tx_policies) @@ -172,7 +171,7 @@ impl Contract> { self, account: &impl Account, tx_policies: TxPolicies, - ) -> Result { + ) -> Result { self.upload_blobs(account, tx_policies) .await? .deploy_if_not_exists(account, tx_policies) @@ -248,7 +247,7 @@ impl Contract> { self, account: &impl Account, tx_policies: TxPolicies, - ) -> Result { + ) -> Result { Contract::regular(self.code(), self.salt, self.storage_slots) .deploy(account, tx_policies) .await @@ -258,7 +257,7 @@ impl Contract> { self, account: &impl Account, tx_policies: TxPolicies, - ) -> Result { + ) -> Result { Contract::regular(self.code(), self.salt, self.storage_slots) .deploy_if_not_exists(account, tx_policies) .await diff --git a/packages/fuels-programs/src/contract/regular.rs b/packages/fuels-programs/src/contract/regular.rs index 7ba204578e..42158c8a20 100644 --- a/packages/fuels-programs/src/contract/regular.rs +++ b/packages/fuels-programs/src/contract/regular.rs @@ -1,6 +1,6 @@ use std::{default::Default, fmt::Debug, path::Path}; -use fuel_tx::{Bytes32, ContractId, Salt, StorageSlot}; +use fuel_tx::{Bytes32, ContractId, Salt, StorageSlot, TxId}; use fuels_accounts::Account; use fuels_core::{ constants::WORD_SIZE, @@ -8,8 +8,9 @@ use fuels_core::{ types::{ bech32::Bech32ContractId, errors::Result, - transaction::TxPolicies, + transaction::{Transaction, TxPolicies}, transaction_builders::{Blob, CreateTransactionBuilder}, + tx_status::Success, }, Configurables, }; @@ -21,6 +22,13 @@ use super::{ Loader, StorageConfiguration, }; +#[derive(Clone, Debug)] +pub struct DeployResponse { + pub tx_status: Option, + pub tx_id: Option, + pub contract_id: Bech32ContractId, +} + // In a mod so that we eliminate the footgun of getting the private `code` field without applying // configurables mod code_types { @@ -140,7 +148,7 @@ impl Contract { self, account: &impl Account, tx_policies: TxPolicies, - ) -> Result { + ) -> Result { let contract_id = self.contract_id(); let state_root = self.state_root(); let salt = self.salt; @@ -160,15 +168,18 @@ impl Contract { account.adjust_for_fee(&mut tb, 0).await?; let provider = account.try_provider()?; + let consensus_parameters = provider.consensus_parameters().await?; let tx = tb.build(provider).await?; + let tx_id = Some(tx.id(consensus_parameters.chain_id())); - provider - .send_transaction_and_await_commit(tx) - .await? - .check(None)?; + let tx_status = provider.send_transaction_and_await_commit(tx).await?; - Ok(contract_id.into()) + Ok(DeployResponse { + tx_status: Some(tx_status.take_success_checked(None)?), + tx_id, + contract_id: contract_id.into(), + }) } /// Deploys a compiled contract to a running node if a contract with @@ -177,11 +188,15 @@ impl Contract { self, account: &impl Account, tx_policies: TxPolicies, - ) -> Result { + ) -> Result { let contract_id = Bech32ContractId::from(self.contract_id()); let provider = account.try_provider()?; if provider.contract_exists(&contract_id).await? { - Ok(contract_id) + Ok(DeployResponse { + tx_status: None, + tx_id: None, + contract_id, + }) } else { self.deploy(account, tx_policies).await } @@ -210,7 +225,7 @@ impl Contract { account: &impl Account, tx_policies: TxPolicies, max_words_per_blob: usize, - ) -> Result { + ) -> Result { let provider = account.try_provider()?; let max_contract_size = provider .consensus_parameters() diff --git a/packages/fuels-programs/src/executable.rs b/packages/fuels-programs/src/executable.rs index 06be05c777..e79d1ad210 100644 --- a/packages/fuels-programs/src/executable.rs +++ b/packages/fuels-programs/src/executable.rs @@ -1,7 +1,9 @@ use fuels_core::{ types::{ errors::Result, + transaction::Transaction, transaction_builders::{Blob, BlobTransactionBuilder}, + tx_response::TxResponse, }, Configurables, }; @@ -161,13 +163,17 @@ impl Executable { .expect("checked before turning into a Executable") } - /// Uploads a blob containing the original executable code minus the data section. - pub async fn upload_blob(&self, account: impl fuels_accounts::Account) -> Result<()> { + /// If not previously uploaded, uploads a blob containing the original executable code minus the data section. + pub async fn upload_blob( + &self, + account: impl fuels_accounts::Account, + ) -> Result> { let blob = self.blob(); let provider = account.try_provider()?; + let consensus_parameters = provider.consensus_parameters().await?; if provider.blob_exists(blob.id()).await? { - return Ok(()); + return Ok(None); } let mut tb = BlobTransactionBuilder::default() @@ -175,17 +181,17 @@ impl Executable { .with_max_fee_estimation_tolerance(DEFAULT_MAX_FEE_ESTIMATION_TOLERANCE); account.adjust_for_fee(&mut tb, 0).await?; - account.add_witnesses(&mut tb)?; let tx = tb.build(provider).await?; + let tx_id = tx.id(consensus_parameters.chain_id()); - provider - .send_transaction_and_await_commit(tx) - .await? - .check(None)?; + let tx_status = provider.send_transaction_and_await_commit(tx).await?; - Ok(()) + Ok(Some(TxResponse { + tx_status: tx_status.take_success_checked(None)?, + tx_id, + })) } } diff --git a/packages/fuels-programs/src/responses/call.rs b/packages/fuels-programs/src/responses/call.rs index 91ebcf102c..f8041e7559 100644 --- a/packages/fuels-programs/src/responses/call.rs +++ b/packages/fuels-programs/src/responses/call.rs @@ -1,57 +1,32 @@ use std::fmt::Debug; -use fuel_tx::{Bytes32, Receipt}; +use fuel_tx::TxId; use fuels_core::{ codec::{LogDecoder, LogResult}, traits::{Parameterize, Tokenizable}, - types::errors::Result, + types::{errors::Result, tx_status::Success}, }; /// [`CallResponse`] is a struct that is returned by a call to the contract or script. Its value /// field holds the decoded typed value returned by the contract's method. The other field holds all /// the receipts returned by the call. -#[derive(Debug)] +#[derive(Clone, Debug)] // ANCHOR: call_response pub struct CallResponse { pub value: D, - pub receipts: Vec, - pub gas_used: u64, + pub tx_status: Success, + pub tx_id: Option, pub log_decoder: LogDecoder, - pub tx_id: Option, } // ANCHOR_END: call_response impl CallResponse { - /// Get the gas used from ScriptResult receipt - fn get_gas_used(receipts: &[Receipt]) -> u64 { - receipts - .iter() - .rfind(|r| matches!(r, Receipt::ScriptResult { .. })) - .expect("could not retrieve ScriptResult") - .gas_used() - .expect("could not retrieve gas used from ScriptResult") - } - - 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, - } - } - pub fn decode_logs(&self) -> LogResult { - self.log_decoder.decode_logs(&self.receipts) + self.log_decoder.decode_logs(&self.tx_status.receipts) } pub fn decode_logs_with_type(&self) -> Result> { - self.log_decoder.decode_logs_with_type::(&self.receipts) + self.log_decoder + .decode_logs_with_type::(&self.tx_status.receipts) } } diff --git a/packages/fuels-programs/src/responses/submit.rs b/packages/fuels-programs/src/responses/submit.rs index 0f23193290..3f085f43c6 100644 --- a/packages/fuels-programs/src/responses/submit.rs +++ b/packages/fuels-programs/src/responses/submit.rs @@ -54,12 +54,9 @@ where pub async fn response(self) -> Result> { let provider = self.call_handler.account.try_provider()?; - let receipts = provider - .tx_status(&self.tx_id) - .await? - .take_receipts_checked(Some(&self.call_handler.log_decoder))?; + let tx_status = provider.tx_status(&self.tx_id).await?; - self.call_handler.get_response(receipts) + self.call_handler.get_response(tx_status) } pub fn tx_id(&self) -> Bytes32 { @@ -78,12 +75,9 @@ impl SubmitResponse, ()> { pub async fn response(self) -> Result> { let provider = self.call_handler.account.try_provider()?; - let receipts = provider - .tx_status(&self.tx_id) - .await? - .take_receipts_checked(Some(&self.call_handler.log_decoder))?; + let tx_status = provider.tx_status(&self.tx_id).await?; - self.call_handler.get_response(receipts) + self.call_handler.get_response(tx_status) } pub fn tx_id(&self) -> Bytes32 {