openzeppelin_monitor/utils/tests/builders/
network.rs1use crate::models::{
6 BlockChainType, BlockRecoveryConfig, Network, RpcUrl, SecretString, SecretValue,
7};
8
9pub struct NetworkBuilder {
11 name: String,
12 slug: String,
13 network_type: BlockChainType,
14 chain_id: Option<u64>,
15 network_passphrase: Option<String>,
16 store_blocks: Option<bool>,
17 rpc_urls: Vec<RpcUrl>,
18 block_time_ms: u64,
19 confirmation_blocks: u64,
20 cron_schedule: String,
21 max_past_blocks: Option<u64>,
22 recovery_config: Option<BlockRecoveryConfig>,
23}
24
25impl Default for NetworkBuilder {
26 fn default() -> Self {
27 Self {
28 name: "Test Network".to_string(),
29 slug: "test_network".to_string(),
30 network_type: BlockChainType::EVM,
31 chain_id: Some(1),
32 network_passphrase: None,
33 store_blocks: Some(true),
34 rpc_urls: vec![],
35 block_time_ms: 1000,
36 confirmation_blocks: 1,
37 cron_schedule: "0 */5 * * * *".to_string(),
38 max_past_blocks: Some(10),
39 recovery_config: None,
40 }
41 }
42}
43
44impl NetworkBuilder {
45 pub fn new() -> Self {
46 Self::default()
47 }
48
49 pub fn name(mut self, name: &str) -> Self {
50 self.name = name.to_string();
51 self
52 }
53
54 pub fn slug(mut self, slug: &str) -> Self {
55 self.slug = slug.to_string();
56 self
57 }
58
59 pub fn network_type(mut self, network_type: BlockChainType) -> Self {
60 self.network_type = network_type;
61 self
62 }
63
64 pub fn chain_id(mut self, chain_id: u64) -> Self {
65 self.chain_id = Some(chain_id);
66 self
67 }
68
69 pub fn network_passphrase(mut self, passphrase: &str) -> Self {
70 self.network_passphrase = Some(passphrase.to_string());
71 self
72 }
73
74 pub fn store_blocks(mut self, store: bool) -> Self {
75 self.store_blocks = Some(store);
76 self
77 }
78
79 pub fn rpc_url(mut self, url: &str) -> Self {
80 self.rpc_urls = vec![RpcUrl {
81 type_: "rpc".to_string(),
82 url: SecretValue::Plain(SecretString::new(url.to_string())),
83 weight: 100,
84 }];
85 self
86 }
87
88 pub fn rpc_urls(mut self, urls: Vec<&str>) -> Self {
89 self.rpc_urls = urls
90 .into_iter()
91 .map(|url| RpcUrl {
92 type_: "rpc".to_string(),
93 url: SecretValue::Plain(SecretString::new(url.to_string())),
94 weight: 100,
95 })
96 .collect();
97 self
98 }
99
100 pub fn websocket_rpc_urls(mut self, urls: Vec<&str>) -> Self {
101 self.rpc_urls = urls
102 .into_iter()
103 .map(|url| RpcUrl {
104 type_: "ws_rpc".to_string(),
105 url: SecretValue::Plain(SecretString::new(url.to_string())),
106 weight: 100,
107 })
108 .collect();
109 self
110 }
111
112 pub fn add_rpc_url(mut self, url: &str, type_: &str, weight: u32) -> Self {
113 self.rpc_urls.push(RpcUrl {
114 type_: type_.to_string(),
115 url: SecretValue::Plain(SecretString::new(url.to_string())),
116 weight,
117 });
118 self
119 }
120
121 pub fn add_secret_rpc_url(mut self, url: SecretValue, type_: &str, weight: u32) -> Self {
122 self.rpc_urls.push(RpcUrl {
123 type_: type_.to_string(),
124 url,
125 weight,
126 });
127 self
128 }
129
130 pub fn clear_rpc_urls(mut self) -> Self {
131 self.rpc_urls.clear();
132 self
133 }
134
135 pub fn block_time_ms(mut self, block_time: u64) -> Self {
136 self.block_time_ms = block_time;
137 self
138 }
139
140 pub fn confirmation_blocks(mut self, blocks: u64) -> Self {
141 self.confirmation_blocks = blocks;
142 self
143 }
144
145 pub fn cron_schedule(mut self, schedule: &str) -> Self {
146 self.cron_schedule = schedule.to_string();
147 self
148 }
149
150 pub fn max_past_blocks(mut self, blocks: u64) -> Self {
151 self.max_past_blocks = Some(blocks);
152 self
153 }
154
155 pub fn recovery_config(mut self, config: BlockRecoveryConfig) -> Self {
156 self.recovery_config = Some(config);
157 self
158 }
159
160 pub fn build(self) -> Network {
161 Network {
162 name: self.name,
163 slug: self.slug,
164 network_type: self.network_type,
165 chain_id: self.chain_id,
166 network_passphrase: self.network_passphrase,
167 store_blocks: self.store_blocks,
168 rpc_urls: self.rpc_urls,
169 block_time_ms: self.block_time_ms,
170 confirmation_blocks: self.confirmation_blocks,
171 cron_schedule: self.cron_schedule,
172 max_past_blocks: self.max_past_blocks,
173 recovery_config: self.recovery_config,
174 }
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use super::*;
181
182 #[test]
183 fn test_default_network() {
184 let network = NetworkBuilder::new().build();
185
186 assert_eq!(network.name, "Test Network");
187 assert_eq!(network.slug, "test_network");
188 assert_eq!(network.network_type, BlockChainType::EVM);
189 assert_eq!(network.chain_id, Some(1));
190 assert_eq!(network.network_passphrase, None);
191 assert_eq!(network.store_blocks, Some(true));
192 assert_eq!(network.block_time_ms, 1000);
193 assert_eq!(network.confirmation_blocks, 1);
194 assert_eq!(network.cron_schedule, "0 */5 * * * *");
195 assert_eq!(network.max_past_blocks, Some(10));
196 assert_eq!(network.rpc_urls.len(), 0);
197 }
198
199 #[test]
200 fn test_basic_builder_methods() {
201 let network = NetworkBuilder::new()
202 .name("Ethereum")
203 .slug("eth")
204 .network_type(BlockChainType::EVM)
205 .chain_id(1)
206 .store_blocks(true)
207 .block_time_ms(15000)
208 .confirmation_blocks(12)
209 .build();
210
211 assert_eq!(network.name, "Ethereum");
212 assert_eq!(network.slug, "eth");
213 assert_eq!(network.network_type, BlockChainType::EVM);
214 assert_eq!(network.chain_id, Some(1));
215 assert_eq!(network.store_blocks, Some(true));
216 assert_eq!(network.block_time_ms, 15000);
217 assert_eq!(network.confirmation_blocks, 12);
218 }
219
220 #[test]
221 fn test_rpc_url_methods() {
222 let network = NetworkBuilder::new()
223 .clear_rpc_urls()
224 .add_rpc_url("https://rpc1.example.com", "http", 50)
225 .add_rpc_url("https://rpc2.example.com", "ws", 50)
226 .build();
227
228 assert_eq!(network.rpc_urls.len(), 2);
229 assert_eq!(
230 network.rpc_urls[0].url.as_ref().to_string(),
231 "https://rpc1.example.com".to_string()
232 );
233 assert_eq!(network.rpc_urls[0].type_, "http");
234 assert_eq!(network.rpc_urls[0].weight, 50);
235 assert_eq!(
236 network.rpc_urls[1].url.as_ref().to_string(),
237 "https://rpc2.example.com".to_string()
238 );
239 assert_eq!(network.rpc_urls[1].type_, "ws");
240 assert_eq!(network.rpc_urls[1].weight, 50);
241 }
242
243 #[test]
244 fn test_secret_rpc_url() {
245 let network = NetworkBuilder::new()
246 .add_secret_rpc_url(
247 SecretValue::Plain(SecretString::new("https://rpc1.example.com".to_string())),
248 "rpc",
249 50,
250 )
251 .build();
252
253 assert_eq!(network.rpc_urls.len(), 1);
254 assert_eq!(
255 network.rpc_urls[0].url.as_ref().to_string(),
256 "https://rpc1.example.com".to_string()
257 );
258 assert_eq!(network.rpc_urls[0].type_, "rpc");
259 }
260
261 #[test]
262 fn test_rpc_urls_bulk_set() {
263 let network = NetworkBuilder::new()
264 .rpc_urls(vec!["https://rpc1.com", "https://rpc2.com"])
265 .build();
266
267 assert_eq!(network.rpc_urls.len(), 2);
268 assert_eq!(
269 network.rpc_urls[0].url.as_ref().to_string(),
270 "https://rpc1.com".to_string()
271 );
272 assert_eq!(
273 network.rpc_urls[1].url.as_ref().to_string(),
274 "https://rpc2.com".to_string()
275 );
276 assert!(network.rpc_urls.iter().all(|url| url.type_ == "rpc"));
278 assert!(network.rpc_urls.iter().all(|url| url.weight == 100));
279 }
280
281 #[test]
282 fn test_websocket_rpc_urls() {
283 let network = NetworkBuilder::new()
284 .websocket_rpc_urls(vec!["wss://ws1.example.com", "wss://ws2.example.com"])
285 .build();
286
287 assert_eq!(network.rpc_urls.len(), 2);
288 assert_eq!(
289 network.rpc_urls[0].url.as_ref().to_string(),
290 "wss://ws1.example.com".to_string()
291 );
292 assert_eq!(network.rpc_urls[0].type_, "ws_rpc");
293 assert_eq!(network.rpc_urls[1].type_, "ws_rpc");
294 }
295
296 #[test]
297 fn test_stellar_network() {
298 let network = NetworkBuilder::new()
299 .name("Stellar")
300 .slug("xlm")
301 .network_type(BlockChainType::Stellar)
302 .network_passphrase("Test SDF Network")
303 .build();
304
305 assert_eq!(network.network_type, BlockChainType::Stellar);
306 assert_eq!(
307 network.network_passphrase,
308 Some("Test SDF Network".to_string())
309 );
310 assert_eq!(network.chain_id, Some(1)); }
312}