diff --git a/Cargo.lock b/Cargo.lock index bd4c6c5dff..4d2251bf1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5674,7 +5674,7 @@ dependencies = [ "hyper 1.6.0", "hyper-util", "protobuf", - "pyth-lazer-protocol 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pyth-lazer-protocol 0.14.0", "pyth-lazer-publisher-sdk 0.10.0", "reqwest 0.12.23", "serde", @@ -5693,7 +5693,7 @@ dependencies = [ [[package]] name = "pyth-lazer-client" -version = "7.0.0" +version = "8.0.0" dependencies = [ "alloy-primitives 0.8.25", "anyhow", @@ -5711,7 +5711,7 @@ dependencies = [ "hex", "humantime-serde", "libsecp256k1 0.7.2", - "pyth-lazer-protocol 0.14.0", + "pyth-lazer-protocol 0.15.0", "reqwest 0.12.23", "serde", "serde_json", @@ -5726,22 +5726,17 @@ dependencies = [ [[package]] name = "pyth-lazer-protocol" version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91b3e69c264b2ad80b5943df86c606daae63b13f93062abcc008c09a9e2e621e" dependencies = [ - "alloy-primitives 0.8.25", "anyhow", - "assert_float_eq", - "bincode 1.3.3", - "bs58", "byteorder", "chrono", "derive_more 1.0.0", - "ed25519-dalek 2.1.1", "hex", "humantime", "humantime-serde", "itertools 0.13.0", - "libsecp256k1 0.7.2", - "mry", "protobuf", "rust_decimal", "serde", @@ -5751,18 +5746,23 @@ dependencies = [ [[package]] name = "pyth-lazer-protocol" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91b3e69c264b2ad80b5943df86c606daae63b13f93062abcc008c09a9e2e621e" +version = "0.15.0" dependencies = [ + "alloy-primitives 0.8.25", "anyhow", + "assert_float_eq", + "bincode 1.3.3", + "bs58", "byteorder", "chrono", "derive_more 1.0.0", + "ed25519-dalek 2.1.1", "hex", "humantime", "humantime-serde", "itertools 0.13.0", + "libsecp256k1 0.7.2", + "mry", "protobuf", "rust_decimal", "serde", @@ -5780,19 +5780,19 @@ dependencies = [ "fs-err", "protobuf", "protobuf-codegen", - "pyth-lazer-protocol 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pyth-lazer-protocol 0.14.0", "serde_json", ] [[package]] name = "pyth-lazer-publisher-sdk" -version = "0.11.0" +version = "0.12.0" dependencies = [ "anyhow", "fs-err", "protobuf", "protobuf-codegen", - "pyth-lazer-protocol 0.14.0", + "pyth-lazer-protocol 0.15.0", "serde_json", ] 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 966801484b..11b7baf8a0 100644 --- a/lazer/contracts/solana/programs/pyth-lazer-solana-contract/Cargo.toml +++ b/lazer/contracts/solana/programs/pyth-lazer-solana-contract/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pyth-lazer-solana-contract" -version = "0.6.0" +version = "0.7.0" edition = "2021" description = "Pyth Lazer Solana contract and SDK." license = "Apache-2.0" @@ -19,7 +19,7 @@ no-log-ix-name = [] idl-build = ["anchor-lang/idl-build"] [dependencies] -pyth-lazer-protocol = { path = "../../../../sdk/rust/protocol", version = "0.14.0" } +pyth-lazer-protocol = { path = "../../../../sdk/rust/protocol", version = "0.15.0" } anchor-lang = "0.31.1" bytemuck = { version = "1.20.0", features = ["derive"] } diff --git a/lazer/publisher_sdk/rust/Cargo.toml b/lazer/publisher_sdk/rust/Cargo.toml index e2fdeb8753..b1cbc3d1e5 100644 --- a/lazer/publisher_sdk/rust/Cargo.toml +++ b/lazer/publisher_sdk/rust/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "pyth-lazer-publisher-sdk" -version = "0.11.0" +version = "0.12.0" edition = "2021" description = "Pyth Lazer Publisher SDK types." license = "Apache-2.0" repository = "https://github.com/pyth-network/pyth-crosschain" [dependencies] -pyth-lazer-protocol = { version = "0.14.0", path = "../../sdk/rust/protocol" } +pyth-lazer-protocol = { version = "0.15.0", path = "../../sdk/rust/protocol" } anyhow = "1.0.98" protobuf = "3.7.2" serde_json = "1.0.140" diff --git a/lazer/sdk/rust/client/Cargo.toml b/lazer/sdk/rust/client/Cargo.toml index 029bb7d3f0..f93285720c 100644 --- a/lazer/sdk/rust/client/Cargo.toml +++ b/lazer/sdk/rust/client/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "pyth-lazer-client" -version = "7.0.0" +version = "8.0.0" edition = "2021" description = "A Rust client for Pyth Lazer" license = "Apache-2.0" [dependencies] -pyth-lazer-protocol = { path = "../protocol", version = "0.14.0" } +pyth-lazer-protocol = { path = "../protocol", version = "0.15.0" } tokio = { version = "1", features = ["full"] } tokio-tungstenite = { version = "0.20", features = ["native-tls"] } futures-util = "0.3" diff --git a/lazer/sdk/rust/client/examples/subscribe_price_feeds.rs b/lazer/sdk/rust/client/examples/subscribe_price_feeds.rs index 24eac797ae..d1856bc2d5 100644 --- a/lazer/sdk/rust/client/examples/subscribe_price_feeds.rs +++ b/lazer/sdk/rust/client/examples/subscribe_price_feeds.rs @@ -56,11 +56,12 @@ async fn main() -> anyhow::Result<()> { pin!(stream); let subscription_requests = vec![ - // Example subscription: Parsed JSON feed targeting Solana + // Example subscription: Parsed JSON feed targeting Solana, specified by price feed ids SubscribeRequest { subscription_id: SubscriptionId(1), params: SubscriptionParams::new(SubscriptionParamsRepr { - price_feed_ids: vec![PriceFeedId(1), PriceFeedId(2)], + price_feed_ids: Some(vec![PriceFeedId(1), PriceFeedId(2)]), + symbols: None, properties: vec![ PriceFeedProperty::Price, PriceFeedProperty::Exponent, @@ -72,15 +73,20 @@ async fn main() -> anyhow::Result<()> { json_binary_encoding: JsonBinaryEncoding::Base64, parsed: true, channel: Channel::FixedRate(FixedRate::RATE_200_MS), - ignore_invalid_feed_ids: false, + ignore_invalid_feeds: false, }) .expect("invalid subscription params"), }, - // Example subscription: binary feed targeting Solana and EVM + // Example subscription: binary feed targeting Solana and EVM, specified by price feed symbols SubscribeRequest { subscription_id: SubscriptionId(2), params: SubscriptionParams::new(SubscriptionParamsRepr { - price_feed_ids: vec![PriceFeedId(3), PriceFeedId(4)], + price_feed_ids: None, + symbols: Some(vec![ + "Crypto.BTC/USD".to_string(), + "Crypto.ETH/USD".to_string(), + "Crypto.PYTH/USD".to_string(), + ]), properties: vec![ PriceFeedProperty::Price, PriceFeedProperty::Exponent, @@ -92,7 +98,7 @@ async fn main() -> anyhow::Result<()> { json_binary_encoding: JsonBinaryEncoding::Base64, parsed: false, channel: Channel::FixedRate(FixedRate::RATE_50_MS), - ignore_invalid_feed_ids: false, + ignore_invalid_feeds: false, }) .expect("invalid subscription params"), }, diff --git a/lazer/sdk/rust/protocol/Cargo.toml b/lazer/sdk/rust/protocol/Cargo.toml index 47232d91c2..c95e0e85c0 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.14.0" +version = "0.15.0" edition = "2021" description = "Pyth Lazer SDK - protocol types." license = "Apache-2.0" diff --git a/lazer/sdk/rust/protocol/src/api.rs b/lazer/sdk/rust/protocol/src/api.rs index c5a17d21fc..27aa8a83e1 100644 --- a/lazer/sdk/rust/protocol/src/api.rs +++ b/lazer/sdk/rust/protocol/src/api.rs @@ -17,7 +17,8 @@ use crate::{ #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct LatestPriceRequest { - pub price_feed_ids: Vec, + pub price_feed_ids: Option>, + pub symbols: Option>, pub properties: Vec, // "chains" was renamed to "formats". "chains" is still supported for compatibility. #[serde(alias = "chains")] @@ -35,7 +36,9 @@ pub struct LatestPriceRequest { #[serde(rename_all = "camelCase")] pub struct PriceRequest { pub timestamp: TimestampUs, - pub price_feed_ids: Vec, + // Either price feed ids or symbols must be specified. + pub price_feed_ids: Option>, + pub symbols: Option>, pub properties: Vec, pub formats: Vec, #[serde(default)] @@ -181,7 +184,9 @@ impl<'de> Deserialize<'de> for Channel { #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SubscriptionParamsRepr { - pub price_feed_ids: Vec, + // Either price feed ids or symbols must be specified. + pub price_feed_ids: Option>, + pub symbols: Option>, pub properties: Vec, // "chains" was renamed to "formats". "chains" is still supported for compatibility. #[serde(alias = "chains")] @@ -195,8 +200,9 @@ pub struct SubscriptionParamsRepr { #[serde(default = "default_parsed")] pub parsed: bool, pub channel: Channel, - #[serde(default)] - pub ignore_invalid_feed_ids: bool, + // "ignoreInvalidFeedIds" was renamed to "ignoreInvalidFeeds". "ignoreInvalidFeedIds" is still supported for compatibility. + #[serde(default, alias = "ignoreInvalidFeedIds")] + pub ignore_invalid_feeds: bool, } #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)] @@ -215,12 +221,31 @@ impl<'de> Deserialize<'de> for SubscriptionParams { impl SubscriptionParams { pub fn new(value: SubscriptionParamsRepr) -> Result { - if value.price_feed_ids.is_empty() { - return Err("no price feed ids specified"); + if value.price_feed_ids.is_none() && value.symbols.is_none() { + return Err("either price feed ids or symbols must be specified"); } - if !value.price_feed_ids.iter().all_unique() { - return Err("duplicate price feed ids specified"); + if value.price_feed_ids.is_some() && value.symbols.is_some() { + return Err("either price feed ids or symbols must be specified, not both"); } + + if let Some(ref ids) = value.price_feed_ids { + if ids.is_empty() { + return Err("no price feed ids specified"); + } + if !ids.iter().all_unique() { + return Err("duplicate price feed ids specified"); + } + } + + if let Some(ref symbols) = value.symbols { + if symbols.is_empty() { + return Err("no symbols specified"); + } + if !symbols.iter().all_unique() { + return Err("duplicate symbols specified"); + } + } + if !value.formats.iter().all_unique() { return Err("duplicate formats or chains specified"); }