use std::string::FromUtf8Error;
use axum::{
http::StatusCode,
response::{IntoResponse, Response},
};
use entropy_kvdb::kv_manager::error::InnerKvError;
use entropy_protocol::errors::ProtocolExecutionErr;
use subxt::utils::AccountId32;
use thiserror::Error;
use tokio::sync::oneshot::error::RecvError;
use super::ProtocolMessage;
#[derive(Debug, Error)]
pub enum ProtocolErr {
#[error("Protocol Execution Error {0}")]
ProtocolExecution(#[from] ProtocolExecutionErr),
#[error("Kv error: {0}")]
Kv(#[from] entropy_kvdb::kv_manager::error::KvError),
#[error("Inner Kv error: {0}")]
InnerKv(#[from] InnerKvError),
#[error("Codec decoding error: {0}")]
CodecError(#[from] parity_scale_codec::Error),
#[error("Conversion Error: {0}")]
TryFrom(#[from] std::array::TryFromSliceError),
#[error("Decoding Error: {0}")]
Bincode(#[from] Box<bincode::ErrorKind>),
#[error("Deserialization Error: {0}")]
Deserialization(String),
#[error("Oneshot timeout error: {0}")]
OneshotTimeout(#[from] RecvError),
#[error("Subscribe API error: {source} by TSS Account `{account_id:?}`")]
Subscribe { source: SubscribeErr, account_id: AccountId32 },
#[error("reqwest error: {0}")]
Reqwest(#[from] reqwest::Error),
#[error("Utf8Error: {0:?}")]
Utf8(#[from] std::str::Utf8Error),
#[error("reqwest event error: {0}")]
ReqwestEvent(#[from] reqwest_eventsource::Error),
#[error("Broadcast error: {0}")]
Broadcast(#[from] Box<tokio::sync::broadcast::error::SendError<ProtocolMessage>>),
#[error("anyhow error: {0}")]
Anyhow(#[from] anyhow::Error),
#[error("Generic Substrate error: {0}")]
GenericSubstrate(#[from] subxt::error::Error),
#[error("Serde Json error: {0}")]
SerdeJson(#[from] serde_json::Error),
#[error("Session Error: {0}")]
SessionError(String),
#[error("String Conversion Error: {0}")]
StringConversion(#[from] FromUtf8Error),
#[error("User Error: {0}")]
UserError(String),
#[error("Validation Error: {0}")]
ValidationErr(#[from] crate::validation::errors::ValidationErr),
#[error("Subscribe message rejected: {message} by TSS Account `{account_id}`")]
BadSubscribeMessage { message: String, account_id: AccountId32 },
#[error("From Hex Error: {0}")]
FromHex(#[from] hex::FromHexError),
#[error("Conversion Error: {0}")]
Conversion(&'static str),
#[error("Could not open ws connection: {source} with the TSS Account `{account_id:?}`")]
ConnectionError { source: tokio_tungstenite::tungstenite::Error, account_id: AccountId32 },
#[error("Timed out while waiting for peer(s): {:?}", inactive_peers)]
Timeout { source: tokio::time::error::Elapsed, inactive_peers: Vec<AccountId32> },
#[error("Encrypted connection error {source:?} with the TSS Account `{account_id:?}`")]
EncryptedConnection {
source: entropy_protocol::protocol_transport::errors::EncryptedConnectionErr,
account_id: AccountId32,
},
#[error("Program error: {0}")]
ProgramError(#[from] crate::user::errors::ProgramError),
#[error("Invalid length for converting address")]
AddressConversionError(String),
#[error("Kv Fatal error")]
KvSerialize(String),
#[error("Validator Error: {0}")]
ValidatorErr(String),
#[error("Subgroup error: {0}")]
SubgroupError(&'static str),
#[error("Account unable to be deserialized: {0}")]
StringError(&'static str),
#[error("Option Unwrap error: {0}")]
OptionUnwrapError(String),
#[error("Proactive Refresh data incorrect")]
InvalidData,
#[error("Data is repeated")]
RepeatedData,
#[error("Chain Fetch: {0}")]
ChainFetch(&'static str),
#[error("The session ID is not for a signing session")]
BadSessionId,
#[error("Substrate: {0}")]
SubstrateClient(#[from] entropy_client::substrate::SubstrateError),
#[error("Listener: {0}")]
Listener(#[from] entropy_protocol::errors::ListenerErr),
#[error("Failed to derive BIP-32 account: {0}")]
Bip32DerivationError(#[from] bip32::Error),
#[error("Node has started fresh and not yet successfully set up")]
NotReady,
#[error("Application State Error: {0}")]
AppStateError(#[from] crate::helpers::app_state::AppStateError),
}
impl IntoResponse for ProtocolErr {
fn into_response(self) -> Response {
tracing::error!("{:?}", format!("{self}"));
let body = format!("{self}").into_bytes();
(StatusCode::INTERNAL_SERVER_ERROR, body).into_response()
}
}
#[derive(Debug, Error)]
pub enum SubscribeErr {
#[error("no listener: {0}")]
NoListener(&'static str),
#[error("invalid party ID: {0}")]
InvalidPartyId(String),
#[error("Lock Error: {0}")]
LockError(String),
#[error("Invalid Signature: {0}")]
InvalidSignature(&'static str),
#[error("Validation error: {0}")]
Decryption(String),
#[error("Serialization/Deserialization error: {0}")]
Serialization(#[from] bincode::Error),
#[error("User Error: {0}")]
UserError(String),
#[error("Listener: {0}")]
Listener(#[from] entropy_protocol::errors::ListenerErr),
#[error("Protocol version mismatch: {0}")]
VersionMismatch(
#[from] entropy_protocol::protocol_transport::errors::ProtocolVersionMismatchError,
),
#[error("Unable to find `Listener` with `SessionId`: {0:?}")]
NoSessionId(entropy_protocol::SessionId),
}
impl IntoResponse for SubscribeErr {
fn into_response(self) -> Response {
tracing::error!("{:?}", format!("{self}"));
let body = format!("{self}").into_bytes();
(StatusCode::INTERNAL_SERVER_ERROR, body).into_response()
}
}