alloy-chains 0.2.35

Canonical type definitions for EIP-155 chains
Documentation
// @generated by scripts/update-registry.py. Do NOT modify manually.

use alloy_primitives::{Address, address};

/// An Ethereum EIP-155 chain.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[cfg_attr(feature = "schema", schemars(rename_all = "snake_case"))]
#[repr(u64)]
#[allow(missing_docs)]
#[non_exhaustive]
pub enum NamedChain {
%%enum_variants
}

impl NamedChain {
    /// The number of named chains.
    pub const COUNT: usize = %%chain_data_len;

    /// All named chains in declaration order.
    pub const VARIANTS: &'static [Self] = &[
%%variants
    ];

    /// All named chain string representations in declaration order.
    pub const VARIANT_NAMES: &'static [&'static str] = &{
        let mut names = [""; %%chain_data_len];
        let mut index = 0;
        while index < CHAIN_DATA.len() {
            names[index] = CHAIN_DATA[index].name();
            index += 1;
        }
        names
    };

    #[inline]
    const fn from_index(index: ChainIndex) -> Self {
        Self::VARIANTS[index as usize]
    }

    const fn index(self) -> ChainIndex {
        match self {
%%chain_index_arms
        }
    }

    #[inline]
    const fn data(self) -> ChainData {
        CHAIN_DATA[self.index() as usize]
    }

    #[inline]
    const fn has_flag(self, flag: ChainFlags) -> bool {
        self.data().flags & flag != 0
    }

    /// Returns the chain for the given EIP-155 chain ID.
    pub const fn from_chain_id(id: u64) -> Option<Self> {
        match id {
%%chain_id_arms
            _ => None,
        }
    }

    /// Returns the string representation of the chain.
    #[inline]
    pub const fn as_str(&self) -> &'static str {
        self.data().name()
    }

    /// Returns `true` if this chain is Ethereum or an Ethereum testnet.
    #[inline]
    pub const fn is_ethereum(&self) -> bool {
        %%ethereum_predicate
    }

    /// Returns true if the chain contains Optimism configuration.
    #[inline]
    pub const fn is_optimism(self) -> bool {
        %%optimism_predicate
    }

    /// Returns true if the chain contains Gnosis configuration.
    #[inline]
    pub const fn is_gnosis(self) -> bool {
        %%gnosis_predicate
    }

    /// Returns true if the chain contains Polygon configuration.
    #[inline]
    pub const fn is_polygon(self) -> bool {
        %%polygon_predicate
    }

    /// Returns true if the chain contains Arbitrum configuration.
    #[inline]
    pub const fn is_arbitrum(self) -> bool {
        %%arbitrum_predicate
    }

    /// Returns true if the chain contains Elastic Network configuration.
    #[inline]
    pub const fn is_elastic(self) -> bool {
        %%elastic_predicate
    }

    /// Returns true if the chain contains Tempo configuration.
    #[inline]
    pub const fn is_tempo(self) -> bool {
        %%tempo_predicate
    }

    /// Returns true if the chain uses a custom Sourcify-compatible API.
    #[inline]
    pub const fn is_custom_sourcify(self) -> bool {
        %%custom_sourcify_predicate
    }

    /// Returns whether the chain implements EIP-1559.
    #[inline]
    pub const fn is_legacy(self) -> bool {
        %%legacy_predicate
    }

    /// Returns whether the chain supports the Shanghai hardfork.
    #[inline]
    pub const fn supports_shanghai(self) -> bool {
        %%shanghai_predicate
    }

    /// Returns whether the chain is a testnet.
    #[inline]
    pub const fn is_testnet(self) -> bool {
        %%testnet_predicate
    }

    /// Returns the symbol of the chain's native currency.
    #[inline]
    pub const fn native_currency_symbol(self) -> Option<&'static str> {
        self.data().native_currency_symbol()
    }

    /// Returns the chain's blockchain explorer and its API URLs.
    #[inline]
    pub const fn etherscan_urls(self) -> Option<(&'static str, &'static str)> {
        let data = self.data();
        match (data.etherscan_api_url(), data.etherscan_base_url()) {
            (Some(api), Some(base)) => Some((api, base)),
            _ => None,
        }
    }

    /// Returns the chain's blockchain explorer API key environment variable name.
    #[inline]
    pub const fn etherscan_api_key_name(self) -> Option<&'static str> {
        self.data().etherscan_api_key_name()
    }

    /// Returns the address of the most popular wrapped native token address.
    #[inline]
    pub const fn wrapped_native_token(self) -> Option<Address> {
        let index = self.data().wrapped_native_token;
        if index == NO_INDEX {
            None
        } else {
            Some(WRAPPED_NATIVE_TOKENS[index as usize])
        }
    }

    #[inline]
    pub(crate) const fn average_blocktime_millis(self) -> u16 {
        self.data().average_blocktime_millis
    }

    pub(crate) fn from_parse_str(value: &str) -> Option<Self> {
        PARSE_NAMES.get(value).copied().map(Self::from_index)
    }

    #[cfg(feature = "serde")]
    pub(crate) fn from_serde_str(value: &str) -> Option<Self> {
        PARSE_NAMES
            .get(value)
            .or_else(|| SERDE_NAMES.get(value))
            .copied()
            .map(Self::from_index)
    }
}

type ChainIndex = %%chain_index_type;
type ChainFlags = %%flag_type;

%%flag_consts
const NO_INDEX: u8 = u8::MAX;

#[derive(Clone, Copy)]
#[repr(C, packed)]
struct ChainData {
    name: u8,
    native_currency_symbol: u8,
    etherscan_api_url: u8,
    etherscan_base_url: u8,
    etherscan_api_key_name: u8,
    average_blocktime_millis: u16,
    flags: ChainFlags,
    wrapped_native_token: u8,
}

impl ChainData {
    #[inline]
    const fn name(self) -> &'static str {
        CHAIN_NAMES[self.name as usize]
    }

    #[inline]
    const fn native_currency_symbol(self) -> Option<&'static str> {
        static_str(&NATIVE_CURRENCY_SYMBOLS, self.native_currency_symbol)
    }

    #[inline]
    const fn etherscan_api_url(self) -> Option<&'static str> {
        static_str(&ETHERSCAN_API_URLS, self.etherscan_api_url)
    }

    #[inline]
    const fn etherscan_base_url(self) -> Option<&'static str> {
        static_str(&ETHERSCAN_BASE_URLS, self.etherscan_base_url)
    }

    #[inline]
    const fn etherscan_api_key_name(self) -> Option<&'static str> {
        static_str(&ETHERSCAN_API_KEY_NAMES, self.etherscan_api_key_name)
    }
}

const fn static_str(table: &'static [&'static str], index: u8) -> Option<&'static str> {
    if index == NO_INDEX { None } else { Some(table[index as usize]) }
}

#[cfg(test)]
pub(crate) const PARSE_ALIASES: &[(NamedChain, &str)] = &[
%%parse_aliases
];

#[cfg(all(test, feature = "serde"))]
pub(crate) const SERDE_ALIASES: &[(NamedChain, &str)] = &[
%%serde_aliases
];

%%string_table_data

static WRAPPED_NATIVE_TOKENS: [Address; %%wrapped_native_token_len] = [
%%wrapped_native_token_data
];

static CHAIN_DATA: [ChainData; %%chain_data_len] = {
    use NO_INDEX as N;
    use NO_INDEX as W;
%%flag_aliases

    #[allow(clippy::too_many_arguments)]
    const fn d(
        name: u8,
        native_currency_symbol: u8,
        etherscan_api_url: u8,
        etherscan_base_url: u8,
        etherscan_api_key_name: u8,
        average_blocktime_millis: u16,
        flags: ChainFlags,
        wrapped_native_token: u8,
    ) -> ChainData {
        ChainData {
            name,
            native_currency_symbol,
            etherscan_api_url,
            etherscan_base_url,
            etherscan_api_key_name,
            average_blocktime_millis,
            flags,
            wrapped_native_token,
        }
    }

    [
%%chain_data
    ]
};

%%phf_maps

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn no_index_is_not_used_as_index() {
        assert_table_len(CHAIN_NAMES.len());
        assert_table_len(NATIVE_CURRENCY_SYMBOLS.len());
        assert_table_len(ETHERSCAN_API_URLS.len());
        assert_table_len(ETHERSCAN_BASE_URLS.len());
        assert_table_len(ETHERSCAN_API_KEY_NAMES.len());
        assert_table_len(WRAPPED_NATIVE_TOKENS.len());

        for data in CHAIN_DATA.iter().copied() {
            assert_index(data.name, CHAIN_NAMES.len());
            assert_optional_index(data.native_currency_symbol, NATIVE_CURRENCY_SYMBOLS.len());
            assert_optional_index(data.etherscan_api_url, ETHERSCAN_API_URLS.len());
            assert_optional_index(data.etherscan_base_url, ETHERSCAN_BASE_URLS.len());
            assert_optional_index(data.etherscan_api_key_name, ETHERSCAN_API_KEY_NAMES.len());
            assert_optional_index(data.wrapped_native_token, WRAPPED_NATIVE_TOKENS.len());
        }
    }

    fn assert_table_len(len: usize) {
        assert!(len <= NO_INDEX as usize);
    }

    fn assert_index(index: u8, len: usize) {
        assert_ne!(index, NO_INDEX);
        assert!((index as usize) < len);
    }

    fn assert_optional_index(index: u8, len: usize) {
        if index != NO_INDEX {
            assert!((index as usize) < len);
        }
    }
}