use std::fmt::Debug;
use packable::error::UnexpectedEOF;
use serde::{ser::Serializer, Serialize};
use crate::{
client::api::transaction_builder::TransactionBuilderError,
types::block::{
address::AddressError,
context_input::ContextInputError,
input::InputError,
mana::ManaError,
output::{
feature::FeatureError, unlock_condition::UnlockConditionError, NativeTokenError, OutputError,
TokenSchemeError,
},
payload::PayloadError,
semantic::TransactionFailureReason,
signature::SignatureError,
unlock::UnlockError,
BlockError,
},
utils::ConversionError,
};
#[derive(Debug, thiserror::Error, strum::AsRefStr)]
#[strum(serialize_all = "camelCase")]
#[non_exhaustive]
pub enum ClientError {
#[error("invalid bech32 hrp for the connected network: {provided}, expected: {expected}")]
Bech32HrpMismatch {
provided: String,
expected: String,
},
#[error("{0}")]
Blake2b256(&'static str),
#[error("{0}")]
Block(#[from] BlockError),
#[error("{0}")]
Address(#[from] AddressError),
#[error("{0}")]
Crypto(#[from] crypto::Error),
#[error("address: {address} not found in range: {range}")]
InputAddressNotFound {
address: String,
range: String,
},
#[error("invalid amount in API response: {0}")]
InvalidAmount(String),
#[error("invalid mnemonic {0}")]
InvalidMnemonic(String),
#[error("{0}")]
Json(#[from] serde_json::Error),
#[error("must provide required parameter: {0}")]
MissingParameter(&'static str),
#[error("node error: {0}")]
Node(#[from] crate::client::node_api::error::Error),
#[error("No output found for {0}")]
NoOutput(String),
#[error("placeholderSecretManager can't be used for address generation or signing")]
PlaceholderSecretManager,
#[error("rw lock failed")]
PoisonError,
#[error("{0}")]
PrefixHex(#[from] prefix_hex::Error),
#[error("not enough nodes for quorum: {available_nodes} < {minimum_threshold}")]
QuorumPoolSizeError {
available_nodes: usize,
minimum_threshold: usize,
},
#[error("failed to reach quorum: {quorum_size} < {minimum_threshold}")]
QuorumThresholdError {
quorum_size: usize,
minimum_threshold: usize,
},
#[error("cannot unwrap a SecretManager: type mismatch!")]
SecretManagerMismatch,
#[error("no healthy node available")]
HealthyNodePoolEmpty,
#[error("error when building tagged_data block: {0}")]
TaggedData(String),
#[error("transaction ID `{0}` couldn't be accepted")]
TransactionAcceptance(String),
#[cfg(not(target_family = "wasm"))]
#[error("{0}")]
TaskJoin(#[from] tokio::task::JoinError),
#[error("local time {current_time} doesn't match the tangle time: {tangle_time}")]
TimeNotSynced {
current_time: u64,
tangle_time: u64,
},
#[error("the semantic validation of a transaction failed with conflict reason: {} - {0:?}", *.0 as u8)]
TransactionSemantic(#[from] TransactionFailureReason),
#[error("{0}")]
Unpack(#[from] packable::error::UnpackError<BlockError, UnexpectedEOF>),
#[error("can't set {0} to URL")]
UrlAuth(&'static str),
#[error("{0}")]
Url(#[from] url::ParseError),
#[error("{0}")]
UrlValidation(String),
#[error("{0}")]
TransactionBuilder(#[from] TransactionBuilderError),
#[error("missing BIP32 chain to sign with")]
MissingBip32Chain,
#[error("unexpected block body kind: expected {expected}, found {actual}")]
UnexpectedBlockBodyKind { expected: u8, actual: u8 },
#[error("missing transaction payload")]
MissingTransactionPayload,
#[error("output not unlockable due to deadzone in expiration unlock condition")]
ExpirationDeadzone,
#[cfg(feature = "participation")]
#[cfg_attr(docsrs, doc(cfg(feature = "participation")))]
#[error("{0}")]
Participation(#[from] crate::types::api::plugins::participation::error::Error),
#[cfg(feature = "ledger_nano")]
#[cfg_attr(docsrs, doc(cfg(feature = "ledger_nano")))]
#[error("{0}")]
Ledger(Box<crate::client::secret::ledger_nano::Error>),
#[cfg(feature = "mqtt")]
#[cfg_attr(docsrs, doc(cfg(feature = "mqtt")))]
#[error("{0}")]
Mqtt(#[from] crate::client::node_api::mqtt::Error),
#[cfg(feature = "stronghold")]
#[cfg_attr(docsrs, doc(cfg(feature = "stronghold")))]
#[error("{0}")]
Stronghold(#[from] crate::client::stronghold::Error),
#[error("{0}")]
Convert(#[from] ConversionError),
}
impl Serialize for ClientError {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
#[derive(Serialize)]
struct ErrorDto {
#[serde(rename = "type")]
kind: String,
error: String,
}
ErrorDto {
kind: self.as_ref().to_owned(),
error: self.to_string(),
}
.serialize(serializer)
}
}
crate::impl_from_error_via!(ClientError via BlockError:
PayloadError,
OutputError,
InputError,
NativeTokenError,
ManaError,
UnlockConditionError,
FeatureError,
TokenSchemeError,
ContextInputError,
UnlockError,
SignatureError,
);
#[cfg(feature = "ledger_nano")]
impl From<crate::client::secret::ledger_nano::Error> for ClientError {
fn from(value: crate::client::secret::ledger_nano::Error) -> Self {
Self::Ledger(value.into())
}
}