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