use std::{
collections::{HashMap, HashSet},
sync::LazyLock,
time::Duration,
};
use tycho_common::{models::Chain, Bytes};
use crate::encoding::errors::EncodingError;
pub(crate) const DEFAULT_EXECUTORS_JSON: &str =
include_str!("../../../config/executor_addresses.json");
pub(crate) const DEFAULT_ROUTERS_JSON: &str = include_str!("../../../config/router_addresses.json");
pub(crate) const PROTOCOL_SPECIFIC_CONFIG: &str =
include_str!("../../../config/protocol_specific_addresses.json");
pub static DEFAULT_ROUTER_ADDRESSES: LazyLock<HashMap<Chain, Bytes>> = LazyLock::new(|| {
serde_json::from_str(DEFAULT_ROUTERS_JSON).expect("valid router_addresses.json")
});
pub fn get_router_address(chain: &Chain) -> Result<&'static Bytes, EncodingError> {
DEFAULT_ROUTER_ADDRESSES
.get(chain)
.ok_or_else(|| {
EncodingError::FatalError(format!(
"No default router address found for chain {chain:?}"
))
})
}
pub static ROUTER_ETH_ADDRESS: LazyLock<Bytes> = LazyLock::new(|| {
Bytes::from(alloy::primitives::hex!("EeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE").to_vec())
});
pub const ANGSTROM_DEFAULT_BLOCKS_IN_FUTURE: u64 = 5;
pub(crate) const ANGSTROM_DEFAULT_API_URL: &str =
"https://attestations.angstrom.xyz/getAttestations";
pub(crate) const ANGSTROM_ATTESTATION_SIZE: usize = 85;
const ETHEREUM_MIN_BLOCK_TIME_SECS: u64 = 12;
const ANGSTROM_ATTESTATION_REFRESHES_PER_BLOCK: u64 = 2;
pub(crate) const ANGSTROM_ATTESTATION_REFRESH_INTERVAL: Duration =
Duration::from_secs(ETHEREUM_MIN_BLOCK_TIME_SECS / ANGSTROM_ATTESTATION_REFRESHES_PER_BLOCK);
const ANGSTROM_ATTESTATION_MAX_AGE_BLOCKS: u64 = 1;
pub(crate) const ANGSTROM_ATTESTATION_MAX_AGE: Duration =
Duration::from_secs(ETHEREUM_MIN_BLOCK_TIME_SECS * ANGSTROM_ATTESTATION_MAX_AGE_BLOCKS);
pub(crate) const ANGSTROM_API_TIMEOUT: Duration =
Duration::from_secs(ANGSTROM_ATTESTATION_REFRESH_INTERVAL.as_secs() / 2);
pub static GROUPABLE_PROTOCOLS: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
let mut set = HashSet::new();
set.insert("uniswap_v4");
set.insert("uniswap_v4_hooks");
set.insert("vm:balancer_v3");
set.insert("ekubo_v2");
set.insert("ekubo_v3");
set
});
pub static NON_PLE_ENCODED_PROTOCOLS: LazyLock<HashSet<&'static str>> = LazyLock::new(|| {
let mut set = HashSet::new();
set.insert("ekubo_v2");
set.insert("ekubo_v3");
set
});
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_one_timed_out_refresh_cannot_stale_the_window() {
let slowest_recovery =
ANGSTROM_API_TIMEOUT + ANGSTROM_ATTESTATION_REFRESH_INTERVAL + ANGSTROM_API_TIMEOUT;
assert!(
slowest_recovery <= ANGSTROM_ATTESTATION_MAX_AGE,
"a single timed-out refresh leaves the window stale for {slowest_recovery:?}, past \
the {ANGSTROM_ATTESTATION_MAX_AGE:?} maximum age"
);
}
}