Skip to main content

roshar_types/lighter/
mod.rs

1use serde::{Deserialize, Serialize};
2
3// ── WebSocket messages ────────────────────────────────────────────────────────
4
5/// Subscribe / unsubscribe message for Lighter WebSocket streams.
6/// Format: `{"type": "subscribe", "channel": "order_book/0"}`
7#[derive(Debug, Deserialize, Serialize, Clone)]
8pub struct LighterWssMessage {
9    #[serde(rename = "type")]
10    pub msg_type: String,
11    pub channel: String,
12}
13
14impl LighterWssMessage {
15    pub fn to_json(&self) -> String {
16        serde_json::to_string(self).expect("Failed to serialize LighterWssMessage")
17    }
18
19    /// Lighter requires any frame within 2 minutes; use a subscribe ping pattern.
20    pub fn ping() -> Self {
21        Self {
22            msg_type: "ping".to_string(),
23            channel: String::new(),
24        }
25    }
26
27    pub fn depth(market_index: u32) -> Self {
28        Self {
29            msg_type: "subscribe".to_string(),
30            channel: format!("order_book/{market_index}"),
31        }
32    }
33
34    pub fn depth_unsub(market_index: u32) -> Self {
35        Self {
36            msg_type: "unsubscribe".to_string(),
37            channel: format!("order_book/{market_index}"),
38        }
39    }
40
41    pub fn trades(market_index: u32) -> Self {
42        Self {
43            msg_type: "subscribe".to_string(),
44            channel: format!("trade/{market_index}"),
45        }
46    }
47
48    pub fn trades_unsub(market_index: u32) -> Self {
49        Self {
50            msg_type: "unsubscribe".to_string(),
51            channel: format!("trade/{market_index}"),
52        }
53    }
54
55    pub fn market_stats(market_index: u32) -> Self {
56        Self {
57            msg_type: "subscribe".to_string(),
58            channel: format!("market_stats/{market_index}"),
59        }
60    }
61
62    pub fn all_market_stats() -> Self {
63        Self {
64            msg_type: "subscribe".to_string(),
65            channel: "market_stats/all".to_string(),
66        }
67    }
68
69    pub fn ticker(market_index: u32) -> Self {
70        Self {
71            msg_type: "subscribe".to_string(),
72            channel: format!("ticker/{market_index}"),
73        }
74    }
75}
76
77// ── REST response types ───────────────────────────────────────────────────────
78
79/// Market metadata from `GET /api/v1/orderBooks`.
80#[derive(Debug, Clone, Serialize, Deserialize)]
81pub struct LighterMarket {
82    pub market_id: u32,
83    pub name: String,
84    #[serde(default)]
85    pub maker_fee: String,
86    #[serde(default)]
87    pub taker_fee: String,
88    #[serde(default)]
89    pub min_order_size: String,
90    #[serde(default)]
91    pub min_order_size_increment: String,
92    #[serde(default)]
93    pub min_price_increment: String,
94    #[serde(default)]
95    pub status: String,
96    #[serde(default)]
97    pub contract_type: String,
98}
99
100/// Extended market detail from `GET /api/v1/orderBookDetails`.
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct LighterMarketDetail {
103    pub market_id: u32,
104    pub name: String,
105    #[serde(default)]
106    pub mark_price: String,
107    #[serde(default)]
108    pub index_price: String,
109    #[serde(default)]
110    pub last_price: String,
111    #[serde(default)]
112    pub daily_volume: String,
113    #[serde(default)]
114    pub daily_price_change: String,
115    #[serde(default)]
116    pub open_interest: String,
117    #[serde(default)]
118    pub funding_rate: String,
119    #[serde(default)]
120    pub next_funding_time: i64,
121}
122
123/// Order book snapshot from `GET /api/v1/orderBookOrders`.
124#[derive(Debug, Clone, Serialize, Deserialize)]
125pub struct LighterOrderBook {
126    pub asks: Vec<LighterLevel>,
127    pub bids: Vec<LighterLevel>,
128}
129
130/// Single price level in the order book.
131#[derive(Debug, Clone, Serialize, Deserialize)]
132pub struct LighterLevel {
133    pub price: String,
134    pub size: String,
135}
136
137/// Single trade from `GET /api/v1/recentTrades`.
138#[derive(Debug, Clone, Serialize, Deserialize)]
139pub struct LighterTrade {
140    pub price: String,
141    pub size: String,
142    pub side: String,
143    #[serde(alias = "timestamp", alias = "created_at")]
144    pub timestamp: i64,
145    #[serde(default)]
146    pub market_id: u32,
147}
148
149/// Funding rate entry from `GET /api/v1/funding-rates`.
150#[derive(Debug, Clone, Serialize, Deserialize)]
151pub struct LighterFundingRate {
152    pub market_id: u32,
153    #[serde(default)]
154    pub name: String,
155    pub funding_rate: String,
156    #[serde(default)]
157    pub funding_period: String,
158    #[serde(default)]
159    pub binance_funding_rate: String,
160    #[serde(default)]
161    pub bybit_funding_rate: String,
162    #[serde(default)]
163    pub hyperliquid_funding_rate: String,
164}
165
166/// Wrapper returned by the `/orderBooks` endpoint.
167#[derive(Debug, Clone, Serialize, Deserialize)]
168pub struct LighterMarketsResponse {
169    pub order_books: Vec<LighterMarket>,
170}
171
172/// Wrapper returned by the `/orderBookDetails` endpoint.
173#[derive(Debug, Clone, Serialize, Deserialize)]
174pub struct LighterMarketDetailsResponse {
175    pub order_book_details: Vec<LighterMarketDetail>,
176}
177
178/// Wrapper returned by the `/funding-rates` endpoint.
179#[derive(Debug, Clone, Serialize, Deserialize)]
180pub struct LighterFundingRatesResponse {
181    pub funding_rates: Vec<LighterFundingRate>,
182}