// Ethereum Mainnet
pub const ETH_ETHEREUM_MAINNET: &'static str = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
pub const USDT_ETHEREUM_MAINNET: &'static str = "0xdAC17F958D2ee523a2206206994597C13D831ec7";
pub const USDC_ETHEREUM_MAINNET: &'static str = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
pub const DAI_ETHEREUM_MAINNET: &'static str = "0x6B175474E89094C44Da98b954EedeAC495271d0F";
pub const WBTC_ETHEREUM_MAINNET: &'static str = "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599";

// Arbitrum Mainnet
pub const ETH_ARB_MAINNET: &'static str = "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1";
pub const USDT_ARB_MAINNET: &'static str = "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9";
pub const USDC_ARB_MAINNET: &'static str = "0xaf88d065e77c8cC2239327C5EDb3A432268e5831";
pub const DAI_ARB_MAINNET: &'static str = "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1";
pub const WBTC_ARB_MAINNET: &'static str = "0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f";

// BSC Mainnet
pub const BNB_BSC_MAINNET: &'static str = "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c";
pub const USDT_BSC_MAINNET: &'static str = "0x55d398326f99059fF775485246999027B3197955";
pub const USDC_BSC_MAINNET: &'static str = "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d";
pub const BUSD_BSC_MAINNET: &'static str = "0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56";
pub const ETH_BSC_MAINNET: &'static str = "0x2170Ed0880ac9A755fd29B2688956BD959F933F8";
pub const WBTC_BSC_MAINNET: &'static str = "0x0555E30da8f98308EdB960aa94C0Db47230d2B9c";

// Base Mainnet
pub const ETH_BASE_MAINNET: &'static str = "0x4200000000000000000000000000000000000006";
pub const USDC_BASE_MAINNET: &'static str = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
pub const DAI_BASE_MAINNET: &'static str = "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb";
pub const WBTC_BASE_MAINNET: &'static str = "0x1ceA4b36B8F8b2e40A61d0B7ed03D70Cb5AA6d8C";

// HyperEVM Mainnet
pub const HYPE_HYPEREVM_MAINNET: &'static str = "0x5555555555555555555555555555555555555555";
pub const ETH_HYPEREVM_MAINNET: &'static str = "0xBe6727B535545C67d5cAa73dEa54865B92CF7907";
pub const USDT_HYPEREVM_MAINNET: &'static str = "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb";
pub const USDC_HYPEREVM_MAINNET: &'static str = "0xb88339CB7199b77E23DB6E890353E22632Ba630f";

// Plasma Mainnet
pub const WXPL_PLASMA_MAINNET: &'static str = "0x6100E367285b01F48D07953803A2d8dCA5D19873";

// Polygon Mainnet
pub const POL_POLYGON_MAINNET: &'static str = "0x0000000000000000000000000000000000001010";
pub const USDT_POLYGON_MAINNET: &'static str = "0xc2132D05D31c914a87C6611C10748AEb04B58e8F";
pub const USDC_POLYGON_MAINNET: &'static str = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
pub const WETH_POLYGON_MAINNET: &'static str = "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619";

// Optimism Mainnet
pub const ETH_OPTIMISM_MAINNET: &'static str = "0x4200000000000000000000000000000000000006";
pub const USDT_OPTIMISM_MAINNET: &'static str = "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58";
pub const USDC_OPTIMISM_MAINNET: &'static str = "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85";
pub const DAI_OPTIMISM_MAINNET: &'static str = "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1";

// zkSync Mainnet
pub const ETH_ZKSYNC_MAINNET: &'static str = "0x000000000000000000000000000000000000800A";
pub const USDC_ZKSYNC_MAINNET: &'static str = "0x1d17CBcF0D6D143135aE902365D2E5e2A16538D4";
pub const ZK_ZKSYNC_MAINNET: &'static str = "0x5A7d6b2F92C77FAD6CCaBd7EE0624E64907Eaf3E";

// StarkNet Mainnet
pub const ETH_STARKNET_MAINNET: &'static str =
    "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7";
pub const USDT_STARKNET_MAINNET: &'static str =
    "0x068f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8";
pub const USDC_STARKNET_MAINNET: &'static str =
    "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8";
pub const WBTC_STARKNET_MAINNET: &'static str =
    "0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac";

// Avalanche Mainnet
pub const WAVAX_AVALANCHE_MAINNET: &'static str = "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7";
pub const USDT_AVALANCHE_MAINNET: &'static str = "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7";
pub const USDC_AVALANCHE_MAINNET: &'static str = "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E";
pub const DAI_AVALANCHE_MAINNET: &'static str = "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70";

pub fn is_quote(address: &str) -> bool {
    let address_lower = address.to_lowercase();
    address_lower == ETH_ETHEREUM_MAINNET.to_lowercase()
        || address_lower == USDT_ETHEREUM_MAINNET.to_lowercase()
        || address_lower == USDC_ETHEREUM_MAINNET.to_lowercase()
        || address_lower == DAI_ETHEREUM_MAINNET.to_lowercase()
        || address_lower == WBTC_ETHEREUM_MAINNET.to_lowercase()
        || address_lower == ETH_ARB_MAINNET.to_lowercase()
        || address_lower == USDT_ARB_MAINNET.to_lowercase()
        || address_lower == USDC_ARB_MAINNET.to_lowercase()
        || address_lower == DAI_ARB_MAINNET.to_lowercase()
        || address_lower == WBTC_ARB_MAINNET.to_lowercase()
        || address_lower == BNB_BSC_MAINNET.to_lowercase()
        || address_lower == USDT_BSC_MAINNET.to_lowercase()
        || address_lower == USDC_BSC_MAINNET.to_lowercase()
        || address_lower == BUSD_BSC_MAINNET.to_lowercase()
        || address_lower == ETH_BSC_MAINNET.to_lowercase()
        || address_lower == WBTC_BSC_MAINNET.to_lowercase()
        || address_lower == ETH_BASE_MAINNET.to_lowercase()
        || address_lower == USDC_BASE_MAINNET.to_lowercase()
        || address_lower == DAI_BASE_MAINNET.to_lowercase()
        || address_lower == WBTC_BASE_MAINNET.to_lowercase()
        || address_lower == HYPE_HYPEREVM_MAINNET.to_lowercase()
        || address_lower == ETH_HYPEREVM_MAINNET.to_lowercase()
        || address_lower == USDT_HYPEREVM_MAINNET.to_lowercase()
        || address_lower == USDC_HYPEREVM_MAINNET.to_lowercase()
        || address_lower == WXPL_PLASMA_MAINNET.to_lowercase()
        || address_lower == POL_POLYGON_MAINNET.to_lowercase()
        || address_lower == USDT_POLYGON_MAINNET.to_lowercase()
        || address_lower == USDC_POLYGON_MAINNET.to_lowercase()
        || address_lower == WETH_POLYGON_MAINNET.to_lowercase()
        || address_lower == ETH_OPTIMISM_MAINNET.to_lowercase()
        || address_lower == USDT_OPTIMISM_MAINNET.to_lowercase()
        || address_lower == USDC_OPTIMISM_MAINNET.to_lowercase()
        || address_lower == DAI_OPTIMISM_MAINNET.to_lowercase()
        || address_lower == ETH_ZKSYNC_MAINNET.to_lowercase()
        || address_lower == USDC_ZKSYNC_MAINNET.to_lowercase()
        || address_lower == ZK_ZKSYNC_MAINNET.to_lowercase()
        || address_lower == ETH_STARKNET_MAINNET.to_lowercase()
        || address_lower == USDT_STARKNET_MAINNET.to_lowercase()
        || address_lower == USDC_STARKNET_MAINNET.to_lowercase()
        || address_lower == WBTC_STARKNET_MAINNET.to_lowercase()
        || address_lower == WAVAX_AVALANCHE_MAINNET.to_lowercase()
        || address_lower == USDT_AVALANCHE_MAINNET.to_lowercase()
        || address_lower == USDC_AVALANCHE_MAINNET.to_lowercase()
        || address_lower == DAI_AVALANCHE_MAINNET.to_lowercase()
}

pub fn get_block_time_by_address(address: &str) -> Option<u64> {
    let addr = address.to_lowercase();
    if addr == ETH_ETHEREUM_MAINNET.to_lowercase()
        || addr == USDT_ETHEREUM_MAINNET.to_lowercase()
        || addr == USDC_ETHEREUM_MAINNET.to_lowercase()
    {
        return Some(12);
    }
    if addr == ETH_ARB_MAINNET.to_lowercase()
        || addr == USDT_ARB_MAINNET.to_lowercase()
        || addr == USDC_ARB_MAINNET.to_lowercase()
    {
        return Some(1);
    }
    if addr == BNB_BSC_MAINNET.to_lowercase()
        || addr == USDT_BSC_MAINNET.to_lowercase()
        || addr == USDC_BSC_MAINNET.to_lowercase()
    {
        return Some(3);
    }
    if addr == ETH_BASE_MAINNET.to_lowercase() || addr == USDC_BASE_MAINNET.to_lowercase() {
        return Some(2);
    }
    if addr == HYPE_HYPEREVM_MAINNET.to_lowercase() || addr == ETH_HYPEREVM_MAINNET.to_lowercase() {
        return Some(2);
    }
    if addr == WXPL_PLASMA_MAINNET.to_lowercase() {
        return Some(2);
    }
    if addr == POL_POLYGON_MAINNET.to_lowercase()
        || addr == USDT_POLYGON_MAINNET.to_lowercase()
        || addr == USDC_POLYGON_MAINNET.to_lowercase()
    {
        return Some(2);
    }
    if addr == ETH_OPTIMISM_MAINNET.to_lowercase()
        || addr == USDT_OPTIMISM_MAINNET.to_lowercase()
        || addr == USDC_OPTIMISM_MAINNET.to_lowercase()
    {
        return Some(2);
    }
    if addr == ETH_ZKSYNC_MAINNET.to_lowercase() || addr == USDC_ZKSYNC_MAINNET.to_lowercase() {
        return Some(2);
    }
    if addr == ETH_STARKNET_MAINNET.to_lowercase()
        || addr == USDT_STARKNET_MAINNET.to_lowercase()
        || addr == USDC_STARKNET_MAINNET.to_lowercase()
    {
        return Some(10);
    }
    if addr == WAVAX_AVALANCHE_MAINNET.to_lowercase()
        || addr == USDT_AVALANCHE_MAINNET.to_lowercase()
        || addr == USDC_AVALANCHE_MAINNET.to_lowercase()
    {
        return Some(2);
    }
    None
}

// ============== Ethereum Mainnet ==============
pub const UNISWAP_V2_FACTORY_ETHEREUM: &'static str = "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f";
pub const UNISWAP_V2_ROUTER_ETHEREUM: &'static str = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D";
pub const UNISWAP_V3_FACTORY_ETHEREUM: &'static str = "0x1F98431c8aD98523631AE4a59f267346ea31F984";
pub const UNISWAP_V3_ROUTER_ETHEREUM: &'static str = "0xE592427A0AEce92De3Edee1F18E0157C05861564";

pub const SUSHI_FACTORY_ETHEREUM: &'static str = "0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac";
pub const SUSHI_ROUTER_ETHEREUM: &'static str = "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F";

pub const CURVE_FACTORY_ETHEREUM: &'static str = "0xB9fC157394Af804a3578134A6585C0dc9cc990d4";
pub const CURVE_3POOL_ETHEREUM: &'static str = "0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7";

pub const BALANCER_VAULT_ETHEREUM: &'static str = "0xBA12222222228d8Ba445958a75a0704d566BF2C8";

pub const INCH_V4_ROUTER_ETHEREUM: &'static str = "0x1111111254EEB25477B68fb85Ed929f73A960582";

// ============== Arbitrum Mainnet ==============
pub const UNISWAP_V3_FACTORY_ARBITRUM: &'static str = "0x1F98431c8aD98523631AE4a59f267346ea31F984";
pub const UNISWAP_V3_ROUTER_ARBITRUM: &'static str = "0xE592427A0AEce92De3Edee1F18E0157C05861564";

pub const SUSHI_FACTORY_ARBITRUM: &'static str = "0xc35DADB65012eC5796536bD9864eD8773aBc74C4";
pub const SUSHI_ROUTER_ARBITRUM: &'static str = "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506";

// ============== BSC Mainnet ==============
pub const PANCAKE_V2_FACTORY_BSC: &'static str = "0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73";
pub const PANCAKE_V2_ROUTER_BSC: &'static str = "0x10ED43C718714eb63d5aA57B78B54704E256024E";
pub const PANCAKE_V3_FACTORY_BSC: &'static str = "0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865";
pub const PANCAKE_V3_ROUTER_BSC: &'static str = "0x13f4EA83D0bd40E75C8222255bc855a974568Dd4";

pub const BISWAP_FACTORY_BSC: &'static str = "0x858E3312ed3A876947EA49d572A7C42DE08af7EE";
pub const BISWAP_ROUTER_BSC: &'static str = "0x3a6d8cA21D1CF76F653A67577FA0D27453350dD8";

// ============== Polygon Mainnet ==============
pub const UNISWAP_V3_FACTORY_POLYGON: &'static str = "0x1F98431c8aD98523631AE4a59f267346ea31F984";
pub const UNISWAP_V3_ROUTER_POLYGON: &'static str = "0xE592427A0AEce92De3Edee1F18E0157C05861564";
pub const QUICKSWAP_FACTORY_POLYGON: &'static str = "0x5757371414417b8C6CAad45bAeF941aBc7d3Ab32";
pub const QUICKSWAP_ROUTER_POLYGON: &'static str = "0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff";

pub const SUSHI_FACTORY_POLYGON: &'static str = "0xc35DADB65012eC5796536bD9864eD8773aBc74C4";
pub const SUSHI_ROUTER_POLYGON: &'static str = "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506";

// ============== Optimism Mainnet ==============
pub const UNISWAP_V3_FACTORY_OPTIMISM: &'static str = "0x1F98431c8aD98523631AE4a59f267346ea31F984";
pub const UNISWAP_V3_ROUTER_OPTIMISM: &'static str = "0xE592427A0AEce92De3Edee1F18E0157C05861564";

pub const VELODROME_V2_FACTORY_OPTIMISM: &'static str =
    "0xF1046053aa5682b4F9a81b5481394DA16BE5FF5a";
pub const VELODROME_V2_ROUTER_OPTIMISM: &'static str = "0xa062aE8A9c5e11aaA026fc2670B0D65cCc8B2858";

// ============== Avalanche Mainnet ==============
pub const UNISWAP_V3_FACTORY_AVALANCHE: &'static str = "0x740b1c1de25031C31FF4fC9A62f554A55cdC1baD";
pub const UNISWAP_V3_ROUTER_AVALANCHE: &'static str = "0xbb00FF08d01D300023C629E8fFfFcb65A5a578cE";

pub const TRADER_JOE_FACTORY_AVALANCHE: &'static str = "0x9Ad6C38BE94206cA50bb0d90783181662f0Cfa10";
pub const TRADER_JOE_ROUTER_AVALANCHE: &'static str = "0x60aE616a2155Ee3d9A68541Ba4544862310933d4";

// ============== Base Mainnet ==============
pub const UNISWAP_V3_FACTORY_BASE: &'static str = "0x33128a8fC17869897dcE68Ed026d694621f6FDfD";
pub const UNISWAP_V3_ROUTER_BASE: &'static str = "0x2626664c2603336E57B271c5C0b26F421741e481";

pub const BASESWAP_FACTORY_BASE: &'static str = "0xFDa619b6d20975be80A10332cD39b9a4b0FAa8BB";
pub const BASESWAP_ROUTER_BASE: &'static str = "0x327Df1E6de05895d2ab08513aaDD9313Fe505d86";

// ============== Fantom Mainnet ==============
pub const SPOOKYSWAP_FACTORY_FANTOM: &'static str = "0x152eE697f2E276fA89E96742e9bB9aB1F2E61bE3";
pub const SPOOKYSWAP_ROUTER_FANTOM: &'static str = "0xF491e7B69E4244ad4002BC14e878a34207E38c29";

// ============== zkSync Mainnet ==============
pub const SYNC_SWAP_FACTORY_ZKSYNC: &'static str = "0xf2DAd89f2788a8CD54625C60b55cD3d2D0ACa7Cb";
pub const SYNC_SWAP_ROUTER_ZKSYNC: &'static str = "0x2da10A1e27bF85cEdD8FFb1AbBe97e53391C0295";

// ============== StarkNet Mainnet ==============
pub const MY_SWAP_ROUTER_STARKNET: &'static str =
    "0x010884171baf1914edc28d7afb619b40a4051cfae78a094a55d230f19e944a28";

pub fn get_common_dex_event_signatures() -> Vec<(&'static str, &'static str)> {
    vec![
        (
            "Swap(address,uint256,uint256,uint256,uint256,address)",
            "Uniswap V2",
        ),
        ("Mint(address,uint256,uint256)", "Uniswap V2"),
        ("Burn(address,uint256,uint256)", "Uniswap V2"),
        ("Sync(uint112,uint112)", "Uniswap V2"),
        (
            "Swap(address,address,int256,int256,uint160,uint128,int24)",
            "Uniswap V3",
        ),
        (
            "Mint(address,address,int24,int24,uint128,uint256,uint256)",
            "Uniswap V3",
        ),
        (
            "Burn(address,int24,int24,uint128,uint256,uint256)",
            "Uniswap V3",
        ),
        (
            "Collect(address,address,int24,int24,uint128,uint128)",
            "Uniswap V3",
        ),
        (
            "TokenExchange(address,int128,uint256,int128,uint256)",
            "Curve",
        ),
        (
            "AddLiquidity(address,uint256[2],uint256[2],uint256,uint256)",
            "Curve",
        ),
        ("RemoveLiquidity(address,uint256[2],uint256[2])", "Curve"),
        ("Swap(address,address,uint256,uint256)", "PancakeSwap"),
        (
            "Swap(address,uint256,uint256,uint256,uint256,address)",
            "SushiSwap",
        ),
        ("Swap(address,address,uint256,uint256)", "Trader Joe"),
        ("Swap(address,address,uint256,uint256,uint256)", "Balancer"),
        (
            "Swapped(address,address,address,address,uint256,uint256)",
            "1inch",
        ),
        ("DODOSwap(address,address,uint256,uint256)", "DODO"),
        (
            "Swap(address,address,int256,int256,uint160,address)",
            "KyberSwap",
        ),
    ]
}

pub fn get_dex_name_by_address(address: &str) -> Option<&'static str> {
    let address_lower = address.to_lowercase();
    let verified_dex_mappings: [(&str, &str); 43] = [
        // Ethereum
        (UNISWAP_V2_FACTORY_ETHEREUM, "Uniswap V2 Factory"),
        (UNISWAP_V2_ROUTER_ETHEREUM, "Uniswap V2 Router"),
        (UNISWAP_V3_FACTORY_ETHEREUM, "Uniswap V3 Factory"),
        (UNISWAP_V3_ROUTER_ETHEREUM, "Uniswap V3 Router"),
        (SUSHI_FACTORY_ETHEREUM, "SushiSwap Factory"),
        (SUSHI_ROUTER_ETHEREUM, "SushiSwap Router"),
        (CURVE_FACTORY_ETHEREUM, "Curve Factory"),
        (CURVE_3POOL_ETHEREUM, "Curve 3pool"),
        (BALANCER_VAULT_ETHEREUM, "Balancer Vault"),
        (INCH_V4_ROUTER_ETHEREUM, "1inch V4 Router"),
        // Arbitrum
        (UNISWAP_V3_FACTORY_ARBITRUM, "Uniswap V3 Factory (Arbitrum)"),
        (UNISWAP_V3_ROUTER_ARBITRUM, "Uniswap V3 Router (Arbitrum)"),
        (SUSHI_FACTORY_ARBITRUM, "SushiSwap Factory (Arbitrum)"),
        (SUSHI_ROUTER_ARBITRUM, "SushiSwap Router (Arbitrum)"),
        // BSC
        (PANCAKE_V2_FACTORY_BSC, "PancakeSwap V2 Factory"),
        (PANCAKE_V2_ROUTER_BSC, "PancakeSwap V2 Router"),
        (PANCAKE_V3_FACTORY_BSC, "PancakeSwap V3 Factory"),
        (PANCAKE_V3_ROUTER_BSC, "PancakeSwap V3 Router"),
        (BISWAP_FACTORY_BSC, "BiSwap Factory"),
        (BISWAP_ROUTER_BSC, "BiSwap Router"),
        // Polygon
        (UNISWAP_V3_FACTORY_POLYGON, "Uniswap V3 Factory (Polygon)"),
        (UNISWAP_V3_ROUTER_POLYGON, "Uniswap V3 Router (Polygon)"),
        (QUICKSWAP_FACTORY_POLYGON, "QuickSwap Factory"),
        (QUICKSWAP_ROUTER_POLYGON, "QuickSwap Router"),
        (SUSHI_FACTORY_POLYGON, "SushiSwap Factory (Polygon)"),
        (SUSHI_ROUTER_POLYGON, "SushiSwap Router (Polygon)"),
        // Optimism
        (UNISWAP_V3_FACTORY_OPTIMISM, "Uniswap V3 Factory (Optimism)"),
        (UNISWAP_V3_ROUTER_OPTIMISM, "Uniswap V3 Router (Optimism)"),
        (VELODROME_V2_FACTORY_OPTIMISM, "Velodrome V2 Factory"),
        (VELODROME_V2_ROUTER_OPTIMISM, "Velodrome V2 Router"),
        // Avalanche
        (
            UNISWAP_V3_FACTORY_AVALANCHE,
            "Uniswap V3 Factory (Avalanche)",
        ),
        (UNISWAP_V3_ROUTER_AVALANCHE, "Uniswap V3 Router (Avalanche)"),
        (TRADER_JOE_FACTORY_AVALANCHE, "Trader Joe Factory"),
        (TRADER_JOE_ROUTER_AVALANCHE, "Trader Joe Router"),
        // Base
        (UNISWAP_V3_FACTORY_BASE, "Uniswap V3 Factory (Base)"),
        (UNISWAP_V3_ROUTER_BASE, "Uniswap V3 Router (Base)"),
        (BASESWAP_FACTORY_BASE, "BaseSwap Factory"),
        (BASESWAP_ROUTER_BASE, "BaseSwap Router"),
        // Fantom
        (SPOOKYSWAP_FACTORY_FANTOM, "SpookySwap Factory"),
        (SPOOKYSWAP_ROUTER_FANTOM, "SpookySwap Router"),
        // zkSync
        (SYNC_SWAP_FACTORY_ZKSYNC, "SyncSwap Factory"),
        (SYNC_SWAP_ROUTER_ZKSYNC, "SyncSwap Router"),
        // StarkNet
        (MY_SWAP_ROUTER_STARKNET, "MySwap Router (StarkNet)"),
    ];
    for (dex_addr, dex_name) in &verified_dex_mappings {
        if address_lower == dex_addr.to_lowercase() {
            return Some(dex_name);
        }
    }
    None
}

pub fn get_known_dexes_for_network(evm_type: &str) -> Vec<&'static str> {
    match evm_type {
        "ETHEREUM_MAINNET" => vec!["Uniswap", "SushiSwap", "Curve", "Balancer", "1inch"],
        "ARB_MAINNET" => vec!["Uniswap", "SushiSwap"],
        "BSC_MAINNET" => vec!["PancakeSwap", "BiSwap"],
        "POLYGON_MAINNET" => vec!["Uniswap", "QuickSwap", "SushiSwap"],
        "OPTIMISM_MAINNET" => vec!["Uniswap", "Velodrome"],
        "AVALANCHE_MAINNET" => vec!["Uniswap", "Trader Joe"],
        "BASE_MAINNET" => vec!["Uniswap", "BaseSwap"],
        "FANTOM_MAINNET" => vec!["SpookySwap"],
        "ZKSYNC_MAINNET" => vec!["SyncSwap"],
        "STARKNET_MAINNET" => vec!["MySwap"],
        "HYPEREVM_MAINNET" => vec![],
        "PLASMA_MAINNET" => vec![],
        "RONIN_MAINNET" => vec![],
        "SKALE_MAINNET" => vec![],
        "IMMUTABLE_MAINNET" => vec![],
        _ => vec![],
    }
}

pub fn is_dex_contract(address: &str) -> bool {
    get_dex_name_by_address(address).is_some()
}

pub mod dex_events {
    use ethers::core::utils::keccak256;

    pub fn uniswap_v2_swap() -> [u8; 32] {
        keccak256(b"Swap(address,uint256,uint256,uint256,uint256,address)")
    }

    pub fn uniswap_v2_mint() -> [u8; 32] {
        keccak256(b"Mint(address,uint256,uint256)")
    }

    pub fn uniswap_v2_burn() -> [u8; 32] {
        keccak256(b"Burn(address,uint256,uint256)")
    }

    pub fn uniswap_v2_sync() -> [u8; 32] {
        keccak256(b"Sync(uint112,uint112)")
    }

    pub fn uniswap_v3_swap() -> [u8; 32] {
        keccak256(b"Swap(address,address,int256,int256,uint160,uint128,int24)")
    }

    pub fn uniswap_v3_mint() -> [u8; 32] {
        keccak256(b"Mint(address,address,int24,int24,uint128,uint256,uint256)")
    }

    pub fn uniswap_v3_burn() -> [u8; 32] {
        keccak256(b"Burn(address,int24,int24,uint128,uint256,uint256)")
    }

    pub fn uniswap_v3_collect() -> [u8; 32] {
        keccak256(b"Collect(address,address,int24,int24,uint128,uint128)")
    }

    pub fn curve_token_exchange() -> [u8; 32] {
        keccak256(b"TokenExchange(address,int128,uint256,int128,uint256)")
    }

    pub fn curve_add_liquidity() -> [u8; 32] {
        keccak256(b"AddLiquidity(address,uint256[2],uint256[2],uint256,uint256)")
    }

    pub fn curve_remove_liquidity() -> [u8; 32] {
        keccak256(b"RemoveLiquidity(address,uint256[2],uint256[2])")
    }

    pub fn erc20_transfer() -> [u8; 32] {
        keccak256(b"Transfer(address,address,uint256)")
    }

    pub fn pancake_swap() -> [u8; 32] {
        keccak256(b"Swap(address,address,uint256,uint256)")
    }

    pub fn sushi_swap() -> [u8; 32] {
        keccak256(b"Swap(address,uint256,uint256,uint256,uint256,address)")
    }

    pub fn balancer_swap() -> [u8; 32] {
        keccak256(b"Swap(address,address,uint256,uint256,uint256)")
    }

    pub fn is_dex_event(topic0: &[u8]) -> bool {
        topic0 == &uniswap_v2_swap()[..]
            || topic0 == &uniswap_v2_mint()[..]
            || topic0 == &uniswap_v2_burn()[..]
            || topic0 == &uniswap_v2_sync()[..]
            || topic0 == &uniswap_v3_swap()[..]
            || topic0 == &uniswap_v3_mint()[..]
            || topic0 == &uniswap_v3_burn()[..]
            || topic0 == &uniswap_v3_collect()[..]
            || topic0 == &curve_token_exchange()[..]
            || topic0 == &curve_add_liquidity()[..]
            || topic0 == &curve_remove_liquidity()[..]
            || topic0 == &pancake_swap()[..]
            || topic0 == &sushi_swap()[..]
            || topic0 == &balancer_swap()[..]
    }

    pub fn identify_dex_by_event(topic0: &[u8]) -> Option<&'static str> {
        if topic0 == &uniswap_v2_swap()[..]
            || topic0 == &uniswap_v2_mint()[..]
            || topic0 == &uniswap_v2_burn()[..]
            || topic0 == &uniswap_v2_sync()[..]
        {
            Some("Uniswap V2")
        } else if topic0 == &uniswap_v3_swap()[..]
            || topic0 == &uniswap_v3_mint()[..]
            || topic0 == &uniswap_v3_burn()[..]
            || topic0 == &uniswap_v3_collect()[..]
        {
            Some("Uniswap V3")
        } else if topic0 == &curve_token_exchange()[..]
            || topic0 == &curve_add_liquidity()[..]
            || topic0 == &curve_remove_liquidity()[..]
        {
            Some("Curve")
        } else if topic0 == &pancake_swap()[..] {
            Some("PancakeSwap")
        } else if topic0 == &sushi_swap()[..] {
            Some("SushiSwap")
        } else if topic0 == &balancer_swap()[..] {
            Some("Balancer")
        } else if is_dex_event(topic0) {
            Some("Unknown DEX")
        } else {
            None
        }
    }
}
