sol_parser_sdk/utils/
market.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
4pub enum NormalizedTradeSide {
5 Buy,
6 Sell,
7}
8
9impl NormalizedTradeSide {
10 #[inline]
11 pub const fn as_str(self) -> &'static str {
12 match self {
13 Self::Buy => "Buy",
14 Self::Sell => "Sell",
15 }
16 }
17}
18
19#[inline]
24pub fn sqrt_price_x64_to_price(sqrt_price_x64: u128, base_decimals: u8, quote_decimals: u8) -> f64 {
25 let sqrt = sqrt_price_x64 as f64 / 2_f64.powi(64);
26 let decimal_adjustment = 10_f64.powi(i32::from(base_decimals) - i32::from(quote_decimals));
27 sqrt * sqrt * decimal_adjustment
28}
29
30#[inline]
32pub fn vault_price_from_balances(
33 base_raw: u128,
34 quote_raw: u128,
35 base_decimals: u8,
36 quote_decimals: u8,
37) -> Option<f64> {
38 if base_raw == 0 {
39 return None;
40 }
41 let decimal_adjustment = 10_f64.powi(i32::from(base_decimals) - i32::from(quote_decimals));
42 Some((quote_raw as f64 / base_raw as f64) * decimal_adjustment)
43}
44
45#[inline]
50pub fn normalize_buy_sell_from_token_delta(token_delta: i128) -> Option<NormalizedTradeSide> {
51 match token_delta.cmp(&0) {
52 std::cmp::Ordering::Greater => Some(NormalizedTradeSide::Buy),
53 std::cmp::Ordering::Less => Some(NormalizedTradeSide::Sell),
54 std::cmp::Ordering::Equal => None,
55 }
56}
57
58#[inline]
63pub fn normalize_buy_sell_from_input_mint(
64 input_mint: &str,
65 base_mint: &str,
66 quote_mint: &str,
67) -> Option<NormalizedTradeSide> {
68 if base_mint == quote_mint {
69 return None;
70 }
71 if input_mint == quote_mint {
72 Some(NormalizedTradeSide::Buy)
73 } else if input_mint == base_mint {
74 Some(NormalizedTradeSide::Sell)
75 } else {
76 None
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83
84 #[test]
85 fn sqrt_price_x64_identity_price() {
86 let q64 = 1_u128 << 64;
87 assert_eq!(sqrt_price_x64_to_price(q64, 6, 6), 1.0);
88 assert_eq!(sqrt_price_x64_to_price(q64, 9, 6), 1000.0);
89 }
90
91 #[test]
92 fn vault_price_handles_decimals_and_zero_base() {
93 assert_eq!(vault_price_from_balances(1_000_000, 2_000_000, 6, 6), Some(2.0));
94 assert_eq!(vault_price_from_balances(1_000_000_000, 2_000_000, 9, 6), Some(2.0));
95 assert_eq!(vault_price_from_balances(0, 2_000_000, 6, 6), None);
96 }
97
98 #[test]
99 fn direction_helpers_are_token_relative() {
100 assert_eq!(normalize_buy_sell_from_token_delta(1), Some(NormalizedTradeSide::Buy));
101 assert_eq!(normalize_buy_sell_from_token_delta(-1), Some(NormalizedTradeSide::Sell));
102 assert_eq!(normalize_buy_sell_from_token_delta(0), None);
103 assert_eq!(
104 normalize_buy_sell_from_input_mint("USDC", "SOL", "USDC"),
105 Some(NormalizedTradeSide::Buy)
106 );
107 assert_eq!(
108 normalize_buy_sell_from_input_mint("SOL", "SOL", "USDC"),
109 Some(NormalizedTradeSide::Sell)
110 );
111 }
112}