nautilus_binance/spot/websocket/trading/messages.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//! Binance Spot WebSocket API message types.
17//!
18//! This module defines:
19//! - [`BinanceSpotWsTradingCommand`]: Commands sent from the client to the handler.
20//! - [`BinanceSpotWsTradingMessage`]: Output messages emitted by the handler to the client.
21//! - Request/response structures for the Binance Spot WebSocket Trading API.
22
23use nautilus_network::websocket::WebSocketClient;
24use serde::{Deserialize, Serialize};
25
26use super::user_data::{
27 BinanceSpotAccountPositionMsg, BinanceSpotBalanceUpdateMsg, BinanceSpotExecutionReport,
28 BinanceSpotListStatus,
29};
30use crate::spot::http::{
31 models::{
32 BinanceCancelOpenOrdersResponse, BinanceCancelOrderResponse, BinanceNewOrderResponse,
33 },
34 query::{CancelOrderParams, CancelReplaceOrderParams, NewOrderParams},
35};
36
37/// Commands sent from the outer client to the inner handler.
38///
39/// The handler runs in a dedicated Tokio task and processes these commands
40/// to perform WebSocket API operations (request/response pattern).
41#[allow(
42 missing_debug_implementations,
43 clippy::large_enum_variant,
44 reason = "Commands are ephemeral and immediately consumed"
45)]
46pub enum BinanceSpotWsTradingCommand {
47 /// Sets the WebSocket client after connection.
48 SetClient(WebSocketClient),
49 /// Disconnects and cleans up.
50 Disconnect,
51 /// Places a new order.
52 PlaceOrder {
53 /// Request ID for correlation.
54 id: String,
55 /// Order parameters.
56 params: NewOrderParams,
57 },
58 /// Cancels an order.
59 CancelOrder {
60 /// Request ID for correlation.
61 id: String,
62 /// Cancel parameters.
63 params: CancelOrderParams,
64 },
65 /// Cancels and replaces an order atomically.
66 CancelReplaceOrder {
67 /// Request ID for correlation.
68 id: String,
69 /// Cancel-replace parameters.
70 params: CancelReplaceOrderParams,
71 },
72 /// Cancels all open orders for a symbol.
73 CancelAllOrders {
74 /// Request ID for correlation.
75 id: String,
76 /// Symbol to cancel all orders for.
77 symbol: String,
78 },
79 /// Authenticates the WebSocket session via `session.logon`.
80 SessionLogon,
81 /// Subscribes to the user data stream via `userDataStream.subscribe`.
82 SubscribeUserData,
83}
84
85/// Normalized output message from the WebSocket API handler.
86///
87/// These messages are emitted by the handler and consumed by the client
88/// for routing to callers or the execution engine.
89#[derive(Debug, Clone)]
90pub enum BinanceSpotWsTradingMessage {
91 /// Connection established.
92 Connected,
93 /// Session authenticated successfully.
94 Authenticated,
95 /// Session authentication was rejected or could not be sent.
96 AuthenticationRejected(String),
97 /// Connection was re-established after disconnect.
98 Reconnected,
99 /// Order accepted by venue.
100 OrderAccepted {
101 /// Request ID for correlation.
102 request_id: String,
103 /// Order response from venue.
104 response: BinanceNewOrderResponse,
105 },
106 /// Order rejected by venue.
107 OrderRejected {
108 /// Request ID for correlation.
109 request_id: String,
110 /// Venue response status.
111 status: u16,
112 /// Error code from venue.
113 code: i32,
114 /// Error message from venue.
115 msg: String,
116 },
117 /// Order canceled successfully.
118 OrderCanceled {
119 /// Request ID for correlation.
120 request_id: String,
121 /// Cancel response from venue.
122 response: BinanceCancelOrderResponse,
123 },
124 /// Cancel rejected by venue.
125 CancelRejected {
126 /// Request ID for correlation.
127 request_id: String,
128 /// Venue response status.
129 status: u16,
130 /// Error code from venue.
131 code: i32,
132 /// Error message from venue.
133 msg: String,
134 },
135 /// Cancel-replace response (new order after cancel).
136 CancelReplaceAccepted {
137 /// Request ID for correlation.
138 request_id: String,
139 /// Cancel response.
140 cancel_response: BinanceCancelOrderResponse,
141 /// New order response.
142 new_order_response: BinanceNewOrderResponse,
143 },
144 /// Cancel-replace rejected.
145 CancelReplaceRejected {
146 /// Request ID for correlation.
147 request_id: String,
148 /// Venue response status.
149 status: u16,
150 /// Error code from venue.
151 code: i32,
152 /// Error message from venue.
153 msg: String,
154 },
155 /// Request failed without a structured venue response.
156 RequestFailed {
157 /// Request ID for correlation.
158 request_id: String,
159 /// Failure reason.
160 msg: String,
161 },
162 /// All orders canceled for a symbol.
163 AllOrdersCanceled {
164 /// Request ID for correlation.
165 request_id: String,
166 /// Canceled order responses.
167 responses: Vec<BinanceCancelOpenOrdersResponse>,
168 },
169 /// User data stream subscribed.
170 UserDataSubscribed {
171 /// Subscription ID from Binance.
172 subscription_id: String,
173 },
174 /// User data subscription was rejected or could not be sent.
175 UserDataSubscriptionRejected(String),
176 /// Order execution report from user data stream.
177 ExecutionReport(Box<BinanceSpotExecutionReport>),
178 /// Order-list lifecycle update from user data stream.
179 ListStatus(BinanceSpotListStatus),
180 /// Account position update from user data stream.
181 AccountPosition(BinanceSpotAccountPositionMsg),
182 /// Balance update from user data stream.
183 BalanceUpdate(BinanceSpotBalanceUpdateMsg),
184 /// Server shutdown notice (sent ~10 minutes before disconnection).
185 ServerShutdown {
186 /// Event time in milliseconds.
187 event_time: i64,
188 },
189 /// Error from venue or network.
190 Error(String),
191}
192
193/// Metadata for a pending request.
194///
195/// Stored in the handler to match responses to their originating requests.
196#[derive(Debug, Clone, Copy)]
197pub enum BinanceSpotWsTradingRequestMeta {
198 /// Pending order placement.
199 PlaceOrder,
200 /// Pending order cancellation.
201 CancelOrder,
202 /// Pending cancel-replace.
203 CancelReplaceOrder,
204 /// Pending cancel-all.
205 CancelAllOrders,
206 /// Pending session logon.
207 SessionLogon,
208 /// Pending user data subscription.
209 SubscribeUserData,
210}
211
212/// WebSocket API request wrapper.
213///
214/// Requests are sent as JSON text frames, responses come back as SBE binary.
215#[derive(Debug, Clone, Serialize)]
216pub struct BinanceSpotWsTradingRequest {
217 /// Unique request ID for correlation.
218 pub id: String,
219 /// API method name (e.g., "order.place").
220 pub method: String,
221 /// Request parameters.
222 pub params: serde_json::Value,
223}
224
225impl BinanceSpotWsTradingRequest {
226 /// Creates a new WebSocket API request.
227 #[must_use]
228 pub fn new(
229 id: impl Into<String>,
230 method: impl Into<String>,
231 params: serde_json::Value,
232 ) -> Self {
233 Self {
234 id: id.into(),
235 method: method.into(),
236 params,
237 }
238 }
239}
240
241/// WebSocket API error response (JSON).
242#[derive(Debug, Clone, Deserialize)]
243pub struct BinanceSpotWsTradingResponseError {
244 /// Error code from venue.
245 pub code: i32,
246 /// Error message from venue.
247 pub msg: String,
248 /// Request ID if available.
249 pub id: Option<String>,
250}
251
252/// WebSocket API method names.
253pub mod method {
254 /// Places a new order.
255 pub const ORDER_PLACE: &str = "order.place";
256 /// Cancels an order.
257 pub const ORDER_CANCEL: &str = "order.cancel";
258 /// Cancels and replaces an order.
259 pub const ORDER_CANCEL_REPLACE: &str = "order.cancelReplace";
260 /// Cancels all open orders for a symbol.
261 pub const OPEN_ORDERS_CANCEL_ALL: &str = "openOrders.cancelAll";
262 /// Initiates session logon.
263 pub const SESSION_LOGON: &str = "session.logon";
264 /// Queries session status.
265 pub const SESSION_STATUS: &str = "session.status";
266 /// Initiates session logout.
267 pub const SESSION_LOGOUT: &str = "session.logout";
268}