From dac9d93cfa8cee84c5322a2b58daef698aec8959 Mon Sep 17 00:00:00 2001 From: Bart Platak Date: Mon, 7 Jul 2025 15:56:32 +0100 Subject: [PATCH 01/11] feat(pyth-lazer) Create schema for lazer agent JRPC endpoint --- lazer/publisher_sdk/rust/src/lib.rs | 38 ++++ lazer/sdk/rust/protocol/src/jrpc.rs | 238 ++++++++++++++++++++++++++ lazer/sdk/rust/protocol/src/lib.rs | 5 +- lazer/sdk/rust/protocol/src/router.rs | 37 +++- 4 files changed, 309 insertions(+), 9 deletions(-) create mode 100644 lazer/sdk/rust/protocol/src/jrpc.rs diff --git a/lazer/publisher_sdk/rust/src/lib.rs b/lazer/publisher_sdk/rust/src/lib.rs index bc341e2c5d..1a565e0800 100644 --- a/lazer/publisher_sdk/rust/src/lib.rs +++ b/lazer/publisher_sdk/rust/src/lib.rs @@ -1,9 +1,12 @@ use std::{collections::BTreeMap, time::Duration}; +use crate::publisher_update::feed_update::Update; +use crate::publisher_update::{FeedUpdate, FundingRateUpdate, PriceUpdate}; use ::protobuf::MessageField; use anyhow::{bail, ensure, Context}; use humantime::format_duration; use protobuf::dynamic_value::{dynamic_value, DynamicValue}; +use pyth_lazer_protocol::jrpc::{FeedUpdateParams, UpdateParams}; use pyth_lazer_protocol::router::TimestampUs; pub mod transaction_envelope { @@ -164,3 +167,38 @@ impl TryFrom for serde_value::Value { } } } + +impl From for FeedUpdate { + fn from(value: FeedUpdateParams) -> Self { + FeedUpdate { + feed_id: Some(value.feed_id.0), + source_timestamp: value.source_timestamp.into(), + update: Some(value.update.into()), + special_fields: Default::default(), + } + } +} + +impl From for Update { + fn from(value: UpdateParams) -> Self { + match value { + UpdateParams::PriceUpdate { + price, + best_bid_price, + best_ask_price, + } => Update::PriceUpdate(PriceUpdate { + price: Some(price.0.into()), + best_bid_price: Some(best_bid_price.0.into()), + best_ask_price: Some(best_ask_price.0.into()), + special_fields: Default::default(), + }), + UpdateParams::FundingRateUpdate { price, rate } => { + Update::FundingRateUpdate(FundingRateUpdate { + price: Some(price.0.into()), + rate: Some(rate.0.into()), + special_fields: Default::default(), + }) + } + } + } +} diff --git a/lazer/sdk/rust/protocol/src/jrpc.rs b/lazer/sdk/rust/protocol/src/jrpc.rs new file mode 100644 index 0000000000..be5459aaf6 --- /dev/null +++ b/lazer/sdk/rust/protocol/src/jrpc.rs @@ -0,0 +1,238 @@ +use std::time::Duration; +use crate::router::{Price, PriceFeedId, Rate, TimestampUs}; +use serde::{Deserialize, Serialize}; + +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +pub struct PythLazerAgentJrpcV1 { + pub jsonrpc: JsonRpcVersion, + #[serde(flatten)] + pub params: JrpcParams, + pub id: i64, +} + +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +#[serde(tag = "method", content = "params")] +pub enum JrpcParams { + #[serde(rename = "send_updates")] + SendUpdates(FeedUpdateParams), + #[serde(rename = "get_symbols")] + GetMetadata(GetMetadataParams), +} + +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +pub struct FeedUpdateParams { + pub feed_id: PriceFeedId, + pub source_timestamp: TimestampUs, + pub update: UpdateParams, +} + +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +#[serde(tag = "type")] +pub enum UpdateParams { + #[serde(rename = "price")] + PriceUpdate { + price: Price, + best_bid_price: Price, + best_ask_price: Price, + }, + #[serde(rename = "funding_rate")] + FundingRateUpdate { price: Price, rate: Rate }, +} + +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +pub struct Filter { + name: Option, + asset_type: Option, +} + +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +pub struct GetMetadataParams { + filters: Option>, +} + +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +pub enum JsonRpcVersion { + #[serde(rename = "2.0")] + V2, +} + +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +pub struct JrpcResponse { + pub jsonrpc: JsonRpcVersion, + pub result: T, + pub id: i64, +} + +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +pub struct ErrorResponse { + pub message: String +} + +#[derive(Serialize, Deserialize)] +struct SymbolMetadata { + pub asset_type: String, + pub cmc_id: i64, + pub description: String, + pub exponent: i64, + pub hermes_id: String, + #[serde(default, with = "humantime_serde", alias = "interval")] + pub interval: Option, + pub min_channel: String, + pub min_publishers: i64, + pub name: String, + pub pyth_lazer_id: i64, + pub schedule: String, + pub state: String, + pub symbol: String, +} + +#[cfg(test)] +mod tests { + use crate::jrpc::JrpcParams::{GetMetadata, SendUpdates}; + use crate::jrpc::{ + FeedUpdateParams, Filter, GetMetadataParams, JsonRpcVersion, PythLazerAgentJrpcV1, + UpdateParams, + }; + use crate::router::{Price, PriceFeedId, Rate, TimestampUs}; + + #[test] + fn test_send_updates_price() { + let json = r#" + { + "jsonrpc": "2.0", + "method": "send_updates", + "params": { + "feed_id": 1, + "source_timestamp": 124214124124, + + "update": { + "type": "price", + "price": 1234567890, + "best_bid_price": 1234567891, + "best_ask_price": 1234567892 + } + }, + "id": 1 + } + "#; + + let expected = PythLazerAgentJrpcV1 { + jsonrpc: JsonRpcVersion::V2, + params: SendUpdates(FeedUpdateParams { + feed_id: PriceFeedId(1), + source_timestamp: TimestampUs(124214124124), + update: UpdateParams::PriceUpdate { + price: Price::from_integer(1234567890, 0).unwrap(), + best_bid_price: Price::from_integer(1234567891, 0).unwrap(), + best_ask_price: Price::from_integer(1234567892, 0).unwrap(), + }, + }), + id: 1, + }; + + assert_eq!( + serde_json::from_str::(json).unwrap(), + expected + ); + } + + #[test] + fn test_send_updates_funding_rate() { + let json = r#" + { + "jsonrpc": "2.0", + "method": "send_updates", + "params": { + "feed_id": 1, + "source_timestamp": 124214124124, + + "update": { + "type": "funding_rate", + "price": 1234567890, + "rate": 1234567891 + } + }, + "id": 1 + } + "#; + + let expected = PythLazerAgentJrpcV1 { + jsonrpc: JsonRpcVersion::V2, + params: SendUpdates(FeedUpdateParams { + feed_id: PriceFeedId(1), + source_timestamp: TimestampUs(124214124124), + update: UpdateParams::FundingRateUpdate { + price: Price::from_integer(1234567890, 0).unwrap(), + rate: Rate::from_integer(1234567891, 0).unwrap(), + }, + }), + id: 1, + }; + + assert_eq!( + serde_json::from_str::(json).unwrap(), + expected + ); + } + #[test] + fn test_send_get_symbols() { + let json = r#" + { + "jsonrpc": "2.0", + "method": "get_symbols", + "params": { + "filters": [ + {"name": "BTC/USD"}, + {"asset_type": "crypto"} + ] + }, + "id": 1 + } + "#; + + let expected = PythLazerAgentJrpcV1 { + jsonrpc: JsonRpcVersion::V2, + params: GetMetadata(GetMetadataParams { + filters: Some(vec![ + Filter { + name: Some("BTC/USD".to_string()), + asset_type: None, + }, + Filter { + name: None, + asset_type: Some("crypto".to_string()), + }, + ]), + }), + id: 1, + }; + + assert_eq!( + serde_json::from_str::(json).unwrap(), + expected + ); + } + + #[test] + fn test_get_symbols_without_filters() { + let json = r#" + { + "jsonrpc": "2.0", + "method": "get_symbols", + "params": {}, + "id": 1 + } + "#; + + let expected = PythLazerAgentJrpcV1 { + jsonrpc: JsonRpcVersion::V2, + params: GetMetadata(GetMetadataParams { filters: None }), + id: 1, + }; + + assert_eq!( + serde_json::from_str::(json).unwrap(), + expected + ); + } +} diff --git a/lazer/sdk/rust/protocol/src/lib.rs b/lazer/sdk/rust/protocol/src/lib.rs index d10bedeebc..ded13bec8c 100644 --- a/lazer/sdk/rust/protocol/src/lib.rs +++ b/lazer/sdk/rust/protocol/src/lib.rs @@ -2,6 +2,7 @@ pub mod api; pub mod binary_update; +pub mod jrpc; pub mod message; pub mod payload; pub mod publisher; @@ -23,7 +24,7 @@ fn magics_in_big_endian() { }; // The values listed in this test can be used when reading the magic headers in BE format - // (e.g. on EVM). + // (e.g., on EVM). assert_eq!(u32::swap_bytes(BINARY_UPDATE_FORMAT_MAGIC), 1937213467); assert_eq!(u32::swap_bytes(PAYLOAD_FORMAT_MAGIC), 1976813459); @@ -44,6 +45,6 @@ fn magics_in_big_endian() { LE_UNSIGNED_FORMAT_MAGIC, ] { // Required to distinguish between byte orders. - assert!(u32::swap_bytes(magic) != magic); + assert_ne!(u32::swap_bytes(magic), magic); } } diff --git a/lazer/sdk/rust/protocol/src/router.rs b/lazer/sdk/rust/protocol/src/router.rs index 356b7dab88..41d7bf7dc7 100644 --- a/lazer/sdk/rust/protocol/src/router.rs +++ b/lazer/sdk/rust/protocol/src/router.rs @@ -1,5 +1,6 @@ -//! WebSocket JSON protocol types for API the router provides to consumers and publishers. +//! WebSocket JSON protocol types for the API the router provides to consumers and publishers. +use protobuf::MessageField; use { crate::payload::AggregatedPriceFeedData, anyhow::{bail, Context}, @@ -37,6 +38,26 @@ impl TryFrom<&Timestamp> for TimestampUs { } } +impl Into for TimestampUs { + fn into(self) -> Timestamp { + Timestamp { + #[allow( + clippy::cast_possible_wrap, + reason = "u64 to i64 after this division can never overflow because the value cannot be too big" + )] + seconds: (self.0 / 1_000_000) as i64, + nanos: (self.0 % 1_000_000) as i32 * 1000, + special_fields: Default::default(), + } + } +} + +impl Into> for TimestampUs { + fn into(self) -> MessageField { + MessageField::some(self.into()) + } +} + impl TimestampUs { pub fn now() -> Self { let value = SystemTime::now() @@ -304,7 +325,7 @@ impl<'de> Deserialize<'de> for Channel { D: serde::Deserializer<'de>, { let value = ::deserialize(deserializer)?; - parse_channel(&value).ok_or_else(|| D::Error::custom("unknown channel")) + parse_channel(&value).ok_or_else(|| Error::custom("unknown channel")) } } @@ -341,12 +362,14 @@ fn fixed_rate_values() { "values must be unique and sorted" ); for value in FixedRate::ALL { - assert!( - 1000 % value.ms == 0, + assert_eq!( + 1000 % value.ms, + 0, "1 s must contain whole number of intervals" ); - assert!( - value.value_us() % FixedRate::MIN.value_us() == 0, + assert_eq!( + value.value_us() % FixedRate::MIN.value_us(), + 0, "the interval's borders must be a subset of the minimal interval's borders" ); } @@ -383,7 +406,7 @@ impl<'de> Deserialize<'de> for SubscriptionParams { D: serde::Deserializer<'de>, { let value = SubscriptionParamsRepr::deserialize(deserializer)?; - Self::new(value).map_err(D::Error::custom) + Self::new(value).map_err(Error::custom) } } From f1e15e1e630cfbade6f51e6a4bd80edb19218eb0 Mon Sep 17 00:00:00 2001 From: Bart Platak Date: Mon, 7 Jul 2025 16:35:27 +0100 Subject: [PATCH 02/11] add missing dep --- Cargo.lock | 2 +- lazer/sdk/rust/protocol/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 17075d2611..5219c1fe64 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5600,13 +5600,13 @@ version = "0.7.3" dependencies = [ "alloy-primitives 0.8.25", "anyhow", - "base64 0.22.1", "bincode 1.3.3", "bs58", "byteorder", "derive_more 1.0.0", "ed25519-dalek 2.1.1", "hex", + "humantime-serde", "itertools 0.13.0", "libsecp256k1 0.7.2", "protobuf", diff --git a/lazer/sdk/rust/protocol/Cargo.toml b/lazer/sdk/rust/protocol/Cargo.toml index 75ba2f0d08..1a467f3cc9 100644 --- a/lazer/sdk/rust/protocol/Cargo.toml +++ b/lazer/sdk/rust/protocol/Cargo.toml @@ -14,8 +14,8 @@ serde_json = "1.0" derive_more = { version = "1.0.0", features = ["from"] } itertools = "0.13.0" rust_decimal = "1.36.0" -base64 = "0.22.1" protobuf = "3.7.2" +humantime-serde = "1.1.1" [dev-dependencies] bincode = "1.3.3" From a42a994afbbb101771b0664c4b92864b2a78815b Mon Sep 17 00:00:00 2001 From: Bart Platak Date: Mon, 7 Jul 2025 16:43:10 +0100 Subject: [PATCH 03/11] make clippy happy --- Cargo.lock | 36 +++++++++++++-------------- lazer/publisher_sdk/rust/src/lib.rs | 2 +- lazer/sdk/rust/protocol/src/jrpc.rs | 4 +-- lazer/sdk/rust/protocol/src/router.rs | 14 +++++------ 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5219c1fe64..7e454154c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5539,8 +5539,8 @@ dependencies = [ "hyper 1.6.0", "hyper-util", "protobuf", - "pyth-lazer-protocol 0.7.2", - "pyth-lazer-publisher-sdk 0.1.5", + "pyth-lazer-protocol 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "pyth-lazer-publisher-sdk 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde", "serde_json", "soketto", @@ -5579,15 +5579,19 @@ dependencies = [ [[package]] name = "pyth-lazer-protocol" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9bdf4e2ba853a8b437309487542e742c7d094d8db189db194cb538f2be02ecd" +version = "0.7.3" dependencies = [ + "alloy-primitives 0.8.25", "anyhow", - "base64 0.22.1", + "bincode 1.3.3", + "bs58", "byteorder", "derive_more 1.0.0", + "ed25519-dalek 2.1.1", + "hex", + "humantime-serde", "itertools 0.13.0", + "libsecp256k1 0.7.2", "protobuf", "rust_decimal", "serde", @@ -5597,18 +5601,14 @@ dependencies = [ [[package]] name = "pyth-lazer-protocol" version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6445dc5d2f7fff7c677fb8edc5a080a82ef7583c1bdb39daa95421788c23f695" dependencies = [ - "alloy-primitives 0.8.25", "anyhow", - "bincode 1.3.3", - "bs58", + "base64 0.22.1", "byteorder", "derive_more 1.0.0", - "ed25519-dalek 2.1.1", - "hex", - "humantime-serde", "itertools 0.13.0", - "libsecp256k1 0.7.2", "protobuf", "rust_decimal", "serde", @@ -5617,16 +5617,14 @@ dependencies = [ [[package]] name = "pyth-lazer-publisher-sdk" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e633db28ca38210de8ab3e99d5bd85ad8cae08a08bb0292506340ee9d1c718" +version = "0.1.6" dependencies = [ "anyhow", "fs-err", "humantime", "protobuf", "protobuf-codegen", - "pyth-lazer-protocol 0.7.2", + "pyth-lazer-protocol 0.7.3", "serde-value", "tracing", ] @@ -5634,13 +5632,15 @@ dependencies = [ [[package]] name = "pyth-lazer-publisher-sdk" version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db6ef4052ebf2a7943259b3d52a10b2231ffc346717735c50e44d73fe92019d5" dependencies = [ "anyhow", "fs-err", "humantime", "protobuf", "protobuf-codegen", - "pyth-lazer-protocol 0.7.3", + "pyth-lazer-protocol 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde-value", "tracing", ] diff --git a/lazer/publisher_sdk/rust/src/lib.rs b/lazer/publisher_sdk/rust/src/lib.rs index 1a565e0800..1dd1f350f2 100644 --- a/lazer/publisher_sdk/rust/src/lib.rs +++ b/lazer/publisher_sdk/rust/src/lib.rs @@ -195,7 +195,7 @@ impl From for Update { UpdateParams::FundingRateUpdate { price, rate } => { Update::FundingRateUpdate(FundingRateUpdate { price: Some(price.0.into()), - rate: Some(rate.0.into()), + rate: Some(rate.0), special_fields: Default::default(), }) } diff --git a/lazer/sdk/rust/protocol/src/jrpc.rs b/lazer/sdk/rust/protocol/src/jrpc.rs index be5459aaf6..4747071c53 100644 --- a/lazer/sdk/rust/protocol/src/jrpc.rs +++ b/lazer/sdk/rust/protocol/src/jrpc.rs @@ -1,6 +1,6 @@ -use std::time::Duration; use crate::router::{Price, PriceFeedId, Rate, TimestampUs}; use serde::{Deserialize, Serialize}; +use std::time::Duration; #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] pub struct PythLazerAgentJrpcV1 { @@ -65,7 +65,7 @@ pub struct JrpcResponse { #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] pub struct ErrorResponse { - pub message: String + pub message: String, } #[derive(Serialize, Deserialize)] diff --git a/lazer/sdk/rust/protocol/src/router.rs b/lazer/sdk/rust/protocol/src/router.rs index 41d7bf7dc7..29dda4f298 100644 --- a/lazer/sdk/rust/protocol/src/router.rs +++ b/lazer/sdk/rust/protocol/src/router.rs @@ -38,23 +38,23 @@ impl TryFrom<&Timestamp> for TimestampUs { } } -impl Into for TimestampUs { - fn into(self) -> Timestamp { +impl From for Timestamp { + fn from(value: TimestampUs) -> Self { Timestamp { #[allow( clippy::cast_possible_wrap, reason = "u64 to i64 after this division can never overflow because the value cannot be too big" )] - seconds: (self.0 / 1_000_000) as i64, - nanos: (self.0 % 1_000_000) as i32 * 1000, + seconds: (value.0 / 1_000_000) as i64, + nanos: (value.0 % 1_000_000) as i32 * 1000, special_fields: Default::default(), } } } -impl Into> for TimestampUs { - fn into(self) -> MessageField { - MessageField::some(self.into()) +impl From for MessageField { + fn from(value: TimestampUs) -> Self { + MessageField::some(value.into()) } } From 6361828473a2ea9163565f48d4e1bdb414560bf2 Mon Sep 17 00:00:00 2001 From: Bart Platak Date: Wed, 9 Jul 2025 00:53:20 +0100 Subject: [PATCH 04/11] add error response formats --- lazer/sdk/rust/protocol/src/jrpc.rs | 132 ++++++++++++++++++++++------ 1 file changed, 107 insertions(+), 25 deletions(-) diff --git a/lazer/sdk/rust/protocol/src/jrpc.rs b/lazer/sdk/rust/protocol/src/jrpc.rs index 4747071c53..bccc2869a9 100644 --- a/lazer/sdk/rust/protocol/src/jrpc.rs +++ b/lazer/sdk/rust/protocol/src/jrpc.rs @@ -1,6 +1,7 @@ -use crate::router::{Price, PriceFeedId, Rate, TimestampUs}; -use serde::{Deserialize, Serialize}; use std::time::Duration; +use crate::router::{Channel, Price, PriceFeedId, Rate, TimestampUs}; +use serde::{Deserialize, Serialize}; +use crate::symbol_state::SymbolState; #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] pub struct PythLazerAgentJrpcV1 { @@ -41,13 +42,13 @@ pub enum UpdateParams { #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] pub struct Filter { - name: Option, - asset_type: Option, + pub name: Option, + pub asset_type: Option, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] pub struct GetMetadataParams { - filters: Option>, + pub filters: Option>, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] @@ -57,42 +58,78 @@ pub enum JsonRpcVersion { } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] -pub struct JrpcResponse { +pub enum JrpcResponse { + Success(JrpcSuccessResponse), + Error(JrpcErrorResponse), +} + +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +pub struct JrpcSuccessResponse { pub jsonrpc: JsonRpcVersion, pub result: T, pub id: i64, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] -pub struct ErrorResponse { +pub struct JrpcErrorResponse { + pub jsonrpc: JsonRpcVersion, + pub error: JrpcErrorObject, + pub id: Option, +} + +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] +pub struct JrpcErrorObject { + pub code: i64, pub message: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub data: Option, } -#[derive(Serialize, Deserialize)] -struct SymbolMetadata { - pub asset_type: String, - pub cmc_id: i64, - pub description: String, - pub exponent: i64, - pub hermes_id: String, - #[serde(default, with = "humantime_serde", alias = "interval")] - pub interval: Option, - pub min_channel: String, - pub min_publishers: i64, +#[derive(Debug, Eq, PartialEq)] +pub enum JrpcError { + ParseError, + InternalError, +} + +impl From for JrpcErrorObject { + fn from(error: JrpcError) -> Self { + match error { + JrpcError::ParseError => JrpcErrorObject { + code: -32700, + message: "Parse error".to_string(), + data: None, + }, + JrpcError::InternalError => JrpcErrorObject { + code: -32603, + message: "Internal error".to_string(), + data: None, + }, + } + } +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash)] +pub struct SymbolMetadata { + pub pyth_lazer_id: PriceFeedId, pub name: String, - pub pyth_lazer_id: i64, - pub schedule: String, - pub state: String, pub symbol: String, + pub description: String, + pub asset_type: String, + pub exponent: i16, + pub cmc_id: Option, + #[serde(default, with = "humantime_serde", alias = "interval")] + pub funding_rate_interval: Option, + pub min_publishers: u16, + pub min_channel: Channel, + pub state: SymbolState, + pub hermes_id: Option, + pub quote_currency: Option, } #[cfg(test)] mod tests { use crate::jrpc::JrpcParams::{GetMetadata, SendUpdates}; - use crate::jrpc::{ - FeedUpdateParams, Filter, GetMetadataParams, JsonRpcVersion, PythLazerAgentJrpcV1, - UpdateParams, - }; + use crate::jrpc::{FeedUpdateParams, Filter, GetMetadataParams, JrpcErrorObject, JrpcErrorResponse, JrpcSuccessResponse, JsonRpcVersion, PythLazerAgentJrpcV1, UpdateParams}; use crate::router::{Price, PriceFeedId, Rate, TimestampUs}; #[test] @@ -235,4 +272,49 @@ mod tests { expected ); } + + #[test] + fn test_response_format_error() { + let response = serde_json::from_str::( + r#" + { + "jsonrpc": "2.0", + "id": 2, + "error": { + "message": "Internal error", + "code": -32603 + } + } + "# + ).unwrap(); + + assert_eq!(response, JrpcErrorResponse { + jsonrpc: JsonRpcVersion::V2, + error: JrpcErrorObject { + code: -32603, + message: "Internal error".to_string(), + data: None, + }, + id: Some(2), + }); + } + + #[test] + pub fn test_response_format_success() { + let response = serde_json::from_str::>( + r#" + { + "jsonrpc": "2.0", + "id": 2, + "result": "success" + } + "# + ).unwrap(); + + assert_eq!(response, JrpcSuccessResponse:: { + jsonrpc: JsonRpcVersion::V2, + result: "success".to_string(), + id: 2, + }); + } } From 95176458b2da6785d1b972383aecb21df8c76723 Mon Sep 17 00:00:00 2001 From: Bart Platak Date: Wed, 9 Jul 2025 01:00:50 +0100 Subject: [PATCH 05/11] review --- lazer/sdk/rust/protocol/src/jrpc.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lazer/sdk/rust/protocol/src/jrpc.rs b/lazer/sdk/rust/protocol/src/jrpc.rs index bccc2869a9..58fcdc02ba 100644 --- a/lazer/sdk/rust/protocol/src/jrpc.rs +++ b/lazer/sdk/rust/protocol/src/jrpc.rs @@ -7,15 +7,15 @@ use crate::symbol_state::SymbolState; pub struct PythLazerAgentJrpcV1 { pub jsonrpc: JsonRpcVersion, #[serde(flatten)] - pub params: JrpcParams, + pub params: JrpcCall, pub id: i64, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] #[serde(tag = "method", content = "params")] -pub enum JrpcParams { - #[serde(rename = "send_updates")] - SendUpdates(FeedUpdateParams), +pub enum JrpcCall { + #[serde(rename_all = "snake_case")] + PushUpdate(FeedUpdateParams), #[serde(rename = "get_symbols")] GetMetadata(GetMetadataParams), } @@ -128,7 +128,7 @@ pub struct SymbolMetadata { #[cfg(test)] mod tests { - use crate::jrpc::JrpcParams::{GetMetadata, SendUpdates}; + use crate::jrpc::JrpcCall::{GetMetadata, PushUpdate}; use crate::jrpc::{FeedUpdateParams, Filter, GetMetadataParams, JrpcErrorObject, JrpcErrorResponse, JrpcSuccessResponse, JsonRpcVersion, PythLazerAgentJrpcV1, UpdateParams}; use crate::router::{Price, PriceFeedId, Rate, TimestampUs}; From 1116639da68f8858c5a861573c4ce160c37defc6 Mon Sep 17 00:00:00 2001 From: Bart Platak Date: Wed, 9 Jul 2025 01:06:49 +0100 Subject: [PATCH 06/11] review --- lazer/sdk/rust/protocol/src/jrpc.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lazer/sdk/rust/protocol/src/jrpc.rs b/lazer/sdk/rust/protocol/src/jrpc.rs index 58fcdc02ba..11bfd3eb40 100644 --- a/lazer/sdk/rust/protocol/src/jrpc.rs +++ b/lazer/sdk/rust/protocol/src/jrpc.rs @@ -48,7 +48,8 @@ pub struct Filter { #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] pub struct GetMetadataParams { - pub filters: Option>, + pub names: Option>, + pub asset_types: Option>, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] From 478004dd9bdd69b2113bbbe7c01b1ec3772d1c89 Mon Sep 17 00:00:00 2001 From: Bart Platak Date: Wed, 9 Jul 2025 16:49:11 +0100 Subject: [PATCH 07/11] fix tests --- Cargo.lock | 11 ++++++++ lazer/sdk/rust/protocol/Cargo.toml | 1 + lazer/sdk/rust/protocol/src/jrpc.rs | 43 +++++++++++------------------ 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e454154c7..95bc4d9a42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4143,6 +4143,16 @@ dependencies = [ "serde_json", ] +[[package]] +name = "jsonrpc-types" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d203b1b00d03d1cee9ddcaf970d2ccdd40d8036d8fafef34a0b1b841486b232" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "jsonwebtoken" version = "8.3.0" @@ -5591,6 +5601,7 @@ dependencies = [ "hex", "humantime-serde", "itertools 0.13.0", + "jsonrpc-types", "libsecp256k1 0.7.2", "protobuf", "rust_decimal", diff --git a/lazer/sdk/rust/protocol/Cargo.toml b/lazer/sdk/rust/protocol/Cargo.toml index 1a467f3cc9..70c8a43f9e 100644 --- a/lazer/sdk/rust/protocol/Cargo.toml +++ b/lazer/sdk/rust/protocol/Cargo.toml @@ -16,6 +16,7 @@ itertools = "0.13.0" rust_decimal = "1.36.0" protobuf = "3.7.2" humantime-serde = "1.1.1" +jsonrpc-types = "0.3.3" [dev-dependencies] bincode = "1.3.3" diff --git a/lazer/sdk/rust/protocol/src/jrpc.rs b/lazer/sdk/rust/protocol/src/jrpc.rs index 11bfd3eb40..07b86609d9 100644 --- a/lazer/sdk/rust/protocol/src/jrpc.rs +++ b/lazer/sdk/rust/protocol/src/jrpc.rs @@ -13,10 +13,9 @@ pub struct PythLazerAgentJrpcV1 { #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] #[serde(tag = "method", content = "params")] +#[serde(rename_all = "snake_case")] pub enum JrpcCall { - #[serde(rename_all = "snake_case")] PushUpdate(FeedUpdateParams), - #[serde(rename = "get_symbols")] GetMetadata(GetMetadataParams), } @@ -134,11 +133,11 @@ mod tests { use crate::router::{Price, PriceFeedId, Rate, TimestampUs}; #[test] - fn test_send_updates_price() { + fn test_push_update_price() { let json = r#" { "jsonrpc": "2.0", - "method": "send_updates", + "method": "push_update", "params": { "feed_id": 1, "source_timestamp": 124214124124, @@ -156,7 +155,7 @@ mod tests { let expected = PythLazerAgentJrpcV1 { jsonrpc: JsonRpcVersion::V2, - params: SendUpdates(FeedUpdateParams { + params: PushUpdate(FeedUpdateParams { feed_id: PriceFeedId(1), source_timestamp: TimestampUs(124214124124), update: UpdateParams::PriceUpdate { @@ -175,11 +174,11 @@ mod tests { } #[test] - fn test_send_updates_funding_rate() { + fn test_push_update_funding_rate() { let json = r#" { "jsonrpc": "2.0", - "method": "send_updates", + "method": "push_update", "params": { "feed_id": 1, "source_timestamp": 124214124124, @@ -196,7 +195,7 @@ mod tests { let expected = PythLazerAgentJrpcV1 { jsonrpc: JsonRpcVersion::V2, - params: SendUpdates(FeedUpdateParams { + params: PushUpdate(FeedUpdateParams { feed_id: PriceFeedId(1), source_timestamp: TimestampUs(124214124124), update: UpdateParams::FundingRateUpdate { @@ -213,16 +212,14 @@ mod tests { ); } #[test] - fn test_send_get_symbols() { + fn test_send_get_metadata() { let json = r#" { "jsonrpc": "2.0", - "method": "get_symbols", + "method": "get_metadata", "params": { - "filters": [ - {"name": "BTC/USD"}, - {"asset_type": "crypto"} - ] + "names": ["BTC/USD"], + "asset_types": ["crypto"] }, "id": 1 } @@ -231,16 +228,8 @@ mod tests { let expected = PythLazerAgentJrpcV1 { jsonrpc: JsonRpcVersion::V2, params: GetMetadata(GetMetadataParams { - filters: Some(vec![ - Filter { - name: Some("BTC/USD".to_string()), - asset_type: None, - }, - Filter { - name: None, - asset_type: Some("crypto".to_string()), - }, - ]), + names: Some(vec!["BTC/USD".to_string()]), + asset_types: Some(vec!["crypto".to_string()]), }), id: 1, }; @@ -252,11 +241,11 @@ mod tests { } #[test] - fn test_get_symbols_without_filters() { + fn test_get_metadata_without_filters() { let json = r#" { "jsonrpc": "2.0", - "method": "get_symbols", + "method": "get_metadata", "params": {}, "id": 1 } @@ -264,7 +253,7 @@ mod tests { let expected = PythLazerAgentJrpcV1 { jsonrpc: JsonRpcVersion::V2, - params: GetMetadata(GetMetadataParams { filters: None }), + params: GetMetadata(GetMetadataParams { names: None, asset_types: None }), id: 1, }; From 3df3efd65217f7f51e50ed53c61edeecf97c768c Mon Sep 17 00:00:00 2001 From: Bart Platak Date: Wed, 9 Jul 2025 17:23:21 +0100 Subject: [PATCH 08/11] fix cargo checks --- lazer/sdk/rust/protocol/src/jrpc.rs | 61 +++++++++++++++++------------ 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/lazer/sdk/rust/protocol/src/jrpc.rs b/lazer/sdk/rust/protocol/src/jrpc.rs index 07b86609d9..8f1b98c94b 100644 --- a/lazer/sdk/rust/protocol/src/jrpc.rs +++ b/lazer/sdk/rust/protocol/src/jrpc.rs @@ -1,7 +1,7 @@ -use std::time::Duration; use crate::router::{Channel, Price, PriceFeedId, Rate, TimestampUs}; -use serde::{Deserialize, Serialize}; use crate::symbol_state::SymbolState; +use serde::{Deserialize, Serialize}; +use std::time::Duration; #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] pub struct PythLazerAgentJrpcV1 { @@ -91,6 +91,7 @@ pub enum JrpcError { InternalError, } +// note: error codes can be found in the rfc https://www.jsonrpc.org/specification#error_object impl From for JrpcErrorObject { fn from(error: JrpcError) -> Self { match error { @@ -128,9 +129,8 @@ pub struct SymbolMetadata { #[cfg(test)] mod tests { + use super::*; use crate::jrpc::JrpcCall::{GetMetadata, PushUpdate}; - use crate::jrpc::{FeedUpdateParams, Filter, GetMetadataParams, JrpcErrorObject, JrpcErrorResponse, JrpcSuccessResponse, JsonRpcVersion, PythLazerAgentJrpcV1, UpdateParams}; - use crate::router::{Price, PriceFeedId, Rate, TimestampUs}; #[test] fn test_push_update_price() { @@ -218,8 +218,8 @@ mod tests { "jsonrpc": "2.0", "method": "get_metadata", "params": { - "names": ["BTC/USD"], - "asset_types": ["crypto"] + "names": ["BTC/USD"], + "asset_types": ["crypto"] }, "id": 1 } @@ -253,7 +253,10 @@ mod tests { let expected = PythLazerAgentJrpcV1 { jsonrpc: JsonRpcVersion::V2, - params: GetMetadata(GetMetadataParams { names: None, asset_types: None }), + params: GetMetadata(GetMetadataParams { + names: None, + asset_types: None, + }), id: 1, }; @@ -275,18 +278,22 @@ mod tests { "code": -32603 } } - "# - ).unwrap(); + "#, + ) + .unwrap(); - assert_eq!(response, JrpcErrorResponse { - jsonrpc: JsonRpcVersion::V2, - error: JrpcErrorObject { - code: -32603, - message: "Internal error".to_string(), - data: None, - }, - id: Some(2), - }); + assert_eq!( + response, + JrpcErrorResponse { + jsonrpc: JsonRpcVersion::V2, + error: JrpcErrorObject { + code: -32603, + message: "Internal error".to_string(), + data: None, + }, + id: Some(2), + } + ); } #[test] @@ -298,13 +305,17 @@ mod tests { "id": 2, "result": "success" } - "# - ).unwrap(); + "#, + ) + .unwrap(); - assert_eq!(response, JrpcSuccessResponse:: { - jsonrpc: JsonRpcVersion::V2, - result: "success".to_string(), - id: 2, - }); + assert_eq!( + response, + JrpcSuccessResponse:: { + jsonrpc: JsonRpcVersion::V2, + result: "success".to_string(), + id: 2, + } + ); } } From ea69d88083f9bb879f5662c3b773494fd1cdc51a Mon Sep 17 00:00:00 2001 From: Bart Platak Date: Wed, 9 Jul 2025 17:29:39 +0100 Subject: [PATCH 09/11] remove unused dept, make some params optional, bump ver --- Cargo.lock | 41 +++++-------- lazer/sdk/rust/protocol/Cargo.toml | 3 +- lazer/sdk/rust/protocol/src/jrpc.rs | 89 +++++++++++++++++++++++++++-- 3 files changed, 99 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 95bc4d9a42..3f84f62804 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4143,16 +4143,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "jsonrpc-types" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d203b1b00d03d1cee9ddcaf970d2ccdd40d8036d8fafef34a0b1b841486b232" -dependencies = [ - "serde", - "serde_json", -] - [[package]] name = "jsonwebtoken" version = "8.3.0" @@ -5549,7 +5539,7 @@ dependencies = [ "hyper 1.6.0", "hyper-util", "protobuf", - "pyth-lazer-protocol 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "pyth-lazer-protocol 0.7.3", "pyth-lazer-publisher-sdk 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "serde", "serde_json", @@ -5578,7 +5568,7 @@ dependencies = [ "futures-util", "hex", "libsecp256k1 0.7.2", - "pyth-lazer-protocol 0.7.3", + "pyth-lazer-protocol 0.7.4", "serde", "serde_json", "tokio", @@ -5590,19 +5580,14 @@ dependencies = [ [[package]] name = "pyth-lazer-protocol" version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6445dc5d2f7fff7c677fb8edc5a080a82ef7583c1bdb39daa95421788c23f695" dependencies = [ - "alloy-primitives 0.8.25", "anyhow", - "bincode 1.3.3", - "bs58", + "base64 0.22.1", "byteorder", "derive_more 1.0.0", - "ed25519-dalek 2.1.1", - "hex", - "humantime-serde", "itertools 0.13.0", - "jsonrpc-types", - "libsecp256k1 0.7.2", "protobuf", "rust_decimal", "serde", @@ -5611,15 +5596,19 @@ dependencies = [ [[package]] name = "pyth-lazer-protocol" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6445dc5d2f7fff7c677fb8edc5a080a82ef7583c1bdb39daa95421788c23f695" +version = "0.7.4" dependencies = [ + "alloy-primitives 0.8.25", "anyhow", - "base64 0.22.1", + "bincode 1.3.3", + "bs58", "byteorder", "derive_more 1.0.0", + "ed25519-dalek 2.1.1", + "hex", + "humantime-serde", "itertools 0.13.0", + "libsecp256k1 0.7.2", "protobuf", "rust_decimal", "serde", @@ -5635,7 +5624,7 @@ dependencies = [ "humantime", "protobuf", "protobuf-codegen", - "pyth-lazer-protocol 0.7.3", + "pyth-lazer-protocol 0.7.4", "serde-value", "tracing", ] @@ -5651,7 +5640,7 @@ dependencies = [ "humantime", "protobuf", "protobuf-codegen", - "pyth-lazer-protocol 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "pyth-lazer-protocol 0.7.3", "serde-value", "tracing", ] diff --git a/lazer/sdk/rust/protocol/Cargo.toml b/lazer/sdk/rust/protocol/Cargo.toml index 70c8a43f9e..d0ef7aa904 100644 --- a/lazer/sdk/rust/protocol/Cargo.toml +++ b/lazer/sdk/rust/protocol/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pyth-lazer-protocol" -version = "0.7.3" +version = "0.8.0" edition = "2021" description = "Pyth Lazer SDK - protocol types." license = "Apache-2.0" @@ -16,7 +16,6 @@ itertools = "0.13.0" rust_decimal = "1.36.0" protobuf = "3.7.2" humantime-serde = "1.1.1" -jsonrpc-types = "0.3.3" [dev-dependencies] bincode = "1.3.3" diff --git a/lazer/sdk/rust/protocol/src/jrpc.rs b/lazer/sdk/rust/protocol/src/jrpc.rs index 8f1b98c94b..fa3fdce72c 100644 --- a/lazer/sdk/rust/protocol/src/jrpc.rs +++ b/lazer/sdk/rust/protocol/src/jrpc.rs @@ -32,11 +32,11 @@ pub enum UpdateParams { #[serde(rename = "price")] PriceUpdate { price: Price, - best_bid_price: Price, - best_ask_price: Price, + best_bid_price: Option, + best_ask_price: Option, }, #[serde(rename = "funding_rate")] - FundingRateUpdate { price: Price, rate: Rate }, + FundingRateUpdate { price: Option, rate: Rate }, } #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] @@ -160,8 +160,47 @@ mod tests { source_timestamp: TimestampUs(124214124124), update: UpdateParams::PriceUpdate { price: Price::from_integer(1234567890, 0).unwrap(), - best_bid_price: Price::from_integer(1234567891, 0).unwrap(), - best_ask_price: Price::from_integer(1234567892, 0).unwrap(), + best_bid_price: Some(Price::from_integer(1234567891, 0).unwrap()), + best_ask_price: Some(Price::from_integer(1234567892, 0).unwrap()), + }, + }), + id: 1, + }; + + assert_eq!( + serde_json::from_str::(json).unwrap(), + expected + ); + } + + #[test] + fn test_push_update_price_without_bid_ask() { + let json = r#" + { + "jsonrpc": "2.0", + "method": "push_update", + "params": { + "feed_id": 1, + "source_timestamp": 124214124124, + + "update": { + "type": "price", + "price": 1234567890 + } + }, + "id": 1 + } + "#; + + let expected = PythLazerAgentJrpcV1 { + jsonrpc: JsonRpcVersion::V2, + params: PushUpdate(FeedUpdateParams { + feed_id: PriceFeedId(1), + source_timestamp: TimestampUs(124214124124), + update: UpdateParams::PriceUpdate { + price: Price::from_integer(1234567890, 0).unwrap(), + best_bid_price: None, + best_ask_price: None, }, }), id: 1, @@ -199,7 +238,7 @@ mod tests { feed_id: PriceFeedId(1), source_timestamp: TimestampUs(124214124124), update: UpdateParams::FundingRateUpdate { - price: Price::from_integer(1234567890, 0).unwrap(), + price: Some(Price::from_integer(1234567890, 0).unwrap()), rate: Rate::from_integer(1234567891, 0).unwrap(), }, }), @@ -211,6 +250,44 @@ mod tests { expected ); } + #[test] + fn test_push_update_funding_rate_without_price() { + let json = r#" + { + "jsonrpc": "2.0", + "method": "push_update", + "params": { + "feed_id": 1, + "source_timestamp": 124214124124, + + "update": { + "type": "funding_rate", + "rate": 1234567891 + } + }, + "id": 1 + } + "#; + + let expected = PythLazerAgentJrpcV1 { + jsonrpc: JsonRpcVersion::V2, + params: PushUpdate(FeedUpdateParams { + feed_id: PriceFeedId(1), + source_timestamp: TimestampUs(124214124124), + update: UpdateParams::FundingRateUpdate { + price: None, + rate: Rate::from_integer(1234567891, 0).unwrap(), + }, + }), + id: 1, + }; + + assert_eq!( + serde_json::from_str::(json).unwrap(), + expected + ); + } + #[test] fn test_send_get_metadata() { let json = r#" From 9b40549fcad312fd5f63bbcd126dad41511552cc Mon Sep 17 00:00:00 2001 From: Bart Platak Date: Wed, 9 Jul 2025 17:41:25 +0100 Subject: [PATCH 10/11] remove unused dept, make some params optional, bump ver --- Cargo.lock | 6 +++--- .../solana/programs/pyth-lazer-solana-contract/Cargo.toml | 2 +- lazer/publisher_sdk/rust/Cargo.toml | 2 +- lazer/publisher_sdk/rust/src/lib.rs | 6 +++--- lazer/sdk/rust/client/Cargo.toml | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3f84f62804..47aa66fc91 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5568,7 +5568,7 @@ dependencies = [ "futures-util", "hex", "libsecp256k1 0.7.2", - "pyth-lazer-protocol 0.7.4", + "pyth-lazer-protocol 0.8.0", "serde", "serde_json", "tokio", @@ -5596,7 +5596,7 @@ dependencies = [ [[package]] name = "pyth-lazer-protocol" -version = "0.7.4" +version = "0.8.0" dependencies = [ "alloy-primitives 0.8.25", "anyhow", @@ -5624,7 +5624,7 @@ dependencies = [ "humantime", "protobuf", "protobuf-codegen", - "pyth-lazer-protocol 0.7.4", + "pyth-lazer-protocol 0.8.0", "serde-value", "tracing", ] diff --git a/lazer/contracts/solana/programs/pyth-lazer-solana-contract/Cargo.toml b/lazer/contracts/solana/programs/pyth-lazer-solana-contract/Cargo.toml index aa3e2a9f85..4888f6669e 100644 --- a/lazer/contracts/solana/programs/pyth-lazer-solana-contract/Cargo.toml +++ b/lazer/contracts/solana/programs/pyth-lazer-solana-contract/Cargo.toml @@ -19,7 +19,7 @@ no-log-ix-name = [] idl-build = ["anchor-lang/idl-build"] [dependencies] -pyth-lazer-protocol = { path = "../../../../sdk/rust/protocol", version = "0.7.2" } +pyth-lazer-protocol = { path = "../../../../sdk/rust/protocol", version = "0.8.0" } anchor-lang = "0.30.1" bytemuck = "1.20.0" diff --git a/lazer/publisher_sdk/rust/Cargo.toml b/lazer/publisher_sdk/rust/Cargo.toml index 13f8bb6c61..25c00f42c3 100644 --- a/lazer/publisher_sdk/rust/Cargo.toml +++ b/lazer/publisher_sdk/rust/Cargo.toml @@ -7,7 +7,7 @@ license = "Apache-2.0" repository = "https://github.com/pyth-network/pyth-crosschain" [dependencies] -pyth-lazer-protocol = { version = "0.7.2", path = "../../sdk/rust/protocol" } +pyth-lazer-protocol = { version = "0.8.0", path = "../../sdk/rust/protocol" } anyhow = "1.0.98" protobuf = "3.7.2" serde-value = "0.7.0" diff --git a/lazer/publisher_sdk/rust/src/lib.rs b/lazer/publisher_sdk/rust/src/lib.rs index 1dd1f350f2..d027371f97 100644 --- a/lazer/publisher_sdk/rust/src/lib.rs +++ b/lazer/publisher_sdk/rust/src/lib.rs @@ -188,13 +188,13 @@ impl From for Update { best_ask_price, } => Update::PriceUpdate(PriceUpdate { price: Some(price.0.into()), - best_bid_price: Some(best_bid_price.0.into()), - best_ask_price: Some(best_ask_price.0.into()), + best_bid_price: best_bid_price.map(|p| p.0.into()), + best_ask_price: best_ask_price.map(|p| p.0.into()), special_fields: Default::default(), }), UpdateParams::FundingRateUpdate { price, rate } => { Update::FundingRateUpdate(FundingRateUpdate { - price: Some(price.0.into()), + price: price.map(|p| p.0.into()), rate: Some(rate.0), special_fields: Default::default(), }) diff --git a/lazer/sdk/rust/client/Cargo.toml b/lazer/sdk/rust/client/Cargo.toml index 4670ea301b..405556457f 100644 --- a/lazer/sdk/rust/client/Cargo.toml +++ b/lazer/sdk/rust/client/Cargo.toml @@ -6,7 +6,7 @@ description = "A Rust client for Pyth Lazer" license = "Apache-2.0" [dependencies] -pyth-lazer-protocol = { path = "../protocol", version = "0.7.2" } +pyth-lazer-protocol = { path = "../protocol", version = "0.8.0" } tokio = { version = "1", features = ["full"] } tokio-tungstenite = { version = "0.20", features = ["native-tls"] } futures-util = "0.3" From 28e13465fe683af5fae1d609b99ca3cbe2da45de Mon Sep 17 00:00:00 2001 From: Bart Platak Date: Wed, 9 Jul 2025 18:13:39 +0100 Subject: [PATCH 11/11] up version in cargo.lock for solana contract --- lazer/contracts/solana/Cargo.lock | 36 +++++++++++-------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/lazer/contracts/solana/Cargo.lock b/lazer/contracts/solana/Cargo.lock index d689daad3a..a4b07b8930 100644 --- a/lazer/contracts/solana/Cargo.lock +++ b/lazer/contracts/solana/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "Inflector" @@ -616,12 +616,6 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - [[package]] name = "base64ct" version = "1.6.0" @@ -2006,6 +2000,16 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" +[[package]] +name = "humantime-serde" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a3db5ea5923d99402c94e9feb261dc5ee9b4efa158b0315f788cf549cc200c" +dependencies = [ + "humantime", + "serde", +] + [[package]] name = "hyper" version = "0.14.31" @@ -3200,12 +3204,12 @@ dependencies = [ [[package]] name = "pyth-lazer-protocol" -version = "0.7.3" +version = "0.8.0" dependencies = [ "anyhow", - "base64 0.22.1", "byteorder", "derive_more", + "humantime-serde", "itertools 0.13.0", "protobuf", "rust_decimal", @@ -3213,20 +3217,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "pyth-lazer-publisher-sdk" -version = "0.1.6" -dependencies = [ - "anyhow", - "fs-err", - "humantime", - "protobuf", - "protobuf-codegen", - "pyth-lazer-protocol", - "serde-value", - "tracing", -] - [[package]] name = "pyth-lazer-solana-contract" version = "0.4.2"