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