tycho_common/models/
token.rs

1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4
5use super::{Address, Balance};
6use crate::{models::Chain, traits::TokenOwnerFinding, Bytes};
7
8/// Cost related to a token transfer, for example amount of gas in evm chains.
9pub type TransferCost = u64;
10
11/// Tax related to a token transfer. Should be given in Basis Points (1/100th of a percent)
12pub type TransferTax = u64;
13
14#[derive(PartialEq, Debug, Clone, Deserialize, Serialize)]
15pub struct CurrencyToken {
16    pub address: Bytes,
17    pub symbol: String,
18    pub decimals: u32,
19    pub tax: TransferTax,
20    pub gas: Vec<Option<TransferCost>>,
21    pub chain: Chain,
22    /// Quality is between 0-100, where:
23    ///  - 100: Normal token
24    ///  - 75: Rebase token
25    ///  - 50: Fee token
26    ///  - 10: Token analysis failed at creation
27    ///  - 9-5: Token analysis failed on cronjob (after creation).
28    ///  - 0: Failed to extract decimals onchain
29    pub quality: u32,
30}
31
32impl CurrencyToken {
33    pub fn new(
34        address: &Bytes,
35        symbol: &str,
36        decimals: u32,
37        tax: u64,
38        gas: &[Option<u64>],
39        chain: Chain,
40        quality: u32,
41    ) -> Self {
42        Self {
43            address: address.clone(),
44            symbol: symbol.to_string(),
45            decimals,
46            tax,
47            gas: gas.to_owned(),
48            chain,
49            quality,
50        }
51    }
52}
53
54/// Represents the quality of a token.
55///
56/// * `Good`: Indicates that the token has successfully passed the analysis process.
57/// * `Bad`: Indicates that the token has failed the analysis process. In this case, a detailed
58///   reason for the failure is provided.
59///
60/// Note: Transfer taxes do not impact the token's quality.
61/// Even if a token has transfer taxes, as long as it successfully passes the analysis,
62/// it will still be marked as `Good`.
63#[derive(Debug, Clone, Eq, PartialEq)]
64pub enum TokenQuality {
65    Good,
66    Bad { reason: String },
67}
68
69impl TokenQuality {
70    pub fn is_good(&self) -> bool {
71        matches!(self, Self::Good { .. })
72    }
73
74    pub fn bad(reason: impl ToString) -> Self {
75        Self::Bad { reason: reason.to_string() }
76    }
77}
78
79/// A store for tracking token owners and their balances.
80///
81/// The `TokenOwnerStore` maintains a mapping between token addresses and their respective
82/// owner's address and balance. It can be used to quickly retrieve token owner information
83/// without needing to query external sources.
84///
85/// # Fields
86/// * `values` - A `HashMap` where:
87///   * The key is the token `Address`, representing the address of the token being tracked.
88///   * The value is a tuple containing:
89///     * The owner `Address` of the token.
90///     * The `Balance` of the owner for the token.
91#[derive(Debug)]
92pub struct TokenOwnerStore {
93    values: HashMap<Address, (Address, Balance)>,
94}
95
96impl TokenOwnerStore {
97    pub fn new(values: HashMap<Address, (Address, Balance)>) -> Self {
98        TokenOwnerStore { values }
99    }
100}
101
102#[async_trait::async_trait]
103impl TokenOwnerFinding for TokenOwnerStore {
104    async fn find_owner(
105        &self,
106        token: Address,
107        _min_balance: Balance,
108    ) -> Result<Option<(Address, Balance)>, String> {
109        Ok(self.values.get(&token).cloned())
110    }
111}