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 }
92
93#[derive(Debug, Clone, Deserialize)]
94#[serde(rename_all = "kebab-case")]
95pub enum AssetClass {
96 Crypto,
97 Fx,
98 Equity,
99 Metal,
100 Rates,
101 Nav,
102 Commodity,
103 FundingRate,
104}
105
106impl AssetClass {
107 pub fn as_str(&self) -> &'static str {
108 match self {
109 AssetClass::Crypto => "crypto",
110 AssetClass::Fx => "fx",
111 AssetClass::Equity => "equity",
112 AssetClass::Metal => "metal",
113 AssetClass::Rates => "rates",
114 AssetClass::Nav => "nav",
115 AssetClass::Commodity => "commodity",
116 AssetClass::FundingRate => "funding-rate",
117 }
118 }
119}
120
121enum ExponentFactor {
123 Mul(i64),
125 Div(i64),
127}
128
129impl ExponentFactor {
130 fn get(exponent: i16) -> Option<Self> {
131 if exponent >= 0 {
132 let exponent: u32 = exponent.try_into().ok()?;
133 Some(ExponentFactor::Div(10_i64.checked_pow(exponent)?))
134 } else {
135 let minus_exponent: u32 = exponent.checked_neg()?.try_into().ok()?;
136 Some(ExponentFactor::Mul(10_i64.checked_pow(minus_exponent)?))
137 }
138 }
139}
140
141#[test]
142fn magics_in_big_endian() {
143 use crate::{
144 binary_update::BINARY_UPDATE_FORMAT_MAGIC,
145 message::format_magics_le::{
146 EVM_FORMAT_MAGIC, JSON_FORMAT_MAGIC, LE_ECDSA_FORMAT_MAGIC, LE_UNSIGNED_FORMAT_MAGIC,
147 SOLANA_FORMAT_MAGIC,
148 },
149 payload::PAYLOAD_FORMAT_MAGIC,
150 };
151
152 assert_eq!(u32::swap_bytes(BINARY_UPDATE_FORMAT_MAGIC), 1937213467);
156 assert_eq!(u32::swap_bytes(PAYLOAD_FORMAT_MAGIC), 1976813459);
157
158 assert_eq!(u32::swap_bytes(SOLANA_FORMAT_MAGIC), 3103857282);
159 assert_eq!(u32::swap_bytes(JSON_FORMAT_MAGIC), 2584795844);
160 assert_eq!(u32::swap_bytes(EVM_FORMAT_MAGIC), 706910618);
161 assert_eq!(u32::swap_bytes(LE_ECDSA_FORMAT_MAGIC), 3837609805);
162 assert_eq!(u32::swap_bytes(LE_UNSIGNED_FORMAT_MAGIC), 206398297);
163
164 for magic in [
165 BINARY_UPDATE_FORMAT_MAGIC,
166 PAYLOAD_FORMAT_MAGIC,
167 SOLANA_FORMAT_MAGIC,
168 JSON_FORMAT_MAGIC,
169 EVM_FORMAT_MAGIC,
170 LE_ECDSA_FORMAT_MAGIC,
171 LE_UNSIGNED_FORMAT_MAGIC,
172 ] {
173 assert_ne!(u32::swap_bytes(magic), magic);
175 }
176}