ccxt_exchanges/hyperliquid/
exchange_impl.rs

1//! Exchange trait implementation for HyperLiquid
2//!
3//! This module implements the unified `Exchange` trait from `ccxt-core` for HyperLiquid.
4
5use async_trait::async_trait;
6use ccxt_core::{
7    Result,
8    exchange::{Exchange, ExchangeCapabilities},
9    types::{
10        Balance, Market, Ohlcv, Order, OrderBook, OrderSide, OrderType, Ticker, Timeframe, Trade,
11    },
12};
13use rust_decimal::Decimal;
14use std::collections::HashMap;
15
16use super::HyperLiquid;
17
18#[async_trait]
19impl Exchange for HyperLiquid {
20    // ==================== Metadata ====================
21
22    fn id(&self) -> &str {
23        "hyperliquid"
24    }
25
26    fn name(&self) -> &str {
27        "HyperLiquid"
28    }
29
30    fn version(&self) -> &'static str {
31        "1"
32    }
33
34    fn certified(&self) -> bool {
35        false
36    }
37
38    fn has_websocket(&self) -> bool {
39        true
40    }
41
42    fn capabilities(&self) -> ExchangeCapabilities {
43        ExchangeCapabilities {
44            // Market Data (Public API)
45            fetch_markets: true,
46            fetch_currencies: false,
47            fetch_ticker: true,
48            fetch_tickers: true,
49            fetch_order_book: true,
50            fetch_trades: true,
51            fetch_ohlcv: true,
52            fetch_status: false,
53            fetch_time: false,
54
55            // Trading (Private API)
56            create_order: true,
57            create_market_order: true,
58            create_limit_order: true,
59            cancel_order: true,
60            cancel_all_orders: true,
61            edit_order: false,
62            fetch_order: false, // Not directly supported
63            fetch_orders: false,
64            fetch_open_orders: true,
65            fetch_closed_orders: false,
66            fetch_canceled_orders: false,
67
68            // Account (Private API)
69            fetch_balance: true,
70            fetch_my_trades: false,
71            fetch_deposits: false,
72            fetch_withdrawals: false,
73            fetch_transactions: false,
74            fetch_ledger: false,
75
76            // Funding
77            fetch_deposit_address: false,
78            create_deposit_address: false,
79            withdraw: false,
80            transfer: false,
81
82            // Margin Trading
83            fetch_borrow_rate: false,
84            fetch_borrow_rates: false,
85            fetch_funding_rate: true,
86            fetch_funding_rates: false,
87            fetch_positions: true,
88            set_leverage: true,
89            set_margin_mode: false,
90
91            // WebSocket
92            websocket: true,
93            watch_ticker: true,
94            watch_tickers: false,
95            watch_order_book: true,
96            watch_trades: true,
97            watch_ohlcv: false,
98            watch_balance: false,
99            watch_orders: true,
100            watch_my_trades: false,
101        }
102    }
103
104    fn timeframes(&self) -> Vec<Timeframe> {
105        vec![
106            Timeframe::M1,
107            Timeframe::M5,
108            Timeframe::M15,
109            Timeframe::M30,
110            Timeframe::H1,
111            Timeframe::H4,
112            Timeframe::D1,
113            Timeframe::W1,
114        ]
115    }
116
117    fn rate_limit(&self) -> f64 {
118        100.0
119    }
120
121    // ==================== Market Data (Public API) ====================
122
123    async fn fetch_markets(&self) -> Result<Vec<Market>> {
124        HyperLiquid::fetch_markets(self).await
125    }
126
127    async fn load_markets(&self, reload: bool) -> Result<HashMap<String, Market>> {
128        HyperLiquid::load_markets(self, reload).await
129    }
130
131    async fn fetch_ticker(&self, symbol: &str) -> Result<Ticker> {
132        HyperLiquid::fetch_ticker(self, symbol).await
133    }
134
135    async fn fetch_tickers(&self, symbols: Option<&[String]>) -> Result<Vec<Ticker>> {
136        let symbols_vec = symbols.map(|s| s.to_vec());
137        HyperLiquid::fetch_tickers(self, symbols_vec).await
138    }
139
140    async fn fetch_order_book(&self, symbol: &str, limit: Option<u32>) -> Result<OrderBook> {
141        HyperLiquid::fetch_order_book(self, symbol, limit).await
142    }
143
144    async fn fetch_trades(&self, symbol: &str, limit: Option<u32>) -> Result<Vec<Trade>> {
145        HyperLiquid::fetch_trades(self, symbol, limit).await
146    }
147
148    async fn fetch_ohlcv(
149        &self,
150        symbol: &str,
151        timeframe: Timeframe,
152        since: Option<i64>,
153        limit: Option<u32>,
154    ) -> Result<Vec<Ohlcv>> {
155        let timeframe_str = timeframe.to_string();
156        HyperLiquid::fetch_ohlcv(self, symbol, &timeframe_str, since, limit).await
157    }
158
159    // ==================== Trading (Private API) ====================
160
161    async fn create_order(
162        &self,
163        symbol: &str,
164        order_type: OrderType,
165        side: OrderSide,
166        amount: Decimal,
167        price: Option<Decimal>,
168    ) -> Result<Order> {
169        let amount_f64 = amount.to_string().parse::<f64>().unwrap_or(0.0);
170        let price_f64 = price.map(|p| p.to_string().parse::<f64>().unwrap_or(0.0));
171
172        HyperLiquid::create_order(self, symbol, order_type, side, amount_f64, price_f64).await
173    }
174
175    async fn cancel_order(&self, id: &str, symbol: Option<&str>) -> Result<Order> {
176        let symbol_str = symbol.ok_or_else(|| {
177            ccxt_core::Error::invalid_request("Symbol is required for cancel_order on HyperLiquid")
178        })?;
179        HyperLiquid::cancel_order(self, id, symbol_str).await
180    }
181
182    async fn cancel_all_orders(&self, symbol: Option<&str>) -> Result<Vec<Order>> {
183        HyperLiquid::cancel_all_orders(self, symbol).await
184    }
185
186    async fn fetch_order(&self, _id: &str, _symbol: Option<&str>) -> Result<Order> {
187        Err(ccxt_core::Error::not_implemented("fetch_order"))
188    }
189
190    async fn fetch_open_orders(
191        &self,
192        symbol: Option<&str>,
193        since: Option<i64>,
194        limit: Option<u32>,
195    ) -> Result<Vec<Order>> {
196        HyperLiquid::fetch_open_orders(self, symbol, since, limit).await
197    }
198
199    async fn fetch_closed_orders(
200        &self,
201        _symbol: Option<&str>,
202        _since: Option<i64>,
203        _limit: Option<u32>,
204    ) -> Result<Vec<Order>> {
205        Err(ccxt_core::Error::not_implemented("fetch_closed_orders"))
206    }
207
208    // ==================== Account (Private API) ====================
209
210    async fn fetch_balance(&self) -> Result<Balance> {
211        HyperLiquid::fetch_balance(self).await
212    }
213
214    async fn fetch_my_trades(
215        &self,
216        _symbol: Option<&str>,
217        _since: Option<i64>,
218        _limit: Option<u32>,
219    ) -> Result<Vec<Trade>> {
220        Err(ccxt_core::Error::not_implemented("fetch_my_trades"))
221    }
222
223    // ==================== Helper Methods ====================
224
225    async fn market(&self, symbol: &str) -> Result<Market> {
226        self.base().market(symbol).await
227    }
228
229    async fn markets(&self) -> HashMap<String, Market> {
230        let cache = self.base().market_cache.read().await;
231        cache.markets.clone()
232    }
233}