From 6a9b9c5994d822db59d1fb79718527dffec4b002 Mon Sep 17 00:00:00 2001 From: Ryan Swanson Date: Wed, 11 Jan 2023 21:29:32 -0500 Subject: [PATCH 01/17] beginnings of proof of concept --- Cargo.lock | 8 +++ Cargo.toml | 1 + tools/accessed-funds-calculator/Cargo.toml | 10 +++ tools/accessed-funds-calculator/src/main.rs | 76 +++++++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 tools/accessed-funds-calculator/Cargo.toml create mode 100644 tools/accessed-funds-calculator/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 93609019..fa701070 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12,6 +12,14 @@ dependencies = [ "regex", ] +[[package]] +name = "accessed-funds-calculator" +version = "0.1.0" +dependencies = [ + "reqwest", + "tokio", +] + [[package]] name = "accumulator" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 3cdd0628..934e8adf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,4 +21,5 @@ members = [ "tools/nomad-cli", "tools/balance-exporter", "tools/killswitch", + "tools/accessed-funds-calculator", ] diff --git a/tools/accessed-funds-calculator/Cargo.toml b/tools/accessed-funds-calculator/Cargo.toml new file mode 100644 index 00000000..841d0569 --- /dev/null +++ b/tools/accessed-funds-calculator/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "accessed-funds-calculator" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +reqwest = { version = "0.11", features = ["json"] } +tokio = { version = "1", features = ["full"] } \ No newline at end of file diff --git a/tools/accessed-funds-calculator/src/main.rs b/tools/accessed-funds-calculator/src/main.rs new file mode 100644 index 00000000..92ed9177 --- /dev/null +++ b/tools/accessed-funds-calculator/src/main.rs @@ -0,0 +1,76 @@ +use std::collections::HashMap; +use std::env; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let query_list = vec![ + AffectedTokens::USDC(String::from("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")), + AffectedTokens::CQT(String::from("0xD417144312DbF50465b1C641d016962017Ef6240")), + AffectedTokens::USDT(String::from("0xdAC17F958D2ee523a2206206994597C13D831ec7")), + AffectedTokens::FRAX(String::from("0x853d955aCEf822Db058eb8505911ED77F175b99e")), + AffectedTokens::WBTC(String::from("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599")), + AffectedTokens::IAG(String::from("0x40EB746DEE876aC1E78697b7Ca85142D178A1Fc8")), + AffectedTokens::WETH(String::from("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")), + AffectedTokens::DAI(String::from("0x6B175474E89094C44Da98b954EedeAC495271d0F")), + AffectedTokens::MC3(String::from("0xf1a91C7d44768070F711c68f33A7CA25c8D30268")), + AffectedTokens::FXS(String::from("0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0")), + AffectedTokens::CARDS(String::from("0x3d6F0DEa3AC3C607B3998e6Ce14b6350721752d9")), + AffectedTokens::HBOT(String::from("0xE5097D9baeAFB89f9bcB78C9290d545dB5f9e9CB")), + AffectedTokens::SDL(String::from("0xf1Dc500FdE233A4055e25e5BbF516372BC4F6871")), + AffectedTokens::GERO(String::from("0x3431F91b3a388115F00C5Ba9FdB899851D005Fb5")), + ]; + let address = "0xa4B86BcbB18639D8e708d6163a0c734aFcDB770c"; + + for token in query_list.iter() { + let value: u128 = get_token_balance(&token, address).await?["result"].parse().unwrap(); + println!("{:?}", value); + } + Ok(()) +} + +async fn get_token_balance(token: &AffectedTokens, address: &str) -> Result, Box> { + let etherscan_url = "https://api.etherscan.io/api"; + let module = "account"; + let action = "tokenbalance"; + let apiKey = env::var("ETHERSCAN_KEY")?; + let request_url = + match token { + AffectedTokens::USDC(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), + AffectedTokens::CQT(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), + AffectedTokens::USDT(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), + AffectedTokens::FRAX(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), + AffectedTokens::WBTC(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), + AffectedTokens::IAG(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), + AffectedTokens::WETH(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), + AffectedTokens::DAI(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), + AffectedTokens::MC3(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), + AffectedTokens::FXS(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), + AffectedTokens::CARDS(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), + AffectedTokens::HBOT(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), + AffectedTokens::SDL(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), + AffectedTokens::GERO(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), + }; + + let resp = reqwest::get(request_url) + .await? + .json::>() + .await?; + Ok(resp) +} + +enum AffectedTokens { + USDC(String), + CQT(String), + USDT(String), + FRAX(String), + WBTC(String), + IAG(String), + WETH(String), + DAI(String), + MC3(String), + FXS(String), + CARDS(String), + HBOT(String), + SDL(String), + GERO(String), +} \ No newline at end of file From af4c2083f0839f07f304b82156a1aea6e2855b2f Mon Sep 17 00:00:00 2001 From: Ryan Swanson Date: Wed, 11 Jan 2023 22:30:43 -0500 Subject: [PATCH 02/17] beginnings of refactor, playing around with structure --- tools/accessed-funds-calculator/src/main.rs | 168 ++++++++++++------ tools/accessed-funds-calculator/src/tokens.rs | 21 +++ 2 files changed, 133 insertions(+), 56 deletions(-) create mode 100644 tools/accessed-funds-calculator/src/tokens.rs diff --git a/tools/accessed-funds-calculator/src/main.rs b/tools/accessed-funds-calculator/src/main.rs index 92ed9177..531b97c3 100644 --- a/tools/accessed-funds-calculator/src/main.rs +++ b/tools/accessed-funds-calculator/src/main.rs @@ -1,76 +1,132 @@ use std::collections::HashMap; use std::env; +mod tokens; + +use crate::tokens::{Token, TokenName}; + + #[tokio::main] -async fn main() -> Result<(), Box> { - let query_list = vec![ - AffectedTokens::USDC(String::from("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")), - AffectedTokens::CQT(String::from("0xD417144312DbF50465b1C641d016962017Ef6240")), - AffectedTokens::USDT(String::from("0xdAC17F958D2ee523a2206206994597C13D831ec7")), - AffectedTokens::FRAX(String::from("0x853d955aCEf822Db058eb8505911ED77F175b99e")), - AffectedTokens::WBTC(String::from("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599")), - AffectedTokens::IAG(String::from("0x40EB746DEE876aC1E78697b7Ca85142D178A1Fc8")), - AffectedTokens::WETH(String::from("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")), - AffectedTokens::DAI(String::from("0x6B175474E89094C44Da98b954EedeAC495271d0F")), - AffectedTokens::MC3(String::from("0xf1a91C7d44768070F711c68f33A7CA25c8D30268")), - AffectedTokens::FXS(String::from("0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0")), - AffectedTokens::CARDS(String::from("0x3d6F0DEa3AC3C607B3998e6Ce14b6350721752d9")), - AffectedTokens::HBOT(String::from("0xE5097D9baeAFB89f9bcB78C9290d545dB5f9e9CB")), - AffectedTokens::SDL(String::from("0xf1Dc500FdE233A4055e25e5BbF516372BC4F6871")), - AffectedTokens::GERO(String::from("0x3431F91b3a388115F00C5Ba9FdB899851D005Fb5")), - ]; +async fn main() -> Result<(), Box> { + let usdc = Token { + name: TokenName::USDC, + contract_address: String::from("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), + }; + + let cqt = Token { + name: TokenName::CQT, + contract_address: String::from("0xD417144312DbF50465b1C641d016962017Ef6240"), + }; + + let usdt = Token{ + name: TokenName::WBTC, + contract_address: String::from("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"), + }; + + let wbtc = Token { + name: TokenName::FRAX, + contract_address: String::from("0x853d955aCEf822Db058eb8505911ED77F175b99e"), + }; + + let frax = Token { + name: TokenName::FRAX, + contract_address: String::from("0x853d955aCEf822Db058eb8505911ED77F175b99e"), + }; + + let iag = Token { + name: TokenName::IAG, + contract_address: String::from("0x40EB746DEE876aC1E78697b7Ca85142D178A1Fc8"), + }; + + let weth = Token { + name: TokenName::WETH, + contract_address: String::from("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), + }; + + let dai = Token { + name: TokenName::DAI, + contract_address: String::from("0x6B175474E89094C44Da98b954EedeAC495271d0F"), + }; + + let c3 = Token { + name: TokenName::C3, + contract_address: String::from("0xf1a91C7d44768070F711c68f33A7CA25c8D30268"), + }; + + let fxs = Token { + name: TokenName::FXS, + contract_address: String::from("0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0"), + }; + + let cards = Token { + name: TokenName::CARDS, + contract_address: String::from("0x3d6F0DEa3AC3C607B3998e6Ce14b6350721752d9"), + }; + + let hbot = Token { + name: TokenName::HBOT, + contract_address: String::from("0xE5097D9baeAFB89f9bcB78C9290d545dB5f9e9CB"), + }; + + let sdl = Token { + name: TokenName::SDL, + contract_address: String::from("0xf1Dc500FdE233A4055e25e5BbF516372BC4F6871"), + }; + + let gero = Token { + name: TokenName::GERO, + contract_address: String::from("0x3431F91b3a388115F00C5Ba9FdB899851D005Fb5"), + }; + let address = "0xa4B86BcbB18639D8e708d6163a0c734aFcDB770c"; - for token in query_list.iter() { - let value: u128 = get_token_balance(&token, address).await?["result"].parse().unwrap(); - println!("{:?}", value); + let balance_usdc: u128 = get_token_balance(&usdc, address).await?["result"].parse().unwrap(); + let balance_cqt: u128 = get_token_balance(&cqt, address).await?["result"].parse().unwrap(); + let balance_usdt: u128 = get_token_balance(&usdt, address).await?["result"].parse().unwrap(); + let balance_wbtc: u128 = get_token_balance(&wbtc, address).await?["result"].parse().unwrap(); + let balance_frax: u128 = get_token_balance(&frax, address).await?["result"].parse().unwrap(); + let balance_iag: u128 = get_token_balance(&iag, address).await?["result"].parse().unwrap(); + let balance_weth: u128 = get_token_balance(&weth, address).await?["result"].parse().unwrap(); + let balance_dai: u128 = get_token_balance(&dai, address).await?["result"].parse().unwrap(); + let balance_c3: u128 = get_token_balance(&c3, address).await?["result"].parse().unwrap(); + let balance_fxs: u128 = get_token_balance(&fxs, address).await?["result"].parse().unwrap(); + let balance_cards: u128 = get_token_balance(&cards, address).await?["result"].parse().unwrap(); + let balance_hbot: u128 = get_token_balance(&hbot, address).await?["result"].parse().unwrap(); + let balance_sdl: u128 = get_token_balance(&sdl, address).await?["result"].parse().unwrap(); + let balance_gero: u128 = get_token_balance(&gero, address).await?["result"].parse().unwrap(); + + let balances = vec![ + balance_usdc, + balance_cqt, + balance_usdt, + balance_wbtc, + balance_frax, + balance_iag, + balance_weth, + balance_dai, + balance_c3, + balance_fxs, + balance_cards, + balance_hbot, + balance_sdl, + balance_gero, + ]; + + for balance in balances { + println!("{}", balance ); } Ok(()) } -async fn get_token_balance(token: &AffectedTokens, address: &str) -> Result, Box> { +async fn get_token_balance(token: &Token, address: &str) -> Result, Box> { let etherscan_url = "https://api.etherscan.io/api"; let module = "account"; let action = "tokenbalance"; let apiKey = env::var("ETHERSCAN_KEY")?; - let request_url = - match token { - AffectedTokens::USDC(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), - AffectedTokens::CQT(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), - AffectedTokens::USDT(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), - AffectedTokens::FRAX(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), - AffectedTokens::WBTC(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), - AffectedTokens::IAG(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), - AffectedTokens::WETH(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), - AffectedTokens::DAI(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), - AffectedTokens::MC3(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), - AffectedTokens::FXS(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), - AffectedTokens::CARDS(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), - AffectedTokens::HBOT(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), - AffectedTokens::SDL(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), - AffectedTokens::GERO(token_address) => format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token_address, &address, &apiKey), - }; - + let request_url = format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token.contract_address, &address, &apiKey); let resp = reqwest::get(request_url) .await? .json::>() .await?; Ok(resp) } - -enum AffectedTokens { - USDC(String), - CQT(String), - USDT(String), - FRAX(String), - WBTC(String), - IAG(String), - WETH(String), - DAI(String), - MC3(String), - FXS(String), - CARDS(String), - HBOT(String), - SDL(String), - GERO(String), -} \ No newline at end of file diff --git a/tools/accessed-funds-calculator/src/tokens.rs b/tools/accessed-funds-calculator/src/tokens.rs new file mode 100644 index 00000000..31dcb019 --- /dev/null +++ b/tools/accessed-funds-calculator/src/tokens.rs @@ -0,0 +1,21 @@ +pub enum TokenName { + USDC, + CQT, + USDT, + FRAX, + WBTC, + IAG, + WETH, + DAI, + C3, + FXS, + CARDS, + HBOT, + SDL, + GERO, +} + +pub struct Token { + pub name: TokenName, + pub contract_address: String, +} From 290ef6cc4e2349f6dc31bcac62f31d9fd7fb212d Mon Sep 17 00:00:00 2001 From: Ryan Swanson Date: Thu, 12 Jan 2023 12:45:04 -0500 Subject: [PATCH 03/17] adding some more wip functionality to get token prices plus some refactoring --- Cargo.lock | 1 + tools/accessed-funds-calculator/Cargo.toml | 3 +- tools/accessed-funds-calculator/src/main.rs | 91 ++++++++++++------- tools/accessed-funds-calculator/src/tokens.rs | 3 + 4 files changed, 63 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fa701070..92034b03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,7 @@ name = "accessed-funds-calculator" version = "0.1.0" dependencies = [ "reqwest", + "serde 1.0.147", "tokio", ] diff --git a/tools/accessed-funds-calculator/Cargo.toml b/tools/accessed-funds-calculator/Cargo.toml index 841d0569..7be56d4b 100644 --- a/tools/accessed-funds-calculator/Cargo.toml +++ b/tools/accessed-funds-calculator/Cargo.toml @@ -7,4 +7,5 @@ edition = "2021" [dependencies] reqwest = { version = "0.11", features = ["json"] } -tokio = { version = "1", features = ["full"] } \ No newline at end of file +tokio = { version = "1", features = ["full"] } +serde = { version = "1.0", features = ["derive"] } \ No newline at end of file diff --git a/tools/accessed-funds-calculator/src/main.rs b/tools/accessed-funds-calculator/src/main.rs index 531b97c3..dad78d52 100644 --- a/tools/accessed-funds-calculator/src/main.rs +++ b/tools/accessed-funds-calculator/src/main.rs @@ -1,6 +1,8 @@ use std::collections::HashMap; use std::env; +use serde::{Deserialize, Serialize}; + mod tokens; use crate::tokens::{Token, TokenName}; @@ -10,115 +12,118 @@ use crate::tokens::{Token, TokenName}; async fn main() -> Result<(), Box> { let usdc = Token { name: TokenName::USDC, + id: String::from("usd-coin"), contract_address: String::from("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), }; let cqt = Token { name: TokenName::CQT, + id: String::from("covalent"), contract_address: String::from("0xD417144312DbF50465b1C641d016962017Ef6240"), }; let usdt = Token{ name: TokenName::WBTC, + id: String::from("tether"), contract_address: String::from("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"), }; let wbtc = Token { name: TokenName::FRAX, + id: String::from("wrapped-bitcoin"), contract_address: String::from("0x853d955aCEf822Db058eb8505911ED77F175b99e"), }; let frax = Token { name: TokenName::FRAX, + id: String::from("frax"), contract_address: String::from("0x853d955aCEf822Db058eb8505911ED77F175b99e"), }; let iag = Token { name: TokenName::IAG, + id: String::from("iagon"), contract_address: String::from("0x40EB746DEE876aC1E78697b7Ca85142D178A1Fc8"), }; let weth = Token { name: TokenName::WETH, + id: String::from("weth"), contract_address: String::from("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), }; let dai = Token { name: TokenName::DAI, + id: String::from("dai"), contract_address: String::from("0x6B175474E89094C44Da98b954EedeAC495271d0F"), }; let c3 = Token { name: TokenName::C3, + id: String::from("charli3"), contract_address: String::from("0xf1a91C7d44768070F711c68f33A7CA25c8D30268"), }; let fxs = Token { name: TokenName::FXS, + id: String::from("frax-share"), contract_address: String::from("0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0"), }; let cards = Token { name: TokenName::CARDS, + id: String::from("cardstarter"), contract_address: String::from("0x3d6F0DEa3AC3C607B3998e6Ce14b6350721752d9"), }; let hbot = Token { name: TokenName::HBOT, + id: String::from("hummingbot"), contract_address: String::from("0xE5097D9baeAFB89f9bcB78C9290d545dB5f9e9CB"), }; let sdl = Token { name: TokenName::SDL, + id: String::from("saddle-finance"), contract_address: String::from("0xf1Dc500FdE233A4055e25e5BbF516372BC4F6871"), }; let gero = Token { name: TokenName::GERO, + id: String::from("gerowallet"), contract_address: String::from("0x3431F91b3a388115F00C5Ba9FdB899851D005Fb5"), }; let address = "0xa4B86BcbB18639D8e708d6163a0c734aFcDB770c"; - let balance_usdc: u128 = get_token_balance(&usdc, address).await?["result"].parse().unwrap(); - let balance_cqt: u128 = get_token_balance(&cqt, address).await?["result"].parse().unwrap(); - let balance_usdt: u128 = get_token_balance(&usdt, address).await?["result"].parse().unwrap(); - let balance_wbtc: u128 = get_token_balance(&wbtc, address).await?["result"].parse().unwrap(); - let balance_frax: u128 = get_token_balance(&frax, address).await?["result"].parse().unwrap(); - let balance_iag: u128 = get_token_balance(&iag, address).await?["result"].parse().unwrap(); - let balance_weth: u128 = get_token_balance(&weth, address).await?["result"].parse().unwrap(); - let balance_dai: u128 = get_token_balance(&dai, address).await?["result"].parse().unwrap(); - let balance_c3: u128 = get_token_balance(&c3, address).await?["result"].parse().unwrap(); - let balance_fxs: u128 = get_token_balance(&fxs, address).await?["result"].parse().unwrap(); - let balance_cards: u128 = get_token_balance(&cards, address).await?["result"].parse().unwrap(); - let balance_hbot: u128 = get_token_balance(&hbot, address).await?["result"].parse().unwrap(); - let balance_sdl: u128 = get_token_balance(&sdl, address).await?["result"].parse().unwrap(); - let balance_gero: u128 = get_token_balance(&gero, address).await?["result"].parse().unwrap(); - - let balances = vec![ - balance_usdc, - balance_cqt, - balance_usdt, - balance_wbtc, - balance_frax, - balance_iag, - balance_weth, - balance_dai, - balance_c3, - balance_fxs, - balance_cards, - balance_hbot, - balance_sdl, - balance_gero, + let token_vec = vec![ + usdc, + cqt, + usdt, + wbtc, + frax, + iag, + weth, + dai, + c3, + fxs, + cards, + hbot, + sdl, + gero, ]; - for balance in balances { - println!("{}", balance ); + for token in token_vec { + let balance: u128 = get_token_balance(&token, address).await?; + // let token_price = get_token_price(&token).await?; + println!("{:?}",balance); + // println!("{:#?}",token_price); } + Ok(()) } -async fn get_token_balance(token: &Token, address: &str) -> Result, Box> { +async fn get_token_balance(token: &Token, address: &str) -> Result> { let etherscan_url = "https://api.etherscan.io/api"; let module = "account"; let action = "tokenbalance"; @@ -128,5 +133,23 @@ async fn get_token_balance(token: &Token, address: &str) -> Result>() .await?; - Ok(resp) + let balance = resp["result"].parse().unwrap(); + Ok(balance) +} + +async fn get_token_price(token: &Token) -> Result> { + let coingecko_url = "https://api.coingecko.com/api/v3/simple/price"; + let ids = "ethereum"; + let vs_currency = "usd"; + + let request_url = format!("{}?ids={}&vs_currencies={}", coingecko_url, ids, vs_currency); + + let resp = reqwest::get(request_url) + .await? + .json::() + .await?; + let price = resp; + println!("here"); + Ok(price) + } diff --git a/tools/accessed-funds-calculator/src/tokens.rs b/tools/accessed-funds-calculator/src/tokens.rs index 31dcb019..cf6a90c5 100644 --- a/tools/accessed-funds-calculator/src/tokens.rs +++ b/tools/accessed-funds-calculator/src/tokens.rs @@ -1,3 +1,4 @@ +#[derive(Debug)] pub enum TokenName { USDC, CQT, @@ -15,7 +16,9 @@ pub enum TokenName { GERO, } +#[derive(Debug)] pub struct Token { pub name: TokenName, + pub id: String, pub contract_address: String, } From da58d4d46c90728068e3ba19645f40b17b61de41 Mon Sep 17 00:00:00 2001 From: Ryan Swanson Date: Thu, 12 Jan 2023 12:57:30 -0500 Subject: [PATCH 04/17] formatting --- tools/accessed-funds-calculator/src/main.rs | 43 ++++++++------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/tools/accessed-funds-calculator/src/main.rs b/tools/accessed-funds-calculator/src/main.rs index dad78d52..672968a3 100644 --- a/tools/accessed-funds-calculator/src/main.rs +++ b/tools/accessed-funds-calculator/src/main.rs @@ -7,9 +7,8 @@ mod tokens; use crate::tokens::{Token, TokenName}; - #[tokio::main] -async fn main() -> Result<(), Box> { +async fn main() -> Result<(), Box> { let usdc = Token { name: TokenName::USDC, id: String::from("usd-coin"), @@ -22,7 +21,7 @@ async fn main() -> Result<(), Box> { contract_address: String::from("0xD417144312DbF50465b1C641d016962017Ef6240"), }; - let usdt = Token{ + let usdt = Token { name: TokenName::WBTC, id: String::from("tether"), contract_address: String::from("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"), @@ -97,38 +96,31 @@ async fn main() -> Result<(), Box> { let address = "0xa4B86BcbB18639D8e708d6163a0c734aFcDB770c"; let token_vec = vec![ - usdc, - cqt, - usdt, - wbtc, - frax, - iag, - weth, - dai, - c3, - fxs, - cards, - hbot, - sdl, - gero, + usdc, cqt, usdt, wbtc, frax, iag, weth, dai, c3, fxs, cards, hbot, sdl, gero, ]; for token in token_vec { let balance: u128 = get_token_balance(&token, address).await?; // let token_price = get_token_price(&token).await?; - println!("{:?}",balance); + println!("{:?}", balance); // println!("{:#?}",token_price); } Ok(()) } -async fn get_token_balance(token: &Token, address: &str) -> Result> { +async fn get_token_balance( + token: &Token, + address: &str, +) -> Result> { let etherscan_url = "https://api.etherscan.io/api"; let module = "account"; let action = "tokenbalance"; let apiKey = env::var("ETHERSCAN_KEY")?; - let request_url = format!("{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", ðerscan_url, &module, &action, &token.contract_address, &address, &apiKey); + let request_url = format!( + "{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", + ðerscan_url, &module, &action, &token.contract_address, &address, &apiKey + ); let resp = reqwest::get(request_url) .await? .json::>() @@ -142,14 +134,13 @@ async fn get_token_price(token: &Token) -> Result() - .await?; + let resp = reqwest::get(request_url).await?.json::().await?; let price = resp; println!("here"); Ok(price) - } From 9d29a400472c7a23b9d53b62ca261d707f7e2684 Mon Sep 17 00:00:00 2001 From: Ryan Swanson Date: Fri, 13 Jan 2023 08:42:42 -0500 Subject: [PATCH 05/17] more hardcoded values as we progress to fully functional --- Cargo.lock | 1 + tools/accessed-funds-calculator/Cargo.toml | 3 +- tools/accessed-funds-calculator/src/main.rs | 110 ++++++++++++++---- tools/accessed-funds-calculator/src/tokens.rs | 3 + 4 files changed, 91 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 92034b03..558f12f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,6 +18,7 @@ version = "0.1.0" dependencies = [ "reqwest", "serde 1.0.147", + "serde_json", "tokio", ] diff --git a/tools/accessed-funds-calculator/Cargo.toml b/tools/accessed-funds-calculator/Cargo.toml index 7be56d4b..ffd52d30 100644 --- a/tools/accessed-funds-calculator/Cargo.toml +++ b/tools/accessed-funds-calculator/Cargo.toml @@ -8,4 +8,5 @@ edition = "2021" [dependencies] reqwest = { version = "0.11", features = ["json"] } tokio = { version = "1", features = ["full"] } -serde = { version = "1.0", features = ["derive"] } \ No newline at end of file +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" \ No newline at end of file diff --git a/tools/accessed-funds-calculator/src/main.rs b/tools/accessed-funds-calculator/src/main.rs index 672968a3..d0f0927b 100644 --- a/tools/accessed-funds-calculator/src/main.rs +++ b/tools/accessed-funds-calculator/src/main.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use std::env; -use serde::{Deserialize, Serialize}; +use serde_json; mod tokens; @@ -12,107 +12,155 @@ async fn main() -> Result<(), Box> { let usdc = Token { name: TokenName::USDC, id: String::from("usd-coin"), + decimals: 6.0, contract_address: String::from("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), + recovered_total: 12_890_538.932401, + currentPrice: 0.9992, }; let cqt = Token { name: TokenName::CQT, id: String::from("covalent"), + decimals: 18.0, contract_address: String::from("0xD417144312DbF50465b1C641d016962017Ef6240"), + recovered_total: 34_082_775.75159970, + currentPrice: 0.112701, }; let usdt = Token { name: TokenName::WBTC, id: String::from("tether"), - contract_address: String::from("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"), + decimals: 6.0, + contract_address: String::from("0xdAC17F958D2ee523a2206206994597C13D831ec7"), + recovered_total: 4_673_863.595197, + currentPrice: 0.9994, }; let wbtc = Token { - name: TokenName::FRAX, + name: TokenName::WBTC, id: String::from("wrapped-bitcoin"), - contract_address: String::from("0x853d955aCEf822Db058eb8505911ED77F175b99e"), + decimals: 8.0, + contract_address: String::from("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"), + recovered_total: 280.73117399, + currentPrice: 18_805.78, }; let frax = Token { name: TokenName::FRAX, id: String::from("frax"), + decimals: 18.0, contract_address: String::from("0x853d955aCEf822Db058eb8505911ED77F175b99e"), + recovered_total: 2_644_469.91860909, + currentPrice: 1.001, }; let iag = Token { name: TokenName::IAG, id: String::from("iagon"), + decimals: 18.0, contract_address: String::from("0x40EB746DEE876aC1E78697b7Ca85142D178A1Fc8"), + recovered_total: 349_507_392.18740200, + currentPrice: 0.0054, }; let weth = Token { name: TokenName::WETH, id: String::from("weth"), + decimals: 18.0, contract_address: String::from("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), + recovered_total: 1_049.63562980, + currentPrice: 1425.31, }; let dai = Token { name: TokenName::DAI, id: String::from("dai"), + decimals: 18.0, contract_address: String::from("0x6B175474E89094C44Da98b954EedeAC495271d0F"), + recovered_total: 866_070.75687635, + currentPrice: 1.0, }; let c3 = Token { name: TokenName::C3, id: String::from("charli3"), + decimals: 18.0, contract_address: String::from("0xf1a91C7d44768070F711c68f33A7CA25c8D30268"), + recovered_total: 1_684_711.12239136, + currentPrice: 0.1673, }; let fxs = Token { name: TokenName::FXS, id: String::from("frax-share"), + decimals: 18.0, contract_address: String::from("0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0"), + recovered_total: 46_895.68804450, + currentPrice: 5.93, }; let cards = Token { name: TokenName::CARDS, id: String::from("cardstarter"), + decimals: 18.0, contract_address: String::from("0x3d6F0DEa3AC3C607B3998e6Ce14b6350721752d9"), + recovered_total: 165_005.81948028, + currentPrice: 0.2026, }; let hbot = Token { name: TokenName::HBOT, id: String::from("hummingbot"), + decimals: 18.0, contract_address: String::from("0xE5097D9baeAFB89f9bcB78C9290d545dB5f9e9CB"), + recovered_total: 900_239.99796600, + currentPrice: 0.0086, }; let sdl = Token { name: TokenName::SDL, id: String::from("saddle-finance"), + decimals: 18.0, contract_address: String::from("0xf1Dc500FdE233A4055e25e5BbF516372BC4F6871"), + recovered_total: 9_790.82405700, + currentPrice: 0.0, }; let gero = Token { name: TokenName::GERO, id: String::from("gerowallet"), + decimals: 18.0, contract_address: String::from("0x3431F91b3a388115F00C5Ba9FdB899851D005Fb5"), + recovered_total: 23_245_641.66618310, + currentPrice: 0.0, }; let address = "0xa4B86BcbB18639D8e708d6163a0c734aFcDB770c"; let token_vec = vec![ - usdc, cqt, usdt, wbtc, frax, iag, weth, dai, c3, fxs, cards, hbot, sdl, gero, + usdc, cqt, usdt, wbtc, frax, iag, weth, dai, c3, fxs, cards, hbot, ]; + let mut total_accessed_value = 0.0; for token in token_vec { - let balance: u128 = get_token_balance(&token, address).await?; + let balance: f64 = get_token_balance(&token, address).await?; + let accessed = token.recovered_total - balance; + total_accessed_value = total_accessed_value + (accessed * token.currentPrice); + println!("{}:{}", token.id, accessed); + // let token_price = get_token_price(&token).await?; - println!("{:?}", balance); - // println!("{:#?}",token_price); + // println!("{:#?}", token_price["ethereum"]); } + println!("total accessed value: ${}", total_accessed_value); + Ok(()) } async fn get_token_balance( token: &Token, address: &str, -) -> Result> { +) -> Result> { let etherscan_url = "https://api.etherscan.io/api"; let module = "account"; let action = "tokenbalance"; @@ -125,22 +173,34 @@ async fn get_token_balance( .await? .json::>() .await?; - let balance = resp["result"].parse().unwrap(); + let balance: f64 = resp["result"].parse().unwrap(); + let denominator = (10.0_f64).powf(token.decimals); + // println!("balance: {}/{}", balance, denominator); + let balance = balance / ((10.0_f64).powf(token.decimals)); + Ok(balance) } -async fn get_token_price(token: &Token) -> Result> { - let coingecko_url = "https://api.coingecko.com/api/v3/simple/price"; - let ids = "ethereum"; - let vs_currency = "usd"; - - let request_url = format!( - "{}?ids={}&vs_currencies={}", - coingecko_url, ids, vs_currency - ); - - let resp = reqwest::get(request_url).await?.json::().await?; - let price = resp; - println!("here"); - Ok(price) -} +// async fn get_token_price( +// token: &Token, +// ) -> Result, Box> { +// let coingecko_url = "https://api.coingecko.com/api/v3/simple/price"; +// let ids = "ethereum"; +// let vs_currency = "usd"; + +// let request_url = format!( +// "{}?ids={}&vs_currencies={}", +// coingecko_url, ids, vs_currency +// ); + +// let resp = reqwest::get(request_url) +// .await? +// .text() +// .await?; +// // let resp: &str = &resp.await?; +// let resp = serde_json::from_str(&resp)?; + +// dbg!(&resp); +// // println!("{:?}",resp); +// Ok(resp) +// } diff --git a/tools/accessed-funds-calculator/src/tokens.rs b/tools/accessed-funds-calculator/src/tokens.rs index cf6a90c5..704ae61d 100644 --- a/tools/accessed-funds-calculator/src/tokens.rs +++ b/tools/accessed-funds-calculator/src/tokens.rs @@ -20,5 +20,8 @@ pub enum TokenName { pub struct Token { pub name: TokenName, pub id: String, + pub decimals: f64, + pub currentPrice: f64, pub contract_address: String, + pub recovered_total: f64, } From b34e308d71472587bc0a9b58e4561e0b36ef0dc9 Mon Sep 17 00:00:00 2001 From: Ryan Swanson Date: Fri, 13 Jan 2023 09:39:44 -0500 Subject: [PATCH 06/17] updating to correct enum value --- tools/accessed-funds-calculator/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/accessed-funds-calculator/src/main.rs b/tools/accessed-funds-calculator/src/main.rs index d0f0927b..1602d716 100644 --- a/tools/accessed-funds-calculator/src/main.rs +++ b/tools/accessed-funds-calculator/src/main.rs @@ -28,7 +28,7 @@ async fn main() -> Result<(), Box> { }; let usdt = Token { - name: TokenName::WBTC, + name: TokenName::USDT, id: String::from("tether"), decimals: 6.0, contract_address: String::from("0xdAC17F958D2ee523a2206206994597C13D831ec7"), From 26106e66590c17f920ce92142ef188be82787784 Mon Sep 17 00:00:00 2001 From: Swanny Date: Fri, 13 Jan 2023 12:06:11 -0500 Subject: [PATCH 07/17] bumping to latest action versions --- .github/workflows/docker.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index abc48281..5b572ce6 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -15,15 +15,15 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: toolchain: stable - - uses: Swatinem/rust-cache@v1 + - uses: Swatinem/rust-cache@v2 with: # Add a key to prevent rust cache collision with rust.yml workflows key: 'release' - + - name: Build agents (release) run: cargo build --release @@ -43,14 +43,14 @@ jobs: type=sha - name: Login to Docker repository - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: registry: gcr.io username: _json_key password: ${{ secrets.GCLOUD_SERVICE_KEY }} - name: Build and push container - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v3 with: context: . push: true From f2ed2ccdaf538f4752d9a7edfe07dd37a8c7f4a9 Mon Sep 17 00:00:00 2001 From: Ryan Swanson Date: Mon, 16 Jan 2023 10:26:23 -0500 Subject: [PATCH 08/17] cleaning up quite a bit --- tools/accessed-funds-calculator/src/main.rs | 126 ++++++++---------- tools/accessed-funds-calculator/src/tokens.rs | 1 - 2 files changed, 53 insertions(+), 74 deletions(-) diff --git a/tools/accessed-funds-calculator/src/main.rs b/tools/accessed-funds-calculator/src/main.rs index 1602d716..0c084c80 100644 --- a/tools/accessed-funds-calculator/src/main.rs +++ b/tools/accessed-funds-calculator/src/main.rs @@ -1,8 +1,6 @@ use std::collections::HashMap; use std::env; -use serde_json; - mod tokens; use crate::tokens::{Token, TokenName}; @@ -11,128 +9,114 @@ use crate::tokens::{Token, TokenName}; async fn main() -> Result<(), Box> { let usdc = Token { name: TokenName::USDC, - id: String::from("usd-coin"), + id: "usd-coin".to_string(), decimals: 6.0, - contract_address: String::from("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"), + contract_address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48".to_string(), recovered_total: 12_890_538.932401, - currentPrice: 0.9992, }; let cqt = Token { name: TokenName::CQT, - id: String::from("covalent"), + id: "covalent".to_string(), decimals: 18.0, - contract_address: String::from("0xD417144312DbF50465b1C641d016962017Ef6240"), + contract_address: "0xD417144312DbF50465b1C641d016962017Ef6240".to_string(), recovered_total: 34_082_775.75159970, - currentPrice: 0.112701, }; let usdt = Token { name: TokenName::USDT, - id: String::from("tether"), + id: "tether".to_string(), decimals: 6.0, - contract_address: String::from("0xdAC17F958D2ee523a2206206994597C13D831ec7"), + contract_address: "0xdAC17F958D2ee523a2206206994597C13D831ec7".to_string(), recovered_total: 4_673_863.595197, - currentPrice: 0.9994, }; let wbtc = Token { name: TokenName::WBTC, - id: String::from("wrapped-bitcoin"), + id: "wrapped-bitcoin".to_string(), decimals: 8.0, - contract_address: String::from("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"), + contract_address: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599".to_string(), recovered_total: 280.73117399, - currentPrice: 18_805.78, }; let frax = Token { name: TokenName::FRAX, - id: String::from("frax"), + id: "frax".to_string(), decimals: 18.0, - contract_address: String::from("0x853d955aCEf822Db058eb8505911ED77F175b99e"), + contract_address: "0x853d955aCEf822Db058eb8505911ED77F175b99e".to_string(), recovered_total: 2_644_469.91860909, - currentPrice: 1.001, }; let iag = Token { name: TokenName::IAG, - id: String::from("iagon"), + id: "iagon".to_string(), decimals: 18.0, - contract_address: String::from("0x40EB746DEE876aC1E78697b7Ca85142D178A1Fc8"), + contract_address: "0x40EB746DEE876aC1E78697b7Ca85142D178A1Fc8".to_string(), recovered_total: 349_507_392.18740200, - currentPrice: 0.0054, }; let weth = Token { name: TokenName::WETH, - id: String::from("weth"), + id: "weth".to_string(), decimals: 18.0, - contract_address: String::from("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"), + contract_address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2".to_string(), recovered_total: 1_049.63562980, - currentPrice: 1425.31, }; let dai = Token { name: TokenName::DAI, - id: String::from("dai"), + id: "dai".to_string(), decimals: 18.0, - contract_address: String::from("0x6B175474E89094C44Da98b954EedeAC495271d0F"), + contract_address: "0x6B175474E89094C44Da98b954EedeAC495271d0F".to_string(), recovered_total: 866_070.75687635, - currentPrice: 1.0, }; let c3 = Token { name: TokenName::C3, - id: String::from("charli3"), + id: "charli3".to_string(), decimals: 18.0, - contract_address: String::from("0xf1a91C7d44768070F711c68f33A7CA25c8D30268"), + contract_address: "0xf1a91C7d44768070F711c68f33A7CA25c8D30268".to_string(), recovered_total: 1_684_711.12239136, - currentPrice: 0.1673, }; let fxs = Token { name: TokenName::FXS, - id: String::from("frax-share"), + id: "frax-share".to_string(), decimals: 18.0, - contract_address: String::from("0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0"), + contract_address: "0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0".to_string(), recovered_total: 46_895.68804450, - currentPrice: 5.93, }; let cards = Token { name: TokenName::CARDS, - id: String::from("cardstarter"), + id: "cardstarter".to_string(), decimals: 18.0, - contract_address: String::from("0x3d6F0DEa3AC3C607B3998e6Ce14b6350721752d9"), + contract_address: "0x3d6F0DEa3AC3C607B3998e6Ce14b6350721752d9".to_string(), recovered_total: 165_005.81948028, - currentPrice: 0.2026, }; let hbot = Token { name: TokenName::HBOT, - id: String::from("hummingbot"), + id: "hummingbot".to_string(), decimals: 18.0, - contract_address: String::from("0xE5097D9baeAFB89f9bcB78C9290d545dB5f9e9CB"), + contract_address: "0xE5097D9baeAFB89f9bcB78C9290d545dB5f9e9CB".to_string(), recovered_total: 900_239.99796600, - currentPrice: 0.0086, }; let sdl = Token { name: TokenName::SDL, - id: String::from("saddle-finance"), + id: "saddle-finance".to_string(), decimals: 18.0, - contract_address: String::from("0xf1Dc500FdE233A4055e25e5BbF516372BC4F6871"), + contract_address: "0xf1Dc500FdE233A4055e25e5BbF516372BC4F6871".to_string(), recovered_total: 9_790.82405700, - currentPrice: 0.0, }; let gero = Token { name: TokenName::GERO, - id: String::from("gerowallet"), + id: "gerowallet".to_string(), decimals: 18.0, - contract_address: String::from("0x3431F91b3a388115F00C5Ba9FdB899851D005Fb5"), + contract_address: "0x3431F91b3a388115F00C5Ba9FdB899851D005Fb5".to_string(), recovered_total: 23_245_641.66618310, - currentPrice: 0.0, }; let address = "0xa4B86BcbB18639D8e708d6163a0c734aFcDB770c"; @@ -145,14 +129,17 @@ async fn main() -> Result<(), Box> { for token in token_vec { let balance: f64 = get_token_balance(&token, address).await?; let accessed = token.recovered_total - balance; - total_accessed_value = total_accessed_value + (accessed * token.currentPrice); - println!("{}:{}", token.id, accessed); + let token_price = get_token_price(&token).await?; - // let token_price = get_token_price(&token).await?; - // println!("{:#?}", token_price["ethereum"]); + total_accessed_value = total_accessed_value + (accessed * token_price); + println!("{}:{} accessed, price: {}", token.id, accessed, token_price); } - println!("total accessed value: ${}", total_accessed_value); + println!("#################################################"); + println!("#################################################"); + println!("### total accessed value: ${} ###", total_accessed_value); + println!("#################################################"); + println!("#################################################"); Ok(()) } @@ -175,32 +162,25 @@ async fn get_token_balance( .await?; let balance: f64 = resp["result"].parse().unwrap(); let denominator = (10.0_f64).powf(token.decimals); - // println!("balance: {}/{}", balance, denominator); let balance = balance / ((10.0_f64).powf(token.decimals)); Ok(balance) } -// async fn get_token_price( -// token: &Token, -// ) -> Result, Box> { -// let coingecko_url = "https://api.coingecko.com/api/v3/simple/price"; -// let ids = "ethereum"; -// let vs_currency = "usd"; - -// let request_url = format!( -// "{}?ids={}&vs_currencies={}", -// coingecko_url, ids, vs_currency -// ); - -// let resp = reqwest::get(request_url) -// .await? -// .text() -// .await?; -// // let resp: &str = &resp.await?; -// let resp = serde_json::from_str(&resp)?; - -// dbg!(&resp); -// // println!("{:?}",resp); -// Ok(resp) -// } +async fn get_token_price(token: &Token) -> Result> { + let coingecko_url = "https://api.coingecko.com/api/v3/simple/price"; + let vs_currency = "usd"; + + let request_url = format!( + "{}?ids={}&vs_currencies={}", + coingecko_url, &token.id, vs_currency + ); + let resp = reqwest::get(request_url) + .await? + .json::>>() + .await?; + let price = resp[&token.id].clone(); + let price = price["usd"]; + + Ok(price) +} diff --git a/tools/accessed-funds-calculator/src/tokens.rs b/tools/accessed-funds-calculator/src/tokens.rs index 704ae61d..35ee4262 100644 --- a/tools/accessed-funds-calculator/src/tokens.rs +++ b/tools/accessed-funds-calculator/src/tokens.rs @@ -21,7 +21,6 @@ pub struct Token { pub name: TokenName, pub id: String, pub decimals: f64, - pub currentPrice: f64, pub contract_address: String, pub recovered_total: f64, } From 9f96ca4eca91af09e1132f3e9369e925286a9bda Mon Sep 17 00:00:00 2001 From: Ryan Swanson Date: Mon, 16 Jan 2023 10:59:44 -0500 Subject: [PATCH 09/17] cleaning up linter complaints --- tools/accessed-funds-calculator/src/main.rs | 61 +++++++++---------- tools/accessed-funds-calculator/src/tokens.rs | 26 ++++---- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/tools/accessed-funds-calculator/src/main.rs b/tools/accessed-funds-calculator/src/main.rs index 0c084c80..7da734a4 100644 --- a/tools/accessed-funds-calculator/src/main.rs +++ b/tools/accessed-funds-calculator/src/main.rs @@ -8,67 +8,67 @@ use crate::tokens::{Token, TokenName}; #[tokio::main] async fn main() -> Result<(), Box> { let usdc = Token { - name: TokenName::USDC, + name: TokenName::Usdc, id: "usd-coin".to_string(), decimals: 6.0, contract_address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48".to_string(), - recovered_total: 12_890_538.932401, + recovered_total: 12_890_538.932_401, }; let cqt = Token { - name: TokenName::CQT, + name: TokenName::Cqt, id: "covalent".to_string(), decimals: 18.0, contract_address: "0xD417144312DbF50465b1C641d016962017Ef6240".to_string(), - recovered_total: 34_082_775.75159970, + recovered_total: 34_082_775.751_599_7, }; let usdt = Token { - name: TokenName::USDT, + name: TokenName::Usdt, id: "tether".to_string(), decimals: 6.0, contract_address: "0xdAC17F958D2ee523a2206206994597C13D831ec7".to_string(), - recovered_total: 4_673_863.595197, + recovered_total: 4_673_863.595_197, }; let wbtc = Token { - name: TokenName::WBTC, + name: TokenName::Wbtc, id: "wrapped-bitcoin".to_string(), decimals: 8.0, contract_address: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599".to_string(), - recovered_total: 280.73117399, + recovered_total: 280.731_173_99, }; let frax = Token { - name: TokenName::FRAX, + name: TokenName::Frax, id: "frax".to_string(), decimals: 18.0, contract_address: "0x853d955aCEf822Db058eb8505911ED77F175b99e".to_string(), - recovered_total: 2_644_469.91860909, + recovered_total: 2_644_469.918_609_09, }; let iag = Token { - name: TokenName::IAG, + name: TokenName::Iag, id: "iagon".to_string(), decimals: 18.0, contract_address: "0x40EB746DEE876aC1E78697b7Ca85142D178A1Fc8".to_string(), - recovered_total: 349_507_392.18740200, + recovered_total: 349_507_392.187_402, }; let weth = Token { - name: TokenName::WETH, + name: TokenName::Weth, id: "weth".to_string(), decimals: 18.0, contract_address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2".to_string(), - recovered_total: 1_049.63562980, + recovered_total: 1_049.635_629_8, }; let dai = Token { - name: TokenName::DAI, + name: TokenName::Dai, id: "dai".to_string(), decimals: 18.0, contract_address: "0x6B175474E89094C44Da98b954EedeAC495271d0F".to_string(), - recovered_total: 866_070.75687635, + recovered_total: 866_070.756_876_35, }; let c3 = Token { @@ -76,53 +76,53 @@ async fn main() -> Result<(), Box> { id: "charli3".to_string(), decimals: 18.0, contract_address: "0xf1a91C7d44768070F711c68f33A7CA25c8D30268".to_string(), - recovered_total: 1_684_711.12239136, + recovered_total: 1_684_711.122_391_36, }; let fxs = Token { - name: TokenName::FXS, + name: TokenName::Fxs, id: "frax-share".to_string(), decimals: 18.0, contract_address: "0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0".to_string(), - recovered_total: 46_895.68804450, + recovered_total: 46_895.688_044_5, }; let cards = Token { - name: TokenName::CARDS, + name: TokenName::Cards, id: "cardstarter".to_string(), decimals: 18.0, contract_address: "0x3d6F0DEa3AC3C607B3998e6Ce14b6350721752d9".to_string(), - recovered_total: 165_005.81948028, + recovered_total: 165_005.819_480_28, }; let hbot = Token { - name: TokenName::HBOT, + name: TokenName::Hbot, id: "hummingbot".to_string(), decimals: 18.0, contract_address: "0xE5097D9baeAFB89f9bcB78C9290d545dB5f9e9CB".to_string(), - recovered_total: 900_239.99796600, + recovered_total: 900_239.997_966, }; let sdl = Token { - name: TokenName::SDL, + name: TokenName::Sdl, id: "saddle-finance".to_string(), decimals: 18.0, contract_address: "0xf1Dc500FdE233A4055e25e5BbF516372BC4F6871".to_string(), - recovered_total: 9_790.82405700, + recovered_total: 9_790.824_057, }; let gero = Token { - name: TokenName::GERO, + name: TokenName::Gero, id: "gerowallet".to_string(), decimals: 18.0, contract_address: "0x3431F91b3a388115F00C5Ba9FdB899851D005Fb5".to_string(), - recovered_total: 23_245_641.66618310, + recovered_total: 23_245_641.666_183_1, }; let address = "0xa4B86BcbB18639D8e708d6163a0c734aFcDB770c"; let token_vec = vec![ - usdc, cqt, usdt, wbtc, frax, iag, weth, dai, c3, fxs, cards, hbot, + usdc, cqt, usdt, wbtc, frax, iag, weth, dai, c3, fxs, cards, hbot, sdl, gero ]; let mut total_accessed_value = 0.0; @@ -151,17 +151,16 @@ async fn get_token_balance( let etherscan_url = "https://api.etherscan.io/api"; let module = "account"; let action = "tokenbalance"; - let apiKey = env::var("ETHERSCAN_KEY")?; + let api_key = env::var("ETHERSCAN_KEY")?; let request_url = format!( "{}?module={}&action={}&contractaddress={}&address={}&apiKey={}", - ðerscan_url, &module, &action, &token.contract_address, &address, &apiKey + ðerscan_url, &module, &action, &token.contract_address, &address, &api_key ); let resp = reqwest::get(request_url) .await? .json::>() .await?; let balance: f64 = resp["result"].parse().unwrap(); - let denominator = (10.0_f64).powf(token.decimals); let balance = balance / ((10.0_f64).powf(token.decimals)); Ok(balance) diff --git a/tools/accessed-funds-calculator/src/tokens.rs b/tools/accessed-funds-calculator/src/tokens.rs index 35ee4262..6efad9bf 100644 --- a/tools/accessed-funds-calculator/src/tokens.rs +++ b/tools/accessed-funds-calculator/src/tokens.rs @@ -1,19 +1,19 @@ #[derive(Debug)] pub enum TokenName { - USDC, - CQT, - USDT, - FRAX, - WBTC, - IAG, - WETH, - DAI, + Usdc, + Cqt, + Usdt, + Frax, + Wbtc, + Iag, + Weth, + Dai, C3, - FXS, - CARDS, - HBOT, - SDL, - GERO, + Fxs, + Cards, + Hbot, + Sdl, + Gero, } #[derive(Debug)] From 0747138c15ae0522cbe10b05cf9af4c1e7243cbd Mon Sep 17 00:00:00 2001 From: Ryan Swanson Date: Mon, 16 Jan 2023 11:02:36 -0500 Subject: [PATCH 10/17] cleaning up linter complaints --- tools/accessed-funds-calculator/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/accessed-funds-calculator/src/main.rs b/tools/accessed-funds-calculator/src/main.rs index 7da734a4..402d40a3 100644 --- a/tools/accessed-funds-calculator/src/main.rs +++ b/tools/accessed-funds-calculator/src/main.rs @@ -122,7 +122,7 @@ async fn main() -> Result<(), Box> { let address = "0xa4B86BcbB18639D8e708d6163a0c734aFcDB770c"; let token_vec = vec![ - usdc, cqt, usdt, wbtc, frax, iag, weth, dai, c3, fxs, cards, hbot, sdl, gero + usdc, cqt, usdt, wbtc, frax, iag, weth, dai, c3, fxs, cards, hbot, sdl, gero, ]; let mut total_accessed_value = 0.0; From 00ee6f1ffc1aa14700d64d64aeabb984035c8bc6 Mon Sep 17 00:00:00 2001 From: Ryan Swanson Date: Mon, 16 Jan 2023 11:10:59 -0500 Subject: [PATCH 11/17] cleaning up linter complaints --- tools/accessed-funds-calculator/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/accessed-funds-calculator/src/main.rs b/tools/accessed-funds-calculator/src/main.rs index 402d40a3..5738f11b 100644 --- a/tools/accessed-funds-calculator/src/main.rs +++ b/tools/accessed-funds-calculator/src/main.rs @@ -130,8 +130,8 @@ async fn main() -> Result<(), Box> { let balance: f64 = get_token_balance(&token, address).await?; let accessed = token.recovered_total - balance; let token_price = get_token_price(&token).await?; - - total_accessed_value = total_accessed_value + (accessed * token_price); + total_accessed_value += accessed * token_price; + println!("{}:{} accessed, price: {}", token.id, accessed, token_price); } From 7067f67c48c75e8a5517f4c80bf07d56195bcb9c Mon Sep 17 00:00:00 2001 From: Ryan Swanson Date: Mon, 16 Jan 2023 11:14:32 -0500 Subject: [PATCH 12/17] cleaning up linter complaints --- tools/accessed-funds-calculator/src/main.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/accessed-funds-calculator/src/main.rs b/tools/accessed-funds-calculator/src/main.rs index 5738f11b..1a20c560 100644 --- a/tools/accessed-funds-calculator/src/main.rs +++ b/tools/accessed-funds-calculator/src/main.rs @@ -131,7 +131,6 @@ async fn main() -> Result<(), Box> { let accessed = token.recovered_total - balance; let token_price = get_token_price(&token).await?; total_accessed_value += accessed * token_price; - println!("{}:{} accessed, price: {}", token.id, accessed, token_price); } From 2681ec44184c914ec568faf914abd6b2205a75f3 Mon Sep 17 00:00:00 2001 From: Ryan Swanson Date: Mon, 16 Jan 2023 13:26:55 -0500 Subject: [PATCH 13/17] refactor into a more testable structure --- tools/accessed-funds-calculator/src/main.rs | 143 ++------ tools/accessed-funds-calculator/src/tokens.rs | 308 ++++++++++++++++++ 2 files changed, 331 insertions(+), 120 deletions(-) diff --git a/tools/accessed-funds-calculator/src/main.rs b/tools/accessed-funds-calculator/src/main.rs index 1a20c560..9d579ec7 100644 --- a/tools/accessed-funds-calculator/src/main.rs +++ b/tools/accessed-funds-calculator/src/main.rs @@ -7,133 +7,36 @@ use crate::tokens::{Token, TokenName}; #[tokio::main] async fn main() -> Result<(), Box> { - let usdc = Token { - name: TokenName::Usdc, - id: "usd-coin".to_string(), - decimals: 6.0, - contract_address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48".to_string(), - recovered_total: 12_890_538.932_401, - }; - - let cqt = Token { - name: TokenName::Cqt, - id: "covalent".to_string(), - decimals: 18.0, - contract_address: "0xD417144312DbF50465b1C641d016962017Ef6240".to_string(), - recovered_total: 34_082_775.751_599_7, - }; - - let usdt = Token { - name: TokenName::Usdt, - id: "tether".to_string(), - decimals: 6.0, - contract_address: "0xdAC17F958D2ee523a2206206994597C13D831ec7".to_string(), - recovered_total: 4_673_863.595_197, - }; - - let wbtc = Token { - name: TokenName::Wbtc, - id: "wrapped-bitcoin".to_string(), - decimals: 8.0, - contract_address: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599".to_string(), - recovered_total: 280.731_173_99, - }; - - let frax = Token { - name: TokenName::Frax, - id: "frax".to_string(), - decimals: 18.0, - contract_address: "0x853d955aCEf822Db058eb8505911ED77F175b99e".to_string(), - recovered_total: 2_644_469.918_609_09, - }; - - let iag = Token { - name: TokenName::Iag, - id: "iagon".to_string(), - decimals: 18.0, - contract_address: "0x40EB746DEE876aC1E78697b7Ca85142D178A1Fc8".to_string(), - recovered_total: 349_507_392.187_402, - }; - - let weth = Token { - name: TokenName::Weth, - id: "weth".to_string(), - decimals: 18.0, - contract_address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2".to_string(), - recovered_total: 1_049.635_629_8, - }; - - let dai = Token { - name: TokenName::Dai, - id: "dai".to_string(), - decimals: 18.0, - contract_address: "0x6B175474E89094C44Da98b954EedeAC495271d0F".to_string(), - recovered_total: 866_070.756_876_35, - }; - - let c3 = Token { - name: TokenName::C3, - id: "charli3".to_string(), - decimals: 18.0, - contract_address: "0xf1a91C7d44768070F711c68f33A7CA25c8D30268".to_string(), - recovered_total: 1_684_711.122_391_36, - }; - - let fxs = Token { - name: TokenName::Fxs, - id: "frax-share".to_string(), - decimals: 18.0, - contract_address: "0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0".to_string(), - recovered_total: 46_895.688_044_5, - }; - - let cards = Token { - name: TokenName::Cards, - id: "cardstarter".to_string(), - decimals: 18.0, - contract_address: "0x3d6F0DEa3AC3C607B3998e6Ce14b6350721752d9".to_string(), - recovered_total: 165_005.819_480_28, - }; - - let hbot = Token { - name: TokenName::Hbot, - id: "hummingbot".to_string(), - decimals: 18.0, - contract_address: "0xE5097D9baeAFB89f9bcB78C9290d545dB5f9e9CB".to_string(), - recovered_total: 900_239.997_966, - }; - - let sdl = Token { - name: TokenName::Sdl, - id: "saddle-finance".to_string(), - decimals: 18.0, - contract_address: "0xf1Dc500FdE233A4055e25e5BbF516372BC4F6871".to_string(), - recovered_total: 9_790.824_057, - }; - - let gero = Token { - name: TokenName::Gero, - id: "gerowallet".to_string(), - decimals: 18.0, - contract_address: "0x3431F91b3a388115F00C5Ba9FdB899851D005Fb5".to_string(), - recovered_total: 23_245_641.666_183_1, - }; - let address = "0xa4B86BcbB18639D8e708d6163a0c734aFcDB770c"; - - let token_vec = vec![ + let usdc = Token::get_instance_of(TokenName::Usdc); + let usdt = Token::get_instance_of(TokenName::Usdt); + let cqt = Token::get_instance_of(TokenName::Cqt); + let wbtc = Token::get_instance_of(TokenName::Wbtc); + let frax = Token::get_instance_of(TokenName::Frax); + let iag = Token::get_instance_of(TokenName::Iag); + let weth = Token::get_instance_of(TokenName::Weth); + let dai = Token::get_instance_of(TokenName::Dai); + let c3 = Token::get_instance_of(TokenName::C3); + let fxs = Token::get_instance_of(TokenName::Fxs); + let cards = Token::get_instance_of(TokenName::Cards); + let hbot = Token::get_instance_of(TokenName::Hbot); + let sdl = Token::get_instance_of(TokenName::Sdl); + let gero = Token::get_instance_of(TokenName::Gero); + + let tokens: Vec = vec![ usdc, cqt, usdt, wbtc, frax, iag, weth, dai, c3, fxs, cards, hbot, sdl, gero, ]; - let mut total_accessed_value = 0.0; - for token in token_vec { + let mut total_accessed_value: f64 = 0.0; + for token in tokens { let balance: f64 = get_token_balance(&token, address).await?; - let accessed = token.recovered_total - balance; - let token_price = get_token_price(&token).await?; + let accessed: f64 = token.recovered_total - balance; + let token_price: f64 = get_token_price(&token).await?; total_accessed_value += accessed * token_price; println!("{}:{} accessed, price: {}", token.id, accessed, token_price); } - + + println!(); println!("#################################################"); println!("#################################################"); println!("### total accessed value: ${} ###", total_accessed_value); @@ -148,7 +51,7 @@ async fn get_token_balance( address: &str, ) -> Result> { let etherscan_url = "https://api.etherscan.io/api"; - let module = "account"; + let module= "account"; let action = "tokenbalance"; let api_key = env::var("ETHERSCAN_KEY")?; let request_url = format!( diff --git a/tools/accessed-funds-calculator/src/tokens.rs b/tools/accessed-funds-calculator/src/tokens.rs index 6efad9bf..737f4c0a 100644 --- a/tools/accessed-funds-calculator/src/tokens.rs +++ b/tools/accessed-funds-calculator/src/tokens.rs @@ -24,3 +24,311 @@ pub struct Token { pub contract_address: String, pub recovered_total: f64, } + +impl Token { + pub fn get_instance_of(token_name: TokenName) -> Token { + match token_name { + TokenName::Usdc => Token { + name: TokenName::Usdc, + id: "usd-coin".to_string(), + decimals: 6.0, + contract_address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48".to_string(), + recovered_total: 12_890_538.932_401, + }, + TokenName::Cqt => Token { + name: TokenName::Cqt, + id: "covalent".to_string(), + decimals: 18.0, + contract_address: "0xD417144312DbF50465b1C641d016962017Ef6240".to_string(), + recovered_total: 34_082_775.751_599_7, + }, + TokenName::Usdt => Token { + name: TokenName::Usdt, + id: "tether".to_string(), + decimals: 6.0, + contract_address: "0xdAC17F958D2ee523a2206206994597C13D831ec7".to_string(), + recovered_total: 4_673_863.595_197, + }, + TokenName::Frax => Token { + name: TokenName::Frax, + id: "frax".to_string(), + decimals: 18.0, + contract_address: "0x853d955aCEf822Db058eb8505911ED77F175b99e".to_string(), + recovered_total: 2_644_469.918_609_09, + }, + TokenName::Wbtc => Token { + name: TokenName::Wbtc, + id: "wrapped-bitcoin".to_string(), + decimals: 8.0, + contract_address: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599".to_string(), + recovered_total: 280.731_173_99, + }, + TokenName::Iag => Token { + name: TokenName::Iag, + id: "iagon".to_string(), + decimals: 18.0, + contract_address: "0x40EB746DEE876aC1E78697b7Ca85142D178A1Fc8".to_string(), + recovered_total: 349_507_392.187_402, + }, + TokenName::Weth => Token { + name: TokenName::Weth, + id: "weth".to_string(), + decimals: 18.0, + contract_address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2".to_string(), + recovered_total: 1_049.635_629_8, + }, + TokenName::Dai => Token { + name: TokenName::Dai, + id: "dai".to_string(), + decimals: 18.0, + contract_address: "0x6B175474E89094C44Da98b954EedeAC495271d0F".to_string(), + recovered_total: 866_070.756_876_35, + }, + TokenName::C3 => Token { + name: TokenName::C3, + id: "charli3".to_string(), + decimals: 18.0, + contract_address: "0xf1a91C7d44768070F711c68f33A7CA25c8D30268".to_string(), + recovered_total: 1_684_711.122_391_36, + }, + TokenName::Fxs => Token { + name: TokenName::Fxs, + id: "frax-share".to_string(), + decimals: 18.0, + contract_address: "0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0".to_string(), + recovered_total: 46_895.688_044_5, + }, + TokenName::Cards => Token { + name: TokenName::Cards, + id: "cardstarter".to_string(), + decimals: 18.0, + contract_address: "0x3d6F0DEa3AC3C607B3998e6Ce14b6350721752d9".to_string(), + recovered_total: 165_005.819_480_28, + }, + TokenName::Hbot => Token { + name: TokenName::Hbot, + id: "hummingbot".to_string(), + decimals: 18.0, + contract_address: "0xE5097D9baeAFB89f9bcB78C9290d545dB5f9e9CB".to_string(), + recovered_total: 900_239.997_966, + }, + TokenName::Sdl => Token { + name: TokenName::Sdl, + id: "saddle-finance".to_string(), + decimals: 18.0, + contract_address: "0xf1Dc500FdE233A4055e25e5BbF516372BC4F6871".to_string(), + recovered_total: 9_790.824_057, + }, + TokenName::Gero => Token { + name: TokenName::Gero, + id: "gerowallet".to_string(), + decimals: 18.0, + contract_address: "0x3431F91b3a388115F00C5Ba9FdB899851D005Fb5".to_string(), + recovered_total: 23_245_641.666_183_1, + } + } + } +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn validate_usdc() { + let usdc = Token { + name: TokenName::Usdc, + id: "usd-coin".to_string(), + decimals: 6.0, + contract_address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48".to_string(), + recovered_total: 12_890_538.932_401, + }; + let test_token = Token::get_instance_of(TokenName::Usdc); + assert_eq!(test_token.id, usdc.id); + assert_eq!(test_token.decimals, usdc.decimals); + assert_eq!(test_token.recovered_total, usdc.recovered_total); + } + #[test] + fn validate_cqt() { + let usdc = Token { + name: TokenName::Cqt, + id: "covalent".to_string(), + decimals: 18.0, + contract_address: "0xD417144312DbF50465b1C641d016962017Ef6240".to_string(), + recovered_total: 34_082_775.751_599_7, + }; + let test_token = Token::get_instance_of(TokenName::Cqt); + assert_eq!(test_token.id, usdc.id); + assert_eq!(test_token.decimals, usdc.decimals); + assert_eq!(test_token.recovered_total, usdc.recovered_total); + } + #[test] + fn validate_usdt() { + let usdc = Token { + name: TokenName::Usdt, + id: "tether".to_string(), + decimals: 6.0, + contract_address: "0xdAC17F958D2ee523a2206206994597C13D831ec7".to_string(), + recovered_total: 4_673_863.595_197, + }; + let test_token = Token::get_instance_of(TokenName::Usdt); + assert_eq!(test_token.id, usdc.id); + assert_eq!(test_token.decimals, usdc.decimals); + assert_eq!(test_token.recovered_total, usdc.recovered_total); + } + #[test] + fn validate_frax() { + let usdc = Token { + name: TokenName::Frax, + id: "frax".to_string(), + decimals: 18.0, + contract_address: "0x853d955aCEf822Db058eb8505911ED77F175b99e".to_string(), + recovered_total: 2_644_469.918_609_09, + }; + let test_token = Token::get_instance_of(TokenName::Frax); + assert_eq!(test_token.id, usdc.id); + assert_eq!(test_token.decimals, usdc.decimals); + assert_eq!(test_token.recovered_total, usdc.recovered_total); + } + #[test] + fn validate_wbtc() { + let usdc = Token { + name: TokenName::Wbtc, + id: "wrapped-bitcoin".to_string(), + decimals: 8.0, + contract_address: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599".to_string(), + recovered_total: 280.731_173_99, + }; + let test_token = Token::get_instance_of(TokenName::Wbtc); + assert_eq!(test_token.id, usdc.id); + assert_eq!(test_token.decimals, usdc.decimals); + assert_eq!(test_token.recovered_total, usdc.recovered_total); + } + #[test] + fn validate_iag() { + let usdc = Token { + name: TokenName::Iag, + id: "iagon".to_string(), + decimals: 18.0, + contract_address: "0x40EB746DEE876aC1E78697b7Ca85142D178A1Fc8".to_string(), + recovered_total: 349_507_392.187_402, + }; + let test_token = Token::get_instance_of(TokenName::Iag); + assert_eq!(test_token.id, usdc.id); + assert_eq!(test_token.decimals, usdc.decimals); + assert_eq!(test_token.recovered_total, usdc.recovered_total); + } + #[test] + fn validate_weth() { + let usdc = Token { + name: TokenName::Weth, + id: "weth".to_string(), + decimals: 18.0, + contract_address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2".to_string(), + recovered_total: 1_049.635_629_8, + }; + let test_token = Token::get_instance_of(TokenName::Weth); + assert_eq!(test_token.id, usdc.id); + assert_eq!(test_token.decimals, usdc.decimals); + assert_eq!(test_token.recovered_total, usdc.recovered_total); + } + #[test] + fn validate_dai() { + let usdc = Token { + name: TokenName::Dai, + id: "dai".to_string(), + decimals: 18.0, + contract_address: "0x6B175474E89094C44Da98b954EedeAC495271d0F".to_string(), + recovered_total: 866_070.756_876_35, + }; + let test_token = Token::get_instance_of(TokenName::Dai); + assert_eq!(test_token.id, usdc.id); + assert_eq!(test_token.decimals, usdc.decimals); + assert_eq!(test_token.recovered_total, usdc.recovered_total); + } + #[test] + fn validate_c3() { + let c3 = Token { + name: TokenName::C3, + id: "charli3".to_string(), + decimals: 18.0, + contract_address: "0xf1a91C7d44768070F711c68f33A7CA25c8D30268".to_string(), + recovered_total: 1_684_711.122_391_36, + }; + let test_token = Token::get_instance_of(TokenName::C3); + assert_eq!(test_token.id, c3.id); + assert_eq!(test_token.decimals, c3.decimals); + assert_eq!(test_token.recovered_total, c3.recovered_total); + } + #[test] + fn validate_fxs() { + let fxs = Token { + name: TokenName::Fxs, + id: "frax-share".to_string(), + decimals: 18.0, + contract_address: "0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0".to_string(), + recovered_total: 46_895.688_044_5, + }; + let test_token = Token::get_instance_of(TokenName::Fxs); + assert_eq!(test_token.id, fxs.id); + assert_eq!(test_token.decimals, fxs.decimals); + assert_eq!(test_token.recovered_total, fxs.recovered_total); + } + #[test] + fn validate_cards() { + let cards = Token { + name: TokenName::Cards, + id: "cardstarter".to_string(), + decimals: 18.0, + contract_address: "0x3d6F0DEa3AC3C607B3998e6Ce14b6350721752d9".to_string(), + recovered_total: 165_005.819_480_28, + }; + let test_token = Token::get_instance_of(TokenName::Cards); + assert_eq!(test_token.id, cards.id); + assert_eq!(test_token.decimals, cards.decimals); + assert_eq!(test_token.recovered_total, cards.recovered_total); + } + #[test] + fn validate_hbot() { + let hbot = Token { + name: TokenName::Hbot, + id: "hummingbot".to_string(), + decimals: 18.0, + contract_address: "0xE5097D9baeAFB89f9bcB78C9290d545dB5f9e9CB".to_string(), + recovered_total: 900_239.997_966, + }; + let test_token = Token::get_instance_of(TokenName::Hbot); + assert_eq!(test_token.id, hbot.id); + assert_eq!(test_token.decimals, hbot.decimals); + assert_eq!(test_token.recovered_total, hbot.recovered_total); + } + #[test] + fn validate_sdl() { + let sdl = Token { + name: TokenName::Sdl, + id: "saddle-finance".to_string(), + decimals: 18.0, + contract_address: "0xf1Dc500FdE233A4055e25e5BbF516372BC4F6871".to_string(), + recovered_total: 9_790.824_057, + }; + let test_token = Token::get_instance_of(TokenName::Sdl); + assert_eq!(test_token.id, sdl.id); + assert_eq!(test_token.decimals, sdl.decimals); + assert_eq!(test_token.recovered_total, sdl.recovered_total); + } + #[test] + fn validate_gero() { + let gero = Token { + name: TokenName::Gero, + id: "gerowallet".to_string(), + decimals: 18.0, + contract_address: "0x3431F91b3a388115F00C5Ba9FdB899851D005Fb5".to_string(), + recovered_total: 23_245_641.666_183_1, + }; + let test_token = Token::get_instance_of(TokenName::Gero); + assert_eq!(test_token.id, gero.id); + assert_eq!(test_token.decimals, gero.decimals); + assert_eq!(test_token.recovered_total, gero.recovered_total); + } +} \ No newline at end of file From e5f6d94132b8e1e5262315bba34b7cede6b3cd1e Mon Sep 17 00:00:00 2001 From: Ryan Swanson Date: Mon, 16 Jan 2023 13:29:37 -0500 Subject: [PATCH 14/17] forgot to fmt --- tools/accessed-funds-calculator/src/main.rs | 4 +- tools/accessed-funds-calculator/src/tokens.rs | 37 +++++++++---------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/tools/accessed-funds-calculator/src/main.rs b/tools/accessed-funds-calculator/src/main.rs index 9d579ec7..97a706d7 100644 --- a/tools/accessed-funds-calculator/src/main.rs +++ b/tools/accessed-funds-calculator/src/main.rs @@ -35,7 +35,7 @@ async fn main() -> Result<(), Box> { total_accessed_value += accessed * token_price; println!("{}:{} accessed, price: {}", token.id, accessed, token_price); } - + println!(); println!("#################################################"); println!("#################################################"); @@ -51,7 +51,7 @@ async fn get_token_balance( address: &str, ) -> Result> { let etherscan_url = "https://api.etherscan.io/api"; - let module= "account"; + let module = "account"; let action = "tokenbalance"; let api_key = env::var("ETHERSCAN_KEY")?; let request_url = format!( diff --git a/tools/accessed-funds-calculator/src/tokens.rs b/tools/accessed-funds-calculator/src/tokens.rs index 737f4c0a..5049f011 100644 --- a/tools/accessed-funds-calculator/src/tokens.rs +++ b/tools/accessed-funds-calculator/src/tokens.rs @@ -33,14 +33,14 @@ impl Token { id: "usd-coin".to_string(), decimals: 6.0, contract_address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48".to_string(), - recovered_total: 12_890_538.932_401, + recovered_total: 12_890_538.932_401, }, TokenName::Cqt => Token { name: TokenName::Cqt, id: "covalent".to_string(), decimals: 18.0, contract_address: "0xD417144312DbF50465b1C641d016962017Ef6240".to_string(), - recovered_total: 34_082_775.751_599_7, + recovered_total: 34_082_775.751_599_7, }, TokenName::Usdt => Token { name: TokenName::Usdt, @@ -125,12 +125,11 @@ impl Token { decimals: 18.0, contract_address: "0x3431F91b3a388115F00C5Ba9FdB899851D005Fb5".to_string(), recovered_total: 23_245_641.666_183_1, - } - } + }, + } } } - #[cfg(test)] mod tests { use super::*; @@ -156,8 +155,8 @@ mod tests { id: "covalent".to_string(), decimals: 18.0, contract_address: "0xD417144312DbF50465b1C641d016962017Ef6240".to_string(), - recovered_total: 34_082_775.751_599_7, - }; + recovered_total: 34_082_775.751_599_7, + }; let test_token = Token::get_instance_of(TokenName::Cqt); assert_eq!(test_token.id, usdc.id); assert_eq!(test_token.decimals, usdc.decimals); @@ -171,7 +170,7 @@ mod tests { decimals: 6.0, contract_address: "0xdAC17F958D2ee523a2206206994597C13D831ec7".to_string(), recovered_total: 4_673_863.595_197, - }; + }; let test_token = Token::get_instance_of(TokenName::Usdt); assert_eq!(test_token.id, usdc.id); assert_eq!(test_token.decimals, usdc.decimals); @@ -185,7 +184,7 @@ mod tests { decimals: 18.0, contract_address: "0x853d955aCEf822Db058eb8505911ED77F175b99e".to_string(), recovered_total: 2_644_469.918_609_09, - }; + }; let test_token = Token::get_instance_of(TokenName::Frax); assert_eq!(test_token.id, usdc.id); assert_eq!(test_token.decimals, usdc.decimals); @@ -199,7 +198,7 @@ mod tests { decimals: 8.0, contract_address: "0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599".to_string(), recovered_total: 280.731_173_99, - }; + }; let test_token = Token::get_instance_of(TokenName::Wbtc); assert_eq!(test_token.id, usdc.id); assert_eq!(test_token.decimals, usdc.decimals); @@ -213,7 +212,7 @@ mod tests { decimals: 18.0, contract_address: "0x40EB746DEE876aC1E78697b7Ca85142D178A1Fc8".to_string(), recovered_total: 349_507_392.187_402, - }; + }; let test_token = Token::get_instance_of(TokenName::Iag); assert_eq!(test_token.id, usdc.id); assert_eq!(test_token.decimals, usdc.decimals); @@ -241,7 +240,7 @@ mod tests { decimals: 18.0, contract_address: "0x6B175474E89094C44Da98b954EedeAC495271d0F".to_string(), recovered_total: 866_070.756_876_35, - }; + }; let test_token = Token::get_instance_of(TokenName::Dai); assert_eq!(test_token.id, usdc.id); assert_eq!(test_token.decimals, usdc.decimals); @@ -255,7 +254,7 @@ mod tests { decimals: 18.0, contract_address: "0xf1a91C7d44768070F711c68f33A7CA25c8D30268".to_string(), recovered_total: 1_684_711.122_391_36, - }; + }; let test_token = Token::get_instance_of(TokenName::C3); assert_eq!(test_token.id, c3.id); assert_eq!(test_token.decimals, c3.decimals); @@ -269,7 +268,7 @@ mod tests { decimals: 18.0, contract_address: "0x3432B6A60D23Ca0dFCa7761B7ab56459D9C964D0".to_string(), recovered_total: 46_895.688_044_5, - }; + }; let test_token = Token::get_instance_of(TokenName::Fxs); assert_eq!(test_token.id, fxs.id); assert_eq!(test_token.decimals, fxs.decimals); @@ -283,7 +282,7 @@ mod tests { decimals: 18.0, contract_address: "0x3d6F0DEa3AC3C607B3998e6Ce14b6350721752d9".to_string(), recovered_total: 165_005.819_480_28, - }; + }; let test_token = Token::get_instance_of(TokenName::Cards); assert_eq!(test_token.id, cards.id); assert_eq!(test_token.decimals, cards.decimals); @@ -297,7 +296,7 @@ mod tests { decimals: 18.0, contract_address: "0xE5097D9baeAFB89f9bcB78C9290d545dB5f9e9CB".to_string(), recovered_total: 900_239.997_966, - }; + }; let test_token = Token::get_instance_of(TokenName::Hbot); assert_eq!(test_token.id, hbot.id); assert_eq!(test_token.decimals, hbot.decimals); @@ -311,7 +310,7 @@ mod tests { decimals: 18.0, contract_address: "0xf1Dc500FdE233A4055e25e5BbF516372BC4F6871".to_string(), recovered_total: 9_790.824_057, - }; + }; let test_token = Token::get_instance_of(TokenName::Sdl); assert_eq!(test_token.id, sdl.id); assert_eq!(test_token.decimals, sdl.decimals); @@ -325,10 +324,10 @@ mod tests { decimals: 18.0, contract_address: "0x3431F91b3a388115F00C5Ba9FdB899851D005Fb5".to_string(), recovered_total: 23_245_641.666_183_1, - }; + }; let test_token = Token::get_instance_of(TokenName::Gero); assert_eq!(test_token.id, gero.id); assert_eq!(test_token.decimals, gero.decimals); assert_eq!(test_token.recovered_total, gero.recovered_total); } -} \ No newline at end of file +} From 12b0c4ac225fbd944d803633fc0bb5f134c0b762 Mon Sep 17 00:00:00 2001 From: Ryan Swanson Date: Mon, 16 Jan 2023 14:10:54 -0500 Subject: [PATCH 15/17] adding documentation --- tools/accessed-funds-calculator/CHANGELOG.md | 5 +++++ tools/accessed-funds-calculator/README.md | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 tools/accessed-funds-calculator/CHANGELOG.md create mode 100644 tools/accessed-funds-calculator/README.md diff --git a/tools/accessed-funds-calculator/CHANGELOG.md b/tools/accessed-funds-calculator/CHANGELOG.md new file mode 100644 index 00000000..21251ff4 --- /dev/null +++ b/tools/accessed-funds-calculator/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +### 1.0 + +- Added initial cli tool to calculate the total amount of recovered funds that have been accessed \ No newline at end of file diff --git a/tools/accessed-funds-calculator/README.md b/tools/accessed-funds-calculator/README.md new file mode 100644 index 00000000..67c08bf8 --- /dev/null +++ b/tools/accessed-funds-calculator/README.md @@ -0,0 +1,16 @@ +# Requirements + +- Needs a valid Etherscan API key to be configured in your local environment, or to be included with the run command +``` +export ETHERSCAN_KEY=YOUR_KEY +``` + +# Usage +*Using the binary:* +``` +./accessed_funds_calculator +``` +*Using cargo:* +``` +cargo run -p accessed-funds-calculator +``` From eee860c23e081156a0ec3d1b32adb10930016be8 Mon Sep 17 00:00:00 2001 From: Ryan Swanson Date: Mon, 16 Jan 2023 14:15:00 -0500 Subject: [PATCH 16/17] forgot to finish a few variable name refactors in tests --- tools/accessed-funds-calculator/src/tokens.rs | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/tools/accessed-funds-calculator/src/tokens.rs b/tools/accessed-funds-calculator/src/tokens.rs index 5049f011..0b26875e 100644 --- a/tools/accessed-funds-calculator/src/tokens.rs +++ b/tools/accessed-funds-calculator/src/tokens.rs @@ -150,7 +150,7 @@ mod tests { } #[test] fn validate_cqt() { - let usdc = Token { + let cqt = Token { name: TokenName::Cqt, id: "covalent".to_string(), decimals: 18.0, @@ -158,13 +158,13 @@ mod tests { recovered_total: 34_082_775.751_599_7, }; let test_token = Token::get_instance_of(TokenName::Cqt); - assert_eq!(test_token.id, usdc.id); - assert_eq!(test_token.decimals, usdc.decimals); - assert_eq!(test_token.recovered_total, usdc.recovered_total); + assert_eq!(test_token.id, cqt.id); + assert_eq!(test_token.decimals, cqt.decimals); + assert_eq!(test_token.recovered_total, cqt.recovered_total); } #[test] fn validate_usdt() { - let usdc = Token { + let usdt = Token { name: TokenName::Usdt, id: "tether".to_string(), decimals: 6.0, @@ -172,13 +172,13 @@ mod tests { recovered_total: 4_673_863.595_197, }; let test_token = Token::get_instance_of(TokenName::Usdt); - assert_eq!(test_token.id, usdc.id); - assert_eq!(test_token.decimals, usdc.decimals); - assert_eq!(test_token.recovered_total, usdc.recovered_total); + assert_eq!(test_token.id, usdt.id); + assert_eq!(test_token.decimals, usdt.decimals); + assert_eq!(test_token.recovered_total, usdt.recovered_total); } #[test] fn validate_frax() { - let usdc = Token { + let frax = Token { name: TokenName::Frax, id: "frax".to_string(), decimals: 18.0, @@ -186,13 +186,13 @@ mod tests { recovered_total: 2_644_469.918_609_09, }; let test_token = Token::get_instance_of(TokenName::Frax); - assert_eq!(test_token.id, usdc.id); - assert_eq!(test_token.decimals, usdc.decimals); - assert_eq!(test_token.recovered_total, usdc.recovered_total); + assert_eq!(test_token.id, frax.id); + assert_eq!(test_token.decimals, frax.decimals); + assert_eq!(test_token.recovered_total, frax.recovered_total); } #[test] fn validate_wbtc() { - let usdc = Token { + let wbtc = Token { name: TokenName::Wbtc, id: "wrapped-bitcoin".to_string(), decimals: 8.0, @@ -200,13 +200,13 @@ mod tests { recovered_total: 280.731_173_99, }; let test_token = Token::get_instance_of(TokenName::Wbtc); - assert_eq!(test_token.id, usdc.id); - assert_eq!(test_token.decimals, usdc.decimals); - assert_eq!(test_token.recovered_total, usdc.recovered_total); + assert_eq!(test_token.id, wbtc.id); + assert_eq!(test_token.decimals, wbtc.decimals); + assert_eq!(test_token.recovered_total, wbtc.recovered_total); } #[test] fn validate_iag() { - let usdc = Token { + let iag = Token { name: TokenName::Iag, id: "iagon".to_string(), decimals: 18.0, @@ -214,13 +214,13 @@ mod tests { recovered_total: 349_507_392.187_402, }; let test_token = Token::get_instance_of(TokenName::Iag); - assert_eq!(test_token.id, usdc.id); - assert_eq!(test_token.decimals, usdc.decimals); - assert_eq!(test_token.recovered_total, usdc.recovered_total); + assert_eq!(test_token.id, iag.id); + assert_eq!(test_token.decimals, iag.decimals); + assert_eq!(test_token.recovered_total, iag.recovered_total); } #[test] fn validate_weth() { - let usdc = Token { + let weth = Token { name: TokenName::Weth, id: "weth".to_string(), decimals: 18.0, @@ -228,13 +228,13 @@ mod tests { recovered_total: 1_049.635_629_8, }; let test_token = Token::get_instance_of(TokenName::Weth); - assert_eq!(test_token.id, usdc.id); - assert_eq!(test_token.decimals, usdc.decimals); - assert_eq!(test_token.recovered_total, usdc.recovered_total); + assert_eq!(test_token.id, weth.id); + assert_eq!(test_token.decimals, weth.decimals); + assert_eq!(test_token.recovered_total, weth.recovered_total); } #[test] fn validate_dai() { - let usdc = Token { + let dai = Token { name: TokenName::Dai, id: "dai".to_string(), decimals: 18.0, @@ -242,9 +242,9 @@ mod tests { recovered_total: 866_070.756_876_35, }; let test_token = Token::get_instance_of(TokenName::Dai); - assert_eq!(test_token.id, usdc.id); - assert_eq!(test_token.decimals, usdc.decimals); - assert_eq!(test_token.recovered_total, usdc.recovered_total); + assert_eq!(test_token.id, dai.id); + assert_eq!(test_token.decimals, dai.decimals); + assert_eq!(test_token.recovered_total, dai.recovered_total); } #[test] fn validate_c3() { From 5d32b0e3f0f31ebb9a554b9d456f1465fc03adbf Mon Sep 17 00:00:00 2001 From: Ryan Swanson Date: Mon, 16 Jan 2023 16:05:18 -0500 Subject: [PATCH 17/17] minor readme updates and more modularizing --- tools/accessed-funds-calculator/README.md | 16 ++++++++++++++-- tools/accessed-funds-calculator/src/main.rs | 4 ++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/tools/accessed-funds-calculator/README.md b/tools/accessed-funds-calculator/README.md index 67c08bf8..0d4227c4 100644 --- a/tools/accessed-funds-calculator/README.md +++ b/tools/accessed-funds-calculator/README.md @@ -1,11 +1,23 @@ -# Requirements +# Accessed Funds Calculator + +A quick and simple (and hopefully portable-ish) calculator to answer the question "how much has been accessed from the contract so far" +## Requirements - Needs a valid Etherscan API key to be configured in your local environment, or to be included with the run command ``` export ETHERSCAN_KEY=YOUR_KEY ``` +- Requires a valid etherscan api url +``` +export ETHERSCAN_API=https://api.etherscan.io/api +``` +- Requires a valid token price api +``` +export PRICING_API=https://api.coingecko.com/api/v3/simple/price +``` + -# Usage +## Usage *Using the binary:* ``` ./accessed_funds_calculator diff --git a/tools/accessed-funds-calculator/src/main.rs b/tools/accessed-funds-calculator/src/main.rs index 97a706d7..fa4c27b5 100644 --- a/tools/accessed-funds-calculator/src/main.rs +++ b/tools/accessed-funds-calculator/src/main.rs @@ -50,7 +50,7 @@ async fn get_token_balance( token: &Token, address: &str, ) -> Result> { - let etherscan_url = "https://api.etherscan.io/api"; + let etherscan_url = env::var("ETHERSCAN_API")?; let module = "account"; let action = "tokenbalance"; let api_key = env::var("ETHERSCAN_KEY")?; @@ -69,7 +69,7 @@ async fn get_token_balance( } async fn get_token_price(token: &Token) -> Result> { - let coingecko_url = "https://api.coingecko.com/api/v3/simple/price"; + let coingecko_url = env::var("PRICING_API")?; let vs_currency = "usd"; let request_url = format!(