use alloy::primitives::{Signed, U160, U256};
use nautilus_model::{
defi::Token,
enums::OrderSide,
types::{Price, Quantity, fixed::FIXED_PRECISION},
};
use crate::{events::swap::SwapEvent, math::convert_i256_to_f64};
fn calculate_price_from_sqrt_price(
sqrt_price_x96: U160,
token0_decimals: u8,
token1_decimals: u8,
) -> f64 {
let sqrt_price_u256 = U256::from(sqrt_price_x96);
let price_x192 = sqrt_price_u256 * sqrt_price_u256;
let price_str = price_x192.to_string();
let price_x192_f64: f64 = price_str.parse().unwrap_or(f64::INFINITY);
let two_pow_192: f64 = (1u128 << 96) as f64 * (1u128 << 96) as f64;
let price_raw = price_x192_f64 / two_pow_192;
let decimal_adjustment = 10f64.powi(i32::from(token0_decimals) - i32::from(token1_decimals));
price_raw * decimal_adjustment
}
pub fn convert_to_trade_data(
token0: &Token,
token1: &Token,
swap_event: &SwapEvent,
) -> anyhow::Result<(OrderSide, Quantity, Price)> {
let price_f64 = calculate_price_from_sqrt_price(
swap_event.sqrt_price_x96,
token0.decimals,
token1.decimals,
);
if !price_f64.is_finite() || price_f64 <= 0.0 {
anyhow::bail!(
"Invalid price calculated from sqrt_price_x96: {}, result: {}",
swap_event.sqrt_price_x96,
price_f64
);
}
let price = Price::from(format!(
"{:.precision$}",
price_f64,
precision = FIXED_PRECISION as usize
));
let quantity_f64 = convert_i256_to_f64(swap_event.amount1, token1.decimals)?.abs();
if !quantity_f64.is_finite() || quantity_f64 < 0.0 {
anyhow::bail!(
"Invalid quantity calculated from amount1: {}, result: {}",
swap_event.amount1,
quantity_f64
);
}
let quantity = Quantity::from(format!(
"{:.precision$}",
quantity_f64,
precision = FIXED_PRECISION as usize
));
let zero = Signed::<256, 4>::ZERO;
let side = if swap_event.amount1 > zero {
OrderSide::Buy } else {
OrderSide::Sell };
Ok((side, quantity, price))
}