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)]
115mod tests {
116 use rstest::rstest;
117 use serde_json;
118
119 use super::*;
120
121 #[rstest]
122 #[case(HyperliquidWsChannel::Trades, r#""trades""#)]
123 #[case(HyperliquidWsChannel::L2Book, r#""l2Book""#)]
124 #[case(HyperliquidWsChannel::UserFills, r#""userFills""#)]
125 #[case(HyperliquidWsChannel::Bbo, r#""bbo""#)]
126 #[case(
127 HyperliquidWsChannel::SubscriptionResponse,
128 r#""subscriptionResponse""#
129 )]
130 fn test_channel_serialization(#[case] channel: HyperliquidWsChannel, #[case] expected: &str) {
131 assert_eq!(serde_json::to_string(&channel).unwrap(), expected);
132 }
133
134 #[rstest]
135 #[case(r#""trades""#, HyperliquidWsChannel::Trades)]
136 #[case(r#""l2Book""#, HyperliquidWsChannel::L2Book)]
137 #[case(r#""userEvents""#, HyperliquidWsChannel::UserEvents)]
138 #[case(r#""bbo""#, HyperliquidWsChannel::Bbo)]
139 #[case(r#""pong""#, HyperliquidWsChannel::Pong)]
140 fn test_channel_deserialization(#[case] json: &str, #[case] expected: HyperliquidWsChannel) {
141 assert_eq!(
142 serde_json::from_str::<HyperliquidWsChannel>(json).unwrap(),
143 expected
144 );
145 }
146
147 #[rstest]
148 #[case(HyperliquidWsChannel::Trades, "trades")]
149 #[case(HyperliquidWsChannel::L2Book, "l2Book")]
150 #[case(HyperliquidWsChannel::UserFills, "userFills")]
151 #[case(
152 HyperliquidWsChannel::UserNonFundingLedgerUpdates,
153 "userNonFundingLedgerUpdates"
154 )]
155 #[case(HyperliquidWsChannel::Bbo, "bbo")]
156 fn test_as_str_method(#[case] channel: HyperliquidWsChannel, #[case] expected: &str) {
157 assert_eq!(channel.as_str(), expected);
158 }
159
160 #[rstest]
161 fn test_display_trait() {
162 assert_eq!(format!("{}", HyperliquidWsChannel::Trades), "Trades");
163 assert_eq!(format!("{}", HyperliquidWsChannel::L2Book), "L2Book");
164 assert_eq!(format!("{}", HyperliquidWsChannel::UserFills), "UserFills");
165 }
166
167 #[rstest]
168 fn test_is_public_channel() {
169 assert!(HyperliquidWsChannel::Trades.is_public());
170 assert!(HyperliquidWsChannel::L2Book.is_public());
171 assert!(HyperliquidWsChannel::Bbo.is_public());
172 assert!(HyperliquidWsChannel::SubscriptionResponse.is_public());
173 assert!(HyperliquidWsChannel::Pong.is_public());
174
175 assert!(!HyperliquidWsChannel::OrderUpdates.is_public());
176 assert!(!HyperliquidWsChannel::UserEvents.is_public());
177 assert!(!HyperliquidWsChannel::UserFills.is_public());
178 assert!(!HyperliquidWsChannel::UserFundings.is_public());
179 assert!(!HyperliquidWsChannel::UserNonFundingLedgerUpdates.is_public());
180 assert!(!HyperliquidWsChannel::Post.is_public());
181 }
182
183 #[rstest]
184 fn test_is_private_channel() {
185 assert!(!HyperliquidWsChannel::Trades.is_private());
186 assert!(!HyperliquidWsChannel::L2Book.is_private());
187 assert!(!HyperliquidWsChannel::Bbo.is_private());
188
189 assert!(HyperliquidWsChannel::OrderUpdates.is_private());
190 assert!(HyperliquidWsChannel::UserEvents.is_private());
191 assert!(HyperliquidWsChannel::UserFills.is_private());
192 assert!(HyperliquidWsChannel::UserFundings.is_private());
193 assert!(HyperliquidWsChannel::UserNonFundingLedgerUpdates.is_private());
194 assert!(HyperliquidWsChannel::Post.is_private());
195 }
196
197 #[rstest]
198 fn test_enum_iter() {
199 use strum::IntoEnumIterator;
200
201 let channels: Vec<HyperliquidWsChannel> = HyperliquidWsChannel::iter().collect();
202 assert_eq!(channels.len(), 15);
203 assert!(channels.contains(&HyperliquidWsChannel::Trades));
204 assert!(channels.contains(&HyperliquidWsChannel::L2Book));
205 assert!(channels.contains(&HyperliquidWsChannel::UserFills));
206 assert!(channels.contains(&HyperliquidWsChannel::Candle));
207 assert!(channels.contains(&HyperliquidWsChannel::AllMids));
208 assert!(channels.contains(&HyperliquidWsChannel::Notification));
209 }
210
211 #[rstest]
212 fn test_from_str() {
213 use std::str::FromStr;
214
215 assert_eq!(
216 HyperliquidWsChannel::from_str("Trades").unwrap(),
217 HyperliquidWsChannel::Trades
218 );
219 assert_eq!(
220 HyperliquidWsChannel::from_str("L2Book").unwrap(),
221 HyperliquidWsChannel::L2Book
222 );
223 assert_eq!(
224 HyperliquidWsChannel::from_str("UserFills").unwrap(),
225 HyperliquidWsChannel::UserFills
226 );
227
228 assert!(HyperliquidWsChannel::from_str("InvalidChannel").is_err());
229 }
230}