Skip to main content

bybit/ws/
config.rs

1use std::time::Duration;
2
3use crate::{Category, Environment, SensitiveString, ServerClock, Timestamp};
4
5/// Default interval of the application-level heartbeat ping.
6pub const DEFAULT_PING_INTERVAL: Duration = Duration::from_secs(20);
7/// Default time to wait for the heartbeat reply before reconnecting.
8pub const DEFAULT_PONG_TIMEOUT: Duration = Duration::from_secs(10);
9/// Default timeout of the TCP/TLS/WebSocket handshake.
10pub const DEFAULT_CONNECT_TIMEOUT: Duration = Duration::from_secs(10);
11/// Default time [`TradeClient`](crate::ws::TradeClient) waits for a reply.
12pub const DEFAULT_REQUEST_TIMEOUT: Duration = Duration::from_secs(10);
13/// Default validity of the stream `auth` message, milliseconds.
14pub const DEFAULT_AUTH_RECV_WINDOW: Timestamp = 5_000;
15
16/// Configuration of a [`Stream`](crate::ws::Stream); start with [`Config::public`], [`Config::private`] or [`Config::new`].
17#[derive(Debug, Clone)]
18pub struct Config {
19    /// WebSocket server URL
20    pub url: String,
21
22    /// Maximum number of pending commands (backpressure)
23    pub command_queue_size: usize,
24
25    /// Maximum number of buffered events (backpressure)
26    pub event_queue_size: usize,
27
28    /// Maximum number of consecutive reconnect attempts without a successful
29    /// connection (0 = no reconnect). The counter resets once a connection is
30    /// established.
31    pub max_reconnect_attempts: u32,
32
33    /// Base delay between reconnect attempts
34    pub reconnect_base_delay: Duration,
35
36    /// Maximum delay cap for exponential back-off
37    pub reconnect_max_delay: Duration,
38
39    /// How long to wait for a clean close handshake
40    pub close_timeout: Duration,
41
42    /// How long to wait for the TCP/TLS/WebSocket handshake to complete.
43    pub connect_timeout: Duration,
44
45    /// How often to send a Ping frame to the server.
46    /// `None` disables the heartbeat entirely.
47    pub ping_interval: Option<Duration>,
48
49    /// How long to wait for a Pong after sending a Ping before treating the
50    /// connection as dead and triggering a reconnect.
51    /// Ignored when `ping_interval` is `None`.
52    pub pong_timeout: Duration,
53
54    /// API key for private streams. With [`Config::api_secret`] set, the
55    /// driver authenticates on every (re)connect before subscribing.
56    pub api_key: Option<SensitiveString>,
57
58    /// API secret for private streams (see [`Config::api_key`]).
59    pub api_secret: Option<SensitiveString>,
60
61    /// How long the `auth` message (and, for
62    /// [`TradeClient`](crate::ws::TradeClient), each order entry request)
63    /// stays valid, milliseconds.
64    pub auth_recv_window: Timestamp,
65
66    /// Clock used for the `auth` expiry; share
67    /// [`http::Client::clock`](crate::http::Client::clock) to use the offset
68    /// measured by `sync_time`.
69    pub server_clock: ServerClock,
70
71    /// How long [`TradeClient`](crate::ws::TradeClient) waits for the reply
72    /// to an order entry request.
73    pub request_timeout: Duration,
74}
75
76impl Default for Config {
77    fn default() -> Self {
78        Self {
79            url: String::new(),
80            command_queue_size: 64,
81            event_queue_size: 256,
82            max_reconnect_attempts: 5,
83            reconnect_base_delay: Duration::from_millis(500),
84            reconnect_max_delay: Duration::from_secs(30),
85            close_timeout: Duration::from_secs(5),
86            connect_timeout: DEFAULT_CONNECT_TIMEOUT,
87            ping_interval: Some(DEFAULT_PING_INTERVAL),
88            pong_timeout: DEFAULT_PONG_TIMEOUT,
89            api_key: None,
90            api_secret: None,
91            auth_recv_window: DEFAULT_AUTH_RECV_WINDOW,
92            server_clock: ServerClock::new(),
93            request_timeout: DEFAULT_REQUEST_TIMEOUT,
94        }
95    }
96}
97
98impl Config {
99    /// Config for a stream URL, e.g. `wss://stream.bybit.com/v5/public/linear`, with default settings.
100    pub fn new(url: impl Into<String>) -> Self {
101        Self {
102            url: url.into(),
103            ..Default::default()
104        }
105    }
106
107    /// Config for the public stream of `category` in `env`.
108    pub fn public(env: Environment, category: Category) -> Self {
109        Self::new(env.public_stream_url(category))
110    }
111
112    /// Config for the order entry stream of `env`, used by
113    /// [`TradeClient`](crate::ws::TradeClient). Fails where Bybit offers no
114    /// order entry stream (see [`Environment::trade_stream_url`]).
115    pub fn trade(env: Environment) -> Result<Self, crate::ws::Error> {
116        env.trade_stream_url().map(Self::new).ok_or_else(|| {
117            crate::ws::Error::InvalidUrl(format!("{env:?} has no order entry stream"))
118        })
119    }
120
121    /// Config for the private stream (orders, positions, executions,
122    /// wallet) in `env`.
123    pub fn private(env: Environment) -> Self {
124        Self::new(env.private_stream_url())
125    }
126
127    /// Maximum number of pending commands; further commands wait
128    /// (or fail with `QueueFull` for `try_*`).
129    pub fn command_queue_size(mut self, n: usize) -> Self {
130        self.command_queue_size = n;
131        self
132    }
133
134    /// Maximum number of buffered events; data events beyond it are dropped
135    /// and reported by [`Event::Lagged`](crate::ws::Event::Lagged).
136    pub fn event_queue_size(mut self, n: usize) -> Self {
137        self.event_queue_size = n;
138        self
139    }
140
141    /// Maximum consecutive reconnect attempts without a successful
142    /// connection; 0 disables reconnecting.
143    pub fn max_reconnect_attempts(mut self, n: u32) -> Self {
144        self.max_reconnect_attempts = n;
145        self
146    }
147
148    /// Delay before the first reconnect attempt; it doubles per attempt.
149    pub fn reconnect_base_delay(mut self, d: Duration) -> Self {
150        self.reconnect_base_delay = d;
151        self
152    }
153
154    /// Upper bound of the reconnect delay.
155    pub fn reconnect_max_delay(mut self, d: Duration) -> Self {
156        self.reconnect_max_delay = d;
157        self
158    }
159
160    /// How long to wait for the close handshake on disconnect.
161    pub fn close_timeout(mut self, d: Duration) -> Self {
162        self.close_timeout = d;
163        self
164    }
165
166    /// Timeout of the TCP/TLS/WebSocket handshake.
167    pub fn connect_timeout(mut self, d: Duration) -> Self {
168        self.connect_timeout = d;
169        self
170    }
171
172    /// Heartbeat interval; `None` disables the heartbeat.
173    pub fn ping_interval(mut self, d: Option<Duration>) -> Self {
174        self.ping_interval = d;
175        self
176    }
177
178    /// How long to wait for the heartbeat reply before reconnecting.
179    pub fn pong_timeout(mut self, d: Duration) -> Self {
180        self.pong_timeout = d;
181        self
182    }
183
184    /// Credentials for a private stream: the driver sends `auth` on every
185    /// (re)connect and subscribes only after it succeeded.
186    pub fn credentials(
187        mut self,
188        api_key: impl Into<SensitiveString>,
189        api_secret: impl Into<SensitiveString>,
190    ) -> Self {
191        self.api_key = Some(api_key.into());
192        self.api_secret = Some(api_secret.into());
193        self
194    }
195
196    /// Validity of the `auth` message, milliseconds.
197    pub fn auth_recv_window(mut self, recv_window: Timestamp) -> Self {
198        self.auth_recv_window = recv_window;
199        self
200    }
201
202    /// How long [`TradeClient`](crate::ws::TradeClient) waits for a reply.
203    pub fn request_timeout(mut self, d: Duration) -> Self {
204        self.request_timeout = d;
205        self
206    }
207
208    /// Clock for the `auth` expiry, e.g. `client.clock()`.
209    pub fn server_clock(mut self, clock: ServerClock) -> Self {
210        self.server_clock = clock;
211        self
212    }
213}