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 = "orderUpdates")]
43 OrderUpdates,
44 #[serde(rename = "userEvents")]
45 UserEvents,
46 #[serde(rename = "userFills")]
47 UserFills,
48 #[serde(rename = "userFundings")]
49 UserFundings,
50 #[serde(rename = "userNonFundingLedgerUpdates")]
51 UserNonFundingLedgerUpdates,
52 #[serde(rename = "post")]
53 Post,
54 #[serde(rename = "pong")]
55 Pong,
56}
57
58impl HyperliquidWsChannel {
59 pub fn as_str(&self) -> &'static str {
61 match self {
62 Self::SubscriptionResponse => "subscriptionResponse",
63 Self::Trades => "trades",
64 Self::L2Book => "l2Book",
65 Self::Bbo => "bbo",
66 Self::OrderUpdates => "orderUpdates",
67 Self::UserEvents => "userEvents",
68 Self::UserFills => "userFills",
69 Self::UserFundings => "userFundings",
70 Self::UserNonFundingLedgerUpdates => "userNonFundingLedgerUpdates",
71 Self::Post => "post",
72 Self::Pong => "pong",
73 }
74 }
75
76 pub fn is_public(&self) -> bool {
78 matches!(
79 self,
80 Self::SubscriptionResponse | Self::Trades | Self::L2Book | Self::Bbo | Self::Pong
81 )
82 }
83
84 pub fn is_private(&self) -> bool {
86 !self.is_public()
87 }
88}
89
90#[cfg(test)]
95mod tests {
96 use rstest::rstest;
97 use serde_json;
98
99 use super::*;
100
101 #[rstest]
102 #[case(HyperliquidWsChannel::Trades, r#""trades""#)]
103 #[case(HyperliquidWsChannel::L2Book, r#""l2Book""#)]
104 #[case(HyperliquidWsChannel::UserFills, r#""userFills""#)]
105 #[case(HyperliquidWsChannel::Bbo, r#""bbo""#)]
106 #[case(
107 HyperliquidWsChannel::SubscriptionResponse,
108 r#""subscriptionResponse""#
109 )]
110 fn test_channel_serialization(#[case] channel: HyperliquidWsChannel, #[case] expected: &str) {
111 assert_eq!(serde_json::to_string(&channel).unwrap(), expected);
112 }
113
114 #[rstest]
115 #[case(r#""trades""#, HyperliquidWsChannel::Trades)]
116 #[case(r#""l2Book""#, HyperliquidWsChannel::L2Book)]
117 #[case(r#""userEvents""#, HyperliquidWsChannel::UserEvents)]
118 #[case(r#""bbo""#, HyperliquidWsChannel::Bbo)]
119 #[case(r#""pong""#, HyperliquidWsChannel::Pong)]
120 fn test_channel_deserialization(#[case] json: &str, #[case] expected: HyperliquidWsChannel) {
121 assert_eq!(
122 serde_json::from_str::<HyperliquidWsChannel>(json).unwrap(),
123 expected
124 );
125 }
126
127 #[rstest]
128 #[case(HyperliquidWsChannel::Trades, "trades")]
129 #[case(HyperliquidWsChannel::L2Book, "l2Book")]
130 #[case(HyperliquidWsChannel::UserFills, "userFills")]
131 #[case(
132 HyperliquidWsChannel::UserNonFundingLedgerUpdates,
133 "userNonFundingLedgerUpdates"
134 )]
135 #[case(HyperliquidWsChannel::Bbo, "bbo")]
136 fn test_as_str_method(#[case] channel: HyperliquidWsChannel, #[case] expected: &str) {
137 assert_eq!(channel.as_str(), expected);
138 }
139
140 #[test]
141 fn test_display_trait() {
142 assert_eq!(format!("{}", HyperliquidWsChannel::Trades), "Trades");
143 assert_eq!(format!("{}", HyperliquidWsChannel::L2Book), "L2Book");
144 assert_eq!(format!("{}", HyperliquidWsChannel::UserFills), "UserFills");
145 }
146
147 #[test]
148 fn test_is_public_channel() {
149 assert!(HyperliquidWsChannel::Trades.is_public());
150 assert!(HyperliquidWsChannel::L2Book.is_public());
151 assert!(HyperliquidWsChannel::Bbo.is_public());
152 assert!(HyperliquidWsChannel::SubscriptionResponse.is_public());
153 assert!(HyperliquidWsChannel::Pong.is_public());
154
155 assert!(!HyperliquidWsChannel::OrderUpdates.is_public());
156 assert!(!HyperliquidWsChannel::UserEvents.is_public());
157 assert!(!HyperliquidWsChannel::UserFills.is_public());
158 assert!(!HyperliquidWsChannel::UserFundings.is_public());
159 assert!(!HyperliquidWsChannel::UserNonFundingLedgerUpdates.is_public());
160 assert!(!HyperliquidWsChannel::Post.is_public());
161 }
162
163 #[test]
164 fn test_is_private_channel() {
165 assert!(!HyperliquidWsChannel::Trades.is_private());
166 assert!(!HyperliquidWsChannel::L2Book.is_private());
167 assert!(!HyperliquidWsChannel::Bbo.is_private());
168
169 assert!(HyperliquidWsChannel::OrderUpdates.is_private());
170 assert!(HyperliquidWsChannel::UserEvents.is_private());
171 assert!(HyperliquidWsChannel::UserFills.is_private());
172 assert!(HyperliquidWsChannel::UserFundings.is_private());
173 assert!(HyperliquidWsChannel::UserNonFundingLedgerUpdates.is_private());
174 assert!(HyperliquidWsChannel::Post.is_private());
175 }
176
177 #[test]
178 fn test_enum_iter() {
179 use strum::IntoEnumIterator;
180
181 let channels: Vec<HyperliquidWsChannel> = HyperliquidWsChannel::iter().collect();
182 assert_eq!(channels.len(), 11);
183 assert!(channels.contains(&HyperliquidWsChannel::Trades));
184 assert!(channels.contains(&HyperliquidWsChannel::L2Book));
185 assert!(channels.contains(&HyperliquidWsChannel::UserFills));
186 }
187
188 #[test]
189 fn test_from_str() {
190 use std::str::FromStr;
191
192 assert_eq!(
193 HyperliquidWsChannel::from_str("Trades").unwrap(),
194 HyperliquidWsChannel::Trades
195 );
196 assert_eq!(
197 HyperliquidWsChannel::from_str("L2Book").unwrap(),
198 HyperliquidWsChannel::L2Book
199 );
200 assert_eq!(
201 HyperliquidWsChannel::from_str("UserFills").unwrap(),
202 HyperliquidWsChannel::UserFills
203 );
204
205 assert!(HyperliquidWsChannel::from_str("InvalidChannel").is_err());
206 }
207}