use num_bigint::BigUint;
use thiserror::Error;
use tokio::task::JoinHandle;
use tycho_simulation::tycho_common::models::Address;
use crate::feed::market_data::SharedMarketDataRef;
#[non_exhaustive]
#[derive(Error, Debug, Clone)]
pub enum PriceProviderError {
#[error("price source unavailable: {0}")]
Unavailable(String),
#[non_exhaustive]
#[error("token not found: {address}")]
TokenNotFound {
address: String,
},
#[non_exhaustive]
#[error("price not found for pair {token_in} -> {token_out}")]
PriceNotFound {
token_in: String,
token_out: String,
},
#[non_exhaustive]
#[error("price data stale: last update {age_ms}ms ago")]
StaleData {
age_ms: u64,
},
}
#[derive(Debug, Clone)]
pub struct ExternalPrice {
expected_amount_out: BigUint,
source: String,
timestamp_ms: u64,
}
impl ExternalPrice {
pub fn new(expected_amount_out: BigUint, source: String, timestamp_ms: u64) -> Self {
Self { expected_amount_out, source, timestamp_ms }
}
pub fn expected_amount_out(&self) -> &BigUint {
&self.expected_amount_out
}
pub fn source(&self) -> &str {
&self.source
}
pub fn timestamp_ms(&self) -> u64 {
self.timestamp_ms
}
}
pub trait PriceProvider: Send + Sync + 'static {
fn start(&mut self, market_data: SharedMarketDataRef) -> JoinHandle<()>;
fn get_expected_out(
&self,
token_in: &Address,
token_out: &Address,
amount_in: &BigUint,
) -> Result<ExternalPrice, PriceProviderError>;
}