rusty_feeder/exchange/coinbase/data/
subscription.rs

1use serde::{Deserialize, Serialize};
2use smartstring::alias::String;
3
4/// Coinbase WebSocket channel types
5#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
6#[serde(rename_all = "lowercase")]
7pub enum ChannelType {
8    /// Ticker channel for price updates
9    #[serde(rename = "ticker")]
10    Ticker,
11    /// Level2 channel for order book updates
12    #[serde(rename = "level2")]
13    Level2,
14    /// Matches channel for trade data
15    #[serde(rename = "matches")]
16    Matches,
17    /// Heartbeat channel for connection monitoring
18    #[serde(rename = "heartbeat")]
19    Heartbeat,
20    /// Status channel for exchange status updates
21    #[serde(rename = "status")]
22    Status,
23}
24
25/// Coinbase WebSocket subscription message
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct SubscriptionMessage {
28    /// Message type (always "subscribe")
29    #[serde(rename = "type")]
30    pub message_type: String,
31    /// List of channels to subscribe to
32    pub channels: Vec<SubscriptionChannel>,
33}
34
35/// Coinbase WebSocket subscription channel
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct SubscriptionChannel {
38    /// Channel name (ticker, level2, matches, heartbeat, status)
39    pub name: String,
40    /// List of product IDs to subscribe to
41    pub product_ids: Vec<String>,
42}
43
44impl SubscriptionMessage {
45    /// Create a new subscription message
46    #[must_use]
47    pub fn new(channels: Vec<SubscriptionChannel>) -> Self {
48        Self {
49            message_type: "subscribe".into(),
50            channels,
51        }
52    }
53
54    /// Create a subscription for trade data
55    #[must_use]
56    pub fn trades(product_ids: Vec<String>) -> Self {
57        let channel = SubscriptionChannel {
58            name: "matches".into(),
59            product_ids: product_ids.into_iter().collect(),
60        };
61
62        Self::new(vec![channel])
63    }
64
65    /// Create a subscription for order book data
66    #[must_use]
67    pub fn orderbook(product_ids: Vec<String>) -> Self {
68        let channel = SubscriptionChannel {
69            name: "level2".into(),
70            product_ids: product_ids.into_iter().collect(),
71        };
72
73        Self::new(vec![channel])
74    }
75
76    /// Create a subscription for ticker data
77    #[must_use]
78    pub fn ticker(product_ids: Vec<String>) -> Self {
79        let channel = SubscriptionChannel {
80            name: "ticker".into(),
81            product_ids: product_ids.into_iter().collect(),
82        };
83
84        Self::new(vec![channel])
85    }
86
87    /// Create a heartbeat subscription
88    #[must_use]
89    pub fn heartbeat(product_ids: Vec<String>) -> Self {
90        let channel = SubscriptionChannel {
91            name: "heartbeat".into(),
92            product_ids: product_ids.into_iter().collect(),
93        };
94
95        Self::new(vec![channel])
96    }
97}
98
99/// Coinbase WebSocket unsubscribe message
100#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct UnsubscribeMessage {
102    /// Message type (always "unsubscribe")
103    #[serde(rename = "type")]
104    pub message_type: String,
105    /// List of channel names to unsubscribe from
106    pub channels: Vec<String>,
107}
108
109impl UnsubscribeMessage {
110    /// Create a new unsubscribe message
111    #[must_use]
112    pub fn new(channels: Vec<String>) -> Self {
113        Self {
114            message_type: "unsubscribe".into(),
115            channels,
116        }
117    }
118}