feat: use thiserror library to handle error creation
This commit is contained in:
		
							parent
							
								
									06fa9d751b
								
							
						
					
					
						commit
						61e58240fc
					
				
							
								
								
									
										9
									
								
								bdk-ffi/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										9
									
								
								bdk-ffi/Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -161,6 +161,7 @@ dependencies = [ | |||||||
|  "bdk", |  "bdk", | ||||||
|  "bdk_esplora", |  "bdk_esplora", | ||||||
|  "bdk_file_store", |  "bdk_file_store", | ||||||
|  |  "thiserror", | ||||||
|  "uniffi", |  "uniffi", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| @ -883,18 +884,18 @@ dependencies = [ | |||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "thiserror" | name = "thiserror" | ||||||
| version = "1.0.56" | version = "1.0.58" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" | checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "thiserror-impl", |  "thiserror-impl", | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| [[package]] | [[package]] | ||||||
| name = "thiserror-impl" | name = "thiserror-impl" | ||||||
| version = "1.0.56" | version = "1.0.58" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" | checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  "proc-macro2", |  "proc-macro2", | ||||||
|  "quote", |  "quote", | ||||||
|  | |||||||
| @ -24,6 +24,7 @@ bdk_esplora = { version = "0.9.0", default-features = false, features = ["std", | |||||||
| bdk_file_store = { version = "0.7.0" } | bdk_file_store = { version = "0.7.0" } | ||||||
| 
 | 
 | ||||||
| uniffi = { version = "=0.26.1" } | uniffi = { version = "=0.26.1" } | ||||||
|  | thiserror = "1.0.58" | ||||||
| 
 | 
 | ||||||
| [build-dependencies] | [build-dependencies] | ||||||
| uniffi = { version = "=0.26.1", features = ["build"] } | uniffi = { version = "=0.26.1", features = ["build"] } | ||||||
|  | |||||||
| @ -3,8 +3,6 @@ use crate::bitcoin::OutPoint; | |||||||
| use bdk::chain::tx_graph::CalculateFeeError as BdkCalculateFeeError; | use bdk::chain::tx_graph::CalculateFeeError as BdkCalculateFeeError; | ||||||
| use bdk_esplora::esplora_client::Error as BdkEsploraError; | use bdk_esplora::esplora_client::Error as BdkEsploraError; | ||||||
| 
 | 
 | ||||||
| use std::fmt; |  | ||||||
| 
 |  | ||||||
| use bdk::bitcoin::Network; | use bdk::bitcoin::Network; | ||||||
| use bdk::descriptor::DescriptorError; | use bdk::descriptor::DescriptorError; | ||||||
| use bdk::wallet::error::{BuildFeeBumpError, CreateTxError}; | use bdk::wallet::error::{BuildFeeBumpError, CreateTxError}; | ||||||
| @ -14,77 +12,93 @@ use bdk_file_store::FileError as BdkFileError; | |||||||
| use bdk_file_store::IterError; | use bdk_file_store::IterError; | ||||||
| use std::convert::Infallible; | use std::convert::Infallible; | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] | #[derive(Debug, thiserror::Error)] | ||||||
| pub enum Alpha3Error { | pub enum Alpha3Error { | ||||||
|  |     #[error("generic error in ffi")] | ||||||
|     Generic, |     Generic, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl fmt::Display for Alpha3Error { | #[derive(Debug, thiserror::Error)] | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | pub enum CalculateFeeError { | ||||||
|         match self { |     #[error("missing transaction output: {out_points:?}")] | ||||||
|             Alpha3Error::Generic => write!(f, "Error in FFI"), |     MissingTxOut { out_points: Vec<OutPoint> }, | ||||||
|         } | 
 | ||||||
|     } |     #[error("negative fee value: {fee}")] | ||||||
|  |     NegativeFee { fee: i64 }, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl std::error::Error for Alpha3Error {} | #[derive(Debug, thiserror::Error)] | ||||||
| 
 |  | ||||||
| #[derive(Debug)] |  | ||||||
| pub enum WalletCreationError { | pub enum WalletCreationError { | ||||||
|     // Errors coming from the FileError enum
 |     // Errors coming from the FileError enum
 | ||||||
|     Io { |     #[error("io error trying to read file: {e}")] | ||||||
|         e: String, |     Io { e: String }, | ||||||
|     }, | 
 | ||||||
|     InvalidMagicBytes { |     #[error("file has invalid magic bytes: expected={expected:?} got={got:?}")] | ||||||
|         got: Vec<u8>, |     InvalidMagicBytes { got: Vec<u8>, expected: Vec<u8> }, | ||||||
|         expected: Vec<u8>, |  | ||||||
|     }, |  | ||||||
| 
 | 
 | ||||||
|     // Errors coming from the NewOrLoadError enum
 |     // Errors coming from the NewOrLoadError enum
 | ||||||
|  |     #[error("error with descriptor")] | ||||||
|     Descriptor, |     Descriptor, | ||||||
|  | 
 | ||||||
|  |     #[error("failed to write to persistence")] | ||||||
|     Write, |     Write, | ||||||
|  | 
 | ||||||
|  |     #[error("failed to load from persistence")] | ||||||
|     Load, |     Load, | ||||||
|  | 
 | ||||||
|  |     #[error("wallet is not initialized, persistence backend is empty")] | ||||||
|     NotInitialized, |     NotInitialized, | ||||||
|  | 
 | ||||||
|  |     #[error("loaded genesis hash does not match the expected one")] | ||||||
|     LoadedGenesisDoesNotMatch, |     LoadedGenesisDoesNotMatch, | ||||||
|  | 
 | ||||||
|  |     #[error("loaded network type is not {expected}, got {got:?}")] | ||||||
|     LoadedNetworkDoesNotMatch { |     LoadedNetworkDoesNotMatch { | ||||||
|         expected: Network, |         expected: Network, | ||||||
|         got: Option<Network>, |         got: Option<Network>, | ||||||
|     }, |     }, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl fmt::Display for WalletCreationError { | #[derive(Debug, thiserror::Error)] | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | pub enum EsploraError { | ||||||
|         match self { |     #[error("ureq error: {error_message}")] | ||||||
|             Self::Io { e } => write!(f, "io error trying to read file: {}", e), |     Ureq { error_message: String }, | ||||||
|             Self::InvalidMagicBytes { got, expected } => write!( |  | ||||||
|                 f, |  | ||||||
|                 "file has invalid magic bytes: expected={:?} got={:?}", |  | ||||||
|                 expected, got, |  | ||||||
|             ), |  | ||||||
|             Self::Descriptor => write!(f, "error with descriptor"), |  | ||||||
|             Self::Write => write!(f, "failed to write to persistence"), |  | ||||||
|             Self::Load => write!(f, "failed to load from persistence"), |  | ||||||
|             Self::NotInitialized => { |  | ||||||
|                 write!(f, "wallet is not initialized, persistence backend is empty") |  | ||||||
|             } |  | ||||||
|             Self::LoadedGenesisDoesNotMatch => { |  | ||||||
|                 write!(f, "loaded genesis hash does not match the expected one") |  | ||||||
|             } |  | ||||||
|             Self::LoadedNetworkDoesNotMatch { expected, got } => { |  | ||||||
|                 write!(f, "loaded network type is not {}, got {:?}", expected, got) |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| impl std::error::Error for WalletCreationError {} |     #[error("ureq transport error: {error_message}")] | ||||||
|  |     UreqTransport { error_message: String }, | ||||||
|  | 
 | ||||||
|  |     #[error("http error with status code: {status_code}")] | ||||||
|  |     Http { status_code: u16 }, | ||||||
|  | 
 | ||||||
|  |     #[error("io error: {error_message}")] | ||||||
|  |     Io { error_message: String }, | ||||||
|  | 
 | ||||||
|  |     #[error("no header found in the response")] | ||||||
|  |     NoHeader, | ||||||
|  | 
 | ||||||
|  |     #[error("parsing error: {error_message}")] | ||||||
|  |     Parsing { error_message: String }, | ||||||
|  | 
 | ||||||
|  |     #[error("bitcoin encoding error: {error_message}")] | ||||||
|  |     BitcoinEncoding { error_message: String }, | ||||||
|  | 
 | ||||||
|  |     #[error("hex decoding error: {error_message}")] | ||||||
|  |     Hex { error_message: String }, | ||||||
|  | 
 | ||||||
|  |     #[error("transaction not found")] | ||||||
|  |     TransactionNotFound, | ||||||
|  | 
 | ||||||
|  |     #[error("header height {height} not found")] | ||||||
|  |     HeaderHeightNotFound { height: u32 }, | ||||||
|  | 
 | ||||||
|  |     #[error("header hash not found")] | ||||||
|  |     HeaderHashNotFound, | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| impl From<BdkFileError> for WalletCreationError { | impl From<BdkFileError> for WalletCreationError { | ||||||
|     fn from(error: BdkFileError) -> Self { |     fn from(error: BdkFileError) -> Self { | ||||||
|         match error { |         match error { | ||||||
|             BdkFileError::Io(_) => WalletCreationError::Io { |             BdkFileError::Io(e) => WalletCreationError::Io { e: e.to_string() }, | ||||||
|                 e: "io error trying to read file".to_string(), |  | ||||||
|             }, |  | ||||||
|             BdkFileError::InvalidMagicBytes { got, expected } => { |             BdkFileError::InvalidMagicBytes { got, expected } => { | ||||||
|                 WalletCreationError::InvalidMagicBytes { got, expected } |                 WalletCreationError::InvalidMagicBytes { got, expected } | ||||||
|             } |             } | ||||||
| @ -157,23 +171,6 @@ impl From<CreateTxError<std::io::Error>> for Alpha3Error { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug)] |  | ||||||
| pub enum CalculateFeeError { |  | ||||||
|     MissingTxOut { out_points: Vec<OutPoint> }, |  | ||||||
|     NegativeFee { fee: i64 }, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl fmt::Display for CalculateFeeError { |  | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |  | ||||||
|         match self { |  | ||||||
|             CalculateFeeError::MissingTxOut { out_points } => { |  | ||||||
|                 write!(f, "Missing transaction output: {:?}", out_points) |  | ||||||
|             } |  | ||||||
|             CalculateFeeError::NegativeFee { fee } => write!(f, "Negative fee value: {}", fee), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl From<BdkCalculateFeeError> for CalculateFeeError { | impl From<BdkCalculateFeeError> for CalculateFeeError { | ||||||
|     fn from(error: BdkCalculateFeeError) -> Self { |     fn from(error: BdkCalculateFeeError) -> Self { | ||||||
|         match error { |         match error { | ||||||
| @ -185,53 +182,6 @@ impl From<BdkCalculateFeeError> for CalculateFeeError { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl std::error::Error for CalculateFeeError {} |  | ||||||
| 
 |  | ||||||
| #[derive(Debug)] |  | ||||||
| pub enum EsploraError { |  | ||||||
|     Ureq { error_message: String }, |  | ||||||
|     UreqTransport { error_message: String }, |  | ||||||
|     Http { status_code: u16 }, |  | ||||||
|     Io { error_message: String }, |  | ||||||
|     NoHeader, |  | ||||||
|     Parsing { error_message: String }, |  | ||||||
|     BitcoinEncoding { error_message: String }, |  | ||||||
|     Hex { error_message: String }, |  | ||||||
|     TransactionNotFound, |  | ||||||
|     HeaderHeightNotFound { height: u32 }, |  | ||||||
|     HeaderHashNotFound, |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl fmt::Display for EsploraError { |  | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |  | ||||||
|         match self { |  | ||||||
|             EsploraError::Ureq { error_message } => write!(f, "Ureq error: {}", error_message), |  | ||||||
|             EsploraError::UreqTransport { error_message } => { |  | ||||||
|                 write!(f, "Ureq transport error: {}", error_message) |  | ||||||
|             } |  | ||||||
|             EsploraError::Http { status_code } => { |  | ||||||
|                 write!(f, "HTTP error with status code: {}", status_code) |  | ||||||
|             } |  | ||||||
|             EsploraError::Io { error_message } => write!(f, "IO error: {}", error_message), |  | ||||||
|             EsploraError::NoHeader => write!(f, "No header found in the response"), |  | ||||||
|             EsploraError::Parsing { error_message } => { |  | ||||||
|                 write!(f, "Parsing error: {}", error_message) |  | ||||||
|             } |  | ||||||
|             EsploraError::BitcoinEncoding { error_message } => { |  | ||||||
|                 write!(f, "Bitcoin encoding error: {}", error_message) |  | ||||||
|             } |  | ||||||
|             EsploraError::Hex { error_message } => { |  | ||||||
|                 write!(f, "Hex decoding error: {}", error_message) |  | ||||||
|             } |  | ||||||
|             EsploraError::TransactionNotFound => write!(f, "Transaction not found"), |  | ||||||
|             EsploraError::HeaderHeightNotFound { height } => { |  | ||||||
|                 write!(f, "Header height {} not found", height) |  | ||||||
|             } |  | ||||||
|             EsploraError::HeaderHashNotFound => write!(f, "Header hash not found"), |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl From<BdkEsploraError> for EsploraError { | impl From<BdkEsploraError> for EsploraError { | ||||||
|     fn from(error: BdkEsploraError) -> Self { |     fn from(error: BdkEsploraError) -> Self { | ||||||
|         match error { |         match error { | ||||||
| @ -264,8 +214,6 @@ impl From<BdkEsploraError> for EsploraError { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl std::error::Error for EsploraError {} |  | ||||||
| 
 |  | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod test { | mod test { | ||||||
|     use crate::error::EsploraError; |     use crate::error::EsploraError; | ||||||
| @ -290,7 +238,7 @@ mod test { | |||||||
|         let error = CalculateFeeError::MissingTxOut { out_points }; |         let error = CalculateFeeError::MissingTxOut { out_points }; | ||||||
| 
 | 
 | ||||||
|         let expected_message: String = format!( |         let expected_message: String = format!( | ||||||
|             "Missing transaction output: [{:?}, {:?}]", |             "missing transaction output: [{:?}, {:?}]", | ||||||
|             OutPoint { |             OutPoint { | ||||||
|                 txid: "0000000000000000000000000000000000000000000000000000000000000001" |                 txid: "0000000000000000000000000000000000000000000000000000000000000001" | ||||||
|                     .to_string(), |                     .to_string(), | ||||||
| @ -310,7 +258,7 @@ mod test { | |||||||
|     fn test_error_negative_fee() { |     fn test_error_negative_fee() { | ||||||
|         let error = CalculateFeeError::NegativeFee { fee: -100 }; |         let error = CalculateFeeError::NegativeFee { fee: -100 }; | ||||||
| 
 | 
 | ||||||
|         assert_eq!(error.to_string(), "Negative fee value: -100"); |         assert_eq!(error.to_string(), "negative fee value: -100"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[test] |     #[test] | ||||||
| @ -320,49 +268,49 @@ mod test { | |||||||
|                 EsploraError::Ureq { |                 EsploraError::Ureq { | ||||||
|                     error_message: "Network error".to_string(), |                     error_message: "Network error".to_string(), | ||||||
|                 }, |                 }, | ||||||
|                 "Ureq error: Network error", |                 "ureq error: Network error", | ||||||
|             ), |             ), | ||||||
|             ( |             ( | ||||||
|                 EsploraError::UreqTransport { |                 EsploraError::UreqTransport { | ||||||
|                     error_message: "Timeout occurred".to_string(), |                     error_message: "Timeout occurred".to_string(), | ||||||
|                 }, |                 }, | ||||||
|                 "Ureq transport error: Timeout occurred", |                 "ureq transport error: Timeout occurred", | ||||||
|             ), |             ), | ||||||
|             ( |             ( | ||||||
|                 EsploraError::Http { status_code: 404 }, |                 EsploraError::Http { status_code: 404 }, | ||||||
|                 "HTTP error with status code: 404", |                 "http error with status code: 404", | ||||||
|             ), |             ), | ||||||
|             ( |             ( | ||||||
|                 EsploraError::Io { |                 EsploraError::Io { | ||||||
|                     error_message: "File not found".to_string(), |                     error_message: "File not found".to_string(), | ||||||
|                 }, |                 }, | ||||||
|                 "IO error: File not found", |                 "io error: File not found", | ||||||
|             ), |             ), | ||||||
|             (EsploraError::NoHeader, "No header found in the response"), |             (EsploraError::NoHeader, "no header found in the response"), | ||||||
|             ( |             ( | ||||||
|                 EsploraError::Parsing { |                 EsploraError::Parsing { | ||||||
|                     error_message: "Invalid JSON".to_string(), |                     error_message: "Invalid JSON".to_string(), | ||||||
|                 }, |                 }, | ||||||
|                 "Parsing error: Invalid JSON", |                 "parsing error: Invalid JSON", | ||||||
|             ), |             ), | ||||||
|             ( |             ( | ||||||
|                 EsploraError::BitcoinEncoding { |                 EsploraError::BitcoinEncoding { | ||||||
|                     error_message: "Bad format".to_string(), |                     error_message: "Bad format".to_string(), | ||||||
|                 }, |                 }, | ||||||
|                 "Bitcoin encoding error: Bad format", |                 "bitcoin encoding error: Bad format", | ||||||
|             ), |             ), | ||||||
|             ( |             ( | ||||||
|                 EsploraError::Hex { |                 EsploraError::Hex { | ||||||
|                     error_message: "Invalid hex".to_string(), |                     error_message: "Invalid hex".to_string(), | ||||||
|                 }, |                 }, | ||||||
|                 "Hex decoding error: Invalid hex", |                 "hex decoding error: Invalid hex", | ||||||
|             ), |             ), | ||||||
|             (EsploraError::TransactionNotFound, "Transaction not found"), |             (EsploraError::TransactionNotFound, "transaction not found"), | ||||||
|             ( |             ( | ||||||
|                 EsploraError::HeaderHeightNotFound { height: 123456 }, |                 EsploraError::HeaderHeightNotFound { height: 123456 }, | ||||||
|                 "Header height 123456 not found", |                 "header height 123456 not found", | ||||||
|             ), |             ), | ||||||
|             (EsploraError::HeaderHashNotFound, "Header hash not found"), |             (EsploraError::HeaderHashNotFound, "header hash not found"), | ||||||
|         ]; |         ]; | ||||||
| 
 | 
 | ||||||
|         for (error, expected_message) in cases { |         for (error, expected_message) in cases { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user