use std::{collections::HashMap, fmt, sync::Arc};
use chrono::{DateTime, Utc};
use tracing::debug;
use tycho_common::{
models::{token::Token, Chain},
simulation::protocol_sim::ProtocolSim,
Bytes,
};
use crate::{
protocol::models::ProtocolComponent,
snapshot_feed::{
errors::FeedError, SnapshotFeedEvent, SnapshotFeedOutcome, SnapshotFeedStream,
SnapshotFeedStreams, SnapshotFeedWatch,
},
};
#[cfg_attr(
not(test),
expect(
dead_code,
reason = "nothing in this crate implements a book feed yet; the layer is exercised by its own tests"
)
)]
pub(crate) mod component;
#[cfg_attr(
not(test),
expect(
dead_code,
reason = "nothing in this crate implements a book feed yet; the layer is exercised by its own tests"
)
)]
pub(crate) mod levels;
pub mod quote_tokens;
#[cfg_attr(
not(test),
expect(
dead_code,
reason = "nothing in this crate implements a book feed yet; the layer is exercised by its own tests"
)
)]
pub(crate) mod sim;
#[cfg_attr(
not(test),
expect(
dead_code,
reason = "nothing in this crate implements a book feed yet; the layer is exercised by its own tests"
)
)]
pub(crate) mod tvl;
#[derive(Clone, Debug)]
pub struct Book {
pub component: ProtocolComponent,
pub state: Arc<dyn ProtocolSim>,
pub updated_at: Option<DateTime<Utc>>,
}
#[derive(Clone, Debug)]
pub struct BookSnapshot<A> {
pub anchor: A,
pub books: Arc<HashMap<String, Book>>,
}
impl BookSnapshot<ReceivedAt> {
pub fn received_now(books: HashMap<String, Book>) -> Self {
BookSnapshot { anchor: ReceivedAt(Utc::now()), books: Arc::new(books) }
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ReceivedAt(pub DateTime<Utc>);
#[derive(Clone, derive_more::Debug)]
pub struct BookFeedConfig {
pub chain: Chain,
#[debug("{} tokens", tokens.len())]
pub tokens: Arc<HashMap<Bytes, Token>>,
pub min_tvl_usd: f64,
}
impl BookFeedConfig {
#[expect(
dead_code,
reason = "nothing in this crate implements a book feed yet; the layer is exercised by its own tests"
)]
pub(crate) fn pair_tokens(&self, a: &Bytes, b: &Bytes) -> Option<(&Token, &Token)> {
Some((self.tokens.get(a)?, self.tokens.get(b)?))
}
#[expect(
dead_code,
reason = "nothing in this crate implements a book feed yet; the layer is exercised by its own tests"
)]
pub(crate) fn clears_min_tvl(&self, tvl_usd: f64, book_label: impl fmt::Display) -> bool {
let clears = tvl_usd >= self.min_tvl_usd;
if !clears {
debug!(
book = %book_label,
tvl_usd,
min_tvl_usd = self.min_tvl_usd,
"filtering out book below the TVL floor"
);
}
clears
}
}
pub type BookFeedStreams<A = ReceivedAt> = SnapshotFeedStreams<BookSnapshot<A>, FeedError>;
pub type BookFeedStream<A = ReceivedAt> = SnapshotFeedStream<BookSnapshot<A>, FeedError>;
pub type BookFeedEvent<A = ReceivedAt> = SnapshotFeedEvent<BookSnapshot<A>, FeedError>;
pub type BookFeedWatch<A = ReceivedAt> = SnapshotFeedWatch<BookSnapshot<A>, FeedError>;
pub type BookFeedOutcome = SnapshotFeedOutcome<FeedError>;