odos_sdk/
router_type.rs

1//! Router type definitions for Odos protocol
2//!
3//! This module provides enums and types to represent the different router types
4//! available across Odos-supported chains.
5
6use std::fmt;
7
8/// Represents the different types of Odos routers
9///
10/// Different chains support different combinations of these router types.
11/// Use the `OdosChain` trait methods to check router availability per chain.
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13pub enum RouterType {
14    /// Limit Order V2 router for limit order functionality
15    ///
16    /// Available on all supported chains
17    LimitOrder,
18
19    /// V2 router for swap functionality
20    ///
21    /// Available on all supported chains
22    V2,
23
24    /// V3 router for enhanced swap functionality
25    ///
26    /// Available on all supported chains (unified address)
27    V3,
28}
29
30impl RouterType {
31    /// Returns all possible router types
32    pub const fn all() -> [RouterType; 3] {
33        [RouterType::LimitOrder, RouterType::V2, RouterType::V3]
34    }
35
36    /// Returns the router type as a string identifier
37    pub const fn as_str(&self) -> &'static str {
38        match self {
39            RouterType::LimitOrder => "LO",
40            RouterType::V2 => "V2",
41            RouterType::V3 => "V3",
42        }
43    }
44}
45
46impl fmt::Display for RouterType {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        write!(f, "{}", self.as_str())
49    }
50}
51
52/// Represents which routers are available on a specific chain
53///
54/// This provides a type-safe way to query router availability without
55/// needing to call multiple trait methods.
56#[derive(Debug, Clone, Copy, PartialEq, Eq)]
57pub struct RouterAvailability {
58    /// Whether the Limit Order V2 router is available
59    pub limit_order: bool,
60    /// Whether the V2 router is available
61    pub v2: bool,
62    /// Whether the V3 router is available
63    pub v3: bool,
64}
65
66impl RouterAvailability {
67    /// Creates a new `RouterAvailability` with all routers available
68    pub const fn all() -> Self {
69        Self {
70            limit_order: true,
71            v2: true,
72            v3: true,
73        }
74    }
75
76    /// Creates a new `RouterAvailability` with no routers available
77    pub const fn none() -> Self {
78        Self {
79            limit_order: false,
80            v2: false,
81            v3: false,
82        }
83    }
84
85    /// Creates availability for LO + V3 only
86    pub const fn lo_v3_only() -> Self {
87        Self {
88            limit_order: true,
89            v2: false,
90            v3: true,
91        }
92    }
93
94    /// Creates availability for V2 + V3 only (most chains)
95    pub const fn v2_v3_only() -> Self {
96        Self {
97            limit_order: false,
98            v2: true,
99            v3: true,
100        }
101    }
102
103    /// Checks if the specified router type is available
104    pub const fn has(&self, router_type: RouterType) -> bool {
105        match router_type {
106            RouterType::LimitOrder => self.limit_order,
107            RouterType::V2 => self.v2,
108            RouterType::V3 => self.v3,
109        }
110    }
111
112    /// Returns all available router types
113    pub fn available_routers(&self) -> Vec<RouterType> {
114        let mut routers = Vec::new();
115        if self.limit_order {
116            routers.push(RouterType::LimitOrder);
117        }
118        if self.v2 {
119            routers.push(RouterType::V2);
120        }
121        if self.v3 {
122            routers.push(RouterType::V3);
123        }
124        routers
125    }
126
127    /// Returns the count of available routers
128    pub const fn count(&self) -> usize {
129        let mut count = 0;
130        if self.limit_order {
131            count += 1;
132        }
133        if self.v2 {
134            count += 1;
135        }
136        if self.v3 {
137            count += 1;
138        }
139        count
140    }
141
142    /// Checks if any router is available
143    pub const fn has_any(&self) -> bool {
144        self.limit_order || self.v2 || self.v3
145    }
146}
147
148impl fmt::Display for RouterAvailability {
149    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150        let routers = self.available_routers();
151        if routers.is_empty() {
152            write!(f, "No routers available")
153        } else {
154            write!(
155                f,
156                "{}",
157                routers
158                    .iter()
159                    .map(|r| r.as_str())
160                    .collect::<Vec<_>>()
161                    .join(", ")
162            )
163        }
164    }
165}
166
167#[cfg(test)]
168mod tests {
169    use super::*;
170
171    #[test]
172    fn test_router_type_all() {
173        let all = RouterType::all();
174        assert_eq!(all.len(), 3);
175        assert!(all.contains(&RouterType::LimitOrder));
176        assert!(all.contains(&RouterType::V2));
177        assert!(all.contains(&RouterType::V3));
178    }
179
180    #[test]
181    fn test_router_type_display() {
182        assert_eq!(RouterType::LimitOrder.to_string(), "LO");
183        assert_eq!(RouterType::V2.to_string(), "V2");
184        assert_eq!(RouterType::V3.to_string(), "V3");
185    }
186
187    #[test]
188    fn test_router_availability_all() {
189        let avail = RouterAvailability::all();
190        assert!(avail.limit_order);
191        assert!(avail.v2);
192        assert!(avail.v3);
193        assert_eq!(avail.count(), 3);
194    }
195
196    #[test]
197    fn test_router_availability_none() {
198        let avail = RouterAvailability::none();
199        assert!(!avail.limit_order);
200        assert!(!avail.v2);
201        assert!(!avail.v3);
202        assert_eq!(avail.count(), 0);
203        assert!(!avail.has_any());
204    }
205
206    #[test]
207    fn test_router_availability_lo_v3_only() {
208        let avail = RouterAvailability::lo_v3_only();
209        assert!(avail.limit_order);
210        assert!(!avail.v2);
211        assert!(avail.v3);
212        assert_eq!(avail.count(), 2);
213        assert!(avail.has(RouterType::LimitOrder));
214        assert!(!avail.has(RouterType::V2));
215        assert!(avail.has(RouterType::V3));
216    }
217
218    #[test]
219    fn test_router_availability_v2_v3_only() {
220        let avail = RouterAvailability::v2_v3_only();
221        assert!(!avail.limit_order);
222        assert!(avail.v2);
223        assert!(avail.v3);
224        assert_eq!(avail.count(), 2);
225    }
226
227    #[test]
228    fn test_available_routers() {
229        let avail = RouterAvailability::all();
230        let routers = avail.available_routers();
231        assert_eq!(routers.len(), 3);
232
233        let avail = RouterAvailability::lo_v3_only();
234        let routers = avail.available_routers();
235        assert_eq!(routers.len(), 2);
236        assert!(routers.contains(&RouterType::LimitOrder));
237        assert!(routers.contains(&RouterType::V3));
238    }
239
240    #[test]
241    fn test_display() {
242        let avail = RouterAvailability::all();
243        assert_eq!(avail.to_string(), "LO, V2, V3");
244
245        let avail = RouterAvailability::lo_v3_only();
246        assert_eq!(avail.to_string(), "LO, V3");
247
248        let avail = RouterAvailability::none();
249        assert_eq!(avail.to_string(), "No routers available");
250    }
251}