use once_cell::sync::Lazy;
use solana_pubkey::pubkey;
use std::collections::HashMap;
use crate::chain::{ChainId, eip155, solana};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NetworkInfo {
pub name: &'static str,
pub namespace: &'static str,
pub reference: &'static str,
}
impl NetworkInfo {
pub fn chain_id(&self) -> ChainId {
ChainId::new(self.namespace, self.reference)
}
}
#[allow(dead_code)]
pub trait KnownNetworkEip155<A> {
fn base() -> A;
fn base_sepolia() -> A;
fn polygon() -> A;
fn polygon_amoy() -> A;
fn avalanche() -> A;
fn avalanche_fuji() -> A;
fn sei() -> A;
fn sei_testnet() -> A;
fn xdc() -> A;
fn xrpl_evm() -> A;
fn peaq() -> A;
fn iotex() -> A;
}
#[allow(dead_code)]
pub trait KnownNetworkSolana<A> {
fn solana() -> A;
fn solana_devnet() -> A;
}
impl KnownNetworkEip155<ChainId> for ChainId {
fn base() -> ChainId {
ChainId::new("eip155", "8453")
}
fn base_sepolia() -> ChainId {
ChainId::new("eip155", "84532")
}
fn polygon() -> ChainId {
ChainId::new("eip155", "137")
}
fn polygon_amoy() -> ChainId {
ChainId::new("eip155", "80002")
}
fn avalanche() -> ChainId {
ChainId::new("eip155", "43114")
}
fn avalanche_fuji() -> ChainId {
ChainId::new("eip155", "43113")
}
fn sei() -> ChainId {
ChainId::new("eip155", "1329")
}
fn sei_testnet() -> ChainId {
ChainId::new("eip155", "1328")
}
fn xdc() -> ChainId {
ChainId::new("eip155", "50")
}
fn xrpl_evm() -> ChainId {
ChainId::new("eip155", "1440000")
}
fn peaq() -> ChainId {
ChainId::new("eip155", "3338")
}
fn iotex() -> ChainId {
ChainId::new("eip155", "4689")
}
}
impl KnownNetworkSolana<ChainId> for ChainId {
fn solana() -> ChainId {
solana::SolanaChainReference::solana().into()
}
fn solana_devnet() -> ChainId {
solana::SolanaChainReference::solana_devnet().into()
}
}
static KNOWN_NETWORKS: &[NetworkInfo] = &[
NetworkInfo {
name: "base",
namespace: "eip155",
reference: "8453",
},
NetworkInfo {
name: "base-sepolia",
namespace: "eip155",
reference: "84532",
},
NetworkInfo {
name: "polygon",
namespace: "eip155",
reference: "137",
},
NetworkInfo {
name: "polygon-amoy",
namespace: "eip155",
reference: "80002",
},
NetworkInfo {
name: "avalanche",
namespace: "eip155",
reference: "43114",
},
NetworkInfo {
name: "avalanche-fuji",
namespace: "eip155",
reference: "43113",
},
NetworkInfo {
name: "sei",
namespace: "eip155",
reference: "1329",
},
NetworkInfo {
name: "sei-testnet",
namespace: "eip155",
reference: "1328",
},
NetworkInfo {
name: "xdc",
namespace: "eip155",
reference: "50",
},
NetworkInfo {
name: "xrpl-evm",
namespace: "eip155",
reference: "1440000",
},
NetworkInfo {
name: "peaq",
namespace: "eip155",
reference: "3338",
},
NetworkInfo {
name: "iotex",
namespace: "eip155",
reference: "4689",
},
NetworkInfo {
name: "solana",
namespace: "solana",
reference: "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
},
NetworkInfo {
name: "solana-devnet",
namespace: "solana",
reference: "EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
},
];
static NAME_TO_CHAIN_ID: Lazy<HashMap<&'static str, ChainId>> = Lazy::new(|| {
KNOWN_NETWORKS
.iter()
.map(|n| (n.name, n.chain_id()))
.collect()
});
static CHAIN_ID_TO_NAME: Lazy<HashMap<ChainId, &'static str>> = Lazy::new(|| {
KNOWN_NETWORKS
.iter()
.map(|n| (n.chain_id(), n.name))
.collect()
});
pub fn chain_id_by_network_name(name: &str) -> Option<&ChainId> {
NAME_TO_CHAIN_ID.get(name)
}
pub fn network_name_by_chain_id(chain_id: &ChainId) -> Option<&'static str> {
CHAIN_ID_TO_NAME.get(chain_id).copied()
}
#[allow(dead_code, clippy::upper_case_acronyms)] pub struct USDC;
impl KnownNetworkSolana<solana::SolanaTokenDeployment> for USDC {
fn solana() -> solana::SolanaTokenDeployment {
let address = pubkey!("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
solana::SolanaTokenDeployment::new(
solana::SolanaChainReference::solana(),
address.into(),
6,
)
}
fn solana_devnet() -> solana::SolanaTokenDeployment {
let address = pubkey!("4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU");
solana::SolanaTokenDeployment::new(
solana::SolanaChainReference::solana_devnet(),
address.into(),
6,
)
}
}
impl KnownNetworkEip155<eip155::Eip155TokenDeployment> for USDC {
fn base() -> eip155::Eip155TokenDeployment {
eip155::Eip155TokenDeployment {
chain_reference: eip155::Eip155ChainReference::new(8453),
address: alloy_primitives::address!("0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"),
decimals: 6,
eip712: Some(eip155::TokenDeploymentEip712 {
name: "USD Coin".into(),
version: "2".into(),
}),
}
}
fn base_sepolia() -> eip155::Eip155TokenDeployment {
eip155::Eip155TokenDeployment {
chain_reference: eip155::Eip155ChainReference::new(84532),
address: alloy_primitives::address!("0x036CbD53842c5426634e7929541eC2318f3dCF7e"),
decimals: 6,
eip712: Some(eip155::TokenDeploymentEip712 {
name: "USDC".into(),
version: "2".into(),
}),
}
}
fn polygon() -> eip155::Eip155TokenDeployment {
eip155::Eip155TokenDeployment {
chain_reference: eip155::Eip155ChainReference::new(137),
address: alloy_primitives::address!("0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"),
decimals: 6,
eip712: Some(eip155::TokenDeploymentEip712 {
name: "USDC".into(),
version: "2".into(),
}),
}
}
fn polygon_amoy() -> eip155::Eip155TokenDeployment {
eip155::Eip155TokenDeployment {
chain_reference: eip155::Eip155ChainReference::new(80002),
address: alloy_primitives::address!("0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582"),
decimals: 6,
eip712: Some(eip155::TokenDeploymentEip712 {
name: "USDC".into(),
version: "2".into(),
}),
}
}
fn avalanche() -> eip155::Eip155TokenDeployment {
eip155::Eip155TokenDeployment {
chain_reference: eip155::Eip155ChainReference::new(43114),
address: alloy_primitives::address!("0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"),
decimals: 6,
eip712: Some(eip155::TokenDeploymentEip712 {
name: "USD Coin".into(),
version: "2".into(),
}),
}
}
fn avalanche_fuji() -> eip155::Eip155TokenDeployment {
eip155::Eip155TokenDeployment {
chain_reference: eip155::Eip155ChainReference::new(43113),
address: alloy_primitives::address!("0x5425890298aed601595a70AB815c96711a31Bc65"),
decimals: 6,
eip712: Some(eip155::TokenDeploymentEip712 {
name: "USD Coin".into(),
version: "2".into(),
}),
}
}
fn sei() -> eip155::Eip155TokenDeployment {
eip155::Eip155TokenDeployment {
chain_reference: eip155::Eip155ChainReference::new(1329),
address: alloy_primitives::address!("0xe15fC38F6D8c56aF07bbCBe3BAf5708A2Bf42392"),
decimals: 6,
eip712: Some(eip155::TokenDeploymentEip712 {
name: "USDC".into(),
version: "2".into(),
}),
}
}
fn sei_testnet() -> eip155::Eip155TokenDeployment {
eip155::Eip155TokenDeployment {
chain_reference: eip155::Eip155ChainReference::new(1328),
address: alloy_primitives::address!("0x4fCF1784B31630811181f670Aea7A7bEF803eaED"),
decimals: 6,
eip712: Some(eip155::TokenDeploymentEip712 {
name: "USDC".into(),
version: "2".into(),
}),
}
}
fn xdc() -> eip155::Eip155TokenDeployment {
eip155::Eip155TokenDeployment {
chain_reference: eip155::Eip155ChainReference::new(50),
address: alloy_primitives::address!("0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1"),
decimals: 6,
eip712: Some(eip155::TokenDeploymentEip712 {
name: "USDC".into(),
version: "2".into(),
}),
}
}
fn xrpl_evm() -> eip155::Eip155TokenDeployment {
eip155::Eip155TokenDeployment {
chain_reference: eip155::Eip155ChainReference::new(1440000),
address: alloy_primitives::address!("0xDaF4556169c4F3f2231d8ab7BC8772Ddb7D4c84C"),
decimals: 6,
eip712: None,
}
}
fn peaq() -> eip155::Eip155TokenDeployment {
eip155::Eip155TokenDeployment {
chain_reference: eip155::Eip155ChainReference::new(3338),
address: alloy_primitives::address!("0xbbA60da06c2c5424f03f7434542280FCAd453d10"),
decimals: 6,
eip712: Some(eip155::TokenDeploymentEip712 {
name: "USDC".into(),
version: "2".into(),
}),
}
}
fn iotex() -> eip155::Eip155TokenDeployment {
eip155::Eip155TokenDeployment {
chain_reference: eip155::Eip155ChainReference::new(4689),
address: alloy_primitives::address!("0xcdf79194c6c285077a58da47641d4dbe51f63542"),
decimals: 6,
eip712: Some(eip155::TokenDeploymentEip712 {
name: "Bridged USDC".into(),
version: "2".into(),
}),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_known_networks_by_name() {
let base = chain_id_by_network_name("base").unwrap();
assert_eq!(base.namespace, "eip155");
assert_eq!(base.reference, "8453");
let base_sepolia = chain_id_by_network_name("base-sepolia").unwrap();
assert_eq!(base_sepolia.namespace, "eip155");
assert_eq!(base_sepolia.reference, "84532");
let solana = chain_id_by_network_name("solana").unwrap();
assert_eq!(solana.namespace, "solana");
assert_eq!(solana.reference, "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp");
assert!(chain_id_by_network_name("unknown-network").is_none());
}
#[test]
fn test_known_networks_by_chain_id() {
let chain_id = ChainId::new("eip155", "8453");
let network_name = network_name_by_chain_id(&chain_id).unwrap();
assert_eq!(network_name, "base");
let solana_chain_id = ChainId::new("solana", "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp");
let network_name = network_name_by_chain_id(&solana_chain_id).unwrap();
assert_eq!(network_name, "solana");
let unknown_chain_id = ChainId::new("eip155", "999999");
assert!(network_name_by_chain_id(&unknown_chain_id).is_none());
}
#[test]
fn test_chain_id_from_network_name() {
let chain_id = chain_id_by_network_name("base").unwrap();
assert_eq!(chain_id.namespace, "eip155");
assert_eq!(chain_id.reference, "8453");
let solana_chain_id = chain_id_by_network_name("solana").unwrap();
assert_eq!(solana_chain_id.namespace, "solana");
assert_eq!(
solana_chain_id.reference,
"5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
);
assert!(chain_id_by_network_name("unknown").is_none());
}
#[test]
fn test_chain_id_as_network_name() {
let chain_id = ChainId::new("eip155", "8453");
assert_eq!(chain_id.as_network_name(), Some("base"));
let solana_chain_id = ChainId::new("solana", "5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp");
assert_eq!(solana_chain_id.as_network_name(), Some("solana"));
let unknown_chain_id = ChainId::new("eip155", "999999");
assert!(unknown_chain_id.as_network_name().is_none());
}
#[test]
fn test_network_info_chain_id() {
let chain_id = chain_id_by_network_name("polygon").unwrap();
assert_eq!(chain_id.namespace, "eip155");
assert_eq!(chain_id.reference, "137");
}
}