Skip to main content

df_hyperliquid_core/utils/json/
mod.rs

1//! JSON that keeps what a signature depends on: keys in the order they were
2//! written and numbers as the digits they were written with. An L1 action is
3//! hashed as msgpack, which keeps key order, where `serde_json` sorts keys.
4
5mod msgpack;
6mod parse;
7mod write;
8
9pub use msgpack::Unpackable;
10pub use parse::BadJson;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub enum Json {
14    Null,
15    Bool(bool),
16    /// The number exactly as written: no float ever holds it.
17    Number(String),
18    String(String),
19    Array(Vec<Json>),
20    /// Keys in the order they were written.
21    Object(Vec<(String, Json)>),
22}
23
24impl Json {
25    #[must_use]
26    pub fn get(&self, key: &str) -> Option<&Json> {
27        match self {
28            Json::Object(entries) => entries.iter().find(|(name, _)| name == key).map(|(_, value)| value),
29            _ => None,
30        }
31    }
32
33    #[must_use]
34    pub fn as_str(&self) -> Option<&str> {
35        match self {
36            Json::String(text) => Some(text),
37            _ => None,
38        }
39    }
40
41    /// `true` or `false`; `None` for anything else, a `"true"` string too.
42    #[must_use]
43    pub const fn as_bool(&self) -> Option<bool> {
44        match self {
45            Json::Bool(value) => Some(*value),
46            _ => None,
47        }
48    }
49
50    /// A whole non-negative number, as the venue writes counts and ids.
51    #[must_use]
52    pub fn as_u64(&self) -> Option<u64> {
53        match self {
54            Json::Number(digits) => digits.parse().ok(),
55            _ => None,
56        }
57    }
58
59    #[must_use]
60    pub fn as_array(&self) -> Option<&[Json]> {
61        match self {
62            Json::Array(items) => Some(items),
63            _ => None,
64        }
65    }
66
67    #[must_use]
68    pub fn as_object(&self) -> Option<&[(String, Json)]> {
69        match self {
70            Json::Object(entries) => Some(entries),
71            _ => None,
72        }
73    }
74
75    #[must_use]
76    pub const fn kind(&self) -> &'static str {
77        match self {
78            Json::Null => "null",
79            Json::Bool(_) => "a boolean",
80            Json::Number(_) => "a number",
81            Json::String(_) => "a string",
82            Json::Array(_) => "an array",
83            Json::Object(_) => "an object",
84        }
85    }
86}
87
88#[cfg(test)]
89#[path = "tests/json.rs"]
90mod tests;