1use std::{fmt::Debug, marker::PhantomData};
6
7use alloy_contract::CallBuilder;
8use alloy_network::{Ethereum, Network};
9use alloy_primitives::{Address, Bytes, U256};
10use alloy_provider::Provider;
11use alloy_sol_types::{sol, SolInterface};
12
13use crate::SwapInputs;
14
15use OdosRouterV2::{inputTokenInfo, outputTokenInfo, swapTokenInfo};
17use OdosV2Router::{swapCall, OdosV2RouterCalls, OdosV2RouterInstance, Swap, SwapMulti};
18
19#[derive(Debug, Clone)]
51pub struct V2Router<N: Network = Ethereum, P: Provider<N> = alloy_provider::RootProvider<N>> {
52 instance: OdosV2RouterInstance<P, N>,
53}
54
55impl<N: Network, P: Provider<N>> V2Router<N, P> {
56 pub fn new(address: Address, provider: P) -> Self {
58 Self {
59 instance: OdosV2RouterInstance::new(address, provider),
60 }
61 }
62
63 pub async fn owner(&self) -> Result<Address, alloy_contract::Error> {
65 self.instance.owner().call().await
66 }
67
68 pub fn build_swap_router_funds_call(
70 &self,
71 input_token_info: inputTokenInfo,
72 output_token_info: outputTokenInfo,
73 inputs: &SwapInputs,
74 from: Address,
75 ) -> CallBuilder<&P, PhantomData<OdosV2Router::swapRouterFundsCall>, N> {
76 self.instance
77 .swapRouterFunds(
78 vec![input_token_info],
79 vec![output_token_info],
80 inputs.value_out_min(),
81 inputs.path_definition().clone(),
82 inputs.executor(),
83 )
84 .from(from)
85 }
86
87 pub fn transfer_router_funds(
89 &self,
90 from: Address,
91 token: Address,
92 amount: U256,
93 output_recipient: Address,
94 ) -> CallBuilder<&P, PhantomData<OdosV2Router::transferRouterFundsCall>, N> {
95 self.instance
96 .transferRouterFunds(vec![token], vec![amount], output_recipient)
97 .from(from)
98 }
99
100 pub fn transfer_router_funds_calldata(
102 &self,
103 from: Address,
104 token: Address,
105 amount: U256,
106 output_recipient: Address,
107 ) -> Vec<u8> {
108 self.transfer_router_funds(from, token, amount, output_recipient)
109 .calldata()
110 .to_vec()
111 }
112}
113
114sol!(
116 #[allow(clippy::too_many_arguments)]
117 #[allow(missing_docs)]
118 #[sol(rpc)]
119 OdosV2Router,
120 "abis/odos_v2_router.json"
121);
122
123impl Debug for OdosV2Router::swapRouterFundsReturn {
124 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
125 write!(f, "amountsOut: {:?}", self.amountsOut)
126 }
127}
128
129impl Debug for OdosRouterV2::inputTokenInfo {
130 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131 f.debug_struct("inputTokenInfo")
132 .field("tokenAddress", &self.tokenAddress)
133 .field("amountIn", &self.amountIn)
134 .field("receiver", &self.receiver)
135 .finish()
136 }
137}
138
139impl Debug for OdosRouterV2::outputTokenInfo {
140 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141 f.debug_struct("outputTokenInfo")
142 .field("tokenAddress", &self.tokenAddress)
143 .field("relativeValue", &self.relativeValue)
144 .field("receiver", &self.receiver)
145 .finish()
146 }
147}
148
149impl Debug for swapCall {
150 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
151 f.debug_struct("swapCall")
152 .field("executor", &self.executor)
153 .field("pathDefinition", &self.pathDefinition)
154 .field("referralCode", &self.referralCode)
155 .field("tokenInfo", &self.tokenInfo)
156 .finish()
157 }
158}
159
160impl Debug for swapTokenInfo {
161 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
162 f.debug_struct("swapTokenInfo")
163 .field("inputToken", &self.inputToken)
164 .field("inputAmount", &self.inputAmount)
165 .field("inputReceiver", &self.inputReceiver)
166 .field("outputMin", &self.outputMin)
167 .field("outputQuote", &self.outputQuote)
168 .field("outputReceiver", &self.outputReceiver)
169 .finish()
170 }
171}
172
173impl Debug for SwapMulti {
174 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
175 f.debug_struct("SwapMulti")
176 .field("sender", &self.sender)
177 .field("amountsIn", &self.amountsIn)
178 .field("tokensIn", &self.tokensIn)
179 .field("amountsOut", &self.amountsOut)
180 .field("tokensOut", &self.tokensOut)
181 .finish()
182 }
183}
184
185impl Debug for Swap {
186 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
187 f.debug_struct("Swap")
188 .field("sender", &self.sender)
189 .field("inputAmount", &self.inputAmount)
190 .field("inputToken", &self.inputToken)
191 .field("amountOut", &self.amountOut)
192 .field("outputToken", &self.outputToken)
193 .field("slippage", &self.slippage)
194 .field("referralCode", &self.referralCode)
195 .finish()
196 }
197}
198
199impl TryFrom<&Bytes> for OdosV2RouterCalls {
200 type Error = alloy_sol_types::Error;
201
202 fn try_from(input: &Bytes) -> Result<Self, Self::Error> {
203 OdosV2RouterCalls::abi_decode(input)
204 }
205}