Skip to main content

df_hyperliquid_core/live/subscription/
wire.rs

1//! Writing a subscription as the object a subscribe or unsubscribe frame carries
2//! ([`Subscription::to_json`]), and as one line of JSON.
3
4use std::fmt;
5
6use crate::live::Subscription;
7use crate::utils::Json;
8
9impl Subscription {
10    /// The object a subscribe or unsubscribe frame carries: keys in the docs' order, optional ones
11    /// last and only when set, as the Python SDK sends them. The venue echoes left out options
12    /// filled in (`fast: false`, `dex: ""`), and [`Subscription::parse`] reads that echo back to
13    /// the same subscription.
14    #[must_use]
15    pub fn to_json(&self) -> Json {
16        let mut fields = vec![("type", text(self.kind()))];
17        match self {
18            Subscription::AllMids { dex } if !dex.is_empty() => fields.push(("dex", text(dex))),
19            Subscription::TwapStates { user, dex }
20            | Subscription::ClearinghouseState { user, dex }
21            | Subscription::OpenOrders { user, dex } => {
22                fields.push(("user", text(&user.to_hex())));
23                fields.push(("dex", text(dex)));
24            }
25            Subscription::Candle { coin, interval } => {
26                fields.push(("coin", text(coin)));
27                fields.push(("interval", text(interval.wire())));
28            }
29            Subscription::L2Book { coin, n_sig_figs, mantissa, fast } => {
30                fields.push(("coin", text(coin)));
31                if let Some(figures) = n_sig_figs {
32                    fields.push(("nSigFigs", Json::Number(figures.to_string())));
33                }
34                if let Some(mantissa) = mantissa {
35                    fields.push(("mantissa", Json::Number(mantissa.to_string())));
36                }
37                if *fast {
38                    fields.push(("fast", Json::Bool(true)));
39                }
40            }
41            Subscription::Trades { coin } | Subscription::ActiveAssetCtx { coin } | Subscription::Bbo { coin } => {
42                fields.push(("coin", text(coin)));
43            }
44            Subscription::UserFills { user, aggregate_by_time } => {
45                fields.push(("user", text(&user.to_hex())));
46                if *aggregate_by_time {
47                    fields.push(("aggregateByTime", Json::Bool(true)));
48                }
49            }
50            Subscription::ActiveAssetData { user, coin } => {
51                fields.push(("user", text(&user.to_hex())));
52                fields.push(("coin", text(coin)));
53            }
54            Subscription::SpotState { user, ignore_portfolio_margin } => {
55                fields.push(("user", text(&user.to_hex())));
56                if *ignore_portfolio_margin {
57                    fields.push(("ignorePortfolioMargin", Json::Bool(true)));
58                }
59            }
60            Subscription::AssetCtxs { dex } => fields.push(("dex", text(dex))),
61            Subscription::Notification { user }
62            | Subscription::WebData3 { user }
63            | Subscription::OrderUpdates { user }
64            | Subscription::UserEvents { user }
65            | Subscription::UserFundings { user }
66            | Subscription::UserNonFundingLedgerUpdates { user }
67            | Subscription::UserTwapSliceFills { user }
68            | Subscription::UserTwapHistory { user }
69            | Subscription::AllDexsClearinghouseState { user }
70            | Subscription::UserHistoricalOrders { user } => fields.push(("user", text(&user.to_hex()))),
71            Subscription::AllMids { .. }
72            | Subscription::AllDexsAssetCtxs
73            | Subscription::OutcomeMetaUpdates
74            | Subscription::FastAssetCtxs
75            | Subscription::SpotAssetCtxs => {}
76        }
77        Json::Object(fields.into_iter().map(|(key, value)| (key.to_owned(), value)).collect())
78    }
79}
80
81impl fmt::Display for Subscription {
82    /// The object as one line of JSON.
83    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84        f.write_str(&self.to_json().compact())
85    }
86}
87
88fn text(value: &str) -> Json {
89    Json::String(value.to_owned())
90}
91
92#[cfg(test)]
93#[path = "tests/wire.rs"]
94mod tests;