1use crate::models::{
2 Relayer, RelayerError, RelayerEvmPolicy, RelayerSolanaPolicy, RelayerStellarPolicy,
3};
4use serde::{Deserialize, Serialize};
5
6use super::{RelayerNetworkPolicy, RelayerNetworkType, RpcConfig};
7
8pub type NetworkType = RelayerNetworkType;
10
11pub struct RelayerRepoUpdater {
14 original: RelayerRepoModel,
15}
16
17impl RelayerRepoUpdater {
18 pub fn from_existing(existing: RelayerRepoModel) -> Self {
20 Self { original: existing }
21 }
22
23 pub fn apply_domain_update(self, domain: Relayer) -> RelayerRepoModel {
29 let mut updated = RelayerRepoModel::from(domain);
30 updated.address = self.original.address;
32 updated.system_disabled = self.original.system_disabled;
33 updated
34 }
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct RelayerRepoModel {
39 pub id: String,
40 pub name: String,
41 pub network: String,
42 pub paused: bool,
43 pub network_type: NetworkType,
44 pub signer_id: String,
45 pub policies: RelayerNetworkPolicy,
46 pub address: String,
47 pub notification_id: Option<String>,
48 pub system_disabled: bool,
49 pub custom_rpc_urls: Option<Vec<RpcConfig>>,
50}
51
52impl RelayerRepoModel {
53 pub fn validate_active_state(&self) -> Result<(), RelayerError> {
54 if self.paused {
55 return Err(RelayerError::RelayerPaused);
56 }
57
58 if self.system_disabled {
59 return Err(RelayerError::RelayerDisabled);
60 }
61
62 Ok(())
63 }
64}
65
66impl Default for RelayerRepoModel {
67 fn default() -> Self {
68 Self {
69 id: "".to_string(),
70 name: "".to_string(),
71 network: "".to_string(),
72 paused: false,
73 network_type: NetworkType::Evm,
74 signer_id: "".to_string(),
75 policies: RelayerNetworkPolicy::Evm(RelayerEvmPolicy::default()),
76 address: "0x".to_string(),
77 notification_id: None,
78 system_disabled: false,
79 custom_rpc_urls: None,
80 }
81 }
82}
83
84impl From<RelayerRepoModel> for Relayer {
85 fn from(repo_model: RelayerRepoModel) -> Self {
86 Self {
87 id: repo_model.id,
88 name: repo_model.name,
89 network: repo_model.network,
90 paused: repo_model.paused,
91 network_type: repo_model.network_type,
92 policies: Some(repo_model.policies),
93 signer_id: repo_model.signer_id,
94 notification_id: repo_model.notification_id,
95 custom_rpc_urls: repo_model.custom_rpc_urls,
96 }
97 }
98}
99
100impl From<Relayer> for RelayerRepoModel {
101 fn from(relayer: Relayer) -> Self {
102 Self {
103 id: relayer.id,
104 name: relayer.name,
105 network: relayer.network,
106 paused: relayer.paused,
107 network_type: relayer.network_type,
108 signer_id: relayer.signer_id,
109 policies: relayer.policies.unwrap_or_else(|| {
110 match relayer.network_type {
112 RelayerNetworkType::Evm => {
113 RelayerNetworkPolicy::Evm(RelayerEvmPolicy::default())
114 }
115 RelayerNetworkType::Solana => {
116 RelayerNetworkPolicy::Solana(RelayerSolanaPolicy::default())
117 }
118 RelayerNetworkType::Stellar => {
119 RelayerNetworkPolicy::Stellar(RelayerStellarPolicy::default())
120 }
121 }
122 }),
123 address: "".to_string(), notification_id: relayer.notification_id,
125 system_disabled: false,
126 custom_rpc_urls: relayer.custom_rpc_urls,
127 }
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use crate::models::{
134 RelayerEvmPolicy, RelayerSolanaPolicy, RelayerStellarPolicy, SolanaAllowedTokensPolicy,
135 SolanaFeePaymentStrategy,
136 };
137
138 use super::*;
139
140 fn create_test_relayer(paused: bool, system_disabled: bool) -> RelayerRepoModel {
141 RelayerRepoModel {
142 id: "test_relayer".to_string(),
143 name: "Test Relayer".to_string(),
144 paused,
145 system_disabled,
146 network: "test_network".to_string(),
147 network_type: NetworkType::Evm,
148 signer_id: "test_signer".to_string(),
149 policies: RelayerNetworkPolicy::Evm(RelayerEvmPolicy::default()),
150 address: "0xtest".to_string(),
151 notification_id: None,
152 custom_rpc_urls: None,
153 }
154 }
155
156 fn create_test_relayer_solana(paused: bool, system_disabled: bool) -> RelayerRepoModel {
157 RelayerRepoModel {
158 id: "test_solana_relayer".to_string(),
159 name: "Test Solana Relayer".to_string(),
160 paused,
161 system_disabled,
162 network: "mainnet".to_string(),
163 network_type: NetworkType::Solana,
164 signer_id: "test_signer".to_string(),
165 policies: RelayerNetworkPolicy::Solana(RelayerSolanaPolicy {
166 fee_payment_strategy: Some(SolanaFeePaymentStrategy::Relayer),
167 min_balance: Some(1000000),
168 max_signatures: Some(5),
169 allowed_tokens: None,
170 allowed_programs: None,
171 allowed_accounts: None,
172 disallowed_accounts: None,
173 max_tx_data_size: None,
174 max_allowed_fee_lamports: None,
175 swap_config: None,
176 fee_margin_percentage: None,
177 }),
178 address: "SolanaAddress123".to_string(),
179 notification_id: None,
180 custom_rpc_urls: None,
181 }
182 }
183
184 fn create_test_relayer_stellar(paused: bool, system_disabled: bool) -> RelayerRepoModel {
185 RelayerRepoModel {
186 id: "test_stellar_relayer".to_string(),
187 name: "Test Stellar Relayer".to_string(),
188 paused,
189 system_disabled,
190 network: "mainnet".to_string(),
191 network_type: NetworkType::Stellar,
192 signer_id: "test_signer".to_string(),
193 policies: RelayerNetworkPolicy::Stellar(RelayerStellarPolicy {
194 min_balance: Some(20000000),
195 max_fee: Some(100000),
196 timeout_seconds: Some(30),
197 }),
198 address: "GXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX".to_string(),
199 notification_id: None,
200 custom_rpc_urls: None,
201 }
202 }
203
204 #[test]
205 fn test_validate_active_state_success() {
206 let relayer = create_test_relayer(false, false);
207 assert!(relayer.validate_active_state().is_ok());
208 }
209
210 #[test]
211 fn test_validate_active_state_success_solana() {
212 let relayer = create_test_relayer_solana(false, false);
213 assert!(relayer.validate_active_state().is_ok());
214 }
215
216 #[test]
217 fn test_validate_active_state_success_stellar() {
218 let relayer = create_test_relayer_stellar(false, false);
219 assert!(relayer.validate_active_state().is_ok());
220 }
221
222 #[test]
223 fn test_validate_active_state_paused() {
224 let relayer = create_test_relayer(true, false);
225 let result = relayer.validate_active_state();
226 assert!(result.is_err());
227 assert!(matches!(result.unwrap_err(), RelayerError::RelayerPaused));
228 }
229
230 #[test]
231 fn test_validate_active_state_paused_solana() {
232 let relayer = create_test_relayer_solana(true, false);
233 let result = relayer.validate_active_state();
234 assert!(result.is_err());
235 assert!(matches!(result.unwrap_err(), RelayerError::RelayerPaused));
236 }
237
238 #[test]
239 fn test_validate_active_state_paused_stellar() {
240 let relayer = create_test_relayer_stellar(true, false);
241 let result = relayer.validate_active_state();
242 assert!(result.is_err());
243 assert!(matches!(result.unwrap_err(), RelayerError::RelayerPaused));
244 }
245
246 #[test]
247 fn test_validate_active_state_disabled() {
248 let relayer = create_test_relayer(false, true);
249 let result = relayer.validate_active_state();
250 assert!(result.is_err());
251 assert!(matches!(result.unwrap_err(), RelayerError::RelayerDisabled));
252 }
253
254 #[test]
255 fn test_validate_active_state_disabled_solana() {
256 let relayer = create_test_relayer_solana(false, true);
257 let result = relayer.validate_active_state();
258 assert!(result.is_err());
259 assert!(matches!(result.unwrap_err(), RelayerError::RelayerDisabled));
260 }
261
262 #[test]
263 fn test_validate_active_state_disabled_stellar() {
264 let relayer = create_test_relayer_stellar(false, true);
265 let result = relayer.validate_active_state();
266 assert!(result.is_err());
267 assert!(matches!(result.unwrap_err(), RelayerError::RelayerDisabled));
268 }
269
270 #[test]
271 fn test_validate_active_state_both_paused_and_disabled() {
272 let relayer = create_test_relayer(true, true);
274 let result = relayer.validate_active_state();
275 assert!(result.is_err());
276 assert!(matches!(result.unwrap_err(), RelayerError::RelayerPaused));
277 }
278
279 #[test]
280 fn test_conversion_from_repo_model_to_domain_evm() {
281 let repo_model = create_test_relayer(false, false);
282 let domain_relayer = Relayer::from(repo_model.clone());
283
284 assert_eq!(domain_relayer.id, repo_model.id);
285 assert_eq!(domain_relayer.name, repo_model.name);
286 assert_eq!(domain_relayer.network, repo_model.network);
287 assert_eq!(domain_relayer.paused, repo_model.paused);
288 assert_eq!(domain_relayer.network_type, repo_model.network_type);
289 assert_eq!(domain_relayer.signer_id, repo_model.signer_id);
290 assert_eq!(domain_relayer.notification_id, repo_model.notification_id);
291 assert_eq!(domain_relayer.custom_rpc_urls, repo_model.custom_rpc_urls);
292
293 assert!(domain_relayer.policies.is_some());
295 if let Some(RelayerNetworkPolicy::Evm(_)) = domain_relayer.policies {
296 } else {
298 panic!("Expected EVM policy");
299 }
300 }
301
302 #[test]
303 fn test_conversion_from_repo_model_to_domain_solana() {
304 let repo_model = create_test_relayer_solana(false, false);
305 let domain_relayer = Relayer::from(repo_model.clone());
306
307 assert_eq!(domain_relayer.id, repo_model.id);
308 assert_eq!(domain_relayer.network_type, RelayerNetworkType::Solana);
309
310 assert!(domain_relayer.policies.is_some());
312 if let Some(RelayerNetworkPolicy::Solana(solana_policy)) = domain_relayer.policies {
313 assert_eq!(solana_policy.min_balance, Some(1000000));
314 assert_eq!(solana_policy.max_signatures, Some(5));
315 assert_eq!(
316 solana_policy.fee_payment_strategy,
317 Some(SolanaFeePaymentStrategy::Relayer)
318 );
319 } else {
320 panic!("Expected Solana policy");
321 }
322 }
323
324 #[test]
325 fn test_conversion_from_repo_model_to_domain_stellar() {
326 let repo_model = create_test_relayer_stellar(false, false);
327 let domain_relayer = Relayer::from(repo_model.clone());
328
329 assert_eq!(domain_relayer.id, repo_model.id);
330 assert_eq!(domain_relayer.network_type, RelayerNetworkType::Stellar);
331
332 assert!(domain_relayer.policies.is_some());
334 if let Some(RelayerNetworkPolicy::Stellar(stellar_policy)) = domain_relayer.policies {
335 assert_eq!(stellar_policy.min_balance, Some(20000000));
336 assert_eq!(stellar_policy.max_fee, Some(100000));
337 assert_eq!(stellar_policy.timeout_seconds, Some(30));
338 } else {
339 panic!("Expected Stellar policy");
340 }
341 }
342
343 #[test]
344 fn test_conversion_from_domain_to_repo_model_evm() {
345 let domain_relayer = Relayer {
346 id: "test_evm_relayer".to_string(),
347 name: "Test EVM Relayer".to_string(),
348 network: "mainnet".to_string(),
349 paused: false,
350 network_type: RelayerNetworkType::Evm,
351 policies: Some(RelayerNetworkPolicy::Evm(RelayerEvmPolicy {
352 gas_price_cap: Some(100_000_000_000),
353 eip1559_pricing: Some(true),
354 min_balance: None,
355 gas_limit_estimation: None,
356 whitelist_receivers: None,
357 private_transactions: None,
358 })),
359 signer_id: "test_signer".to_string(),
360 notification_id: Some("notification_123".to_string()),
361 custom_rpc_urls: None,
362 };
363
364 let repo_model = RelayerRepoModel::from(domain_relayer.clone());
365
366 assert_eq!(repo_model.id, domain_relayer.id);
367 assert_eq!(repo_model.name, domain_relayer.name);
368 assert_eq!(repo_model.network, domain_relayer.network);
369 assert_eq!(repo_model.paused, domain_relayer.paused);
370 assert_eq!(repo_model.network_type, domain_relayer.network_type);
371 assert_eq!(repo_model.signer_id, domain_relayer.signer_id);
372 assert_eq!(repo_model.notification_id, domain_relayer.notification_id);
373 assert_eq!(repo_model.custom_rpc_urls, domain_relayer.custom_rpc_urls);
374
375 assert_eq!(repo_model.address, "");
377 assert!(!repo_model.system_disabled);
378
379 if let RelayerNetworkPolicy::Evm(evm_policy) = repo_model.policies {
381 assert_eq!(evm_policy.gas_price_cap, Some(100_000_000_000));
382 assert_eq!(evm_policy.eip1559_pricing, Some(true));
383 } else {
384 panic!("Expected EVM policy");
385 }
386 }
387
388 #[test]
389 fn test_conversion_from_domain_to_repo_model_solana() {
390 let domain_relayer = Relayer {
391 id: "test_solana_relayer".to_string(),
392 name: "Test Solana Relayer".to_string(),
393 network: "mainnet".to_string(),
394 paused: false,
395 network_type: RelayerNetworkType::Solana,
396 policies: Some(RelayerNetworkPolicy::Solana(RelayerSolanaPolicy {
397 fee_payment_strategy: Some(SolanaFeePaymentStrategy::User),
398 min_balance: Some(5000000),
399 max_signatures: Some(8),
400 allowed_tokens: Some(vec![SolanaAllowedTokensPolicy::new(
401 "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v".to_string(),
402 Some(100000),
403 None,
404 )]),
405 allowed_programs: None,
406 allowed_accounts: None,
407 disallowed_accounts: None,
408 max_tx_data_size: None,
409 max_allowed_fee_lamports: None,
410 swap_config: None,
411 fee_margin_percentage: None,
412 })),
413 signer_id: "test_signer".to_string(),
414 notification_id: None,
415 custom_rpc_urls: None,
416 };
417
418 let repo_model = RelayerRepoModel::from(domain_relayer.clone());
419
420 assert_eq!(repo_model.network_type, RelayerNetworkType::Solana);
421
422 if let RelayerNetworkPolicy::Solana(solana_policy) = repo_model.policies {
424 assert_eq!(
425 solana_policy.fee_payment_strategy,
426 Some(SolanaFeePaymentStrategy::User)
427 );
428 assert_eq!(solana_policy.min_balance, Some(5000000));
429 assert_eq!(solana_policy.max_signatures, Some(8));
430 assert!(solana_policy.allowed_tokens.is_some());
431 } else {
432 panic!("Expected Solana policy");
433 }
434 }
435
436 #[test]
437 fn test_conversion_from_domain_to_repo_model_stellar() {
438 let domain_relayer = Relayer {
439 id: "test_stellar_relayer".to_string(),
440 name: "Test Stellar Relayer".to_string(),
441 network: "mainnet".to_string(),
442 paused: false,
443 network_type: RelayerNetworkType::Stellar,
444 policies: Some(RelayerNetworkPolicy::Stellar(RelayerStellarPolicy {
445 min_balance: Some(30000000),
446 max_fee: Some(150000),
447 timeout_seconds: Some(60),
448 })),
449 signer_id: "test_signer".to_string(),
450 notification_id: None,
451 custom_rpc_urls: None,
452 };
453
454 let repo_model = RelayerRepoModel::from(domain_relayer.clone());
455
456 assert_eq!(repo_model.network_type, RelayerNetworkType::Stellar);
457
458 if let RelayerNetworkPolicy::Stellar(stellar_policy) = repo_model.policies {
460 assert_eq!(stellar_policy.min_balance, Some(30000000));
461 assert_eq!(stellar_policy.max_fee, Some(150000));
462 assert_eq!(stellar_policy.timeout_seconds, Some(60));
463 } else {
464 panic!("Expected Stellar policy");
465 }
466 }
467
468 #[test]
469 fn test_conversion_from_domain_with_no_policies_evm() {
470 let domain_relayer = Relayer {
471 id: "test_evm_relayer".to_string(),
472 name: "Test EVM Relayer".to_string(),
473 network: "mainnet".to_string(),
474 paused: false,
475 network_type: RelayerNetworkType::Evm,
476 policies: None, signer_id: "test_signer".to_string(),
478 notification_id: None,
479 custom_rpc_urls: None,
480 };
481
482 let repo_model = RelayerRepoModel::from(domain_relayer);
483
484 if let RelayerNetworkPolicy::Evm(evm_policy) = repo_model.policies {
486 assert_eq!(evm_policy.gas_price_cap, None);
488 assert_eq!(evm_policy.eip1559_pricing, None);
489 assert_eq!(evm_policy.min_balance, None);
490 assert_eq!(evm_policy.gas_limit_estimation, None);
491 assert_eq!(evm_policy.whitelist_receivers, None);
492 assert_eq!(evm_policy.private_transactions, None);
493 } else {
494 panic!("Expected default EVM policy");
495 }
496 }
497
498 #[test]
499 fn test_conversion_from_domain_with_no_policies_solana() {
500 let domain_relayer = Relayer {
501 id: "test_solana_relayer".to_string(),
502 name: "Test Solana Relayer".to_string(),
503 network: "mainnet".to_string(),
504 paused: false,
505 network_type: RelayerNetworkType::Solana,
506 policies: None, signer_id: "test_signer".to_string(),
508 notification_id: None,
509 custom_rpc_urls: None,
510 };
511
512 let repo_model = RelayerRepoModel::from(domain_relayer);
513
514 if let RelayerNetworkPolicy::Solana(solana_policy) = repo_model.policies {
516 assert_eq!(solana_policy.fee_payment_strategy, None);
518 assert_eq!(solana_policy.min_balance, None);
519 assert_eq!(solana_policy.max_signatures, None);
520 assert_eq!(solana_policy.allowed_tokens, None);
521 assert_eq!(solana_policy.allowed_programs, None);
522 assert_eq!(solana_policy.allowed_accounts, None);
523 assert_eq!(solana_policy.disallowed_accounts, None);
524 assert_eq!(solana_policy.max_tx_data_size, None);
525 assert_eq!(solana_policy.max_allowed_fee_lamports, None);
526 assert_eq!(solana_policy.swap_config, None);
527 assert_eq!(solana_policy.fee_margin_percentage, None);
528 } else {
529 panic!("Expected default Solana policy");
530 }
531 }
532
533 #[test]
534 fn test_conversion_from_domain_with_no_policies_stellar() {
535 let domain_relayer = Relayer {
536 id: "test_stellar_relayer".to_string(),
537 name: "Test Stellar Relayer".to_string(),
538 network: "mainnet".to_string(),
539 paused: false,
540 network_type: RelayerNetworkType::Stellar,
541 policies: None, signer_id: "test_signer".to_string(),
543 notification_id: None,
544 custom_rpc_urls: None,
545 };
546
547 let repo_model = RelayerRepoModel::from(domain_relayer);
548
549 if let RelayerNetworkPolicy::Stellar(stellar_policy) = repo_model.policies {
551 assert_eq!(stellar_policy.min_balance, None);
553 assert_eq!(stellar_policy.max_fee, None);
554 assert_eq!(stellar_policy.timeout_seconds, None);
555 } else {
556 panic!("Expected default Stellar policy");
557 }
558 }
559
560 #[test]
561 fn test_relayer_repo_updater_preserves_runtime_fields() {
562 let original = RelayerRepoModel {
564 id: "test_relayer".to_string(),
565 name: "Original Name".to_string(),
566 address: "0x742d35Cc6634C0532925a3b8D8C2e48a73F6ba2E".to_string(), system_disabled: true, paused: false,
569 network: "mainnet".to_string(),
570 network_type: NetworkType::Evm,
571 signer_id: "test_signer".to_string(),
572 policies: RelayerNetworkPolicy::Evm(RelayerEvmPolicy::default()),
573 notification_id: None,
574 custom_rpc_urls: None,
575 };
576
577 let domain_update = Relayer {
579 id: "test_relayer".to_string(),
580 name: "Updated Name".to_string(), paused: true, network: "mainnet".to_string(),
583 network_type: RelayerNetworkType::Evm,
584 signer_id: "test_signer".to_string(),
585 policies: Some(RelayerNetworkPolicy::Evm(RelayerEvmPolicy::default())),
586 notification_id: Some("new_notification".to_string()), custom_rpc_urls: None,
588 };
589
590 let updated =
592 RelayerRepoUpdater::from_existing(original.clone()).apply_domain_update(domain_update);
593
594 assert_eq!(updated.name, "Updated Name");
596 assert!(updated.paused);
597 assert_eq!(
598 updated.notification_id,
599 Some("new_notification".to_string())
600 );
601
602 assert_eq!(
604 updated.address,
605 "0x742d35Cc6634C0532925a3b8D8C2e48a73F6ba2E"
606 );
607 assert!(updated.system_disabled);
608 }
609
610 #[test]
611 fn test_relayer_repo_updater_preserves_runtime_fields_solana() {
612 let original = RelayerRepoModel {
614 id: "test_solana_relayer".to_string(),
615 name: "Original Solana Name".to_string(),
616 address: "SolanaOriginalAddress123".to_string(), system_disabled: true, paused: false,
619 network: "mainnet".to_string(),
620 network_type: NetworkType::Solana,
621 signer_id: "test_signer".to_string(),
622 policies: RelayerNetworkPolicy::Solana(RelayerSolanaPolicy::default()),
623 notification_id: None,
624 custom_rpc_urls: None,
625 };
626
627 let domain_update = Relayer {
629 id: "test_solana_relayer".to_string(),
630 name: "Updated Solana Name".to_string(), paused: true, network: "mainnet".to_string(),
633 network_type: RelayerNetworkType::Solana,
634 signer_id: "test_signer".to_string(),
635 policies: Some(RelayerNetworkPolicy::Solana(RelayerSolanaPolicy {
636 min_balance: Some(2000000), ..RelayerSolanaPolicy::default()
638 })),
639 notification_id: Some("solana_notification".to_string()), custom_rpc_urls: None,
641 };
642
643 let updated =
645 RelayerRepoUpdater::from_existing(original.clone()).apply_domain_update(domain_update);
646
647 assert_eq!(updated.name, "Updated Solana Name");
649 assert!(updated.paused);
650 assert_eq!(
651 updated.notification_id,
652 Some("solana_notification".to_string())
653 );
654
655 assert_eq!(updated.address, "SolanaOriginalAddress123");
657 assert!(updated.system_disabled);
658
659 if let RelayerNetworkPolicy::Solana(solana_policy) = updated.policies {
661 assert_eq!(solana_policy.min_balance, Some(2000000));
662 } else {
663 panic!("Expected Solana policy");
664 }
665 }
666
667 #[test]
668 fn test_relayer_repo_updater_preserves_runtime_fields_stellar() {
669 let original = RelayerRepoModel {
671 id: "test_stellar_relayer".to_string(),
672 name: "Original Stellar Name".to_string(),
673 address: "GORIGINALXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX".to_string(), system_disabled: false, paused: true,
676 network: "mainnet".to_string(),
677 network_type: NetworkType::Stellar,
678 signer_id: "test_signer".to_string(),
679 policies: RelayerNetworkPolicy::Stellar(RelayerStellarPolicy::default()),
680 notification_id: Some("original_notification".to_string()),
681 custom_rpc_urls: None,
682 };
683
684 let domain_update = Relayer {
686 id: "test_stellar_relayer".to_string(),
687 name: "Updated Stellar Name".to_string(), paused: false, network: "mainnet".to_string(),
690 network_type: RelayerNetworkType::Stellar,
691 signer_id: "test_signer".to_string(),
692 policies: Some(RelayerNetworkPolicy::Stellar(RelayerStellarPolicy {
693 min_balance: Some(40000000), max_fee: Some(200000), timeout_seconds: Some(120), })),
697 notification_id: None, custom_rpc_urls: None,
699 };
700
701 let updated =
703 RelayerRepoUpdater::from_existing(original.clone()).apply_domain_update(domain_update);
704
705 assert_eq!(updated.name, "Updated Stellar Name");
707 assert!(!updated.paused);
708 assert_eq!(updated.notification_id, None);
709
710 assert_eq!(
712 updated.address,
713 "GORIGINALXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
714 );
715 assert!(!updated.system_disabled);
716
717 if let RelayerNetworkPolicy::Stellar(stellar_policy) = updated.policies {
719 assert_eq!(stellar_policy.min_balance, Some(40000000));
720 assert_eq!(stellar_policy.max_fee, Some(200000));
721 assert_eq!(stellar_policy.timeout_seconds, Some(120));
722 } else {
723 panic!("Expected Stellar policy");
724 }
725 }
726
727 #[test]
728 fn test_repo_model_serialization_deserialization_evm() {
729 let original = create_test_relayer(false, false);
730
731 let serialized = serde_json::to_string(&original).unwrap();
733 assert!(!serialized.is_empty());
734
735 let deserialized: RelayerRepoModel = serde_json::from_str(&serialized).unwrap();
737
738 assert_eq!(original.id, deserialized.id);
740 assert_eq!(original.name, deserialized.name);
741 assert_eq!(original.network, deserialized.network);
742 assert_eq!(original.paused, deserialized.paused);
743 assert_eq!(original.network_type, deserialized.network_type);
744 assert_eq!(original.signer_id, deserialized.signer_id);
745 assert_eq!(original.address, deserialized.address);
746 assert_eq!(original.notification_id, deserialized.notification_id);
747 assert_eq!(original.system_disabled, deserialized.system_disabled);
748 assert_eq!(original.custom_rpc_urls, deserialized.custom_rpc_urls);
749
750 match (&original.policies, &deserialized.policies) {
752 (RelayerNetworkPolicy::Evm(_), RelayerNetworkPolicy::Evm(_)) => {
753 }
755 _ => panic!("Policy types don't match after serialization/deserialization"),
756 }
757 }
758
759 #[test]
760 fn test_repo_model_serialization_deserialization_solana() {
761 let original = create_test_relayer_solana(true, false);
762
763 let serialized = serde_json::to_string(&original).unwrap();
765 assert!(!serialized.is_empty());
766
767 let deserialized: RelayerRepoModel = serde_json::from_str(&serialized).unwrap();
769
770 assert_eq!(original.id, deserialized.id);
772 assert_eq!(original.network_type, RelayerNetworkType::Solana);
773 assert_eq!(deserialized.network_type, RelayerNetworkType::Solana);
774 assert_eq!(original.paused, deserialized.paused);
775
776 match (&original.policies, &deserialized.policies) {
778 (RelayerNetworkPolicy::Solana(orig), RelayerNetworkPolicy::Solana(deser)) => {
779 assert_eq!(orig.fee_payment_strategy, deser.fee_payment_strategy);
780 assert_eq!(orig.min_balance, deser.min_balance);
781 assert_eq!(orig.max_signatures, deser.max_signatures);
782 }
783 _ => panic!("Policy types don't match after serialization/deserialization"),
784 }
785 }
786
787 #[test]
788 fn test_repo_model_serialization_deserialization_stellar() {
789 let original = create_test_relayer_stellar(false, true);
790
791 let serialized = serde_json::to_string(&original).unwrap();
793 assert!(!serialized.is_empty());
794
795 let deserialized: RelayerRepoModel = serde_json::from_str(&serialized).unwrap();
797
798 assert_eq!(original.id, deserialized.id);
800 assert_eq!(original.network_type, RelayerNetworkType::Stellar);
801 assert_eq!(deserialized.network_type, RelayerNetworkType::Stellar);
802 assert_eq!(original.system_disabled, deserialized.system_disabled);
803
804 match (&original.policies, &deserialized.policies) {
806 (RelayerNetworkPolicy::Stellar(orig), RelayerNetworkPolicy::Stellar(deser)) => {
807 assert_eq!(orig.min_balance, deser.min_balance);
808 assert_eq!(orig.max_fee, deser.max_fee);
809 assert_eq!(orig.timeout_seconds, deser.timeout_seconds);
810 }
811 _ => panic!("Policy types don't match after serialization/deserialization"),
812 }
813 }
814
815 #[test]
816 fn test_repo_model_default() {
817 let default_model = RelayerRepoModel::default();
818
819 assert_eq!(default_model.id, "");
820 assert_eq!(default_model.name, "");
821 assert_eq!(default_model.network, "");
822 assert!(!default_model.paused);
823 assert_eq!(default_model.network_type, NetworkType::Evm);
824 assert_eq!(default_model.signer_id, "");
825 assert_eq!(default_model.address, "0x");
826 assert_eq!(default_model.notification_id, None);
827 assert!(!default_model.system_disabled);
828 assert_eq!(default_model.custom_rpc_urls, None);
829
830 if let RelayerNetworkPolicy::Evm(_) = default_model.policies {
832 } else {
834 panic!("Default should have EVM policy");
835 }
836 }
837
838 #[test]
839 fn test_round_trip_conversion_all_network_types() {
840 let original_evm = Relayer {
844 id: "evm_relayer".to_string(),
845 name: "EVM Relayer".to_string(),
846 network: "mainnet".to_string(),
847 paused: false,
848 network_type: RelayerNetworkType::Evm,
849 policies: Some(RelayerNetworkPolicy::Evm(RelayerEvmPolicy {
850 gas_price_cap: Some(50_000_000_000),
851 eip1559_pricing: Some(true),
852 min_balance: None,
853 gas_limit_estimation: None,
854 whitelist_receivers: None,
855 private_transactions: None,
856 })),
857 signer_id: "evm_signer".to_string(),
858 notification_id: Some("evm_notification".to_string()),
859 custom_rpc_urls: None,
860 };
861
862 let repo_evm = RelayerRepoModel::from(original_evm.clone());
863 let recovered_evm = Relayer::from(repo_evm);
864
865 assert_eq!(original_evm.id, recovered_evm.id);
866 assert_eq!(original_evm.network_type, recovered_evm.network_type);
867 assert_eq!(original_evm.notification_id, recovered_evm.notification_id);
868
869 let original_solana = Relayer {
871 id: "solana_relayer".to_string(),
872 name: "Solana Relayer".to_string(),
873 network: "mainnet".to_string(),
874 paused: true,
875 network_type: RelayerNetworkType::Solana,
876 policies: Some(RelayerNetworkPolicy::Solana(RelayerSolanaPolicy {
877 fee_payment_strategy: Some(SolanaFeePaymentStrategy::User),
878 min_balance: Some(3000000),
879 max_signatures: None,
880 allowed_tokens: None,
881 allowed_programs: None,
882 allowed_accounts: None,
883 disallowed_accounts: None,
884 max_tx_data_size: None,
885 max_allowed_fee_lamports: None,
886 swap_config: None,
887 fee_margin_percentage: None,
888 })),
889 signer_id: "solana_signer".to_string(),
890 notification_id: None,
891 custom_rpc_urls: None,
892 };
893
894 let repo_solana = RelayerRepoModel::from(original_solana.clone());
895 let recovered_solana = Relayer::from(repo_solana);
896
897 assert_eq!(original_solana.id, recovered_solana.id);
898 assert_eq!(original_solana.network_type, recovered_solana.network_type);
899 assert_eq!(original_solana.paused, recovered_solana.paused);
900
901 let original_stellar = Relayer {
903 id: "stellar_relayer".to_string(),
904 name: "Stellar Relayer".to_string(),
905 network: "mainnet".to_string(),
906 paused: false,
907 network_type: RelayerNetworkType::Stellar,
908 policies: Some(RelayerNetworkPolicy::Stellar(RelayerStellarPolicy {
909 min_balance: Some(50000000),
910 max_fee: Some(250000),
911 timeout_seconds: Some(180),
912 })),
913 signer_id: "stellar_signer".to_string(),
914 notification_id: Some("stellar_notification".to_string()),
915 custom_rpc_urls: None,
916 };
917
918 let repo_stellar = RelayerRepoModel::from(original_stellar.clone());
919 let recovered_stellar = Relayer::from(repo_stellar);
920
921 assert_eq!(original_stellar.id, recovered_stellar.id);
922 assert_eq!(
923 original_stellar.network_type,
924 recovered_stellar.network_type
925 );
926 assert_eq!(
927 original_stellar.notification_id,
928 recovered_stellar.notification_id
929 );
930 }
931}