use anyhow::{bail, Result};
use tracing::info;
use tycho_simulation::{
tycho_client::rpc::{HttpRPCClient, HttpRPCClientOptions, ProtocolSystemsParams, RPCClient},
tycho_common::models::Chain,
};
const ALL_ONCHAIN: &str = "all_onchain";
const NATIVE_ONCHAIN: &str = "native_onchain";
const VM_PREFIX: &str = "vm:";
pub async fn fetch_protocol_systems(
tycho_url: &str,
auth_key: Option<&str>,
use_tls: bool,
chain: Chain,
) -> Result<Vec<String>> {
info!("Fetching available protocol systems from Tycho RPC...");
let rpc_url =
if use_tls { format!("https://{tycho_url}") } else { format!("http://{tycho_url}") };
let rpc_options = HttpRPCClientOptions::new().with_auth_key(auth_key.map(|s| s.to_string()));
let rpc_client = HttpRPCClient::new(&rpc_url, rpc_options)?;
let request = ProtocolSystemsParams::new(chain);
let response = rpc_client
.get_protocol_systems(request)
.await?;
let protocols = response
.data()
.protocol_systems()
.to_vec();
info!("Fetched {} protocol system(s) from Tycho RPC", protocols.len());
Ok(protocols)
}
pub async fn resolve_protocols(
tycho_url: &str,
auth_key: Option<&str>,
use_tls: bool,
chain: Chain,
requested: &[String],
) -> Result<Vec<String>> {
let want_native = requested
.iter()
.any(|p| p == NATIVE_ONCHAIN);
let want_all = requested.is_empty() ||
requested
.iter()
.any(|p| p == ALL_ONCHAIN);
let protocols = if want_all || want_native {
let mut fetched = fetch_protocol_systems(tycho_url, auth_key, use_tls, chain).await?;
if want_native {
fetched.retain(|p| !p.starts_with(VM_PREFIX));
}
for p in requested {
if p != ALL_ONCHAIN && p != NATIVE_ONCHAIN && !fetched.contains(p) {
fetched.push(p.clone());
}
}
fetched
} else {
requested.to_vec()
};
if protocols.is_empty() {
bail!("no supported protocols found. Provide --protocols or check Tycho connectivity.");
}
Ok(protocols)
}