1use {
2 crate::{price::Price, rate::Rate, time::TimestampUs, PriceFeedId},
3 derive_more::From,
4 serde::{Deserialize, Serialize},
5};
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
10#[serde(rename_all = "camelCase")]
11pub struct PriceFeedDataV2 {
12 pub price_feed_id: PriceFeedId,
13 pub source_timestamp_us: TimestampUs,
16 pub publisher_timestamp_us: TimestampUs,
18 pub price: Option<Price>,
21 pub best_bid_price: Option<Price>,
24 pub best_ask_price: Option<Price>,
27 pub funding_rate: Option<Rate>,
30}
31
32#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
36#[serde(rename_all = "camelCase")]
37pub struct PriceFeedDataV1 {
38 pub price_feed_id: PriceFeedId,
39 pub source_timestamp_us: TimestampUs,
42 pub publisher_timestamp_us: TimestampUs,
44 #[serde(with = "crate::serde_price_as_i64")]
47 pub price: Option<Price>,
48 #[serde(with = "crate::serde_price_as_i64")]
51 pub best_bid_price: Option<Price>,
52 #[serde(with = "crate::serde_price_as_i64")]
55 pub best_ask_price: Option<Price>,
56}
57
58impl From<PriceFeedDataV1> for PriceFeedDataV2 {
59 fn from(v0: PriceFeedDataV1) -> Self {
60 Self {
61 price_feed_id: v0.price_feed_id,
62 source_timestamp_us: v0.source_timestamp_us,
63 publisher_timestamp_us: v0.publisher_timestamp_us,
64 price: v0.price,
65 best_bid_price: v0.best_bid_price,
66 best_ask_price: v0.best_ask_price,
67 funding_rate: None,
68 }
69 }
70}
71
72#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, From)]
75#[serde(tag = "type")]
76#[serde(rename_all = "camelCase")]
77pub enum ServerResponse {
78 UpdateDeserializationError(UpdateDeserializationErrorResponse),
79}
80#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
82#[serde(rename_all = "camelCase")]
83pub struct UpdateDeserializationErrorResponse {
84 pub error: String,
85}
86
87#[test]
88fn price_feed_data_v1_serde() {
89 let data = [
90 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 2, 0, 0, 0, 0, 0, 0, ];
97
98 let expected = PriceFeedDataV1 {
99 price_feed_id: PriceFeedId(1),
100 source_timestamp_us: TimestampUs::from_micros(2),
101 publisher_timestamp_us: TimestampUs::from_micros(3),
102 price: Some(Price::from_nonzero_mantissa(4.try_into().unwrap())),
103 best_bid_price: Some(Price::from_nonzero_mantissa(5.try_into().unwrap())),
104 best_ask_price: Some(Price::from_nonzero_mantissa(
105 (2 * 256 + 6).try_into().unwrap(),
106 )),
107 };
108 assert_eq!(
109 bincode::serde::decode_from_slice::<PriceFeedDataV1, _>(&data, bincode::config::legacy())
110 .unwrap()
111 .0,
112 expected
113 );
114 assert_eq!(
115 bincode::serde::encode_to_vec(&expected, bincode::config::legacy()).unwrap(),
116 data
117 );
118
119 let data2 = [
120 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ];
127 let expected2 = PriceFeedDataV1 {
128 price_feed_id: PriceFeedId(1),
129 source_timestamp_us: TimestampUs::from_micros(2),
130 publisher_timestamp_us: TimestampUs::from_micros(3),
131 price: Some(Price::from_nonzero_mantissa(4.try_into().unwrap())),
132 best_bid_price: None,
133 best_ask_price: None,
134 };
135 assert_eq!(
136 bincode::serde::decode_from_slice::<PriceFeedDataV1, _>(&data2, bincode::config::legacy())
137 .unwrap()
138 .0,
139 expected2
140 );
141 assert_eq!(
142 bincode::serde::encode_to_vec(&expected2, bincode::config::legacy()).unwrap(),
143 data2
144 );
145}
146
147#[test]
148fn price_feed_data_v2_serde() {
149 let data = [
150 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 1, 5, 0, 0, 0, 0, 0, 0, 0, 1, 6, 2, 0, 0, 0, 0, 0, 0, 0, ];
158
159 let expected = PriceFeedDataV2 {
160 price_feed_id: PriceFeedId(1),
161 source_timestamp_us: TimestampUs::from_micros(2),
162 publisher_timestamp_us: TimestampUs::from_micros(3),
163 price: Some(Price::from_nonzero_mantissa(4.try_into().unwrap())),
164 best_bid_price: Some(Price::from_nonzero_mantissa(5.try_into().unwrap())),
165 best_ask_price: Some(Price::from_nonzero_mantissa(
166 (2 * 256 + 6).try_into().unwrap(),
167 )),
168 funding_rate: None,
169 };
170 assert_eq!(
171 bincode::serde::decode_from_slice::<PriceFeedDataV2, _>(&data, bincode::config::legacy())
172 .unwrap()
173 .0,
174 expected
175 );
176 assert_eq!(
177 bincode::serde::encode_to_vec(&expected, bincode::config::legacy()).unwrap(),
178 data
179 );
180
181 let data2 = [
182 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 7, 3, 0, 0, 0, 0, 0, 0, ];
190 let expected2 = PriceFeedDataV2 {
191 price_feed_id: PriceFeedId(1),
192 source_timestamp_us: TimestampUs::from_micros(2),
193 publisher_timestamp_us: TimestampUs::from_micros(3),
194 price: Some(Price::from_nonzero_mantissa(4.try_into().unwrap())),
195 best_bid_price: None,
196 best_ask_price: None,
197 funding_rate: Some(Rate::from_mantissa(3 * 256 + 7)),
198 };
199 assert_eq!(
200 bincode::serde::decode_from_slice::<PriceFeedDataV2, _>(&data2, bincode::config::legacy())
201 .unwrap()
202 .0,
203 expected2
204 );
205 assert_eq!(
206 bincode::serde::encode_to_vec(&expected2, bincode::config::legacy()).unwrap(),
207 data2
208 );
209}