Skip to main content

nautilus_binance/spot/websocket/streams/
subscription.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Stream subscription management for Binance Spot WebSocket.
17//!
18//! ## Stream Names
19//!
20//! - `<symbol>@trade` - Trade stream
21//! - `<symbol>@bestBidAsk` - Best bid/ask stream (with auto-culling)
22//! - `<symbol>@depth` - Diff depth stream (50ms updates)
23//! - `<symbol>@depth20` - Partial book depth (top 20 levels, 50ms updates)
24//!
25//! ## Connection URL Patterns
26//!
27//! Single stream: `/ws/<streamName>`
28//! Multiple streams: `/stream?streams=<stream1>/<stream2>/...`
29
30/// Maximum number of streams per connection.
31pub const MAX_STREAMS_PER_CONNECTION: usize = 1024;
32
33/// Maximum number of connections per pool.
34pub const MAX_CONNECTIONS: usize = 20;
35
36/// Stream type for subscription management.
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
38pub enum StreamType {
39    /// Trade stream (`<symbol>@trade`).
40    Trade,
41    /// Best bid/ask stream (`<symbol>@bestBidAsk`).
42    BestBidAsk,
43    /// Diff depth stream (`<symbol>@depth`).
44    DepthDiff,
45    /// Partial book depth stream (`<symbol>@depth<N>`).
46    DepthSnapshot { levels: u8 },
47}
48
49impl StreamType {
50    /// Build stream name for a symbol.
51    #[must_use]
52    pub fn stream_name(&self, symbol: &str) -> String {
53        let symbol_lower = symbol.to_lowercase();
54        match self {
55            Self::Trade => format!("{symbol_lower}@trade"),
56            Self::BestBidAsk => format!("{symbol_lower}@bestBidAsk"),
57            Self::DepthDiff => format!("{symbol_lower}@depth"),
58            Self::DepthSnapshot { levels } => format!("{symbol_lower}@depth{levels}"),
59        }
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use rstest::rstest;
66
67    use super::*;
68
69    #[rstest]
70    fn test_stream_names() {
71        assert_eq!(StreamType::Trade.stream_name("BTCUSDT"), "btcusdt@trade");
72        assert_eq!(
73            StreamType::BestBidAsk.stream_name("ETHUSDT"),
74            "ethusdt@bestBidAsk"
75        );
76        assert_eq!(
77            StreamType::DepthDiff.stream_name("BTCUSDT"),
78            "btcusdt@depth"
79        );
80        assert_eq!(
81            StreamType::DepthSnapshot { levels: 20 }.stream_name("BTCUSDT"),
82            "btcusdt@depth20"
83        );
84    }
85}