Explorar o código

Remove 1ms fixed rate from lazer fixed rate channels (#2953)

Dani Mehrjerdi hai 3 meses
pai
achega
fa901a600e

+ 5 - 5
Cargo.lock

@@ -5669,7 +5669,7 @@ dependencies = [
 
 [[package]]
 name = "pyth-lazer-client"
-version = "2.0.1"
+version = "2.1.0"
 dependencies = [
  "alloy-primitives 0.8.25",
  "anyhow",
@@ -5682,7 +5682,7 @@ dependencies = [
  "futures-util",
  "hex",
  "libsecp256k1 0.7.2",
- "pyth-lazer-protocol 0.10.2",
+ "pyth-lazer-protocol 0.12.0",
  "serde",
  "serde_json",
  "tokio",
@@ -5715,7 +5715,7 @@ dependencies = [
 
 [[package]]
 name = "pyth-lazer-protocol"
-version = "0.10.2"
+version = "0.12.0"
 dependencies = [
  "alloy-primitives 0.8.25",
  "anyhow",
@@ -5753,13 +5753,13 @@ dependencies = [
 
 [[package]]
 name = "pyth-lazer-publisher-sdk"
-version = "0.5.0"
+version = "0.6.0"
 dependencies = [
  "anyhow",
  "fs-err",
  "protobuf",
  "protobuf-codegen",
- "pyth-lazer-protocol 0.10.2",
+ "pyth-lazer-protocol 0.12.0",
  "serde_json",
 ]
 

+ 1 - 1
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.10.1" }
+pyth-lazer-protocol = { path = "../../../../sdk/rust/protocol", version = "0.12.0" }
 
 anchor-lang = "0.31.1"
 bytemuck = { version = "1.20.0", features = ["derive"] }

+ 2 - 2
lazer/publisher_sdk/proto/governance_instruction.proto

@@ -235,7 +235,7 @@ message AddFeed {
     // [required]
     optional uint32 min_publishers = 103;
     // [required]
-    optional google.protobuf.Duration min_rate = 104;
+    optional Channel min_channel = 104;
     // [required]
     optional google.protobuf.Duration expiry_time = 105;
     // [required]
@@ -282,7 +282,7 @@ message UpdateFeedProperties {
     // [optional]
     optional uint32 min_publishers = 103;
     // [optional]
-    optional google.protobuf.Duration min_rate = 104;
+    optional Channel min_channel = 104;
     // [optional]
     optional google.protobuf.Duration expiry_time = 105;
     // [optional]

+ 11 - 2
lazer/publisher_sdk/proto/state.proto

@@ -3,11 +3,20 @@ package pyth_lazer;
 
 import "google/protobuf/duration.proto";
 import "google/protobuf/timestamp.proto";
+import "google/protobuf/empty.proto";
 
 import "dynamic_value.proto";
 
+
 // All optional fields should always be set unless documented otherwise.
 
+message Channel {
+    oneof kind {
+        google.protobuf.Duration rate = 1;
+        google.protobuf.Empty real_time = 2;
+    }
+}
+
 // State of a Pyth Lazer shard.
 //
 // The state is shared across all Pyth Lazer aggregators that process this shard.
@@ -92,9 +101,9 @@ message Feed {
     optional sint32 exponent = 102;
     // [required] Minimal number of publisher prices required to produce an aggregate.
     optional uint32 min_publishers = 103;
-    // [required] Minimal rate of aggregation performed by the aggregator for this feed.
+    // [required] Minimal channel of aggregation performed by the aggregator for this feed.
     // Cannot be lower than the shard's top level `State.min_rate`.
-    optional google.protobuf.Duration min_rate = 104;
+    optional Channel min_channel = 104;
     // [required] Time after which the publisher update is discarded.
     optional google.protobuf.Duration expiry_time = 105;
     // [required] Market schedule in Pythnet format.

+ 2 - 2
lazer/publisher_sdk/rust/Cargo.toml

@@ -1,13 +1,13 @@
 [package]
 name = "pyth-lazer-publisher-sdk"
-version = "0.5.0"
+version = "0.6.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.10.2", path = "../../sdk/rust/protocol" }
+pyth-lazer-protocol = { version = "0.12.0", path = "../../sdk/rust/protocol" }
 anyhow = "1.0.98"
 protobuf = "3.7.2"
 serde_json = "1.0.140"

+ 33 - 0
lazer/publisher_sdk/rust/src/lib.rs

@@ -114,3 +114,36 @@ impl From<state::FeedKind> for FeedKind {
         }
     }
 }
+
+impl TryFrom<state::Channel> for pyth_lazer_protocol::router::Channel {
+    type Error = anyhow::Error;
+
+    fn try_from(value: state::Channel) -> Result<Self, Self::Error> {
+        Ok(match value.kind {
+            Some(kind) => match kind {
+                state::channel::Kind::Rate(rate) => {
+                    pyth_lazer_protocol::router::Channel::FixedRate(rate.try_into()?)
+                }
+                state::channel::Kind::RealTime(_) => pyth_lazer_protocol::router::Channel::RealTime,
+            },
+            None => pyth_lazer_protocol::router::Channel::FixedRate(
+                pyth_lazer_protocol::router::FixedRate::MIN,
+            ),
+        })
+    }
+}
+
+impl From<pyth_lazer_protocol::router::Channel> for state::Channel {
+    fn from(value: pyth_lazer_protocol::router::Channel) -> Self {
+        let mut result = state::Channel::new();
+        match value {
+            pyth_lazer_protocol::router::Channel::FixedRate(rate) => {
+                result.set_rate(rate.into());
+            }
+            pyth_lazer_protocol::router::Channel::RealTime => {
+                result.set_real_time(::protobuf::well_known_types::empty::Empty::new());
+            }
+        };
+        result
+    }
+}

+ 2 - 2
lazer/sdk/rust/client/Cargo.toml

@@ -1,12 +1,12 @@
 [package]
 name = "pyth-lazer-client"
-version = "2.0.1"
+version = "2.1.0"
 edition = "2021"
 description = "A Rust client for Pyth Lazer"
 license = "Apache-2.0"
 
 [dependencies]
-pyth-lazer-protocol = { path = "../protocol", version = "0.10.2" }
+pyth-lazer-protocol = { path = "../protocol", version = "0.12.0" }
 tokio = { version = "1", features = ["full"] }
 tokio-tungstenite = { version = "0.20", features = ["native-tls"] }
 futures-util = "0.3"

+ 1 - 1
lazer/sdk/rust/protocol/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = "pyth-lazer-protocol"
-version = "0.10.2"
+version = "0.12.0"
 edition = "2021"
 description = "Pyth Lazer SDK - protocol types."
 license = "Apache-2.0"

+ 30 - 21
lazer/sdk/rust/protocol/src/router.rs

@@ -12,6 +12,7 @@ use {
     rust_decimal::{prelude::FromPrimitive, Decimal},
     serde::{de::Error, Deserialize, Serialize},
     std::{
+        cmp::Ordering,
         fmt::Display,
         num::NonZeroI64,
         ops::{Add, Deref, DerefMut, Div, Sub},
@@ -206,9 +207,24 @@ pub enum JsonBinaryEncoding {
     Hex,
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, From)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, From)]
 pub enum Channel {
     FixedRate(FixedRate),
+    RealTime,
+}
+
+impl PartialOrd for Channel {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        let rate_left = match self {
+            Channel::FixedRate(rate) => rate.duration().as_micros(),
+            Channel::RealTime => FixedRate::MIN.duration().as_micros(),
+        };
+        let rate_right = match other {
+            Channel::FixedRate(rate) => rate.duration().as_micros(),
+            Channel::RealTime => FixedRate::MIN.duration().as_micros(),
+        };
+        Some(rate_left.cmp(&rate_right))
+    }
 }
 
 impl Serialize for Channel {
@@ -217,15 +233,11 @@ impl Serialize for Channel {
         S: serde::Serializer,
     {
         match self {
-            Channel::FixedRate(fixed_rate) => {
-                if *fixed_rate == FixedRate::MIN {
-                    return serializer.serialize_str("real_time");
-                }
-                serializer.serialize_str(&format!(
-                    "fixed_rate@{}ms",
-                    fixed_rate.duration().as_millis()
-                ))
-            }
+            Channel::FixedRate(fixed_rate) => serializer.serialize_str(&format!(
+                "fixed_rate@{}ms",
+                fixed_rate.duration().as_millis()
+            )),
+            Channel::RealTime => serializer.serialize_str("real_time"),
         }
     }
 }
@@ -233,7 +245,7 @@ impl Serialize for Channel {
 pub mod channel_ids {
     use super::ChannelId;
 
-    pub const FIXED_RATE_1: ChannelId = ChannelId(1);
+    pub const REAL_TIME: ChannelId = ChannelId(1);
     pub const FIXED_RATE_50: ChannelId = ChannelId(2);
     pub const FIXED_RATE_200: ChannelId = ChannelId(3);
 }
@@ -241,10 +253,10 @@ pub mod channel_ids {
 impl Display for Channel {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         match self {
-            Channel::FixedRate(fixed_rate) => match *fixed_rate {
-                FixedRate::MIN => write!(f, "real_time"),
-                rate => write!(f, "fixed_rate@{}ms", rate.duration().as_millis()),
-            },
+            Channel::FixedRate(fixed_rate) => {
+                write!(f, "fixed_rate@{}ms", fixed_rate.duration().as_millis())
+            }
+            Channel::RealTime => write!(f, "real_time"),
         }
     }
 }
@@ -253,11 +265,11 @@ impl Channel {
     pub fn id(&self) -> ChannelId {
         match self {
             Channel::FixedRate(fixed_rate) => match fixed_rate.duration().as_millis() {
-                1 => channel_ids::FIXED_RATE_1,
                 50 => channel_ids::FIXED_RATE_50,
                 200 => channel_ids::FIXED_RATE_200,
                 _ => panic!("unknown channel: {self:?}"),
             },
+            Channel::RealTime => channel_ids::REAL_TIME,
         }
     }
 }
@@ -271,7 +283,7 @@ fn id_supports_all_fixed_rates() {
 
 fn parse_channel(value: &str) -> Option<Channel> {
     if value == "real_time" {
-        Some(Channel::FixedRate(FixedRate::MIN))
+        Some(Channel::RealTime)
     } else if let Some(rest) = value.strip_prefix("fixed_rate@") {
         let ms_value = rest.strip_suffix("ms")?;
         Some(Channel::FixedRate(FixedRate::from_millis(
@@ -298,9 +310,6 @@ pub struct FixedRate {
 }
 
 impl FixedRate {
-    pub const RATE_1_MS: Self = Self {
-        rate: DurationUs::from_millis_u32(1),
-    };
     pub const RATE_50_MS: Self = Self {
         rate: DurationUs::from_millis_u32(50),
     };
@@ -312,7 +321,7 @@ impl FixedRate {
     // - Values are sorted.
     // - 1 second contains a whole number of each interval.
     // - all intervals are divisable by the smallest interval.
-    pub const ALL: [Self; 3] = [Self::RATE_1_MS, Self::RATE_50_MS, Self::RATE_200_MS];
+    pub const ALL: [Self; 2] = [Self::RATE_50_MS, Self::RATE_200_MS];
     pub const MIN: Self = Self::ALL[0];
 
     pub fn from_millis(millis: u32) -> Option<Self> {