tycho_simulation/evm/
tycho_models.rs

1use std::collections::HashMap;
2
3use alloy::primitives::{Address, B256, U256};
4use serde::{Deserialize, Serialize};
5pub use tycho_common::{dto::ChangeType, models::Chain};
6
7use crate::{
8    evm::protocol::u256_num,
9    serde_helpers::{hex_bytes, hex_bytes_option},
10};
11
12#[derive(PartialEq, Serialize, Deserialize, Clone, Debug)]
13pub struct AccountUpdate {
14    pub address: Address,
15    pub chain: Chain,
16    pub slots: HashMap<U256, U256>,
17    pub balance: Option<U256>,
18    #[serde(with = "hex_bytes_option")]
19    pub code: Option<Vec<u8>>,
20    pub change: ChangeType,
21}
22
23impl AccountUpdate {
24    #[allow(clippy::too_many_arguments)]
25    pub fn new(
26        address: Address,
27        chain: Chain,
28        slots: HashMap<U256, U256>,
29        balance: Option<U256>,
30        code: Option<Vec<u8>>,
31        change: ChangeType,
32    ) -> Self {
33        Self { address, chain, slots, balance, code, change }
34    }
35}
36
37impl From<tycho_common::dto::AccountUpdate> for AccountUpdate {
38    fn from(value: tycho_common::dto::AccountUpdate) -> Self {
39        Self {
40            chain: value.chain.into(),
41            address: Address::from_slice(&value.address[..20]), // Convert address field to Address
42            slots: u256_num::map_slots_to_u256(value.slots),
43            balance: value
44                .balance
45                .map(|balance| u256_num::bytes_to_u256(balance.into())),
46            code: value.code.map(|code| code.to_vec()),
47            change: value.change,
48        }
49    }
50}
51
52#[derive(PartialEq, Clone, Serialize, Deserialize, Default)]
53#[serde(rename = "Account")]
54/// Account struct for the response from Tycho server for a contract state request.
55///
56/// Code is serialized as a hex string instead of a list of bytes.
57pub struct ResponseAccount {
58    pub chain: Chain,
59    pub address: Address,
60    pub title: String,
61    pub slots: HashMap<U256, U256>,
62    pub native_balance: U256,
63    pub token_balances: HashMap<Address, U256>,
64    #[serde(with = "hex_bytes")]
65    pub code: Vec<u8>,
66    pub code_hash: B256,
67    pub balance_modify_tx: B256,
68    pub code_modify_tx: B256,
69    pub creation_tx: Option<B256>,
70}
71
72impl ResponseAccount {
73    #[allow(clippy::too_many_arguments)]
74    pub fn new(
75        chain: Chain,
76        address: Address,
77        title: String,
78        slots: HashMap<U256, U256>,
79        native_balance: U256,
80        token_balances: HashMap<Address, U256>,
81        code: Vec<u8>,
82        code_hash: B256,
83        balance_modify_tx: B256,
84        code_modify_tx: B256,
85        creation_tx: Option<B256>,
86    ) -> Self {
87        Self {
88            chain,
89            address,
90            title,
91            slots,
92            native_balance,
93            token_balances,
94            code,
95            code_hash,
96            balance_modify_tx,
97            code_modify_tx,
98            creation_tx,
99        }
100    }
101}
102
103/// Implement Debug for ResponseAccount manually to avoid printing the code field.
104impl std::fmt::Debug for ResponseAccount {
105    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106        f.debug_struct("ResponseAccount")
107            .field("chain", &self.chain)
108            .field("address", &self.address)
109            .field("title", &self.title)
110            .field("slots", &self.slots)
111            .field("native_balance", &self.native_balance)
112            .field("token_balances", &self.token_balances)
113            .field("code", &format!("[{} bytes]", self.code.len()))
114            .field("code_hash", &self.code_hash)
115            .field("balance_modify_tx", &self.balance_modify_tx)
116            .field("code_modify_tx", &self.code_modify_tx)
117            .field("creation_tx", &self.creation_tx)
118            .finish()
119    }
120}
121
122impl From<tycho_common::dto::ResponseAccount> for ResponseAccount {
123    #[allow(deprecated)]
124    fn from(value: tycho_common::dto::ResponseAccount) -> Self {
125        Self {
126            chain: value.chain.into(),
127            address: Address::from_slice(&value.address[..20]), // Convert address field to Address
128            title: value.title.clone(),
129            slots: u256_num::map_slots_to_u256(value.slots),
130            native_balance: u256_num::bytes_to_u256(value.native_balance.into()),
131            token_balances: value
132                .token_balances
133                .into_iter()
134                .map(|(address, balance)| {
135                    (Address::from_slice(&address[..20]), u256_num::bytes_to_u256(balance.into()))
136                })
137                .collect(),
138            code: value.code.to_vec(),
139            code_hash: B256::from_slice(&value.code_hash[..]),
140            balance_modify_tx: B256::from_slice(&value.balance_modify_tx[..]),
141            code_modify_tx: B256::from_slice(&value.code_modify_tx[..]),
142            creation_tx: value
143                .creation_tx
144                .map(|tx| B256::from_slice(&tx[..])), // Optionally map creation_tx if present
145        }
146    }
147}