/ src / lib.rs
lib.rs
 1  use ethers::core::{
 2      types::{Address, H256, U256},
 3      utils::format_units,
 4  };
 5  use rusqlite::{named_params, Connection};
 6  use std::collections::HashMap;
 7  
 8  pub trait FullString {
 9      fn full_string(&self) -> String;
10  }
11  
12  impl FullString for Address {
13      fn full_string(&self) -> String {
14          serde_json::to_string(self).unwrap().replace('"', "")
15      }
16  }
17  
18  impl FullString for H256 {
19      fn full_string(&self) -> String {
20          serde_json::to_string(self).unwrap().replace('"', "")
21      }
22  }
23  
24  pub trait ToLabel {
25      fn to_label(&self, addressbook: &HashMap<String, String>) -> String;
26  }
27  
28  impl ToLabel for Address {
29      fn to_label(&self, addressbook: &HashMap<String, String>) -> String {
30          let full_address = &self.full_string();
31  
32          if addressbook.contains_key(full_address) {
33              (*addressbook.get(full_address).unwrap())
34                  .clone()
35                  .to_string()
36          } else if full_address == "0x0000000000000000000000000000000000000000" {
37              "NULL".to_owned()
38          } else if full_address == "0x4822521e6135cd2599199c83ea35179229a172ee" {
39              "Gnosis Pay Spender".to_owned()
40          } else {
41              full_address.to_string()
42          }
43      }
44  }
45  
46  pub trait IsKnownToken {
47      fn is_known_token(&self) -> bool;
48  }
49  
50  impl IsKnownToken for Address {
51      fn is_known_token(&self) -> bool {
52          let connection = Connection::open("rotki_db.db").unwrap();
53          let query = "SELECT COUNT(1)
54                  FROM evm_tokens
55                  WHERE
56                    lower(address) = lower(:address)";
57          let mut statement = connection.prepare(query).unwrap();
58  
59          let res: Result<bool, rusqlite::Error> = statement
60              .query_row(named_params! {":address": self.full_string()}, |row| {
61                  Ok(1 == row.get::<usize, i32>(0).unwrap())
62              });
63  
64          res.unwrap()
65      }
66  }
67  
68  pub fn scale_amount(amount: U256, decimals: u32) -> String {
69      let scaled_amount = format_units(amount, decimals).unwrap();
70  
71      let separator_index = scaled_amount.find('.').unwrap();
72      let least_significant_index = scaled_amount.len()
73          - scaled_amount
74              .chars()
75              .rev()
76              .position(|c| !(c == '0' || c == '.'))
77              .unwrap_or(scaled_amount.len());
78  
79      let cutoff = if separator_index > least_significant_index {
80          separator_index
81      } else {
82          least_significant_index
83      };
84  
85      scaled_amount[..cutoff].to_owned()
86  }