elizaos-plugin-evm 2.0.0

EVM blockchain plugin for elizaOS - Rust implementation with alloy-rs
Documentation
#![allow(missing_docs)]

use std::fmt;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum EVMErrorCode {
    InsufficientFunds,
    UserRejected,
    NetworkError,
    ContractRevert,
    GasEstimationFailed,
    InvalidParams,
    ChainNotConfigured,
    WalletNotInitialized,
    TransactionFailed,
    TokenNotFound,
    RouteNotFound,
    ApprovalFailed,
}

impl fmt::Display for EVMErrorCode {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::InsufficientFunds => write!(f, "INSUFFICIENT_FUNDS"),
            Self::UserRejected => write!(f, "USER_REJECTED"),
            Self::NetworkError => write!(f, "NETWORK_ERROR"),
            Self::ContractRevert => write!(f, "CONTRACT_REVERT"),
            Self::GasEstimationFailed => write!(f, "GAS_ESTIMATION_FAILED"),
            Self::InvalidParams => write!(f, "INVALID_PARAMS"),
            Self::ChainNotConfigured => write!(f, "CHAIN_NOT_CONFIGURED"),
            Self::WalletNotInitialized => write!(f, "WALLET_NOT_INITIALIZED"),
            Self::TransactionFailed => write!(f, "TRANSACTION_FAILED"),
            Self::TokenNotFound => write!(f, "TOKEN_NOT_FOUND"),
            Self::RouteNotFound => write!(f, "ROUTE_NOT_FOUND"),
            Self::ApprovalFailed => write!(f, "APPROVAL_FAILED"),
        }
    }
}

#[derive(Debug)]
pub struct EVMError {
    pub code: EVMErrorCode,
    pub message: String,
    pub source: Option<Box<dyn std::error::Error + Send + Sync>>,
}

impl EVMError {
    #[must_use]
    pub fn new(code: EVMErrorCode, message: impl Into<String>) -> Self {
        Self {
            code,
            message: message.into(),
            source: None,
        }
    }

    #[must_use]
    pub fn with_source<E>(code: EVMErrorCode, message: impl Into<String>, source: E) -> Self
    where
        E: std::error::Error + Send + Sync + 'static,
    {
        Self {
            code,
            message: message.into(),
            source: Some(Box::new(source)),
        }
    }

    #[must_use]
    pub fn insufficient_funds(message: impl Into<String>) -> Self {
        Self::new(EVMErrorCode::InsufficientFunds, message)
    }

    #[must_use]
    pub fn chain_not_configured(chain: &str) -> Self {
        Self::new(
            EVMErrorCode::ChainNotConfigured,
            format!("Chain '{chain}' is not configured"),
        )
    }

    #[must_use]
    pub fn invalid_params(message: impl Into<String>) -> Self {
        Self::new(EVMErrorCode::InvalidParams, message)
    }

    #[must_use]
    pub fn wallet_not_initialized() -> Self {
        Self::new(EVMErrorCode::WalletNotInitialized, "Wallet not initialized")
    }

    #[must_use]
    pub fn transaction_failed(message: impl Into<String>) -> Self {
        Self::new(EVMErrorCode::TransactionFailed, message)
    }

    #[must_use]
    pub fn network_error(message: impl Into<String>) -> Self {
        Self::new(EVMErrorCode::NetworkError, message)
    }
}

impl fmt::Display for EVMError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "[{}] {}", self.code, self.message)
    }
}

impl std::error::Error for EVMError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        self.source
            .as_ref()
            .map(|e| e.as_ref() as &(dyn std::error::Error + 'static))
    }
}

impl From<reqwest::Error> for EVMError {
    fn from(err: reqwest::Error) -> Self {
        Self::with_source(
            EVMErrorCode::NetworkError,
            format!("HTTP request failed: {err}"),
            err,
        )
    }
}

impl From<serde_json::Error> for EVMError {
    fn from(err: serde_json::Error) -> Self {
        Self::with_source(
            EVMErrorCode::InvalidParams,
            format!("JSON parsing failed: {err}"),
            err,
        )
    }
}

impl From<url::ParseError> for EVMError {
    fn from(err: url::ParseError) -> Self {
        Self::with_source(
            EVMErrorCode::InvalidParams,
            format!("URL parsing failed: {err}"),
            err,
        )
    }
}

pub type EVMResult<T> = Result<T, EVMError>;