use crate::{
pair::{AssetSymbol, RawMarketName},
Pair,
};
pub mod margin_type;
pub use margin_type::MarginType;
#[derive(
Clone,
Debug,
Hash,
PartialEq,
PartialOrd,
Ord,
Eq,
Copy,
strum::EnumString,
strum::Display,
strum::EnumIter,
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "borsh",
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
)]
#[strum(ascii_case_insensitive, serialize_all = "UPPERCASE")]
#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
#[non_exhaustive]
pub enum Exchange {
Hyperliquid,
Paradex,
Kraken,
Lmax,
Extended,
}
impl Exchange {
pub fn market_name_from_pair(&self, pair: &Pair) -> RawMarketName {
match self {
Exchange::Hyperliquid => pair.base.to_string(),
Exchange::Paradex => format!("{}-{}-PERP", pair.base, pair.quote),
Exchange::Kraken => match pair.base.as_str() {
"BTC" => "PF_XBTUSD".to_string(),
other => format!("PF_{}{}", other, pair.quote),
},
Exchange::Lmax | Exchange::Extended => format!("{}-{}", pair.base, pair.quote),
}
}
pub fn usd_market_name_from_asset_symbol(&self, asset_symbol: &AssetSymbol) -> RawMarketName {
match self {
Exchange::Hyperliquid => asset_symbol.to_string(),
Exchange::Paradex => format!("{asset_symbol}-USD-PERP"),
Exchange::Kraken => match asset_symbol.to_string().to_uppercase().as_str() {
"BTC" => "PF_XBTUSD".to_string(),
other => format!("PF_{other}USD"),
},
Exchange::Lmax | Exchange::Extended => format!("{asset_symbol}-USD"),
}
}
pub fn asset_symbol_from_raw_market_name(&self, market_name: &RawMarketName) -> AssetSymbol {
match self {
Exchange::Hyperliquid => AssetSymbol::from(market_name),
Exchange::Paradex | Exchange::Lmax | Exchange::Extended => {
market_name.split('-').next().unwrap().into()
}
Exchange::Kraken => {
if market_name.starts_with("PF_") && market_name.ends_with("USD") {
let base_part = &market_name[3..market_name.len() - 3];
match base_part {
"XBT" => "BTC".into(),
other => other.into(),
}
} else {
market_name.split('/').next().unwrap().into()
}
}
}
}
pub const fn taker_fees_rate(&self) -> f64 {
match self {
Exchange::Hyperliquid => 0.00045, Exchange::Paradex => 0.0003, Exchange::Kraken => 0.0002, Exchange::Extended => 0.00025, _ => todo!(),
}
}
pub const fn supports_leverage(&self) -> bool {
match self {
Exchange::Hyperliquid => true,
Exchange::Paradex => true,
Exchange::Kraken => false,
Exchange::Extended => true,
Exchange::Lmax => false,
}
}
pub const fn from_str_const(s: &str) -> Option<Self> {
match s.as_bytes() {
b"Lmax" | b"lmax" | b"LMAX" => Some(Exchange::Lmax),
b"Extended" | b"extended" | b"EXTENDED" => Some(Exchange::Extended),
b"Hyperliquid" | b"hyperliquid" | b"HYPERLIQUID" => Some(Exchange::Hyperliquid),
b"Paradex" | b"paradex" | b"PARADEX" => Some(Exchange::Paradex),
b"Kraken" | b"kraken" | b"KRAKEN" => Some(Exchange::Kraken),
_ => None,
}
}
}