use std::{mem::discriminant, sync::Arc};
use alloy::transports::{RpcError, TransportErrorKind};
use thiserror::Error;
use crate::types::ScannerResult;
use robust_provider::Error as RobustProviderError;
#[derive(Error, Debug, Clone)]
pub enum ScannerError {
#[error("RPC error: {0}")]
RpcError(Arc<RpcError<TransportErrorKind>>),
#[error("Block not found")]
BlockNotFound,
#[error("Operation timed out")]
Timeout,
#[error("{0} {1} exceeds the latest block {2}")]
BlockExceedsLatest(&'static str, u64, u64),
#[error("Event count must be greater than 0")]
InvalidEventCount,
#[error("Max block range must be greater than 0")]
InvalidMaxBlockRange,
#[error("Stream buffer capacity must be greater than 0")]
InvalidBufferCapacity,
#[error("Max concurrent fetches must be greater than 0")]
InvalidMaxConcurrentFetches,
#[error("Subscription closed")]
SubscriptionClosed,
#[error("Subscription lagged")]
Lagged(u64),
}
impl From<RobustProviderError> for ScannerError {
fn from(error: RobustProviderError) -> ScannerError {
match error {
RobustProviderError::Timeout => ScannerError::Timeout,
RobustProviderError::RpcError(err) => ScannerError::RpcError(Arc::new(err)),
RobustProviderError::BlockNotFound => ScannerError::BlockNotFound,
RobustProviderError::Lagged(blocks) => ScannerError::Lagged(blocks),
RobustProviderError::Closed => ScannerError::SubscriptionClosed,
}
}
}
impl From<RpcError<TransportErrorKind>> for ScannerError {
fn from(error: RpcError<TransportErrorKind>) -> Self {
ScannerError::RpcError(Arc::new(error))
}
}
impl<T: Clone> PartialEq<ScannerError> for ScannerResult<T> {
fn eq(&self, other: &ScannerError) -> bool {
match self {
Ok(_) => false,
Err(err) => discriminant(err) == discriminant(other),
}
}
}