1use {
2    crate::{price::Price, rate::Rate, time::TimestampUs, PriceFeedId},
3    derive_more::derive::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::deserialize::<PriceFeedDataV1>(&data).unwrap(),
110        expected
111    );
112    assert_eq!(bincode::serialize(&expected).unwrap(), data);
113
114    let data2 = [
115        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, ];
122    let expected2 = PriceFeedDataV1 {
123        price_feed_id: PriceFeedId(1),
124        source_timestamp_us: TimestampUs::from_micros(2),
125        publisher_timestamp_us: TimestampUs::from_micros(3),
126        price: Some(Price::from_nonzero_mantissa(4.try_into().unwrap())),
127        best_bid_price: None,
128        best_ask_price: None,
129    };
130    assert_eq!(
131        bincode::deserialize::<PriceFeedDataV1>(&data2).unwrap(),
132        expected2
133    );
134    assert_eq!(bincode::serialize(&expected2).unwrap(), data2);
135}
136
137#[test]
138fn price_feed_data_v2_serde() {
139    let data = [
140        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, ];
148
149    let expected = PriceFeedDataV2 {
150        price_feed_id: PriceFeedId(1),
151        source_timestamp_us: TimestampUs::from_micros(2),
152        publisher_timestamp_us: TimestampUs::from_micros(3),
153        price: Some(Price::from_nonzero_mantissa(4.try_into().unwrap())),
154        best_bid_price: Some(Price::from_nonzero_mantissa(5.try_into().unwrap())),
155        best_ask_price: Some(Price::from_nonzero_mantissa(
156            (2 * 256 + 6).try_into().unwrap(),
157        )),
158        funding_rate: None,
159    };
160    assert_eq!(
161        bincode::deserialize::<PriceFeedDataV2>(&data).unwrap(),
162        expected
163    );
164    assert_eq!(bincode::serialize(&expected).unwrap(), data);
165
166    let data2 = [
167        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, ];
175    let expected2 = PriceFeedDataV2 {
176        price_feed_id: PriceFeedId(1),
177        source_timestamp_us: TimestampUs::from_micros(2),
178        publisher_timestamp_us: TimestampUs::from_micros(3),
179        price: Some(Price::from_nonzero_mantissa(4.try_into().unwrap())),
180        best_bid_price: None,
181        best_ask_price: None,
182        funding_rate: Some(Rate::from_mantissa(3 * 256 + 7)),
183    };
184    assert_eq!(
185        bincode::deserialize::<PriceFeedDataV2>(&data2).unwrap(),
186        expected2
187    );
188    assert_eq!(bincode::serialize(&expected2).unwrap(), data2);
189}