diff --git a/.env.example b/.env.example index f1ba3a8..164db02 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ NODE_PROVIDER_API_KEY= -COINCAP_API_KEY= +COIN_MARKET_CAP_API_KEY= TWITTER_OAUTH2_CLIENT_ID= TWITTER_OAUTH2_CLIENT_SECRET= diff --git a/crates/starkwhale-alert/src/api.rs b/crates/starkwhale-alert/src/api.rs index fc2f031..c7f0cc3 100644 --- a/crates/starkwhale-alert/src/api.rs +++ b/crates/starkwhale-alert/src/api.rs @@ -1,5 +1,4 @@ use crate::consts::Token; -use reqwest::{header, header::HeaderValue}; use serde::{Deserialize, Serialize}; use starknet::{ core::{ @@ -11,65 +10,50 @@ use starknet::{ JsonRpcClient, Provider, ProviderError, }, }; +use std::collections::HashMap; use std::time::Duration; #[derive(Debug, Serialize, Deserialize)] struct FetchCoinResponse { - data: Data, - timestamp: u64, + data: HashMap, } #[derive(Debug, Serialize, Deserialize)] struct Data { - id: String, - rank: String, - symbol: String, - name: String, - supply: String, - #[serde(rename = "maxSupply")] - max_supply: Option, - #[serde(rename = "marketCapUsd")] - market_cap_usd: String, - #[serde(rename = "volumeUsd24Hr")] - volume_usd_24_hr: String, - #[serde(rename = "priceUsd")] - price_usd: String, - #[serde(rename = "changePercent24Hr")] - change_percent_24_hr: String, - #[serde(rename = "vwap24Hr")] - vwap_24_hr: String, + quote: HashMap, } -pub async fn fetch_coin(coin_id: &str) -> Result { - let token = dotenv!("COINCAP_API_KEY"); - - let mut headers = reqwest::header::HeaderMap::new(); - let auth = format!("Bearer {token}"); - headers.insert( - header::CONTENT_TYPE, - HeaderValue::from_static("application/json"), - ); - headers.insert( - header::AUTHORIZATION, - HeaderValue::try_from(auth).expect("Unable to parse the Bearer token"), - ); +#[derive(Debug, Serialize, Deserialize)] +struct Quote { + price: f64, +} - let client = reqwest::Client::builder() - .default_headers(headers) - .build()?; +pub async fn fetch_coin(coin_id: &str) -> Result { + let token = dotenv!("COIN_MARKET_CAP_API_KEY"); - let get_link: String = format!("{}{}", "https://api.coincap.io/v2/assets/", coin_id); + let client = reqwest::Client::builder().build()?; let coin_info: FetchCoinResponse = client - .get(get_link) - .header("Accept", "text/plain") + .get("https://pro-api.coinmarketcap.com/v2/cryptocurrency/quotes/latest") + .header("Accepts", "application/json") + .header("X-CMC_PRO_API_KEY", token) + .query(&[("slug", coin_id)]) + .query(&[("convert", "USD")]) .timeout(Duration::from_secs(3)) .send() .await? .json() .await?; - - Ok(coin_info.data.price_usd.parse().expect("Error: fetch_coin")) + Ok(coin_info + .data + .values() + .into_iter() + .next() + .expect("fetch_coin: data map issue") + .quote + .get("USD") + .expect("fetch_coin: quote map issue") + .price) } pub async fn fetch_events( @@ -120,6 +104,8 @@ mod tests { #[case("ethereum")] #[case("usd-coin")] #[case("tether")] + #[case("multi-collateral-dai")] + #[case("starknet-token")] #[tokio::test] async fn test_fetch_coin(#[case] coin: &str) { let value = fetch_coin(coin).await.unwrap(); diff --git a/crates/starkwhale-alert/src/consts.rs b/crates/starkwhale-alert/src/consts.rs index 17be5b6..7f2eaa0 100644 --- a/crates/starkwhale-alert/src/consts.rs +++ b/crates/starkwhale-alert/src/consts.rs @@ -50,9 +50,9 @@ pub const TOKENS: &[Token] = &[ decimals: 18, symbol: "STRK", selector: "Transfer", - threshold: 150_000, + threshold: 500_000, logo: "", - rate_api_id: None, + rate_api_id: Some("starknet-token"), }, ]; diff --git a/crates/starkwhale-alert/src/formatter.rs b/crates/starkwhale-alert/src/formatter.rs index c141f3c..672f7c9 100644 --- a/crates/starkwhale-alert/src/formatter.rs +++ b/crates/starkwhale-alert/src/formatter.rs @@ -97,7 +97,7 @@ async fn format_address(address: FieldElement) -> String { mod tests { use super::{format_address, get_formatted_text, to_rounded}; - use crate::to_u256; + use crate::{consts::TOKENS, to_u256}; use starknet::core::types::{EmittedEvent, FieldElement}; #[tokio::test] @@ -132,7 +132,7 @@ mod tests { ) .unwrap(), }; - let response = get_formatted_text(emitted_event, &USDC).await; + let response = get_formatted_text(emitted_event, &TOKENS[1]).await; println!("{response}"); assert!( response @@ -173,7 +173,7 @@ mod tests { ) .unwrap(), }; - let response = get_formatted_text(emitted_event, &USDC).await; + let response = get_formatted_text(emitted_event, &TOKENS[1]).await; assert!( response == "1,000,000 #USDC $ (1,000,000 USD)\n0x6e1...b3ce bridged to Ethereum L1\nhttps://starkscan.co/tx/0x732b09d901fb0075d283ac23cbaae4f8c486123a88a621eeaa05d0b5ddfb8d8", @@ -216,7 +216,7 @@ mod tests { ) .unwrap(), }; - let response = get_formatted_text(emitted_event, &USDC).await; + let response = get_formatted_text(emitted_event, &TOKENS[1]).await; assert!( response == "1,000,000 #USDC $ (1,000,000 USD)\nFrom 0x6e1...b3ce to 0x6e1...b3ce\nhttps://starkscan.co/tx/0x732b09d901fb0075d283ac23cbaae4f8c486123a88a621eeaa05d0b5ddfb8d8", diff --git a/crates/starkwhale-alert/src/main.rs b/crates/starkwhale-alert/src/main.rs index 0b5d6e3..47e1d44 100644 --- a/crates/starkwhale-alert/src/main.rs +++ b/crates/starkwhale-alert/src/main.rs @@ -99,7 +99,7 @@ async fn get_events_to_tweet_about( fn check_valid_env() { dotenv().ok(); - std::env::var("COINCAP_API_KEY").expect("COINCAP_API_KEY must be set."); + std::env::var("COIN_MARKET_CAP_API_KEY").expect("COIN_MARKET_CAP_API_KEY must be set."); std::env::var("NODE_PROVIDER_API_KEY").expect("NODE_PROVIDER_API_KEY must be set."); std::env::var("TWITTER_OAUTH2_CLIENT_ID").expect("TWITTER_OAUTH2_CLIENT_ID must be set."); std::env::var("TWITTER_OAUTH2_CLIENT_SECRET")