nautilus_hyperliquid/websocket/
enums.rs1use serde::{Deserialize, Serialize};
17use strum::{AsRefStr, Display, EnumIter, EnumString};
18
19#[derive(
21 Clone,
22 Debug,
23 Display,
24 PartialEq,
25 Eq,
26 Hash,
27 AsRefStr,
28 EnumIter,
29 EnumString,
30 Serialize,
31 Deserialize,
32)]
33pub enum HyperliquidWsChannel {
34 #[serde(rename = "subscriptionResponse")]
35 SubscriptionResponse,
36 #[serde(rename = "trades")]
37 Trades,
38 #[serde(rename = "l2Book")]
39 L2Book,
40 #[serde(rename = "bbo")]
41 Bbo,
42 #[serde(rename = "candle")]
43 Candle,
44 #[serde(rename = "allMids")]
45 AllMids,
46 #[serde(rename = "notification")]
47 Notification,
48 #[serde(rename = "orderUpdates")]
49 OrderUpdates,
50 #[serde(rename = "userEvents")]
51 UserEvents,
52 #[serde(rename = "userFills")]
53 UserFills,
54 #[serde(rename = "userFundings")]
55 UserFundings,
56 #[serde(rename = "userNonFundingLedgerUpdates")]
57 UserNonFundingLedgerUpdates,
58 #[serde(rename = "post")]
59 Post,
60 #[serde(rename = "pong")]
61 Pong,
62 #[serde(rename = "error")]
63 Error,
64}
65
66impl HyperliquidWsChannel {
67 pub fn as_str(&self) -> &'static str {
69 match self {
70 Self::SubscriptionResponse => "subscriptionResponse",
71 Self::Trades => "trades",
72 Self::L2Book => "l2Book",
73 Self::Bbo => "bbo",
74 Self::Candle => "candle",
75 Self::AllMids => "allMids",
76 Self::Notification => "notification",
77 Self::OrderUpdates => "orderUpdates",
78 Self::UserEvents => "userEvents",
79 Self::UserFills => "userFills",
80 Self::UserFundings => "userFundings",
81 Self::UserNonFundingLedgerUpdates => "userNonFundingLedgerUpdates",
82 Self::Post => "post",
83 Self::Pong => "pong",
84 Self::Error => "error",
85 }
86 }
87
88 pub fn is_public(&self) -> bool {
90 matches!(
91 self,
92 Self::SubscriptionResponse
93 | Self::Trades
94 | Self::L2Book
95 | Self::Bbo
96 | Self::Candle
97 | Self::AllMids
98 | Self::Notification
99 | Self::Pong
100 | Self::Error
101 )
102 }
103
104 pub fn is_private(&self) -> bool {
106 !self.is_public()
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use rstest::rstest;
113 use serde_json;
114
115 use super::*;
116
117 #[rstest]
118 #[case(HyperliquidWsChannel::Trades, r#""trades""#)]
119 #[case(HyperliquidWsChannel::L2Book, r#""l2Book""#)]
120 #[case(HyperliquidWsChannel::UserFills, r#""userFills""#)]
121 #[case(HyperliquidWsChannel::Bbo, r#""bbo""#)]
122 #[case(
123 HyperliquidWsChannel::SubscriptionResponse,
124 r#""subscriptionResponse""#
125 )]
126 fn test_channel_serialization(#[case] channel: HyperliquidWsChannel, #[case] expected: &str) {
127 assert_eq!(serde_json::to_string(&channel).unwrap(), expected);
128 }
129
130 #[rstest]
131 #[case(r#""trades""#, HyperliquidWsChannel::Trades)]
132 #[case(r#""l2Book""#, HyperliquidWsChannel::L2Book)]
133 #[case(r#""userEvents""#, HyperliquidWsChannel::UserEvents)]
134 #[case(r#""bbo""#, HyperliquidWsChannel::Bbo)]
135 #[case(r#""pong""#, HyperliquidWsChannel::Pong)]
136 fn test_channel_deserialization(#[case] json: &str, #[case] expected: HyperliquidWsChannel) {
137 assert_eq!(
138 serde_json::from_str::<HyperliquidWsChannel>(json).unwrap(),
139 expected
140 );
141 }
142
143 #[rstest]
144 #[case(HyperliquidWsChannel::Trades, "trades")]
145 #[case(HyperliquidWsChannel::L2Book, "l2Book")]
146 #[case(HyperliquidWsChannel::UserFills, "userFills")]
147 #[case(
148 HyperliquidWsChannel::UserNonFundingLedgerUpdates,
149 "userNonFundingLedgerUpdates"
150 )]
151 #[case(HyperliquidWsChannel::Bbo, "bbo")]
152 fn test_as_str_method(#[case] channel: HyperliquidWsChannel, #[case] expected: &str) {
153 assert_eq!(channel.as_str(), expected);
154 }
155
156 #[rstest]
157 fn test_display_trait() {
158 assert_eq!(format!("{}", HyperliquidWsChannel::Trades), "Trades");
159 assert_eq!(format!("{}", HyperliquidWsChannel::L2Book), "L2Book");
160 assert_eq!(format!("{}", HyperliquidWsChannel::UserFills), "UserFills");
161 }
162
163 #[rstest]
164 fn test_is_public_channel() {
165 assert!(HyperliquidWsChannel::Trades.is_public());
166 assert!(HyperliquidWsChannel::L2Book.is_public());
167 assert!(HyperliquidWsChannel::Bbo.is_public());
168 assert!(HyperliquidWsChannel::SubscriptionResponse.is_public());
169 assert!(HyperliquidWsChannel::Pong.is_public());
170
171 assert!(!HyperliquidWsChannel::OrderUpdates.is_public());
172 assert!(!HyperliquidWsChannel::UserEvents.is_public());
173 assert!(!HyperliquidWsChannel::UserFills.is_public());
174 assert!(!HyperliquidWsChannel::UserFundings.is_public());
175 assert!(!HyperliquidWsChannel::UserNonFundingLedgerUpdates.is_public());
176 assert!(!HyperliquidWsChannel::Post.is_public());
177 }
178
179 #[rstest]
180 fn test_is_private_channel() {
181 assert!(!HyperliquidWsChannel::Trades.is_private());
182 assert!(!HyperliquidWsChannel::L2Book.is_private());
183 assert!(!HyperliquidWsChannel::Bbo.is_private());
184
185 assert!(HyperliquidWsChannel::OrderUpdates.is_private());
186 assert!(HyperliquidWsChannel::UserEvents.is_private());
187 assert!(HyperliquidWsChannel::UserFills.is_private());
188 assert!(HyperliquidWsChannel::UserFundings.is_private());
189 assert!(HyperliquidWsChannel::UserNonFundingLedgerUpdates.is_private());
190 assert!(HyperliquidWsChannel::Post.is_private());
191 }
192
193 #[rstest]
194 fn test_enum_iter() {
195 use strum::IntoEnumIterator;
196
197 let channels: Vec<HyperliquidWsChannel> = HyperliquidWsChannel::iter().collect();
198 assert_eq!(channels.len(), 15);
199 assert!(channels.contains(&HyperliquidWsChannel::Trades));
200 assert!(channels.contains(&HyperliquidWsChannel::L2Book));
201 assert!(channels.contains(&HyperliquidWsChannel::UserFills));
202 assert!(channels.contains(&HyperliquidWsChannel::Candle));
203 assert!(channels.contains(&HyperliquidWsChannel::AllMids));
204 assert!(channels.contains(&HyperliquidWsChannel::Notification));
205 }
206
207 #[rstest]
208 fn test_from_str() {
209 use std::str::FromStr;
210
211 assert_eq!(
212 HyperliquidWsChannel::from_str("Trades").unwrap(),
213 HyperliquidWsChannel::Trades
214 );
215 assert_eq!(
216 HyperliquidWsChannel::from_str("L2Book").unwrap(),
217 HyperliquidWsChannel::L2Book
218 );
219 assert_eq!(
220 HyperliquidWsChannel::from_str("UserFills").unwrap(),
221 HyperliquidWsChannel::UserFills
222 );
223
224 assert!(HyperliquidWsChannel::from_str("InvalidChannel").is_err());
225 }
226}