nautilus_model/defi/
chain.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 Posei Systems Pty Ltd. All rights reserved.
3//  https://poseitrader.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16use std::{
17    fmt::{Display, Formatter},
18    sync::Arc,
19};
20
21use serde::{Deserialize, Serialize};
22use strum::{Display, EnumString};
23
24/// Represents different blockchain networks.
25#[derive(
26    Debug,
27    Clone,
28    Copy,
29    Hash,
30    PartialOrd,
31    PartialEq,
32    Ord,
33    Eq,
34    Display,
35    EnumString,
36    Serialize,
37    Deserialize,
38)]
39pub enum Blockchain {
40    Abstract,
41    Arbitrum,
42    ArbitrumNova,
43    ArbitrumSepolia,
44    Aurora,
45    Avalanche,
46    Base,
47    BaseSepolia,
48    Berachain,
49    BerachainBartio,
50    Blast,
51    BlastSepolia,
52    Boba,
53    Bsc,
54    BscTestnet,
55    Celo,
56    Chiliz,
57    CitreaTestnet,
58    Curtis,
59    Cyber,
60    Darwinia,
61    Ethereum,
62    Fantom,
63    Flare,
64    Fraxtal,
65    Fuji,
66    GaladrielDevnet,
67    Gnosis,
68    GnosisChiado,
69    GnosisTraces,
70    HarmonyShard0,
71    Holesky,
72    HoleskyTokenTest,
73    Hyperliquid,
74    HyperliquidTemp,
75    Ink,
76    InternalTestChain,
77    Kroma,
78    Linea,
79    Lisk,
80    Lukso,
81    LuksoTestnet,
82    Manta,
83    Mantle,
84    MegaethTestnet,
85    Merlin,
86    Metall2,
87    Metis,
88    MevCommit,
89    Mode,
90    MonadTestnet,
91    MonadTestnetBackup,
92    MoonbaseAlpha,
93    Moonbeam,
94    Morph,
95    MorphHolesky,
96    Opbnb,
97    Optimism,
98    OptimismSepolia,
99    PharosDevnet,
100    Polygon,
101    PolygonAmoy,
102    PolygonZkEvm,
103    Rootstock,
104    Saakuru,
105    Scroll,
106    Sepolia,
107    ShimmerEvm,
108    Soneium,
109    Sophon,
110    SophonTestnet,
111    Superseed,
112    Unichain,
113    UnichainSepolia,
114    Xdc,
115    XdcTestnet,
116    Zeta,
117    Zircuit,
118    ZKsync,
119    Zora,
120}
121
122/// Defines a blockchain with its unique identifiers and connection details for network interaction.
123#[derive(Debug, Clone)]
124pub struct Chain {
125    /// The blockchain network type.
126    pub name: Blockchain,
127    /// The unique identifier for this blockchain.
128    pub chain_id: u32,
129    /// URL endpoint for HyperSync connection.
130    pub hypersync_url: String,
131    /// URL endpoint for the default RPC connection.
132    pub rpc_url: Option<String>,
133}
134
135pub type SharedChain = Arc<Chain>;
136
137impl Chain {
138    pub fn new(name: Blockchain, chain_id: u32) -> Self {
139        Self {
140            chain_id,
141            name,
142            hypersync_url: format!("https://{}.hypersync.xyz", chain_id),
143            rpc_url: None,
144        }
145    }
146
147    /// Sets the RPC url endpoint.
148    pub fn set_rpc_url(&mut self, rpc: String) {
149        self.rpc_url = Some(rpc);
150    }
151
152    /// Returns a reference to the `Chain` corresponding to the given `chain_id`, or `None` if it is not found.
153    pub fn from_chain_id(chain_id: u32) -> Option<&'static Chain> {
154        match chain_id {
155            2741 => Some(&chains::ABSTRACT),
156            42161 => Some(&chains::ARBITRUM),
157            42170 => Some(&chains::ARBITRUM_NOVA),
158            421614 => Some(&chains::ARBITRUM_SEPOLIA),
159            1313161554 => Some(&chains::AURORA),
160            43114 => Some(&chains::AVALANCHE),
161            8453 => Some(&chains::BASE),
162            84532 => Some(&chains::BASE_SEPOLIA),
163            80094 => Some(&chains::BERACHAIN),
164            80085 => Some(&chains::BERACHAIN_BARTIO),
165            81457 => Some(&chains::BLAST),
166            168587773 => Some(&chains::BLAST_SEPOLIA),
167            288 => Some(&chains::BOBA),
168            56 => Some(&chains::BSC),
169            97 => Some(&chains::BSC_TESTNET),
170            42220 => Some(&chains::CELO),
171            8888 => Some(&chains::CHILIZ),
172            3333 => Some(&chains::CITREA_TESTNET),
173            33111 => Some(&chains::CURTIS),
174            7560 => Some(&chains::CYBER),
175            46 => Some(&chains::DARWINIA),
176            1 => Some(&chains::ETHEREUM),
177            250 => Some(&chains::FANTOM),
178            14 => Some(&chains::FLARE),
179            252 => Some(&chains::FRAXTAL),
180            43113 => Some(&chains::FUJI),
181            696969 => Some(&chains::GALADRIEL_DEVNET),
182            100 => Some(&chains::GNOSIS),
183            10200 => Some(&chains::GNOSIS_CHIADO),
184            10300 => Some(&chains::GNOSIS_TRACES),
185            1666600000 => Some(&chains::HARMONY_SHARD_0),
186            17000 => Some(&chains::HOLESKY),
187            17001 => Some(&chains::HOLESKY_TOKEN_TEST),
188            7979 => Some(&chains::HYPERLIQUID),
189            7978 => Some(&chains::HYPERLIQUID_TEMP),
190            222 => Some(&chains::INK),
191            13337 => Some(&chains::INTERNAL_TEST_CHAIN),
192            255 => Some(&chains::KROMA),
193            59144 => Some(&chains::LINEA),
194            501 => Some(&chains::LISK),
195            42 => Some(&chains::LUKSO),
196            4201 => Some(&chains::LUKSO_TESTNET),
197            169 => Some(&chains::MANTA),
198            5000 => Some(&chains::MANTLE),
199            777 => Some(&chains::MEGAETH_TESTNET),
200            4200 => Some(&chains::MERLIN),
201            90 => Some(&chains::METALL2),
202            1088 => Some(&chains::METIS),
203            11 => Some(&chains::MEV_COMMIT),
204            34443 => Some(&chains::MODE),
205            2323 => Some(&chains::MONAD_TESTNET),
206            2358 => Some(&chains::MONAD_TESTNET_BACKUP),
207            1287 => Some(&chains::MOONBASE_ALPHA),
208            1284 => Some(&chains::MOONBEAM),
209            2710 => Some(&chains::MORPH),
210            2710111 => Some(&chains::MORPH_HOLESKY),
211            204 => Some(&chains::OPBNB),
212            10 => Some(&chains::OPTIMISM),
213            11155420 => Some(&chains::OPTIMISM_SEPOLIA),
214            1337 => Some(&chains::PHAROS_DEVNET),
215            137 => Some(&chains::POLYGON),
216            80002 => Some(&chains::POLYGON_AMOY),
217            1101 => Some(&chains::POLYGON_ZKEVM),
218            30 => Some(&chains::ROOTSTOCK),
219            1204 => Some(&chains::SAAKURU),
220            534352 => Some(&chains::SCROLL),
221            11155111 => Some(&chains::SEPOLIA),
222            148 => Some(&chains::SHIMMER_EVM),
223            109 => Some(&chains::SONEIUM),
224            138 => Some(&chains::SOPHON),
225            139 => Some(&chains::SOPHON_TESTNET),
226            10001 => Some(&chains::SUPERSEED),
227            9999 => Some(&chains::UNICHAIN),
228            9997 => Some(&chains::UNICHAIN_SEPOLIA),
229            50 => Some(&chains::XDC),
230            51 => Some(&chains::XDC_TESTNET),
231            7000 => Some(&chains::ZETA),
232            78600 => Some(&chains::ZIRCUIT),
233            324 => Some(&chains::ZKSYNC),
234            7777777 => Some(&chains::ZORA),
235            _ => None,
236        }
237    }
238}
239
240impl Display for Chain {
241    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
242        write!(f, "Chain(name={}, id={})", self.name, self.chain_id)
243    }
244}
245
246// Define a module to contain all the chain definitions.
247pub mod chains {
248    use std::sync::LazyLock;
249
250    use crate::defi::chain::{Blockchain, Chain};
251
252    pub static ABSTRACT: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Abstract, 2741));
253    pub static ARBITRUM: LazyLock<Chain> =
254        LazyLock::new(|| Chain::new(Blockchain::Arbitrum, 42161));
255    pub static ARBITRUM_NOVA: LazyLock<Chain> =
256        LazyLock::new(|| Chain::new(Blockchain::ArbitrumNova, 42170));
257    pub static ARBITRUM_SEPOLIA: LazyLock<Chain> =
258        LazyLock::new(|| Chain::new(Blockchain::ArbitrumSepolia, 421614));
259    pub static AURORA: LazyLock<Chain> =
260        LazyLock::new(|| Chain::new(Blockchain::Aurora, 1313161554));
261    pub static AVALANCHE: LazyLock<Chain> =
262        LazyLock::new(|| Chain::new(Blockchain::Avalanche, 43114));
263    pub static BASE: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Base, 8453));
264    pub static BASE_SEPOLIA: LazyLock<Chain> =
265        LazyLock::new(|| Chain::new(Blockchain::BaseSepolia, 84532));
266    pub static BERACHAIN: LazyLock<Chain> =
267        LazyLock::new(|| Chain::new(Blockchain::Berachain, 80094));
268    pub static BERACHAIN_BARTIO: LazyLock<Chain> =
269        LazyLock::new(|| Chain::new(Blockchain::BerachainBartio, 80085));
270    pub static BLAST: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Blast, 81457));
271    pub static BLAST_SEPOLIA: LazyLock<Chain> =
272        LazyLock::new(|| Chain::new(Blockchain::BlastSepolia, 168587773));
273    pub static BOBA: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Boba, 288));
274    pub static BSC: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Bsc, 56));
275    pub static BSC_TESTNET: LazyLock<Chain> =
276        LazyLock::new(|| Chain::new(Blockchain::BscTestnet, 97));
277    pub static CELO: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Celo, 42220));
278    pub static CHILIZ: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Chiliz, 8888));
279    pub static CITREA_TESTNET: LazyLock<Chain> =
280        LazyLock::new(|| Chain::new(Blockchain::CitreaTestnet, 3333));
281    pub static CURTIS: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Curtis, 33111));
282    pub static CYBER: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Cyber, 7560));
283    pub static DARWINIA: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Darwinia, 46));
284    pub static ETHEREUM: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Ethereum, 1));
285    pub static FANTOM: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Fantom, 250));
286    pub static FLARE: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Flare, 14));
287    pub static FRAXTAL: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Fraxtal, 252));
288    pub static FUJI: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Fuji, 43113));
289    pub static GALADRIEL_DEVNET: LazyLock<Chain> =
290        LazyLock::new(|| Chain::new(Blockchain::GaladrielDevnet, 696969));
291    pub static GNOSIS: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Gnosis, 100));
292    pub static GNOSIS_CHIADO: LazyLock<Chain> =
293        LazyLock::new(|| Chain::new(Blockchain::GnosisChiado, 10200));
294    pub static GNOSIS_TRACES: LazyLock<Chain> =
295        LazyLock::new(|| Chain::new(Blockchain::GnosisTraces, 100));
296    pub static HARMONY_SHARD_0: LazyLock<Chain> =
297        LazyLock::new(|| Chain::new(Blockchain::HarmonyShard0, 1666600000));
298    pub static HOLESKY: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Holesky, 17000));
299    pub static HOLESKY_TOKEN_TEST: LazyLock<Chain> =
300        LazyLock::new(|| Chain::new(Blockchain::HoleskyTokenTest, 17000));
301    pub static HYPERLIQUID: LazyLock<Chain> =
302        LazyLock::new(|| Chain::new(Blockchain::Hyperliquid, 645749));
303    pub static HYPERLIQUID_TEMP: LazyLock<Chain> =
304        LazyLock::new(|| Chain::new(Blockchain::HyperliquidTemp, 645748));
305    pub static INK: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Ink, 57073));
306    pub static INTERNAL_TEST_CHAIN: LazyLock<Chain> =
307        LazyLock::new(|| Chain::new(Blockchain::InternalTestChain, 9876));
308    pub static KROMA: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Kroma, 255));
309    pub static LINEA: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Linea, 59144));
310    pub static LISK: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Lisk, 4000));
311    pub static LUKSO: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Lukso, 42));
312    pub static LUKSO_TESTNET: LazyLock<Chain> =
313        LazyLock::new(|| Chain::new(Blockchain::LuksoTestnet, 4201));
314    pub static MANTA: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Manta, 169));
315    pub static MANTLE: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Mantle, 5000));
316    pub static MEGAETH_TESTNET: LazyLock<Chain> =
317        LazyLock::new(|| Chain::new(Blockchain::MegaethTestnet, 2023));
318    pub static MERLIN: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Merlin, 4200));
319    pub static METALL2: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Metall2, 33210));
320    pub static METIS: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Metis, 1088));
321    pub static MEV_COMMIT: LazyLock<Chain> =
322        LazyLock::new(|| Chain::new(Blockchain::MevCommit, 5432101));
323    pub static MODE: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Mode, 34443));
324    pub static MONAD_TESTNET: LazyLock<Chain> =
325        LazyLock::new(|| Chain::new(Blockchain::MonadTestnet, 131313));
326    pub static MONAD_TESTNET_BACKUP: LazyLock<Chain> =
327        LazyLock::new(|| Chain::new(Blockchain::MonadTestnetBackup, 131314));
328    pub static MOONBASE_ALPHA: LazyLock<Chain> =
329        LazyLock::new(|| Chain::new(Blockchain::MoonbaseAlpha, 1287));
330    pub static MOONBEAM: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Moonbeam, 1284));
331    pub static MORPH: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Morph, 2221));
332    pub static MORPH_HOLESKY: LazyLock<Chain> =
333        LazyLock::new(|| Chain::new(Blockchain::MorphHolesky, 2522));
334    pub static OPBNB: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Opbnb, 204));
335    pub static OPTIMISM: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Optimism, 10));
336    pub static OPTIMISM_SEPOLIA: LazyLock<Chain> =
337        LazyLock::new(|| Chain::new(Blockchain::OptimismSepolia, 11155420));
338    pub static PHAROS_DEVNET: LazyLock<Chain> =
339        LazyLock::new(|| Chain::new(Blockchain::PharosDevnet, 13371));
340    pub static POLYGON: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Polygon, 137));
341    pub static POLYGON_AMOY: LazyLock<Chain> =
342        LazyLock::new(|| Chain::new(Blockchain::PolygonAmoy, 80002));
343    pub static POLYGON_ZKEVM: LazyLock<Chain> =
344        LazyLock::new(|| Chain::new(Blockchain::PolygonZkEvm, 1101));
345    pub static ROOTSTOCK: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Rootstock, 30));
346    pub static SAAKURU: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Saakuru, 1442));
347    pub static SCROLL: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Scroll, 534352));
348    pub static SEPOLIA: LazyLock<Chain> =
349        LazyLock::new(|| Chain::new(Blockchain::Sepolia, 11155111));
350    pub static SHIMMER_EVM: LazyLock<Chain> =
351        LazyLock::new(|| Chain::new(Blockchain::ShimmerEvm, 148));
352    pub static SONEIUM: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Soneium, 2241));
353    pub static SOPHON: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Sophon, 2242));
354    pub static SOPHON_TESTNET: LazyLock<Chain> =
355        LazyLock::new(|| Chain::new(Blockchain::SophonTestnet, 2323));
356    pub static SUPERSEED: LazyLock<Chain> =
357        LazyLock::new(|| Chain::new(Blockchain::Superseed, 534351));
358    pub static UNICHAIN: LazyLock<Chain> =
359        LazyLock::new(|| Chain::new(Blockchain::Unichain, 18231));
360    pub static UNICHAIN_SEPOLIA: LazyLock<Chain> =
361        LazyLock::new(|| Chain::new(Blockchain::UnichainSepolia, 28231));
362    pub static XDC: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Xdc, 50));
363    pub static XDC_TESTNET: LazyLock<Chain> =
364        LazyLock::new(|| Chain::new(Blockchain::XdcTestnet, 51));
365    pub static ZETA: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Zeta, 7000));
366    pub static ZIRCUIT: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Zircuit, 48899));
367    pub static ZKSYNC: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::ZKsync, 324));
368    pub static ZORA: LazyLock<Chain> = LazyLock::new(|| Chain::new(Blockchain::Zora, 7777777));
369}
370
371#[cfg(test)]
372mod tests {
373    use rstest::rstest;
374
375    use super::*;
376
377    #[rstest]
378    fn test_ethereum_chain() {
379        let eth_chain = chains::ETHEREUM.clone();
380        assert_eq!(eth_chain.to_string(), "Chain(name=Ethereum, id=1)");
381        assert_eq!(eth_chain.name, Blockchain::Ethereum);
382        assert_eq!(eth_chain.chain_id, 1);
383        assert_eq!(eth_chain.hypersync_url.as_str(), "https://1.hypersync.xyz")
384    }
385
386    #[rstest]
387    fn test_arbitrum_chain() {
388        let arbitrum_chain = chains::ARBITRUM.clone();
389        assert_eq!(arbitrum_chain.to_string(), "Chain(name=Arbitrum, id=42161)");
390        assert_eq!(arbitrum_chain.name, Blockchain::Arbitrum);
391        assert_eq!(arbitrum_chain.chain_id, 42161);
392        assert_eq!(
393            arbitrum_chain.hypersync_url.as_str(),
394            "https://42161.hypersync.xyz"
395        );
396    }
397}