1
1
use {
2
2
crate :: {
3
3
chain:: reader:: { BlockNumber , BlockStatus , EntropyReader } ,
4
+ config:: Config ,
4
5
history:: History ,
5
6
state:: MonitoredHashChainState ,
6
7
} ,
22
23
tokio:: sync:: RwLock ,
23
24
url:: Url ,
24
25
} ;
25
- pub use { chain_ids:: * , explorer:: * , index:: * , live:: * , metrics:: * , ready:: * , revelation:: * } ;
26
+ pub use {
27
+ chain_ids:: * , config:: * , explorer:: * , index:: * , live:: * , metrics:: * , ready:: * , revelation:: * ,
28
+ } ;
26
29
27
30
mod chain_ids;
31
+ mod config;
28
32
mod explorer;
29
33
mod index;
30
34
mod live;
@@ -73,13 +77,16 @@ pub struct ApiState {
73
77
pub metrics : Arc < ApiMetrics > ,
74
78
75
79
pub explorer_metrics : Arc < ExplorerMetrics > ,
80
+
81
+ pub config : Config ,
76
82
}
77
83
78
84
impl ApiState {
79
85
pub async fn new (
80
86
chains : Arc < RwLock < HashMap < ChainId , ApiBlockChainState > > > ,
81
87
metrics_registry : Arc < RwLock < Registry > > ,
82
88
history : Arc < History > ,
89
+ config : & Config ,
83
90
) -> ApiState {
84
91
let metrics = ApiMetrics {
85
92
http_requests : Family :: default ( ) ,
@@ -100,6 +107,7 @@ impl ApiState {
100
107
explorer_metrics,
101
108
history,
102
109
metrics_registry,
110
+ config : config. clone ( ) ,
103
111
}
104
112
}
105
113
}
@@ -211,6 +219,7 @@ pub fn routes(state: ApiState) -> Router<(), Body> {
211
219
"/v1/chains/:chain_id/revelations/:sequence" ,
212
220
get ( revelation) ,
213
221
)
222
+ . route ( "/v1/chains/configs" , get ( get_chain_configs) )
214
223
. with_state ( state)
215
224
}
216
225
@@ -230,9 +239,10 @@ mod test {
230
239
crate :: {
231
240
api:: {
232
241
self , ApiBlockChainState , ApiState , BinaryEncoding , Blob , BlockchainState ,
233
- GetRandomValueResponse ,
242
+ ChainConfigSummary , GetRandomValueResponse ,
234
243
} ,
235
244
chain:: reader:: { mock:: MockEntropyReader , BlockStatus } ,
245
+ config:: Config ,
236
246
history:: History ,
237
247
state:: { HashChainState , MonitoredHashChainState , PebbleHashChain } ,
238
248
} ,
@@ -311,10 +321,40 @@ mod test {
311
321
ApiBlockChainState :: Initialized ( avax_state) ,
312
322
) ;
313
323
324
+ // Create a minimal config for testing
325
+ let config = Config {
326
+ chains : HashMap :: new ( ) ,
327
+ provider : crate :: config:: ProviderConfig {
328
+ uri : "http://localhost:8080/" . to_string ( ) ,
329
+ address : PROVIDER ,
330
+ private_key : crate :: config:: SecretString {
331
+ value : Some ( "0xabcd" . to_string ( ) ) ,
332
+ file : None ,
333
+ } ,
334
+ secret : crate :: config:: SecretString {
335
+ value : Some ( "abcd" . to_string ( ) ) ,
336
+ file : None ,
337
+ } ,
338
+ chain_length : 100000 ,
339
+ chain_sample_interval : 10 ,
340
+ fee_manager : None ,
341
+ } ,
342
+ keeper : crate :: config:: KeeperConfig {
343
+ private_key : crate :: config:: SecretString {
344
+ value : Some ( "0xabcd" . to_string ( ) ) ,
345
+ file : None ,
346
+ } ,
347
+ fee_manager_private_key : None ,
348
+ other_keeper_addresses : vec ! [ ] ,
349
+ replica_config : None ,
350
+ } ,
351
+ } ;
352
+
314
353
let api_state = ApiState :: new (
315
354
Arc :: new ( RwLock :: new ( chains) ) ,
316
355
metrics_registry,
317
356
Arc :: new ( History :: new ( ) . await . unwrap ( ) ) ,
357
+ & config,
318
358
)
319
359
. await ;
320
360
@@ -534,4 +574,151 @@ mod test {
534
574
)
535
575
. await ;
536
576
}
577
+
578
+ #[ tokio:: test]
579
+ async fn test_chain_configs ( ) {
580
+ let ( server, _, _) = test_server ( ) . await ;
581
+
582
+ // Test the chain configs endpoint
583
+ let response = server. get ( "/v1/chains/configs" ) . await ;
584
+ response. assert_status ( StatusCode :: OK ) ;
585
+
586
+ // Parse the response as JSON
587
+ let configs: Vec < ChainConfigSummary > = response. json ( ) ;
588
+
589
+ // Verify the response structure - should be empty for test server
590
+ assert_eq ! (
591
+ configs. len( ) ,
592
+ 0 ,
593
+ "Should return empty configs for test server"
594
+ ) ;
595
+ }
596
+
597
+ #[ tokio:: test]
598
+ async fn test_chain_configs_with_data ( ) {
599
+ // Create a config with actual chain data
600
+ let mut config_chains = HashMap :: new ( ) ;
601
+ config_chains. insert (
602
+ "ethereum" . to_string ( ) ,
603
+ crate :: config:: EthereumConfig {
604
+ geth_rpc_addr : "http://localhost:8545" . to_string ( ) ,
605
+ contract_addr : Address :: from_low_u64_be ( 0x1234 ) ,
606
+ reveal_delay_blocks : 1 ,
607
+ confirmed_block_status : BlockStatus :: Latest ,
608
+ backlog_range : 1000 ,
609
+ legacy_tx : false ,
610
+ gas_limit : 500000 ,
611
+ priority_fee_multiplier_pct : 100 ,
612
+ escalation_policy : crate :: config:: EscalationPolicyConfig :: default ( ) ,
613
+ min_profit_pct : 0 ,
614
+ target_profit_pct : 20 ,
615
+ max_profit_pct : 100 ,
616
+ min_keeper_balance : 100000000000000000 ,
617
+ fee : 1500000000000000 ,
618
+ sync_fee_only_on_register : true ,
619
+ commitments : None ,
620
+ max_num_hashes : None ,
621
+ block_delays : vec ! [ 5 ] ,
622
+ } ,
623
+ ) ;
624
+ config_chains. insert (
625
+ "avalanche" . to_string ( ) ,
626
+ crate :: config:: EthereumConfig {
627
+ geth_rpc_addr : "http://localhost:9650" . to_string ( ) ,
628
+ contract_addr : Address :: from_low_u64_be ( 0x5678 ) ,
629
+ reveal_delay_blocks : 2 ,
630
+ confirmed_block_status : BlockStatus :: Latest ,
631
+ backlog_range : 1000 ,
632
+ legacy_tx : false ,
633
+ gas_limit : 600000 ,
634
+ priority_fee_multiplier_pct : 100 ,
635
+ escalation_policy : crate :: config:: EscalationPolicyConfig :: default ( ) ,
636
+ min_profit_pct : 0 ,
637
+ target_profit_pct : 20 ,
638
+ max_profit_pct : 100 ,
639
+ min_keeper_balance : 100000000000000000 ,
640
+ fee : 2000000000000000 ,
641
+ sync_fee_only_on_register : true ,
642
+ commitments : None ,
643
+ max_num_hashes : None ,
644
+ block_delays : vec ! [ 5 ] ,
645
+ } ,
646
+ ) ;
647
+
648
+ let config = Config {
649
+ chains : config_chains,
650
+ provider : crate :: config:: ProviderConfig {
651
+ uri : "http://localhost:8080/" . to_string ( ) ,
652
+ address : PROVIDER ,
653
+ private_key : crate :: config:: SecretString {
654
+ value : Some ( "0xabcd" . to_string ( ) ) ,
655
+ file : None ,
656
+ } ,
657
+ secret : crate :: config:: SecretString {
658
+ value : Some ( "abcd" . to_string ( ) ) ,
659
+ file : None ,
660
+ } ,
661
+ chain_length : 100000 ,
662
+ chain_sample_interval : 10 ,
663
+ fee_manager : None ,
664
+ } ,
665
+ keeper : crate :: config:: KeeperConfig {
666
+ private_key : crate :: config:: SecretString {
667
+ value : Some ( "0xabcd" . to_string ( ) ) ,
668
+ file : None ,
669
+ } ,
670
+ fee_manager_private_key : None ,
671
+ other_keeper_addresses : vec ! [ ] ,
672
+ replica_config : None ,
673
+ } ,
674
+ } ;
675
+
676
+ let metrics_registry = Arc :: new ( RwLock :: new ( Registry :: default ( ) ) ) ;
677
+ let api_state = ApiState :: new (
678
+ Arc :: new ( RwLock :: new ( HashMap :: new ( ) ) ) ,
679
+ metrics_registry,
680
+ Arc :: new ( History :: new ( ) . await . unwrap ( ) ) ,
681
+ & config,
682
+ )
683
+ . await ;
684
+
685
+ let app = api:: routes ( api_state) ;
686
+ let server = TestServer :: new ( app) . unwrap ( ) ;
687
+
688
+ // Test the chain configs endpoint
689
+ let response = server. get ( "/v1/chains/configs" ) . await ;
690
+ response. assert_status ( StatusCode :: OK ) ;
691
+
692
+ // Parse the response as JSON
693
+ let configs: Vec < ChainConfigSummary > = response. json ( ) ;
694
+
695
+ // Verify we have 2 chains
696
+ assert_eq ! ( configs. len( ) , 2 , "Should return 2 chain configs" ) ;
697
+
698
+ // Find ethereum config
699
+ let eth_config = configs
700
+ . iter ( )
701
+ . find ( |c| c. name == "ethereum" )
702
+ . expect ( "Ethereum config not found" ) ;
703
+ assert_eq ! (
704
+ eth_config. contract_addr,
705
+ "0x0000000000000000000000000000000000001234"
706
+ ) ;
707
+ assert_eq ! ( eth_config. reveal_delay_blocks, 1 ) ;
708
+ assert_eq ! ( eth_config. gas_limit, 500000 ) ;
709
+ assert_eq ! ( eth_config. fee, 1500000000000000 ) ;
710
+
711
+ // Find avalanche config
712
+ let avax_config = configs
713
+ . iter ( )
714
+ . find ( |c| c. name == "avalanche" )
715
+ . expect ( "Avalanche config not found" ) ;
716
+ assert_eq ! (
717
+ avax_config. contract_addr,
718
+ "0x0000000000000000000000000000000000005678"
719
+ ) ;
720
+ assert_eq ! ( avax_config. reveal_delay_blocks, 2 ) ;
721
+ assert_eq ! ( avax_config. gas_limit, 600000 ) ;
722
+ assert_eq ! ( avax_config. fee, 2000000000000000 ) ;
723
+ }
537
724
}
0 commit comments