ccxt_exchanges/hyperliquid/
exchange_impl.rs1use async_trait::async_trait;
6use ccxt_core::{
7 Result,
8 exchange::{Capability, Exchange, ExchangeCapabilities},
9 types::{
10 Balance, Market, Ohlcv, Order, OrderBook, OrderSide, OrderType, Ticker, Timeframe, Trade,
11 },
12};
13use rust_decimal::Decimal;
14use rust_decimal::prelude::ToPrimitive;
15use std::collections::HashMap;
16
17use super::HyperLiquid;
18
19#[async_trait]
20impl Exchange for HyperLiquid {
21 fn id(&self) -> &str {
24 "hyperliquid"
25 }
26
27 fn name(&self) -> &str {
28 "HyperLiquid"
29 }
30
31 fn version(&self) -> &'static str {
32 "1"
33 }
34
35 fn certified(&self) -> bool {
36 false
37 }
38
39 fn has_websocket(&self) -> bool {
40 true
41 }
42
43 fn capabilities(&self) -> ExchangeCapabilities {
44 ExchangeCapabilities::builder()
51 .market_data()
52 .trading()
53 .without_capability(Capability::FetchCurrencies)
55 .without_capability(Capability::FetchStatus)
56 .without_capability(Capability::FetchTime)
57 .without_capability(Capability::EditOrder)
59 .without_capability(Capability::FetchOrder)
60 .without_capability(Capability::FetchOrders)
61 .without_capability(Capability::FetchClosedOrders)
62 .without_capability(Capability::FetchCanceledOrders)
63 .capability(Capability::FetchBalance)
65 .capability(Capability::FetchFundingRate)
67 .capability(Capability::FetchPositions)
68 .capability(Capability::SetLeverage)
69 .capability(Capability::Websocket)
71 .capability(Capability::WatchTicker)
72 .capability(Capability::WatchOrderBook)
73 .capability(Capability::WatchTrades)
74 .capability(Capability::WatchOrders)
75 .build()
76 }
77
78 fn timeframes(&self) -> Vec<Timeframe> {
79 vec![
80 Timeframe::M1,
81 Timeframe::M5,
82 Timeframe::M15,
83 Timeframe::M30,
84 Timeframe::H1,
85 Timeframe::H4,
86 Timeframe::D1,
87 Timeframe::W1,
88 ]
89 }
90
91 fn rate_limit(&self) -> u32 {
92 100
93 }
94
95 async fn fetch_markets(&self) -> Result<Vec<Market>> {
98 let markets = HyperLiquid::fetch_markets(self).await?;
99 Ok(markets.into_values().map(|m| (*m).clone()).collect())
100 }
101
102 async fn load_markets(&self, reload: bool) -> Result<HashMap<String, Market>> {
103 let markets = HyperLiquid::load_markets(self, reload).await?;
104 Ok(markets
105 .into_iter()
106 .map(|(k, v)| (k, (*v).clone()))
107 .collect())
108 }
109
110 async fn fetch_ticker(&self, symbol: &str) -> Result<Ticker> {
111 HyperLiquid::fetch_ticker(self, symbol).await
112 }
113
114 async fn fetch_tickers(&self, symbols: Option<&[String]>) -> Result<Vec<Ticker>> {
115 let symbols_vec = symbols.map(|s| s.to_vec());
116 HyperLiquid::fetch_tickers(self, symbols_vec).await
117 }
118
119 async fn fetch_order_book(&self, symbol: &str, limit: Option<u32>) -> Result<OrderBook> {
120 HyperLiquid::fetch_order_book(self, symbol, limit).await
121 }
122
123 async fn fetch_trades(&self, symbol: &str, limit: Option<u32>) -> Result<Vec<Trade>> {
124 HyperLiquid::fetch_trades(self, symbol, limit).await
125 }
126
127 async fn fetch_ohlcv(
128 &self,
129 symbol: &str,
130 timeframe: Timeframe,
131 since: Option<i64>,
132 limit: Option<u32>,
133 ) -> Result<Vec<Ohlcv>> {
134 let timeframe_str = timeframe.to_string();
135 HyperLiquid::fetch_ohlcv(self, symbol, &timeframe_str, since, limit).await
136 }
137
138 async fn create_order(
141 &self,
142 symbol: &str,
143 order_type: OrderType,
144 side: OrderSide,
145 amount: Decimal,
146 price: Option<Decimal>,
147 ) -> Result<Order> {
148 let amount_f64 = amount
149 .to_f64()
150 .ok_or_else(|| ccxt_core::Error::invalid_request("Failed to convert amount to f64"))?;
151 let price_f64 = match price {
152 Some(p) => Some(p.to_f64().ok_or_else(|| {
153 ccxt_core::Error::invalid_request("Failed to convert price to f64")
154 })?),
155 None => None,
156 };
157
158 HyperLiquid::create_order(self, symbol, order_type, side, amount_f64, price_f64).await
159 }
160
161 async fn cancel_order(&self, id: &str, symbol: Option<&str>) -> Result<Order> {
162 let symbol_str = symbol.ok_or_else(|| {
163 ccxt_core::Error::invalid_request("Symbol is required for cancel_order on HyperLiquid")
164 })?;
165 HyperLiquid::cancel_order(self, id, symbol_str).await
166 }
167
168 async fn cancel_all_orders(&self, symbol: Option<&str>) -> Result<Vec<Order>> {
169 HyperLiquid::cancel_all_orders(self, symbol).await
170 }
171
172 async fn fetch_order(&self, _id: &str, _symbol: Option<&str>) -> Result<Order> {
173 Err(ccxt_core::Error::not_implemented("fetch_order"))
174 }
175
176 async fn fetch_open_orders(
177 &self,
178 symbol: Option<&str>,
179 since: Option<i64>,
180 limit: Option<u32>,
181 ) -> Result<Vec<Order>> {
182 HyperLiquid::fetch_open_orders(self, symbol, since, limit).await
183 }
184
185 async fn fetch_closed_orders(
186 &self,
187 _symbol: Option<&str>,
188 _since: Option<i64>,
189 _limit: Option<u32>,
190 ) -> Result<Vec<Order>> {
191 Err(ccxt_core::Error::not_implemented("fetch_closed_orders"))
192 }
193
194 async fn fetch_balance(&self) -> Result<Balance> {
197 HyperLiquid::fetch_balance(self).await
198 }
199
200 async fn fetch_my_trades(
201 &self,
202 _symbol: Option<&str>,
203 _since: Option<i64>,
204 _limit: Option<u32>,
205 ) -> Result<Vec<Trade>> {
206 Err(ccxt_core::Error::not_implemented("fetch_my_trades"))
207 }
208
209 async fn market(&self, symbol: &str) -> Result<Market> {
212 self.base().market(symbol).await.map(|m| (*m).clone())
213 }
214
215 async fn markets(&self) -> HashMap<String, Market> {
216 let cache = self.base().market_cache.read().await;
217 cache
218 .markets
219 .iter()
220 .map(|(k, v)| (k.clone(), (**v).clone()))
221 .collect()
222 }
223}