瀏覽代碼

feat: refactor pyth lazer protocol (#2945)

Keyvan Khademi 2 月之前
父節點
當前提交
61d7e0ae25

+ 5 - 5
Cargo.lock

@@ -5675,7 +5675,7 @@ dependencies = [
 
 [[package]]
 name = "pyth-lazer-client"
-version = "5.0.0"
+version = "6.0.0"
 dependencies = [
  "alloy-primitives 0.8.25",
  "anyhow",
@@ -5688,7 +5688,7 @@ dependencies = [
  "futures-util",
  "hex",
  "libsecp256k1 0.7.2",
- "pyth-lazer-protocol 0.13.0",
+ "pyth-lazer-protocol 0.14.0",
  "serde",
  "serde_json",
  "tokio",
@@ -5721,7 +5721,7 @@ dependencies = [
 
 [[package]]
 name = "pyth-lazer-protocol"
-version = "0.13.0"
+version = "0.14.0"
 dependencies = [
  "alloy-primitives 0.8.25",
  "anyhow",
@@ -5761,13 +5761,13 @@ dependencies = [
 
 [[package]]
 name = "pyth-lazer-publisher-sdk"
-version = "0.8.0"
+version = "0.9.0"
 dependencies = [
  "anyhow",
  "fs-err",
  "protobuf",
  "protobuf-codegen",
- "pyth-lazer-protocol 0.13.0",
+ "pyth-lazer-protocol 0.14.0",
  "serde_json",
 ]
 

+ 3 - 2
lazer/contracts/solana/Cargo.lock

@@ -3293,7 +3293,7 @@ dependencies = [
 
 [[package]]
 name = "pyth-lazer-protocol"
-version = "0.10.2"
+version = "0.12.0"
 dependencies = [
  "anyhow",
  "byteorder",
@@ -3307,11 +3307,12 @@ dependencies = [
  "rust_decimal",
  "serde",
  "serde_json",
+ "thiserror 2.0.12",
 ]
 
 [[package]]
 name = "pyth-lazer-solana-contract"
-version = "0.5.0"
+version = "0.6.0"
 dependencies = [
  "anchor-lang",
  "bytemuck",

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

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

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

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

@@ -1,12 +1,12 @@
 [package]
 name = "pyth-lazer-client"
-version = "5.0.0"
+version = "6.0.0"
 edition = "2021"
 description = "A Rust client for Pyth Lazer"
 license = "Apache-2.0"
 
 [dependencies]
-pyth-lazer-protocol = { path = "../protocol", version = "0.13.0" }
+pyth-lazer-protocol = { path = "../protocol", version = "0.14.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.13.0"
+version = "0.14.0"
 edition = "2021"
 description = "Pyth Lazer SDK - protocol types."
 license = "Apache-2.0"

+ 43 - 38
lazer/sdk/rust/protocol/src/price.rs

@@ -27,17 +27,17 @@ pub struct Price(NonZeroI64);
 
 impl Price {
     pub fn from_integer(value: i64, exponent: i16) -> Result<Price, PriceError> {
-        let value = match ExponentFactor::get(exponent).ok_or(PriceError::Overflow)? {
+        let mantissa = match ExponentFactor::get(exponent).ok_or(PriceError::Overflow)? {
             ExponentFactor::Mul(coef) => value.checked_mul(coef).ok_or(PriceError::Overflow)?,
             ExponentFactor::Div(coef) => value.checked_div(coef).ok_or(PriceError::Overflow)?,
         };
-        let value = NonZeroI64::new(value).ok_or(PriceError::ZeroPriceUnsupported)?;
-        Ok(Self(value))
+        let mantissa = NonZeroI64::new(mantissa).ok_or(PriceError::ZeroPriceUnsupported)?;
+        Ok(Self(mantissa))
     }
 
     pub fn parse_str(value: &str, exponent: i16) -> Result<Price, PriceError> {
         let value: Decimal = value.parse()?;
-        let value = match ExponentFactor::get(exponent).ok_or(PriceError::Overflow)? {
+        let mantissa = match ExponentFactor::get(exponent).ok_or(PriceError::Overflow)? {
             ExponentFactor::Mul(coef) => value
                 .checked_mul(Decimal::from_i64(coef).ok_or(PriceError::Overflow)?)
                 .ok_or(PriceError::Overflow)?,
@@ -45,12 +45,12 @@ impl Price {
                 .checked_div(Decimal::from_i64(coef).ok_or(PriceError::Overflow)?)
                 .ok_or(PriceError::Overflow)?,
         };
-        if !value.is_integer() {
+        if !mantissa.is_integer() {
             return Err(PriceError::TooPrecise);
         }
-        let value: i64 = value.try_into().map_err(|_| PriceError::Overflow)?;
-        let value = NonZeroI64::new(value).ok_or(PriceError::Overflow)?;
-        Ok(Self(value))
+        let mantissa: i64 = mantissa.try_into().map_err(|_| PriceError::Overflow)?;
+        let mantissa = NonZeroI64::new(mantissa).ok_or(PriceError::Overflow)?;
+        Ok(Self(mantissa))
     }
 
     pub const fn from_nonzero_mantissa(mantissa: NonZeroI64) -> Self {
@@ -58,8 +58,8 @@ impl Price {
     }
 
     pub const fn from_mantissa(mantissa: i64) -> Result<Self, PriceError> {
-        if let Some(value) = NonZeroI64::new(mantissa) {
-            Ok(Self(value))
+        if let Some(mantissa) = NonZeroI64::new(mantissa) {
+            Ok(Self(mantissa))
         } else {
             Err(PriceError::ZeroPriceUnsupported)
         }
@@ -75,7 +75,7 @@ impl Price {
 
     pub fn to_f64(self, exponent: i16) -> Result<f64, PriceError> {
         match ExponentFactor::get(exponent).ok_or(PriceError::Overflow)? {
-            // Mul/div is reversed for this conversion
+            // Mul/div is reversed for converting mantissa to value
             ExponentFactor::Mul(coef) => Ok(self.0.get() as f64 / coef as f64),
             ExponentFactor::Div(coef) => Ok(self.0.get() as f64 * coef as f64),
         }
@@ -83,7 +83,7 @@ impl Price {
 
     pub fn from_f64(value: f64, exponent: i16) -> Result<Self, PriceError> {
         let value = Decimal::from_f64(value).ok_or(PriceError::Overflow)?;
-        let value = match ExponentFactor::get(exponent).ok_or(PriceError::Overflow)? {
+        let mantissa = match ExponentFactor::get(exponent).ok_or(PriceError::Overflow)? {
             ExponentFactor::Mul(coef) => value
                 .checked_mul(Decimal::from_i64(coef).ok_or(PriceError::Overflow)?)
                 .ok_or(PriceError::Overflow)?,
@@ -91,65 +91,70 @@ impl Price {
                 .checked_div(Decimal::from_i64(coef).ok_or(PriceError::Overflow)?)
                 .ok_or(PriceError::Overflow)?,
         };
-        let value: i64 = value.try_into().map_err(|_| PriceError::Overflow)?;
+        let mantissa: i64 = mantissa.try_into().map_err(|_| PriceError::Overflow)?;
         Ok(Self(
-            NonZeroI64::new(value).ok_or(PriceError::ZeroPriceUnsupported)?,
+            NonZeroI64::new(mantissa).ok_or(PriceError::ZeroPriceUnsupported)?,
         ))
     }
 
-    pub fn add_with_same_mantissa(self, other: Price) -> Result<Self, PriceError> {
-        let value = self
+    pub fn add_with_same_exponent(self, other: Price) -> Result<Self, PriceError> {
+        let mantissa = self
             .0
             .get()
             .checked_add(other.0.get())
             .ok_or(PriceError::Overflow)?;
-        Self::from_mantissa(value).map_err(|_| PriceError::ZeroPriceUnsupported)
+        Self::from_mantissa(mantissa).map_err(|_| PriceError::ZeroPriceUnsupported)
     }
 
-    pub fn sub_with_same_mantissa(self, other: Price) -> Result<Self, PriceError> {
-        let value = self
+    pub fn sub_with_same_exponent(self, other: Price) -> Result<Self, PriceError> {
+        let mantissa = self
             .0
             .get()
             .checked_sub(other.0.get())
             .ok_or(PriceError::Overflow)?;
-        Self::from_mantissa(value).map_err(|_| PriceError::ZeroPriceUnsupported)
+        Self::from_mantissa(mantissa).map_err(|_| PriceError::ZeroPriceUnsupported)
     }
 
     pub fn mul_integer(self, factor: i64) -> Result<Self, PriceError> {
-        let value = self
+        let mantissa = self
             .0
             .get()
             .checked_mul(factor)
             .ok_or(PriceError::Overflow)?;
-        Self::from_mantissa(value).map_err(|_| PriceError::ZeroPriceUnsupported)
+        Self::from_mantissa(mantissa).map_err(|_| PriceError::ZeroPriceUnsupported)
     }
 
     pub fn div_integer(self, factor: i64) -> Result<Self, PriceError> {
-        let value = self
+        let mantissa = self
             .0
             .get()
             .checked_div(factor)
             .ok_or(PriceError::Overflow)?;
-        Self::from_mantissa(value).map_err(|_| PriceError::ZeroPriceUnsupported)
+        Self::from_mantissa(mantissa).map_err(|_| PriceError::ZeroPriceUnsupported)
     }
 
-    pub fn mul_decimal(self, mantissa: i64, rhs_exponent: i16) -> Result<Self, PriceError> {
-        let left_value = i128::from(self.0.get());
-        let right_value = i128::from(mantissa);
+    pub fn mul_decimal(self, mantissa: i64, exponent: i16) -> Result<Self, PriceError> {
+        let left_mantissa = i128::from(self.0.get());
+        let right_mantissa = i128::from(mantissa);
 
-        let value = left_value
-            .checked_mul(right_value)
+        // multiplied_mantissas = left_mantissa * right_mantissa
+        let multiplied_mantissas = left_mantissa
+            .checked_mul(right_mantissa)
             .ok_or(PriceError::Overflow)?;
 
-        let value = match ExponentFactor::get(rhs_exponent).ok_or(PriceError::Overflow)? {
-            ExponentFactor::Mul(coef) => {
-                value.checked_div(coef.into()).ok_or(PriceError::Overflow)?
-            }
-            ExponentFactor::Div(coef) => {
-                value.checked_mul(coef.into()).ok_or(PriceError::Overflow)?
-            }
+        // result_mantissa = left_mantissa * right_mantissa * 10^exponent
+        // Mul/div is reversed for multiplying 10^exponent
+        let result_mantissa = match ExponentFactor::get(exponent).ok_or(PriceError::Overflow)? {
+            ExponentFactor::Mul(coef) => multiplied_mantissas
+                .checked_div(coef.into())
+                .ok_or(PriceError::Overflow)?,
+            ExponentFactor::Div(coef) => multiplied_mantissas
+                .checked_mul(coef.into())
+                .ok_or(PriceError::Overflow)?,
         };
-        let value: i64 = value.try_into().map_err(|_| PriceError::Overflow)?;
-        Self::from_mantissa(value).map_err(|_| PriceError::ZeroPriceUnsupported)
+        let result_mantissa: i64 = result_mantissa
+            .try_into()
+            .map_err(|_| PriceError::Overflow)?;
+        Self::from_mantissa(result_mantissa).map_err(|_| PriceError::ZeroPriceUnsupported)
     }
 }

+ 6 - 2
lazer/sdk/rust/protocol/src/price/tests.rs

@@ -105,7 +105,7 @@ fn price_ops() {
     let price2 = Price::parse_str("23.45", -8).unwrap();
     assert_float_absolute_eq!(
         price1
-            .add_with_same_mantissa(price2)
+            .add_with_same_exponent(price2)
             .unwrap()
             .to_f64(-8)
             .unwrap(),
@@ -113,7 +113,7 @@ fn price_ops() {
     );
     assert_float_absolute_eq!(
         price1
-            .sub_with_same_mantissa(price2)
+            .sub_with_same_exponent(price2)
             .unwrap()
             .to_f64(-8)
             .unwrap(),
@@ -133,6 +133,10 @@ fn price_ops() {
         12.34 * 34.56
     );
 
+    assert_eq!(
+        price1.mul_decimal(34, 2).unwrap().mantissa_i64(),
+        1234000000 * 3400
+    );
     let price2 = Price::parse_str("42_000", 3).unwrap();
     assert_float_absolute_eq!(
         price2.mul_integer(2).unwrap().to_f64(3).unwrap(),

+ 10 - 10
lazer/sdk/rust/protocol/src/rate.rs

@@ -24,16 +24,16 @@ pub struct Rate(i64);
 
 impl Rate {
     pub fn from_integer(value: i64, exponent: i16) -> Result<Self, RateError> {
-        let value = match ExponentFactor::get(exponent).ok_or(RateError::Overflow)? {
+        let mantissa = match ExponentFactor::get(exponent).ok_or(RateError::Overflow)? {
             ExponentFactor::Mul(coef) => value.checked_mul(coef).ok_or(RateError::Overflow)?,
             ExponentFactor::Div(coef) => value.checked_div(coef).ok_or(RateError::Overflow)?,
         };
-        Ok(Self(value))
+        Ok(Self(mantissa))
     }
 
     pub fn parse_str(value: &str, exponent: i16) -> Result<Self, RateError> {
         let value: Decimal = value.parse()?;
-        let value = match ExponentFactor::get(exponent).ok_or(RateError::Overflow)? {
+        let mantissa = match ExponentFactor::get(exponent).ok_or(RateError::Overflow)? {
             ExponentFactor::Mul(coef) => value
                 .checked_mul(Decimal::from_i64(coef).ok_or(RateError::Overflow)?)
                 .ok_or(RateError::Overflow)?,
@@ -41,11 +41,11 @@ impl Rate {
                 .checked_div(Decimal::from_i64(coef).ok_or(RateError::Overflow)?)
                 .ok_or(RateError::Overflow)?,
         };
-        if !value.is_integer() {
+        if !mantissa.is_integer() {
             return Err(RateError::TooPrecise);
         }
-        let value: i64 = value.try_into().map_err(|_| RateError::Overflow)?;
-        Ok(Self(value))
+        let mantissa: i64 = mantissa.try_into().map_err(|_| RateError::Overflow)?;
+        Ok(Self(mantissa))
     }
 
     pub const fn from_mantissa(mantissa: i64) -> Self {
@@ -54,7 +54,7 @@ impl Rate {
 
     pub fn from_f64(value: f64, exponent: i16) -> Result<Self, RateError> {
         let value = Decimal::from_f64(value).ok_or(RateError::Overflow)?;
-        let value = match ExponentFactor::get(exponent).ok_or(RateError::Overflow)? {
+        let mantissa = match ExponentFactor::get(exponent).ok_or(RateError::Overflow)? {
             ExponentFactor::Mul(coef) => value
                 .checked_mul(Decimal::from_i64(coef).ok_or(RateError::Overflow)?)
                 .ok_or(RateError::Overflow)?,
@@ -62,8 +62,8 @@ impl Rate {
                 .checked_div(Decimal::from_i64(coef).ok_or(RateError::Overflow)?)
                 .ok_or(RateError::Overflow)?,
         };
-        let value: i64 = value.try_into().map_err(|_| RateError::Overflow)?;
-        Ok(Self(value))
+        let mantissa: i64 = mantissa.try_into().map_err(|_| RateError::Overflow)?;
+        Ok(Self(mantissa))
     }
 
     pub fn mantissa(self) -> i64 {
@@ -72,7 +72,7 @@ impl Rate {
 
     pub fn to_f64(self, exponent: i16) -> Result<f64, RateError> {
         match ExponentFactor::get(exponent).ok_or(RateError::Overflow)? {
-            // Mul/div is reversed for this conversion
+            // Mul/div is reversed for converting mantissa to value
             ExponentFactor::Mul(coef) => Ok(self.0 as f64 / coef as f64),
             ExponentFactor::Div(coef) => Ok(self.0 as f64 * coef as f64),
         }