pub mod fetch;
pub mod monitor;
pub mod run;
use crate::cli::output::Output;
use crate::cli::resolve::{DexCandidates, ResolveContext, VenueKind, picker_for, resolve};
use scope::chains::{ChainClientFactory, infer_chain_from_address};
use scope::config::Config;
use scope::error::Result;
use scope::metrics::MetricGroup;
use scope::tokens::TokenAliases;
use scope::watch::{Target, TargetKind, Watchlist};
pub use fetch::{TargetReading, Tick, tick};
pub use run::{csv_header, csv_rows, report_text, run};
#[derive(Clone, Copy)]
pub struct Sources<'a> {
pub config: &'a Config,
pub clients: &'a dyn ChainClientFactory,
}
pub fn venue_ids() -> Vec<String> {
scope::market::VenueRegistry::load()
.map(|r| r.list().into_iter().map(str::to_string).collect())
.unwrap_or_default()
}
#[derive(Debug, Clone, PartialEq)]
pub struct Ready {
pub list: Watchlist,
pub contracts: Vec<Option<String>>,
}
pub async fn prepare(w: &Watchlist, src: Sources<'_>, out: &Output) -> Result<Ready> {
let mut list = w.clone();
let mut contracts = Vec::with_capacity(list.targets.len());
for t in &mut list.targets {
if let Some((address, chain)) =
crate::cli::address_book::resolve_address_book_input(&t.id, src.config)?
{
t.id = address;
t.chain.get_or_insert(chain);
}
if t.chain.is_none() && t.kind != TargetKind::Pair {
t.chain = infer_chain_from_address(&t.id).map(str::to_string);
}
let contract = if t.kind == TargetKind::Token && t.needs(MetricGroup::Token) {
Some(resolve_token(t, src, out).await?)
} else {
None
};
contracts.push(contract);
}
Ok(Ready { list, contracts })
}
async fn resolve_token(t: &mut Target, src: Sources<'_>, out: &Output) -> Result<String> {
if TokenAliases::is_address(t.id.trim()) {
return Ok(t.id.trim().to_string());
}
let dex = src.clients.create_dex_client();
let ctx = ResolveContext {
chain: t.chain.clone(),
venue: VenueKind::Dex,
token_flag: None,
yes: false,
save: false,
};
let source = DexCandidates {
dex: dex.as_ref(),
out,
fallback: Some(src.clients.http()),
};
let picker = picker_for(out, false);
let mut aliases = TokenAliases::load();
let r = resolve(&t.id, &ctx, &source, picker.as_ref(), &mut aliases, out).await?;
if t.chain.is_none() && !r.chain.is_empty() {
t.chain = Some(r.chain);
}
Ok(r.address.unwrap_or_else(|| t.id.clone()))
}