polyoxide_clob/ws/
subscription.rs1use serde::{Deserialize, Serialize};
4
5use super::auth::ApiCredentials;
6
7pub const WS_MARKET_URL: &str = "wss://ws-subscriptions-clob.polymarket.com/ws/market";
9
10pub const WS_USER_URL: &str = "wss://ws-subscriptions-clob.polymarket.com/ws/user";
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
15#[serde(rename_all = "lowercase")]
16pub enum ChannelType {
17 Market,
19 User,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
25pub struct MarketSubscription {
26 pub assets_ids: Vec<String>,
28 #[serde(rename = "type")]
30 pub channel_type: ChannelType,
31}
32
33impl MarketSubscription {
34 pub fn new(assets_ids: Vec<String>) -> Self {
36 Self {
37 assets_ids,
38 channel_type: ChannelType::Market,
39 }
40 }
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize)]
45pub struct UserSubscription {
46 pub markets: Vec<String>,
48 pub auth: ApiCredentials,
50 #[serde(rename = "type")]
52 pub channel_type: ChannelType,
53}
54
55impl UserSubscription {
56 pub fn new(markets: Vec<String>, credentials: ApiCredentials) -> Self {
58 Self {
59 markets,
60 auth: credentials,
61 channel_type: ChannelType::User,
62 }
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn channel_type_serialization() {
72 let market = serde_json::to_value(ChannelType::Market).unwrap();
73 let user = serde_json::to_value(ChannelType::User).unwrap();
74
75 assert_eq!(market, "market");
76 assert_eq!(user, "user");
77 }
78
79 #[test]
80 fn channel_type_deserialization() {
81 let market: ChannelType = serde_json::from_str("\"market\"").unwrap();
82 let user: ChannelType = serde_json::from_str("\"user\"").unwrap();
83
84 assert_eq!(market, ChannelType::Market);
85 assert_eq!(user, ChannelType::User);
86 }
87
88 #[test]
89 fn channel_type_rejects_uppercase() {
90 let result = serde_json::from_str::<ChannelType>("\"MARKET\"");
91 assert!(result.is_err(), "Should reject uppercase channel type");
92 }
93
94 #[test]
95 fn market_subscription_new_sets_channel_type() {
96 let sub = MarketSubscription::new(vec!["asset1".into(), "asset2".into()]);
97 assert_eq!(sub.channel_type, ChannelType::Market);
98 assert_eq!(sub.assets_ids.len(), 2);
99 assert_eq!(sub.assets_ids[0], "asset1");
100 assert_eq!(sub.assets_ids[1], "asset2");
101 }
102
103 #[test]
104 fn market_subscription_serialization() {
105 let sub = MarketSubscription::new(vec!["token123".into()]);
106 let json = serde_json::to_value(&sub).unwrap();
107
108 assert_eq!(json["type"], "market");
109 assert_eq!(json["assets_ids"][0], "token123");
110 }
111
112 #[test]
113 fn market_subscription_empty_assets() {
114 let sub = MarketSubscription::new(vec![]);
115 let json = serde_json::to_value(&sub).unwrap();
116
117 assert_eq!(json["type"], "market");
118 assert!(json["assets_ids"].as_array().unwrap().is_empty());
119 }
120
121 #[test]
122 fn user_subscription_new_sets_channel_type() {
123 let creds = ApiCredentials::new("key", "secret", "pass");
124 let sub = UserSubscription::new(vec!["cond1".into()], creds);
125 assert_eq!(sub.channel_type, ChannelType::User);
126 assert_eq!(sub.markets.len(), 1);
127 assert_eq!(sub.markets[0], "cond1");
128 }
129
130 #[test]
131 fn user_subscription_serialization() {
132 let creds = ApiCredentials::new("my_key", "my_secret", "my_pass");
133 let sub = UserSubscription::new(vec!["market1".into(), "market2".into()], creds);
134 let json = serde_json::to_value(&sub).unwrap();
135
136 assert_eq!(json["type"], "user");
137 assert_eq!(json["markets"][0], "market1");
138 assert_eq!(json["markets"][1], "market2");
139 assert_eq!(json["auth"]["apiKey"], "my_key");
140 assert_eq!(json["auth"]["secret"], "my_secret");
141 assert_eq!(json["auth"]["passphrase"], "my_pass");
142 }
143
144 #[test]
145 fn ws_url_constants() {
146 assert!(WS_MARKET_URL.starts_with("wss://"));
147 assert!(WS_MARKET_URL.contains("market"));
148 assert!(WS_USER_URL.starts_with("wss://"));
149 assert!(WS_USER_URL.contains("user"));
150 }
151}