parazyd 4 роки тому
батько
коміт
2e33d98948
11 змінених файлів з 194 додано та 457 видалено
  1. 1 0
      Cargo.lock
  2. 1 0
      Cargo.toml
  3. 13 38
      src/client.rs
  4. 104 218
      src/error.rs
  5. 7 2
      src/rpc/jsonrpc.rs
  6. 9 4
      src/rpc/websockets.rs
  7. 9 32
      src/service/btc.rs
  8. 12 41
      src/service/eth.rs
  9. 2 2
      src/service/gateway.rs
  10. 26 87
      src/service/sol.rs
  11. 10 33
      src/state.rs

+ 1 - 0
Cargo.lock

@@ -1325,6 +1325,7 @@ dependencies = [
  "spl-associated-token-account",
  "spl-token",
  "subtle",
+ "thiserror",
  "toml",
  "tungstenite 0.15.0",
  "url",

+ 1 - 0
Cargo.toml

@@ -94,6 +94,7 @@ secp256k1 = {version = "0.20.3", default-features = false, features = ["rand-std
 # Cashier Ethereum dependencies
 hash-db = {version = "0.15.2", optional = true}
 keccak-hasher = {version = "0.15.3", optional = true}
+thiserror = "1.0.30"
 
 # Cashier Solana dependencies
 solana-client = {version = "1.8.2", optional = true}

+ 13 - 38
src/client.rs

@@ -27,19 +27,31 @@ use crate::{
 };
 */
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, thiserror::Error)]
 pub enum ClientFailed {
+    #[error("here is no enough value {0}")]
     NotEnoughValue(u64),
+    #[error("Invalid Address  {0}")]
     InvalidAddress(String),
+    #[error("Invalid Amount {0}")]
     InvalidAmount(u64),
+    #[error("Unable to get deposit address")]
     UnableToGetDepositAddress,
+    #[error("Unable to get withdraw address")]
     UnableToGetWithdrawAddress,
+    #[error("Does not have cashier public key")]
     DoesNotHaveCashierPublicKey,
+    #[error("Does not have keypair")]
     DoesNotHaveKeypair,
+    #[error("Password is empty. Cannot create database")]
     EmptyPassword,
+    #[error("Wallet already initalized")]
     WalletInitialized,
+    #[error("Keypair already exists")]
     KeyExists,
+    #[error("{0}")]
     ClientError(String),
+    #[error("Verify error: {0}")]
     VerifyError(String),
 }
 
@@ -537,43 +549,6 @@ impl State {
 }
 */
 
-impl std::error::Error for ClientFailed {}
-
-impl std::fmt::Display for ClientFailed {
-    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        match self {
-            ClientFailed::NotEnoughValue(i) => {
-                write!(f, "There is no enough value {}", i)
-            }
-            ClientFailed::InvalidAddress(i) => {
-                write!(f, "Invalid Address {}", i)
-            }
-            ClientFailed::InvalidAmount(i) => {
-                write!(f, "Invalid Amount {}", i)
-            }
-            ClientFailed::UnableToGetDepositAddress => f.write_str("Unable to get deposit address"),
-            ClientFailed::UnableToGetWithdrawAddress => {
-                f.write_str("Unable to get withdraw address")
-            }
-            ClientFailed::DoesNotHaveCashierPublicKey => {
-                f.write_str("Does not have cashier public key")
-            }
-            ClientFailed::DoesNotHaveKeypair => f.write_str("Does not have keypair"),
-            ClientFailed::EmptyPassword => f.write_str("Password is empty. Cannot create database"),
-            ClientFailed::WalletInitialized => f.write_str("Wallet already initalized"),
-            ClientFailed::KeyExists => f.write_str("Keypair already exists"),
-
-            ClientFailed::ClientError(i) => {
-                write!(f, "{}", i)
-            }
-
-            ClientFailed::VerifyError(i) => {
-                write!(f, "Verify error: {}", i)
-            }
-        }
-    }
-}
-
 impl From<super::error::Error> for ClientFailed {
     fn from(err: super::error::Error) -> ClientFailed {
         ClientFailed::ClientError(err.to_string())

+ 104 - 218
src/error.rs

@@ -1,168 +1,152 @@
-use std::fmt;
-
 use crate::{client, state};
 
 pub type Result<T> = std::result::Result<T, Error>;
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, thiserror::Error)]
 pub enum Error {
+    #[error("io error: `{0:?}`")]
     Io(std::io::ErrorKind),
 
-    /// VarInt was encoded in a non-minimal way
+    #[error("Cannot find home directory")]
     PathNotFound,
+    /// VarInt was encoded in a non-minimal way
+    #[error("non-minimal varint")]
     NonMinimalVarInt,
 
     /// Parsing And Encode/Decode errors
+    #[error("parse failed: `{0}`")]
     ParseFailed(&'static str),
-    ParseIntError,
-    ParseBigIntError,
-    ParseFloatError,
-    FromHexError,
-    UrlParseError,
+    #[error(transparent)]
+    ParseIntError(#[from] std::num::ParseIntError),
+    #[error(transparent)]
+    ParseBigIntError(#[from] num_bigint::ParseBigIntError),
+    #[error(transparent)]
+    ParseFloatError(#[from] std::num::ParseFloatError),
+    #[error(transparent)]
+    FromHexError(#[from] hex::FromHexError),
+    #[error("Url parse erro `{0}`")]
+    UrlParseError(String),
+    #[error("No url found")]
+    NoUrlFound,
+    #[error("Malformed packet")]
     MalformedPacket,
-    AddrParseError,
-    Base58EncodeError(String),
-    Base58DecodeError(String),
-    Utf8Error,
-    StrUtf8Error(String),
+    #[error(transparent)]
+    AddrParseError(#[from] std::net::AddrParseError),
+    #[error(transparent)]
+    Base58EncodeError(#[from] bs58::encode::Error),
+    #[error(transparent)]
+    Base58DecodeError(#[from] bs58::decode::Error),
+    #[error(transparent)]
+    Utf8Error(#[from] std::string::FromUtf8Error),
+    #[error(transparent)]
+    StrUtf8Error(#[from] std::str::Utf8Error),
+    #[error("TryInto error")]
     TryIntoError,
+    #[error("TryFrom error")]
     TryFromError,
-    TryFromBigIntError,
+    #[error(transparent)]
+    TryFromBigIntError(#[from] num_bigint::TryFromBigIntError<num_bigint::BigUint>),
+    #[error("Json serialization error: `{0}`")]
     SerdeJsonError(String),
-    TomlDeserializeError(String),
-    TomlSerializeError(String),
+    #[error(transparent)]
+    TomlDeserializeError(#[from] toml::de::Error),
+    #[error(transparent)]
+    TomlSerializeError(#[from] toml::ser::Error),
 
     /// Contract
+    #[error("Bad variable ref type byte")]
     BadVariableRefType,
+    #[error("Bad operation type byte")]
     BadOperationType,
+    #[error("Bad constraint type byte")]
     BadConstraintType,
+    #[error("Invalid param name")]
     InvalidParamName,
+    #[error("Invalid param type")]
     InvalidParamType,
+    #[error("Missing params")]
     MissingParams,
-    VmError,
+    #[error("Contract is poorly defined")]
     BadContract,
-    Groth16Error,
-    PlonkError,
+    #[error("Operation failed")]
     OperationFailed,
+    #[error("PLONK error")]
+    PlonkError,
+    #[error("Unable to decrypt mint note")]
     NoteDecryptionFailed,
-    VerifyFailed,
+    #[error(transparent)]
+    VerifyFailed(#[from] state::VerifyFailed),
+    #[error("MerkleTree is full")]
     TreeFull,
 
     /// Service
+    #[error("Services Error: `{0}`")]
     ServicesError(&'static str),
+    #[error("Client failed: `{0}`")]
     ClientFailed(String),
     #[cfg(feature = "btc")]
-    BtcFailed(String),
+    #[error(transparent)]
+    BtcFailed(#[from] crate::service::BtcFailed),
     #[cfg(feature = "sol")]
+    #[error("Sol client failed: `{0}`")]
     SolFailed(String),
     #[cfg(feature = "eth")]
-    EthFailed(String),
+    #[error(transparent)]
+    EthFailed(#[from] crate::service::EthFailed),
+    #[error("BridgeError Error: `{0}`")]
     BridgeError(String),
+    #[error("ZmqError: `{0}`")]
     ZmqError(String),
 
     /// Database/Sql errors
+    #[error("Rocksdb error: `{0}`")]
     RocksdbError(String),
+    #[error("Rusqlite error: `{0}`")]
     RusqliteError(String),
+    #[error("SlabsStore Error: `{0}`")]
     SlabsStore(String),
 
     /// RPC errors
+    #[error("JsonRpc Error: `{0}`")]
     JsonRpcError(String),
+    #[error("Not supported network")]
     NotSupportedNetwork,
+    #[error("Not supported token")]
     NotSupportedToken,
+    #[error("Could not parse token parameter")]
     TokenParseError,
+    #[error("Cannot parse network parameter")]
     NetworkParseError,
-    AsyncNativeTlsError,
-    TungsteniteError,
+    #[error("Async_Native_TLS error: `{0}`")]
+    AsyncNativeTlsError(String),
+    #[error("TungsteniteError: `{0}`")]
+    TungsteniteError(String),
 
     /// Network
+    #[error("Connection failed")]
     ConnectFailed,
+    #[error("Connection timed out")]
     ConnectTimeout,
+    #[error("Channel stopped")]
     ChannelStopped,
+    #[error("Channel timed out")]
     ChannelTimeout,
+    #[error("Service stopped")]
     ServiceStopped,
 
     /// Util
+    #[error("No config file detected. Please create one.")]
     ConfigNotFound,
+    #[error("No keypair file detected.")]
     KeypairPathNotFound,
+    #[error("No cashier public keys detected.")]
     CashierKeysNotFound,
+    #[error("SetLoggerError")]
     SetLoggerError,
+    #[error("Async_channel sender error")]
     AsyncChannelSenderError,
-    AsyncChannelReceiverError,
-}
-
-impl std::error::Error for Error {}
-
-impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
-        match *self {
-            Error::PathNotFound => f.write_str("Cannot find home directory"),
-            Error::Io(ref err) => write!(f, "io error:{:?}", err),
-            Error::NonMinimalVarInt => f.write_str("non-minimal varint"),
-            Error::ParseFailed(ref err) => write!(f, "parse failed: {}", err),
-            Error::ParseIntError => f.write_str("Parse int error"),
-            Error::ParseBigIntError => f.write_str("Parse big int error"),
-            Error::ParseFloatError => f.write_str("Parse float error"),
-            Error::UrlParseError => f.write_str("Failed to parse URL"),
-            Error::FromHexError => f.write_str("Failed to convert from hex"),
-            Error::AsyncChannelSenderError => f.write_str("Async_channel sender error"),
-            Error::AsyncChannelReceiverError => f.write_str("Async_channel receiver error"),
-            Error::AsyncNativeTlsError => f.write_str("Async_Native_TLS error"),
-            Error::MalformedPacket => f.write_str("Malformed packet"),
-            Error::AddrParseError => f.write_str("Unable to parse address"),
-            Error::BadVariableRefType => f.write_str("Bad variable ref type byte"),
-            Error::BadOperationType => f.write_str("Bad operation type byte"),
-            Error::BadConstraintType => f.write_str("Bad constraint type byte"),
-            Error::InvalidParamName => f.write_str("Invalid param name"),
-            Error::InvalidParamType => f.write_str("Invalid param type"),
-            Error::MissingParams => f.write_str("Missing params"),
-            Error::VmError => f.write_str("VM error"),
-            Error::BadContract => f.write_str("Contract is poorly defined"),
-            Error::Groth16Error => f.write_str("Groth16 error"),
-            Error::PlonkError => f.write_str("Plonk error"),
-            Error::RusqliteError(ref err) => write!(f, "Rusqlite error {}", err),
-            Error::OperationFailed => f.write_str("Operation failed"),
-            Error::ConnectFailed => f.write_str("Connection failed"),
-            Error::ConnectTimeout => f.write_str("Connection timed out"),
-            Error::ChannelStopped => f.write_str("Channel stopped"),
-            Error::ChannelTimeout => f.write_str("Channel timed out"),
-            Error::ServiceStopped => f.write_str("Service stopped"),
-            Error::Utf8Error => f.write_str("Malformed UTF8"),
-            Error::StrUtf8Error(ref err) => write!(f, "Malformed UTF8: {}", err),
-            Error::NoteDecryptionFailed => f.write_str("Unable to decrypt mint note"),
-            Error::ServicesError(ref err) => write!(f, "Services error: {}", err),
-            Error::ZmqError(ref err) => write!(f, "ZmqError: {}", err),
-            Error::VerifyFailed => f.write_str("Verify failed"),
-            Error::ClientFailed(ref err) => write!(f, "Client failed: {}", err),
-            #[cfg(feature = "btc")]
-            Error::BtcFailed(ref err) => write!(f, "Btc client failed: {}", err),
-            #[cfg(feature = "sol")]
-            Error::SolFailed(ref err) => write!(f, "Sol client failed: {}", err),
-            #[cfg(feature = "eth")]
-            Error::EthFailed(ref err) => write!(f, "Eth client failed: {}", err),
-            Error::TryIntoError => f.write_str("TryInto error"),
-            Error::TryFromError => f.write_str("TryFrom error"),
-            Error::TryFromBigIntError => f.write_str("TryFromBigInt error"),
-            Error::RocksdbError(ref err) => write!(f, "Rocksdb Error: {}", err),
-            Error::SlabsStore(ref err) => write!(f, "SlabsStore Error: {}", err),
-            Error::JsonRpcError(ref err) => write!(f, "JsonRpc Error: {}", err),
-            Error::TreeFull => f.write_str("MerkleTree is full"),
-            Error::NotSupportedNetwork => f.write_str("Not supported network"),
-            Error::NotSupportedToken => f.write_str("Not supported token"),
-            Error::BridgeError(ref err) => write!(f, "Bridge error: {}", err),
-            Error::SerdeJsonError(ref err) => write!(f, "Json serialization error: {}", err),
-            Error::TomlDeserializeError(ref err) => write!(f, "Toml parsing error: {}", err),
-            Error::TomlSerializeError(ref err) => write!(f, "Toml parsing error: {}", err),
-            Error::Base58EncodeError(ref err) => write!(f, "bs58 encode error: {}", err),
-            Error::Base58DecodeError(ref err) => write!(f, "bs58 decode error: {}", err),
-            Error::ConfigNotFound => f.write_str("No config file detected. Please create one."),
-            Error::KeypairPathNotFound => f.write_str("No keypair file detected."),
-            Error::CashierKeysNotFound => f.write_str("No cashier public keys detected."),
-            Error::SetLoggerError => f.write_str("SetLoggerError"),
-            Error::TokenParseError => f.write_str("Could not parse token parameter"),
-            Error::TungsteniteError => f.write_str("TungsteniteError"),
-            Error::NetworkParseError => f.write_str("Cannot parse network parameter"),
-        }
-    }
+    #[error(transparent)]
+    AsyncChannelReceiverError(#[from] async_channel::RecvError),
 }
 
 impl From<zeromq::ZmqError> for Error {
@@ -177,6 +161,12 @@ impl From<rocksdb::Error> for Error {
     }
 }
 
+impl From<rusqlite::Error> for Error {
+    fn from(err: rusqlite::Error) -> Error {
+        Error::RusqliteError(err.to_string())
+    }
+}
+
 impl From<serde_json::Error> for Error {
     fn from(err: serde_json::Error) -> Error {
         Error::SerdeJsonError(err.to_string())
@@ -189,87 +179,21 @@ impl From<std::io::Error> for Error {
     }
 }
 
-impl From<rusqlite::Error> for Error {
-    fn from(err: rusqlite::Error) -> Error {
-        Error::RusqliteError(err.to_string())
-    }
-}
-
 impl<T> From<async_channel::SendError<T>> for Error {
     fn from(_err: async_channel::SendError<T>) -> Error {
         Error::AsyncChannelSenderError
     }
 }
 
-impl From<async_channel::RecvError> for Error {
-    fn from(_err: async_channel::RecvError) -> Error {
-        Error::AsyncChannelReceiverError
-    }
-}
-
 impl From<async_native_tls::Error> for Error {
-    fn from(_err: async_native_tls::Error) -> Error {
-        Error::AsyncNativeTlsError
-    }
-}
-
-impl From<std::net::AddrParseError> for Error {
-    fn from(_err: std::net::AddrParseError) -> Error {
-        Error::AddrParseError
+    fn from(err: async_native_tls::Error) -> Error {
+        Error::AsyncNativeTlsError(err.to_string())
     }
 }
 
 impl From<url::ParseError> for Error {
-    fn from(_err: url::ParseError) -> Error {
-        Error::UrlParseError
-    }
-}
-
-impl From<hex::FromHexError> for Error {
-    fn from(_err: hex::FromHexError) -> Error {
-        Error::FromHexError
-    }
-}
-
-impl From<std::num::ParseIntError> for Error {
-    fn from(_err: std::num::ParseIntError) -> Error {
-        Error::ParseIntError
-    }
-}
-
-impl From<num_bigint::ParseBigIntError> for Error {
-    fn from(_err: num_bigint::ParseBigIntError) -> Error {
-        Error::ParseBigIntError
-    }
-}
-
-impl From<num_bigint::TryFromBigIntError<num_bigint::BigUint>> for Error {
-    fn from(_err: num_bigint::TryFromBigIntError<num_bigint::BigUint>) -> Error {
-        Error::TryFromBigIntError
-    }
-}
-
-impl From<std::num::ParseFloatError> for Error {
-    fn from(_err: std::num::ParseFloatError) -> Error {
-        Error::ParseFloatError
-    }
-}
-
-impl From<std::string::FromUtf8Error> for Error {
-    fn from(_err: std::string::FromUtf8Error) -> Error {
-        Error::Utf8Error
-    }
-}
-
-impl From<std::str::Utf8Error> for Error {
-    fn from(err: std::str::Utf8Error) -> Error {
-        Error::StrUtf8Error(err.to_string())
-    }
-}
-
-impl From<state::VerifyFailed> for Error {
-    fn from(_err: state::VerifyFailed) -> Error {
-        Error::VerifyFailed
+    fn from(err: url::ParseError) -> Error {
+        Error::UrlParseError(err.to_string())
     }
 }
 
@@ -279,51 +203,6 @@ impl From<client::ClientFailed> for Error {
     }
 }
 
-#[cfg(feature = "btc")]
-impl From<crate::service::BtcFailed> for Error {
-    fn from(err: crate::service::BtcFailed) -> Error {
-        Error::BtcFailed(err.to_string())
-    }
-}
-
-#[cfg(feature = "sol")]
-impl From<crate::service::SolFailed> for Error {
-    fn from(err: crate::service::SolFailed) -> Error {
-        Error::SolFailed(err.to_string())
-    }
-}
-
-#[cfg(feature = "eth")]
-impl From<crate::service::EthFailed> for Error {
-    fn from(err: crate::service::EthFailed) -> Error {
-        Error::EthFailed(err.to_string())
-    }
-}
-
-impl From<toml::de::Error> for Error {
-    fn from(err: toml::de::Error) -> Error {
-        Error::TomlDeserializeError(err.to_string())
-    }
-}
-
-impl From<toml::ser::Error> for Error {
-    fn from(err: toml::ser::Error) -> Error {
-        Error::TomlSerializeError(err.to_string())
-    }
-}
-
-impl From<bs58::encode::Error> for Error {
-    fn from(err: bs58::encode::Error) -> Error {
-        Error::Base58EncodeError(err.to_string())
-    }
-}
-
-impl From<bs58::decode::Error> for Error {
-    fn from(err: bs58::decode::Error) -> Error {
-        Error::Base58DecodeError(err.to_string())
-    }
-}
-
 impl From<log::SetLoggerError> for Error {
     fn from(_err: log::SetLoggerError) -> Error {
         Error::SetLoggerError
@@ -331,8 +210,15 @@ impl From<log::SetLoggerError> for Error {
 }
 
 impl From<tungstenite::Error> for Error {
-    fn from(_err: tungstenite::Error) -> Error {
-        Error::TungsteniteError
+    fn from(err: tungstenite::Error) -> Error {
+        Error::TungsteniteError(err.to_string())
+    }
+}
+
+#[cfg(feature = "sol")]
+impl From<crate::service::SolFailed> for Error {
+    fn from(err: crate::service::SolFailed) -> Error {
+        Error::SolFailed(err.to_string())
     }
 }
 

+ 7 - 2
src/rpc/jsonrpc.rs

@@ -135,7 +135,12 @@ pub async fn send_raw_request(url: &str, data: Value) -> Result<JsonResult, Erro
     match parsed_url.scheme() {
         "tcp" => use_tls = false,
         "tls" => use_tls = true,
-        _ => return Err(Error::UrlParseError),
+        scheme => {
+            return Err(Error::UrlParseError(format!(
+                "Invalid scheme `{}` found in `{}`",
+                scheme, parsed_url
+            )))
+        }
     }
 
     // TODO: Error handling
@@ -147,7 +152,7 @@ pub async fn send_raw_request(url: &str, data: Value) -> Result<JsonResult, Erro
         smol::unblock(move || (host.as_str(), port).to_socket_addrs())
             .await?
             .next()
-            .ok_or(Error::UrlParseError)?
+            .ok_or(Error::NoUrlFound)?
     };
 
     let mut buf = [0; 2048];

+ 9 - 4
src/rpc/websockets.rs

@@ -64,15 +64,18 @@ impl Stream for WsStream {
 /// Connects to a WebSocket address (optionally secured by TLS).
 pub async fn connect(addr: &str, tls: TlsConnector) -> DrkResult<(WsStream, Response)> {
     let url = Url::parse(addr)?;
-    let host = url.host_str().ok_or(Error::UrlParseError)?.to_string();
-    let port = url.port_or_known_default().ok_or_else(|| Error::UrlParseError)?;
+    let host =
+        url.host_str().ok_or(Error::UrlParseError(format!("Missing Host in {}", url)))?.to_string();
+    let port = url
+        .port_or_known_default()
+        .ok_or_else(|| Error::UrlParseError(format!("Missing port in {}", url)))?;
 
     let socket_addr = {
         let host = host.clone();
         smol::unblock(move || (host.as_str(), port).to_socket_addrs())
             .await?
             .next()
-            .ok_or(Error::UrlParseError)?
+            .ok_or(Error::NoUrlFound)?
     };
 
     match url.scheme() {
@@ -87,6 +90,8 @@ pub async fn connect(addr: &str, tls: TlsConnector) -> DrkResult<(WsStream, Resp
             let (stream, resp) = async_tungstenite::client_async(addr, stream).await?;
             Ok((WsStream::Tls(stream), resp))
         }
-        scheme => Err(Error::UrlParseError),
+        scheme => {
+            Err(Error::UrlParseError(format!("Invalid url scheme `{}`, in `{}`", scheme, url)))
+        }
     }
 }

+ 9 - 32
src/service/btc.rs

@@ -376,9 +376,7 @@ impl BtcClient {
 
             match new_status {
                 ScriptStatus::Unseen => continue,
-                ScriptStatus::InMempool => {
-                    break
-                }
+                ScriptStatus::InMempool => break,
                 ScriptStatus::Confirmed(inner) => {
                     //Only break when confirmations happen
                     let confirmations = inner.confirmations();
@@ -807,45 +805,24 @@ impl Decodable for Keypair {
     }
 }
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, thiserror::Error)]
 pub enum BtcFailed {
+    #[error("There is no enough value {0}")]
     NotEnoughValue(u64),
+    #[error("could not parse BTC address: {0}")]
     BadBtcAddress(String),
+    #[error("Unable to create Electrum Client: {0}")]
     ElectrumError(String),
+    #[error("BtcFailed: {0}")]
     BtcError(String),
+    #[error("Decode and decode keys error: {0}")]
     DecodeAndEncodeError(String),
+    #[error("Keypair error from Secp256k1:  {0}")]
     KeypairError(String),
+    #[error("Received Notification Error: {0}")]
     Notification(String),
 }
 
-impl std::error::Error for BtcFailed {}
-
-impl std::fmt::Display for BtcFailed {
-    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        match self {
-            BtcFailed::NotEnoughValue(i) => {
-                write!(f, "There is no enough value {}", i)
-            }
-            BtcFailed::BadBtcAddress(ref err) => {
-                write!(f, "Unable to create Electrum Client: {}", err)
-            }
-            BtcFailed::ElectrumError(ref err) => write!(f, "could not parse BTC address: {}", err),
-            BtcFailed::DecodeAndEncodeError(ref err) => {
-                write!(f, "Decode and decode keys error: {}", err)
-            }
-            BtcFailed::KeypairError(ref err) => {
-                write!(f, "Keypair error from Secp256k1: {}", err)
-            }
-            BtcFailed::Notification(i) => {
-                write!(f, "Received Notification Error: {}", i)
-            }
-            BtcFailed::BtcError(i) => {
-                write!(f, "BtcFailed: {}", i)
-            }
-        }
-    }
-}
-
 impl From<crate::error::Error> for BtcFailed {
     fn from(err: crate::error::Error) -> BtcFailed {
         BtcFailed::BtcError(err.to_string())

+ 12 - 41
src/service/eth.rs

@@ -14,7 +14,7 @@ use serde_json::{json, Value};
 use super::bridge::{NetworkClient, TokenNotification, TokenSubscribtion};
 use crate::{
     rpc::{jsonrpc, jsonrpc::JsonResult},
-    serial::{deserialize, serialize},
+    serial::{deserialize, serialize, Decodable, Encodable},
     types::*,
     util::{generate_id, parse::truncate, NetworkName},
     Error, Result,
@@ -439,59 +439,30 @@ impl NetworkClient for EthClient {
     }
 }
 
-#[derive(Debug)]
+#[derive(Debug, Clone, thiserror::Error)]
 pub enum EthFailed {
+    #[error("There is no enough value {0}")]
     NotEnoughValue(u64),
+    #[error("Main Account Has no enough value")]
     MainAccountNotEnoughValue,
+    #[error("Bad Eth Address: {0}")]
     BadEthAddress(String),
+    #[error("Decode and decode keys error: {0}")]
     DecodeAndEncodeError(String),
+    #[error("Rpc Error: {0}")]
     RpcError(String),
+    #[error("Eth client error: {0}")]
     EthClientError(String),
+    #[error("Given mint is not valid: {0}")]
     MintIsNotValid(String),
+    #[error("JsonError: {0}")]
     JsonError(String),
+    #[error("Parse Error: {0}")]
     ParseError(String),
+    #[error("Unable to derive address from private key")]
     ImportPrivateError,
 }
 
-impl std::error::Error for EthFailed {}
-
-impl std::fmt::Display for EthFailed {
-    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        match self {
-            EthFailed::NotEnoughValue(i) => {
-                write!(f, "There is no enough value {}", i)
-            }
-            EthFailed::MainAccountNotEnoughValue => {
-                write!(f, "Main Account Has no enough value")
-            }
-            EthFailed::BadEthAddress(ref err) => {
-                write!(f, "Bad Eth Address: {}", err)
-            }
-            EthFailed::DecodeAndEncodeError(ref err) => {
-                write!(f, "Decode and decode keys error: {}", err)
-            }
-            EthFailed::RpcError(i) => {
-                write!(f, "Rpc Error: {}", i)
-            }
-            EthFailed::ParseError(i) => {
-                write!(f, "Parse Error: {}", i)
-            }
-            EthFailed::MintIsNotValid(i) => {
-                write!(f, "Given mint is not valid: {}", i)
-            }
-            EthFailed::JsonError(i) => {
-                write!(f, "JsonError: {}", i)
-            }
-            EthFailed::ImportPrivateError => {
-                write!(f, "Unable to derive address from private key")
-            }
-            EthFailed::EthClientError(i) => {
-                write!(f, "Eth client error: {}", i)
-            }
-        }
-    }
-}
-
 impl From<crate::error::Error> for EthFailed {
     fn from(err: crate::error::Error) -> EthFailed {
         EthFailed::EthClientError(err.to_string())

+ 2 - 2
src/service/gateway.rs

@@ -185,7 +185,7 @@ impl GatewayClient {
         let addr_sock = (addr.host().unwrap().to_string(), addr.port().unwrap())
             .to_socket_addrs()?
             .next()
-            .ok_or(Error::UrlParseError)?;
+            .ok_or(Error::NoUrlFound)?;
         let protocol = ReqProtocol::new(addr_sock, String::from("GATEWAY CLIENT"));
 
         let slabstore = SlabStore::new(rocks)?;
@@ -195,7 +195,7 @@ impl GatewayClient {
         let sub_addr_sock = (sub_addr.host().unwrap().to_string(), sub_addr.port().unwrap())
             .to_socket_addrs()?
             .next()
-            .ok_or(Error::UrlParseError)?;
+            .ok_or(Error::NoUrlFound)?;
 
         Ok(GatewayClient {
             protocol,

+ 26 - 87
src/service/sol.rs

@@ -161,7 +161,10 @@ impl SolClient {
         let mut sub_iter = 0;
 
         loop {
-            let message = read.next().await.ok_or_else(|| Error::TungsteniteError)?;
+            let message = read
+                .next()
+                .await
+                .ok_or_else(|| Error::TungsteniteError("No more messages".to_string()))?;
             let message = message?;
 
             if let Message::Pong(_) = message.clone() {
@@ -576,100 +579,36 @@ impl Decodable for Pubkey {
     }
 }
 
-#[derive(Debug)]
+#[derive(Debug, thiserror::Error)]
 pub enum SolFailed {
+    #[error("There is no enough value `{0}`")]
     NotEnoughValue(u64),
+    #[error("Main Account Has no enough value")]
     MainAccountNotEnoughValue,
+    #[error("Bad Sol Address: `{0}`")]
     BadSolAddress(String),
+    #[error("Decode and decode keys error: `{0}`")]
     DecodeAndEncodeError(String),
-    WebSocketError(String),
+    #[error(transparent)]
+    WebSocketError(#[from] tungstenite::Error),
+    #[error("RpcError: `{0}`")]
     RpcError(String),
-    SolClientError(String),
+    #[error(transparent)]
+    SolClientError(#[from] solana_client::client_error::ClientError),
+    #[error("Received Notification Error: `{0}`")]
     Notification(String),
-    ProgramError(String),
+    #[error(transparent)]
+    ProgramError(#[from] solana_sdk::program_error::ProgramError),
+    #[error("Given mint is not valid: `{0}`")]
     MintIsNotValid(String),
-    JsonError(String),
-    ParseError(String),
-}
-
-impl std::error::Error for SolFailed {}
-
-impl std::fmt::Display for SolFailed {
-    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        match self {
-            SolFailed::NotEnoughValue(i) => {
-                write!(f, "There is no enough value {}", i)
-            }
-            SolFailed::MainAccountNotEnoughValue => {
-                write!(f, "Main Account Has no enough value")
-            }
-            SolFailed::BadSolAddress(ref err) => {
-                write!(f, "Bad Sol Address: {}", err)
-            }
-            SolFailed::DecodeAndEncodeError(ref err) => {
-                write!(f, "Decode and decode keys error: {}", err)
-            }
-            SolFailed::WebSocketError(i) => {
-                write!(f, "WebSocket Error: {}", i)
-            }
-            SolFailed::RpcError(i) => {
-                write!(f, "Rpc Error: {}", i)
-            }
-            SolFailed::ParseError(i) => {
-                write!(f, "Parse Error: {}", i)
-            }
-            SolFailed::SolClientError(i) => {
-                write!(f, "Solana Client Error: {}", i)
-            }
-            SolFailed::Notification(i) => {
-                write!(f, "Received Notification Error: {}", i)
-            }
-            SolFailed::ProgramError(i) => {
-                write!(f, "ProgramError Error: {}", i)
-            }
-            SolFailed::MintIsNotValid(i) => {
-                write!(f, "Given mint is not valid: {}", i)
-            }
-            SolFailed::JsonError(i) => {
-                write!(f, "JsonError: {}", i)
-            }
-        }
-    }
-}
-
-impl From<solana_sdk::pubkey::ParsePubkeyError> for SolFailed {
-    fn from(err: solana_sdk::pubkey::ParsePubkeyError) -> SolFailed {
-        SolFailed::ParseError(err.to_string())
-    }
-}
-
-impl From<tungstenite::Error> for SolFailed {
-    fn from(err: tungstenite::Error) -> SolFailed {
-        SolFailed::WebSocketError(err.to_string())
-    }
-}
-
-impl From<solana_client::client_error::ClientError> for SolFailed {
-    fn from(err: solana_client::client_error::ClientError) -> SolFailed {
-        SolFailed::SolClientError(err.to_string())
-    }
-}
-
-impl From<solana_sdk::program_error::ProgramError> for SolFailed {
-    fn from(err: solana_sdk::program_error::ProgramError) -> SolFailed {
-        SolFailed::ProgramError(err.to_string())
-    }
-}
-
-impl From<crate::error::Error> for SolFailed {
-    fn from(err: crate::error::Error) -> SolFailed {
-        SolFailed::SolClientError(err.to_string())
-    }
-}
-impl From<serde_json::Error> for SolFailed {
-    fn from(err: serde_json::Error) -> SolFailed {
-        SolFailed::JsonError(err.to_string())
-    }
+    #[error(transparent)]
+    JsonError(#[from] serde_json::Error),
+    #[error(transparent)]
+    ParseError(#[from] solana_sdk::pubkey::ParsePubkeyError),
+    #[error("Signature Error: `{0}`")]
+    Signature(String),
+    #[error(transparent)]
+    Darkfi(#[from] crate::error::Error),
 }
 
 pub type SolResult<T> = std::result::Result<T, SolFailed>;

+ 10 - 33
src/state.rs

@@ -1,5 +1,3 @@
-use std::fmt;
-
 use log::debug;
 
 use crate::{
@@ -28,49 +26,28 @@ pub struct StateUpdate {
 
 pub type VerifyResult<T> = std::result::Result<T, VerifyFailed>;
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, thiserror::Error)]
 pub enum VerifyFailed {
+    #[error("Invalid cashier public key for clear input {0}")]
     InvalidCashierKey(usize),
+    #[error("Invalid merkle root for input {0}")]
     InvalidMerkle(usize),
+    #[error("Duplicate nullifier for input {0}")]
     DuplicateNullifier(usize),
+    #[error("Spend proof for input {0}")]
     SpendProof(usize),
+    #[error("Mint proof for input {0}")]
     MintProof(usize),
+    #[error("Invalid signature for clear input {0}")]
     ClearInputSignature(usize),
+    #[error("Invalid signature for input {0}")]
     InputSignature(usize),
+    #[error("Money in does not match money out (value commits)")]
     MissingFunds,
+    #[error("Assets don't match some inputs or outputs (token commits)")]
     AssetMismatch,
 }
 
-impl std::error::Error for VerifyFailed {}
-
-impl fmt::Display for VerifyFailed {
-    fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
-        match *self {
-            VerifyFailed::InvalidCashierKey(i) => {
-                write!(f, "Invalid cashier public key for clear input {}", i)
-            }
-            VerifyFailed::InvalidMerkle(i) => {
-                write!(f, "Invalid merkle root for input {}", i)
-            }
-            VerifyFailed::DuplicateNullifier(i) => {
-                write!(f, "Duplicate nullifier for input {}", i)
-            }
-            VerifyFailed::SpendProof(i) => write!(f, "Spend proof for input {}", i),
-            VerifyFailed::MintProof(i) => write!(f, "Mint proof for input {}", i),
-            VerifyFailed::ClearInputSignature(i) => {
-                write!(f, "Invalid signature for clear input {}", i)
-            }
-            VerifyFailed::InputSignature(i) => write!(f, "Invalid signature for input {}", i),
-            VerifyFailed::MissingFunds => {
-                f.write_str("Money in does not match money out (value commits)")
-            }
-            VerifyFailed::AssetMismatch => {
-                f.write_str("Assets don't match some inputs or outputs (token commits)")
-            }
-        }
-    }
-}
-
 pub fn state_transition<S: ProgramState>(state: &S, tx: Transaction) -> VerifyResult<StateUpdate> {
     // Check deposits are legit