1pub mod api;
5pub mod binary_update;
7mod dynamic_value;
8mod feed_kind;
9pub mod jrpc;
11pub mod message;
13pub mod payload;
15mod price;
16pub mod publisher;
18mod rate;
19mod serde_price_as_i64;
20mod serde_str;
21mod symbol_state;
22pub mod time;
24
25use serde::{Deserialize, Serialize};
26use utoipa::ToSchema;
27use {
28 derive_more::derive::{From, Into},
29 strum::FromRepr,
30};
31
32pub use crate::{
33 dynamic_value::DynamicValue,
34 feed_kind::FeedKind,
35 price::{Price, PriceError},
36 rate::{Rate, RateError},
37 symbol_state::SymbolState,
38};
39
40#[derive(
41 Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, From, Into,
42)]
43pub struct AssetId(pub u32);
44
45#[derive(
46 Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, From, Into,
47)]
48pub struct PublisherId(pub u16);
49
50#[derive(
51 Debug,
52 Clone,
53 Copy,
54 PartialEq,
55 Eq,
56 Hash,
57 PartialOrd,
58 Ord,
59 Serialize,
60 Deserialize,
61 From,
62 Into,
63 ToSchema,
64)]
65#[schema(value_type = u32)]
66pub struct PriceFeedId(pub u32);
67
68#[derive(
69 Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, From, Into,
70)]
71pub struct ChannelId(pub u8);
72
73impl ChannelId {
74 pub const REAL_TIME: ChannelId = ChannelId(1);
75 pub const FIXED_RATE_50: ChannelId = ChannelId(2);
76 pub const FIXED_RATE_200: ChannelId = ChannelId(3);
77 pub const FIXED_RATE_1000: ChannelId = ChannelId(4);
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, ToSchema, FromRepr)]
81#[serde(rename_all = "camelCase")]
82#[repr(u8)]
83pub enum PriceFeedProperty {
84 Price,
85 BestBidPrice,
86 BestAskPrice,
87 PublisherCount,
88 Exponent,
89 Confidence,
90 FundingRate,
91 FundingTimestamp,
92 FundingRateInterval,
93 MarketSession,
94 EmaPrice,
95 EmaConfidence,
96 FeedUpdateTimestamp,
97 }
99
100#[derive(Debug, Clone, Deserialize)]
101#[serde(rename_all = "kebab-case")]
102pub enum AssetClass {
103 Crypto,
104 Fx,
105 Equity,
106 Metal,
107 Rates,
108 Nav,
109 Commodity,
110 FundingRate,
111 Eco,
112 Kalshi,
113}
114
115impl AssetClass {
116 pub fn as_str(&self) -> &'static str {
117 match self {
118 AssetClass::Crypto => "crypto",
119 AssetClass::Fx => "fx",
120 AssetClass::Equity => "equity",
121 AssetClass::Metal => "metal",
122 AssetClass::Rates => "rates",
123 AssetClass::Nav => "nav",
124 AssetClass::Commodity => "commodity",
125 AssetClass::FundingRate => "funding-rate",
126 AssetClass::Eco => "eco",
127 AssetClass::Kalshi => "kalshi",
128 }
129 }
130}
131
132enum ExponentFactor {
134 Mul(i64),
136 Div(i64),
138}
139
140impl ExponentFactor {
141 fn get(exponent: i16) -> Option<Self> {
142 if exponent >= 0 {
143 let exponent: u32 = exponent.try_into().ok()?;
144 Some(ExponentFactor::Div(10_i64.checked_pow(exponent)?))
145 } else {
146 let minus_exponent: u32 = exponent.checked_neg()?.try_into().ok()?;
147 Some(ExponentFactor::Mul(10_i64.checked_pow(minus_exponent)?))
148 }
149 }
150}
151
152#[test]
153fn magics_in_big_endian() {
154 use crate::{
155 binary_update::BINARY_UPDATE_FORMAT_MAGIC,
156 message::format_magics_le::{
157 EVM_FORMAT_MAGIC, JSON_FORMAT_MAGIC, LE_ECDSA_FORMAT_MAGIC, LE_UNSIGNED_FORMAT_MAGIC,
158 SOLANA_FORMAT_MAGIC,
159 },
160 payload::PAYLOAD_FORMAT_MAGIC,
161 };
162
163 assert_eq!(u32::swap_bytes(BINARY_UPDATE_FORMAT_MAGIC), 1937213467);
167 assert_eq!(u32::swap_bytes(PAYLOAD_FORMAT_MAGIC), 1976813459);
168
169 assert_eq!(u32::swap_bytes(SOLANA_FORMAT_MAGIC), 3103857282);
170 assert_eq!(u32::swap_bytes(JSON_FORMAT_MAGIC), 2584795844);
171 assert_eq!(u32::swap_bytes(EVM_FORMAT_MAGIC), 706910618);
172 assert_eq!(u32::swap_bytes(LE_ECDSA_FORMAT_MAGIC), 3837609805);
173 assert_eq!(u32::swap_bytes(LE_UNSIGNED_FORMAT_MAGIC), 206398297);
174
175 for magic in [
176 BINARY_UPDATE_FORMAT_MAGIC,
177 PAYLOAD_FORMAT_MAGIC,
178 SOLANA_FORMAT_MAGIC,
179 JSON_FORMAT_MAGIC,
180 EVM_FORMAT_MAGIC,
181 LE_ECDSA_FORMAT_MAGIC,
182 LE_UNSIGNED_FORMAT_MAGIC,
183 ] {
184 assert_ne!(u32::swap_bytes(magic), magic);
186 }
187}