From 44f71794a66a32f565048636ea5b05aea190653a Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Fri, 20 Oct 2023 10:19:08 +0400 Subject: [PATCH] feat: Remove fee_ticker and token_trading_volume fetcher modules (#262) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # What ❔ - Removes `fee_ticker` module. - Removes `token_trading_volume` fetcher. - Removes some (now unused) methods from DAL. - Removes some (now unused) types. ## Why ❔ Dead code. ## Checklist - [x] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [ ] ~~Tests for the changes have been added / updated.~~ - [ ] ~~Documentation comments have been added / updated.~~ - [x] Code has been formatted via `zk fmt` and `zk lint`. --- core/lib/dal/sqlx-data.json | 95 ----------- core/lib/dal/src/models/storage_token.rs | 42 +---- core/lib/dal/src/tokens_dal.rs | 38 +---- core/lib/dal/src/tokens_web3_dal.rs | 70 +-------- core/lib/types/src/tokens.rs | 8 - .../src/api_server/web3/namespaces/zks.rs | 27 ++-- core/lib/zksync_core/src/data_fetchers/mod.rs | 3 - .../token_trading_volume/mock.rs | 41 ----- .../data_fetchers/token_trading_volume/mod.rs | 129 --------------- .../token_trading_volume/uniswap.rs | 147 ------------------ core/lib/zksync_core/src/fee_ticker/error.rs | 12 -- .../zksync_core/src/fee_ticker/gas_price.rs | 8 - core/lib/zksync_core/src/fee_ticker/mod.rs | 92 ----------- core/lib/zksync_core/src/fee_ticker/types.rs | 5 - core/lib/zksync_core/src/lib.rs | 1 - 15 files changed, 19 insertions(+), 699 deletions(-) delete mode 100644 core/lib/zksync_core/src/data_fetchers/token_trading_volume/mock.rs delete mode 100644 core/lib/zksync_core/src/data_fetchers/token_trading_volume/mod.rs delete mode 100644 core/lib/zksync_core/src/data_fetchers/token_trading_volume/uniswap.rs delete mode 100644 core/lib/zksync_core/src/fee_ticker/error.rs delete mode 100644 core/lib/zksync_core/src/fee_ticker/gas_price.rs delete mode 100644 core/lib/zksync_core/src/fee_ticker/mod.rs delete mode 100644 core/lib/zksync_core/src/fee_ticker/types.rs diff --git a/core/lib/dal/sqlx-data.json b/core/lib/dal/sqlx-data.json index 9e67a374002..15333648fb7 100644 --- a/core/lib/dal/sqlx-data.json +++ b/core/lib/dal/sqlx-data.json @@ -2712,38 +2712,6 @@ }, "query": "INSERT INTO eth_txs_history\n (eth_tx_id, base_fee_per_gas, priority_fee_per_gas, tx_hash, signed_raw_tx, created_at, updated_at, confirmed_at)\n VALUES ($1, 0, 0, $2, '\\x00', now(), now(), $3)\n RETURNING id" }, - "393345441797999e9f11b8b5ddce0b64356e1e167056d7f76ef6dfffd3534607": { - "describe": { - "columns": [ - { - "name": "name!", - "ordinal": 0, - "type_info": "Varchar" - }, - { - "name": "symbol!", - "ordinal": 1, - "type_info": "Varchar" - }, - { - "name": "decimals!", - "ordinal": 2, - "type_info": "Int4" - } - ], - "nullable": [ - null, - null, - null - ], - "parameters": { - "Left": [ - "Bytea" - ] - } - }, - "query": "\n SELECT\n COALESCE(token_list_name, name) as \"name!\",\n COALESCE(token_list_symbol, symbol) as \"symbol!\",\n COALESCE(token_list_decimals, decimals) as \"decimals!\"\n FROM tokens WHERE l2_address = $1\n " - }, "394bbd64939d47fda4e1545e2752b208901e872b7234a5c3af456bdf429a6074": { "describe": { "columns": [ @@ -3003,20 +2971,6 @@ }, "query": "DELETE FROM events WHERE miniblock_number > $1" }, - "3de5668eca2211f9701304e374100d45b359b1f7832d4a30b325fa679012c3e7": { - "describe": { - "columns": [], - "nullable": [], - "parameters": { - "Left": [ - "Bytea", - "Numeric", - "Timestamp" - ] - } - }, - "query": "UPDATE tokens SET market_volume = $2, market_volume_updated_at = $3, updated_at = now() WHERE l1_address = $1" - }, "3f6332706376ef4cadda96498872429b6ed28eca5402b03b1aa3b77b8262bccd": { "describe": { "columns": [], @@ -7691,29 +7645,6 @@ }, "query": "SELECT l1_batch_number FROM initial_writes WHERE hashed_key = $1" }, - "a9b7a880dbde4f7de5a6c2ff4009281527f2d01a547228981af3af2129ffb3f7": { - "describe": { - "columns": [ - { - "name": "count!", - "ordinal": 0, - "type_info": "Int8" - } - ], - "nullable": [ - null - ], - "parameters": { - "Left": [ - "Bytea", - "Numeric", - "Interval", - "Interval" - ] - } - }, - "query": "\n SELECT COUNT(*) as \"count!\" FROM tokens\n WHERE l2_address = $1 AND\n market_volume > $2 AND now() - market_volume_updated_at < $3 AND\n usd_price > 0 AND now() - usd_price_updated_at < $4\n " - }, "a9d96d6774af2637173d471f02995652cd4c131c05fdcb3d0e1644bcd1aa1809": { "describe": { "columns": [ @@ -7985,32 +7916,6 @@ }, "query": "\n UPDATE scheduler_witness_jobs\n SET aggregation_result_coords = $1,\n updated_at = now()\n WHERE l1_batch_number = $2\n " }, - "adc9ad2c944f9dacc28b5bd133aa37d9e8ea99eca1c5dfbeef37cda4b793f434": { - "describe": { - "columns": [ - { - "name": "market_volume", - "ordinal": 0, - "type_info": "Numeric" - }, - { - "name": "market_volume_updated_at", - "ordinal": 1, - "type_info": "Timestamp" - } - ], - "nullable": [ - true, - true - ], - "parameters": { - "Left": [ - "Bytea" - ] - } - }, - "query": "SELECT market_volume, market_volume_updated_at FROM tokens WHERE l2_address = $1" - }, "ae072f51b65d0b5212264be9a34027922e5aedef7e4741517ad8104bf5aa79e9": { "describe": { "columns": [], diff --git a/core/lib/dal/src/models/storage_token.rs b/core/lib/dal/src/models/storage_token.rs index 1c1e3539f06..1cc42405fe2 100644 --- a/core/lib/dal/src/models/storage_token.rs +++ b/core/lib/dal/src/models/storage_token.rs @@ -3,26 +3,9 @@ use sqlx::types::{ BigDecimal, }; -use zksync_types::tokens::{TokenMarketVolume, TokenMetadata, TokenPrice}; +use zksync_types::tokens::TokenPrice; use zksync_utils::big_decimal_to_ratio; -#[derive(Debug, Clone, sqlx::FromRow)] -pub struct StorageTokenMetadata { - pub name: String, - pub symbol: String, - pub decimals: i32, -} - -impl From for TokenMetadata { - fn from(metadata: StorageTokenMetadata) -> TokenMetadata { - TokenMetadata { - name: metadata.name, - symbol: metadata.symbol, - decimals: metadata.decimals as u8, - } - } -} - #[derive(Debug, Clone, sqlx::FromRow)] pub struct StorageTokenPrice { pub usd_price: Option, @@ -48,26 +31,3 @@ impl From for Option { } } } - -#[derive(Debug, Clone, sqlx::FromRow)] -pub struct StorageTokenMarketVolume { - pub market_volume: Option, - pub market_volume_updated_at: Option, -} - -impl From for Option { - fn from(market_volume: StorageTokenMarketVolume) -> Option { - market_volume - .market_volume - .as_ref() - .map(|volume| TokenMarketVolume { - market_volume: big_decimal_to_ratio(volume).unwrap(), - last_updated: DateTime::::from_naive_utc_and_offset( - market_volume - .market_volume_updated_at - .expect("If `market_volume` is Some then `updated_at` must be Some"), - Utc, - ), - }) - } -} diff --git a/core/lib/dal/src/tokens_dal.rs b/core/lib/dal/src/tokens_dal.rs index 8b32b714073..f7b64aed69e 100644 --- a/core/lib/dal/src/tokens_dal.rs +++ b/core/lib/dal/src/tokens_dal.rs @@ -1,9 +1,8 @@ -use crate::models::storage_token::StorageTokenMarketVolume; use crate::StorageProcessor; use num::{rational::Ratio, BigUint}; use sqlx::types::chrono::Utc; use zksync_types::{ - tokens::{TokenInfo, TokenMarketVolume, TokenMetadata, TokenPrice}, + tokens::{TokenInfo, TokenMetadata, TokenPrice}, Address, MiniblockNumber, ACCOUNT_CODE_STORAGE_ADDRESS, FAILED_CONTRACT_DEPLOYMENT_BYTECODE_HASH, }; @@ -158,41 +157,6 @@ impl TokensDal<'_, '_> { } } - pub async fn set_l1_token_market_volume( - &mut self, - l1_address: &Address, - market_volume: TokenMarketVolume, - ) { - { - sqlx::query!( - "UPDATE tokens SET market_volume = $2, market_volume_updated_at = $3, updated_at = now() WHERE l1_address = $1", - l1_address.as_bytes(), - ratio_to_big_decimal(&market_volume.market_volume, STORED_USD_PRICE_PRECISION), - market_volume.last_updated.naive_utc(), - ) - .execute(self.storage.conn()) - .await - .unwrap(); - } - } - - pub async fn get_token_market_volume( - &mut self, - l2_address: &Address, - ) -> Option { - { - let storage_market_volume = sqlx::query_as!( - StorageTokenMarketVolume, - "SELECT market_volume, market_volume_updated_at FROM tokens WHERE l2_address = $1", - l2_address.as_bytes(), - ) - .fetch_optional(self.storage.conn()) - .await - .unwrap(); - storage_market_volume.and_then(Into::into) - } - } - pub async fn rollback_tokens(&mut self, block_number: MiniblockNumber) { { sqlx::query!( diff --git a/core/lib/dal/src/tokens_web3_dal.rs b/core/lib/dal/src/tokens_web3_dal.rs index 58e9a7ec9a6..aa3674b6c3d 100644 --- a/core/lib/dal/src/tokens_web3_dal.rs +++ b/core/lib/dal/src/tokens_web3_dal.rs @@ -1,16 +1,10 @@ -use crate::models::storage_token::{StorageTokenMetadata, StorageTokenPrice}; +use crate::models::storage_token::StorageTokenPrice; use crate::SqlxError; use crate::StorageProcessor; -use num::{rational::Ratio, BigUint}; -use sqlx::postgres::types::PgInterval; use zksync_types::{ tokens::{TokenInfo, TokenMetadata, TokenPrice}, Address, }; -use zksync_utils::ratio_to_big_decimal; - -// Precision of the USD price per token -pub(crate) const STORED_USD_PRICE_PRECISION: usize = 6; #[derive(Debug)] pub struct TokensWeb3Dal<'a, 'c> { @@ -43,45 +37,6 @@ impl TokensWeb3Dal<'_, '_> { } } - pub async fn is_token_actively_trading( - &mut self, - l2_token: &Address, - min_volume: &Ratio, - max_acceptable_volume_age_in_secs: u32, - max_acceptable_price_age_in_secs: u32, - ) -> Result { - { - let min_volume = ratio_to_big_decimal(min_volume, STORED_USD_PRICE_PRECISION); - let volume_pg_interval = PgInterval { - months: 0, - days: 0, - microseconds: (max_acceptable_volume_age_in_secs as i64) * 1000000, - }; - let price_pg_interval = PgInterval { - months: 0, - days: 0, - microseconds: (max_acceptable_price_age_in_secs as i64) * 1000000, - }; - let count = sqlx::query!( - r#" - SELECT COUNT(*) as "count!" FROM tokens - WHERE l2_address = $1 AND - market_volume > $2 AND now() - market_volume_updated_at < $3 AND - usd_price > 0 AND now() - usd_price_updated_at < $4 - "#, - l2_token.as_bytes(), - min_volume, - volume_pg_interval, - price_pg_interval - ) - .fetch_one(self.storage.conn()) - .await - .unwrap() - .count; - Ok(count == 1) - } - } - pub async fn get_token_price( &mut self, l2_address: &Address, @@ -98,27 +53,4 @@ impl TokensWeb3Dal<'_, '_> { Ok(storage_price.and_then(Into::into)) } } - - pub async fn get_token_metadata( - &mut self, - l2_address: &Address, - ) -> Result, SqlxError> { - { - let storage_token_metadata = sqlx::query_as!( - StorageTokenMetadata, - r#" - SELECT - COALESCE(token_list_name, name) as "name!", - COALESCE(token_list_symbol, symbol) as "symbol!", - COALESCE(token_list_decimals, decimals) as "decimals!" - FROM tokens WHERE l2_address = $1 - "#, - l2_address.as_bytes(), - ) - .fetch_optional(self.storage.conn()) - .await?; - - Ok(storage_token_metadata.map(Into::into)) - } - } } diff --git a/core/lib/types/src/tokens.rs b/core/lib/types/src/tokens.rs index 45d97fee2e3..c4b85cb0e21 100644 --- a/core/lib/types/src/tokens.rs +++ b/core/lib/types/src/tokens.rs @@ -43,11 +43,3 @@ pub struct TokenPrice { pub usd_price: Ratio, pub last_updated: DateTime, } - -/// Token price known to the zkSync network. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct TokenMarketVolume { - #[serde(with = "UnsignedRatioSerializeAsDecimal")] - pub market_volume: Ratio, - pub last_updated: DateTime, -} diff --git a/core/lib/zksync_core/src/api_server/web3/namespaces/zks.rs b/core/lib/zksync_core/src/api_server/web3/namespaces/zks.rs index a5f133868b9..c7cfbe4b7a1 100644 --- a/core/lib/zksync_core/src/api_server/web3/namespaces/zks.rs +++ b/core/lib/zksync_core/src/api_server/web3/namespaces/zks.rs @@ -18,7 +18,7 @@ use zksync_types::{ L1BatchNumber, MiniblockNumber, Transaction, L1_MESSENGER_ADDRESS, L2_ETH_TOKEN_ADDRESS, MAX_GAS_PER_PUBDATA_BYTE, REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_BYTE, U256, U64, }; -use zksync_utils::address_to_h256; +use zksync_utils::{address_to_h256, ratio_to_big_decimal_normalized}; use zksync_web3_decl::{ error::Web3Error, types::{Address, Filter, Log, Token, H256}, @@ -27,7 +27,6 @@ use zksync_web3_decl::{ use crate::api_server::web3::{ backend_jsonrpc::error::internal_error, metrics::API_METRICS, RpcState, }; -use crate::fee_ticker::{error::TickerError, FeeTicker, TokenPriceRequestType}; use crate::l1_gas_price::L1GasPriceProvider; #[derive(Debug)] @@ -178,6 +177,13 @@ impl ZksNamespace { pub async fn get_token_price_impl(&self, l2_token: Address) -> Result { const METHOD_NAME: &str = "get_token_price"; + /// Amount of possible symbols after the decimal dot in the USD. + /// Used to convert `Ratio` to `BigDecimal`. + const USD_PRECISION: usize = 100; + /// Minimum amount of symbols after the decimal dot in the USD. + /// Used to convert `Ratio` to `BigDecimal`. + const MIN_PRECISION: usize = 2; + let method_latency = API_METRICS.start_call(METHOD_NAME); let token_price_result = { let mut storage = self @@ -186,20 +192,19 @@ impl ZksNamespace { .access_storage_tagged("api") .await .unwrap(); - let mut tokens_web3_dal = storage.tokens_web3_dal(); - FeeTicker::get_l2_token_price( - &mut tokens_web3_dal, - TokenPriceRequestType::USDForOneToken, - &l2_token, - ) - .await + storage.tokens_web3_dal().get_token_price(&l2_token).await }; let result = match token_price_result { - Ok(price) => Ok(price), - Err(TickerError::PriceNotTracked(_)) => Ok(BigDecimal::zero()), + Ok(Some(price)) => Ok(ratio_to_big_decimal_normalized( + &price.usd_price, + USD_PRECISION, + MIN_PRECISION, + )), + Ok(None) => Ok(BigDecimal::zero()), Err(err) => Err(internal_error(METHOD_NAME, err)), }; + method_latency.observe(); result } diff --git a/core/lib/zksync_core/src/data_fetchers/mod.rs b/core/lib/zksync_core/src/data_fetchers/mod.rs index ce62a657d97..f04a80c315e 100644 --- a/core/lib/zksync_core/src/data_fetchers/mod.rs +++ b/core/lib/zksync_core/src/data_fetchers/mod.rs @@ -17,7 +17,6 @@ use zksync_dal::ConnectionPool; pub mod error; pub mod token_list; pub mod token_price; -pub mod token_trading_volume; pub fn run_data_fetchers( config: &FetcherConfig, @@ -27,11 +26,9 @@ pub fn run_data_fetchers( ) -> Vec>> { let list_fetcher = token_list::TokenListFetcher::new(config.clone(), network); let price_fetcher = token_price::TokenPriceFetcher::new(config.clone()); - let volume_fetcher = token_trading_volume::TradingVolumeFetcher::new(config.clone()); vec![ tokio::spawn(list_fetcher.run(pool.clone(), stop_receiver.clone())), tokio::spawn(price_fetcher.run(pool.clone(), stop_receiver.clone())), - tokio::spawn(volume_fetcher.run(pool, stop_receiver)), ] } diff --git a/core/lib/zksync_core/src/data_fetchers/token_trading_volume/mock.rs b/core/lib/zksync_core/src/data_fetchers/token_trading_volume/mock.rs deleted file mode 100644 index 8aab1c6bb50..00000000000 --- a/core/lib/zksync_core/src/data_fetchers/token_trading_volume/mock.rs +++ /dev/null @@ -1,41 +0,0 @@ -use std::collections::HashMap; - -use async_trait::async_trait; -use bigdecimal::FromPrimitive; -use chrono::Utc; -use num::{rational::Ratio, BigUint}; -use zksync_types::{tokens::TokenMarketVolume, Address}; - -use crate::data_fetchers::error::ApiFetchError; - -use super::FetcherImpl; - -#[derive(Debug, Clone)] -pub struct MockTradingVolumeFetcher {} - -impl MockTradingVolumeFetcher { - pub fn new() -> Self { - Self {} - } - - pub fn volume(&self, _token: &Address) -> TokenMarketVolume { - TokenMarketVolume { - market_volume: Ratio::from(BigUint::from_u64(1).unwrap()), // We don't use volume in the server anymore. - last_updated: Utc::now(), - } - } -} - -#[async_trait] -impl FetcherImpl for MockTradingVolumeFetcher { - async fn fetch_trading_volumes( - &self, - tokens: &[Address], - ) -> Result, ApiFetchError> { - let volumes: HashMap<_, _> = tokens - .iter() - .map(|token| (*token, self.volume(token))) - .collect(); - Ok(volumes) - } -} diff --git a/core/lib/zksync_core/src/data_fetchers/token_trading_volume/mod.rs b/core/lib/zksync_core/src/data_fetchers/token_trading_volume/mod.rs deleted file mode 100644 index c4cf1250135..00000000000 --- a/core/lib/zksync_core/src/data_fetchers/token_trading_volume/mod.rs +++ /dev/null @@ -1,129 +0,0 @@ -//! Token trading volume fetcher loads the information about how good tokens are being traded on exchanges. -//! We need this information in order to either accept or deny paying fees in a certain tokens: -//! we are only interested in tokens that can be sold to cover expences for the network maintenance. - -use std::{collections::HashMap, time::Duration}; - -use async_trait::async_trait; -use tokio::sync::watch; - -use zksync_config::{configs::fetcher::TokenTradingVolumeSource, FetcherConfig}; -use zksync_dal::{ConnectionPool, StorageProcessor}; -use zksync_types::{tokens::TokenMarketVolume, Address}; - -use super::error::{ApiFetchError, ErrorAnalyzer}; - -mod mock; -mod uniswap; - -#[async_trait] -pub trait FetcherImpl: std::fmt::Debug + Send + Sync { - /// Retrieves the list of known tokens. - async fn fetch_trading_volumes( - &self, - tokens: &[Address], - ) -> Result, ApiFetchError>; -} - -#[derive(Debug)] -pub struct TradingVolumeFetcher { - config: FetcherConfig, - fetcher: Box, - error_handler: ErrorAnalyzer, -} - -impl TradingVolumeFetcher { - fn create_fetcher(config: &FetcherConfig) -> Box { - let token_trading_volume_config = &config.token_trading_volume; - match token_trading_volume_config.source { - TokenTradingVolumeSource::Uniswap => { - Box::new(uniswap::UniswapTradingVolumeFetcher::new(config)) as Box - } - TokenTradingVolumeSource::Mock => { - Box::new(mock::MockTradingVolumeFetcher::new()) as Box - } - } - } - - pub fn new(config: FetcherConfig) -> Self { - let fetcher = Self::create_fetcher(&config); - let error_handler = ErrorAnalyzer::new("TradingVolumeFetcher"); - Self { - config, - fetcher, - error_handler, - } - } - - pub async fn run( - mut self, - pool: ConnectionPool, - stop_receiver: watch::Receiver, - ) -> anyhow::Result<()> { - let mut fetching_interval = - tokio::time::interval(self.config.token_trading_volume.fetching_interval()); - loop { - if *stop_receiver.borrow() { - tracing::info!("Stop signal received, trading_volume_fetcher is shutting down"); - break; - } - - fetching_interval.tick().await; - self.error_handler.update().await; - - let mut storage = pool.access_storage().await.unwrap(); - let known_l1_tokens = self.load_tokens(&mut storage).await; - - let trading_volumes = match self.fetch_trading_volumes(&known_l1_tokens).await { - Ok(volumes) => { - self.error_handler.reset(); - volumes - } - Err(err) => { - self.error_handler.process_error(err); - continue; - } - }; - - self.store_market_volumes(&mut storage, trading_volumes) - .await; - } - Ok(()) - } - - async fn fetch_trading_volumes( - &self, - addresses: &[Address], - ) -> Result, ApiFetchError> { - const AWAITING_TIMEOUT: Duration = Duration::from_secs(2); - - let fetch_future = self.fetcher.fetch_trading_volumes(addresses); - - tokio::time::timeout(AWAITING_TIMEOUT, fetch_future) - .await - .map_err(|_| ApiFetchError::RequestTimeout)? - } - - async fn store_market_volumes( - &self, - storage: &mut StorageProcessor<'_>, - tokens: HashMap, - ) { - let mut tokens_dal = storage.tokens_dal(); - for (token, volume) in tokens { - tokens_dal.set_l1_token_market_volume(&token, volume).await; - } - } - - /// Returns the list of tokens with known metadata (if token is not in the list we use, - /// it's very likely to not have required level of trading volume anyways). - async fn load_tokens(&self, storage: &mut StorageProcessor<'_>) -> Vec
{ - storage - .tokens_dal() - .get_well_known_token_addresses() - .await - .into_iter() - .map(|(l1_token, _)| l1_token) - .collect() - } -} diff --git a/core/lib/zksync_core/src/data_fetchers/token_trading_volume/uniswap.rs b/core/lib/zksync_core/src/data_fetchers/token_trading_volume/uniswap.rs deleted file mode 100644 index 4f4d2495d07..00000000000 --- a/core/lib/zksync_core/src/data_fetchers/token_trading_volume/uniswap.rs +++ /dev/null @@ -1,147 +0,0 @@ -use std::{collections::HashMap, str::FromStr}; - -use async_trait::async_trait; -use chrono::Utc; -use itertools::Itertools; -use num::{rational::Ratio, BigUint}; -use reqwest::{Client, Url}; -use serde::{Deserialize, Serialize}; - -use zksync_config::FetcherConfig; -use zksync_types::{tokens::TokenMarketVolume, Address}; -use zksync_utils::UnsignedRatioSerializeAsDecimal; - -use crate::data_fetchers::error::ApiFetchError; - -use super::FetcherImpl; - -#[derive(Debug, Clone)] -pub struct UniswapTradingVolumeFetcher { - client: Client, - addr: Url, -} - -impl UniswapTradingVolumeFetcher { - pub fn new(config: &FetcherConfig) -> Self { - Self { - client: Client::new(), - addr: Url::from_str(&config.token_trading_volume.url) - .expect("failed parse Uniswap URL"), - } - } -} - -#[async_trait] -impl FetcherImpl for UniswapTradingVolumeFetcher { - async fn fetch_trading_volumes( - &self, - tokens: &[Address], - ) -> Result, ApiFetchError> { - let comma_separated_token_addresses = tokens - .iter() - .map(|token_addr| format!("\"{:#x}\"", token_addr)) - .join(","); - - let query = format!( - "{{tokens(where:{{id_in:[{}]}}){{id, untrackedVolumeUSD}}}}", - comma_separated_token_addresses - ); - - let last_updated = Utc::now(); - - let raw_response = self - .client - .post(self.addr.clone()) - .json(&serde_json::json!({ - "query": query, - })) - .send() - .await - .map_err(|err| { - ApiFetchError::ApiUnavailable(format!("Uniswap API request failed: {}", err)) - })?; - - let response_status = raw_response.status(); - let response_text = raw_response.text().await.map_err(|err| { - ApiFetchError::Other(format!( - "Error: {} while while decoding response to text", - err - )) - })?; - - let response: GraphqlResponse = serde_json::from_str(&response_text).map_err(|err| { - ApiFetchError::UnexpectedJsonFormat(format!( - "Error: {} while decoding response: {} with status: {}", - err, response_text, response_status - )) - })?; - - let result = response - .data - .tokens - .into_iter() - .map(|token_response| { - ( - token_response.id, - TokenMarketVolume { - market_volume: token_response.untracked_volume_usd, - last_updated, - }, - ) - }) - .collect(); - - Ok(result) - } -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct GraphqlResponse { - pub data: GraphqlTokensResponse, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct GraphqlTokensResponse { - pub tokens: Vec, -} - -#[derive(Serialize, Deserialize, Debug)] -pub struct TokenResponse { - pub id: Address, - /// Total amount swapped all time in token pair stored in USD, no minimum liquidity threshold. - #[serde( - with = "UnsignedRatioSerializeAsDecimal", - rename = "untrackedVolumeUSD" - )] - pub untracked_volume_usd: Ratio, -} - -#[tokio::test] -#[ignore] // Remote API may be unavailable, so we ignore this test by default. -async fn test_fetch_uniswap_trading_volumes() { - let mut config = FetcherConfig::from_env().unwrap(); - config.token_trading_volume.url = - "https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2".to_string(); - - let fetcher = UniswapTradingVolumeFetcher::new(&config); - - let tokens = vec![ - Address::from_str("6b175474e89094c44da98b954eedeac495271d0f").expect("DAI"), - Address::from_str("1f9840a85d5af5bf1d1762f925bdaddc4201f984").expect("UNI"), - Address::from_str("514910771af9ca656af840dff83e8264ecf986ca").expect("LINK"), - ]; - - let token_volumes = fetcher - .fetch_trading_volumes(&tokens) - .await - .expect("failed get tokens price"); - - assert_eq!( - token_volumes.len(), - tokens.len(), - "not all data was received" - ); - for token_address in tokens { - assert!(token_volumes.get(&token_address).is_some()); - } -} diff --git a/core/lib/zksync_core/src/fee_ticker/error.rs b/core/lib/zksync_core/src/fee_ticker/error.rs deleted file mode 100644 index a7e2dceaa8e..00000000000 --- a/core/lib/zksync_core/src/fee_ticker/error.rs +++ /dev/null @@ -1,12 +0,0 @@ -use thiserror::Error; -use zksync_types::Address; - -#[derive(Debug, Error)] -pub enum TickerError { - #[error("Token {0:x} is not being tracked for its price")] - PriceNotTracked(Address), - #[error("Third-party API data is temporarily unavailable")] - ApiDataUnavailable, - #[error("Fee ticker internal error")] - InternalError, -} diff --git a/core/lib/zksync_core/src/fee_ticker/gas_price.rs b/core/lib/zksync_core/src/fee_ticker/gas_price.rs deleted file mode 100644 index 3c4cff6991f..00000000000 --- a/core/lib/zksync_core/src/fee_ticker/gas_price.rs +++ /dev/null @@ -1,8 +0,0 @@ -//! This module contains the logic used to calculate the price of 1 gas in Wei. - -use num::{rational::Ratio, BigUint}; - -/// Converts any token price in USD into one Wei price per USD. -pub fn token_price_to_wei_price_usd(token_price: &Ratio, decimals: u32) -> Ratio { - token_price / BigUint::from(10u32).pow(decimals) -} diff --git a/core/lib/zksync_core/src/fee_ticker/mod.rs b/core/lib/zksync_core/src/fee_ticker/mod.rs deleted file mode 100644 index 3589c9e30b3..00000000000 --- a/core/lib/zksync_core/src/fee_ticker/mod.rs +++ /dev/null @@ -1,92 +0,0 @@ -//! This module defines the price components of L2 transactions. - -use core::fmt::Debug; - -use bigdecimal::BigDecimal; -use multivm::vm_latest::utils::fee::base_fee_to_gas_per_pubdata; -use num::{rational::Ratio, BigUint}; -use zksync_types::Address; -use zksync_utils::ratio_to_big_decimal_normalized; - -use self::error::TickerError; -use zksync_dal::tokens_web3_dal::TokensWeb3Dal; - -pub mod error; -mod gas_price; -pub mod types; - -/// Amount of possible symbols after the decimal dot in the USD. -/// Used to convert `Ratio` to `BigDecimal`. -pub const USD_PRECISION: usize = 100; - -/// Minimum amount of symbols after the decimal dot in the USD. -/// Used to convert `Ratio` to `BigDecimal`. -pub const MIN_PRECISION: usize = 2; - -#[derive(Debug, PartialEq, Eq)] -pub enum TokenPriceRequestType { - USDForOneWei, - USDForOneToken, -} - -#[derive(Debug, Default)] -pub struct FeeTicker; - -impl FeeTicker { - /// Returns the token price in USD. - pub async fn get_l2_token_price( - tokens_web3_dal: &mut TokensWeb3Dal<'_, '_>, - request_type: TokenPriceRequestType, - l2_token_addr: &Address, - ) -> Result { - Self::get_l2_token_price_inner(tokens_web3_dal, request_type, l2_token_addr) - .await - .map(|final_price| { - ratio_to_big_decimal_normalized(&final_price, USD_PRECISION, MIN_PRECISION) - }) - } - - /// Returns the acceptable `gas_per_pubdata_byte` based on the current gas price. - pub fn gas_per_pubdata_byte(gas_price_wei: u64, base_fee: u64) -> u32 { - base_fee_to_gas_per_pubdata(gas_price_wei, base_fee) as u32 - } - - async fn get_l2_token_price_inner( - tokens_web3_dal: &mut TokensWeb3Dal<'_, '_>, - request_type: TokenPriceRequestType, - l2_token_addr: &Address, - ) -> Result, TickerError> { - let token_price = tokens_web3_dal - .get_token_price(l2_token_addr) - .await - .map_err(|_| TickerError::InternalError)? - .ok_or(TickerError::PriceNotTracked(*l2_token_addr))? - .usd_price; - - let final_price = match request_type { - TokenPriceRequestType::USDForOneToken => token_price, - TokenPriceRequestType::USDForOneWei => { - let token_metadata = tokens_web3_dal - .get_token_metadata(l2_token_addr) - .await - .map_err(|_| TickerError::InternalError)? - .ok_or_else(|| { - // It's kinda not OK that we have a price for token, but no metadata. - // Not a reason for a panic, but surely highest possible report level. - tracing::error!( - "Token {:x} has price, but no stored metadata", - l2_token_addr - ); - TickerError::PriceNotTracked(*l2_token_addr) - })?; - - gas_price::token_price_to_wei_price_usd( - &token_price, - token_metadata.decimals as u32, - ) - } - }; - - Ok(final_price) - } -} diff --git a/core/lib/zksync_core/src/fee_ticker/types.rs b/core/lib/zksync_core/src/fee_ticker/types.rs deleted file mode 100644 index daedb6f4a6d..00000000000 --- a/core/lib/zksync_core/src/fee_ticker/types.rs +++ /dev/null @@ -1,5 +0,0 @@ -#[derive(Debug, PartialEq, Eq)] -pub enum TokenPriceRequestType { - USDForOneWei, - USDForOneToken, -} diff --git a/core/lib/zksync_core/src/lib.rs b/core/lib/zksync_core/src/lib.rs index 319a9aae1dd..f0e9f57d878 100644 --- a/core/lib/zksync_core/src/lib.rs +++ b/core/lib/zksync_core/src/lib.rs @@ -53,7 +53,6 @@ pub mod consistency_checker; pub mod data_fetchers; pub mod eth_sender; pub mod eth_watch; -pub mod fee_ticker; pub mod gas_tracker; pub mod genesis; pub mod house_keeper;