1pub mod abi;
2pub mod events;
3pub mod global;
4pub mod liquidity;
5pub mod price;
6pub mod tool;
7pub mod types;
8use crate::abi::{IPool, IPoolManager};
9use crate::analyze::FarmAnalyzer;
10use crate::events::{FarmEventListener, UniswapEventListener};
11use crate::farm::FarmService;
12use crate::router::Router;
13use crate::tool::address::str_to_address;
14use crate::tool::cal_price_from_sqrt_price_x96;
15use crate::types::{PairCreatedEvent, SwapEvent, TickInfo, V4PoolInfo, V4PositionInfo};
16use ethers::providers::Provider;
17use ethers::signers::Signer;
18use ethers::types::Bytes;
19use ethers::types::{Address, H256, U256};
20use evm_client::EvmType;
21use evm_sdk::Evm;
22use std::sync::Arc;
23pub mod analyze;
24pub mod factory;
25pub mod farm;
26pub mod oracle;
27pub mod risk;
28pub mod router;
29use evm_sdk::types::EvmError;
30
31pub struct UniswapService {
33 evm: Arc<Evm>,
34 router: Router,
35}
36
37impl UniswapService {
38 pub fn new(evm: Arc<Evm>) -> Self {
40 Self {
41 evm: evm.clone(),
42 router: Router::new(evm),
43 }
44 }
45
46 pub fn farm_service(&self) -> FarmService {
48 FarmService::new(self.evm.clone())
49 }
50
51 pub fn farm_analyzer(&self) -> FarmAnalyzer {
53 FarmAnalyzer::new(self.evm.clone())
54 }
55
56 pub fn farm_event_listener(&self) -> FarmEventListener {
58 FarmEventListener::new(self.evm.clone())
59 }
60
61 pub async fn get_amounts_out(
74 &self,
75 router_address: Address,
76 amount_in: U256,
77 path: Vec<Address>,
78 ) -> Result<Vec<U256>, EvmError> {
79 let router = self.router.v2_router(router_address);
80 router
81 .get_amounts_out(amount_in, path)
82 .call()
83 .await
84 .map_err(|e| EvmError::ContractError(format!("Failed to get amounts out: {}", e)))
85 }
86
87 pub async fn get_amounts_in(
100 &self,
101 router_address: Address,
102 amount_out: U256,
103 path: Vec<Address>,
104 ) -> Result<Vec<U256>, EvmError> {
105 let router = self.router.v2_router(router_address);
106 router
107 .get_amounts_in(amount_out, path)
108 .call()
109 .await
110 .map_err(|e| EvmError::ContractError(format!("Failed to get amounts in: {}", e)))
111 }
112
113 pub async fn swap_exact_tokens_for_tokens(
128 &self,
129 router_address: Address,
130 amount_in: U256,
131 amount_out_min: U256,
132 path: Vec<Address>,
133 deadline: u64,
134 ) -> Result<H256, EvmError> {
135 if self.evm.client.wallet.is_none() {
136 return Err(EvmError::WalletError("No wallet configured".to_string()));
137 }
138 let wallet_address = self.evm.client.wallet.as_ref().unwrap().address();
139 let router = self.router.v2_router(router_address);
140 let tx = router.swap_exact_tokens_for_tokens(
141 amount_in,
142 amount_out_min,
143 path,
144 wallet_address,
145 deadline.into(),
146 );
147 let pending_tx = tx
148 .send()
149 .await
150 .map_err(|e| EvmError::TransactionError(format!("Failed to swap tokens: {}", e)))?;
151 Ok(pending_tx.tx_hash())
152 }
153
154 pub async fn swap_exact_eth_for_tokens(
169 &self,
170 router_address: Address,
171 amount_out_min: U256,
172 path: Vec<Address>,
173 value: U256,
174 deadline: u64,
175 ) -> Result<H256, EvmError> {
176 if self.evm.client.wallet.is_none() {
177 return Err(EvmError::WalletError("No wallet configured".to_string()));
178 }
179 let wallet_address = self.evm.client.wallet.as_ref().unwrap().address();
180 let router = self.router.v2_router(router_address);
181 let tx = router
182 .swap_exact_eth_for_tokens(amount_out_min, path, wallet_address, deadline.into())
183 .value(value);
184 let pending_tx = tx.send().await.map_err(|e| {
185 EvmError::TransactionError(format!("Failed to swap ETH for tokens: {}", e))
186 })?;
187 Ok(pending_tx.tx_hash())
188 }
189
190 pub async fn swap_exact_tokens_for_eth(
205 &self,
206 router_address: Address,
207 amount_in: U256,
208 amount_out_min: U256,
209 path: Vec<Address>,
210 deadline: u64,
211 ) -> Result<H256, EvmError> {
212 if self.evm.client.wallet.is_none() {
213 return Err(EvmError::WalletError("No wallet configured".to_string()));
214 }
215 let wallet_address = self.evm.client.wallet.as_ref().unwrap().address();
216 let router = self.router.v2_router(router_address);
217 let tx = router.swap_exact_tokens_for_eth(
218 amount_in,
219 amount_out_min,
220 path,
221 wallet_address,
222 deadline.into(),
223 );
224 let pending_tx = tx.send().await.map_err(|e| {
225 EvmError::TransactionError(format!("Failed to swap tokens for ETH: {}", e))
226 })?;
227 Ok(pending_tx.tx_hash())
228 }
229
230 pub async fn add_liquidity(
248 &self,
249 router_address: Address,
250 token_a: Address,
251 token_b: Address,
252 amount_a_desired: U256,
253 amount_b_desired: U256,
254 amount_a_min: U256,
255 amount_b_min: U256,
256 deadline: u64,
257 ) -> Result<H256, EvmError> {
258 if self.evm.client.wallet.is_none() {
259 return Err(EvmError::WalletError("No wallet configured".to_string()));
260 }
261 let wallet_address = self.evm.client.wallet.as_ref().unwrap().address();
262 let router = self.router.v2_router(router_address);
263 let tx = router.add_liquidity(
264 token_a,
265 token_b,
266 amount_a_desired,
267 amount_b_desired,
268 amount_a_min,
269 amount_b_min,
270 wallet_address,
271 deadline.into(),
272 );
273 let pending_tx = tx
274 .send()
275 .await
276 .map_err(|e| EvmError::TransactionError(format!("Failed to add liquidity: {}", e)))?;
277 Ok(pending_tx.tx_hash())
278 }
279
280 pub async fn add_liquidity_eth(
297 &self,
298 router_address: Address,
299 token: Address,
300 amount_token_desired: U256,
301 amount_token_min: U256,
302 amount_eth_min: U256,
303 value: U256,
304 deadline: u64,
305 ) -> Result<H256, EvmError> {
306 if self.evm.client.wallet.is_none() {
307 return Err(EvmError::WalletError("No wallet configured".to_string()));
308 }
309 let wallet_address = self.evm.client.wallet.as_ref().unwrap().address();
310 let router = self.router.v2_router(router_address);
311 let tx = router
312 .add_liquidity_eth(
313 token,
314 amount_token_desired,
315 amount_token_min,
316 amount_eth_min,
317 wallet_address,
318 deadline.into(),
319 )
320 .value(value);
321 let pending_tx = tx.send().await.map_err(|e| {
322 EvmError::TransactionError(format!("Failed to add liquidity with ETH: {}", e))
323 })?;
324 Ok(pending_tx.tx_hash())
325 }
326
327 pub async fn exact_input_single(
345 &self,
346 router_address: Address,
347 token_in: Address,
348 token_out: Address,
349 fee: u32,
350 amount_in: U256,
351 amount_out_min: U256,
352 sqrt_price_limit_x96: U256,
353 deadline: u64,
354 ) -> Result<H256, EvmError> {
355 if self.evm.client.wallet.is_none() {
356 return Err(EvmError::WalletError("No wallet configured".to_string()));
357 }
358 let wallet_address = self.evm.client.wallet.as_ref().unwrap().address();
359 let router = self.router.v3_router(router_address);
360 let tx = router.exact_input_single(
361 token_in,
362 token_out,
363 fee,
364 wallet_address,
365 deadline.into(),
366 amount_in,
367 amount_out_min,
368 sqrt_price_limit_x96.into(),
369 );
370 let pending_tx = tx.send().await.map_err(|e| {
371 EvmError::TransactionError(format!("Failed to execute exact input single: {}", e))
372 })?;
373 Ok(pending_tx.tx_hash())
374 }
375
376 pub async fn exact_input(
378 &self,
379 router_address: Address,
380 path: Bytes,
381 amount_in: U256,
382 amount_out_min: U256,
383 deadline: u64,
384 ) -> Result<H256, EvmError> {
385 if self.evm.client.wallet.is_none() {
386 return Err(EvmError::WalletError("No wallet configured".to_string()));
387 }
388 let wallet_address = self.evm.client.wallet.as_ref().unwrap().address();
389 let router = self.router.v3_router(router_address);
390 let tx = router.exact_input(
391 path,
392 wallet_address,
393 deadline.into(),
394 amount_in,
395 amount_out_min,
396 );
397 let pending_tx = tx.send().await.map_err(|e| {
398 EvmError::TransactionError(format!("Failed to execute exact input: {}", e))
399 })?;
400 Ok(pending_tx.tx_hash())
401 }
402
403 pub async fn exact_output_single(
405 &self,
406 router_address: Address,
407 token_in: Address,
408 token_out: Address,
409 fee: u32,
410 amount_out: U256,
411 amount_in_max: U256,
412 sqrt_price_limit_x96: U256,
413 deadline: u64,
414 ) -> Result<H256, EvmError> {
415 if self.evm.client.wallet.is_none() {
416 return Err(EvmError::WalletError("No wallet configured".to_string()));
417 }
418 let wallet_address = self.evm.client.wallet.as_ref().unwrap().address();
419 let router = self.router.v3_router(router_address);
420 let tx = router.exact_output_single(
421 token_in,
422 token_out,
423 fee,
424 wallet_address,
425 deadline.into(),
426 amount_out,
427 amount_in_max,
428 sqrt_price_limit_x96.into(),
429 );
430 let pending_tx = tx.send().await.map_err(|e| {
431 EvmError::TransactionError(format!("Failed to execute exact output single: {}", e))
432 })?;
433 Ok(pending_tx.tx_hash())
434 }
435
436 pub async fn remove_liquidity(
453 &self,
454 router_address: Address,
455 token_a: Address,
456 token_b: Address,
457 liquidity: U256,
458 amount_a_min: U256,
459 amount_b_min: U256,
460 deadline: u64,
461 ) -> Result<H256, EvmError> {
462 if self.evm.client.wallet.is_none() {
463 return Err(EvmError::WalletError("No wallet configured".to_string()));
464 }
465 let wallet_address = self.evm.client.wallet.as_ref().unwrap().address();
466 let router = self.router.v2_router(router_address);
467 let tx = router.remove_liquidity(
468 token_a,
469 token_b,
470 liquidity,
471 amount_a_min,
472 amount_b_min,
473 wallet_address,
474 deadline.into(),
475 );
476 let pending_tx = tx.send().await.map_err(|e| {
477 EvmError::TransactionError(format!("Failed to remove liquidity: {}", e))
478 })?;
479 Ok(pending_tx.tx_hash())
480 }
481
482 pub async fn remove_liquidity_eth(
498 &self,
499 router_address: Address,
500 token: Address,
501 liquidity: U256,
502 amount_token_min: U256,
503 amount_eth_min: U256,
504 deadline: u64,
505 ) -> Result<H256, EvmError> {
506 if self.evm.client.wallet.is_none() {
507 return Err(EvmError::WalletError("No wallet configured".to_string()));
508 }
509 let wallet_address = self.evm.client.wallet.as_ref().unwrap().address();
510 let router = self.router.v2_router(router_address);
511 let tx = router.remove_liquidity_eth(
512 token,
513 liquidity,
514 amount_token_min,
515 amount_eth_min,
516 wallet_address,
517 deadline.into(),
518 );
519 let pending_tx = tx.send().await.map_err(|e| {
520 EvmError::TransactionError(format!("Failed to remove liquidity with ETH: {}", e))
521 })?;
522 Ok(pending_tx.tx_hash())
523 }
524
525 pub fn event_listener(&self) -> UniswapEventListener {
526 UniswapEventListener::new(self.evm.clone())
527 }
528
529 pub async fn start_monitoring_swaps(
541 &self,
542 pair_addresses: Vec<Address>,
543 on_swap: impl Fn(SwapEvent) + Send + Sync + 'static,
544 ) -> Result<(), EvmError> {
545 self.event_listener()
546 .start_swap_listener(pair_addresses, on_swap)
547 .await
548 }
549
550 pub async fn start_monitoring_new_pairs(
562 &self,
563 factory_address: Address,
564 on_pair_created: impl Fn(PairCreatedEvent) + Send + Sync + 'static,
565 ) -> Result<(), EvmError> {
566 self.event_listener()
567 .start_pair_created_listener(vec![factory_address], on_pair_created)
568 .await
569 }
570}
571
572pub struct UniswapV4Service {
574 evm: Arc<Evm>,
575}
576
577impl UniswapV4Service {
578 pub fn new(evm: Arc<Evm>) -> Self {
580 Self { evm: evm }
581 }
582
583 fn pool_manager(
584 &self,
585 manager_address: Address,
586 ) -> IPoolManager<Provider<ethers::providers::Http>> {
587 IPoolManager::new(manager_address, self.evm.client.provider.clone())
588 }
589
590 fn v4_pool(&self, pool_address: Address) -> IPool<Provider<ethers::providers::Http>> {
591 IPool::new(pool_address, self.evm.client.provider.clone())
592 }
593
594 pub async fn initialize_pool(
612 &self,
613 manager_address: Address,
614 currency0: Address,
615 currency1: Address,
616 fee: u32,
617 tick_spacing: i32,
618 hooks: Address,
619 sqrt_price_x96: U256,
620 hook_data: Vec<u8>,
621 ) -> Result<Address, EvmError> {
622 if self.evm.client.wallet.is_none() {
623 return Err(EvmError::WalletError("No wallet configured".to_string()));
624 }
625 let pool_manager = self.pool_manager(manager_address);
626 let tx = pool_manager.initialize(
627 currency0,
628 currency1,
629 fee,
630 tick_spacing,
631 hooks,
632 sqrt_price_x96.into(),
633 hook_data.into(),
634 );
635 let pending_tx = tx.send().await.map_err(|e| {
636 EvmError::TransactionError(format!("Failed to initialize V4 pool: {}", e))
637 })?;
638 let receipt = pending_tx.await.map_err(|e| {
639 EvmError::TransactionError(format!("Failed to get transaction receipt: {}", e))
640 })?;
641 if let Some(log) = receipt.unwrap().logs.first() {
642 Ok(log.address)
643 } else {
644 Err(EvmError::ContractError(
645 "Failed to parse pool address from logs".to_string(),
646 ))
647 }
648 }
649
650 pub async fn swap(
668 &self,
669 manager_address: Address,
670 currency0: Address,
671 currency1: Address,
672 fee: u32,
673 tick_spacing: i32,
674 hooks: Address,
675 zero_for_one: bool,
676 amount_specified: i128,
677 sqrt_price_limit_x96: U256,
678 hook_data: Vec<u8>,
679 ) -> Result<(i128, i128), EvmError> {
680 if self.evm.client.wallet.is_none() {
681 return Err(EvmError::WalletError("No wallet configured".to_string()));
682 }
683 let pool_manager = self.pool_manager(manager_address);
684 let tx = pool_manager.swap(
685 currency0,
686 currency1,
687 fee,
688 tick_spacing,
689 hooks,
690 zero_for_one,
691 amount_specified.into(),
692 sqrt_price_limit_x96.into(),
693 hook_data.into(),
694 );
695 let result = tx
696 .call()
697 .await
698 .map_err(|e| EvmError::ContractError(format!("Failed to execute V4 swap: {}", e)))?;
699 Ok((result.0.as_i128(), result.1.as_i128()))
700 }
701
702 pub async fn modify_position(
720 &self,
721 manager_address: Address,
722 currency0: Address,
723 currency1: Address,
724 fee: u32,
725 tick_spacing: i32,
726 hooks: Address,
727 tick_lower: i32,
728 tick_upper: i32,
729 liquidity_delta: i128,
730 hook_data: Vec<u8>,
731 ) -> Result<(i128, i128), EvmError> {
732 if self.evm.client.wallet.is_none() {
733 return Err(EvmError::WalletError("No wallet configured".to_string()));
734 }
735 let pool_manager = self.pool_manager(manager_address);
736 let tx = pool_manager.modify_position(
737 currency0,
738 currency1,
739 fee,
740 tick_spacing,
741 hooks,
742 tick_lower,
743 tick_upper,
744 liquidity_delta.into(),
745 hook_data.into(),
746 );
747 let result = tx
748 .call()
749 .await
750 .map_err(|e| EvmError::ContractError(format!("Failed to modify V4 position: {}", e)))?;
751 Ok((result.0.as_i128(), result.1.as_i128()))
752 }
753
754 pub async fn get_pool_address(
768 &self,
769 manager_address: Address,
770 currency0: Address,
771 currency1: Address,
772 fee: u32,
773 tick_spacing: i32,
774 hooks: Address,
775 ) -> Result<Address, EvmError> {
776 let pool_manager = self.pool_manager(manager_address);
777 let pool_address = pool_manager
778 .get_pool(currency0, currency1, fee, tick_spacing, hooks)
779 .call()
780 .await
781 .map_err(|e| EvmError::ContractError(format!("Failed to get pool address: {}", e)))?;
782 Ok(pool_address)
783 }
784
785 pub async fn get_pool_info(&self, pool_address: Address) -> Result<V4PoolInfo, EvmError> {
794 let pool = self.v4_pool(pool_address);
795 let slot0 = pool
796 .slot_0()
797 .call()
798 .await
799 .map_err(|e| EvmError::ContractError(format!("Failed to get pool slot0: {}", e)))?;
800 let liquidity =
801 pool.liquidity().call().await.map_err(|e| {
802 EvmError::ContractError(format!("Failed to get pool liquidity: {}", e))
803 })?;
804 let fee_growth_global0_x128 = pool.fee_growth_global_0x128().call().await.map_err(|e| {
805 EvmError::ContractError(format!("Failed to get fee growth global0: {}", e))
806 })?;
807
808 let fee_growth_global1_x128 = pool.fee_growth_global_1x128().call().await.map_err(|e| {
809 EvmError::ContractError(format!("Failed to get fee growth global1: {}", e))
810 })?;
811 let protocol_fees =
812 pool.protocol_fees().call().await.map_err(|e| {
813 EvmError::ContractError(format!("Failed to get protocol fees: {}", e))
814 })?;
815 Ok(V4PoolInfo {
816 pool_address,
817 currency0: Address::zero(),
818 currency1: Address::zero(),
819 fee: 0,
820 tick_spacing: 0,
821 hooks: Address::zero(),
822 sqrt_price_x96: slot0.0.into(),
823 current_tick: slot0.1,
824 liquidity: liquidity.into(),
825 fee_growth_global0_x128,
826 fee_growth_global1_x128,
827 protocol_fees_token0: protocol_fees.0.into(),
828 protocol_fees_token1: protocol_fees.1.into(),
829 })
830 }
831
832 pub async fn get_pool_price(&self, pool_address: Address) -> Result<f64, EvmError> {
840 let pool = self.v4_pool(pool_address);
841 let slot0 = pool
842 .slot_0()
843 .call()
844 .await
845 .map_err(|e| EvmError::ContractError(format!("Failed to get pool slot0: {}", e)))?;
846 let price = cal_price_from_sqrt_price_x96(slot0.0.into());
847 Ok(price)
848 }
849
850 pub async fn donate(
852 &self,
853 manager_address: Address,
854 currency0: Address,
855 currency1: Address,
856 fee: u32,
857 tick_spacing: i32,
858 hooks: Address,
859 amount0: U256,
860 amount1: U256,
861 hook_data: Vec<u8>,
862 ) -> Result<(i128, i128), EvmError> {
863 if self.evm.client.wallet.is_none() {
864 return Err(EvmError::WalletError("No wallet configured".to_string()));
865 }
866 let pool_manager = self.pool_manager(manager_address);
867 let tx = pool_manager.donate(
868 currency0,
869 currency1,
870 fee,
871 tick_spacing,
872 hooks,
873 amount0,
874 amount1,
875 hook_data.into(),
876 );
877 let result = tx
878 .call()
879 .await
880 .map_err(|e| EvmError::ContractError(format!("Failed to donate to V4 pool: {}", e)))?;
881
882 Ok((result.0.as_i128(), result.1.as_i128()))
883 }
884
885 pub async fn settle(
887 &self,
888 manager_address: Address,
889 currency: Address,
890 ) -> Result<U256, EvmError> {
891 if self.evm.client.wallet.is_none() {
892 return Err(EvmError::WalletError("No wallet configured".to_string()));
893 }
894 let pool_manager = self.pool_manager(manager_address);
895 let tx = pool_manager.settle(currency);
896 let result = tx
897 .call()
898 .await
899 .map_err(|e| EvmError::ContractError(format!("Failed to settle currency: {}", e)))?;
900 Ok(result)
901 }
902
903 pub async fn get_currency_balance(
905 &self,
906 manager_address: Address,
907 account: Address,
908 currency: Address,
909 ) -> Result<U256, EvmError> {
910 let pool_manager = self.pool_manager(manager_address);
911 let balance = U256::zero();
912 todo!();
913 Ok(balance)
914 }
915
916 pub async fn get_position_info(
924 &self,
925 pool_address: Address,
926 position_key: [u8; 32],
927 ) -> Result<V4PositionInfo, EvmError> {
928 let pool = self.v4_pool(pool_address);
929 let position = pool
930 .positions(position_key.into())
931 .call()
932 .await
933 .map_err(|e| EvmError::ContractError(format!("Failed to get position info: {}", e)))?;
934 Ok(V4PositionInfo {
935 position_key: position_key.into(),
936 owner: Address::zero(),
937 liquidity: position.0.into(),
938 fee_growth_inside0_last_x128: position.1,
939 fee_growth_inside1_last_x128: position.2,
940 tokens_owed0: position.3.into(),
941 tokens_owed1: position.4.into(),
942 })
943 }
944
945 pub async fn get_tick_info(
953 &self,
954 pool_address: Address,
955 tick: i32,
956 ) -> Result<TickInfo, EvmError> {
957 let pool = self.v4_pool(pool_address);
958 let tick_info = pool
959 .ticks(tick)
960 .call()
961 .await
962 .map_err(|e| EvmError::ContractError(format!("Failed to get tick info: {}", e)))?;
963 Ok(TickInfo {
964 liquidity_gross: tick_info.0.into(),
965 liquidity_net: tick_info.1 as i128,
966 fee_growth_outside0_x128: tick_info.2,
967 fee_growth_outside1_x128: tick_info.3,
968 tick_cumulative_outside: tick_info.4 as i64,
969 seconds_per_liquidity_outside_x128: tick_info.5,
970 seconds_outside: tick_info.6,
971 initialized: tick_info.7,
972 })
973 }
974}
975
976pub struct UniswapConfig;
977
978impl UniswapConfig {
979 pub fn v2_router_address(chain: EvmType) -> Result<Address, EvmError> {
980 match chain {
981 EvmType::ETHEREUM_MAINNET => Ok(str_to_address(
982 crate::global::ethereum::mainnet::dex::uniswap::ROUTER_V2_ADDRESS,
983 )
984 .unwrap()),
985 EvmType::ARB_MAINNET => Ok(str_to_address(
986 crate::global::arb::mainnet::dex::uniswap::ROUTER_V2_ADDRESS,
987 )
988 .unwrap()),
989 EvmType::BSC_MAINNET => Ok(str_to_address(
990 crate::global::bsc::mainnet::dex::uniswap::ROUTER_V2_ADDRESS,
991 )
992 .unwrap()),
993 EvmType::BASE_MAINNET => Ok(str_to_address(
994 crate::global::base::mainnet::dex::uniswap::ROUTER_V2_ADDRESS,
995 )
996 .unwrap()),
997 _ => Err(EvmError::ConfigError(
998 "Unsupported chain for Uniswap V2".to_string(),
999 )),
1000 }
1001 }
1002
1003 pub fn v2_factory_address(chain: EvmType) -> Result<Address, EvmError> {
1004 match chain {
1005 EvmType::ETHEREUM_MAINNET => {
1006 Ok(str_to_address("0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f").unwrap())
1007 }
1008 EvmType::ARB_MAINNET => {
1009 Ok(str_to_address("0xc35DADB65012eC5796536bD9864eD8773aBc74C4").unwrap())
1010 }
1011 EvmType::BSC_MAINNET => {
1012 Ok(str_to_address("0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73").unwrap())
1013 }
1014 EvmType::BASE_MAINNET => {
1015 Ok(str_to_address("0x8909Dc15e40173Ff4699343b6eB8132c65e18eC6").unwrap())
1016 }
1017 _ => Err(EvmError::ConfigError(
1018 "Unsupported chain for Uniswap V2".to_string(),
1019 )),
1020 }
1021 }
1022
1023 pub fn v3_router_address(chain: EvmType) -> Result<Address, EvmError> {
1024 match chain {
1025 EvmType::ETHEREUM_MAINNET => {
1026 Ok(str_to_address("0xE592427A0AEce92De3Edee1F18E0157C05861564").unwrap())
1027 }
1028 EvmType::ARB_MAINNET => {
1029 Ok(str_to_address("0xE592427A0AEce92De3Edee1F18E0157C05861564").unwrap())
1030 }
1031 EvmType::BSC_MAINNET => {
1032 Ok(str_to_address("0xB971eF87ede563556b2ED4b1C0b0019111Dd85d2").unwrap())
1033 }
1034 EvmType::BASE_MAINNET => {
1035 Ok(str_to_address("0x2626664c2603336E57B271c5C0b26F421741e481").unwrap())
1036 }
1037 _ => Err(EvmError::ConfigError(
1038 "Unsupported chain for Uniswap V3".to_string(),
1039 )),
1040 }
1041 }
1042}