rusty_feeder/exchange/binance/spot/data/
subscription_converter.rs

1//! BinanceSubscriptionConverter - Conversion between standardized options and Binance-specific formats
2//!
3//! This module provides functions to convert from the standardized SubscriptionOptions
4//! structure to Binance Spot-specific subscription formats.
5
6use smallvec::SmallVec;
7use smartstring::alias::String;
8use std::fmt::Display;
9
10use super::subscription::{
11    WebSocketSubscribeRequest, create_kline_subscription, create_orderbook_subscription,
12    create_ticker_subscription, create_trade_subscription,
13};
14use crate::provider::prelude::*;
15
16/// Convert from standardized SubscriptionOptions to Binance subscription format
17#[inline]
18pub fn options_to_binance_subscription(options: &SubscriptionOptions) -> WebSocketSubscribeRequest {
19    match options.subscription_type {
20        SubscriptionType::Trade => create_trade_subscription(
21            &options.id,
22            options.symbols.clone(),
23            options.request_id,
24            options.api_key.as_deref(),
25            options.test,
26        ),
27        SubscriptionType::OrderBook => create_orderbook_subscription(
28            &options.id,
29            options.symbols.clone(),
30            options.depth.map(|d| d as usize),
31            options.update_speed_ms,
32            options.request_id,
33            options.api_key.as_deref(),
34            options.test,
35        ),
36        SubscriptionType::Ticker => create_ticker_subscription(
37            &options.id,
38            options.symbols.clone(),
39            options.request_id,
40            options.api_key.as_deref(),
41            options.test,
42        ),
43        SubscriptionType::Kline => {
44            if let Some(interval) = &options.interval {
45                create_kline_subscription(
46                    &options.id,
47                    options.symbols.clone(),
48                    interval,
49                    options.request_id,
50                    options.api_key.as_deref(),
51                    options.test,
52                )
53            } else {
54                // Default to 1m if no interval specified
55                create_kline_subscription(
56                    &options.id,
57                    options.symbols.clone(),
58                    "1m",
59                    options.request_id,
60                    options.api_key.as_deref(),
61                    options.test,
62                )
63            }
64        }
65        _ => WebSocketSubscribeRequest {
66            id: options.id.clone(),
67            method: "SUBSCRIBE".into(),
68            params: SmallVec::<[String; 8]>::new(), // Empty params for unsupported subscription types
69            request_id: options.request_id,
70            api_key: options.api_key.clone(),
71            test: options.test,
72        },
73    }
74}
75
76/// Helper to create stream names with format `<symbol>@<type>`
77#[inline]
78pub fn format_stream_name<S: Display, T: Display>(symbol: S, stream_type: T) -> String {
79    format!("{symbol}@{stream_type}").into()
80}
81
82/// Helper to create aggregate trade stream name
83#[inline]
84pub fn format_trade_stream(symbol: &str) -> String {
85    format_stream_name(symbol.to_lowercase(), "aggTrade")
86}
87
88/// Helper to create order book stream name with specific depth
89#[inline]
90pub fn format_orderbook_stream(
91    symbol: &str,
92    depth: Option<u32>,
93    update_speed: Option<u64>,
94) -> String {
95    let symbol = symbol.to_lowercase();
96
97    // Default depth is regular "depth" (full order book)
98    let depth_suffix = match depth {
99        Some(5) => "depth5",
100        Some(10) => "depth10",
101        Some(20) => "depth20",
102        _ => "depth",
103    };
104
105    // Default update speed is 1000ms (1s)
106    let speed_suffix = match update_speed {
107        Some(100) => "@100ms",
108        _ => "",
109    };
110
111    format!("{symbol}@{depth_suffix}{speed_suffix}").into()
112}
113
114/// Helper to create ticker stream name
115#[inline]
116pub fn format_ticker_stream(symbol: &str) -> String {
117    format_stream_name(symbol.to_lowercase(), "ticker")
118}
119
120/// Helper to create kline stream name with interval
121#[inline]
122pub fn format_kline_stream(symbol: &str, interval: &str) -> String {
123    format!("{}@kline_{}", symbol.to_lowercase(), interval).into()
124}