pub use crate::pyth::functions::{ get_ema_price_no_older_than, get_ema_price_unsafe, get_price_no_older_than, get_price_unsafe, get_update_fee, get_valid_time_period, parse_price_feed_updates, parse_price_feed_updates_unique, update_price_feeds, update_price_feeds_if_necessary, }; use alloc::vec::Vec; use alloy_primitives::{Bytes, B256, U256}; use alloy_sol_types::SolValue; use stylus_sdk::{ abi::Bytes as AbiBytes, prelude::*, storage::{StorageAddress, TopLevelStorage}, }; /// `IPyth` is a trait that defines methods for interacting with the Pyth contract. pub trait IPyth { /// The Error Type for the Pyth Contract. /// - `Vec`: The error message in bytes. type Error: Into>; /// Retrieves the latest price feed without any recency checks. /// /// # Parameters /// - `id`: The unique identifier for the price feed. /// /// # Returns /// - `Result, Self::Error>`: The price data in bytes, or an error. fn get_price_unsafe(&mut self, id: B256) -> Result, Self::Error>; /// Retrieves a price that is no older than a specified `age`. /// /// # Parameters /// - `id`: The unique identifier for the price feed. /// - `age`: The maximum acceptable age of the price in seconds. /// /// # Returns /// - `Result, Self::Error>`: The price data in bytes, or an error. fn get_price_no_older_than(&mut self, id: B256, age: U256) -> Result, Self::Error>; /// Retrieves the exponentially-weighted moving average (EMA) price without recency checks. /// /// # Parameters /// - `id`: The unique identifier for the price feed. /// /// # Returns /// - `Result, Self::Error>`: The EMA price data in bytes, or an error. fn get_ema_price_unsafe(&mut self, id: B256) -> Result, Self::Error>; /// Retrieves an EMA price that is no older than the specified `age`. /// /// # Parameters /// - `id`: The unique identifier for the price feed. /// - `age`: The maximum acceptable age of the price in seconds. /// /// # Returns /// - `Result, Self::Error>`: The EMA price data in bytes, or an error. fn get_ema_price_no_older_than(&mut self, id: B256, age: U256) -> Result, Self::Error>; /// Updates price feeds with the given data. /// /// # Parameters /// - `update_data`: Array of price update data. /// /// # Returns /// - `Result<(), Self::Error>`: Success or error. fn update_price_feeds(&mut self, update_data: Vec) -> Result<(), Self::Error>; /// Updates price feeds if necessary, based on given publish times. /// /// # Parameters /// - `update_data`: Array of price update data. /// - `price_ids`: Array of price IDs. /// - `publish_times`: Array of publish times for the corresponding price IDs. /// /// # Returns /// - `Result<(), Self::Error>`: Success or error. fn update_price_feeds_if_necessary( &mut self, update_data: Vec, price_ids: Vec, publish_times: Vec, ) -> Result<(), Self::Error>; /// Returns the fee required to update the price feeds based on the provided data. /// /// # Parameters /// - `update_data`: Array of price update data. /// /// # Returns /// - `Result`: The required fee in Wei, or an error. fn get_update_fee(&mut self, update_data: Vec) -> Result; /// Returns the fee required to update the price feeds based on the provided data. /// /// # Parameters /// - `update_data`: Array of price update data. /// /// # Returns /// - `Result`: The required fee in Wei, or an error. fn get_valid_time_period(&mut self) -> Result; /// Parses the price feed updates for specific price IDs within a given time range. /// /// # Parameters /// - `update_data`: Array of price update data. /// - `price_ids`: Array of price IDs to parse. /// - `min_publish_time`: Minimum acceptable publish time for the price IDs. /// - `max_publish_time`: Maximum acceptable publish time for the price IDs. /// /// # Returns /// - `Result, Self::Error>`: Parsed price feed data in bytes, or an error. fn parse_price_feed_updates( &mut self, update_data: Vec, price_ids: Vec, min_publish_time: u64, max_publish_time: u64, ) -> Result, Self::Error>; /// Parses price feed updates for specific price IDs, ensuring only the first updates within a time range are returned. /// /// # Parameters /// - `update_data`: Array of price update data. /// - `price_ids`: Array of price IDs to parse. /// - `min_publish_time`: Minimum acceptable publish time for the price IDs. /// - `max_publish_time`: Maximum acceptable publish time for the price IDs. /// /// # Returns /// - `Result, Self::Error>`: Parsed price feed data in bytes, or an error. fn parse_price_feed_updates_unique( &mut self, update_data: Vec, price_ids: Vec, min_publish_time: u64, max_publish_time: u64, ) -> Result, Self::Error>; } #[storage] pub struct PythContract { pub _ipyth: StorageAddress, } unsafe impl TopLevelStorage for PythContract {} #[public] impl IPyth for PythContract { type Error = Vec; fn get_price_unsafe(&mut self, id: B256) -> Result, Self::Error> { let price = get_price_unsafe(self, self._ipyth.get(), id)?; let data = price.abi_encode(); Ok(data) } fn get_price_no_older_than(&mut self, id: B256, age: U256) -> Result, Self::Error> { let price = get_price_no_older_than(self, self._ipyth.get(), id, age)?; let data = price.abi_encode(); Ok(data) } fn get_ema_price_unsafe(&mut self, id: B256) -> Result, Self::Error> { let price = get_ema_price_unsafe(self, self._ipyth.get(), id)?; let data = price.abi_encode(); Ok(data) } fn get_ema_price_no_older_than(&mut self, id: B256, age: U256) -> Result, Self::Error> { let price = get_ema_price_no_older_than(self, self._ipyth.get(), id, age)?; let data = price.abi_encode(); Ok(data) } fn get_valid_time_period(&mut self) -> Result { let time = get_valid_time_period(self, self._ipyth.get())?; Ok(time) } fn get_update_fee(&mut self, update_data: Vec) -> Result { let data = update_data.into_iter().map(|x| Bytes::from(x.0)).collect(); let fee = get_update_fee(self, self._ipyth.get(), data)?; Ok(fee) } #[payable] fn update_price_feeds(&mut self, update_data: Vec) -> Result<(), Self::Error> { let data = update_data.into_iter().map(|x| Bytes::from(x.0)).collect(); update_price_feeds(self, self._ipyth.get(), data)?; Ok(()) } #[payable] fn update_price_feeds_if_necessary( &mut self, update_data: Vec, price_ids: Vec, publish_times: Vec, ) -> Result<(), Self::Error> { let data = update_data.into_iter().map(|x| Bytes::from(x.0)).collect(); update_price_feeds_if_necessary(self, self._ipyth.get(), data, price_ids, publish_times)?; Ok(()) } #[payable] fn parse_price_feed_updates( &mut self, update_data: Vec, price_ids: Vec, min_publish_time: u64, max_publish_time: u64, ) -> Result, Self::Error> { let data = update_data.into_iter().map(|x| Bytes::from(x.0)).collect(); let encode_data = parse_price_feed_updates( self, self._ipyth.get(), data, price_ids, min_publish_time, max_publish_time, )? .abi_encode(); Ok(encode_data) } #[payable] fn parse_price_feed_updates_unique( &mut self, update_data: Vec, price_ids: Vec, min_publish_time: u64, max_publish_time: u64, ) -> Result, Self::Error> { let data = update_data.into_iter().map(|x| Bytes::from(x.0)).collect(); let encode_data = parse_price_feed_updates_unique( self, self._ipyth.get(), data, price_ids, min_publish_time, max_publish_time, )? .abi_encode(); Ok(encode_data) } }