tycho_execution/encoding/
models.rs1use clap::ValueEnum;
2use num_bigint::BigUint;
3use serde::{Deserialize, Serialize};
4use tycho_common::{
5 models::protocol::ProtocolComponent, simulation::protocol_sim::ProtocolSim, Bytes,
6};
7
8use crate::encoding::serde_primitives::biguint_string;
9
10#[derive(Clone, Debug, PartialEq, ValueEnum)]
29pub enum UserTransferType {
30 TransferFromPermit2,
31 TransferFrom,
32 None,
33}
34
35#[derive(Clone, Default, Debug, Deserialize, Serialize)]
38pub struct Solution<'a> {
39 pub sender: Bytes,
41 pub receiver: Bytes,
43 pub given_token: Bytes,
45 #[serde(with = "biguint_string")]
47 pub given_amount: BigUint,
48 pub checked_token: Bytes,
50 #[serde(default)]
53 pub exact_out: bool,
54 #[serde(with = "biguint_string")]
56 pub checked_amount: BigUint,
57 pub swaps: Vec<Swap<'a>>,
59 pub native_action: Option<NativeAction>,
61}
62
63#[derive(Clone, PartialEq, Debug, Deserialize, Serialize)]
69#[serde(rename_all = "snake_case")]
70pub enum NativeAction {
71 Wrap,
72 Unwrap,
73}
74
75#[derive(Clone, Debug, Deserialize, Serialize)]
77pub struct Swap<'a> {
78 pub component: ProtocolComponent,
80 pub token_in: Bytes,
82 pub token_out: Bytes,
84 #[serde(default)]
86 pub split: f64,
87 pub user_data: Option<Bytes>,
89 #[serde(skip)]
91 pub protocol_state: Option<&'a dyn ProtocolSim>,
92 pub estimated_amount_in: Option<BigUint>,
95}
96
97impl<'a> Swap<'a> {
98 pub fn new<T: Into<ProtocolComponent>>(
99 component: T,
100 token_in: Bytes,
101 token_out: Bytes,
102 split: f64,
103 user_data: Option<Bytes>,
104 protocol_state: Option<&'a dyn ProtocolSim>,
105 estimated_amount_in: Option<BigUint>,
106 ) -> Self {
107 Self {
108 component: component.into(),
109 token_in,
110 token_out,
111 split,
112 user_data,
113 protocol_state,
114 estimated_amount_in,
115 }
116 }
117}
118
119impl<'a> PartialEq for Swap<'a> {
120 fn eq(&self, other: &Self) -> bool {
121 self.component == other.component &&
122 self.token_in == other.token_in &&
123 self.token_out == other.token_out &&
124 self.split == other.split &&
125 self.user_data == other.user_data
126 }
128}
129
130pub struct SwapBuilder<'a> {
131 component: ProtocolComponent,
132 token_in: Bytes,
133 token_out: Bytes,
134 split: f64,
135 user_data: Option<Bytes>,
136 protocol_state: Option<&'a dyn ProtocolSim>,
137 estimated_amount_in: Option<BigUint>,
138}
139
140impl<'a> SwapBuilder<'a> {
141 pub fn new<T: Into<ProtocolComponent>>(
142 component: T,
143 token_in: Bytes,
144 token_out: Bytes,
145 ) -> Self {
146 Self {
147 component: component.into(),
148 token_in,
149 token_out,
150 split: 0.0,
151 user_data: None,
152 protocol_state: None,
153 estimated_amount_in: None,
154 }
155 }
156
157 pub fn split(mut self, split: f64) -> Self {
158 self.split = split;
159 self
160 }
161
162 pub fn user_data(mut self, user_data: Bytes) -> Self {
163 self.user_data = Some(user_data);
164 self
165 }
166
167 pub fn protocol_state(mut self, protocol_state: &'a dyn ProtocolSim) -> Self {
168 self.protocol_state = Some(protocol_state);
169 self
170 }
171
172 pub fn estimated_amount_in(mut self, estimated_amount_in: BigUint) -> Self {
173 self.estimated_amount_in = Some(estimated_amount_in);
174 self
175 }
176
177 pub fn build(self) -> Swap<'a> {
178 Swap {
179 component: self.component,
180 token_in: self.token_in,
181 token_out: self.token_out,
182 split: self.split,
183 user_data: self.user_data,
184 protocol_state: self.protocol_state,
185 estimated_amount_in: self.estimated_amount_in,
186 }
187 }
188}
189
190#[derive(Clone, Debug)]
197pub struct Transaction {
198 pub to: Bytes,
199 pub value: BigUint,
200 pub data: Vec<u8>,
201}
202
203#[derive(Clone, Debug)]
212pub struct EncodedSolution {
213 pub swaps: Vec<u8>,
214 pub interacting_with: Bytes,
215 pub function_signature: String,
216 pub n_tokens: usize,
217 pub permit: Option<PermitSingle>,
218}
219
220#[derive(Debug, Clone)]
227pub struct PermitSingle {
228 pub details: PermitDetails,
229 pub spender: Bytes,
230 pub sig_deadline: BigUint,
231}
232
233#[derive(Debug, Clone)]
241pub struct PermitDetails {
242 pub token: Bytes,
243 pub amount: BigUint,
244 pub expiration: BigUint,
245 pub nonce: BigUint,
246}
247
248impl PartialEq for PermitSingle {
249 fn eq(&self, other: &Self) -> bool {
250 self.details == other.details && self.spender == other.spender
251 }
253}
254
255impl PartialEq for PermitDetails {
256 fn eq(&self, other: &Self) -> bool {
257 self.token == other.token && self.amount == other.amount && self.nonce == other.nonce
258 }
260}
261
262#[derive(Clone, Debug)]
274pub struct EncodingContext {
275 pub receiver: Bytes,
276 pub exact_out: bool,
277 pub router_address: Option<Bytes>,
278 pub group_token_in: Bytes,
279 pub group_token_out: Bytes,
280 pub transfer_type: TransferType,
281}
282
283#[repr(u8)]
291#[derive(Copy, Clone, Debug, PartialEq)]
292pub enum TransferType {
293 TransferFrom = 0,
294 Transfer = 1,
295 None = 2,
296}
297
298mod tests {
299 use super::*;
300
301 struct MockProtocolComponent {
302 id: String,
303 protocol_system: String,
304 }
305
306 impl From<MockProtocolComponent> for ProtocolComponent {
307 fn from(component: MockProtocolComponent) -> Self {
308 ProtocolComponent {
309 id: component.id,
310 protocol_system: component.protocol_system,
311 tokens: vec![],
312 protocol_type_name: "".to_string(),
313 chain: Default::default(),
314 contract_addresses: vec![],
315 static_attributes: Default::default(),
316 change: Default::default(),
317 creation_tx: Default::default(),
318 created_at: Default::default(),
319 }
320 }
321 }
322
323 #[test]
324 fn test_swap_new() {
325 let component = MockProtocolComponent {
326 id: "i-am-an-id".to_string(),
327 protocol_system: "uniswap_v2".to_string(),
328 };
329 let user_data = Some(Bytes::from("0x1234"));
330 let swap = Swap::new(
331 component,
332 Bytes::from("0x12"),
333 Bytes::from("34"),
334 0.5,
335 user_data.clone(),
336 None,
337 None,
338 );
339 assert_eq!(swap.token_in, Bytes::from("0x12"));
340 assert_eq!(swap.token_out, Bytes::from("0x34"));
341 assert_eq!(swap.component.protocol_system, "uniswap_v2");
342 assert_eq!(swap.component.id, "i-am-an-id");
343 assert_eq!(swap.split, 0.5);
344 assert_eq!(swap.user_data, user_data);
345 }
346}