Skip to main content

bullet_ws_interface/
client.rs

1// The per-action `ORDER.*` variants below are deprecated in favour of
2// `Submit`. Allow `deprecated` within this module so serde's derived impls
3// (which reference every variant) compile cleanly under `-D warnings`;
4// downstream crates still receive the deprecation warning when they use them.
5#![allow(deprecated)]
6
7use serde::{Deserialize, Serialize};
8
9use crate::RequestId;
10
11/// Parameters for a transaction submission.
12#[derive(Serialize, Deserialize, Clone, Debug)]
13pub struct OrderParams {
14    /// Base64-encoded raw transaction bytes
15    pub tx: String,
16}
17
18/// Messages sent from client to server (Binance-style)
19#[derive(Serialize, Deserialize, Clone, Debug)]
20#[serde(tag = "method", rename_all = "SCREAMING_SNAKE_CASE")]
21pub enum ClientMessage {
22    #[serde(alias = "subscribe")]
23    Subscribe {
24        id: Option<RequestId>,
25        #[serde(default)]
26        params: Vec<String>,
27    },
28
29    #[serde(alias = "unsubscribe")]
30    Unsubscribe {
31        id: Option<RequestId>,
32        #[serde(default)]
33        params: Vec<String>,
34    },
35
36    #[serde(alias = "list_subscriptions")]
37    ListSubscriptions { id: Option<RequestId> },
38
39    #[serde(alias = "ping")]
40    Ping { id: Option<RequestId> },
41
42    /// Submit a signed transaction over the rollup WebSocket.
43    ///
44    /// The action — place, cancel, amend, cancel-all, cancel-and-place, etc. —
45    /// is encoded in the signed transaction itself (`bullet-exchange-interface`'s
46    /// `UserAction`); the server decodes the transaction and dispatches on the
47    /// inner action. Prefer this over the per-action `ORDER.*` methods below,
48    /// which restate — without enforcing — the action already in `tx`.
49    #[serde(alias = "submit")]
50    Submit { id: Option<RequestId>, params: OrderParams },
51
52    /// Place an order via the rollup WebSocket.
53    #[deprecated(
54        since = "0.3.0",
55        note = "use `ClientMessage::Submit`; the action is decoded from the signed tx"
56    )]
57    #[serde(alias = "order.place", rename = "ORDER.PLACE")]
58    OrderPlace { id: Option<RequestId>, params: OrderParams },
59
60    /// Cancel an order via the rollup WebSocket.
61    #[deprecated(
62        since = "0.3.0",
63        note = "use `ClientMessage::Submit`; the action is decoded from the signed tx"
64    )]
65    #[serde(alias = "order.cancel", rename = "ORDER.CANCEL")]
66    OrderCancel { id: Option<RequestId>, params: OrderParams },
67
68    /// Amend an order via the rollup WebSocket.
69    #[deprecated(
70        since = "0.3.0",
71        note = "use `ClientMessage::Submit`; the action is decoded from the signed tx"
72    )]
73    #[serde(alias = "order.amend", alias = "order.modify", rename = "ORDER.AMEND")]
74    OrderAmend { id: Option<RequestId>, params: OrderParams },
75
76    /// Cancel all open orders via the rollup WebSocket.
77    #[deprecated(
78        since = "0.3.0",
79        note = "use `ClientMessage::Submit`; the action is decoded from the signed tx"
80    )]
81    #[serde(alias = "order.cancelAll", rename = "ORDER.CANCEL_ALL")]
82    OrderCancelAll { id: Option<RequestId>, params: OrderParams },
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn submit_serializes_with_screaming_method() {
91        let msg = ClientMessage::Submit {
92            id: Some(RequestId::from(7u64)),
93            params: OrderParams { tx: "deadbeef".to_string() },
94        };
95        let json = serde_json::to_string(&msg).unwrap();
96        assert_eq!(json, r#"{"method":"SUBMIT","id":7,"params":{"tx":"deadbeef"}}"#);
97    }
98
99    #[test]
100    fn submit_accepts_lowercase_alias() {
101        let json = r#"{"method":"submit","id":7,"params":{"tx":"deadbeef"}}"#;
102        let msg: ClientMessage = serde_json::from_str(json).unwrap();
103        assert!(matches!(msg, ClientMessage::Submit { .. }));
104    }
105
106    #[test]
107    fn deprecated_order_place_still_round_trips() {
108        // The legacy ORDER.* methods remain on the wire for backward compat
109        // until the server and SDK migrate to SUBMIT.
110        let json = r#"{"method":"ORDER.PLACE","id":1,"params":{"tx":"abc"}}"#;
111        let msg: ClientMessage = serde_json::from_str(json).unwrap();
112        assert!(matches!(msg, ClientMessage::OrderPlace { .. }));
113    }
114}