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}