hotpot-sdk 0.2.2

Rust SDK for interacting with the HotPot cross-chain DEX aggregator API.
Documentation
pub mod client;
pub mod types;

pub use client::Client;
pub use ApiClientError as Error;

use serde::Deserialize;

/// Entity types that can be referenced in error responses
#[derive(Debug, Clone, Deserialize)]
pub enum EntityKind {
    Approval,
    Intent,
    Network,
    Quote,
    Resolver,
    SupportedToken,
    Swap,
    Token,
    UserNonce,
    Transaction,
    TransactionReceipt,
    InternalEvent,
    BlockchainEvent,
    WatcherRequest,
    Webhooks,
    Affiliate,
    Address,
    UserWithdrawTask,
    Other,
    Htlc,
    ResolverApiClient,
}

/// Error response returned by the server for 4xx and 5xx HTTP errors
#[derive(Debug, Deserialize)]
pub struct ErrorResponse {
    /// Error code from the server
    pub code: u64,
    /// Human-readable error message
    pub message: String,
    /// The entity type related to this error
    pub entity: EntityKind,
}

/// Main error type for the API client
#[derive(Debug, thiserror::Error)]
pub enum ApiClientError {
    /// Network-related errors (connection issues, DNS failures, etc.)
    #[error("Network error: {0}")]
    Network(String),

    /// Request timeout
    #[error("Request timed out")]
    Timeout,

    /// Invalid endpoint URL
    #[error("Invalid endpoint URL: {0}")]
    InvalidUrl(String),

    /// Invalid API key format
    #[error("Invalid API key: {0}")]
    InvalidApiKey(String),

    /// Failed to initialize HTTP client
    #[error("Client initialization failed: {0}")]
    ClientInitialization(String),

    /// Serialization error
    #[error("Serialization error: {0}")]
    SerializationError(String),

    /// HTTP 404 Not Found - endpoint does not exist
    #[error("Resource not found (404)")]
    NotFound,

    /// Server returned 4xx or 5xx error with structured error response
    #[error("Server error: {0}")]
    ServerErrorResponse(ErrorResponse),

    /// Failed to deserialize response body
    #[error("Deserialization error: {0}")]
    DeserializationError(String),
}

impl std::fmt::Display for ErrorResponse {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "Error code: {}, message: {}, entity: {:?}",
            self.code, self.message, self.entity
        )
    }
}

impl From<reqwest::Error> for ApiClientError {
    fn from(err: reqwest::Error) -> Self {
        if err.is_timeout() {
            return ApiClientError::Timeout;
        }
        ApiClientError::Network(err.to_string())
    }
}