|
| 1 | +pub use self::price_conf::PriceConf; |
| 2 | + |
| 3 | +mod entrypoint; |
| 4 | +pub mod processor; |
| 5 | +pub mod instruction; |
| 6 | + |
| 7 | +mod price_conf; |
| 8 | +solana_program::declare_id!("PythC11111111111111111111111111111111111111"); |
| 9 | + |
1 | 10 | pub const MAGIC : u32 = 0xa1b2c3d4; |
2 | 11 | pub const VERSION_2 : u32 = 2; |
3 | 12 | pub const VERSION : u32 = VERSION_2; |
@@ -134,34 +143,68 @@ pub struct Price |
134 | 143 | impl Price { |
135 | 144 | /** |
136 | 145 | * Get the current price and confidence interval as fixed-point numbers of the form a * 10^e. |
137 | | - * Returns a triple of the current price, confidence interval, and the exponent for both |
138 | | - * numbers. For example: |
139 | | - * |
140 | | - * get_current_price() -> Some((12345, 267, -2)) // represents 123.45 +- 2.67 |
141 | | - * get_current_price() -> Some((123, 1, 2)) // represents 12300 +- 100 |
142 | | - * |
143 | | - * Returns None if price information is currently unavailable. |
| 146 | + * Returns a struct containing the current price, confidence interval, and the exponent for both |
| 147 | + * numbers. Returns None if price information is currently unavailable. |
144 | 148 | */ |
145 | | - pub fn get_current_price(&self) -> Option<(i64, u64, i32)> { |
| 149 | + pub fn get_current_price(&self) -> Option<PriceConf> { |
146 | 150 | if !matches!(self.agg.status, PriceStatus::Trading) { |
147 | 151 | None |
148 | 152 | } else { |
149 | | - Some((self.agg.price, self.agg.conf, self.expo)) |
| 153 | + Some(PriceConf { |
| 154 | + price: self.agg.price, |
| 155 | + conf: self.agg.conf, |
| 156 | + expo: self.expo |
| 157 | + }) |
150 | 158 | } |
151 | 159 | } |
152 | 160 |
|
153 | 161 | /** |
154 | | - * Get the time-weighted average price (TWAP) as a fixed point number of the form a * 10^e. |
155 | | - * Returns a tuple of the current twap and its exponent. For example: |
156 | | - * |
157 | | - * get_twap() -> Some((123, -2)) // represents 1.23 |
158 | | - * get_twap() -> Some((45, 3)) // represents 45000 |
159 | | - * |
| 162 | + * Get the time-weighted average price (TWAP) and a confidence interval on the result. |
160 | 163 | * Returns None if the twap is currently unavailable. |
| 164 | + * |
| 165 | + * At the moment, the confidence interval returned by this method is computed in |
| 166 | + * a somewhat questionable way, so we do not recommend using it for high-value applications. |
161 | 167 | */ |
162 | | - pub fn get_twap(&self) -> Option<(i64, i32)> { |
| 168 | + pub fn get_twap(&self) -> Option<PriceConf> { |
163 | 169 | // This method currently cannot return None, but may do so in the future. |
164 | | - Some((self.twap.val, self.expo)) |
| 170 | + // Note that the twac is a positive number in i64, so safe to cast to u64. |
| 171 | + Some(PriceConf { price: self.twap.val, conf: self.twac.val as u64, expo: self.expo }) |
| 172 | + } |
| 173 | + |
| 174 | + /** |
| 175 | + * Get the current price of this account in a different quote currency. If this account |
| 176 | + * represents the price of the product X/Z, and `quote` represents the price of the product Y/Z, |
| 177 | + * this method returns the price of X/Y. Use this method to get the price of e.g., mSOL/SOL from |
| 178 | + * the mSOL/USD and SOL/USD accounts. |
| 179 | + * |
| 180 | + * `result_expo` determines the exponent of the result, i.e., the number of digits below the decimal |
| 181 | + * point. This method returns `None` if either the price or confidence are too large to be |
| 182 | + * represented with the requested exponent. |
| 183 | + */ |
| 184 | + pub fn get_price_in_quote(&self, quote: &Price, result_expo: i32) -> Option<PriceConf> { |
| 185 | + return match (self.get_current_price(), quote.get_current_price()) { |
| 186 | + (Some(base_price_conf), Some(quote_price_conf)) => |
| 187 | + base_price_conf.div("e_price_conf)?.scale_to_exponent(result_expo), |
| 188 | + (_, _) => None, |
| 189 | + } |
| 190 | + } |
| 191 | + |
| 192 | + /** |
| 193 | + * Get the price of a basket of currencies. Each entry in `amounts` is of the form |
| 194 | + * `(price, qty, qty_expo)`, and the result is the sum of `price * qty * 10^qty_expo`. |
| 195 | + * The result is returned with exponent `result_expo`. |
| 196 | + * |
| 197 | + * An example use case for this function is to get the value of an LP token. |
| 198 | + */ |
| 199 | + pub fn price_basket(amounts: &[(Price, i64, i32)], result_expo: i32) -> Option<PriceConf> { |
| 200 | + assert!(amounts.len() > 0); |
| 201 | + let mut res = PriceConf { price: 0, conf: 0, expo: result_expo }; |
| 202 | + for i in 0..amounts.len() { |
| 203 | + res = res.add( |
| 204 | + &amounts[i].0.get_current_price()?.cmul(amounts[i].1, amounts[i].2)?.scale_to_exponent(result_expo)? |
| 205 | + )? |
| 206 | + } |
| 207 | + Some(res) |
165 | 208 | } |
166 | 209 | } |
167 | 210 |
|
|
0 commit comments