Skip to main content

near_kit/types/
network.rs

1//! Chain identification for NEAR Protocol.
2
3use std::fmt;
4
5/// Identifies the NEAR chain the client is connected to.
6///
7/// This is a string-based newtype that replaces the former `Network` enum,
8/// allowing any chain identifier (not just the hardcoded variants).
9///
10/// Use the named constructors for well-known chains, or [`ChainId::new`]
11/// for custom ones.
12///
13/// # Examples
14///
15/// ```
16/// use near_kit::ChainId;
17///
18/// let mainnet = ChainId::mainnet();
19/// assert!(mainnet.is_mainnet());
20/// assert_eq!(mainnet.as_str(), "mainnet");
21///
22/// let custom = ChainId::new("localnet");
23/// assert_eq!(custom.as_str(), "localnet");
24/// ```
25#[derive(Clone, Debug, PartialEq, Eq, Hash)]
26pub struct ChainId(String);
27
28impl ChainId {
29    /// Create a chain ID from any string.
30    pub fn new(id: impl Into<String>) -> Self {
31        Self(id.into())
32    }
33
34    /// NEAR mainnet.
35    pub fn mainnet() -> Self {
36        Self("mainnet".to_string())
37    }
38
39    /// NEAR testnet.
40    pub fn testnet() -> Self {
41        Self("testnet".to_string())
42    }
43
44    /// Returns true if this is mainnet.
45    pub fn is_mainnet(&self) -> bool {
46        self.0 == "mainnet"
47    }
48
49    /// Returns true if this is testnet.
50    pub fn is_testnet(&self) -> bool {
51        self.0 == "testnet"
52    }
53
54    /// Returns the chain identifier as a string slice.
55    pub fn as_str(&self) -> &str {
56        &self.0
57    }
58}
59
60impl Default for ChainId {
61    fn default() -> Self {
62        Self::mainnet()
63    }
64}
65
66impl AsRef<str> for ChainId {
67    fn as_ref(&self) -> &str {
68        &self.0
69    }
70}
71
72impl fmt::Display for ChainId {
73    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74        f.write_str(&self.0)
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81
82    #[test]
83    fn test_chain_id_display() {
84        assert_eq!(ChainId::mainnet().to_string(), "mainnet");
85        assert_eq!(ChainId::testnet().to_string(), "testnet");
86        assert_eq!(ChainId::new("custom").to_string(), "custom");
87    }
88
89    #[test]
90    fn test_chain_id_predicates() {
91        assert!(ChainId::mainnet().is_mainnet());
92        assert!(!ChainId::mainnet().is_testnet());
93
94        assert!(ChainId::testnet().is_testnet());
95        assert!(!ChainId::testnet().is_mainnet());
96    }
97
98    #[test]
99    fn test_default_is_mainnet() {
100        assert_eq!(ChainId::default(), ChainId::mainnet());
101    }
102
103    #[test]
104    fn test_as_str() {
105        assert_eq!(ChainId::mainnet().as_str(), "mainnet");
106        assert_eq!(ChainId::new("localnet").as_str(), "localnet");
107    }
108
109    #[test]
110    fn test_as_ref_str() {
111        let chain_id = ChainId::mainnet();
112        let s: &str = chain_id.as_ref();
113        assert_eq!(s, "mainnet");
114    }
115
116    #[test]
117    fn test_custom_chain_id() {
118        let chain_id = ChainId::new("my-custom-network");
119        assert_eq!(chain_id.as_str(), "my-custom-network");
120        assert!(!chain_id.is_mainnet());
121        assert!(!chain_id.is_testnet());
122    }
123}