1use std::{fmt::Debug, marker::PhantomData};
2
3use alloy_contract::CallBuilder;
4use alloy_network::Ethereum;
5use alloy_primitives::{Address, Bytes, U256};
6use alloy_provider::Provider;
7use alloy_sol_types::{sol, SolInterface};
8use OdosRouterV2::{inputTokenInfo, outputTokenInfo, swapTokenInfo};
9use OdosV2Router::{swapCall, OdosV2RouterCalls, OdosV2RouterInstance, Swap, SwapMulti};
10
11use crate::SwapInputs;
12
13#[derive(Debug, Clone)]
15pub struct V2Router<P: Provider<Ethereum>> {
16 instance: OdosV2RouterInstance<P>,
17}
18
19impl<P: Provider<Ethereum>> V2Router<P> {
20 pub fn new(address: Address, provider: P) -> Self {
21 Self {
22 instance: OdosV2RouterInstance::new(address, provider),
23 }
24 }
25
26 pub async fn owner(&self) -> Result<Address, alloy_contract::Error> {
27 self.instance.owner().call().await
28 }
29
30 pub fn build_swap_router_funds_call(
31 &self,
32 input_token_info: inputTokenInfo,
33 output_token_info: outputTokenInfo,
34 inputs: &SwapInputs,
35 from: Address,
36 ) -> CallBuilder<&P, PhantomData<OdosV2Router::swapRouterFundsCall>> {
37 self.instance
38 .swapRouterFunds(
39 vec![input_token_info],
40 vec![output_token_info],
41 inputs.value_out_min(),
42 inputs.path_definition().clone(),
43 inputs.executor(),
44 )
45 .from(from)
46 }
47
48 pub fn transfer_router_funds(
49 &self,
50 from: Address,
51 token: Address,
52 amount: U256,
53 output_recipient: Address,
54 ) -> CallBuilder<&P, PhantomData<OdosV2Router::transferRouterFundsCall>> {
55 self.instance
56 .transferRouterFunds(vec![token], vec![amount], output_recipient)
57 .from(from)
58 }
59
60 pub fn transfer_router_funds_calldata(
61 &self,
62 from: Address,
63 token: Address,
64 amount: U256,
65 output_recipient: Address,
66 ) -> Vec<u8> {
67 self.transfer_router_funds(from, token, amount, output_recipient)
68 .calldata()
69 .to_vec()
70 }
71}
72
73sol!(
75 #[allow(clippy::too_many_arguments)]
76 #[allow(missing_docs)]
77 #[sol(rpc)]
78 OdosV2Router,
79 "abis/odos_v2_router.json"
80);
81
82impl Debug for OdosV2Router::swapRouterFundsReturn {
83 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84 write!(f, "amountsOut: {:?}", self.amountsOut)
85 }
86}
87
88impl Debug for OdosRouterV2::inputTokenInfo {
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90 f.debug_struct("inputTokenInfo")
91 .field("tokenAddress", &self.tokenAddress)
92 .field("amountIn", &self.amountIn)
93 .field("receiver", &self.receiver)
94 .finish()
95 }
96}
97
98impl Debug for OdosRouterV2::outputTokenInfo {
99 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100 f.debug_struct("outputTokenInfo")
101 .field("tokenAddress", &self.tokenAddress)
102 .field("relativeValue", &self.relativeValue)
103 .field("receiver", &self.receiver)
104 .finish()
105 }
106}
107
108impl Debug for swapCall {
109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110 f.debug_struct("swapCall")
111 .field("executor", &self.executor)
112 .field("pathDefinition", &self.pathDefinition)
113 .field("referralCode", &self.referralCode)
114 .field("tokenInfo", &self.tokenInfo)
115 .finish()
116 }
117}
118
119impl Debug for swapTokenInfo {
120 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121 f.debug_struct("swapTokenInfo")
122 .field("inputToken", &self.inputToken)
123 .field("inputAmount", &self.inputAmount)
124 .field("inputReceiver", &self.inputReceiver)
125 .field("outputMin", &self.outputMin)
126 .field("outputQuote", &self.outputQuote)
127 .field("outputReceiver", &self.outputReceiver)
128 .finish()
129 }
130}
131
132impl Debug for SwapMulti {
133 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
134 f.debug_struct("SwapMulti")
135 .field("sender", &self.sender)
136 .field("amountsIn", &self.amountsIn)
137 .field("tokensIn", &self.tokensIn)
138 .field("amountsOut", &self.amountsOut)
139 .field("tokensOut", &self.tokensOut)
140 .finish()
141 }
142}
143
144impl Debug for Swap {
145 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146 f.debug_struct("Swap")
147 .field("sender", &self.sender)
148 .field("inputAmount", &self.inputAmount)
149 .field("inputToken", &self.inputToken)
150 .field("amountOut", &self.amountOut)
151 .field("outputToken", &self.outputToken)
152 .field("slippage", &self.slippage)
153 .field("referralCode", &self.referralCode)
154 .finish()
155 }
156}
157
158impl TryFrom<&Bytes> for OdosV2RouterCalls {
159 type Error = alloy_sol_types::Error;
160
161 fn try_from(input: &Bytes) -> Result<Self, Self::Error> {
162 OdosV2RouterCalls::abi_decode(input)
163 }
164}