ソースを参照

feat: change hermes twap binary response, add twap data model and parsing to price-service-sdk

Tejas Badadare 11 ヶ月 前
コミット
3091a73e5a

+ 1 - 1
apps/hermes/server/Cargo.lock

@@ -1868,7 +1868,7 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
 
 [[package]]
 name = "hermes"
-version = "0.8.0"
+version = "0.8.1"
 dependencies = [
  "anyhow",
  "async-trait",

+ 1 - 1
apps/hermes/server/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name        = "hermes"
-version     = "0.8.0"
+version     = "0.8.1"
 description = "Hermes is an agent that provides Verified Prices from the Pythnet Pyth Oracle."
 edition     = "2021"
 

+ 13 - 22
apps/hermes/server/src/state/aggregate.rs

@@ -652,7 +652,6 @@ where
     }
 
     let mut twaps = Vec::new();
-    let mut update_data = Vec::new();
 
     // Iterate through start and end messages together
     for (start_message, end_message) in start_messages.iter().zip(end_messages.iter()) {
@@ -676,34 +675,26 @@ where
                         end_timestamp: end_twap.publish_time,
                         down_slots_ratio,
                     });
-
-                    // Combine messages for update data
-                    let mut messages = Vec::new();
-                    messages.push(start_message.clone().into());
-                    messages.push(end_message.clone().into());
-
-                    if let Ok(update) = construct_update_data(messages) {
-                        update_data.push(update);
-                    } else {
-                        tracing::warn!(
-                            "Failed to construct update data for price feed {:?}",
-                            start_twap.feed_id
-                        );
-                        continue;
-                    }
                 }
                 Err(e) => {
-                    tracing::warn!(
+                    return Err(anyhow!(
                         "Failed to calculate TWAP for price feed {:?}: {}",
                         start_twap.feed_id,
                         e
-                    );
-                    continue;
+                    ));
                 }
             }
         }
     }
 
+    // Construct update data.
+    // update_data[0] will contain the start VAA and merkle proofs
+    // update_data[1] will contain the end VAA and merkle proofs
+    let start_updates =
+        construct_update_data(start_messages.into_iter().map(Into::into).collect())?;
+    let end_updates = construct_update_data(end_messages.into_iter().map(Into::into).collect())?;
+    let update_data = vec![start_updates, end_updates];
+
     Ok(TwapsWithUpdateData { twaps, update_data })
 }
 
@@ -1316,10 +1307,10 @@ mod test {
         assert_eq!(twap_2.start_timestamp, 100);
         assert_eq!(twap_2.end_timestamp, 200);
 
-        // Verify update data contains both start and end messages for both feeds
+        // Each update_data element contains a VAA and merkle proofs for both feeds
         assert_eq!(result.update_data.len(), 2);
-        assert_eq!(result.update_data[0].len(), 2); // Should contain 2 messages
-        assert_eq!(result.update_data[1].len(), 2); // Should contain 2 messages
+        assert_eq!(result.update_data[0].len(), 1); // Start update
+        assert_eq!(result.update_data[1].len(), 1); // End update
     }
     #[tokio::test]
 

+ 1 - 1
price_service/sdk/js/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@pythnetwork/price-service-sdk",
-  "version": "1.7.1",
+  "version": "1.8.0",
   "description": "Pyth price service SDK",
   "homepage": "https://pyth.network",
   "main": "lib/index.js",

+ 48 - 1
price_service/sdk/js/src/AccumulatorUpdateData.ts

@@ -5,12 +5,12 @@ const MAJOR_VERSION = 1;
 const MINOR_VERSION = 0;
 const KECCAK160_HASH_SIZE = 20;
 const PRICE_FEED_MESSAGE_VARIANT = 0;
+const TWAP_MESSAGE_VARIANT = 1;
 
 export type AccumulatorUpdateData = {
   vaa: Buffer;
   updates: { message: Buffer; proof: number[][] }[];
 };
-
 export type PriceFeedMessage = {
   feedId: Buffer;
   price: BN;
@@ -22,6 +22,17 @@ export type PriceFeedMessage = {
   emaConf: BN;
 };
 
+export type TwapMessage = {
+  feedId: Buffer;
+  cumulativePrice: BN;
+  cumulativeConf: BN;
+  numDownSlots: BN;
+  exponent: number;
+  publishTime: BN;
+  prevPublishTime: BN;
+  publishSlot: BN;
+};
+
 export function isAccumulatorUpdateData(updateBytes: Buffer): boolean {
   return (
     updateBytes.toString("hex").slice(0, 8) === ACCUMULATOR_MAGIC &&
@@ -29,6 +40,7 @@ export function isAccumulatorUpdateData(updateBytes: Buffer): boolean {
     updateBytes[5] === MINOR_VERSION
   );
 }
+
 export function parsePriceFeedMessage(message: Buffer): PriceFeedMessage {
   let cursor = 0;
   const variant = message.readUInt8(cursor);
@@ -64,6 +76,41 @@ export function parsePriceFeedMessage(message: Buffer): PriceFeedMessage {
   };
 }
 
+export function parseTwapMessage(message: Buffer): TwapMessage {
+  let cursor = 0;
+  const variant = message.readUInt8(cursor);
+  if (variant !== TWAP_MESSAGE_VARIANT) {
+    throw new Error("Not a twap message");
+  }
+  cursor += 1;
+  const feedId = message.subarray(cursor, cursor + 32);
+  cursor += 32;
+  const cumulativePrice = new BN(message.subarray(cursor, cursor + 16), "be");
+  cursor += 16;
+  const cumulativeConf = new BN(message.subarray(cursor, cursor + 16), "be");
+  cursor += 16;
+  const numDownSlots = new BN(message.subarray(cursor, cursor + 8), "be");
+  cursor += 8;
+  const exponent = message.readInt32BE(cursor);
+  cursor += 4;
+  const publishTime = new BN(message.subarray(cursor, cursor + 8), "be");
+  cursor += 8;
+  const prevPublishTime = new BN(message.subarray(cursor, cursor + 8), "be");
+  cursor += 8;
+  const publishSlot = new BN(message.subarray(cursor, cursor + 8), "be");
+  cursor += 8;
+  return {
+    feedId,
+    cumulativePrice,
+    cumulativeConf,
+    numDownSlots,
+    exponent,
+    publishTime,
+    prevPublishTime,
+    publishSlot,
+  };
+}
+
 /**
  * An AccumulatorUpdateData contains a VAA and a list of updates. This function returns a new serialized AccumulatorUpdateData with only the updates in the range [start, end).
  */