Skip to content

Commit 08e2427

Browse files
authored
fix(lazer): serialize Option<Price> as i64 in publisher protocol (#2182)
1 parent e399a03 commit 08e2427

File tree

5 files changed

+81
-3
lines changed

5 files changed

+81
-3
lines changed

lazer/Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lazer/sdk/rust/protocol/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "pyth-lazer-protocol"
3-
version = "0.1.2"
3+
version = "0.1.3"
44
edition = "2021"
55
description = "Pyth Lazer SDK - protocol types."
66
license = "Apache-2.0"
@@ -13,3 +13,6 @@ serde = { version = "1.0.210", features = ["derive"] }
1313
derive_more = { version = "1.0.0", features = ["from"] }
1414
itertools = "0.13.0"
1515
rust_decimal = "1.36.0"
16+
17+
[dev-dependencies]
18+
bincode = "1.3.3"

lazer/sdk/rust/protocol/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ pub mod message;
44
pub mod payload;
55
pub mod publisher;
66
pub mod router;
7+
mod serde_price_as_i64;
78
mod serde_str;
89
pub mod subscription;

lazer/sdk/rust/protocol/src/publisher.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,64 @@ pub struct PriceFeedData {
1818
pub source_timestamp_us: TimestampUs,
1919
/// Timestamp of the last update provided by the publisher.
2020
pub publisher_timestamp_us: TimestampUs,
21-
/// Last known value of the "main" (?) price of this price feed.
21+
/// Last known value of the best executable price of this price feed.
2222
/// `None` if no value is currently available.
23+
#[serde(with = "crate::serde_price_as_i64")]
2324
pub price: Option<Price>,
2425
/// Last known value of the best bid price of this price feed.
2526
/// `None` if no value is currently available.
27+
#[serde(with = "crate::serde_price_as_i64")]
2628
pub best_bid_price: Option<Price>,
2729
/// Last known value of the best ask price of this price feed.
2830
/// `None` if no value is currently available.
31+
#[serde(with = "crate::serde_price_as_i64")]
2932
pub best_ask_price: Option<Price>,
3033
}
34+
35+
#[test]
36+
fn price_feed_data_serde() {
37+
let data = [
38+
1, 0, 0, 0, // price_feed_id
39+
2, 0, 0, 0, 0, 0, 0, 0, // source_timestamp_us
40+
3, 0, 0, 0, 0, 0, 0, 0, // publisher_timestamp_us
41+
4, 0, 0, 0, 0, 0, 0, 0, // price
42+
5, 0, 0, 0, 0, 0, 0, 0, // best_bid_price
43+
6, 2, 0, 0, 0, 0, 0, 0, // best_ask_price
44+
];
45+
46+
let expected = PriceFeedData {
47+
price_feed_id: PriceFeedId(1),
48+
source_timestamp_us: TimestampUs(2),
49+
publisher_timestamp_us: TimestampUs(3),
50+
price: Some(Price(4.try_into().unwrap())),
51+
best_bid_price: Some(Price(5.try_into().unwrap())),
52+
best_ask_price: Some(Price((2 * 256 + 6).try_into().unwrap())),
53+
};
54+
assert_eq!(
55+
bincode::deserialize::<PriceFeedData>(&data).unwrap(),
56+
expected
57+
);
58+
assert_eq!(bincode::serialize(&expected).unwrap(), data);
59+
60+
let data2 = [
61+
1, 0, 0, 0, // price_feed_id
62+
2, 0, 0, 0, 0, 0, 0, 0, // source_timestamp_us
63+
3, 0, 0, 0, 0, 0, 0, 0, // publisher_timestamp_us
64+
4, 0, 0, 0, 0, 0, 0, 0, // price
65+
0, 0, 0, 0, 0, 0, 0, 0, // best_bid_price
66+
0, 0, 0, 0, 0, 0, 0, 0, // best_ask_price
67+
];
68+
let expected2 = PriceFeedData {
69+
price_feed_id: PriceFeedId(1),
70+
source_timestamp_us: TimestampUs(2),
71+
publisher_timestamp_us: TimestampUs(3),
72+
price: Some(Price(4.try_into().unwrap())),
73+
best_bid_price: None,
74+
best_ask_price: None,
75+
};
76+
assert_eq!(
77+
bincode::deserialize::<PriceFeedData>(&data2).unwrap(),
78+
expected2
79+
);
80+
assert_eq!(bincode::serialize(&expected2).unwrap(), data2);
81+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
use {
2+
crate::router::Price,
3+
serde::{Deserialize, Deserializer, Serialize, Serializer},
4+
std::num::NonZeroI64,
5+
};
6+
7+
pub fn serialize<S>(value: &Option<Price>, serializer: S) -> Result<S::Ok, S::Error>
8+
where
9+
S: Serializer,
10+
{
11+
value
12+
.map_or(0i64, |price| price.0.get())
13+
.serialize(serializer)
14+
}
15+
16+
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Price>, D::Error>
17+
where
18+
D: Deserializer<'de>,
19+
{
20+
let value = i64::deserialize(deserializer)?;
21+
Ok(NonZeroI64::new(value).map(Price))
22+
}

0 commit comments

Comments
 (0)