Skip to content

Commit

Permalink
Merge #1362
Browse files Browse the repository at this point in the history
1362: Add an API-endpoint to grab the list of the tokens acceptable for fees r=popzxc a=AntonD3



Co-authored-by: AntonD3 <AntonV.Dyadyuk@gmail.com>
Co-authored-by: Chris Sosnin <chris125_@live.com>
  • Loading branch information
3 people authored Feb 2, 2021
2 parents 90eefbb + 4fb89bc commit bb7bc2a
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 1 deletion.
1 change: 1 addition & 0 deletions changelog/core.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ All notable changes to the core components will be documented in this file.
### Added

- `prometheus_exporter` is launched by every microservice.
- `tokens_acceptable_for_fees` endpoint that returns the list of tokens acceptable for fees was added to REST API v0.1.

### Fixed

Expand Down
4 changes: 4 additions & 0 deletions core/bin/zksync_api/src/api_server/rest/v01/api_decl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ impl ApiV01 {
.route("/testnet_config", web::get().to(Self::testnet_config))
.route("/status", web::get().to(Self::status))
.route("/tokens", web::get().to(Self::tokens))
.route(
"/tokens_acceptable_for_fees",
web::get().to(Self::tokens_acceptable_for_fees),
)
.route(
"/account/{address}/history/{offset}/{limit}",
web::get().to(Self::tx_history),
Expand Down
23 changes: 23 additions & 0 deletions core/bin/zksync_api/src/api_server/rest/v01/api_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::api_server::{
},
};
use actix_web::{web, HttpResponse, Result as ActixResult};
use num::{rational::Ratio, BigUint, FromPrimitive};
use std::time::Instant;
use zksync_storage::chain::operations_ext::SearchDirection;
use zksync_types::{Address, BlockNumber};
Expand Down Expand Up @@ -54,6 +55,28 @@ impl ApiV01 {
ok_json!(vec_tokens)
}

pub async fn tokens_acceptable_for_fees(self_: web::Data<Self>) -> ActixResult<HttpResponse> {
let start = Instant::now();

let liquidity_volume = Ratio::from(
BigUint::from_f64(self_.config.ticker.liquidity_volume)
.expect("TickerConfig::liquidity_volume must be positive"),
);

let mut storage = self_.access_storage().await?;
let tokens = storage
.tokens_schema()
.load_tokens_by_market_volume(liquidity_volume)
.await
.map_err(Self::db_error)?;

let mut tokens = tokens.values().cloned().collect::<Vec<_>>();
tokens.sort_by_key(|t| t.id);

metrics::histogram!("api.v01.tokens_acceptable_for_fees", start.elapsed());
ok_json!(tokens)
}

pub async fn tx_history(
self_: web::Data<Self>,
web::Path((address, mut offset, mut limit)): web::Path<(Address, u64, u64)>,
Expand Down
38 changes: 38 additions & 0 deletions core/lib/storage/sqlx-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,44 @@
"nullable": []
}
},
"2d70c5906b5c17523afd243c8be132f5b1724482e2f9d2795085455cafa0d6ce": {
"query": "\n SELECT id, address, symbol, decimals\n FROM tokens\n INNER JOIN ticker_market_volume\n ON tokens.id = ticker_market_volume.token_id\n WHERE ticker_market_volume.market_volume >= $1\n ORDER BY id ASC\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int4"
},
{
"ordinal": 1,
"name": "address",
"type_info": "Text"
},
{
"ordinal": 2,
"name": "symbol",
"type_info": "Text"
},
{
"ordinal": 3,
"name": "decimals",
"type_info": "Int2"
}
],
"parameters": {
"Left": [
"Numeric"
]
},
"nullable": [
false,
false,
false,
false
]
}
},
"2e92926816053cda2de6d571867a625fab5bb9668840db94bd18c411f96dc39b": {
"query": "SELECT * FROM blocks WHERE number = $1",
"describe": {
Expand Down
45 changes: 44 additions & 1 deletion core/lib/storage/src/tests/tokens.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// External imports
use num::{rational::Ratio, BigUint};
// Workspace imports
use zksync_types::{Token, TokenId, TokenLike, TokenPrice};
use zksync_types::{tokens::TokenMarketVolume, Token, TokenId, TokenLike, TokenPrice};
use zksync_utils::{big_decimal_to_ratio, ratio_to_big_decimal};
// Local imports
use crate::tests::db_test;
Expand Down Expand Up @@ -150,3 +150,46 @@ async fn test_ticker_price(mut storage: StorageProcessor<'_>) -> QueryResult<()>

Ok(())
}

/// Checks the store/load routine for `ticker_market_volume` table and load tokens by market volume.
#[db_test]
async fn test_market_volume(mut storage: StorageProcessor<'_>) -> QueryResult<()> {
const TOKEN_ID: TokenId = TokenId(0);

let market_volume = TokenMarketVolume {
market_volume: Ratio::new(BigUint::from(2u32), BigUint::from(5u32)),
last_updated: chrono::Utc::now(),
};

storage
.tokens_schema()
.update_token_market_volume(TOKEN_ID, market_volume.clone())
.await?;

let loaded = storage
.tokens_schema()
.get_token_market_volume(TOKEN_ID)
.await?
.expect("couldn't load market volume");

assert_eq!(loaded.market_volume, market_volume.market_volume);

assert_eq!(
loaded.last_updated.timestamp(),
market_volume.last_updated.timestamp()
);

let tokens = TokensSchema(&mut storage)
.load_tokens_by_market_volume(Ratio::new(BigUint::from(3u32), BigUint::from(5u32)))
.await
.expect("Load tokens by market volume query failed");
assert_eq!(tokens.len(), 0);

let tokens = TokensSchema(&mut storage)
.load_tokens_by_market_volume(Ratio::new(BigUint::from(2u32), BigUint::from(5u32)))
.await
.expect("Load tokens by market volume query failed");
assert_eq!(tokens.len(), 1);

Ok(())
}
35 changes: 35 additions & 0 deletions core/lib/storage/src/tokens/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use std::collections::HashMap;
use std::time::Instant;
// External imports
use num::{rational::Ratio, BigUint};
// Workspace imports
use zksync_types::{Token, TokenId, TokenLike, TokenPrice};
use zksync_utils::ratio_to_big_decimal;
Expand Down Expand Up @@ -73,6 +74,40 @@ impl<'a, 'c> TokensSchema<'a, 'c> {
result
}

/// Loads all the stored tokens, which have market_volume (ticker_market_volume table)
/// not less than parameter (min_market_volume)
pub async fn load_tokens_by_market_volume(
&mut self,
min_market_volume: Ratio<BigUint>,
) -> QueryResult<HashMap<TokenId, Token>> {
let start = Instant::now();
let tokens = sqlx::query_as!(
DbToken,
r#"
SELECT id, address, symbol, decimals
FROM tokens
INNER JOIN ticker_market_volume
ON tokens.id = ticker_market_volume.token_id
WHERE ticker_market_volume.market_volume >= $1
ORDER BY id ASC
"#,
ratio_to_big_decimal(&min_market_volume, STORED_USD_PRICE_PRECISION)
)
.fetch_all(self.0.conn())
.await?;

let result = Ok(tokens
.into_iter()
.map(|t| {
let token: Token = t.into();
(token.id, token)
})
.collect());

metrics::histogram!("sql.token.load_tokens_by_market_volume", start.elapsed());
result
}

/// Get the number of tokens from Database
pub async fn get_count(&mut self) -> QueryResult<i64> {
let start = Instant::now();
Expand Down
1 change: 1 addition & 0 deletions infrastructure/grafana/dashboards/api_v01.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ local metrics = [
"api.v01.status",
"api.v01.testnet_config",
"api.v01.tokens",
"api.v01.tokens_acceptable_for_fees",
"api.v01.tx_by_hash",
"api.v01.tx_history",
"api.v01.tx_history_newer_than",
Expand Down
1 change: 1 addition & 0 deletions infrastructure/grafana/dashboards/sql_token.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ local metrics = [
"sql.token.get_historical_ticker_price",
"sql.token.get_token",
"sql.token.load_tokens",
"sql.token.load_tokens_by_market_volume",
"sql.token.store_token",
"sql.token.update_historical_ticker_price",
"sql.token.update_market_volume",
Expand Down

0 comments on commit bb7bc2a

Please sign in to comment.