tycho_common/models/
mod.rs

1pub mod blockchain;
2pub mod contract;
3pub mod protocol;
4pub mod token;
5
6use std::{collections::HashMap, fmt::Display, str::FromStr, sync::Arc};
7
8use serde::{Deserialize, Serialize};
9use strum_macros::{Display, EnumString};
10use thiserror::Error;
11use token::CurrencyToken;
12
13use crate::{dto, Bytes};
14
15/// Address hash literal type to uniquely identify contracts/accounts on a
16/// blockchain.
17pub type Address = Bytes;
18
19/// Block hash literal type to uniquely identify a block in the chain and
20/// likely across chains.
21pub type BlockHash = Bytes;
22
23/// Transaction hash literal type to uniquely identify a transaction in the
24/// chain and likely across chains.
25pub type TxHash = Bytes;
26
27/// Smart contract code is represented as a byte vector containing opcodes.
28pub type Code = Bytes;
29
30/// The hash of a contract's code is used to identify it.
31pub type CodeHash = Bytes;
32
33/// The balance of an account is a big endian serialised integer of variable size.
34pub type Balance = Bytes;
35
36/// Key literal type of the contract store.
37pub type StoreKey = Bytes;
38
39/// Key literal type of the attribute store.
40pub type AttrStoreKey = String;
41
42/// Value literal type of the contract store.
43pub type StoreVal = Bytes;
44
45/// A binary key value store for an account.
46pub type ContractStore = HashMap<StoreKey, Option<StoreVal>>;
47
48/// Multiple key values stores grouped by account address.
49pub type AccountToContractStore = HashMap<Address, ContractStore>;
50
51/// Component id literal type to uniquely identify a component.
52pub type ComponentId = String;
53
54#[derive(
55    Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, EnumString, Display, Default,
56)]
57#[serde(rename_all = "lowercase")]
58#[strum(serialize_all = "lowercase")]
59pub enum Chain {
60    #[default]
61    Ethereum,
62    Starknet,
63    ZkSync,
64    Arbitrum,
65    Base,
66    Unichain,
67}
68
69impl From<dto::Chain> for Chain {
70    fn from(value: dto::Chain) -> Self {
71        match value {
72            dto::Chain::Ethereum => Chain::Ethereum,
73            dto::Chain::Starknet => Chain::Starknet,
74            dto::Chain::ZkSync => Chain::ZkSync,
75            dto::Chain::Arbitrum => Chain::Arbitrum,
76            dto::Chain::Base => Chain::Base,
77            dto::Chain::Unichain => Chain::Unichain,
78        }
79    }
80}
81
82fn native_eth(chain: Chain) -> CurrencyToken {
83    CurrencyToken::new(
84        &Bytes::from_str("0x0000000000000000000000000000000000000000").unwrap(),
85        "ETH",
86        18,
87        0,
88        &[Some(2300)],
89        chain,
90        100,
91    )
92}
93
94impl Chain {
95    /// Returns the native token symbol for the chain.
96    pub fn native_token(&self) -> CurrencyToken {
97        match self {
98            Chain::Ethereum => native_eth(Chain::Ethereum),
99            // It was decided that STRK token will be tracked as a dedicated AccountBalance on
100            // Starknet accounts and ETH balances will be tracked as a native balance.
101            Chain::Starknet => native_eth(Chain::Starknet),
102            Chain::ZkSync => native_eth(Chain::ZkSync),
103            Chain::Arbitrum => native_eth(Chain::Arbitrum),
104            Chain::Base => native_eth(Chain::Base),
105            Chain::Unichain => native_eth(Chain::Unichain),
106        }
107    }
108}
109
110#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash, Default)]
111pub struct ExtractorIdentity {
112    pub chain: Chain,
113    pub name: String,
114}
115
116impl ExtractorIdentity {
117    pub fn new(chain: Chain, name: &str) -> Self {
118        Self { chain, name: name.to_owned() }
119    }
120}
121
122impl std::fmt::Display for ExtractorIdentity {
123    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124        write!(f, "{}:{}", self.chain, self.name)
125    }
126}
127
128#[derive(Debug, PartialEq, Clone)]
129pub struct ExtractionState {
130    pub name: String,
131    pub chain: Chain,
132    pub attributes: serde_json::Value,
133    pub cursor: Vec<u8>,
134    pub block_hash: Bytes,
135}
136
137impl ExtractionState {
138    pub fn new(
139        name: String,
140        chain: Chain,
141        attributes: Option<serde_json::Value>,
142        cursor: &[u8],
143        block_hash: Bytes,
144    ) -> Self {
145        ExtractionState {
146            name,
147            chain,
148            attributes: attributes.unwrap_or_default(),
149            cursor: cursor.to_vec(),
150            block_hash,
151        }
152    }
153}
154
155// TODO: replace with types from dto on extractor
156#[typetag::serde(tag = "type")]
157pub trait NormalisedMessage:
158    std::any::Any + std::fmt::Debug + std::fmt::Display + Send + Sync + 'static
159{
160    fn source(&self) -> ExtractorIdentity;
161
162    fn drop_state(&self) -> Arc<dyn NormalisedMessage>;
163
164    fn as_any(&self) -> &dyn std::any::Any;
165}
166
167#[derive(PartialEq, Debug, Clone, Default, Deserialize, Serialize)]
168pub enum ImplementationType {
169    #[default]
170    Vm,
171    Custom,
172}
173
174#[derive(PartialEq, Debug, Clone, Default, Deserialize, Serialize)]
175pub enum FinancialType {
176    #[default]
177    Swap,
178    Psm,
179    Debt,
180    Leverage,
181}
182
183#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
184pub struct ProtocolType {
185    pub name: String,
186    pub financial_type: FinancialType,
187    pub attribute_schema: Option<serde_json::Value>,
188    pub implementation: ImplementationType,
189}
190
191impl ProtocolType {
192    pub fn new(
193        name: String,
194        financial_type: FinancialType,
195        attribute_schema: Option<serde_json::Value>,
196        implementation: ImplementationType,
197    ) -> Self {
198        ProtocolType { name, financial_type, attribute_schema, implementation }
199    }
200}
201
202#[derive(Debug, PartialEq, Default, Copy, Clone, Deserialize, Serialize)]
203pub enum ChangeType {
204    #[default]
205    Update,
206    Deletion,
207    Creation,
208}
209
210#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
211pub struct ContractId {
212    pub address: Address,
213    pub chain: Chain,
214}
215
216/// Uniquely identifies a contract on a specific chain.
217impl ContractId {
218    pub fn new(chain: Chain, address: Address) -> Self {
219        Self { address, chain }
220    }
221
222    pub fn address(&self) -> &Address {
223        &self.address
224    }
225}
226
227impl Display for ContractId {
228    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
229        write!(f, "{:?}: 0x{}", self.chain, hex::encode(&self.address))
230    }
231}
232
233#[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)]
234pub struct PaginationParams {
235    pub page: i64,
236    pub page_size: i64,
237}
238
239impl PaginationParams {
240    pub fn new(page: i64, page_size: i64) -> Self {
241        Self { page, page_size }
242    }
243
244    pub fn offset(&self) -> i64 {
245        self.page * self.page_size
246    }
247}
248
249impl From<&dto::PaginationParams> for PaginationParams {
250    fn from(value: &dto::PaginationParams) -> Self {
251        PaginationParams { page: value.page, page_size: value.page_size }
252    }
253}
254
255#[derive(Error, Debug, PartialEq)]
256pub enum DeltaError {
257    #[error("Id mismatch: {0} vs {1}")]
258    IdMismatch(String, String),
259}