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::{Capability, Exchange, ExchangeCapabilities},
9    types::{
10        Amount, Balance, Market, Ohlcv, Order, OrderBook, OrderSide, OrderType, Price, Ticker,
11        Timeframe, Trade,
12    },
13};
14use std::collections::HashMap;
15use std::sync::Arc;
16
17use super::HyperLiquid;
18
19#[async_trait]
20impl Exchange for HyperLiquid {
21    // ==================== Metadata ====================
22
23    fn id(&self) -> &'static str {
24        "hyperliquid"
25    }
26
27    fn name(&self) -> &'static 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        // HyperLiquid supports:
45        // - Market Data: markets, ticker, tickers, order_book, trades, ohlcv
46        // - Trading: create_order, cancel_order, cancel_all_orders, open_orders
47        // - Account: balance
48        // - Margin: funding_rate, positions, set_leverage
49        // - WebSocket: ticker, order_book, trades, orders
50        ExchangeCapabilities::builder()
51            .market_data()
52            .trading()
53            // Remove unsupported market data capabilities
54            .without_capability(Capability::FetchCurrencies)
55            .without_capability(Capability::FetchStatus)
56            .without_capability(Capability::FetchTime)
57            // Remove unsupported trading capabilities
58            .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            // Add account capabilities
64            .capability(Capability::FetchBalance)
65            // Add margin capabilities
66            .capability(Capability::FetchFundingRate)
67            .capability(Capability::FetchPositions)
68            .capability(Capability::SetLeverage)
69            // Add WebSocket capabilities
70            .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    // ==================== Market Data (Public API) ====================
96
97    async fn fetch_markets(&self) -> Result<Vec<Market>> {
98        let markets = HyperLiquid::fetch_markets(self).await?;
99        Ok(markets.values().map(|m| (**m).clone()).collect())
100    }
101
102    async fn load_markets(&self, reload: bool) -> Result<Arc<HashMap<String, Arc<Market>>>> {
103        HyperLiquid::load_markets(self, reload).await
104    }
105
106    async fn fetch_ticker(&self, symbol: &str) -> Result<Ticker> {
107        HyperLiquid::fetch_ticker(self, symbol).await
108    }
109
110    async fn fetch_tickers(&self, symbols: Option<&[String]>) -> Result<Vec<Ticker>> {
111        let symbols_vec = symbols.map(<[String]>::to_vec);
112        HyperLiquid::fetch_tickers(self, symbols_vec).await
113    }
114
115    async fn fetch_order_book(&self, symbol: &str, limit: Option<u32>) -> Result<OrderBook> {
116        HyperLiquid::fetch_order_book(self, symbol, limit).await
117    }
118
119    async fn fetch_trades(&self, symbol: &str, limit: Option<u32>) -> Result<Vec<Trade>> {
120        HyperLiquid::fetch_trades(self, symbol, limit).await
121    }
122
123    async fn fetch_ohlcv(
124        &self,
125        symbol: &str,
126        timeframe: Timeframe,
127        since: Option<i64>,
128        limit: Option<u32>,
129    ) -> Result<Vec<Ohlcv>> {
130        let timeframe_str = timeframe.to_string();
131        HyperLiquid::fetch_ohlcv(self, symbol, &timeframe_str, since, limit).await
132    }
133
134    // ==================== Trading (Private API) ====================
135
136    async fn create_order(
137        &self,
138        symbol: &str,
139        order_type: OrderType,
140        side: OrderSide,
141        amount: Amount,
142        price: Option<Price>,
143    ) -> Result<Order> {
144        // Direct delegation - no type conversion needed
145        HyperLiquid::create_order(self, symbol, order_type, side, amount, price).await
146    }
147
148    async fn cancel_order(&self, id: &str, symbol: Option<&str>) -> Result<Order> {
149        let symbol_str = symbol.ok_or_else(|| {
150            ccxt_core::Error::invalid_request("Symbol is required for cancel_order on HyperLiquid")
151        })?;
152        HyperLiquid::cancel_order(self, id, symbol_str).await
153    }
154
155    async fn cancel_all_orders(&self, symbol: Option<&str>) -> Result<Vec<Order>> {
156        HyperLiquid::cancel_all_orders(self, symbol).await
157    }
158
159    async fn fetch_order(&self, _id: &str, _symbol: Option<&str>) -> Result<Order> {
160        Err(ccxt_core::Error::not_implemented("fetch_order"))
161    }
162
163    async fn fetch_open_orders(
164        &self,
165        symbol: Option<&str>,
166        since: Option<i64>,
167        limit: Option<u32>,
168    ) -> Result<Vec<Order>> {
169        HyperLiquid::fetch_open_orders(self, symbol, since, limit).await
170    }
171
172    async fn fetch_closed_orders(
173        &self,
174        _symbol: Option<&str>,
175        _since: Option<i64>,
176        _limit: Option<u32>,
177    ) -> Result<Vec<Order>> {
178        Err(ccxt_core::Error::not_implemented("fetch_closed_orders"))
179    }
180
181    // ==================== Account (Private API) ====================
182
183    async fn fetch_balance(&self) -> Result<Balance> {
184        HyperLiquid::fetch_balance(self).await
185    }
186
187    async fn fetch_my_trades(
188        &self,
189        _symbol: Option<&str>,
190        _since: Option<i64>,
191        _limit: Option<u32>,
192    ) -> Result<Vec<Trade>> {
193        Err(ccxt_core::Error::not_implemented("fetch_my_trades"))
194    }
195
196    // ==================== Helper Methods ====================
197
198    async fn market(&self, symbol: &str) -> Result<Arc<Market>> {
199        self.base().market(symbol).await
200    }
201
202    async fn markets(&self) -> Arc<HashMap<String, Arc<Market>>> {
203        let cache = self.base().market_cache.read().await;
204        cache.markets.clone()
205    }
206}