use alloy::primitives::{B256, U256};
use thiserror::Error;
#[derive(Error, Debug)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum PerpCityError {
#[error("invalid price: {reason}")]
InvalidPrice { reason: String },
#[error("invalid margin: {reason}")]
InvalidMargin { reason: String },
#[error("invalid leverage: {reason}")]
InvalidLeverage { reason: String },
#[error("invalid tick range: lower={lower}, upper={upper}")]
InvalidTickRange { lower: i32, upper: i32 },
#[error("invalid margin ratio: {value} (must be in [{min}, {max}])")]
InvalidMarginRatio { value: u32, min: u32, max: u32 },
#[error("invalid configuration: {reason}")]
InvalidConfig { reason: String },
#[error("arithmetic overflow: {context}")]
Overflow { context: String },
#[error("transaction reverted: {reason}")]
TxReverted { reason: String },
#[error("event not found in receipt: {event_name}")]
EventNotFound { event_name: String },
#[error("gas price unavailable: {reason}")]
GasPriceUnavailable { reason: String },
#[error("too many in-flight transactions: {count} (max {max})")]
TooManyInFlight { count: usize, max: usize },
#[error("perp does not exist: {perp_id}")]
PerpNotFound { perp_id: B256 },
#[error("position does not exist: id={pos_id}")]
PositionNotFound { pos_id: U256 },
#[error("module not registered: {module}")]
ModuleNotRegistered { module: String },
#[error(transparent)]
AlloyContract(#[from] alloy::contract::Error),
#[error(transparent)]
AlloyTransport(#[from] alloy::transports::TransportError),
#[error(transparent)]
Serde(#[from] serde_json::Error),
}
pub type Result<T> = std::result::Result<T, PerpCityError>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn serde_error_converts() {
let json_err = serde_json::from_str::<String>("not valid json").unwrap_err();
let err: PerpCityError = json_err.into();
assert!(matches!(err, PerpCityError::Serde(_)));
}
#[test]
fn error_is_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<PerpCityError>();
}
}