From 487dc7d78c77f079b1b061fcf6ba7b7b958b09a2 Mon Sep 17 00:00:00 2001 From: hal3e Date: Wed, 7 Feb 2024 08:01:45 +0100 Subject: [PATCH] refactor: `Error` type --- examples/contracts/src/lib.rs | 105 ++++-------- examples/cookbook/src/lib.rs | 6 +- examples/predicates/src/lib.rs | 12 +- examples/providers/src/lib.rs | 11 +- .../src/rust_bindings_formatted.rs | 1 - examples/types/src/lib.rs | 12 +- examples/wallets/src/lib.rs | 9 +- packages/fuels-accounts/src/account.rs | 53 ++---- packages/fuels-accounts/src/accounts_utils.rs | 7 +- packages/fuels-accounts/src/predicate.rs | 15 +- packages/fuels-accounts/src/provider.rs | 152 +++++++----------- .../fuels-accounts/src/provider/retry_util.rs | 31 ++-- .../src/provider/retryable_client.rs | 88 ++++++---- .../src/provider/supported_versions.rs | 2 +- packages/fuels-accounts/src/wallet.rs | 90 +++-------- .../program_bindings/abigen/abigen_target.rs | 2 +- .../program_bindings/abigen/bindings/utils.rs | 4 +- .../program_bindings/custom_types/enums.rs | 2 +- .../src/program_bindings/generated_code.rs | 2 +- .../src/program_bindings/resolved_type.rs | 6 +- packages/fuels-core/src/codec/abi_decoder.rs | 68 +++++--- .../src/codec/abi_decoder/bounded_decoder.rs | 18 +-- .../experimental_bounded_decoder.rs | 14 +- packages/fuels-core/src/codec/logs.rs | 17 +- .../fuels-core/src/traits/parameterize.rs | 4 +- packages/fuels-core/src/traits/tokenizable.rs | 125 ++++++-------- packages/fuels-core/src/types.rs | 9 +- packages/fuels-core/src/types/core/bits.rs | 10 +- packages/fuels-core/src/types/core/bytes.rs | 10 +- .../fuels-core/src/types/core/identity.rs | 6 +- .../src/types/core/sized_ascii_string.rs | 34 ++-- packages/fuels-core/src/types/core/u256.rs | 4 +- .../fuels-core/src/types/enum_variants.rs | 8 +- packages/fuels-core/src/types/errors.rs | 111 +++++++------ packages/fuels-core/src/types/param_types.rs | 124 ++++++++------ .../src/types/transaction_builders.rs | 22 +-- packages/fuels-core/src/types/tx_status.rs | 16 +- .../src/types/wrappers/coin_type.rs | 17 +- .../src/types/wrappers/transaction.rs | 23 +-- .../types/wrappers/transaction_response.rs | 5 +- packages/fuels-core/src/utils.rs | 12 +- .../fuels-macros/src/derive/tokenizable.rs | 10 +- packages/fuels-macros/src/derive/try_from.rs | 2 +- packages/fuels-macros/src/derive/utils.rs | 16 +- packages/fuels-macros/src/parse_utils.rs | 12 +- .../fuels-macros/src/parse_utils/command.rs | 6 +- .../src/parse_utils/unique_lit_strs.rs | 6 +- .../src/parse_utils/unique_name_values.rs | 40 +++-- .../ui/abigen/duplicate_attribute.stderr | 6 +- .../tests/ui/abigen/invalid_abi_value.stderr | 2 +- .../tests/ui/abigen/invalid_name_value.stderr | 2 +- .../ui/abigen/invalid_program_type.stderr | 2 +- .../ui/abigen/missing_abi_attribute.stderr | 2 +- .../tests/ui/abigen/missing_name_attr.stderr | 2 +- .../ui/abigen/unrecognized_attribute.stderr | 2 +- .../attribute_must_be_named_value.stderr | 4 +- .../only_one_variant_element_supported.stderr | 4 +- ...ct_like_enum_variants_not_supported.stderr | 2 +- .../only_one_variant_element_supported.stderr | 4 +- ...ct_like_enum_variants_not_supported.stderr | 2 +- .../duplicate_wallet_names.stderr | 4 +- packages/fuels-programs/src/call_utils.rs | 4 +- packages/fuels-programs/src/contract.rs | 57 ++++--- packages/fuels-programs/src/receipt_parser.rs | 4 +- .../fuels-programs/src/submit_response.rs | 3 +- packages/fuels-test-helpers/src/accounts.rs | 2 +- .../src/fuel_bin_service.rs | 37 ++--- packages/fuels-test-helpers/src/service.rs | 8 +- packages/fuels/src/lib.rs | 3 +- packages/fuels/tests/contracts.rs | 52 +++--- packages/fuels/tests/logs.rs | 23 ++- packages/fuels/tests/predicates.rs | 20 +-- packages/fuels/tests/providers.rs | 22 +-- packages/fuels/tests/scripts.rs | 3 +- packages/fuels/tests/storage.rs | 9 +- packages/fuels/tests/types_contracts.rs | 47 +++--- packages/fuels/tests/types_predicates.rs | 10 +- packages/fuels/tests/wallets.rs | 7 +- scripts/check-docs/src/lib.rs | 2 +- 79 files changed, 791 insertions(+), 919 deletions(-) diff --git a/examples/contracts/src/lib.rs b/examples/contracts/src/lib.rs index dfef678a0..dd48664a2 100644 --- a/examples/contracts/src/lib.rs +++ b/examples/contracts/src/lib.rs @@ -3,7 +3,10 @@ mod tests { use fuels::{ core::codec::DecoderConfig, prelude::{Config, LoadConfiguration, StorageConfiguration}, - types::{errors::Result, Bits256}, + types::{ + errors::{transaction::Reason, Result}, + Bits256, + }, }; #[tokio::test] @@ -405,7 +408,7 @@ mod tests { assert!(matches!( response, - Err(Error::RevertTransactionError { .. }) + Err(Error::Transaction(Reason::Reverted { .. })) )); // ANCHOR_END: dependency_estimation_fail @@ -440,80 +443,32 @@ mod tests { #[tokio::test] #[allow(unused_variables)] async fn get_contract_outputs() -> Result<()> { - use fuels::{prelude::*, tx::Receipt}; - { - abigen!(Contract( - name = "TestContract", - abi = - "packages/fuels/tests/contracts/contract_test/out/debug/contract_test-abi.json" - )); - let wallet = launch_provider_and_get_wallet().await?; - - let contract_id = Contract::load_from( - "../../packages/fuels/tests/contracts/contract_test/out/debug/contract_test.bin", - LoadConfiguration::default(), - )? - .deploy(&wallet, TxPolicies::default()) - .await?; + use fuels::prelude::*; - let contract_methods = TestContract::new(contract_id, wallet).methods(); - - let response = contract_methods.increment_counter(162).call().await?; - let response = contract_methods.increment_counter(162).call().await; - match response { - // The transaction is valid and executes to completion - Ok(call_response) => { - let receipts: Vec = call_response.receipts; - // Do things with logs and receipts - } - // The transaction is malformed - Err(Error::ValidationError(e)) => { - println!("Transaction is malformed (ValidationError): {e}"); - } - // Failed request to provider - Err(Error::ProviderError(reason)) => { - println!("Provider request failed with reason: {reason}"); - } - // The transaction is valid but reverts - Err(Error::RevertTransactionError { - reason, receipts, .. - }) => { - println!("ContractCall failed with reason: {reason}"); - println!("Transaction receipts are: {receipts:?}"); - } - Err(_) => {} - } - } - { - // ANCHOR: deployed_contracts - abigen!(Contract( - name = "MyContract", - // Replace with your contract ABI.json path - abi = - "packages/fuels/tests/contracts/contract_test/out/debug/contract_test-abi.json" - )); - let wallet_original = launch_provider_and_get_wallet().await?; - - let wallet = wallet_original.clone(); - // Your bech32m encoded contract ID. - let contract_id: Bech32ContractId = - "fuel1vkm285ypjesypw7vhdlhnty3kjxxx4efckdycqh3ttna4xvmxtfs6murwy" - .parse() - .expect("Invalid ID"); - - let connected_contract_instance = MyContract::new(contract_id, wallet); - // You can now use the `connected_contract_instance` just as you did above! - // ANCHOR_END: deployed_contracts - - let wallet = wallet_original; - // ANCHOR: deployed_contracts_hex - let contract_id: ContractId = - "0x65b6a3d081966040bbccbb7f79ac91b48c635729c59a4c02f15ae7da999b32d3" - .parse() - .expect("Invalid ID"); - let connected_contract_instance = MyContract::new(contract_id, wallet); - // ANCHOR_END: deployed_contracts_hex - } + // ANCHOR: deployed_contracts + abigen!(Contract( + name = "MyContract", + // Replace with your contract ABI.json path + abi = "packages/fuels/tests/contracts/contract_test/out/debug/contract_test-abi.json" + )); + let wallet_original = launch_provider_and_get_wallet().await?; + + let wallet = wallet_original.clone(); + // Your bech32m encoded contract ID. + let contract_id: Bech32ContractId = + "fuel1vkm285ypjesypw7vhdlhnty3kjxxx4efckdycqh3ttna4xvmxtfs6murwy".parse()?; + + let connected_contract_instance = MyContract::new(contract_id, wallet); + // You can now use the `connected_contract_instance` just as you did above! + // ANCHOR_END: deployed_contracts + + let wallet = wallet_original; + // ANCHOR: deployed_contracts_hex + let contract_id: ContractId = + "0x65b6a3d081966040bbccbb7f79ac91b48c635729c59a4c02f15ae7da999b32d3".parse()?; + + let connected_contract_instance = MyContract::new(contract_id, wallet); + // ANCHOR_END: deployed_contracts_hex Ok(()) } diff --git a/examples/cookbook/src/lib.rs b/examples/cookbook/src/lib.rs index d37d1a286..d51413223 100644 --- a/examples/cookbook/src/lib.rs +++ b/examples/cookbook/src/lib.rs @@ -35,9 +35,7 @@ mod tests { // ANCHOR: liquidity_wallet let base_asset_id: AssetId = - "0x9ae5b658754e096e4d681c548daf46354495a437cc61492599e33fc64dcdc30c" - .parse() - .unwrap(); + "0x9ae5b658754e096e4d681c548daf46354495a437cc61492599e33fc64dcdc30c".parse()?; let asset_ids = [AssetId::default(), base_asset_id]; let asset_configs = asset_ids @@ -171,7 +169,7 @@ mod tests { let mut inputs = vec![]; let mut outputs = vec![]; for (id_string, amount) in balances { - let id = AssetId::from_str(&id_string).unwrap(); + let id = AssetId::from_str(&id_string)?; // leave the base asset to cover transaction fees if id == BASE_ASSET_ID { diff --git a/examples/predicates/src/lib.rs b/examples/predicates/src/lib.rs index b91d7927a..94cbe2d18 100644 --- a/examples/predicates/src/lib.rs +++ b/examples/predicates/src/lib.rs @@ -11,19 +11,13 @@ mod tests { async fn predicate_example() -> Result<()> { // ANCHOR: predicate_wallets let secret_key1: SecretKey = - "0x862512a2363db2b3a375c0d4bbbd27172180d89f23f2e259bac850ab02619301" - .parse() - .unwrap(); + "0x862512a2363db2b3a375c0d4bbbd27172180d89f23f2e259bac850ab02619301".parse()?; let secret_key2: SecretKey = - "0x37fa81c84ccd547c30c176b118d5cb892bdb113e8e80141f266519422ef9eefd" - .parse() - .unwrap(); + "0x37fa81c84ccd547c30c176b118d5cb892bdb113e8e80141f266519422ef9eefd".parse()?; let secret_key3: SecretKey = - "0x976e5c3fa620092c718d852ca703b6da9e3075b9f2ecb8ed42d9f746bf26aafb" - .parse() - .unwrap(); + "0x976e5c3fa620092c718d852ca703b6da9e3075b9f2ecb8ed42d9f746bf26aafb".parse()?; let mut wallet = WalletUnlocked::new_from_private_key(secret_key1, None); let mut wallet2 = WalletUnlocked::new_from_private_key(secret_key2, None); diff --git a/examples/providers/src/lib.rs b/examples/providers/src/lib.rs index f8e9f9d2a..e5228f15f 100644 --- a/examples/providers/src/lib.rs +++ b/examples/providers/src/lib.rs @@ -18,9 +18,9 @@ mod tests { let provider = Provider::connect("beta-4.fuel.network").await.unwrap(); // Setup a private key - let secret = - SecretKey::from_str("a1447cd75accc6b71a976fd3401a1f6ce318d27ba660b0315ee6ac347bf39568") - .unwrap(); + let secret = SecretKey::from_str( + "a1447cd75accc6b71a976fd3401a1f6ce318d27ba660b0315ee6ac347bf39568", + )?; // Create the wallet let wallet = WalletUnlocked::new_from_private_key(secret, Some(provider)); @@ -33,10 +33,9 @@ mod tests { let port = provider.url().split(':').last().unwrap(); // ANCHOR: local_node_address - let _provider = Provider::connect(format!("127.0.0.1:{port}")) - .await - .unwrap(); + let _provider = Provider::connect(format!("127.0.0.1:{port}")).await?; // ANCHOR_END: local_node_address + Ok(()) } diff --git a/examples/rust_bindings/src/rust_bindings_formatted.rs b/examples/rust_bindings/src/rust_bindings_formatted.rs index 3c6b02f5a..503267a6e 100644 --- a/examples/rust_bindings/src/rust_bindings_formatted.rs +++ b/examples/rust_bindings/src/rust_bindings_formatted.rs @@ -120,4 +120,3 @@ pub mod abigen_bindings { pub use abigen_bindings::my_contract_mod::MyContract; pub use abigen_bindings::my_contract_mod::MyContractConfigurables; pub use abigen_bindings::my_contract_mod::MyContractMethods; - diff --git a/examples/types/src/lib.rs b/examples/types/src/lib.rs index b418546ca..7022e850c 100644 --- a/examples/types/src/lib.rs +++ b/examples/types/src/lib.rs @@ -27,7 +27,7 @@ mod tests { // From a hex string. let hex_str = "0x0000000000000000000000000000000000000000000000000000000000000000"; - let b256 = Bytes32::from_str(hex_str).expect("failed to create Bytes32 from string"); + let b256 = Bytes32::from_str(hex_str)?; assert_eq!([0u8; 32], *b256); // ANCHOR_END: bytes32 @@ -62,7 +62,7 @@ mod tests { // From a string. let hex_str = "0x0000000000000000000000000000000000000000000000000000000000000000"; - let address = Address::from_str(hex_str).expect("failed to create Address from string"); + let address = Address::from_str(hex_str)?; assert_eq!([0u8; 32], *address); // ANCHOR_END: address Ok(()) @@ -83,8 +83,7 @@ mod tests { // From a string. let address = "fuel1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqsx2mt2"; - let bech32_address = - Bech32Address::from_str(address).expect("failed to create Bech32 address from string"); + let bech32_address = Bech32Address::from_str(address)?; assert_eq!([0u8; 32], *bech32_address.hash()); // From Address @@ -120,7 +119,7 @@ mod tests { // From a string. let hex_str = "0x0000000000000000000000000000000000000000000000000000000000000000"; - let asset_id = AssetId::from_str(hex_str).expect("failed to create AssetId from string"); + let asset_id = AssetId::from_str(hex_str)?; assert_eq!([0u8; 32], *asset_id); // ANCHOR_END: asset_id Ok(()) @@ -146,8 +145,7 @@ mod tests { // From a string. let hex_str = "0x0000000000000000000000000000000000000000000000000000000000000000"; - let contract_id = - ContractId::from_str(hex_str).expect("failed to create ContractId from string"); + let contract_id = ContractId::from_str(hex_str)?; assert_eq!([0u8; 32], *contract_id); // ANCHOR_END: contract_id Ok(()) diff --git a/examples/wallets/src/lib.rs b/examples/wallets/src/lib.rs index ec263f21f..fd3fdfb59 100644 --- a/examples/wallets/src/lib.rs +++ b/examples/wallets/src/lib.rs @@ -353,9 +353,9 @@ mod tests { let wallet = wallets.first().unwrap(); let amount = 1000; - let base_layer_address = - Address::from_str("0x4710162c2e3a95a6faff05139150017c9e38e5e280432d546fae345d6ce6d8fe") - .expect("Invalid address."); + let base_layer_address = Address::from_str( + "0x4710162c2e3a95a6faff05139150017c9e38e5e280432d546fae345d6ce6d8fe", + )?; 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 @@ -369,12 +369,13 @@ mod tests { .try_provider()? .get_message_proof(&tx_id, &msg_id, None, Some(2)) .await? - .expect("Failed to retrieve message proof."); + .expect("failed to retrieve message proof"); // Verify the amount and recipient assert_eq!(proof.amount, amount); assert_eq!(proof.recipient, base_layer_address); // ANCHOR_END: wallet_withdraw_to_base + Ok(()) } } diff --git a/packages/fuels-accounts/src/account.rs b/packages/fuels-accounts/src/account.rs index 54061a593..cc8b19486 100644 --- a/packages/fuels-accounts/src/account.rs +++ b/packages/fuels-accounts/src/account.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, fmt::Display}; +use std::collections::HashMap; use async_trait::async_trait; use fuel_core_client::client::pagination::{PaginatedResult, PaginationRequest}; @@ -10,7 +10,7 @@ use fuels_core::{ bech32::{Bech32Address, Bech32ContractId}, coin::Coin, coin_type::CoinType, - errors::{Error, Result}, + errors::Result, input::Input, message::Message, transaction::{Transaction, TxPolicies}, @@ -26,36 +26,11 @@ use crate::{ provider::{Provider, ResourceFilter}, }; -#[derive(Debug)] -pub struct AccountError(String); - -impl AccountError { - pub fn no_provider() -> Self { - Self("No provider was setup: make sure to set_provider in your account!".to_string()) - } -} - -impl Display for AccountError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{self:?}") - } -} - -impl std::error::Error for AccountError {} - -impl From for Error { - fn from(e: AccountError) -> Self { - Error::AccountError(e.0) - } -} - -pub type AccountResult = std::result::Result; - #[cfg_attr(not(target_arch = "wasm32"), async_trait)] pub trait ViewOnlyAccount: std::fmt::Debug + Send + Sync + Clone { fn address(&self) -> &Bech32Address; - fn try_provider(&self) -> AccountResult<&Provider>; + fn try_provider(&self) -> Result<&Provider>; async fn get_transactions( &self, @@ -82,7 +57,6 @@ pub trait ViewOnlyAccount: std::fmt::Debug + Send + Sync + Clone { self.try_provider()? .get_asset_balance(self.address(), *asset_id) .await - .map_err(Into::into) } /// Gets all unspent messages owned by the account. @@ -94,10 +68,7 @@ pub trait ViewOnlyAccount: std::fmt::Debug + Send + Sync + Clone { /// the coins because we are only returning the sum of UTXOs coins amount and not the UTXOs /// coins themselves. async fn get_balances(&self) -> Result> { - self.try_provider()? - .get_balances(self.address()) - .await - .map_err(Into::into) + self.try_provider()?.get_balances(self.address()).await } /// Get some spendable resources (coins and messages) of asset `asset_id` owned by the account @@ -115,10 +86,7 @@ pub trait ViewOnlyAccount: std::fmt::Debug + Send + Sync + Clone { ..Default::default() }; - self.try_provider()? - .get_spendable_resources(filter) - .await - .map_err(Into::into) + self.try_provider()?.get_spendable_resources(filter).await } } @@ -225,7 +193,7 @@ pub trait Account: ViewOnlyAccount { balance: u64, asset_id: AssetId, tx_policies: TxPolicies, - ) -> std::result::Result<(String, Vec), Error> { + ) -> Result<(String, Vec)> { let provider = self.try_provider()?; let zeroes = Bytes32::zeroed(); @@ -277,7 +245,7 @@ pub trait Account: ViewOnlyAccount { to: &Bech32Address, amount: u64, tx_policies: TxPolicies, - ) -> std::result::Result<(TxId, Nonce, Vec), Error> { + ) -> Result<(TxId, Nonce, Vec)> { let provider = self.try_provider()?; let inputs = self @@ -324,16 +292,13 @@ mod tests { use crate::wallet::WalletUnlocked; #[tokio::test] - async fn sign_and_verify() -> std::result::Result<(), Box> { + async fn sign_and_verify() -> Result<()> { // ANCHOR: sign_message let mut rng = StdRng::seed_from_u64(2322u64); let mut secret_seed = [0u8; 32]; rng.fill_bytes(&mut secret_seed); - let secret = secret_seed - .as_slice() - .try_into() - .expect("The seed size is valid"); + let secret = secret_seed.as_slice().try_into()?; // Create a wallet using the private key created above. let wallet = WalletUnlocked::new_from_private_key(secret, None); diff --git a/packages/fuels-accounts/src/accounts_utils.rs b/packages/fuels-accounts/src/accounts_utils.rs index 5d818ece5..7cf62b1cc 100644 --- a/packages/fuels-accounts/src/accounts_utils.rs +++ b/packages/fuels-accounts/src/accounts_utils.rs @@ -4,7 +4,7 @@ use fuels_core::{ constants::BASE_ASSET_ID, types::{ bech32::Bech32Address, - errors::{error, Result}, + errors::{error_transaction, Result}, input::Input, transaction_builders::TransactionBuilder, }, @@ -24,7 +24,10 @@ pub async fn calculate_missing_base_amount( let transaction_fee = tb .fee_checked_from_tx(provider) .await? - .ok_or(error!(InvalidData, "Error calculating TransactionFee"))?; + .ok_or(error_transaction!( + Other, + "error calculating `TransactionFee`" + ))?; let available_amount = available_base_amount(tb); diff --git a/packages/fuels-accounts/src/predicate.rs b/packages/fuels-accounts/src/predicate.rs index cdbdb62ba..91809afe7 100644 --- a/packages/fuels-accounts/src/predicate.rs +++ b/packages/fuels-accounts/src/predicate.rs @@ -3,12 +3,16 @@ use std::{fmt::Debug, fs}; #[cfg(feature = "std")] use fuels_core::types::{input::Input, AssetId}; use fuels_core::{ - types::{bech32::Bech32Address, errors::Result, unresolved_bytes::UnresolvedBytes}, + types::{ + bech32::Bech32Address, + errors::{error, Result}, + unresolved_bytes::UnresolvedBytes, + }, Configurables, }; #[cfg(feature = "std")] -use crate::{provider::Provider, Account, AccountError, AccountResult, ViewOnlyAccount}; +use crate::{provider::Provider, Account, ViewOnlyAccount}; #[derive(Debug, Clone)] pub struct Predicate { @@ -98,8 +102,11 @@ impl ViewOnlyAccount for Predicate { self.address() } - fn try_provider(&self) -> AccountResult<&Provider> { - self.provider.as_ref().ok_or(AccountError::no_provider()) + fn try_provider(&self) -> Result<&Provider> { + self.provider.as_ref().ok_or(error!( + Other, + "no provider available. Make sure to use `set_provider`" + )) } } diff --git a/packages/fuels-accounts/src/provider.rs b/packages/fuels-accounts/src/provider.rs index ec68195ef..9cbec2e23 100644 --- a/packages/fuels-accounts/src/provider.rs +++ b/packages/fuels-accounts/src/provider.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, fmt::Debug, io, net::SocketAddr}; +use std::{collections::HashMap, fmt::Debug, net::SocketAddr}; mod retry_util; mod retryable_client; @@ -27,7 +27,7 @@ use fuels_core::{ chain_info::ChainInfo, coin::Coin, coin_type::CoinType, - errors::{error, Error, Result}, + errors::{error, Result}, message::Message, message_proof::MessageProof, node_info::NodeInfo, @@ -40,7 +40,6 @@ use fuels_core::{ pub use retry_util::{Backoff, RetryConfig}; use supported_versions::{check_fuel_core_version_compatibility, VersionCompatibility}; use tai64::Tai64; -use thiserror::Error; #[cfg(feature = "coin-cache")] use tokio::sync::Mutex; @@ -48,8 +47,6 @@ use tokio::sync::Mutex; use crate::coin_cache::CoinsCache; use crate::provider::retryable_client::RetryableClient; -type ProviderResult = std::result::Result; - #[derive(Debug)] pub struct TransactionCost { pub min_gas_price: u64, @@ -131,28 +128,6 @@ impl Default for ResourceFilter { } } -#[derive(Debug, Error)] -pub enum ProviderError { - // Every IO error in the context of Provider comes from the gql client - #[error("Client request error: {0}")] - ClientRequestError(#[from] io::Error), - #[error("Receipts have not yet been propagated. Retry the request later.")] - ReceiptsNotPropagatedYet, - #[error("Invalid Fuel client version: {0}")] - InvalidFuelClientVersion(#[from] semver::Error), - #[error("Unsupported Fuel client version. Current version: {current}, supported version: {supported}")] - UnsupportedFuelClientVersion { - current: semver::Version, - supported: semver::Version, - }, -} - -impl From for Error { - fn from(e: ProviderError) -> Self { - Error::ProviderError(e.to_string()) - } -} - /// Encapsulates common client operations in the SDK. /// Note that you may also use `client`, which is an instance /// of `FuelClient`, directly, which provides a broader API. @@ -272,15 +247,11 @@ impl Provider { Ok(tx_id) } - pub async fn tx_status(&self, tx_id: &TxId) -> ProviderResult { - self.client - .transaction_status(tx_id) - .await - .map(Into::into) - .map_err(Into::into) + pub async fn tx_status(&self, tx_id: &TxId) -> Result { + Ok(self.client.transaction_status(tx_id).await?.into()) } - pub async fn chain_info(&self) -> ProviderResult { + pub async fn chain_info(&self) -> Result { Ok(self.client.chain_info().await?.into()) } @@ -288,8 +259,12 @@ impl Provider { &self.consensus_parameters } - fn ensure_client_version_is_supported(node_info: &NodeInfo) -> ProviderResult<()> { - let node_version = node_info.node_version.parse::()?; + fn ensure_client_version_is_supported(node_info: &NodeInfo) -> Result<()> { + let node_version = node_info + .node_version + .parse::() + .map_err(|e| error!(Provider, "could not parse Fuel client version: {}", e))?; + let VersionCompatibility { supported_version, is_major_supported, @@ -298,15 +273,18 @@ impl Provider { } = check_fuel_core_version_compatibility(node_version.clone()); if !is_major_supported || !is_minor_supported { - return Err(ProviderError::UnsupportedFuelClientVersion { - current: node_version, - supported: supported_version, - }); + return Err(error!( + Provider, + "unsupported Fuel client version. \\ + Current version: {}, supported version: {}", + node_version, + supported_version + )); } else if !is_patch_supported { tracing::warn!( fuel_client_version = %node_version, supported_version = %supported_version, - "The patch versions of the client and SDK differ.", + "the patch versions of the client and SDK differ", ); }; @@ -317,7 +295,7 @@ impl Provider { self.consensus_parameters.chain_id } - pub async fn node_info(&self) -> ProviderResult { + pub async fn node_info(&self) -> Result { Ok(self.client.node_info().await?.into()) } @@ -357,11 +335,7 @@ impl Provider { } /// Gets all unspent coins owned by address `from`, with asset ID `asset_id`. - pub async fn get_coins( - &self, - from: &Bech32Address, - asset_id: AssetId, - ) -> ProviderResult> { + pub async fn get_coins(&self, from: &Bech32Address, asset_id: AssetId) -> Result> { let mut coins: Vec = vec![]; let mut cursor = None; @@ -390,10 +364,7 @@ impl Provider { Ok(coins) } - async fn request_coins_to_spend( - &self, - filter: ResourceFilter, - ) -> ProviderResult> { + async fn request_coins_to_spend(&self, filter: ResourceFilter) -> Result> { let queries = filter.resource_queries(); let res = self @@ -406,8 +377,8 @@ impl Provider { .await? .into_iter() .flatten() - .map(|c| CoinType::try_from(c).map_err(ProviderError::ClientRequestError)) - .collect::>>()?; + .map(CoinType::try_from) + .collect::>>()?; Ok(res) } @@ -416,10 +387,7 @@ impl Provider { /// amount `amount`. The returned coins (UTXOs) are actual coins that can be spent. The number /// of coins (UXTOs) is optimized to prevent dust accumulation. #[cfg(not(feature = "coin-cache"))] - pub async fn get_spendable_resources( - &self, - filter: ResourceFilter, - ) -> ProviderResult> { + pub async fn get_spendable_resources(&self, filter: ResourceFilter) -> Result> { self.request_coins_to_spend(filter).await } @@ -431,8 +399,9 @@ impl Provider { pub async fn get_spendable_resources( &self, mut filter: ResourceFilter, - ) -> ProviderResult> { + ) -> Result> { self.extend_filter_with_cached(&mut filter).await; + self.request_coins_to_spend(filter).await } @@ -472,11 +441,11 @@ impl Provider { &self, address: &Bech32Address, asset_id: AssetId, - ) -> ProviderResult { - self.client + ) -> Result { + Ok(self + .client .balance(&address.into(), Some(&asset_id)) - .await - .map_err(Into::into) + .await?) } /// Get the balance of all spendable coins `asset_id` for contract with id `contract_id`. @@ -484,20 +453,17 @@ impl Provider { &self, contract_id: &Bech32ContractId, asset_id: AssetId, - ) -> ProviderResult { - self.client + ) -> Result { + Ok(self + .client .contract_balance(&contract_id.into(), Some(&asset_id)) - .await - .map_err(Into::into) + .await?) } /// Get all the spendable balances of all assets for address `address`. This is different from /// getting the coins because we are only returning the numbers (the sum of UTXOs coins amount /// for each asset id) and not the UTXOs coins themselves - pub async fn get_balances( - &self, - address: &Bech32Address, - ) -> ProviderResult> { + pub async fn get_balances(&self, address: &Bech32Address) -> Result> { // We don't paginate results because there are likely at most ~100 different assets in one // wallet let pagination = PaginationRequest { @@ -527,7 +493,7 @@ impl Provider { pub async fn get_contract_balances( &self, contract_id: &Bech32ContractId, - ) -> ProviderResult> { + ) -> Result> { // We don't paginate results because there are likely at most ~100 different assets in one // wallet let pagination = PaginationRequest { @@ -554,17 +520,14 @@ impl Provider { Ok(balances) } - pub async fn get_transaction_by_id( - &self, - tx_id: &TxId, - ) -> ProviderResult> { + pub async fn get_transaction_by_id(&self, tx_id: &TxId) -> Result> { Ok(self.client.transaction(tx_id).await?.map(Into::into)) } pub async fn get_transactions( &self, request: PaginationRequest, - ) -> ProviderResult> { + ) -> Result> { let pr = self.client.transactions(request).await?; Ok(PaginatedResult { @@ -580,7 +543,7 @@ impl Provider { &self, owner: &Bech32Address, request: PaginationRequest, - ) -> ProviderResult> { + ) -> Result> { let pr = self .client .transactions_by_owner(&owner.into(), request) @@ -594,11 +557,11 @@ impl Provider { }) } - pub async fn latest_block_height(&self) -> ProviderResult { + pub async fn latest_block_height(&self) -> Result { Ok(self.chain_info().await?.latest_block.header.height) } - pub async fn latest_block_time(&self) -> ProviderResult>> { + pub async fn latest_block_time(&self) -> Result>> { Ok(self.chain_info().await?.latest_block.header.time) } @@ -606,25 +569,26 @@ impl Provider { &self, blocks_to_produce: u32, start_time: Option>, - ) -> io::Result { + ) -> Result { let start_time = start_time.map(|time| Tai64::from_unix(time.timestamp()).0); - self.client + + Ok(self + .client .produce_blocks(blocks_to_produce, start_time) - .await - .map(Into::into) + .await? + .into()) } /// Get block by id. - pub async fn block(&self, block_id: &Bytes32) -> ProviderResult> { - let block = self.client.block(block_id).await?.map(Into::into); - Ok(block) + pub async fn block(&self, block_id: &Bytes32) -> Result> { + Ok(self.client.block(block_id).await?.map(Into::into)) } // - Get block(s) pub async fn get_blocks( &self, request: PaginationRequest, - ) -> ProviderResult> { + ) -> Result> { let pr = self.client.blocks(request).await?; Ok(PaginatedResult { @@ -669,6 +633,7 @@ impl Provider { tolerance: f64, ) -> Result { let gas_used = self.get_gas_used(&self.dry_run_no_validation(tx).await?); + Ok((gas_used as f64 * (1.0 + tolerance)) as u64) } @@ -684,12 +649,13 @@ impl Provider { .unwrap_or(0) } - pub async fn get_messages(&self, from: &Bech32Address) -> ProviderResult> { + pub async fn get_messages(&self, from: &Bech32Address) -> Result> { let pagination = PaginationRequest { cursor: None, results: 100, direction: PageDirection::Forward, }; + Ok(self .client .messages(Some(&from.into()), pagination) @@ -706,7 +672,7 @@ impl Provider { nonce: &Nonce, commit_block_id: Option<&Bytes32>, commit_block_height: Option, - ) -> ProviderResult> { + ) -> Result> { let proof = self .client .message_proof( @@ -717,11 +683,13 @@ impl Provider { ) .await? .map(Into::into); + Ok(proof) } pub fn with_retry_config(mut self, retry_config: RetryConfig) -> Self { self.client.set_retry_config(retry_config); + self } } @@ -731,14 +699,12 @@ impl DryRunner for Provider { async fn dry_run_and_get_used_gas(&self, tx: FuelTransaction, tolerance: f32) -> Result { let receipts = self.client.dry_run_opt(&tx, Some(false)).await?; let gas_used = self.get_gas_used(&receipts); + Ok((gas_used as f64 * (1.0 + tolerance as f64)) as u64) } async fn min_gas_price(&self) -> Result { - self.node_info() - .await - .map(|ni| ni.min_gas_price) - .map_err(Into::into) + Ok(self.node_info().await.map(|ni| ni.min_gas_price)?) } fn consensus_parameters(&self) -> &ConsensusParameters { diff --git a/packages/fuels-accounts/src/provider/retry_util.rs b/packages/fuels-accounts/src/provider/retry_util.rs index 631ba81a2..fa9450df5 100644 --- a/packages/fuels-accounts/src/provider/retry_util.rs +++ b/packages/fuels-accounts/src/provider/retry_util.rs @@ -1,6 +1,6 @@ use std::{fmt::Debug, future::Future, num::NonZeroU32, time::Duration}; -use fuels_core::types::errors::{error, Result as SdkResult}; +use fuels_core::types::errors::{error, Result}; /// A set of strategies to control retry intervals between attempts. /// @@ -81,9 +81,9 @@ pub struct RetryConfig { // ANCHOR_END: retry_config impl RetryConfig { - pub fn new(max_attempts: u32, interval: Backoff) -> SdkResult { + pub fn new(max_attempts: u32, interval: Backoff) -> Result { let max_attempts = NonZeroU32::new(max_attempts) - .ok_or_else(|| error!(InvalidData, "`max_attempts` must be greater than 0."))?; + .ok_or_else(|| error!(Other, "`max_attempts` must be greater than `0`"))?; Ok(RetryConfig { max_attempts, @@ -95,7 +95,7 @@ impl RetryConfig { impl Default for RetryConfig { fn default() -> Self { Self { - max_attempts: NonZeroU32::new(1).expect("Should not fail!"), + max_attempts: NonZeroU32::new(1).expect("should not fail"), interval: Default::default(), } } @@ -145,7 +145,7 @@ where tokio::time::sleep(retry_config.interval.wait_duration(attempt)).await; } - last_result.expect("Should not happen") + last_result.expect("should not happen") } #[cfg(test)] @@ -153,10 +153,7 @@ mod tests { mod retry_until { use std::time::{Duration, Instant}; - use fuels_core::{ - error, - types::errors::{Error, Result}, - }; + use fuels_core::types::errors::{error, Result}; use tokio::sync::Mutex; use crate::provider::{retry_util, Backoff, RetryConfig}; @@ -164,7 +161,7 @@ mod tests { #[tokio::test] async fn returns_last_received_response() -> Result<()> { // given - let err_msgs = ["Err1", "Err2", "Err3"]; + let err_msgs = ["err1", "err2", "err3"]; let number_of_attempts = Mutex::new(0usize); let will_always_fail = || async { @@ -183,7 +180,7 @@ mod tests { retry_util::retry(will_always_fail, &retry_options, should_retry_fn).await; // then - assert_eq!(response, "Err3"); + assert_eq!(response, "err3"); Ok(()) } @@ -216,7 +213,7 @@ mod tests { let will_fail_and_record_timestamp = || async { timestamps.lock().await.push(Instant::now()); - Result::<()>::Err(Error::InvalidData("Error".to_string())) + Result::<()>::Err(error!(Other, "error")) }; let should_retry_fn = |_res: &_| -> bool { true }; @@ -244,7 +241,7 @@ mod tests { assert!( timestamps_spaced_out_at_least_100_mills, - "Retry did not wait for the specified time between attempts." + "retry did not wait for the specified time between attempts" ); Ok(()) @@ -257,7 +254,7 @@ mod tests { let will_fail_and_record_timestamp = || async { timestamps.lock().await.push(Instant::now()); - Result::<()>::Err(Error::InvalidData("Error".to_string())) + Result::<()>::Err(error!(Other, "error")) }; let should_retry_fn = |_res: &_| -> bool { true }; @@ -286,7 +283,7 @@ mod tests { assert!( timestamps_spaced_out_at_least_100_mills, - "Retry did not wait for the specified time between attempts." + "retry did not wait for the specified time between attempts" ); Ok(()) @@ -299,7 +296,7 @@ mod tests { let will_fail_and_record_timestamp = || async { timestamps.lock().await.push(Instant::now()); - Result::<()>::Err(error!(InvalidData, "Error")) + Result::<()>::Err(error!(Other, "error")) }; let should_retry_fn = |_res: &_| -> bool { true }; @@ -329,7 +326,7 @@ mod tests { assert!( timestamps_spaced_out_at_least_100_mills, - "Retry did not wait for the specified time between attempts." + "retry did not wait for the specified time between attempts" ); Ok(()) diff --git a/packages/fuels-accounts/src/provider/retryable_client.rs b/packages/fuels-accounts/src/provider/retryable_client.rs index 450652fb1..f71d36704 100644 --- a/packages/fuels-accounts/src/provider/retryable_client.rs +++ b/packages/fuels-accounts/src/provider/retryable_client.rs @@ -2,16 +2,33 @@ use std::{future::Future, io}; use fuel_core_client::client::{ pagination::{PaginatedResult, PaginationRequest}, - types, - types::{primitives::BlockId, TransactionResponse, TransactionStatus}, + types::{ + primitives::{BlockId, TransactionId}, + Balance, Block, ChainInfo, Coin, CoinType, ContractBalance, Message, MessageProof, + NodeInfo, TransactionResponse, TransactionStatus, + }, FuelClient, }; use fuel_tx::{Receipt, Transaction, TxId, UtxoId}; use fuel_types::{Address, AssetId, BlockHeight, ContractId, Nonce}; -use fuels_core::{error, types::errors::Result}; +use fuels_core::types::errors::{error, Error, Result}; use crate::provider::{retry_util, RetryConfig}; +#[derive(Debug, thiserror::Error)] +pub(crate) enum RequestError { + #[error(transparent)] + IO(#[from] io::Error), +} + +type RequestResult = std::result::Result; + +impl From for Error { + fn from(e: RequestError) -> Self { + Error::Provider(e.to_string()) + } +} + #[derive(Debug, Clone)] pub(crate) struct RetryableClient { client: FuelClient, @@ -22,7 +39,8 @@ pub(crate) struct RetryableClient { impl RetryableClient { pub(crate) fn new(url: impl AsRef, retry_config: RetryConfig) -> Result { let url = url.as_ref().to_string(); - let client = FuelClient::new(&url).map_err(|err| error!(InfrastructureError, "{err}"))?; + let client = FuelClient::new(&url).map_err(|e| error!(Provider, "{e}"))?; + Ok(Self { client, retry_config, @@ -38,48 +56,52 @@ impl RetryableClient { self.retry_config = retry_config; } - async fn our_retry(&self, action: impl Fn() -> Fut) -> io::Result + async fn our_retry(&self, action: impl Fn() -> Fut) -> RequestResult where Fut: Future>, { - retry_util::retry(action, &self.retry_config, |result| result.is_err()).await + Ok(retry_util::retry(action, &self.retry_config, |result| result.is_err()).await?) } // DELEGATION START - pub async fn health(&self) -> io::Result { + pub async fn health(&self) -> RequestResult { self.our_retry(|| self.client.health()).await } - pub async fn transaction(&self, id: &TxId) -> io::Result> { + pub async fn transaction(&self, id: &TxId) -> RequestResult> { self.our_retry(|| self.client.transaction(id)).await } - pub(crate) async fn chain_info(&self) -> io::Result { + pub(crate) async fn chain_info(&self) -> RequestResult { self.our_retry(|| self.client.chain_info()).await } - pub async fn await_transaction_commit(&self, id: &TxId) -> io::Result { + pub async fn await_transaction_commit(&self, id: &TxId) -> RequestResult { self.our_retry(|| self.client.await_transaction_commit(id)) .await } - pub async fn submit_and_await_commit(&self, tx: &Transaction) -> io::Result { + pub async fn submit_and_await_commit( + &self, + tx: &Transaction, + ) -> RequestResult { self.our_retry(|| self.client.submit_and_await_commit(tx)) .await } - pub async fn submit(&self, tx: &Transaction) -> io::Result { + pub async fn submit(&self, tx: &Transaction) -> RequestResult { self.our_retry(|| self.client.submit(tx)).await } - pub async fn transaction_status(&self, id: &TxId) -> io::Result { + pub async fn transaction_status(&self, id: &TxId) -> RequestResult { self.our_retry(|| self.client.transaction_status(id)).await } - pub async fn node_info(&self) -> io::Result { + pub async fn node_info(&self) -> RequestResult { self.our_retry(|| self.client.node_info()).await } - pub async fn dry_run(&self, tx: &Transaction) -> io::Result> { + + pub async fn dry_run(&self, tx: &Transaction) -> RequestResult> { self.our_retry(|| self.client.dry_run(tx)).await } @@ -87,7 +109,7 @@ impl RetryableClient { &self, tx: &Transaction, utxo_validation: Option, - ) -> io::Result> { + ) -> RequestResult> { self.our_retry(|| self.client.dry_run_opt(tx, utxo_validation)) .await } @@ -97,7 +119,7 @@ impl RetryableClient { owner: &Address, asset_id: Option<&AssetId>, request: PaginationRequest, - ) -> io::Result> { + ) -> RequestResult> { self.our_retry(move || self.client.coins(owner, asset_id, request.clone())) .await } @@ -107,13 +129,15 @@ impl RetryableClient { owner: &Address, spend_query: Vec<(AssetId, u64, Option)>, excluded_ids: Option<(Vec, Vec)>, - ) -> io::Result>> { - self.client - .coins_to_spend(owner, spend_query, excluded_ids) - .await + ) -> RequestResult>> { + self.our_retry(move || { + self.client + .coins_to_spend(owner, spend_query.clone(), excluded_ids.clone()) + }) + .await } - pub async fn balance(&self, owner: &Address, asset_id: Option<&AssetId>) -> io::Result { + pub async fn balance(&self, owner: &Address, asset_id: Option<&AssetId>) -> RequestResult { self.our_retry(|| self.client.balance(owner, asset_id)) .await } @@ -122,7 +146,7 @@ impl RetryableClient { &self, id: &ContractId, asset: Option<&AssetId>, - ) -> io::Result { + ) -> RequestResult { self.our_retry(|| self.client.contract_balance(id, asset)) .await } @@ -131,7 +155,7 @@ impl RetryableClient { &self, contract: &ContractId, request: PaginationRequest, - ) -> io::Result> { + ) -> RequestResult> { self.our_retry(|| self.client.contract_balances(contract, request.clone())) .await } @@ -140,7 +164,7 @@ impl RetryableClient { &self, owner: &Address, request: PaginationRequest, - ) -> io::Result> { + ) -> RequestResult> { self.our_retry(|| self.client.balances(owner, request.clone())) .await } @@ -148,7 +172,7 @@ impl RetryableClient { pub async fn transactions( &self, request: PaginationRequest, - ) -> io::Result> { + ) -> RequestResult> { self.our_retry(|| self.client.transactions(request.clone())) .await } @@ -157,7 +181,7 @@ impl RetryableClient { &self, owner: &Address, request: PaginationRequest, - ) -> io::Result> { + ) -> RequestResult> { self.our_retry(|| self.client.transactions_by_owner(owner, request.clone())) .await } @@ -166,7 +190,7 @@ impl RetryableClient { &self, blocks_to_produce: u32, start_timestamp: Option, - ) -> io::Result { + ) -> RequestResult { self.our_retry(|| { self.client .produce_blocks(blocks_to_produce, start_timestamp) @@ -174,14 +198,14 @@ impl RetryableClient { .await } - pub async fn block(&self, id: &BlockId) -> io::Result> { + pub async fn block(&self, id: &BlockId) -> RequestResult> { self.our_retry(|| self.client.block(id)).await } pub async fn blocks( &self, request: PaginationRequest, - ) -> io::Result> { + ) -> RequestResult> { self.our_retry(|| self.client.blocks(request.clone())).await } @@ -189,7 +213,7 @@ impl RetryableClient { &self, owner: Option<&Address>, request: PaginationRequest, - ) -> io::Result> { + ) -> RequestResult> { self.our_retry(|| self.client.messages(owner, request.clone())) .await } @@ -201,7 +225,7 @@ impl RetryableClient { nonce: &Nonce, commit_block_id: Option<&BlockId>, commit_block_height: Option, - ) -> io::Result> { + ) -> RequestResult> { self.our_retry(|| { self.client .message_proof(transaction_id, nonce, commit_block_id, commit_block_height) diff --git a/packages/fuels-accounts/src/provider/supported_versions.rs b/packages/fuels-accounts/src/provider/supported_versions.rs index bd67bb516..3ef803575 100644 --- a/packages/fuels-accounts/src/provider/supported_versions.rs +++ b/packages/fuels-accounts/src/provider/supported_versions.rs @@ -1,7 +1,7 @@ use semver::Version; fn get_supported_fuel_core_version() -> Version { - "0.22.0".parse().unwrap() + "0.22.0".parse().expect("is valid version") } #[derive(Debug, PartialEq, Eq)] diff --git a/packages/fuels-accounts/src/wallet.rs b/packages/fuels-accounts/src/wallet.rs index b17eef2a8..5e1147cc6 100644 --- a/packages/fuels-accounts/src/wallet.rs +++ b/packages/fuels-accounts/src/wallet.rs @@ -2,57 +2,24 @@ use std::{fmt, ops, path::Path}; use async_trait::async_trait; use elliptic_curve::rand_core; -use eth_keystore::KeystoreError; use fuel_crypto::{Message, PublicKey, SecretKey, Signature}; use fuels_core::{ traits::Signer, types::{ bech32::{Bech32Address, FUEL_BECH32_HRP}, - errors::{Error, Result}, + errors::{error, Result}, input::Input, transaction_builders::TransactionBuilder, AssetId, }, }; use rand::{CryptoRng, Rng}; -use thiserror::Error; use zeroize::{Zeroize, ZeroizeOnDrop}; -use crate::{ - provider::{Provider, ProviderError}, - Account, AccountError, AccountResult, ViewOnlyAccount, -}; +use crate::{provider::Provider, Account, ViewOnlyAccount}; pub const DEFAULT_DERIVATION_PATH_PREFIX: &str = "m/44'/1179993420'"; -#[derive(Error, Debug)] -/// Error thrown by the Wallet module -pub enum WalletError { - /// Error propagated from the hex crate. - #[error(transparent)] - Hex(#[from] hex::FromHexError), - /// Error propagated by parsing of a slice - #[error("Failed to parse slice")] - Parsing(#[from] std::array::TryFromSliceError), - /// Keystore error - #[error(transparent)] - KeystoreError(#[from] KeystoreError), - #[error(transparent)] - FuelCrypto(#[from] fuel_crypto::Error), - #[error(transparent)] - ProviderError(#[from] ProviderError), - #[error("Called `try_provider` method on wallet where no provider was set up")] - NoProviderError, -} - -impl From for Error { - fn from(e: WalletError) -> Self { - Error::WalletError(e.to_string()) - } -} - -type WalletResult = std::result::Result; - /// A FuelVM-compatible wallet that can be used to list assets, balances and more. /// /// Note that instances of the `Wallet` type only know their public address, and as a result can @@ -115,8 +82,11 @@ impl ViewOnlyAccount for Wallet { self.address() } - fn try_provider(&self) -> AccountResult<&Provider> { - self.provider.as_ref().ok_or(AccountError::no_provider()) + fn try_provider(&self) -> Result<&Provider> { + self.provider.as_ref().ok_or(error!( + Other, + "no provider available. Make sure to use `set_provider`" + )) } } @@ -152,10 +122,7 @@ impl WalletUnlocked { /// Creates a new wallet from a mnemonic phrase. /// The default derivation path is used. - pub fn new_from_mnemonic_phrase( - phrase: &str, - provider: Option, - ) -> WalletResult { + pub fn new_from_mnemonic_phrase(phrase: &str, provider: Option) -> Result { let path = format!("{DEFAULT_DERIVATION_PATH_PREFIX}/0'/0/0"); Self::new_from_mnemonic_phrase_with_path(phrase, provider, &path) } @@ -166,7 +133,7 @@ impl WalletUnlocked { phrase: &str, provider: Option, path: &str, - ) -> WalletResult { + ) -> Result { let secret_key = SecretKey::new_from_mnemonic_phrase_with_path(phrase, path)?; Ok(Self::new_from_private_key(secret_key, provider)) @@ -178,16 +145,16 @@ impl WalletUnlocked { rng: &mut R, password: S, provider: Option, - ) -> WalletResult<(Self, String)> + ) -> Result<(Self, String)> where P: AsRef, R: Rng + CryptoRng + rand_core::CryptoRng, S: AsRef<[u8]>, { - let (secret, uuid) = eth_keystore::new(dir, rng, password, None)?; + let (secret, uuid) = + eth_keystore::new(dir, rng, password, None).map_err(|e| error!(Other, "{e}"))?; - let secret_key = - SecretKey::try_from(secret.as_slice()).expect("A new secret should be correct size"); + let secret_key = SecretKey::try_from(secret.as_slice()).expect("should have correct size"); let wallet = Self::new_from_private_key(secret_key, provider); @@ -196,33 +163,25 @@ impl WalletUnlocked { /// Encrypts the wallet's private key with the given password and saves it /// to the given path. - pub fn encrypt(&self, dir: P, password: S) -> WalletResult + pub fn encrypt(&self, dir: P, password: S) -> Result where P: AsRef, S: AsRef<[u8]>, { let mut rng = rand::thread_rng(); - Ok(eth_keystore::encrypt_key( - dir, - &mut rng, - *self.private_key, - password, - None, - )?) + eth_keystore::encrypt_key(dir, &mut rng, *self.private_key, password, None) + .map_err(|e| error!(Other, "{e}")) } /// Recreates a wallet from an encrypted JSON wallet given the provided path and password. - pub fn load_keystore( - keypath: P, - password: S, - provider: Option, - ) -> WalletResult + pub fn load_keystore(keypath: P, password: S, provider: Option) -> Result where P: AsRef, S: AsRef<[u8]>, { - let secret = eth_keystore::decrypt_key(keypath, password)?; + let secret = + eth_keystore::decrypt_key(keypath, password).map_err(|e| error!(Other, "{e}"))?; let secret_key = SecretKey::try_from(secret.as_slice()) .expect("Decrypted key should have a correct size"); Ok(Self::new_from_private_key(secret_key, provider)) @@ -238,8 +197,11 @@ impl ViewOnlyAccount for WalletUnlocked { self.wallet.address() } - fn try_provider(&self) -> AccountResult<&Provider> { - self.provider.as_ref().ok_or(AccountError::no_provider()) + fn try_provider(&self) -> Result<&Provider> { + self.provider.as_ref().ok_or(error!( + Other, + "no provider available. Make sure to use `set_provider`" + )) } } @@ -300,7 +262,7 @@ impl ops::Deref for WalletUnlocked { /// Generates a random mnemonic phrase given a random number generator and the number of words to /// generate, `count`. -pub fn generate_mnemonic_phrase(rng: &mut R, count: usize) -> WalletResult { +pub fn generate_mnemonic_phrase(rng: &mut R, count: usize) -> Result { Ok(fuel_crypto::generate_mnemonic_phrase(rng, count)?) } @@ -338,8 +300,8 @@ mod tests { #[tokio::test] async fn mnemonic_generation() -> Result<()> { let mnemonic = generate_mnemonic_phrase(&mut rand::thread_rng(), 12)?; - let _wallet = WalletUnlocked::new_from_mnemonic_phrase(&mnemonic, None)?; + Ok(()) } diff --git a/packages/fuels-code-gen/src/program_bindings/abigen/abigen_target.rs b/packages/fuels-code-gen/src/program_bindings/abigen/abigen_target.rs index d8a1595b8..1fd8649a4 100644 --- a/packages/fuels-code-gen/src/program_bindings/abigen/abigen_target.rs +++ b/packages/fuels-code-gen/src/program_bindings/abigen/abigen_target.rs @@ -65,7 +65,7 @@ impl FromStr for ProgramType { "Predicate" => ProgramType::Predicate, _ => { return Err(error!( - "'{string}' is not a valid program type. Expected one of: 'Script', 'Contract', 'Predicate'." + "`{string}` is not a valid program type. Expected one of: `Script`, `Contract`, `Predicate`" )) } }; diff --git a/packages/fuels-code-gen/src/program_bindings/abigen/bindings/utils.rs b/packages/fuels-code-gen/src/program_bindings/abigen/bindings/utils.rs index 8b17b50c8..29f35e580 100644 --- a/packages/fuels-code-gen/src/program_bindings/abigen/bindings/utils.rs +++ b/packages/fuels-code-gen/src/program_bindings/abigen/bindings/utils.rs @@ -32,7 +32,7 @@ mod tests { fn correctly_extracts_the_main_fn() { let functions = ["fn_1", "main", "fn_2"].map(given_a_fun_named); - let fun = extract_main_fn(&functions).expect("Should have succeeded"); + let fun = extract_main_fn(&functions).expect("should have succeeded"); assert_eq!(*fun, functions[1]); } @@ -41,7 +41,7 @@ mod tests { fn fails_if_there_is_more_than_one_main_fn() { let functions = ["main", "another", "main"].map(given_a_fun_named); - let err = extract_main_fn(&functions).expect_err("Should have failed."); + let err = extract_main_fn(&functions).expect_err("should have failed"); assert_eq!( err.to_string(), diff --git a/packages/fuels-code-gen/src/program_bindings/custom_types/enums.rs b/packages/fuels-code-gen/src/program_bindings/custom_types/enums.rs index 35c120594..efe8bfde2 100644 --- a/packages/fuels-code-gen/src/program_bindings/custom_types/enums.rs +++ b/packages/fuels-code-gen/src/program_bindings/custom_types/enums.rs @@ -25,7 +25,7 @@ pub(crate) fn expand_custom_enum( let components = Components::new(&type_decl.components, false, enum_type_path.parent())?; if components.is_empty() { - return Err(error!("Enum must have at least one component!")); + return Err(error!("enum must have at least one component")); } let generics = extract_generic_parameters(type_decl); diff --git a/packages/fuels-code-gen/src/program_bindings/generated_code.rs b/packages/fuels-code-gen/src/program_bindings/generated_code.rs index 54a0a0955..388a3bece 100644 --- a/packages/fuels-code-gen/src/program_bindings/generated_code.rs +++ b/packages/fuels-code-gen/src/program_bindings/generated_code.rs @@ -343,6 +343,6 @@ mod tests { } fn given_type_path(path: &str) -> TypePath { - TypePath::new(path).expect("Hand crafted, should be valid.") + TypePath::new(path).expect("hand crafted, should be valid") } } diff --git a/packages/fuels-code-gen/src/program_bindings/resolved_type.rs b/packages/fuels-code-gen/src/program_bindings/resolved_type.rs index ab6d809bc..32cc49ef8 100644 --- a/packages/fuels-code-gen/src/program_bindings/resolved_type.rs +++ b/packages/fuels-code-gen/src/program_bindings/resolved_type.rs @@ -133,7 +133,7 @@ impl TypeResolver { } let type_field = &type_application.type_decl.type_field; - Err(error!("Could not resolve '{type_field}' to any known type")) + Err(error!("could not resolve '{type_field}' to any known type")) } fn resolve_multiple( @@ -149,7 +149,7 @@ impl TypeResolver { fn is_deprecated(type_field: &str) -> Result<()> { match type_field { "struct std::u256::U256" | "struct U256" => { - Err(error!("{} is deprecated. Use `u256` instead.", type_field)) + Err(error!("{} is deprecated. Use `u256` instead", type_field)) } _ => Ok(()), } @@ -178,7 +178,7 @@ impl TypeResolver { [single_type] => single_type, other => { return Err(error!( - "Array must have only one component! Actual components: {other:?}" + "array must have only one component. Actual components: {other:?}" )); } }; diff --git a/packages/fuels-core/src/codec/abi_decoder.rs b/packages/fuels-core/src/codec/abi_decoder.rs index 2d7bcbd4a..7262c53f4 100644 --- a/packages/fuels-core/src/codec/abi_decoder.rs +++ b/packages/fuels-core/src/codec/abi_decoder.rs @@ -2,14 +2,13 @@ mod bounded_decoder; #[cfg(experimental)] mod experimental_bounded_decoder; +#[cfg(experimental)] +use crate::codec::abi_decoder::experimental_bounded_decoder::ExperimentalBoundedDecoder; use crate::{ codec::abi_decoder::bounded_decoder::BoundedDecoder, types::{errors::Result, param_types::ParamType, Token}, }; -#[cfg(experimental)] -use crate::codec::abi_decoder::experimental_bounded_decoder::ExperimentalBoundedDecoder; - #[derive(Debug, Clone, Copy)] pub struct DecoderConfig { /// Entering a struct, array, tuple, enum or vector increases the depth. Decoding will fail if @@ -118,6 +117,7 @@ mod tests { let decoded = ABIDecoder::default().decode(&ParamType::U32, &data)?; assert_eq!(decoded, Token::U32(u32::MAX)); + Ok(()) } @@ -154,6 +154,7 @@ mod tests { Token::U256(U256::MAX), ]; assert_eq!(decoded, expected); + Ok(()) } @@ -167,6 +168,7 @@ mod tests { let expected = vec![Token::Bool(true), Token::Bool(false)]; assert_eq!(decoded, expected); + Ok(()) } @@ -181,6 +183,7 @@ mod tests { let decoded = ABIDecoder::default().decode(&ParamType::B256, &data)?; assert_eq!(decoded, Token::B256(data)); + Ok(()) } @@ -205,6 +208,7 @@ mod tests { ]; assert_eq!(decoded, expected); + Ok(()) } @@ -225,6 +229,7 @@ mod tests { ))]; assert_eq!(decoded, expected); + Ok(()) } @@ -238,6 +243,7 @@ mod tests { let expected = vec![Token::Array(vec![Token::U8(255), Token::U8(42)])]; assert_eq!(decoded, expected); + Ok(()) } @@ -261,6 +267,7 @@ mod tests { let expected = Token::Struct(vec![Token::U8(1), Token::Bool(true)]); assert_eq!(decoded, expected); + Ok(()) } @@ -272,6 +279,7 @@ mod tests { let expected = Token::Bytes(data.to_vec()); assert_eq!(decoded, expected); + Ok(()) } @@ -298,6 +306,7 @@ mod tests { let expected = vec![Token::Enum(Box::new((0, Token::U32(42), inner_enum_types)))]; assert_eq!(decoded, expected); + Ok(()) } @@ -350,6 +359,7 @@ mod tests { Token::U32(54321), ]); assert_eq!(decoded, expected); + Ok(()) } @@ -396,6 +406,7 @@ mod tests { ]; assert_eq!(decoded, Token::Struct(my_nested_struct)); + Ok(()) } @@ -472,6 +483,7 @@ mod tests { let expected: Vec = vec![foo, u8_arr, b256]; assert_eq!(decoded, expected); + Ok(()) } @@ -489,6 +501,7 @@ mod tests { let expected = Token::Struct(vec![Token::Unit, Token::U64(u64::MAX)]); assert_eq!(actual, expected); + Ok(()) } @@ -506,6 +519,7 @@ mod tests { let expected_enum = Token::Enum(Box::new((1, Token::Unit, variants))); assert_eq!(result, expected_enum); + Ok(()) } @@ -521,10 +535,11 @@ mod tests { let result = ABIDecoder::default().decode(&enum_type, &data); - let error = result.expect_err("Should have resulted in an error"); + let error = result.expect_err("should have resulted in an error"); + + let expected_msg = "discriminant `1` doesn't point to any variant: "; + assert!(matches!(error, Error::Other(str) if str.starts_with(expected_msg))); - let expected_msg = "Discriminant '1' doesn't point to any variant: "; - assert!(matches!(error, Error::InvalidData(str) if str.starts_with(expected_msg))); Ok(()) } @@ -532,7 +547,7 @@ mod tests { pub fn division_by_zero() { let param_type = Vec::<[u16; 0]>::param_type(); let result = ABIDecoder::default().decode(¶m_type, &[]); - assert!(matches!(result, Err(Error::InvalidType(_)))); + assert!(matches!(result, Err(Error::Codec(_)))); } #[test] @@ -557,7 +572,7 @@ mod tests { }, &[], ); - assert!(matches!(result, Err(Error::InvalidType(_)))); + assert!(matches!(result, Err(Error::Codec(_)))); } #[test] @@ -573,7 +588,7 @@ mod tests { }, &[], ); - assert!(matches!(result, Err(Error::InvalidType(_)))); + assert!(matches!(result, Err(Error::Codec(_)))); } #[test] @@ -582,7 +597,7 @@ mod tests { &Array(Box::new(Array(Box::new(Tuple(vec![])), usize::MAX)), 1), &[], ); - assert!(matches!(result, Err(Error::InvalidType(_)))); + assert!(matches!(result, Err(Error::Codec(_)))); } #[test] @@ -592,14 +607,14 @@ mod tests { param_type = Vector(Box::new(param_type)); } let result = ABIDecoder::default().decode(¶m_type, &[]); - assert!(matches!(result, Err(Error::InvalidType(_)))); + assert!(matches!(result, Err(Error::Codec(_)))); } #[test] pub fn capacity_maloc() { let param_type = Array(Box::new(U8), usize::MAX); let result = ABIDecoder::default().decode(¶m_type, &[]); - assert!(matches!(result, Err(Error::InvalidData(_)))); + assert!(matches!(result, Err(Error::Codec(_)))); } #[test] @@ -631,10 +646,9 @@ mod tests { // fails if there is more than one variant using heap type in the enum let error = ABIDecoder::default() .decode(&enum_param_type, &data) - .expect_err("Should fail"); + .expect_err("should fail"); let expected_error = - "Invalid type: Enums currently support only one heap-type variant. Found: 2" - .to_string(); + "codec: enums currently support only one heap-type variant. Found: 2".to_string(); assert_eq!(error.to_string(), expected_error); Ok(()) @@ -659,13 +673,13 @@ mod tests { .decode(&enum_param_type, &[]) .expect_err("should have failed"); - let Error::InvalidType(msg) = err else { - panic!("Unexpected err: {err}"); + let Error::Codec(msg) = err else { + panic!("unexpected err: {err}"); }; assert_eq!( msg, - "Enums currently support only one level deep heap types." + "enums currently support only one level deep heap types" ); } @@ -676,7 +690,7 @@ mod tests { max_depth: MAX_DEPTH, ..Default::default() }; - let msg = format!("Depth limit ({MAX_DEPTH}) reached while decoding. Try increasing it."); + let msg = format!("depth limit `{MAX_DEPTH}` reached while decoding. Try increasing it"); // for each nested enum so that it may read the discriminant let data = [0; MAX_DEPTH * WORD_SIZE]; @@ -737,7 +751,7 @@ mod tests { assert_decoding_failed_w_data( config, ¶m_type, - "Token limit (3) reached while decoding. Try increasing it.", + "token limit `3` reached while decoding. Try increasing it", &data, ); } @@ -749,14 +763,15 @@ mod tests { let err = ABIDecoder::default() .decode(¶m_type, &[]) - .expect_err("Vectors of ZST should be prohibited"); + .expect_err("vectors of ZST should be prohibited"); - let Error::InvalidType(msg) = err else { - panic!("Expected error of type InvalidType") + let Error::Codec(msg) = err else { + panic!("expected error of type Codec") }; + assert_eq!( msg, - "Cannot calculate the number of elements because the type is zero-sized." + "cannot calculate the number of elements because the type is zero-sized" ); } @@ -790,9 +805,10 @@ mod tests { let err = decoder.decode(param_type, data); - let Err(Error::InvalidType(actual_msg)) = err else { - panic!("Unexpected an InvalidType error! Got: {err:?}"); + let Err(Error::Codec(actual_msg)) = err else { + panic!("unexpected an Codec error! Got: {err:?}"); }; + assert_eq!(actual_msg, msg); } diff --git a/packages/fuels-core/src/codec/abi_decoder/bounded_decoder.rs b/packages/fuels-core/src/codec/abi_decoder/bounded_decoder.rs index d7556c2ff..98672357e 100644 --- a/packages/fuels-core/src/codec/abi_decoder/bounded_decoder.rs +++ b/packages/fuels-core/src/codec/abi_decoder/bounded_decoder.rs @@ -26,8 +26,8 @@ const B256_BYTES_SIZE: usize = 4 * WORD_SIZE; impl BoundedDecoder { pub(crate) fn new(config: DecoderConfig) -> Self { - let depth_tracker = CounterWithLimit::new(config.max_depth, "Depth"); - let token_tracker = CounterWithLimit::new(config.max_tokens, "Token"); + let depth_tracker = CounterWithLimit::new(config.max_depth, "depth"); + let token_tracker = CounterWithLimit::new(config.max_tokens, "token"); Self { depth_tracker, token_tracker, @@ -389,8 +389,8 @@ impl CounterWithLimit { self.count += 1; if self.count > self.max { Err(error!( - InvalidType, - "{} limit ({}) reached while decoding. Try increasing it.", self.name, self.max + Codec, + "{} limit `{}` reached while decoding. Try increasing it", self.name, self.max )) } else { Ok(()) @@ -425,7 +425,7 @@ fn peek_u32(bytes: &[u8]) -> Result { let slice = peek_fixed::(bytes)?; let bytes = slice[WORD_SIZE - BYTES..] .try_into() - .expect("peek_u32: You must use a slice containing exactly 4B."); + .expect("peek_u32: You must use a slice containing exactly 4B"); Ok(u32::from_be_bytes(bytes)) } @@ -435,7 +435,7 @@ fn peek_u16(bytes: &[u8]) -> Result { let slice = peek_fixed::(bytes)?; let bytes = slice[WORD_SIZE - BYTES..] .try_into() - .expect("peek_u16: You must use a slice containing exactly 2B."); + .expect("peek_u16: You must use a slice containing exactly 2B"); Ok(u16::from_be_bytes(bytes)) } @@ -445,7 +445,7 @@ fn peek_u8(bytes: &[u8]) -> Result { let slice = peek_fixed::<1>(bytes)?; let bytes = slice[1 - BYTES..] .try_into() - .expect("peek_u8: You must use a slice containing exactly 1B."); + .expect("peek_u8: You must use a slice containing exactly 1B"); Ok(u8::from_be_bytes(bytes)) } @@ -458,7 +458,7 @@ fn peek_fixed(data: &[u8]) -> Result<&[u8; LEN]> { fn peek(data: &[u8], len: usize) -> Result<&[u8]> { if len > data.len() { Err(error!( - InvalidData, + Codec, "tried to read {len} bytes from response but only had {} remaining!", data.len() )) @@ -470,7 +470,7 @@ fn peek(data: &[u8], len: usize) -> Result<&[u8]> { fn skip(slice: &[u8], num_bytes: usize) -> Result<&[u8]> { if num_bytes > slice.len() { Err(error!( - InvalidData, + Codec, "tried to consume {num_bytes} bytes from response but only had {} remaining!", slice.len() )) diff --git a/packages/fuels-core/src/codec/abi_decoder/experimental_bounded_decoder.rs b/packages/fuels-core/src/codec/abi_decoder/experimental_bounded_decoder.rs index e8728bf08..5876b387f 100644 --- a/packages/fuels-core/src/codec/abi_decoder/experimental_bounded_decoder.rs +++ b/packages/fuels-core/src/codec/abi_decoder/experimental_bounded_decoder.rs @@ -30,8 +30,8 @@ const DISCRIMINANT_BYTES_SIZE: usize = WORD_SIZE; impl ExperimentalBoundedDecoder { pub(crate) fn new(config: DecoderConfig) -> Self { - let depth_tracker = CounterWithLimit::new(config.max_depth, "Depth"); - let token_tracker = CounterWithLimit::new(config.max_tokens, "Token"); + let depth_tracker = CounterWithLimit::new(config.max_depth, "depth"); + let token_tracker = CounterWithLimit::new(config.max_tokens, "token"); Self { depth_tracker, token_tracker, @@ -314,8 +314,8 @@ impl CounterWithLimit { self.count += 1; if self.count > self.max { return Err(error!( - InvalidType, - "{} limit ({}) reached while decoding. Try increasing it.", self.name, self.max + Codec, + "{} limit `{}` reached while decoding. Try increasing it", self.name, self.max )); } @@ -364,7 +364,7 @@ fn peek_length(bytes: &[u8]) -> Result { u64::from_be_bytes(*slice) .try_into() - .map_err(|_| error!(InvalidData, "could not convert `u64` to `usize`")) + .map_err(|_| error!(Other, "could not convert `u64` to `usize`")) } fn peek_discriminant(bytes: &[u8]) -> Result { @@ -374,7 +374,7 @@ fn peek_discriminant(bytes: &[u8]) -> Result { fn peek(data: &[u8], len: usize) -> Result<&[u8]> { (len <= data.len()).then_some(&data[..len]).ok_or(error!( - InvalidData, + Codec, "tried to read `{len}` bytes but only had `{}` remaining!", data.len() )) @@ -391,7 +391,7 @@ fn skip(slice: &[u8], num_bytes: usize) -> Result<&[u8]> { (num_bytes <= slice.len()) .then_some(&slice[num_bytes..]) .ok_or(error!( - InvalidData, + Codec, "tried to consume `{num_bytes}` bytes but only had `{}` remaining!", slice.len() )) diff --git a/packages/fuels-core/src/codec/logs.rs b/packages/fuels-core/src/codec/logs.rs index 920c164c7..a6d750cdb 100644 --- a/packages/fuels-core/src/codec/logs.rs +++ b/packages/fuels-core/src/codec/logs.rs @@ -7,15 +7,14 @@ use std::{ use fuel_tx::{ContractId, Receipt}; +#[cfg(not(experimental))] +use crate::types::param_types::ParamType; use crate::{ codec::{ABIDecoder, DecoderConfig}, traits::{Parameterize, Tokenizable}, types::errors::{error, Error, Result}, }; -#[cfg(not(experimental))] -use crate::types::param_types::ParamType; - #[derive(Clone)] pub struct LogFormatter { formatter: fn(DecoderConfig, &[u8]) -> Result, @@ -52,8 +51,8 @@ impl LogFormatter { // String slices can not be decoded from logs as they are encoded as ptr, len // TODO: Once https://github.com/FuelLabs/sway/issues/5110 is resolved we can remove this ParamType::StringSlice => Err(error!( - InvalidData, - "String slices can not be decoded from logs. Convert the slice to `str[N]` with `__to_str_array`" + Codec, + "string slices can not be decoded from logs. Convert the slice to `str[N]` with `__to_str_array`" )), _ => Ok(()), } @@ -138,9 +137,9 @@ impl LogDecoder { .get(log_id) .ok_or_else(|| { error!( - InvalidData, + Codec, "missing log formatter for log_id: `{:?}`, data: `{:?}`. \ - Consider adding external contracts with `with_contracts()`", + Consider adding external contracts using `with_contracts()`", log_id, data ) @@ -154,7 +153,7 @@ impl LogDecoder { .rev() .extract_log_id_and_data() .next() - .ok_or_else(|| error!(InvalidData, "No receipts found for decoding last log.")) + .ok_or_else(|| error!(Codec, "no receipts found for decoding last log")) .and_then(|(log_id, data)| self.format_log(&log_id, &data)) } @@ -170,7 +169,7 @@ impl LogDecoder { match res.as_deref() { Ok([rhs, lhs]) => Ok((lhs.to_string(), rhs.to_string())), Ok(some_slice) => Err(error!( - InvalidData, + Codec, "expected to have two logs. Found {}", some_slice.len() )), diff --git a/packages/fuels-core/src/traits/parameterize.rs b/packages/fuels-core/src/traits/parameterize.rs index 447101a78..648cab1a0 100644 --- a/packages/fuels-core/src/traits/parameterize.rs +++ b/packages/fuels-core/src/traits/parameterize.rs @@ -123,7 +123,7 @@ where fn param_type() -> ParamType { let param_types = vec![ParamType::Unit, T::param_type()]; let variants = EnumVariants::new(param_types) - .expect("should never happen as we provided valid Option param types"); + .expect("should never happen as we provided valid `Option` param types"); ParamType::Enum { variants, generics: vec![T::param_type()], @@ -139,7 +139,7 @@ where fn param_type() -> ParamType { let param_types = vec![T::param_type(), E::param_type()]; let variants = EnumVariants::new(param_types.clone()) - .expect("should never happen as we provided valid Result param types"); + .expect("should never happen as we provided valid `Result` param types"); ParamType::Enum { variants, generics: param_types, diff --git a/packages/fuels-core/src/traits/tokenizable.rs b/packages/fuels-core/src/traits/tokenizable.rs index e87d3b865..c00120f08 100644 --- a/packages/fuels-core/src/traits/tokenizable.rs +++ b/packages/fuels-core/src/traits/tokenizable.rs @@ -35,8 +35,8 @@ impl Tokenizable for Bits256 { match token { Token::B256(data) => Ok(Bits256(data)), _ => Err(error!( - InvalidData, - "Bits256 cannot be constructed from token {token}" + Other, + "`Bits256` cannot be constructed from token {token}" )), } } @@ -55,8 +55,8 @@ impl Tokenizable for Vec { tokens.into_iter().map(Tokenizable::from_token).collect() } else { Err(error!( - InvalidData, - "Vec::from_token must only be given a Token::Vector. Got: {token}" + Other, + "`Vec::from_token` must only be given a `Token::Vector`. Got: `{token}`" )) } } @@ -71,10 +71,7 @@ impl Tokenizable for bool { fn from_token(token: Token) -> Result { match token { Token::Bool(data) => Ok(data), - other => Err(error!( - InstantiationError, - "Expected `bool`, got {:?}", other - )), + other => Err(error!(Other, "expected `bool`, got `{:?}`", other)), } } fn into_token(self) -> Token { @@ -89,10 +86,7 @@ impl Tokenizable for () { { match token { Token::Unit => Ok(()), - other => Err(error!( - InstantiationError, - "Expected `Unit`, got {:?}", other - )), + other => Err(error!(Other, "expected `Unit`, got `{:?}`", other)), } } @@ -105,7 +99,7 @@ impl Tokenizable for u8 { fn from_token(token: Token) -> Result { match token { Token::U8(data) => Ok(data), - other => Err(error!(InstantiationError, "Expected `u8`, got {:?}", other)), + other => Err(error!(Other, "expected `u8`, got `{:?}`", other)), } } fn into_token(self) -> Token { @@ -117,10 +111,7 @@ impl Tokenizable for u16 { fn from_token(token: Token) -> Result { match token { Token::U16(data) => Ok(data), - other => Err(error!( - InstantiationError, - "Expected `u16`, got {:?}", other - )), + other => Err(error!(Other, "expected `u16`, got `{:?}`", other)), } } fn into_token(self) -> Token { @@ -132,10 +123,7 @@ impl Tokenizable for u32 { fn from_token(token: Token) -> Result { match token { Token::U32(data) => Ok(data), - other => Err(error!( - InstantiationError, - "Expected `u32`, got {:?}", other - )), + other => Err(error!(Other, "expected `u32`, got {:?}", other)), } } fn into_token(self) -> Token { @@ -147,10 +135,7 @@ impl Tokenizable for u64 { fn from_token(token: Token) -> Result { match token { Token::U64(data) => Ok(data), - other => Err(error!( - InstantiationError, - "Expected `u64`, got {:?}", other - )), + other => Err(error!(Other, "expected `u64`, got {:?}", other)), } } fn into_token(self) -> Token { @@ -162,10 +147,7 @@ impl Tokenizable for u128 { fn from_token(token: Token) -> Result { match token { Token::U128(data) => Ok(data), - other => Err(error!( - InstantiationError, - "Expected `u128`, got {:?}", other - )), + other => Err(error!(Other, "expected `u128`, got {:?}", other)), } } fn into_token(self) -> Token { @@ -180,8 +162,8 @@ impl Tokenizable for RawSlice { { match token { Token::RawSlice(contents) => Ok(Self(contents)), - _ => Err(error!(InvalidData, - "RawSlice::from_token expected a token of the variant Token::RawSlice, got: {token}" + _ => Err(error!(Other, + "`RawSlice::from_token` expected a token of the variant `Token::RawSlice`, got: `{token}`" )), } } @@ -199,8 +181,8 @@ impl Tokenizable for Bytes { match token { Token::Bytes(contents) => Ok(Self(contents)), _ => Err(error!( - InvalidData, - "Bytes::from_token expected a token of the variant Token::Bytes, got: {token}" + Other, + "`Bytes::from_token` expected a token of the variant `Token::Bytes`, got: `{token}`" )), } } @@ -218,8 +200,8 @@ impl Tokenizable for String { match token { Token::String(string) => Ok(string), _ => Err(error!( - InvalidData, - "String::from_token expected a token of the variant Token::String, got: {token}" + Other, + "`String::from_token` expected a token of the variant `Token::String`, got: `{token}`" )), } } @@ -246,15 +228,15 @@ macro_rules! impl_tokenizable_tuples { let mut it = tokens.into_iter(); let mut next_token = move || { it.next().ok_or_else(|| { - error!(InstantiationError,"Ran out of tokens before tuple could be constructed") + error!(Other, "ran out of tokens before tuple could be constructed") }) }; Ok(($( $ty::from_token(next_token()?)?, )+)) }, - other => Err(error!(InstantiationError, - "Expected `Tuple`, got {:?}", + other => Err(error!(Other, + "expected `Tuple`, got `{:?}`", other )), } @@ -299,14 +281,14 @@ impl Tokenizable for ContractId { Ok(ContractId::from(*data)) } else { Err(error!( - InstantiationError, - "ContractId expected one `Token::B256`, got {tokens:?}" + Other, + "`ContractId` expected one `Token::B256`, got `{tokens:?}`" )) } } else { Err(error!( - InstantiationError, - "Address expected `Token::Struct` got {token:?}" + Other, + "`ContractId` expected `Token::Struct` got `{token:?}`" )) } } @@ -327,14 +309,14 @@ impl Tokenizable for Address { Ok(Address::from(*data)) } else { Err(error!( - InstantiationError, - "Address expected one `Token::B256`, got {tokens:?}" + Other, + "`Address` expected one `Token::B256`, got `{tokens:?}`" )) } } else { Err(error!( - InstantiationError, - "Address expected `Token::Struct` got {token:?}" + Other, + "`Address` expected `Token::Struct` got `{token:?}`" )) } } @@ -356,14 +338,14 @@ impl Tokenizable for AssetId { Ok(AssetId::from(*data)) } else { Err(error!( - InstantiationError, - "AssetId expected one `Token::B256`, got {tokens:?}" + Other, + "`AssetId` expected one `Token::B256`, got `{tokens:?}`" )) } } else { Err(error!( - InstantiationError, - "AssetId expected `Token::Struct` got {token:?}" + Other, + "`AssetId` expected `Token::Struct` got `{token:?}`" )) } } @@ -384,14 +366,15 @@ where (0, _, _) => Ok(None), (1, token, _) => Ok(Option::::Some(T::from_token(token)?)), (_, _, _) => Err(error!( - InstantiationError, - "Could not construct Option from enum_selector. Received: {:?}", enum_selector + Other, + "could not construct `Option` from `enum_selector`. Received: `{:?}`", + enum_selector )), } } else { Err(error!( - InstantiationError, - "Could not construct Option from token. Received: {token:?}" + Other, + "could not construct `Option` from token. Received: `{token:?}`" )) } } @@ -404,7 +387,7 @@ where let selector = (dis, tok, variants); Token::Enum(Box::new(selector)) } else { - panic!("should never happen as Option::param_type() returns valid Enum variants"); + panic!("should never happen as `Option::param_type()` returns valid Enum variants"); } } } @@ -420,14 +403,15 @@ where (0, token, _) => Ok(std::result::Result::::Ok(T::from_token(token)?)), (1, token, _) => Ok(std::result::Result::::Err(E::from_token(token)?)), (_, _, _) => Err(error!( - InstantiationError, - "Could not construct Result from enum_selector. Received: {:?}", enum_selector + Other, + "could not construct `Result` from `enum_selector`. Received: `{:?}`", + enum_selector )), } } else { Err(error!( - InstantiationError, - "Could not construct Result from token. Received: {token:?}" + Other, + "could not construct `Result` from token. Received: `{token:?}`" )) } } @@ -450,19 +434,14 @@ impl Tokenizable for [T; SIZE] { where Self: Sized, { - let gen_error = |reason| { - error!( - InvalidData, - "While constructing an array of size {SIZE}: {reason}" - ) - }; + let gen_error = |reason| error!(Other, "constructing an array of size {SIZE}: {reason}"); match token { Token::Array(elements) => { let len = elements.len(); if len != SIZE { return Err(gen_error(format!( - "Was given a Token::Array with wrong number of elements: {len}" + "`Token::Array` has wrong number of elements: {len}" ))); } @@ -475,10 +454,10 @@ impl Tokenizable for [T; SIZE] { })?; Ok(detokenized.try_into().unwrap_or_else(|_| { - panic!("This should never fail since we're checking the length beforehand.") + panic!("this should never fail since we're checking the length beforehand") })) } - _ => Err(gen_error(format!("Expected a Token::Array, got {token}"))), + _ => Err(gen_error(format!("expected a `Token::Array`, got {token}"))), } } @@ -496,12 +475,12 @@ impl Tokenizable for SizedAsciiString { Token::StringArray(contents) => { let expected_len = contents.get_encodable_str()?.len() ; if expected_len!= LEN { - return Err(error!(InvalidData,"SizedAsciiString<{LEN}>::from_token got a Token::StringArray whose expected length({}) is != {LEN}", expected_len)) + return Err(error!(Other,"`SizedAsciiString<{LEN}>::from_token` got a `Token::StringArray` whose expected length({}) is != {LEN}", expected_len)) } Self::new(contents.try_into()?) }, _ => { - Err(error!(InvalidData,"SizedAsciiString<{LEN}>::from_token expected a token of the variant Token::StringArray, got: {token}")) + Err(error!(Other,"`SizedAsciiString<{LEN}>::from_token` expected a token of the variant `Token::StringArray`, got: `{token}`")) } } } @@ -521,7 +500,7 @@ impl Tokenizable for AsciiString { Self::new(contents.try_into()?) }, _ => { - Err(error!(InvalidData,"AsciiString::from_token expected a token of the variant Token::StringSlice, got: {token}")) + Err(error!(Other,"`AsciiString::from_token` expected a token of the variant `Token::StringSlice`, got: `{token}`")) } } } @@ -591,7 +570,7 @@ mod tests { assert_eq!(contents, "abc"); } _ => { - panic!("Not tokenized correctly! Should have gotten a Token::String") + panic!("not tokenized correctly! Should have gotten a `Token::String`") } } @@ -603,7 +582,7 @@ mod tests { let token = Token::StringArray(StaticStringToken::new("abc".to_string(), Some(3))); let sized_ascii_string = - SizedAsciiString::<3>::from_token(token).expect("Should have succeeded"); + SizedAsciiString::<3>::from_token(token).expect("should have succeeded"); assert_eq!(sized_ascii_string, "abc"); diff --git a/packages/fuels-core/src/types.rs b/packages/fuels-core/src/types.rs index 60e7f57a4..7fa70a2bd 100644 --- a/packages/fuels-core/src/types.rs +++ b/packages/fuels-core/src/types.rs @@ -37,17 +37,14 @@ impl StaticStringToken { fn validate(&self) -> Result<()> { if !self.data.is_ascii() { - return Err(error!( - InvalidData, - "String data can only have ascii values" - )); + return Err(error!(Codec, "string data can only have ascii values")); } if let Some(expected_len) = self.expected_len { if self.data.len() != expected_len { return Err(error!( - InvalidData, - "String data has len {}, but the expected len is {}", + Codec, + "string data has len {}, but the expected len is {}", self.data.len(), expected_len )); diff --git a/packages/fuels-core/src/types/core/bits.rs b/packages/fuels-core/src/types/core/bits.rs index 7271f2b1a..05c25f3cb 100644 --- a/packages/fuels-core/src/types/core/bits.rs +++ b/packages/fuels-core/src/types/core/bits.rs @@ -1,7 +1,7 @@ use fuel_types::AssetId; use fuels_macros::{Parameterize, Tokenizable, TryFrom}; -use crate::types::errors::{error, Result}; +use crate::types::errors::Result; // A simple wrapper around [u8; 32] representing the `b256` type. Exists // mainly so that we may differentiate `Parameterize` and `Tokenizable` @@ -25,12 +25,8 @@ impl Bits256 { }; let mut bytes = [0u8; 32]; - hex::decode_to_slice(hex, &mut bytes as &mut [u8]).map_err(|e| { - error!( - InvalidData, - "Could not convert hex str '{hex}' to Bits256! {e}" - ) - })?; + hex::decode_to_slice(hex, &mut bytes as &mut [u8])?; + Ok(Bits256(bytes)) } } diff --git a/packages/fuels-core/src/types/core/bytes.rs b/packages/fuels-core/src/types/core/bytes.rs index dcea9f354..b064dfd5f 100644 --- a/packages/fuels-core/src/types/core/bytes.rs +++ b/packages/fuels-core/src/types/core/bytes.rs @@ -1,4 +1,4 @@ -use crate::types::errors::{error, Result}; +use crate::types::errors::Result; #[derive(Debug, PartialEq, Clone, Eq)] pub struct Bytes(pub Vec); @@ -12,13 +12,7 @@ impl Bytes { } else { hex }; - - let bytes = hex::decode(hex).map_err(|e| { - error!( - InvalidData, - "Could not convert hex str '{hex}' to Bytes! {e}" - ) - })?; + let bytes = hex::decode(hex)?; Ok(Bytes(bytes)) } diff --git a/packages/fuels-core/src/types/core/identity.rs b/packages/fuels-core/src/types/core/identity.rs index 7d7615dc1..61af35bcd 100644 --- a/packages/fuels-core/src/types/core/identity.rs +++ b/packages/fuels-core/src/types/core/identity.rs @@ -1,8 +1,9 @@ -use crate::types::bech32::{Bech32Address, Bech32ContractId}; use fuel_tx::{Address, ContractId}; use fuels_macros::{Parameterize, Tokenizable, TryFrom}; use serde::{Deserialize, Serialize}; +use crate::types::bech32::{Bech32Address, Bech32ContractId}; + #[derive( Debug, Clone, PartialEq, Eq, Hash, Parameterize, Tokenizable, TryFrom, Serialize, Deserialize, )] @@ -74,9 +75,10 @@ impl From for Identity { #[cfg(test)] mod test { - use super::*; use std::str::FromStr; + use super::*; + #[test] fn test_bech32() { let b32_str = "fuel1dved7k25uxadatl7l5kql309jnw07dcn4t3a6x9hm9nxyjcpqqns50p7n2"; diff --git a/packages/fuels-core/src/types/core/sized_ascii_string.rs b/packages/fuels-core/src/types/core/sized_ascii_string.rs index 1eccc9850..698109701 100644 --- a/packages/fuels-core/src/types/core/sized_ascii_string.rs +++ b/packages/fuels-core/src/types/core/sized_ascii_string.rs @@ -14,8 +14,8 @@ pub struct AsciiString { impl AsciiString { pub fn new(data: String) -> Result { if !data.is_ascii() { - return Err(error!(InvalidData, - "AsciiString must be constructed from a string containing only ascii encodable characters. Got: {data}" + return Err(error!(Other, + "`AsciiString` must be constructed from a string containing only ascii encodable characters. Got: `{data}`" )); } Ok(Self { data }) @@ -82,13 +82,13 @@ pub struct SizedAsciiString { impl SizedAsciiString { pub fn new(data: String) -> Result { if !data.is_ascii() { - return Err(error!(InvalidData, - "SizedAsciiString must be constructed from a string containing only ascii encodable characters. Got: {data}" + return Err(error!(Other, + "`SizedAsciiString` must be constructed from a `String` containing only ascii encodable characters. Got: `{data}`" )); } if data.len() != LEN { - return Err(error!(InvalidData, - "SizedAsciiString<{LEN}> can only be constructed from a String of length {LEN}. Got: {data}" + return Err(error!(Other, + "`SizedAsciiString<{LEN}>` must be constructed from a `String` of length {LEN}. Got: `{data}`" )); } Ok(Self { data }) @@ -108,8 +108,8 @@ impl SizedAsciiString { pub fn new_with_right_whitespace_padding(data: String) -> Result { if data.len() > LEN { return Err(error!( - InvalidData, - "SizedAsciiString<{LEN}> cannot be constructed from a string of size {}", + Other, + "`SizedAsciiString<{LEN}>` cannot be constructed from a string of size {}", data.len() )); } @@ -194,7 +194,7 @@ mod tests { let ascii_data = "abc".to_string(); SizedAsciiString::<3>::new(ascii_data) - .expect("Should have succeeded since we gave ascii data of correct length!"); + .expect("should have succeeded since we gave ascii data of correct length!"); // ANCHOR_END: string_simple_example } @@ -203,10 +203,10 @@ mod tests { let ascii_data = "ab©".to_string(); let err = SizedAsciiString::<3>::new(ascii_data) - .expect_err("Should not have succeeded since we gave non ascii data"); + .expect_err("should not have succeeded since we gave non ascii data"); - let expected_reason = "SizedAsciiString must be constructed from a string containing only ascii encodable characters. Got: "; - assert!(matches!(err, Error::InvalidData(reason) if reason.starts_with(expected_reason))); + let expected_reason = "`SizedAsciiString` must be constructed from a `String` containing only ascii encodable characters. Got: "; + assert!(matches!(err, Error::Other(reason) if reason.starts_with(expected_reason))); } #[test] @@ -214,22 +214,22 @@ mod tests { let ascii_data = "abcd".to_string(); let err = SizedAsciiString::<3>::new(ascii_data) - .expect_err("Should not have succeeded since we gave data of wrong length"); + .expect_err("should not have succeeded since we gave data of wrong length"); let expected_reason = - "SizedAsciiString<3> can only be constructed from a String of length 3. Got: abcd"; - assert!(matches!(err, Error::InvalidData(reason) if reason.starts_with(expected_reason))); + "`SizedAsciiString<3>` must be constructed from a `String` of length 3. Got: `abcd`"; + assert!(matches!(err, Error::Other(reason) if reason.starts_with(expected_reason))); } // ANCHOR: conversion #[test] fn can_be_constructed_from_str_ref() { - let _: SizedAsciiString<3> = "abc".try_into().expect("Should have succeeded"); + let _: SizedAsciiString<3> = "abc".try_into().expect("should have succeeded"); } #[test] fn can_be_constructed_from_string() { - let _: SizedAsciiString<3> = "abc".to_string().try_into().expect("Should have succeeded"); + let _: SizedAsciiString<3> = "abc".to_string().try_into().expect("should have succeeded"); } #[test] diff --git a/packages/fuels-core/src/types/core/u256.rs b/packages/fuels-core/src/types/core/u256.rs index dcca899eb..d2f504918 100644 --- a/packages/fuels-core/src/types/core/u256.rs +++ b/packages/fuels-core/src/types/core/u256.rs @@ -31,8 +31,8 @@ impl Tokenizable for U256 { match token { Token::U256(data) => Ok(data), _ => Err(error!( - InvalidData, - "U256 cannot be constructed from token {token}" + Other, + "`U256` cannot be constructed from token `{token}`" )), } } diff --git a/packages/fuels-core/src/types/enum_variants.rs b/packages/fuels-core/src/types/enum_variants.rs index fc2f9d0a5..bc706ad94 100644 --- a/packages/fuels-core/src/types/enum_variants.rs +++ b/packages/fuels-core/src/types/enum_variants.rs @@ -15,7 +15,7 @@ pub struct EnumVariants { impl EnumVariants { pub fn new(param_types: Vec) -> Result { if param_types.is_empty() { - return Err(error!(InvalidData, "Enum variants can not be empty!")); + return Err(error!(Other, "enum variants can not be empty!")); } Ok(EnumVariants { param_types }) } @@ -27,8 +27,8 @@ impl EnumVariants { pub fn param_type_of_variant(&self, discriminant: u64) -> Result<&ParamType> { self.param_types.get(discriminant as usize).ok_or_else(|| { error!( - InvalidData, - "Discriminant '{discriminant}' doesn't point to any variant: {:?}", + Other, + "discriminant `{discriminant}` doesn't point to any variant: {:?}", self.param_types() ) }) @@ -60,7 +60,7 @@ impl EnumVariants { checked_round_up_to_word_alignment(width)? .checked_add(ENUM_DISCRIMINANT_BYTE_WIDTH) - .ok_or_else(|| error!(InvalidType, "Enum variants are too wide")) + .ok_or_else(|| error!(Other, "enum variants are too wide")) } /// Determines the padding needed for the provided enum variant (based on the width of the diff --git a/packages/fuels-core/src/types/errors.rs b/packages/fuels-core/src/types/errors.rs index 5e42bf608..58743627b 100644 --- a/packages/fuels-core/src/types/errors.rs +++ b/packages/fuels-core/src/types/errors.rs @@ -2,51 +2,50 @@ use std::{array::TryFromSliceError, str::Utf8Error}; use fuel_tx::{Receipt, ValidityError}; use fuel_vm::checked_transaction::CheckError; +use hex::FromHexError; use thiserror::Error; +pub mod transaction { + use super::*; + + #[derive(Error, Debug)] + pub enum Reason { + #[error("builder: {0}")] + Builder(String), + #[error("validation: {0}")] + Validation(String), + #[error("squeezedOut: {0}")] + SqueezedOut(String), + #[error("reverted: {reason}, receipts: {receipts:?}")] + Reverted { + reason: String, + revert_id: u64, + receipts: Vec, + }, + #[error(": {0}")] + Other(String), + } +} +use transaction::Reason; + #[derive(Error, Debug)] pub enum Error { - #[error("Invalid data: {0}")] - InvalidData(String), - #[error("Serialization error: {0}")] - SerdeJson(#[from] serde_json::Error), - #[error("IO error: {0}")] - IOError(#[from] std::io::Error), - #[error("Invalid type: {0}")] - InvalidType(String), - #[error("Utf8 error: {0}")] - Utf8Error(#[from] Utf8Error), - #[error("Instantiation error: {0}")] - InstantiationError(String), - #[error("Infrastructure error: {0}")] - InfrastructureError(String), - #[error("Account error: {0}")] - AccountError(String), - #[error("Wallet error: {0}")] - WalletError(String), - #[error("Provider error: {0}")] - ProviderError(String), - #[error("Validation error: {0}")] - ValidationError(String), - #[error("Tried to forward assets to a contract method that is not payable.")] - AssetsForwardedToNonPayableMethod, - #[error("Revert transaction error: {reason},\n receipts: {receipts:?}")] - RevertTransactionError { - reason: String, - revert_id: u64, - receipts: Vec, - }, - #[error("Transaction was squeezed out. Reason: `{0}`")] - SqueezedOutTransactionError(String), - #[error("Transaction build error: {0}")] - TransactionBuildError(String), + #[error("io: {0}")] + IO(#[from] std::io::Error), + #[error("codec: {0}")] + Codec(String), + #[error("transaction {0}")] + Transaction(Reason), + #[error("provider: {0}")] + Provider(String), + #[error("{0}")] + Other(String), } pub type Result = std::result::Result; /// This macro can only be used for `Error` variants that have a `String` field. -/// Those are: `InvalidData`, `InvalidType`, `InfrastructureError`, -/// `InstantiationError`, `WalletError`, `ProviderError`, `TransactionBuildError` +/// Those are: `IO`, `Codec`, `Provider`, `Other`. #[macro_export] macro_rules! error { ($err_variant:ident, $fmt_str: literal $(,$arg: expr)*) => { @@ -55,27 +54,43 @@ macro_rules! error { } pub use error; -macro_rules! impl_error_from { - ($err_variant:ident, $err_type:ty ) => { - impl From<$err_type> for Error { - fn from(err: $err_type) -> Error { - Error::$err_variant(err.to_string()) - } - } - }; +/// This macro can only be used for `Error::Transaction` variants that have a `String` field. +/// Those are: `Builder`, `Validation`, `SqueezedOut`, `Other`. +#[macro_export] +macro_rules! error_transaction { + ($err_variant:ident, $fmt_str: literal $(,$arg: expr)*) => { + $crate::types::errors::Error::Transaction( + $crate::types::errors::transaction::Reason::$err_variant(format!($fmt_str,$($arg),*))) + } } +pub use error_transaction; impl From for Error { fn from(err: CheckError) -> Error { - Error::ValidationError(format!("{:?}", err)) + error_transaction!(Validation, "{err:?}") } } impl From for Error { fn from(err: ValidityError) -> Error { - Error::ValidationError(format!("{:?}", err)) + error_transaction!(Validation, "{err:?}") } } -impl_error_from!(InvalidData, bech32::Error); -impl_error_from!(InvalidData, TryFromSliceError); +macro_rules! impl_error_from { + ($err_variant:ident, $err_type:ty ) => { + impl From<$err_type> for $crate::types::errors::Error { + fn from(err: $err_type) -> $crate::types::errors::Error { + $crate::types::errors::Error::$err_variant(err.to_string()) + } + } + }; +} + +impl_error_from!(Other, &'static str); +impl_error_from!(Other, bech32::Error); +impl_error_from!(Other, fuel_crypto::Error); +impl_error_from!(Other, serde_json::Error); +impl_error_from!(Other, FromHexError); +impl_error_from!(Other, TryFromSliceError); +impl_error_from!(Other, Utf8Error); diff --git a/packages/fuels-core/src/types/param_types.rs b/packages/fuels-core/src/types/param_types.rs index c2bff0e2f..f436140e0 100644 --- a/packages/fuels-core/src/types/param_types.rs +++ b/packages/fuels-core/src/types/param_types.rs @@ -70,20 +70,22 @@ impl ParamType { let memory_size = param_type.compute_encoding_in_bytes()?; if memory_size == 0 { return Err(error!( - InvalidType, - "Cannot calculate the number of elements because the type is zero-sized." + Codec, + "cannot calculate the number of elements because the type is zero-sized" )); } + let remainder = available_bytes % memory_size; if remainder != 0 { return Err(error!( - InvalidData, + Codec, "{remainder} extra bytes detected while decoding heap type" )); } let num_of_elements = available_bytes .checked_div(memory_size) - .ok_or_else(|| error!(InvalidData, "Type {param_type:?} has a memory_size of 0"))?; + .ok_or_else(|| error!(Codec, "type {param_type:?} has a memory_size of 0"))?; + Ok(num_of_elements) } @@ -114,8 +116,8 @@ impl ParamType { .any(|child| child.children_need_extra_receipts()); if grandchildren_need_receipts { return Err(error!( - InvalidType, - "Enums currently support only one level deep heap types." + Codec, + "enums currently support only one level deep heap types" )); } @@ -125,15 +127,16 @@ impl ParamType { .count(); if num_of_children_needing_receipts > 1 { return Err(error!( - InvalidType, - "Enums currently support only one heap-type variant. Found: \ + Codec, + "enums currently support only one heap-type variant. Found: \ {num_of_children_needing_receipts}" )); } } else if self.children_need_extra_receipts() { return Err(error!( - InvalidType, - "type {:?} is not decodable: nested heap types are currently not supported except in Enums.", + Codec, + "type `{:?}` is not decodable: nested heap types are currently not \ + supported except in enums", DebugWithDepth::new(self, max_depth) )); } @@ -181,8 +184,8 @@ impl ParamType { pub fn compute_encoding_in_bytes(&self) -> Result { let overflow_error = || { error!( - InvalidType, - "Reached overflow while computing encoding size for {:?}", self + Codec, + "reached overflow while computing encoding size for {:?}", self ) }; match &self { @@ -256,7 +259,7 @@ impl Type { ) -> Result { let type_declaration = type_lookup.get(&type_application.type_id).ok_or_else(|| { error!( - InvalidData, + Codec, "type id {} not found in type lookup", type_application.type_id ) })?; @@ -267,7 +270,7 @@ impl Type { .find(|(id, _)| *id == type_application.type_id) .ok_or_else(|| { error!( - InvalidData, + Codec, "type id {} not found in parent's generic parameters", type_application.type_id ) @@ -395,8 +398,8 @@ impl TryFrom<&Type> for ParamType { matched_param_type.map(Ok).unwrap_or_else(|| { Err(error!( - InvalidType, - "Type {} couldn't be converted into a ParamType", the_type.type_field + Codec, + "type {} couldn't be converted into a ParamType", the_type.type_field )) }) } @@ -430,8 +433,8 @@ fn try_vector(the_type: &Type) -> Result> { if the_type.generic_params.len() != 1 { return Err(error!( - InvalidType, - "Vec must have exactly one generic argument for its type. Found: {:?}", + Codec, + "`Vec` must have exactly one generic argument for its type. Found: `{:?}`", the_type.generic_params )); } @@ -520,8 +523,8 @@ fn try_array(the_type: &Type) -> Result> { Ok(Some(ParamType::Array(Box::new(array_type), len))) } _ => Err(error!( - InvalidType, - "An array must have elements of exactly one type. Array types: {:?}", + Codec, + "array must have elements of exactly one type. Array types: {:?}", the_type.components )), }; @@ -1459,15 +1462,15 @@ mod tests { let max_depth = DecoderConfig::default().max_depth; let nested_heap_type_error_message = |p: ParamType| { format!( - "Invalid type: type {:?} is not decodable: nested heap types are currently not \ - supported except in Enums.", + "codec: type `{:?}` is not decodable: nested heap types are currently not \ + supported except in enums", DebugWithDepth::new(&p, max_depth) ) }; let cannot_be_decoded = |p: ParamType| { assert_eq!( p.validate_is_decodable(max_depth) - .expect_err(&format!("Should not be decodable: {:?}", p)) + .expect_err(&format!("should not be decodable: {:?}", p)) .to_string(), nested_heap_type_error_message(p) ) @@ -1504,46 +1507,53 @@ mod tests { let variants_no_bytes_type = EnumVariants::new(param_types_no_bytes.clone())?; let variants_one_bytes_type = EnumVariants::new(param_types_containing_bytes.clone())?; let variants_two_bytes_type = EnumVariants::new(vec![ParamType::Bytes, ParamType::Bytes])?; + can_be_decoded(ParamType::Enum { variants: variants_no_bytes_type.clone(), generics: param_types_no_bytes.clone(), }); + can_be_decoded(ParamType::Enum { variants: variants_one_bytes_type.clone(), generics: param_types_no_bytes.clone(), }); - let expected = "Invalid type: Enums currently support only one heap-type variant. Found: 2" - .to_string(); + + let expected = + "codec: enums currently support only one heap-type variant. Found: 2".to_string(); assert_eq!( ParamType::Enum { variants: variants_two_bytes_type.clone(), generics: param_types_no_bytes.clone(), } .validate_is_decodable(max_depth) - .expect_err("Should not be decodable") + .expect_err("should not be decodable") .to_string(), expected ); + can_be_decoded(ParamType::Enum { variants: variants_no_bytes_type, generics: param_types_containing_bytes.clone(), }); + can_be_decoded(ParamType::Enum { variants: variants_one_bytes_type, generics: param_types_containing_bytes.clone(), }); - let expected = "Invalid type: Enums currently support only one heap-type variant. Found: 2" - .to_string(); + + let expected = + "codec: enums currently support only one heap-type variant. Found: 2".to_string(); assert_eq!( ParamType::Enum { variants: variants_two_bytes_type.clone(), generics: param_types_containing_bytes.clone(), } .validate_is_decodable(max_depth) - .expect_err("Should not be decodable") + .expect_err("should not be decodable") .to_string(), expected ); + Ok(()) } @@ -1555,15 +1565,15 @@ mod tests { let param_types_nested_string = vec![ParamType::Unit, ParamType::Bool, base_string.clone()]; let nested_heap_type_error_message = |p: ParamType| { format!( - "Invalid type: type {:?} is not decodable: nested heap types \ - are currently not supported except in Enums.", + "codec: type `{:?}` is not decodable: nested heap types \ + are currently not supported except in enums", DebugWithDepth::new(&p, max_depth) ) }; let cannot_be_decoded = |p: ParamType| { assert_eq!( p.validate_is_decodable(max_depth) - .expect_err(&format!("Should not be decodable: {:?}", p)) + .expect_err(&format!("should not be decodable: {:?}", p)) .to_string(), nested_heap_type_error_message(p) ) @@ -1606,46 +1616,53 @@ mod tests { let variants_no_string_type = EnumVariants::new(param_types_no_string.clone())?; let variants_one_string_type = EnumVariants::new(param_types_containing_string.clone())?; let variants_two_string_type = EnumVariants::new(vec![ParamType::Bytes, ParamType::Bytes])?; + can_be_decoded(ParamType::Enum { variants: variants_no_string_type.clone(), generics: param_types_no_string.clone(), }); + can_be_decoded(ParamType::Enum { variants: variants_one_string_type.clone(), generics: param_types_no_string.clone(), }); - let expected = "Invalid type: Enums currently support only one heap-type variant. Found: 2" - .to_string(); + + let expected = + "codec: enums currently support only one heap-type variant. Found: 2".to_string(); assert_eq!( ParamType::Enum { variants: variants_two_string_type.clone(), generics: param_types_no_string.clone(), } .validate_is_decodable(1) - .expect_err("Should not be decodable") + .expect_err("should not be decodable") .to_string(), expected ); + can_be_decoded(ParamType::Enum { variants: variants_no_string_type, generics: param_types_containing_string.clone(), }); + can_be_decoded(ParamType::Enum { variants: variants_one_string_type, generics: param_types_containing_string.clone(), }); - let expected = "Invalid type: Enums currently support only one heap-type variant. Found: 2" - .to_string(); + + let expected = + "codec: enums currently support only one heap-type variant. Found: 2".to_string(); assert_eq!( ParamType::Enum { variants: variants_two_string_type.clone(), generics: param_types_containing_string.clone(), } .validate_is_decodable(1) - .expect_err("Should not be decodable") + .expect_err("should not be decodable") .to_string(), expected ); + Ok(()) } @@ -1660,15 +1677,16 @@ mod tests { let param_types_no_vector = vec![ParamType::U64, ParamType::U32]; let nested_heap_type_error_message = |p: ParamType| { format!( - "Invalid type: type {:?} is not decodable: nested heap types \ - are currently not supported except in Enums.", + "codec: type `{:?}` is not decodable: nested heap types \ + are currently not supported except in enums", DebugWithDepth::new(&p, max_depth) ) }; + let cannot_be_decoded = |p: ParamType| { assert_eq!( p.validate_is_decodable(max_depth) - .expect_err(&format!("Should not be decodable: {:?}", p)) + .expect_err(&format!("should not be decodable: {:?}", p)) .to_string(), nested_heap_type_error_message(p) ) @@ -1717,23 +1735,26 @@ mod tests { ParamType::Vector(Box::new(ParamType::U8)), ParamType::Vector(Box::new(ParamType::U16)), ])?; + can_be_decoded(ParamType::Enum { variants: variants_no_vector_type.clone(), generics: param_types_no_vector.clone(), }); + can_be_decoded(ParamType::Enum { variants: variants_one_vector_type.clone(), generics: param_types_no_vector.clone(), }); - let expected = "Invalid type: Enums currently support only one heap-type variant. Found: 2" - .to_string(); + + let expected = + "codec: enums currently support only one heap-type variant. Found: 2".to_string(); assert_eq!( ParamType::Enum { variants: variants_two_vector_type.clone(), generics: param_types_no_vector.clone(), } .validate_is_decodable(max_depth) - .expect_err("Should not be decodable") + .expect_err("should not be decodable") .to_string(), expected ); @@ -1745,15 +1766,15 @@ mod tests { variants: variants_one_vector_type, generics: param_types_containing_vector.clone(), }); - let expected = "Invalid type: Enums currently support only one heap-type variant. Found: 2" - .to_string(); + let expected = + "codec: enums currently support only one heap-type variant. Found: 2".to_string(); assert_eq!( ParamType::Enum { variants: variants_two_vector_type.clone(), generics: param_types_containing_vector.clone(), } .validate_is_decodable(max_depth) - .expect_err("Should not be decodable") + .expect_err("should not be decodable") .to_string(), expected ); @@ -1835,8 +1856,8 @@ mod tests { let overflows = |p: ParamType| { let error = p.compute_encoding_in_bytes().unwrap_err(); let overflow_error = error!( - InvalidType, - "Reached overflow while computing encoding size for {:?}", p + Codec, + "reached overflow while computing encoding size for {:?}", p ); assert_eq!(error.to_string(), overflow_error.to_string()); }; @@ -1875,16 +1896,19 @@ mod tests { assert!(ParamType::calculate_num_of_elements(&failing_param_type, 0) .unwrap_err() .to_string() - .contains("Reached overflow")); + .contains("reached overflow")); + let zero_sized_type = ParamType::Array(Box::new(ParamType::StringArray(0)), 1000); assert!(ParamType::calculate_num_of_elements(&zero_sized_type, 0) .unwrap_err() .to_string() .contains("the type is zero-sized")); + assert!(ParamType::calculate_num_of_elements(&ParamType::U16, 9) .unwrap_err() .to_string() .contains("1 extra bytes detected while decoding heap type")); + Ok(()) } diff --git a/packages/fuels-core/src/types/transaction_builders.rs b/packages/fuels-core/src/types/transaction_builders.rs index 9eab467aa..729c734d3 100644 --- a/packages/fuels-core/src/types/transaction_builders.rs +++ b/packages/fuels-core/src/types/transaction_builders.rs @@ -27,7 +27,7 @@ use crate::{ bech32::Bech32Address, coin::Coin, coin_type::CoinType, - errors::{error, Result}, + errors::{error_transaction, Result}, input::Input, message::Message, transaction::{ @@ -144,9 +144,9 @@ macro_rules! impl_tx_trait { .owner_to_idx_offset .contains_key(address) { - return Err(error!( - InvalidData, - "Already added `Signer` with address: `{address}`" + return Err(error_transaction!( + Builder, + "already added `Signer` with address: `{address}`" )); } @@ -280,8 +280,8 @@ macro_rules! impl_tx_trait { let num_witnesses = self.witnesses().len(); if num_witnesses + self.unresolved_signers.len() > 256 { - return Err(error!( - InvalidData, + return Err(error_transaction!( + Builder, "tx can not have more than 256 witnesses" )); } @@ -782,8 +782,8 @@ fn resolve_signed_resource( unresolved_witness_indexes .owner_to_idx_offset .get(owner) - .ok_or(error!( - InvalidData, + .ok_or(error_transaction!( + Builder, "signature missing for coin with owner: `{owner:?}`" )) .map(|witness_idx_offset| { @@ -797,8 +797,8 @@ fn resolve_signed_resource( unresolved_witness_indexes .owner_to_idx_offset .get(recipient) - .ok_or(error!( - InvalidData, + .ok_or(error_transaction!( + Builder, "signature missing for message with recipient: `{recipient:?}`" )) .map(|witness_idx_offset| { @@ -1127,7 +1127,7 @@ mod tests { } #[tokio::test] - #[should_panic(expected = "Already added `Signer` with address:")] + #[should_panic(expected = "already added `Signer` with address:")] async fn add_signer_called_multiple_times() { let mut tb = ScriptTransactionBuilder::default(); let signer = MockSigner::default(); diff --git a/packages/fuels-core/src/types/tx_status.rs b/packages/fuels-core/src/types/tx_status.rs index e61bee27f..472f62e00 100644 --- a/packages/fuels-core/src/types/tx_status.rs +++ b/packages/fuels-core/src/types/tx_status.rs @@ -10,7 +10,7 @@ use fuel_vm::state::ProgramState; use crate::{ codec::LogDecoder, - types::errors::{Error, Result}, + types::errors::{transaction::Reason, Error, Result}, }; #[derive(Debug, Clone)] @@ -32,7 +32,9 @@ pub enum TxStatus { impl TxStatus { pub fn check(&self, log_decoder: Option<&LogDecoder>) -> Result<()> { match self { - Self::SqueezedOut { reason } => Err(Error::SqueezedOutTransactionError(reason.clone())), + Self::SqueezedOut { reason } => { + Err(Error::Transaction(Reason::SqueezedOut(reason.clone()))) + } Self::Revert { receipts, reason, @@ -62,17 +64,17 @@ impl TxStatus { } } } - (FAILED_ASSERT_SIGNAL, _) => "assertion failed.".into(), - (FAILED_SEND_MESSAGE_SIGNAL, _) => "failed to send message.".into(), - (FAILED_TRANSFER_TO_ADDRESS_SIGNAL, _) => "failed transfer to address.".into(), + (FAILED_ASSERT_SIGNAL, _) => "assertion failed".into(), + (FAILED_SEND_MESSAGE_SIGNAL, _) => "failed to send message".into(), + (FAILED_TRANSFER_TO_ADDRESS_SIGNAL, _) => "failed transfer to address".into(), _ => reason.to_string(), }; - Err(Error::RevertTransactionError { + Err(Error::Transaction(Reason::Reverted { reason, revert_id: id, receipts: receipts.to_vec(), - }) + })) } pub fn take_receipts_checked(self, log_decoder: Option<&LogDecoder>) -> Result> { diff --git a/packages/fuels-core/src/types/wrappers/coin_type.rs b/packages/fuels-core/src/types/wrappers/coin_type.rs index 93cba94f7..6d5f18b54 100644 --- a/packages/fuels-core/src/types/wrappers/coin_type.rs +++ b/packages/fuels-core/src/types/wrappers/coin_type.rs @@ -1,11 +1,17 @@ #![cfg(feature = "std")] use fuel_core_client::client::types::CoinType as ClientCoinType; -use fuel_types::AssetId; use crate::{ constants::BASE_ASSET_ID, - types::{bech32::Bech32Address, coin::Coin, coin_type_id::CoinTypeId, message::Message}, + types::{ + bech32::Bech32Address, + coin::Coin, + coin_type_id::CoinTypeId, + errors::{error, Error}, + message::Message, + AssetId, + }, }; #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -15,16 +21,13 @@ pub enum CoinType { } impl TryFrom for CoinType { - type Error = std::io::Error; + type Error = Error; fn try_from(client_resource: ClientCoinType) -> Result { match client_resource { ClientCoinType::Coin(coin) => Ok(CoinType::Coin(coin.into())), ClientCoinType::MessageCoin(message) => Ok(CoinType::Message(message.into())), - ClientCoinType::Unknown => Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - "Got unknown `ClientCoinType`", - )), + ClientCoinType::Unknown => Err(error!(Other, "unknown `ClientCoinType`")), } } } diff --git a/packages/fuels-core/src/types/wrappers/transaction.rs b/packages/fuels-core/src/types/wrappers/transaction.rs index dc44dc66e..2459d34bd 100644 --- a/packages/fuels-core/src/types/wrappers/transaction.rs +++ b/packages/fuels-core/src/types/wrappers/transaction.rs @@ -24,7 +24,10 @@ use itertools::Itertools; use crate::{ constants::BASE_ASSET_ID, traits::Signer, - types::{bech32::Bech32Address, errors::error, Result}, + types::{ + bech32::Bech32Address, + errors::{error_transaction, Result}, + }, utils::calculate_witnesses_size, }; @@ -379,8 +382,8 @@ macro_rules! impl_tx_wrapper { )) as u64; if new_witnesses_size > self.tx.witness_limit() { - Err(error!( - ValidationError, + Err(error_transaction!( + Validation, "Witness limit exceeded. Consider setting the limit manually with \ a transaction builder. The new limit should be: `{new_witnesses_size}`" )) @@ -463,8 +466,8 @@ impl GasValidation for CreateTransaction { // because `CreateTransaction` has no gas_limit` fn validate_gas(&self, min_gas_price: u64, _: u64) -> Result<()> { if min_gas_price > self.tx.gas_price() { - return Err(error!( - ValidationError, + return Err(error_transaction!( + Validation, "gas_price({}) is lower than the required min_gas_price({})", self.tx.gas_price(), min_gas_price @@ -486,15 +489,15 @@ impl EstimablePredicates for ScriptTransaction { impl GasValidation for ScriptTransaction { fn validate_gas(&self, min_gas_price: u64, gas_used: u64) -> Result<()> { if gas_used > *self.tx.script_gas_limit() { - return Err(error!( - ValidationError, + return Err(error_transaction!( + Validation, "script_gas_limit({}) is lower than the estimated gas_used({})", self.tx.script_gas_limit(), gas_used )); } else if min_gas_price > self.tx.gas_price() { - return Err(error!( - ValidationError, + return Err(error_transaction!( + Validation, "gas_price({}) is lower than the required min_gas_price({})", self.tx.gas_price(), min_gas_price @@ -549,7 +552,7 @@ mod test { let witness = vec![0, 1, 2].into(); let err = tx.append_witness(witness).expect_err("should error"); - let expected_err_str = "Validation error: Witness limit exceeded. \ + let expected_err_str = "transaction validation: Witness limit exceeded. \ Consider setting the limit manually with a transaction builder. \ The new limit should be: `16`"; diff --git a/packages/fuels-core/src/types/wrappers/transaction_response.rs b/packages/fuels-core/src/types/wrappers/transaction_response.rs index f875470cc..87f45e56d 100644 --- a/packages/fuels-core/src/types/wrappers/transaction_response.rs +++ b/packages/fuels-core/src/types/wrappers/transaction_response.rs @@ -30,9 +30,8 @@ impl From for TransactionResponse { ClientTransactionStatus::Success { block_id, .. } | ClientTransactionStatus::Failure { block_id, .. } => Some(block_id), }; - let block_id = block_id.map(|id| { - Bytes32::from_str(id).expect("Client returned block id with invalid format.") - }); + let block_id = block_id + .map(|id| Bytes32::from_str(id).expect("client returned block id with invalid format")); let time = match &client_response.status { ClientTransactionStatus::Submitted { .. } diff --git a/packages/fuels-core/src/utils.rs b/packages/fuels-core/src/utils.rs index c3ab65ba2..1adde80eb 100644 --- a/packages/fuels-core/src/utils.rs +++ b/packages/fuels-core/src/utils.rs @@ -9,20 +9,20 @@ use crate::{error, types::errors::Result}; pub fn checked_round_up_to_word_alignment(bytes_len: usize) -> Result { let lhs = bytes_len.checked_add(WORD_SIZE - 1).ok_or_else(|| { error!( - InvalidType, - "Addition overflow while rounding up {bytes_len} bytes to word alignment" + Codec, + "addition overflow while rounding up {bytes_len} bytes to word alignment" ) })?; let rhs = lhs.checked_rem(WORD_SIZE).ok_or_else(|| { error!( - InvalidType, - "Remainder overflow while rounding up {bytes_len} bytes to word alignment" + Codec, + "remainder overflow while rounding up {bytes_len} bytes to word alignment" ) })?; lhs.checked_sub(rhs).ok_or_else(|| { error!( - InvalidType, - "Substraction overflow while rounding up {bytes_len} bytes to word alignment" + Codec, + "substraction overflow while rounding up {bytes_len} bytes to word alignment" ) }) } diff --git a/packages/fuels-macros/src/derive/tokenizable.rs b/packages/fuels-macros/src/derive/tokenizable.rs index c6ac9b5c5..2e12d8c98 100644 --- a/packages/fuels-macros/src/derive/tokenizable.rs +++ b/packages/fuels-macros/src/derive/tokenizable.rs @@ -69,7 +69,7 @@ fn tokenizable_for_struct( let mut tokens_iter = tokens.into_iter(); let mut next_token = move || { tokens_iter .next() - .ok_or_else(|| { #fuels_types_path::errors::Error::InstantiationError(#std_lib::format!("Ran out of tokens before '{}' has finished construction.", #struct_name_str)) }) + .ok_or_else(|| { #fuels_types_path::errors::Error::Other(#std_lib::format!("ran out of tokens before `{}` has finished construction", #struct_name_str)) }) }; ::core::result::Result::Ok(Self { #( @@ -79,7 +79,7 @@ fn tokenizable_for_struct( }) }, - other => ::core::result::Result::Err(#fuels_types_path::errors::Error::InstantiationError(#std_lib::format!("Error while constructing '{}'. Expected token of type Token::Struct, got {:?}", #struct_name_str, other))), + other => ::core::result::Result::Err(#fuels_types_path::errors::Error::Other(#std_lib::format!("error while constructing `{}`. Expected token of type `Token::Struct`, got `{:?}`", #struct_name_str, other))), } } } @@ -110,7 +110,7 @@ fn tokenizable_for_enum( let variants = match ::param_type() { #fuels_types_path::param_types::ParamType::Enum{variants, ..} => variants, - other => ::std::panic!("Calling {}::param_type() must return a ParamType::Enum but instead it returned: {:?}", #name_stringified, other) + other => ::std::panic!("calling {}::param_type() must return a `ParamType::Enum` but instead it returned: `{:?}`", #name_stringified, other) }; #fuels_types_path::Token::Enum(#std_lib::boxed::Box::new((discriminant, token, variants))) @@ -125,8 +125,8 @@ fn tokenizable_for_enum( let (discriminant, variant_token, _) = *selector; #constructed_variant } - _ => ::core::result::Result::Err(#std_lib::format!("Given token ({}) is not of the type Token::Enum.", token)), - }.map_err(|e| #fuels_types_path::errors::Error::InvalidData(#std_lib::format!("Error while instantiating {} from token! {}", #name_stringified, e)) ) + _ => ::core::result::Result::Err(#std_lib::format!("token `{}` is not of the type `Token::Enum`", token)), + }.map_err(|e| #fuels_types_path::errors::Error::Other(#std_lib::format!("error while instantiating `{}` from token `{}`", #name_stringified, e)) ) } } }) diff --git a/packages/fuels-macros/src/derive/try_from.rs b/packages/fuels-macros/src/derive/try_from.rs index 7ebf2529d..67ec7d581 100644 --- a/packages/fuels-macros/src/derive/try_from.rs +++ b/packages/fuels-macros/src/derive/try_from.rs @@ -17,7 +17,7 @@ pub fn generate_try_from_impl(input: DeriveInput) -> Result { } Data::Union(union) => Err(Error::new_spanned( union.union_token, - "Unions are not supported.", + "unions are not supported", )), } } diff --git a/packages/fuels-macros/src/derive/utils.rs b/packages/fuels-macros/src/derive/utils.rs index 27bee2a5f..1c987fdd2 100644 --- a/packages/fuels-macros/src/derive/utils.rs +++ b/packages/fuels-macros/src/derive/utils.rs @@ -17,7 +17,7 @@ pub(crate) fn get_path_from_attr_or( let Meta::NameValue(name_value) = &attr.meta else { return Err(Error::new_spanned( attr.meta.path(), - "Expected name='value'", + "expected name='value'", )); }; @@ -28,12 +28,12 @@ pub(crate) fn get_path_from_attr_or( else { return Err(Error::new_spanned( &name_value.value, - "Expected string literal", + "expected string literal", )); }; TypePath::new(lit_str.value()) - .map_err(|_| Error::new_spanned(lit_str.value(), "Invalid path.")) + .map_err(|_| Error::new_spanned(lit_str.value(), "invalid path")) .map(|type_path| type_path.to_token_stream()) } @@ -81,7 +81,7 @@ pub(crate) fn extract_variants( validate_variant_type(&variant)?; let discriminant = discriminant.try_into().map_err(|_| { - Error::new_spanned(&variant.ident, "Enums can not have more than 256 variants") + Error::new_spanned(&variant.ident, "enums can not have more than 256 variants") })?; Ok(ExtractedVariant::Normal { @@ -121,7 +121,7 @@ impl ExtractedVariants { ExtractedVariant::Ignored { info: VariantInfo{ name, is_unit } } => { let panic_expression = { let name_stringified = name.to_string(); - quote! {::core::panic!("Variant '{}' should never be constructed.", #name_stringified)} + quote! {::core::panic!("variant `{}` should never be constructed", #name_stringified)} }; if *is_unit { quote! { Self::#name => #panic_expression } @@ -163,7 +163,7 @@ impl ExtractedVariants { match discriminant { #(#match_discriminant,)* _ => ::core::result::Result::Err(#std_lib::format!( - "Discriminant {} doesn't point to any of the enums variants.", discriminant + "discriminant {} doesn't point to any of the enums variants", discriminant )), } } @@ -175,7 +175,7 @@ fn validate_variant_type(variant: &Variant) -> Result<()> { Fields::Named(named_fields) => { return Err(Error::new_spanned( named_fields.clone(), - "Struct like enum variants are not supported".to_string(), + "struct like enum variants are not supported".to_string(), )) } Fields::Unnamed(unnamed_fields) => { @@ -184,7 +184,7 @@ fn validate_variant_type(variant: &Variant) -> Result<()> { if fields.len() != 1 { return Err(Error::new_spanned( unnamed_fields.clone(), - "Tuple-like enum variants must contain exactly one element.".to_string(), + "tuple-like enum variants must contain exactly one element".to_string(), )); } } diff --git a/packages/fuels-macros/src/parse_utils.rs b/packages/fuels-macros/src/parse_utils.rs index c34032846..fa71cd348 100644 --- a/packages/fuels-macros/src/parse_utils.rs +++ b/packages/fuels-macros/src/parse_utils.rs @@ -45,13 +45,13 @@ where let original_error = iter .next() - .map(|first_el| Error::new_spanned(first_el, "Original defined here:")); + .map(|first_el| Error::new_spanned(first_el, "original defined here:")); - let the_rest = iter.map(|duplicate| Error::new_spanned(duplicate, "Duplicate!")); + let the_rest = iter.map(|duplicate| Error::new_spanned(duplicate, "duplicate!")); chain!(original_error, the_rest) .combine_errors() - .expect("Has to be at least one error!") + .expect("has to be at least one error!") } fn group_up_duplicates(name_values: &[T], key: KeyFn) -> Vec> @@ -132,7 +132,7 @@ impl Members { .map(|field| { let name = field .ident - .expect("FieldsNamed to only contain named fields."); + .expect("`FieldsNamed` to only contain named fields"); if has_ignore_attr(&field.attrs) { Member::Ignored { name } } else { @@ -162,7 +162,7 @@ impl Members { if fields_unnamed.unnamed.len() != 1 { return Err(Error::new( fields_unnamed.paren_token.span.join(), - "Must have exactly one element", + "must have exactly one element", )); } fields_unnamed.unnamed.into_iter().next() @@ -171,7 +171,7 @@ impl Members { Fields::Named(named_fields) => { return Err(Error::new_spanned( named_fields, - "Struct-like enum variants are not supported.", + "struct-like enum variants are not supported", )) } } diff --git a/packages/fuels-macros/src/parse_utils/command.rs b/packages/fuels-macros/src/parse_utils/command.rs index e634f2787..5f0bb09fa 100644 --- a/packages/fuels-macros/src/parse_utils/command.rs +++ b/packages/fuels-macros/src/parse_utils/command.rs @@ -27,7 +27,7 @@ impl Command { let name = meta_list.path.get_ident().cloned().ok_or_else(|| { Error::new_spanned( &meta_list.path, - "Command name cannot be a Path -- i.e. contain ':'.", + "command name cannot be a Path -- i.e. contain ':'", ) })?; @@ -38,7 +38,7 @@ impl Command { } else { Err(Error::new_spanned( meta, - "Expected a command name literal -- e.g. `Something(...)`", + "expected a command name literal -- e.g. `Something(...)`", )) } } @@ -60,7 +60,7 @@ impl Command { ) -> syn::Result { syn::parse::Parser::parse2(Command::parse_multiple, stream.clone())? .pop() - .ok_or_else(|| Error::new_spanned(stream, "Expected to have at least one command!")) + .ok_or_else(|| Error::new_spanned(stream, "expected to have at least one command!")) } } #[cfg(test)] diff --git a/packages/fuels-macros/src/parse_utils/unique_lit_strs.rs b/packages/fuels-macros/src/parse_utils/unique_lit_strs.rs index 52b1d6a52..a4e43cb5e 100644 --- a/packages/fuels-macros/src/parse_utils/unique_lit_strs.rs +++ b/packages/fuels-macros/src/parse_utils/unique_lit_strs.rs @@ -75,18 +75,18 @@ mod tests { let stream = quote! {SomeCommand("lit1", "lit2", "lit1")}; // when - let err = parse_unique_lit_strs(stream).expect_err("Should have failed"); + let err = parse_unique_lit_strs(stream).expect_err("should have failed"); // then let messages = err.into_iter().map(|e| e.to_string()).collect::>(); - assert_eq!(messages, vec!["Original defined here:", "Duplicate!"]); + assert_eq!(messages, vec!["original defined here:", "duplicate!"]); } #[test] fn only_strings_allowed() { let stream = quote! {SomeCommand("lit1", "lit2", true)}; - let err = parse_unique_lit_strs(stream).expect_err("Should have failed"); + let err = parse_unique_lit_strs(stream).expect_err("should have failed"); assert_eq!(err.to_string(), "expected string literal"); } diff --git a/packages/fuels-macros/src/parse_utils/unique_name_values.rs b/packages/fuels-macros/src/parse_utils/unique_name_values.rs index 5071d0a9f..3b6a87e69 100644 --- a/packages/fuels-macros/src/parse_utils/unique_name_values.rs +++ b/packages/fuels-macros/src/parse_utils/unique_name_values.rs @@ -20,7 +20,7 @@ impl UniqueNameValues { pub fn new(tokens: TokenStream) -> syn::Result { let name_value_metas = Punctuated::::parse_terminated .parse2(tokens) - .map_err(|e| Error::new(e.span(), "Expected name='value'"))?; + .map_err(|e| Error::new(e.span(), "expected name='value'"))?; let span = name_value_metas.span(); let name_values = Self::extract_name_values(name_value_metas.into_iter())?; @@ -49,9 +49,7 @@ impl UniqueNameValues { .map(|name| { Error::new_spanned( name.clone(), - format!( - "Attribute '{name}' not recognized! Expected one of: {expected_names}." - ), + format!("attribute '{name}' not recognized! Expected one of: {expected_names}"), ) }) .validate_no_errors() @@ -60,14 +58,14 @@ impl UniqueNameValues { pub fn get_as_lit_str(&self, name: &str) -> syn::Result<&LitStr> { let value = self .try_get(name) - .ok_or_else(|| Error::new(self.span, format!("Missing attribute '{name}'.")))?; + .ok_or_else(|| Error::new(self.span, format!("missing attribute '{name}'")))?; if let Lit::Str(lit_str) = value { Ok(lit_str) } else { Err(Error::new_spanned( value.clone(), - format!("Expected the attribute '{name}' to have a string value!"), + format!("expected the attribute '{name}' to have a string value"), )) } } @@ -81,12 +79,12 @@ impl UniqueNameValues { let ident = nv.path.get_ident().cloned().ok_or_else(|| { Error::new_spanned( nv.path, - "Attribute name cannot be a `Path` -- i.e. must not contain ':'.", + "attribute name cannot be a `Path` -- i.e. must not contain ':'", ) })?; let Expr::Lit(expr_lit) = nv.value else { - return Err(Error::new_spanned(nv.value, "Expected literal")); + return Err(Error::new_spanned(nv.value, "expected literal")); }; Ok((ident, expr_lit.lit)) @@ -117,7 +115,7 @@ mod tests { let attr_values = ["attr1", "attr2"].map(|attr| { name_values .try_get(attr) - .unwrap_or_else(|| panic!("Attribute {attr} should have existed!")) + .unwrap_or_else(|| panic!("attribute {attr} should have existed")) .clone() }); @@ -138,22 +136,22 @@ mod tests { let tokens = quote! {SomeCommand(duplicate=1, something=2, duplicate=3)}; // when - let err = extract_name_values(tokens).expect_err("Should have failed"); + let err = extract_name_values(tokens).expect_err("should have failed"); // then let messages = err.into_iter().map(|e| e.to_string()).collect::>(); - assert_eq!(messages, vec!["Original defined here:", "Duplicate!"]); + assert_eq!(messages, vec!["original defined here:", "duplicate!"]); } #[test] fn attr_names_cannot_be_paths() { let tokens = quote! {SomeCommand(something::duplicate=1)}; - let err = extract_name_values(tokens).expect_err("Should have failed"); + let err = extract_name_values(tokens).expect_err("should have failed"); assert_eq!( err.to_string(), - "Attribute name cannot be a `Path` -- i.e. must not contain ':'." + "attribute name cannot be a `Path` -- i.e. must not contain ':'" ); } @@ -161,9 +159,9 @@ mod tests { fn only_name_value_is_accepted() { let tokens = quote! {SomeCommand(name="value", "something_else")}; - let err = extract_name_values(tokens).expect_err("Should have failed"); + let err = extract_name_values(tokens).expect_err("should have failed"); - assert_eq!(err.to_string(), "Expected name='value'"); + assert_eq!(err.to_string(), "expected name='value'"); } #[test] @@ -185,11 +183,11 @@ mod tests { let err = name_values .validate_has_no_other_names(&["name", "other_is_not_allowed"]) - .expect_err("Should have failed"); + .expect_err("should have failed"); assert_eq!( err.to_string(), - "Attribute 'other' not recognized! Expected one of: 'name', 'other_is_not_allowed'." + "attribute 'other' not recognized! Expected one of: 'name', 'other_is_not_allowed'" ); Ok(()) @@ -212,11 +210,11 @@ mod tests { let err = name_values .get_as_lit_str("name") - .expect_err("Should have failed"); + .expect_err("should have failed"); assert_eq!( err.to_string(), - "Expected the attribute 'name' to have a string value!" + "expected the attribute 'name' to have a string value" ); Ok(()) @@ -228,9 +226,9 @@ mod tests { let err = name_values .get_as_lit_str("missing") - .expect_err("Should have failed"); + .expect_err("should have failed"); - assert_eq!(err.to_string(), "Missing attribute 'missing'."); + assert_eq!(err.to_string(), "missing attribute 'missing'"); Ok(()) } diff --git a/packages/fuels-macros/tests/ui/abigen/duplicate_attribute.stderr b/packages/fuels-macros/tests/ui/abigen/duplicate_attribute.stderr index 3eaa627e3..b01cb1a7c 100644 --- a/packages/fuels-macros/tests/ui/abigen/duplicate_attribute.stderr +++ b/packages/fuels-macros/tests/ui/abigen/duplicate_attribute.stderr @@ -1,16 +1,16 @@ -error: Original defined here: +error: original defined here: --> tests/ui/abigen/duplicate_attribute.rs:4:5 | 4 | abi = "some-abi.json", | ^^^ -error: Duplicate! +error: duplicate! --> tests/ui/abigen/duplicate_attribute.rs:5:5 | 5 | abi = "some-abi2.json", | ^^^ -error: Duplicate! +error: duplicate! --> tests/ui/abigen/duplicate_attribute.rs:7:5 | 7 | abi = "some-abi3.json", diff --git a/packages/fuels-macros/tests/ui/abigen/invalid_abi_value.stderr b/packages/fuels-macros/tests/ui/abigen/invalid_abi_value.stderr index a31a87fa1..c86c3565b 100644 --- a/packages/fuels-macros/tests/ui/abigen/invalid_abi_value.stderr +++ b/packages/fuels-macros/tests/ui/abigen/invalid_abi_value.stderr @@ -1,4 +1,4 @@ -error: Expected the attribute 'abi' to have a string value! +error: expected the attribute 'abi' to have a string value --> tests/ui/abigen/invalid_abi_value.rs:3:43 | 3 | abigen!(Contract(name = "SomeName", abi = true,)); diff --git a/packages/fuels-macros/tests/ui/abigen/invalid_name_value.stderr b/packages/fuels-macros/tests/ui/abigen/invalid_name_value.stderr index 345f9faa2..413fe612f 100644 --- a/packages/fuels-macros/tests/ui/abigen/invalid_name_value.stderr +++ b/packages/fuels-macros/tests/ui/abigen/invalid_name_value.stderr @@ -1,4 +1,4 @@ -error: Expected the attribute 'name' to have a string value! +error: expected the attribute 'name' to have a string value --> tests/ui/abigen/invalid_name_value.rs:3:25 | 3 | abigen!(Contract(name = true, abi = "some-abi.json",)); diff --git a/packages/fuels-macros/tests/ui/abigen/invalid_program_type.stderr b/packages/fuels-macros/tests/ui/abigen/invalid_program_type.stderr index 1269a1a5f..bd8a22e9c 100644 --- a/packages/fuels-macros/tests/ui/abigen/invalid_program_type.stderr +++ b/packages/fuels-macros/tests/ui/abigen/invalid_program_type.stderr @@ -1,4 +1,4 @@ -error: 'SomeInvalidProgramType' is not a valid program type. Expected one of: 'Script', 'Contract', 'Predicate'. +error: `SomeInvalidProgramType` is not a valid program type. Expected one of: `Script`, `Contract`, `Predicate` --> tests/ui/abigen/invalid_program_type.rs:3:9 | 3 | abigen!(SomeInvalidProgramType( diff --git a/packages/fuels-macros/tests/ui/abigen/missing_abi_attribute.stderr b/packages/fuels-macros/tests/ui/abigen/missing_abi_attribute.stderr index 406ef9913..68fc5c272 100644 --- a/packages/fuels-macros/tests/ui/abigen/missing_abi_attribute.stderr +++ b/packages/fuels-macros/tests/ui/abigen/missing_abi_attribute.stderr @@ -1,4 +1,4 @@ -error: Missing attribute 'abi'. +error: missing attribute 'abi' --> tests/ui/abigen/missing_abi_attribute.rs:3:18 | 3 | abigen!(Contract(name = "SomeName")); diff --git a/packages/fuels-macros/tests/ui/abigen/missing_name_attr.stderr b/packages/fuels-macros/tests/ui/abigen/missing_name_attr.stderr index 1c0d82faf..f1f6af27c 100644 --- a/packages/fuels-macros/tests/ui/abigen/missing_name_attr.stderr +++ b/packages/fuels-macros/tests/ui/abigen/missing_name_attr.stderr @@ -1,4 +1,4 @@ -error: Missing attribute 'name'. +error: missing attribute 'name' --> tests/ui/abigen/missing_name_attr.rs:3:18 | 3 | abigen!(Contract(abi = "some-abi.json")); diff --git a/packages/fuels-macros/tests/ui/abigen/unrecognized_attribute.stderr b/packages/fuels-macros/tests/ui/abigen/unrecognized_attribute.stderr index 54491e253..8c4eadc93 100644 --- a/packages/fuels-macros/tests/ui/abigen/unrecognized_attribute.stderr +++ b/packages/fuels-macros/tests/ui/abigen/unrecognized_attribute.stderr @@ -1,4 +1,4 @@ -error: Attribute 'unknown' not recognized! Expected one of: 'name', 'abi'. +error: attribute 'unknown' not recognized! Expected one of: 'name', 'abi' --> tests/ui/abigen/unrecognized_attribute.rs:6:5 | 6 | unknown = "something" diff --git a/packages/fuels-macros/tests/ui/derive/parameterize/attribute_must_be_named_value.stderr b/packages/fuels-macros/tests/ui/derive/parameterize/attribute_must_be_named_value.stderr index 0ce1b2af3..e1fdf0423 100644 --- a/packages/fuels-macros/tests/ui/derive/parameterize/attribute_must_be_named_value.stderr +++ b/packages/fuels-macros/tests/ui/derive/parameterize/attribute_must_be_named_value.stderr @@ -1,10 +1,10 @@ -error: Expected name='value' +error: expected name='value' --> tests/ui/derive/parameterize/attribute_must_be_named_value.rs:4:3 | 4 | #[FuelsTypesPath] | ^^^^^^^^^^^^^^ -error: Expected string literal +error: expected string literal --> tests/ui/derive/parameterize/attribute_must_be_named_value.rs:10:20 | 10 | #[FuelsTypesPath = true] diff --git a/packages/fuels-macros/tests/ui/derive/parameterize/only_one_variant_element_supported.stderr b/packages/fuels-macros/tests/ui/derive/parameterize/only_one_variant_element_supported.stderr index 7bb7264cc..4bc345b0a 100644 --- a/packages/fuels-macros/tests/ui/derive/parameterize/only_one_variant_element_supported.stderr +++ b/packages/fuels-macros/tests/ui/derive/parameterize/only_one_variant_element_supported.stderr @@ -1,10 +1,10 @@ -error: Must have exactly one element +error: must have exactly one element --> tests/ui/derive/parameterize/only_one_variant_element_supported.rs:6:6 | 6 | B(), | ^^ -error: Must have exactly one element +error: must have exactly one element --> tests/ui/derive/parameterize/only_one_variant_element_supported.rs:11:6 | 11 | A(u64, u32), diff --git a/packages/fuels-macros/tests/ui/derive/parameterize/struct_like_enum_variants_not_supported.stderr b/packages/fuels-macros/tests/ui/derive/parameterize/struct_like_enum_variants_not_supported.stderr index 782235e16..4478fdcac 100644 --- a/packages/fuels-macros/tests/ui/derive/parameterize/struct_like_enum_variants_not_supported.stderr +++ b/packages/fuels-macros/tests/ui/derive/parameterize/struct_like_enum_variants_not_supported.stderr @@ -1,4 +1,4 @@ -error: Struct-like enum variants are not supported. +error: struct-like enum variants are not supported --> tests/ui/derive/parameterize/struct_like_enum_variants_not_supported.rs:6:7 | 6 | B { something: u64 }, diff --git a/packages/fuels-macros/tests/ui/derive/tokenizable/only_one_variant_element_supported.stderr b/packages/fuels-macros/tests/ui/derive/tokenizable/only_one_variant_element_supported.stderr index 5808337d1..c43fbffe8 100644 --- a/packages/fuels-macros/tests/ui/derive/tokenizable/only_one_variant_element_supported.stderr +++ b/packages/fuels-macros/tests/ui/derive/tokenizable/only_one_variant_element_supported.stderr @@ -1,10 +1,10 @@ -error: Tuple-like enum variants must contain exactly one element. +error: tuple-like enum variants must contain exactly one element --> tests/ui/derive/tokenizable/only_one_variant_element_supported.rs:6:6 | 6 | B(), | ^^ -error: Tuple-like enum variants must contain exactly one element. +error: tuple-like enum variants must contain exactly one element --> tests/ui/derive/tokenizable/only_one_variant_element_supported.rs:11:6 | 11 | A(u64, u32), diff --git a/packages/fuels-macros/tests/ui/derive/tokenizable/struct_like_enum_variants_not_supported.stderr b/packages/fuels-macros/tests/ui/derive/tokenizable/struct_like_enum_variants_not_supported.stderr index 68906daac..09e18b6ea 100644 --- a/packages/fuels-macros/tests/ui/derive/tokenizable/struct_like_enum_variants_not_supported.stderr +++ b/packages/fuels-macros/tests/ui/derive/tokenizable/struct_like_enum_variants_not_supported.stderr @@ -1,4 +1,4 @@ -error: Struct like enum variants are not supported +error: struct like enum variants are not supported --> tests/ui/derive/tokenizable/struct_like_enum_variants_not_supported.rs:6:7 | 6 | B { something: u64 }, diff --git a/packages/fuels-macros/tests/ui/setup_program_test/duplicate_wallet_names.stderr b/packages/fuels-macros/tests/ui/setup_program_test/duplicate_wallet_names.stderr index c626cdb4f..a08b64360 100644 --- a/packages/fuels-macros/tests/ui/setup_program_test/duplicate_wallet_names.stderr +++ b/packages/fuels-macros/tests/ui/setup_program_test/duplicate_wallet_names.stderr @@ -1,10 +1,10 @@ -error: Original defined here: +error: original defined here: --> tests/ui/setup_program_test/duplicate_wallet_names.rs:4:13 | 4 | Wallets("wallet1", "wallet1"), | ^^^^^^^^^ -error: Duplicate! +error: duplicate! --> tests/ui/setup_program_test/duplicate_wallet_names.rs:4:24 | 4 | Wallets("wallet1", "wallet1"), diff --git a/packages/fuels-programs/src/call_utils.rs b/packages/fuels-programs/src/call_utils.rs index d9a58f0e8..b89d40442 100644 --- a/packages/fuels-programs/src/call_utils.rs +++ b/packages/fuels-programs/src/call_utils.rs @@ -10,7 +10,7 @@ use fuels_core::{ offsets::call_script_data_offset, types::{ bech32::{Bech32Address, Bech32ContractId}, - errors::{Error as FuelsError, Result}, + errors::{transaction::Reason, Error, Result}, input::Input, param_types::ParamType, transaction::{ScriptTransaction, TxPolicies}, @@ -86,7 +86,7 @@ pub trait TxDependencyExtension: Sized { match self.simulate().await { Ok(_) => return Ok(self), - Err(FuelsError::RevertTransactionError { ref receipts, .. }) => { + Err(Error::Transaction(Reason::Reverted { ref receipts, .. })) => { self = self.append_missing_dependencies(receipts); } diff --git a/packages/fuels-programs/src/contract.rs b/packages/fuels-programs/src/contract.rs index 6b4f50f43..11a20b527 100644 --- a/packages/fuels-programs/src/contract.rs +++ b/packages/fuels-programs/src/contract.rs @@ -1,7 +1,7 @@ use std::{ collections::HashMap, fmt::Debug, - fs, + fs, io, marker::PhantomData, path::{Path, PathBuf}, }; @@ -184,9 +184,9 @@ impl StorageSlots { validate_path_and_extension(storage_path, "json")?; let storage_json_string = std::fs::read_to_string(storage_path).map_err(|e| { - error!( - InvalidData, - "failed to read storage slots from: {storage_path:?}. Reason: {e}" + io::Error::new( + e.kind(), + format!("failed to read storage slots from: {storage_path:?}: {e}"), ) })?; @@ -330,8 +330,12 @@ impl Contract { let binary_filepath = binary_filepath.as_ref(); validate_path_and_extension(binary_filepath, "bin")?; - let mut binary = fs::read(binary_filepath) - .map_err(|_| error!(InvalidData, "failed to read binary: {binary_filepath:?}"))?; + let mut binary = fs::read(binary_filepath).map_err(|e| { + std::io::Error::new( + e.kind(), + format!("failed to read binary: {binary_filepath:?}: {e}"), + ) + })?; config.configurables.update_constants_in(&mut binary); @@ -360,10 +364,11 @@ impl Contract { fn autoload_storage_slots(contract_binary: &Path) -> Result { let storage_file = expected_storage_slots_filepath(contract_binary) - .ok_or_else(|| error!(InvalidData, "Could not determine storage slots file"))?; + .ok_or_else(|| error!(Other, "could not determine storage slots file"))?; StorageSlots::load_from_file(&storage_file) - .map_err(|_| error!(InvalidData, "Could not autoload storage slots from file: {storage_file:?}. Either provide the file or disable autoloading in StorageConfiguration")) + .map_err(|_| error!(Other, "could not autoload storage slots from file: {storage_file:?}. \ + Either provide the file or disable autoloading in `StorageConfiguration`")) } fn expected_storage_slots_filepath(contract_binary: &Path) -> Option { @@ -376,19 +381,19 @@ fn expected_storage_slots_filepath(contract_binary: &Path) -> Option { fn validate_path_and_extension(file_path: &Path, extension: &str) -> Result<()> { if !file_path.exists() { - return Err(error!(InvalidData, "file {file_path:?} does not exist")); + return Err(Error::IO(io::Error::new( + io::ErrorKind::NotFound, + format!("file {file_path:?} does not exist"), + ))); } - let path_extension = file_path.extension().ok_or_else(|| { - error!( - InvalidData, - "could not extract extension from: {file_path:?}" - ) - })?; + let path_extension = file_path + .extension() + .ok_or_else(|| error!(Other, "could not extract extension from: {file_path:?}"))?; if extension != path_extension { return Err(error!( - InvalidData, + Other, "expected {file_path:?} to have '.{extension}' extension" )); } @@ -563,7 +568,7 @@ where /// ``` pub fn call_params(mut self, params: CallParameters) -> Result { if !self.is_payable() && params.amount > 0 { - return Err(Error::AssetsForwardedToNonPayableMethod); + return Err(error!(Other, "assets forwarded to non-payable method")); } self.contract_call.call_parameters = params; Ok(self) @@ -820,8 +825,8 @@ impl MultiContractCallHandler { fn validate_contract_calls(&self) -> Result<()> { if self.contract_calls.is_empty() { return Err(error!( - InvalidData, - "No calls added. Have you used '.add_calls()'?" + Other, + "no calls added. Have you used '.add_calls()'?" )); } @@ -844,13 +849,13 @@ impl MultiContractCallHandler { Ok(()) } else { Err(error!( - InvalidData, - "The contract call with the heap type return must be at the last position" + Other, + "the contract call with the heap type return must be at the last position" )) } } _ => Err(error!( - InvalidData, + Other, "`MultiContractCallHandler` can have only one call that returns a heap type" )), } @@ -1058,14 +1063,14 @@ mod tests { // when let error = Contract::load_from(&contract_bin, load_config) - .expect_err("Should have failed because the storage slots file is missing"); + .expect_err("should have failed because the storage slots file is missing"); // then let storage_slots_path = temp_dir.path().join("my_contract-storage_slots.json"); - let Error::InvalidData(msg) = error else { - panic!("Expected an error of type InvalidData"); + let Error::Other(msg) = error else { + panic!("expected an error of type `Other`"); }; - assert_eq!(msg, format!("Could not autoload storage slots from file: {storage_slots_path:?}. Either provide the file or disable autoloading in StorageConfiguration")); + assert_eq!(msg, format!("could not autoload storage slots from file: {storage_slots_path:?}. Either provide the file or disable autoloading in `StorageConfiguration`")); } fn save_slots(slots: &Vec, path: &Path) { diff --git a/packages/fuels-programs/src/receipt_parser.rs b/packages/fuels-programs/src/receipt_parser.rs index 7804de912..1c68d02b7 100644 --- a/packages/fuels-programs/src/receipt_parser.rs +++ b/packages/fuels-programs/src/receipt_parser.rs @@ -54,8 +54,8 @@ impl ReceiptParser { fn missing_receipts_error(output_param: &ParamType) -> Error { error!( - InvalidData, - "ReceiptDecoder: failed to find matching receipts entry for {output_param:?}" + Codec, + "`ReceiptDecoder`: failed to find matching receipts entry for {output_param:?}" ) } diff --git a/packages/fuels-programs/src/submit_response.rs b/packages/fuels-programs/src/submit_response.rs index 793f6326f..13d0b332b 100644 --- a/packages/fuels-programs/src/submit_response.rs +++ b/packages/fuels-programs/src/submit_response.rs @@ -73,7 +73,8 @@ where CallHandler::Contract(contract_handler) => &contract_handler.account, CallHandler::Script(script_handler) => &script_handler.account, }; - Ok(account.try_provider()?) + + account.try_provider() } fn log_decoder(&self) -> &LogDecoder { diff --git a/packages/fuels-test-helpers/src/accounts.rs b/packages/fuels-test-helpers/src/accounts.rs index a56573922..e601c7d26 100644 --- a/packages/fuels-test-helpers/src/accounts.rs +++ b/packages/fuels-test-helpers/src/accounts.rs @@ -169,7 +169,7 @@ mod tests { CoinType::Coin(coin) => { assert_eq!(&coin.owner, wallet.address()) } - CoinType::Message(_) => panic!("Resources contained messages."), + CoinType::Message(_) => panic!("resources contained messages"), } } } diff --git a/packages/fuels-test-helpers/src/fuel_bin_service.rs b/packages/fuels-test-helpers/src/fuel_bin_service.rs index b55f6ff7b..84cc91e80 100644 --- a/packages/fuels-test-helpers/src/fuel_bin_service.rs +++ b/packages/fuels-test-helpers/src/fuel_bin_service.rs @@ -1,4 +1,8 @@ -use std::{net::SocketAddr, path::PathBuf, time::Duration}; +use std::{ + net::{IpAddr, SocketAddr}, + path::PathBuf, + time::Duration, +}; use fuel_core_client::client::FuelClient; use fuel_core_services::State; @@ -103,9 +107,9 @@ impl FuelService { let requested_port = config.addr.port(); let bound_address = match requested_port { - 0 => get_socket_address(), + 0 => get_socket_address()?, _ if is_free(requested_port) => config.addr, - _ => return Err(Error::IOError(std::io::ErrorKind::AddrInUse.into())), + _ => return Err(Error::IO(std::io::ErrorKind::AddrInUse.into())), }; let config = Config { @@ -148,18 +152,17 @@ async fn server_health_check(address: SocketAddr) -> FuelResult<()> { } if !healthy { - return Err(error!( - InfrastructureError, - "Could not connect to fuel core server." - )); + return Err(error!(Other, "could not connect to fuel core server")); } Ok(()) } -fn get_socket_address() -> SocketAddr { - let free_port = pick_unused_port().expect("No ports free"); - SocketAddr::new("127.0.0.1".parse().unwrap(), free_port) +fn get_socket_address() -> FuelResult { + let free_port = pick_unused_port().ok_or(error!(Other, "could not pick a free port"))?; + let address: IpAddr = "127.0.0.1".parse().expect("is valid ip"); + + Ok(SocketAddr::new(address, free_port)) } async fn run_node(mut extended_config: ExtendedConfig) -> FuelResult> { @@ -168,22 +171,16 @@ async fn run_node(mut extended_config: ExtendedConfig) -> FuelResult>(); let path = paths .first() - .ok_or_else(|| error!(InfrastructureError, "no '{}' in PATH", binary_name))?; + .ok_or_else(|| error!(Other, "no `{binary_name}` in PATH"))?; if paths.len() > 1 { eprintln!( - "found more than one '{}' binary in PATH, using '{}'", - binary_name, + "found more than one `{binary_name}` binary in PATH, using `{}`", path.display() ); } @@ -196,7 +193,7 @@ async fn run_node(mut extended_config: ExtendedConfig) -> FuelResult SocketAddr { diff --git a/packages/fuels/src/lib.rs b/packages/fuels/src/lib.rs index c2f928841..e14de266a 100644 --- a/packages/fuels/src/lib.rs +++ b/packages/fuels/src/lib.rs @@ -72,6 +72,7 @@ pub mod prelude { #[cfg(feature = "std")] pub use super::{ accounts::{ + predicate::Predicate, provider::*, wallet::{generate_mnemonic_phrase, WalletUnlocked}, Account, ViewOnlyAccount, @@ -93,7 +94,7 @@ pub mod prelude { pub use super::{ core::constants::*, macros::{abigen, setup_program_test}, - tx::Salt, + tx::{Receipt, Salt}, types::{ bech32::{Bech32Address, Bech32ContractId}, errors::{Error, Result}, diff --git a/packages/fuels/tests/contracts.rs b/packages/fuels/tests/contracts.rs index 48644a5e7..e8b3c0052 100644 --- a/packages/fuels/tests/contracts.rs +++ b/packages/fuels/tests/contracts.rs @@ -1,14 +1,8 @@ -#[allow(unused_imports)] -use std::future::Future; -use std::vec; - use fuels::{ - accounts::{predicate::Predicate, Account}, - core::codec::{calldata, fn_selector}, + core::codec::{calldata, fn_selector, DecoderConfig}, prelude::*, - types::Bits256, + types::{errors::transaction::Reason, Bits256}, }; -use fuels_core::codec::DecoderConfig; #[tokio::test] async fn test_multiple_args() -> Result<()> { @@ -136,7 +130,7 @@ async fn test_reverting_transaction() -> Result<()> { assert!(matches!( response, - Err(Error::RevertTransactionError { revert_id, .. }) if revert_id == 128 + Err(Error::Transaction(Reason::Reverted { revert_id, .. })) if revert_id == 128 )); Ok(()) @@ -696,7 +690,7 @@ async fn test_output_variable_estimation() -> Result<()> { assert!(matches!( response, - Err(Error::RevertTransactionError { .. }) + Err(Error::Transaction(Reason::Reverted { .. })) )); } @@ -709,7 +703,7 @@ async fn test_output_variable_estimation() -> Result<()> { assert!(matches!( response, - Err(Error::RevertTransactionError { .. }) + Err(Error::Transaction(Reason::Reverted { .. })) )); } @@ -854,6 +848,8 @@ async fn test_contract_instance_get_balances() -> Result<()> { #[tokio::test] async fn contract_call_futures_implement_send() -> Result<()> { + use std::future::Future; + fn tokio_spawn_imitation(_: T) where T: Future + Send + 'static, @@ -922,7 +918,10 @@ async fn test_contract_set_estimation() -> Result<()> { .call() .await; - assert!(matches!(res, Err(Error::RevertTransactionError { .. }))); + assert!(matches!( + res, + Err(Error::Transaction(Reason::Reverted { .. })) + )); } let res = contract_caller_instance @@ -1121,20 +1120,19 @@ async fn test_add_custom_assets() -> Result<()> { async fn contract_load_error_messages() { { let binary_path = "tests/contracts/contract_test/out/debug/no_file_on_path.bin"; - let expected_error = format!("Invalid data: file \"{binary_path}\" does not exist"); + let expected_error = format!("io: file \"{binary_path}\" does not exist"); let error = Contract::load_from(binary_path, LoadConfiguration::default()) - .expect_err("Should have failed"); + .expect_err("should have failed"); assert_eq!(error.to_string(), expected_error); } { let binary_path = "tests/contracts/contract_test/out/debug/contract_test-abi.json"; - let expected_error = - format!("Invalid data: expected \"{binary_path}\" to have '.bin' extension"); + let expected_error = format!("expected \"{binary_path}\" to have '.bin' extension"); let error = Contract::load_from(binary_path, LoadConfiguration::default()) - .expect_err("Should have failed"); + .expect_err("should have failed"); assert_eq!(error.to_string(), expected_error); } @@ -1173,9 +1171,9 @@ async fn test_payable_annotation() -> Result<()> { let err = contract_methods .non_payable() .call_params(CallParameters::default().with_amount(100)) - .expect_err("Should return call params error."); + .expect_err("should return call params error"); - assert!(matches!(err, Error::AssetsForwardedToNonPayableMethod)); + assert!(matches!(err, Error::Other(s) if s.contains("assets forwarded to non-payable method"))); // ANCHOR_END: non_payable_params let response = contract_methods @@ -1332,7 +1330,7 @@ fn db_rocksdb() { accounts::wallet::WalletUnlocked, client::{PageDirection, PaginationRequest}, crypto::SecretKey, - prelude::{setup_test_provider, DbType, ViewOnlyAccount, DEFAULT_COIN_AMOUNT}, + prelude::{setup_test_provider, DbType, Error, ViewOnlyAccount, DEFAULT_COIN_AMOUNT}, }; let temp_dir = tempfile::tempdir() @@ -1351,8 +1349,7 @@ fn db_rocksdb() { let wallet = WalletUnlocked::new_from_private_key( SecretKey::from_str( "0x4433d156e8c53bf5b50af07aa95a29436f29a94e0ccc5d58df8e57bdc8583c32", - ) - .unwrap(), + )?, None, ); @@ -1382,7 +1379,7 @@ fn db_rocksdb() { provider.produce_blocks(2, None).await?; - Ok::<(), Box>(()) + Ok::<(), Error>(()) }) .unwrap(); @@ -1401,8 +1398,7 @@ fn db_rocksdb() { let mut wallet = WalletUnlocked::new_from_private_key( SecretKey::from_str( "0x4433d156e8c53bf5b50af07aa95a29436f29a94e0ccc5d58df8e57bdc8583c32", - ) - .unwrap(), + )?, None, ); @@ -1435,7 +1431,7 @@ fn db_rocksdb() { .expect("Db parent folder does not exist"), )?; - Ok::<(), Box>(()) + Ok::<(), Error>(()) }) .unwrap(); } @@ -1459,7 +1455,7 @@ async fn can_configure_decoding_of_contract_return() -> Result<()> { { // Single call: Will not work if max_tokens not big enough methods.i_return_a_1k_el_array().with_decoder_config(DecoderConfig{max_tokens: 100, ..Default::default()}).call().await.expect_err( - "Should have failed because there are more tokens than what is supported by default.", + "should have failed because there are more tokens than what is supported by default", ); } { @@ -1622,7 +1618,7 @@ async fn test_heap_type_multicall() -> Result<()> { let error = multi_call_handler.submit().await.expect_err("Should error"); assert!(error .to_string() - .contains("The contract call with the heap type return must be at the last position")); + .contains("the contract call with the heap type return must be at the last position")); } Ok(()) diff --git a/packages/fuels/tests/logs.rs b/packages/fuels/tests/logs.rs index fe8fe74a9..fe97b23fc 100644 --- a/packages/fuels/tests/logs.rs +++ b/packages/fuels/tests/logs.rs @@ -1,11 +1,8 @@ -use std::fmt::Debug; - use fuels::{ + core::codec::DecoderConfig, prelude::*, - tx::Receipt, - types::{Bits256, SizedAsciiString}, + types::{errors::transaction::Reason, Bits256, SizedAsciiString}, }; -use fuels_core::codec::DecoderConfig; #[tokio::test] async fn test_parse_logged_variables() -> Result<()> { @@ -425,8 +422,8 @@ async fn test_multi_call_contract_with_contract_logs() -> Result<()> { } fn assert_revert_containing_msg(msg: &str, error: Error) { - assert!(matches!(error, Error::RevertTransactionError { .. })); - if let Error::RevertTransactionError { reason, .. } = error { + assert!(matches!(error, Error::Transaction(Reason::Reverted { .. }))); + if let Error::Transaction(Reason::Reverted { reason, .. }) = error { assert!( reason.contains(msg), "message: \"{msg}\" not contained in reason: \"{reason}\"" @@ -1081,7 +1078,7 @@ async fn test_script_require_from_contract() -> Result<()> { Ok(()) } -fn assert_assert_eq_containing_msg(left: T, right: T, error: Error) { +fn assert_assert_eq_containing_msg(left: T, right: T, error: Error) { let msg = format!("left: `\"{left:?}\"`\n right: `\"{right:?}\"`"); assert_revert_containing_msg(&msg, error) } @@ -1293,8 +1290,8 @@ async fn test_log_results() -> Result<()> { let log = response.decode_logs(); let expected_err = format!( - "Invalid data: missing log formatter for log_id: `LogId({:?}, 128)`, data: `{:?}`. \ - Consider adding external contracts with `with_contracts()`", + "codec: missing log formatter for log_id: `LogId({:?}, 128)`, data: `{:?}`. \ + Consider adding external contracts using `with_contracts()`", contract_instance.id().hash, [0u8; 8] ); @@ -1370,11 +1367,11 @@ async fn can_configure_decoder_for_contract_log_decoding() -> Result<()> { .await?; response.decode_logs_with_type::<[u8; 1000]>().expect_err( - "Should have failed since there are more tokens than what is supported by default.", + "should have failed since there are more tokens than what is supported by default", ); let logs = response.decode_logs(); - assert!(!logs.filter_failed().is_empty(), "Should have had failed to decode logs since there are more tokens than what is supported by default"); + assert!(!logs.filter_failed().is_empty(), "should have had failed to decode logs since there are more tokens than what is supported by default"); } { // Multi call: increasing limits makes the test pass @@ -1478,7 +1475,7 @@ async fn string_slice_log() -> Result<()> { let log = response.decode_logs(); let expected_err = - "Invalid data: String slices can not be decoded from logs. Convert the slice to `str[N]` with `__to_str_array`".to_string(); + "codec: string slices can not be decoded from logs. Convert the slice to `str[N]` with `__to_str_array`".to_string(); let failed = log.filter_failed(); assert_eq!(failed.first().unwrap().to_string(), expected_err); diff --git a/packages/fuels/tests/predicates.rs b/packages/fuels/tests/predicates.rs index 817f7f7f4..fb5ec349c 100644 --- a/packages/fuels/tests/predicates.rs +++ b/packages/fuels/tests/predicates.rs @@ -1,17 +1,7 @@ -use fuel_tx::Output; use fuels::{ - accounts::{predicate::Predicate, Account}, + core::{codec::ABIEncoder, traits::Tokenizable}, prelude::*, - types::{ - coin::Coin, - message::Message, - transaction_builders::{BuildableTransaction, ScriptTransactionBuilder}, - }, -}; -use fuels_core::{ - codec::ABIEncoder, - traits::Tokenizable, - types::{coin_type::CoinType, input::Input}, + types::{coin::Coin, coin_type::CoinType, input::Input, message::Message, output::Output}, }; async fn assert_address_balance( @@ -374,8 +364,7 @@ async fn predicate_transfer_to_base_layer() -> Result<()> { let amount = 1000; let base_layer_address = - Address::from_str("0x4710162c2e3a95a6faff05139150017c9e38e5e280432d546fae345d6ce6d8fe") - .expect("Invalid address."); + Address::from_str("0x4710162c2e3a95a6faff05139150017c9e38e5e280432d546fae345d6ce6d8fe")?; let base_layer_address = Bech32Address::from(base_layer_address); let (tx_id, msg_nonce, _receipts) = predicate @@ -389,10 +378,11 @@ async fn predicate_transfer_to_base_layer() -> Result<()> { .try_provider()? .get_message_proof(&tx_id, &msg_nonce, None, Some(2)) .await? - .expect("Failed to retrieve message proof."); + .expect("failed to retrieve message proof"); assert_eq!(proof.amount, amount); assert_eq!(proof.recipient, base_layer_address); + Ok(()) } diff --git a/packages/fuels/tests/providers.rs b/packages/fuels/tests/providers.rs index d59917ef9..b7a03a7f9 100644 --- a/packages/fuels/tests/providers.rs +++ b/packages/fuels/tests/providers.rs @@ -1,4 +1,4 @@ -use std::{iter, ops::Add, str::FromStr, vec}; +use std::{ops::Add, str::FromStr}; use chrono::{DateTime, Duration, NaiveDateTime, TimeZone, Utc}; use fuels::{ @@ -10,13 +10,12 @@ use fuels::{ types::{ block::Block, coin_type::CoinType, + errors::transaction::Reason, message::Message, transaction_builders::{BuildableTransaction, ScriptTransactionBuilder}, Bits256, }, }; -use rand::Rng; -use tai64::Tai64; #[tokio::test] async fn test_provider_launch_and_connect() -> Result<()> { @@ -89,7 +88,7 @@ async fn test_network_error() -> Result<()> { .deploy(&wallet, TxPolicies::default()) .await; - assert!(matches!(response, Err(Error::ProviderError(_)))); + assert!(matches!(response, Err(Error::Provider(_)))); Ok(()) } @@ -97,7 +96,7 @@ async fn test_network_error() -> Result<()> { async fn test_input_message() -> Result<()> { let compare_messages = |messages_from_provider: Vec, used_messages: Vec| -> bool { - iter::zip(&used_messages, &messages_from_provider).all(|(a, b)| { + std::iter::zip(&used_messages, &messages_from_provider).all(|(a, b)| { a.sender == b.sender && a.recipient == b.recipient && a.nonce == b.nonce @@ -295,7 +294,7 @@ async fn contract_deployment_respects_maturity() -> Result<()> { "Should not deploy contract since block height (0) is less than the requested maturity (1)", ); - let Error::ValidationError(s) = err else { + let Error::Transaction(Reason::Validation(s)) = err else { panic!("Expected a ValidationError, got: {err}"); }; assert_eq!(s, "TransactionMaturity"); @@ -487,7 +486,7 @@ async fn test_gas_errors() -> Result<()> { .await .expect_err("should error"); - let expected = "Revert transaction error: OutOfGas"; + let expected = "transaction reverted: OutOfGas"; assert!(response.to_string().starts_with(expected)); // Test for insufficient base asset amount to pay for the transaction fee @@ -499,7 +498,7 @@ async fn test_gas_errors() -> Result<()> { .await .expect_err("should error"); - let expected = "Response errors; Validity(InsufficientFeeAmount"; + let expected = "provider: Response errors; Validity(InsufficientFeeAmount"; assert!(response.to_string().contains(expected)); Ok(()) @@ -530,7 +529,8 @@ async fn test_call_param_gas_errors() -> Result<()> { .await .expect_err("should error"); - let expected = "Revert transaction error: OutOfGas"; + let expected = "transaction reverted: OutOfGas"; + dbg!(&response.to_string()); assert!(response.to_string().starts_with(expected)); // Call params gas_forwarded exceeds transaction limit @@ -575,6 +575,8 @@ async fn test_get_gas_used() -> Result<()> { #[tokio::test] #[ignore] async fn testnet_hello_world() -> Result<()> { + use rand::Rng; + // Note that this test might become flaky. // This test depends on: // 1. The testnet being up and running; @@ -735,7 +737,7 @@ fn given_a_message(address: Bech32Address, message_amount: u64) -> Message { } fn convert_to_datetime(timestamp: u64) -> DateTime { - let unix = Tai64(timestamp).to_unix(); + let unix = tai64::Tai64(timestamp).to_unix(); NaiveDateTime::from_timestamp_opt(unix, 0) .unwrap() .and_local_timezone(Utc) diff --git a/packages/fuels/tests/scripts.rs b/packages/fuels/tests/scripts.rs index c210133cd..e20b31ecd 100644 --- a/packages/fuels/tests/scripts.rs +++ b/packages/fuels/tests/scripts.rs @@ -1,5 +1,4 @@ -use fuels::{prelude::*, types::Bits256}; -use fuels_core::codec::DecoderConfig; +use fuels::{core::codec::DecoderConfig, prelude::*, types::Bits256}; #[tokio::test] async fn main_function_arguments() -> Result<()> { diff --git a/packages/fuels/tests/storage.rs b/packages/fuels/tests/storage.rs index 64e8ebb60..c0abb31c2 100644 --- a/packages/fuels/tests/storage.rs +++ b/packages/fuels/tests/storage.rs @@ -86,22 +86,21 @@ async fn test_init_storage_automatically() -> Result<()> { async fn storage_load_error_messages() { { let json_path = "tests/contracts/storage/out/debug/no_file_on_path.json"; - let expected_error = format!("Invalid data: file \"{json_path}\" does not exist"); + let expected_error = format!("io: file \"{json_path}\" does not exist"); let error = StorageConfiguration::default() .add_slot_overrides_from_file(json_path) - .expect_err("Should have failed"); + .expect_err("should have failed"); assert_eq!(error.to_string(), expected_error); } { let json_path = "tests/contracts/storage/out/debug/storage.bin"; - let expected_error = - format!("Invalid data: expected \"{json_path}\" to have '.json' extension"); + let expected_error = format!("expected \"{json_path}\" to have '.json' extension"); let error = StorageConfiguration::default() .add_slot_overrides_from_file(json_path) - .expect_err("Should have failed"); + .expect_err("should have failed"); assert_eq!(error.to_string(), expected_error); } diff --git a/packages/fuels/tests/types_contracts.rs b/packages/fuels/tests/types_contracts.rs index ad3470d9a..0e83147ca 100644 --- a/packages/fuels/tests/types_contracts.rs +++ b/packages/fuels/tests/types_contracts.rs @@ -1,4 +1,4 @@ -use std::{result::Result as StdResult, str::FromStr}; +use std::str::FromStr; use fuels::{ prelude::*, @@ -8,7 +8,7 @@ use fuels::{ pub fn null_contract_id() -> Bech32ContractId { // a bech32 contract address that decodes to [0u8;32] Bech32ContractId::from_str("fuel1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqsx2mt2") - .unwrap() + .expect("is valid") } #[tokio::test] @@ -538,7 +538,7 @@ async fn test_enum_inside_struct() -> Result<()> { } #[tokio::test] -async fn native_types_support() -> StdResult<(), Box> { +async fn native_types_support() -> Result<()> { setup_program_test!( Wallets("wallet"), Abigen(Contract( @@ -571,6 +571,7 @@ async fn native_types_support() -> StdResult<(), Box> { response.value, Address::from_str("0x0000000000000000000000000000000000000000000000000000000000000000")? ); + Ok(()) } @@ -790,13 +791,13 @@ async fn type_inside_enum() -> Result<()> { response.value, "The FuelVM deems that we've not encoded the nested enum correctly. Investigate!" ); + Ok(()) } #[tokio::test] -#[should_panic( - expected = "SizedAsciiString<4> can only be constructed from a String of length 4. Got: fuell" -)] +#[should_panic(expected = "`SizedAsciiString<4>` must be constructed from a \ + `String` of length 4. Got: `fuell`")] async fn strings_must_have_correct_length() { abigen!(Contract( name = "SimpleContract", @@ -847,9 +848,8 @@ async fn strings_must_have_correct_length() { } #[tokio::test] -#[should_panic( - expected = "SizedAsciiString must be constructed from a string containing only ascii encodable characters. Got: fueŁ" -)] +#[should_panic(expected = "`SizedAsciiString` must be constructed from a `String` \ + containing only ascii encodable characters. Got: `fueŁ`")] async fn strings_must_have_all_ascii_chars() { abigen!(Contract( name = "SimpleContract", @@ -898,9 +898,8 @@ async fn strings_must_have_all_ascii_chars() { } #[tokio::test] -#[should_panic( - expected = "SizedAsciiString<4> can only be constructed from a String of length 4. Got: fuell" -)] +#[should_panic(expected = "`SizedAsciiString<4>` must be constructed from a \ + `String` of length 4. Got: `fuell`")] async fn strings_must_have_correct_length_custom_types() { abigen!(Contract( name = "SimpleContract", @@ -984,9 +983,8 @@ async fn strings_must_have_correct_length_custom_types() { } #[tokio::test] -#[should_panic( - expected = "SizedAsciiString must be constructed from a string containing only ascii encodable characters. Got: fueŁ" -)] +#[should_panic(expected = "`SizedAsciiString` must be constructed from a `String` \ + containing only ascii encodable characters. Got: `fueŁ`")] async fn strings_must_have_all_ascii_chars_custom_types() { abigen!(Contract( name = "SimpleContract", @@ -1078,7 +1076,7 @@ async fn strings_must_have_all_ascii_chars_custom_types() { } #[tokio::test] -async fn test_rust_option_can_be_decoded() -> StdResult<(), Box> { +async fn test_rust_option_can_be_decoded() -> Result<()> { setup_program_test!( Wallets("wallet"), Abigen(Contract( @@ -1130,7 +1128,7 @@ async fn test_rust_option_can_be_decoded() -> StdResult<(), Box StdResult<(), Box> { +async fn test_rust_option_can_be_encoded() -> Result<()> { setup_program_test!( Wallets("wallet"), Abigen(Contract( @@ -1184,7 +1182,7 @@ async fn test_rust_option_can_be_encoded() -> StdResult<(), Box StdResult<(), Box> { +async fn test_rust_result_can_be_decoded() -> Result<()> { setup_program_test!( Wallets("wallet"), Abigen(Contract( @@ -1236,7 +1234,7 @@ async fn test_rust_result_can_be_decoded() -> StdResult<(), Box StdResult<(), Box> { +async fn test_rust_result_can_be_encoded() -> Result<()> { setup_program_test!( Wallets("wallet"), Abigen(Contract( @@ -1271,7 +1269,7 @@ async fn test_rust_result_can_be_encoded() -> StdResult<(), Box StdResult<(), Box> { +async fn test_identity_can_be_decoded() -> Result<()> { setup_program_test!( Wallets("wallet"), Abigen(Contract( @@ -1316,7 +1314,7 @@ async fn test_identity_can_be_decoded() -> StdResult<(), Box StdResult<(), Box> { +async fn test_identity_can_be_encoded() -> Result<()> { setup_program_test!( Wallets("wallet"), Abigen(Contract( @@ -1364,7 +1362,7 @@ async fn test_identity_can_be_encoded() -> StdResult<(), Box StdResult<(), Box> { +async fn test_identity_with_two_contracts() -> Result<()> { setup_program_test!( Wallets("wallet"), Abigen(Contract( @@ -2141,9 +2139,8 @@ async fn test_heap_type_in_enums() -> Result<()> { .returns_a_heap_type_too_deep() .call() .await - .expect_err("Should fail because it has a deeply nested heap type"); - let expected = - "Invalid type: Enums currently support only one level deep heap types.".to_string(); + .expect_err("should fail because it has a deeply nested heap type"); + let expected = "codec: enums currently support only one level deep heap types".to_string(); assert_eq!(resp.to_string(), expected); Ok(()) } diff --git a/packages/fuels/tests/types_predicates.rs b/packages/fuels/tests/types_predicates.rs index 5d6c71f1f..24a8c7a33 100644 --- a/packages/fuels/tests/types_predicates.rs +++ b/packages/fuels/tests/types_predicates.rs @@ -3,9 +3,10 @@ use std::path::Path; use fuels::{ accounts::{predicate::Predicate, Account}, prelude::*, - types::{coin::Coin, message::Message, unresolved_bytes::UnresolvedBytes, AssetId, U256}, + types::{ + coin::Coin, message::Message, unresolved_bytes::UnresolvedBytes, AssetId, Bits256, U256, + }, }; -use fuels_core::types::Bits256; async fn assert_predicate_spendable( data: UnresolvedBytes, @@ -147,9 +148,8 @@ async fn spend_predicate_coins_messages_address() -> Result<()> { abi = "packages/fuels/tests/types/predicates/address/out/debug/address-abi.json" )); - let addr: Address = "0xef86afa9696cf0dc6385e2c407a6e159a1103cefb7e2ae0636fb33d3cb2a9e4a" - .parse() - .unwrap(); + let addr: Address = + "0xef86afa9696cf0dc6385e2c407a6e159a1103cefb7e2ae0636fb33d3cb2a9e4a".parse()?; let data = MyPredicateEncoder::encode_data(addr); diff --git a/packages/fuels/tests/wallets.rs b/packages/fuels/tests/wallets.rs index daf72d56d..6ef3906e1 100644 --- a/packages/fuels/tests/wallets.rs +++ b/packages/fuels/tests/wallets.rs @@ -1,12 +1,7 @@ use std::iter::repeat; use fuel_tx::{input::coin::CoinSigned, Bytes32, Input, Output, TxPointer, UtxoId}; -use fuels::{ - prelude::*, - types::transaction_builders::{BuildableTransaction, ScriptTransactionBuilder}, -}; -use fuels_accounts::wallet::WalletUnlocked; -use fuels_test_helpers::setup_test_provider; +use fuels::prelude::*; #[tokio::test] async fn test_wallet_balance_api_multi_asset() -> Result<()> { diff --git a/scripts/check-docs/src/lib.rs b/scripts/check-docs/src/lib.rs index 457cd7d0d..1e5bcd903 100644 --- a/scripts/check-docs/src/lib.rs +++ b/scripts/check-docs/src/lib.rs @@ -176,7 +176,7 @@ pub fn extract_starts_and_ends( let anchor_name = &capture[3]; Ok(Anchor { - line_no: line_no.parse().unwrap(), + line_no: line_no.parse()?, name: anchor_name.to_string(), file, })