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