1use std::collections::HashMap;
2use std::sync::Arc;
3
4use crate::topology_config::TransportType;
5use crate::topology_config::{BroadcasterConfig, ClientConfig, EncoderConfig, EstimatorConfig, SignersConfig, TopologyConfig};
6use alloy_primitives::Address;
7use alloy_provider::network::Ethereum;
8use alloy_provider::{Network, Provider, ProviderBuilder, RootProvider};
9use alloy_rpc_client::ClientBuilder;
10use alloy_transport_ipc::IpcConnect;
11use alloy_transport_ws::WsConnect;
12use eyre::{eyre, Result};
13use kabu_broadcast_accounts::{InitializeSignersOneShotBlockingActor, NonceAndBalanceMonitorActor, TxSignersActor};
14use kabu_broadcast_broadcaster::FlashbotsBroadcastActor;
15use kabu_broadcast_flashbots::Flashbots;
16use kabu_core_actors::{Accessor, Actor, Consumer, Producer, SharedState, WorkerResult};
17use kabu_core_block_history::BlockHistoryActor;
18use kabu_core_blockchain::{Blockchain, BlockchainState, Strategy};
19use kabu_core_mempool::MempoolActor;
20use kabu_defi_health_monitor::PoolHealthMonitorActor;
21use kabu_defi_market::{HistoryPoolLoaderOneShotActor, NewPoolLoaderActor, PoolLoaderActor, ProtocolPoolLoaderOneShotActor};
22use kabu_defi_pools::PoolLoadersBuilder;
23use kabu_defi_preloader::MarketStatePreloadedOneShotActor;
24use kabu_defi_price::PriceActor;
25use kabu_evm_db::{DatabaseKabuExt, KabuDBError};
26use kabu_execution_estimator::{EvmEstimatorActor, GethEstimatorActor};
27use kabu_execution_multicaller::MulticallerSwapEncoder;
28use kabu_node_actor_config::NodeBlockActorConfig;
29use kabu_node_json_rpc::{NodeBlockActor, NodeMempoolActor};
30use kabu_types_blockchain::{KabuDataTypes, KabuDataTypesEthereum};
31use kabu_types_entities::pool_config::PoolsLoadingConfig;
32use kabu_types_entities::{BlockHistoryState, MarketState, PoolLoaders, SwapEncoder, TxSigners};
33use revm::{Database, DatabaseCommit, DatabaseRef};
34use tokio::task::JoinHandle;
35use tracing::{error, info, warn};
36
37pub struct Topology<
38 DB: Clone + Send + Sync + 'static,
39 E: Send + Sync + Clone + 'static = MulticallerSwapEncoder,
40 P: Provider<N> + Send + Sync + Clone + 'static = RootProvider,
41 N: Network = Ethereum,
42 LDT: KabuDataTypes = KabuDataTypesEthereum,
43> {
44 config: TopologyConfig,
45 clients: HashMap<String, RootProvider<N>>,
46 blockchains: HashMap<String, Blockchain>,
47 blockchain_states: HashMap<String, BlockchainState<DB, LDT>>,
48 strategies: HashMap<String, Strategy<DB>>,
49 signers: HashMap<String, SharedState<TxSigners>>,
50 multicaller_encoders: HashMap<String, Address>,
51 default_blockchain_name: Option<String>,
52 default_multicaller_encoder_name: Option<String>,
53 default_signer_name: Option<String>,
54 swap_encoder: E,
55 pool_loaders: Arc<PoolLoaders<P, N, LDT>>,
56}
57
58impl<
59 DB: Database<Error = KabuDBError>
60 + DatabaseRef<Error = KabuDBError>
61 + DatabaseCommit
62 + DatabaseKabuExt
63 + BlockHistoryState<KabuDataTypesEthereum>
64 + Default
65 + Send
66 + Sync
67 + Clone
68 + 'static,
69 E: SwapEncoder + Send + Sync + Clone + 'static,
70 P: Provider<Ethereum> + Send + Sync + Clone + 'static,
71 > Topology<DB, E, P, Ethereum, KabuDataTypesEthereum>
72{
73 pub fn from_config(config: TopologyConfig) -> Topology<DB, MulticallerSwapEncoder> {
74 let encoder = MulticallerSwapEncoder::default();
75 let pool_loaders = Arc::new(PoolLoadersBuilder::<RootProvider>::new().build());
76
77 Topology::<DB, MulticallerSwapEncoder> {
78 config,
79 clients: HashMap::new(),
80 blockchains: HashMap::new(),
81 blockchain_states: HashMap::new(),
82 strategies: HashMap::new(),
83 signers: HashMap::new(),
84 multicaller_encoders: HashMap::new(),
85 default_blockchain_name: None,
86 default_multicaller_encoder_name: None,
87 default_signer_name: None,
88 swap_encoder: encoder,
89 pool_loaders,
90 }
91 }
92
93 pub fn with_swap_encoder<NE: SwapEncoder + Send + Sync + Clone + 'static>(
94 self,
95 swap_encoder: NE,
96 ) -> Topology<DB, NE, P, Ethereum, KabuDataTypesEthereum> {
97 Topology {
99 config: self.config,
100 clients: self.clients,
101 blockchains: self.blockchains,
102 blockchain_states: self.blockchain_states,
103 strategies: self.strategies,
104 signers: self.signers,
105 multicaller_encoders: self.multicaller_encoders,
106 default_blockchain_name: self.default_blockchain_name,
107 default_multicaller_encoder_name: self.default_multicaller_encoder_name,
108 default_signer_name: self.default_signer_name,
109 pool_loaders: self.pool_loaders,
110 swap_encoder,
111 }
112 }
113
114 pub fn with_pool_loaders<NP: Provider + Send + Sync + Clone + 'static>(
115 self,
116 pool_loaders: PoolLoaders<NP, Ethereum, KabuDataTypesEthereum>,
117 ) -> Topology<DB, E, NP, Ethereum, KabuDataTypesEthereum> {
118 Topology {
119 config: self.config,
120 clients: self.clients,
121 blockchains: self.blockchains,
122 blockchain_states: self.blockchain_states,
123 strategies: self.strategies,
124 signers: self.signers,
125 multicaller_encoders: self.multicaller_encoders,
126 default_blockchain_name: self.default_blockchain_name,
127 default_multicaller_encoder_name: self.default_multicaller_encoder_name,
128 default_signer_name: self.default_signer_name,
129 swap_encoder: self.swap_encoder,
130 pool_loaders: Arc::new(pool_loaders),
131 }
132 }
133
134 pub async fn start_clients(self) -> Result<Self> {
135 let mut clients = HashMap::new();
136 for (name, v) in self.config.clients.iter() {
137 let config_params = v.clone();
138
139 info!("Connecting to {name} : {v:?}");
140
141 let client = match config_params.transport {
142 TransportType::Ipc => {
143 info!("Starting IPC connection");
144
145 let transport = IpcConnect::from(config_params.url);
146 ClientBuilder::default().ipc(transport).await
147 }
148 _ => {
149 info!("Starting WS connection");
150 let transport = WsConnect::new(config_params.url);
151 ClientBuilder::default().ws(transport).await
152 }
153 };
154
155 let client = match client {
156 Ok(client) => client,
157 Err(e) => {
158 error!("Error connecting to {name} error : {}", e);
159 continue;
160 }
161 };
162
163 let provider = ProviderBuilder::<_, _, Ethereum>::new().disable_recommended_fillers().connect_client(client);
164
165 clients.insert(name.clone(), provider);
166 }
167 Ok(Topology { clients, ..self })
168 }
169
170 pub fn build_blockchains(self) -> Self {
171 let mut multicaller_encoders = HashMap::new();
172 let mut strategies = HashMap::new();
173 let mut blockchains = HashMap::new();
174 let mut blockchain_states = HashMap::new();
175 let mut signers = HashMap::new();
176
177 let mut default_blockchain_name: Option<String> = None;
178 let mut default_multicaller_encoder_name: Option<String> = None;
179 let mut default_signer_name: Option<String> = None;
180
181 for (k, v) in self.config.encoders.iter() {
182 match v {
183 EncoderConfig::SwapStep(c) => {
184 if let Ok(address) = c.address.parse() {
185 multicaller_encoders.insert(k.clone(), address);
186 default_multicaller_encoder_name = Some(k.clone());
187 }
188 }
189 }
190 }
191
192 for (k, params) in self.config.blockchains.iter() {
193 let blockchain = Blockchain::new(params.chain_id.unwrap_or(1) as u64);
194 let market_state = MarketState::new(DB::default());
195 let blockchain_state = BlockchainState::<DB, KabuDataTypesEthereum>::new_with_market_state(market_state);
196 let strategy = Strategy::<DB>::new();
197
198 blockchains.insert(k.clone(), blockchain);
199
200 blockchain_states.insert(k.clone(), blockchain_state);
201 strategies.insert(k.clone(), strategy);
202
203 default_blockchain_name = Some(k.clone());
204 }
205
206 for (name, params) in self.config.signers.iter() {
207 match params {
208 SignersConfig::Env(_params) => {
209 let signers_state = SharedState::new(TxSigners::new());
210 signers.insert(name.clone(), signers_state);
211 default_signer_name = Some(name.clone());
212 }
213 }
214 }
215
216 Self {
217 blockchains,
218 blockchain_states,
219 multicaller_encoders,
220 strategies,
221 signers,
222 default_multicaller_encoder_name,
223 default_blockchain_name,
224 default_signer_name,
225 ..self
226 }
227 }
228
229 pub async fn start_actors(&self) -> Result<Vec<JoinHandle<WorkerResult>>> {
230 let mut tasks: Vec<JoinHandle<WorkerResult>> = Vec::new();
231
232 if self.clients.is_empty() {
233 return Err(eyre!("NO_CLIENTS_CONNECTED"));
234 }
235
236 for (k, _params) in self.config.blockchains.iter() {
237 let blockchain = self.get_blockchain(Some(k))?;
238 let blockchain_state = self.get_blockchain_state(Some(k))?;
239 let client = self.get_client(None)?;
240
241 info!("Starting block history actor {k}");
242 let mut block_history_actor = BlockHistoryActor::new(client);
243 match block_history_actor
244 .access(blockchain.latest_block())
245 .access(blockchain_state.market_state())
246 .access(blockchain_state.block_history())
247 .consume(blockchain.new_block_headers_channel())
248 .consume(blockchain.new_block_with_tx_channel())
249 .consume(blockchain.new_block_logs_channel())
250 .consume(blockchain.new_block_state_update_channel())
251 .produce(blockchain.market_events_channel())
252 .start()
253 {
254 Ok(r) => {
255 tasks.extend(r);
256 info!("Block history actor started successfully")
257 }
258 Err(e) => {
259 panic!("{}", e)
260 }
261 }
262
263 info!("Starting mempool actor {k}");
264 let mut mempool_actor = MempoolActor::new();
265 match mempool_actor
266 .access(blockchain.mempool())
267 .consume(blockchain.new_mempool_tx_channel())
268 .consume(blockchain.new_block_headers_channel())
269 .consume(blockchain.new_block_with_tx_channel())
270 .produce(blockchain.mempool_events_channel())
271 .produce(blockchain.influxdb_write_channel())
272 .start()
273 {
274 Ok(r) => {
275 tasks.extend(r);
276 info!("Mempool actor started successfully")
277 }
278 Err(e) => {
279 panic!("{}", e)
280 }
281 }
282
283 info!("Starting pool monitor monitor actor {k}");
284 let mut new_pool_health_monior_actor = PoolHealthMonitorActor::new();
285 match new_pool_health_monior_actor
286 .access(blockchain.market())
287 .consume(blockchain.health_monitor_channel())
288 .produce(blockchain.influxdb_write_channel())
289 .start()
290 {
291 Ok(r) => {
292 tasks.extend(r);
293 info!("Pool monitor monitor actor started")
294 }
295 Err(e) => {
296 panic!("PoolHealthMonitorActor error {e}")
297 }
298 }
299 }
300
301 for (name, params) in self.config.signers.iter() {
302 let signers = self.get_signers(Some(name))?;
303 match params {
304 SignersConfig::Env(params) => {
305 info!("Starting initialize env signers actor {name}");
306 let blockchain = self.get_blockchain(params.blockchain.as_ref())?;
307
308 let mut initialize_signers_actor = InitializeSignersOneShotBlockingActor::new_from_encrypted_env();
309 match initialize_signers_actor.access(signers.clone()).access(blockchain.nonce_and_balance()).start_and_wait() {
310 Ok(_) => {
311 info!("Signers have been initialized")
312 }
313 Err(e) => {
314 panic!("Cannot initialize signers {e}");
315 }
316 }
317
318 let mut signers_actor = TxSignersActor::new();
319 match signers_actor.consume(blockchain.tx_compose_channel()).produce(blockchain.tx_compose_channel()).start() {
320 Ok(r) => {
321 tasks.extend(r);
322 info!("Signers actor has been started")
323 }
324 Err(e) => {
325 panic!("Cannot start signers actor {e}")
326 }
327 }
328 }
329 }
330 }
331
332 if let Some(preloader_actors) = &self.config.preloaders {
333 for (name, params) in preloader_actors {
334 info!("Starting market state preload actor {name}");
335
336 let blockchain_state = self.get_blockchain_state(params.blockchain.as_ref())?;
337 let client = self.get_client(params.client.as_ref())?;
338 let signers = self.get_signers(params.signers.as_ref())?;
339
340 let mut market_state_preload_actor = MarketStatePreloadedOneShotActor::new(client)
341 .with_signers(signers.clone())
342 .with_copied_account(self.get_multicaller_address(None)?);
343 match market_state_preload_actor.access(blockchain_state.market_state()).start_and_wait() {
344 Ok(_) => {
345 info!("Market state preload actor executed successfully")
346 }
347 Err(e) => {
348 panic!("MarketStatePreloadedOneShotActor : {e}")
349 }
350 }
351 }
352 } else {
353 warn!("No preloader in config")
354 }
355
356 if let Some(node_block_actors) = &self.config.actors.node {
357 for (name, params) in node_block_actors {
358 let client = self.get_client(params.client.as_ref())?;
359 let blockchain = self.get_blockchain(params.blockchain.as_ref())?;
360 let client_config = self.get_client_config(params.client.as_ref())?;
361
362 info!("Starting node actor {name}");
363
364 if client_config.db_path.is_none() {
365 let mut node_block_actor = NodeBlockActor::new(client, NodeBlockActorConfig::all_enabled());
366 match node_block_actor
367 .produce(blockchain.new_block_headers_channel())
368 .produce(blockchain.new_block_with_tx_channel())
369 .produce(blockchain.new_block_logs_channel())
370 .produce(blockchain.new_block_state_update_channel())
371 .start()
372 {
373 Ok(r) => {
374 tasks.extend(r);
375 info!("Node actor started successfully for : {} @ {}", name, blockchain.chain_id())
376 }
377 Err(e) => {
378 panic!("{}", e)
379 }
380 }
381 }
382 }
383 }
384
385 if let Some(node_mempool_actors) = &self.config.actors.mempool {
386 for (name, params) in node_mempool_actors {
387 let blockchain = self.get_blockchain(params.blockchain.as_ref())?;
388 match self.get_client(params.client.as_ref()) {
389 Ok(client) => {
390 println!("Starting node mempool actor {name}");
391 let mut node_mempool_actor = NodeMempoolActor::new(client).with_name(name.clone());
392 match node_mempool_actor.produce(blockchain.new_mempool_tx_channel()).start() {
393 Ok(r) => {
394 tasks.extend(r);
395 info!("Node mempool actor started successfully {name}")
396 }
397 Err(e) => {
398 panic!("{}", e)
399 }
400 }
401 }
402 Err(e) => {
403 error!("Skipping mempool actor for {} @ {} : {}", name, blockchain.chain_id(), e)
404 }
405 }
406 }
407 }
408
409 if let Some(price_actors) = &self.config.actors.price {
410 for (name, c) in price_actors {
411 let client = self.get_client(c.client.as_ref())?;
412 let blockchain = self.get_blockchain(c.blockchain.as_ref())?;
413 info!("Starting price actor");
414 let mut price_actor = PriceActor::new(client);
415 match price_actor.access(blockchain.market()).start() {
416 Ok(r) => {
417 tasks.extend(r);
418 info!("Price actor has been initialized : {}", name)
419 }
420 Err(e) => {
421 panic!("Cannot initialize price actor {name} : {e}");
422 }
423 }
424 }
425 } else {
426 warn!("No price actor in config")
427 }
428
429 if let Some(node_balance_actors) = &self.config.actors.noncebalance {
430 for (name, c) in node_balance_actors {
431 let client = self.get_client(c.client.as_ref())?;
432 let blockchain = self.get_blockchain(c.blockchain.as_ref())?;
433
434 info!("Starting nonce and balance monitor actor {name}");
435 let mut nonce_and_balance_monitor = NonceAndBalanceMonitorActor::new(client);
436 match nonce_and_balance_monitor
437 .access(blockchain.nonce_and_balance())
438 .access(blockchain.latest_block())
439 .consume(blockchain.market_events_channel())
440 .start()
441 {
442 Ok(r) => {
443 tasks.extend(r);
444 info!("Nonce monitor has been initialized {name} for {}", blockchain.chain_id())
445 }
446 Err(e) => {
447 panic!("Cannot initialize nonce and balance monitor {name} : {e}");
448 }
449 }
450 }
451 } else {
452 warn!("No nonce and balance actors in config");
453 }
454
455 if let Some(broadcaster_actors) = &self.config.actors.broadcaster {
456 for (name, params) in broadcaster_actors {
457 match params {
458 BroadcasterConfig::Flashbots(params) => {
459 let client = self.get_client(params.client.as_ref())?;
460 let blockchain = self.get_blockchain(params.blockchain.as_ref())?;
461
462 let flashbots_client = Flashbots::new(client, "https://relay.flashbots.net", None).with_default_relays();
463 let mut flashbots_actor = FlashbotsBroadcastActor::new(flashbots_client, true);
464 match flashbots_actor.consume(blockchain.tx_compose_channel()).start() {
465 Ok(r) => {
466 tasks.extend(r);
467 info!("Flashbots broadcaster actor {name} started successfully for {}", blockchain.chain_id())
468 }
469 Err(e) => {
470 panic!("Error starting flashbots broadcaster actor {name} for {} : {}", blockchain.chain_id(), e)
471 }
472 }
473 }
474 }
475 }
476 } else {
477 warn!("No broadcaster actors in config")
478 }
479
480 if let Some(pool_actors) = &self.config.actors.pools {
481 let mut blockchains = HashMap::new();
482
483 for (name, params) in pool_actors {
484 let client = self.get_client(params.client.as_ref())?;
485 let blockchain = self.get_blockchain(params.blockchain.as_ref())?;
486 let blockchain_state = self.get_blockchain_state(params.blockchain.as_ref())?;
487
488 let pool_loaders = self.pool_loaders.clone();
489
490 blockchains.insert(blockchain.chain_id(), blockchain);
491 if params.history {
492 info!("Starting history pools loader {name}");
493
494 let mut history_pools_loader_actor = HistoryPoolLoaderOneShotActor::new(client.clone(), pool_loaders.clone());
495 match history_pools_loader_actor.produce(blockchain.tasks_channel()).start() {
496 Ok(r) => {
497 tasks.extend(r);
498 info!("History pool loader actor started successfully {name}")
499 }
500 Err(e) => {
501 panic!("HistoryPoolLoaderOneShotActor : {e}")
502 }
503 }
504 }
505 if params.protocol {
506 info!("Starting curve pools loader {name}");
507
508 let mut curve_pools_loader_actor = ProtocolPoolLoaderOneShotActor::new(client.clone(), pool_loaders.clone());
509 match curve_pools_loader_actor.produce(blockchain.tasks_channel()).start() {
510 Err(e) => {
511 panic!("CurvePoolLoaderOneShotActor : {e}")
512 }
513 Ok(r) => {
514 tasks.extend(r);
515 info!("Curve pool loader actor started successfully")
516 }
517 }
518 }
519
520 if params.new {
521 info!("Starting new pool loader actor {name}");
522 let mut new_pool_actor = NewPoolLoaderActor::new(pool_loaders.clone());
523 match new_pool_actor.consume(blockchain.new_block_logs_channel()).produce(blockchain.tasks_channel()).start() {
524 Ok(r) => {
525 tasks.extend(r);
526 info!("New pool actor started")
527 }
528 Err(e) => {
529 panic!("NewPoolLoaderActor : {e}")
530 }
531 }
532 }
533
534 info!("Starting pool loader actor {name}");
535 let mut pool_loader_actor = PoolLoaderActor::new(client.clone(), pool_loaders.clone(), PoolsLoadingConfig::new());
536 match pool_loader_actor
537 .access(blockchain.market())
538 .access(blockchain_state.market_state())
539 .consume(blockchain.tasks_channel())
540 .produce(blockchain.market_events_channel())
541 .start()
542 {
543 Ok(r) => {
544 tasks.extend(r);
545 info!("Pool loader actor started successfully")
546 }
547 Err(e) => {
548 panic!("PoolLoaderActor : {e}")
549 }
550 }
551 }
552 } else {
553 warn!("No pool loader actors in config")
554 }
555
556 if let Some(estimator_actors) = &self.config.actors.estimator {
557 for (name, params) in estimator_actors {
558 match params {
559 EstimatorConfig::Evm(params) => {
560 let client = params.client.as_ref().map(|x| self.get_client(Some(x))).transpose()?; let blockchain = self.get_blockchain(params.blockchain.as_ref())?;
563 let strategy = self.get_strategy(params.blockchain.as_ref())?;
564 let multicaller_address = self.get_multicaller_address(params.encoder.as_ref())?;
565
566 let mut encoder = self.swap_encoder.clone();
567 encoder.set_address(multicaller_address);
568
569 let mut evm_estimator_actor = EvmEstimatorActor::new_with_provider(encoder, client);
570 match evm_estimator_actor
571 .consume(strategy.swap_compose_channel())
572 .produce(strategy.swap_compose_channel())
573 .produce(blockchain.health_monitor_channel())
574 .produce(blockchain.influxdb_write_channel())
575 .start()
576 {
577 Ok(r) => {
578 tasks.extend(r);
579 info!("EVM estimator actor started successfully {name} @ {}", blockchain.chain_id())
580 }
581 Err(e) => {
582 panic!("Error starting EVM estimator actor {name} @ {} : {}", blockchain.chain_id(), e)
583 }
584 }
585 }
586 EstimatorConfig::Geth(params) => {
587 let client = self.get_client(params.client.as_ref())?;
588 let blockchain = self.get_blockchain(params.blockchain.as_ref())?;
589 let strategy = self.get_strategy(params.blockchain.as_ref())?;
590 let multicaller_address = self.get_multicaller_address(params.encoder.as_ref())?;
591
592 let mut encoder = self.swap_encoder.clone();
593 encoder.set_address(multicaller_address);
594
595 let flashbots_client = Arc::new(Flashbots::new(client, "https://relay.flashbots.net", None).with_default_relays());
596
597 let mut geth_estimator_actor = GethEstimatorActor::new(flashbots_client, encoder);
598 match geth_estimator_actor.consume(strategy.swap_compose_channel()).produce(strategy.swap_compose_channel()).start()
599 {
600 Ok(r) => {
601 tasks.extend(r);
602 info!("Geth estimator actor started successfully {name} @ {}", blockchain.chain_id())
603 }
604 Err(e) => {
605 panic!("Error starting Geth estimator actor for {name} @ {} : {}", blockchain.chain_id(), e)
606 }
607 }
608 }
609 }
610 }
611 } else {
612 warn!("No estimator actors in config")
613 }
614
615 Ok(tasks)
616 }
617
618 pub fn get_client(&self, name: Option<&String>) -> Result<RootProvider> {
619 match self.clients.get(name.unwrap_or(&"local".to_string())) {
620 Some(a) => Ok(a.clone()),
621 None => Err(eyre!("CLIENT_NOT_FOUND")),
622 }
623 }
624
625 pub fn get_client_config(&self, name: Option<&String>) -> Result<ClientConfig> {
626 match self.config.clients.get(name.unwrap_or(&"local".to_string())) {
627 Some(a) => Ok(a.clone()),
628 None => Err(eyre!("CLIENT_NOT_FOUND")),
629 }
630 }
631
632 pub fn get_blockchain(&self, name: Option<&String>) -> Result<&Blockchain> {
633 match self.blockchains.get(name.unwrap_or(&self.default_blockchain_name.clone().unwrap())) {
634 Some(a) => Ok(a),
635 None => Err(eyre!("BLOCKCHAIN_NOT_FOUND")),
636 }
637 }
638
639 pub fn get_blockchain_state(&self, name: Option<&String>) -> Result<&BlockchainState<DB, KabuDataTypesEthereum>> {
640 match self.blockchain_states.get(name.unwrap_or(&self.default_blockchain_name.clone().unwrap())) {
641 Some(a) => Ok(a),
642 None => Err(eyre!("BLOCKCHAIN_NOT_FOUND")),
643 }
644 }
645
646 pub fn get_strategy(&self, name: Option<&String>) -> Result<&Strategy<DB>> {
647 match self.strategies.get(name.unwrap_or(&self.default_blockchain_name.clone().unwrap())) {
648 Some(a) => Ok(a),
649 None => Err(eyre!("BLOCKCHAIN_NOT_FOUND")),
650 }
651 }
652
653 pub fn get_multicaller_address(&self, name: Option<&String>) -> Result<Address> {
654 match self.multicaller_encoders.get(name.unwrap_or(&self.default_multicaller_encoder_name.clone().unwrap())) {
655 Some(multicaller_address) => Ok(*multicaller_address),
656 None => Err(eyre!("ENCODER_NOT_FOUND")),
657 }
658 }
659
660 pub fn get_signers(&self, name: Option<&String>) -> Result<SharedState<TxSigners>> {
661 match self.signers.get(name.unwrap_or(&self.default_multicaller_encoder_name.clone().unwrap())) {
662 Some(a) => Ok(a.clone()),
663 None => Err(eyre!("SIGNERS_NOT_FOUND")),
664 }
665 }
666 pub fn get_blockchain_mut(&mut self, name: Option<&String>) -> Result<&mut Blockchain> {
667 match self.blockchains.get_mut(name.unwrap_or(&self.default_blockchain_name.clone().unwrap())) {
668 Some(a) => Ok(a),
669 None => Err(eyre!("CLIENT_NOT_FOUND")),
670 }
671 }
672}