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