Skip to main content

df_hyperliquid_core/live/
market.rs

1//! The websocket's own market frames: the best bid and offer, and one dex's mids. Books, trades,
2//! candles and asset contexts come in the shapes the `/info` reads answer, the [`crate::markets`]
3//! types. Every price and size is an exact [`Dec`] read from the venue's string; a number written
4//! as a float is refused, never rounded.
5
6use crate::markets::Level;
7use crate::utils::Dec;
8use serde::Deserialize;
9
10/// `bbo`: the best bid and offer, sent only when one of them moves. A side with nothing
11/// resting is `None`.
12#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
13#[serde(from = "RawBbo")]
14pub struct Bbo {
15    pub coin: String,
16    /// Milliseconds.
17    pub time: u64,
18    pub bid: Option<Level>,
19    pub ask: Option<Level>,
20}
21
22#[derive(Deserialize)]
23struct RawBbo {
24    coin: String,
25    time: u64,
26    bbo: (Option<Level>, Option<Level>),
27}
28
29impl From<RawBbo> for Bbo {
30    fn from(raw: RawBbo) -> Self {
31        let (bid, ask) = raw.bbo;
32        Bbo { coin: raw.coin, time: raw.time, bid, ask }
33    }
34}
35
36/// `allMids`: every coin's mid on one perp dex, in the order sent. The first dex's (`dex` empty)
37/// also carries spot pairs (`@107`, `PURR/USDC`) and outcome sides (`#14720`).
38#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
39pub struct Mids {
40    #[serde(default)]
41    pub dex: String,
42    /// The map `allMids` answers.
43    pub mids: crate::markets::mids::Mids,
44}
45
46impl Mids {
47    /// A coin's mid, the coin spelled as the venue spells it.
48    #[must_use]
49    pub fn get(&self, coin: &str) -> Option<Dec> {
50        self.mids.get(coin)
51    }
52}
53
54#[cfg(test)]
55#[path = "tests/market.rs"]
56mod tests;