Skip to content

Commit

Permalink
Optimize: get assets. (#250)
Browse files Browse the repository at this point in the history
  • Loading branch information
s1q1ch4n authored Apr 7, 2024
1 parent 7c16c9b commit 75371e6
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 166 deletions.
2 changes: 2 additions & 0 deletions explorer/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod service;
use crate::service::api::Api;
use crate::service::v2::asset::get_assets;
use crate::service::v2::block::{get_block_by_hash, get_block_by_num, get_blocks};
use crate::service::v2::transaction::{get_tx_by_hash, get_txs};
use anyhow::Result;
Expand Down Expand Up @@ -51,6 +52,7 @@ async fn main() -> Result<()> {
.route("/api/v2/blocks", get(get_blocks))
.route("/api/v2/hash/tx", get(get_tx_by_hash))
.route("/api/v2/txs", get(get_txs))
.route("/api/v2/assets", get(get_assets))
.layer(cors)
.with_state(app_state);
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
Expand Down
194 changes: 67 additions & 127 deletions explorer/src/service/v2/asset.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,24 @@
use crate::service::api::Api;
use anyhow::Result;
use poem_openapi::param::Query;
use poem_openapi::{payload::Json, ApiResponse, Object};
use reqwest::StatusCode;
use crate::service::v2::error::internal_error;
use crate::service::v2::error::Result;
use crate::service::v2::QueryResult;
use crate::AppState;
use axum::extract::{Query, State};
use axum::Json;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use sqlx::Row;
use std::ops::Add;
use std::sync::Arc;

#[derive(ApiResponse)]
pub enum V2AssetTxResponse {
#[oai(status = 200)]
Ok(Json<V2AssetTxResult>),
#[oai(status = 404)]
NotFound(Json<V2AssetTxResult>),
#[oai(status = 500)]
InternalError(Json<V2AssetTxResult>),
#[derive(Serialize, Deserialize)]
pub struct GetAssetsParams {
pub address: Option<String>,
pub page: Option<i32>,
pub page_size: Option<i32>,
}

#[derive(Serialize, Deserialize, Debug, Object)]
pub struct V2AssetTxResult {
pub code: u16,
pub message: String,
pub data: Option<V2AssetData>,
}

#[derive(Serialize, Deserialize, Debug, Object)]
pub struct V2AssetData {
pub page: i32,
pub page_size: i32,
pub total: i64,
pub assets: Vec<V2AssetOp>,
}

#[derive(Serialize, Deserialize, Debug, Object)]
pub struct V2AssetOp {
#[derive(Serialize, Deserialize, Debug)]
pub struct AssetResponse {
pub asset: String,
pub tx: String,
pub block: String,
Expand All @@ -43,102 +28,61 @@ pub struct V2AssetOp {
pub ty: i32,
pub value: Value,
}
#[allow(dead_code)]
pub async fn v2_get_asset(
api: &Api,
address: Query<String>,
page: Query<Option<i32>>,
page_size: Query<Option<i32>>,
) -> Result<V2AssetTxResponse> {
let mut conn = api.storage.lock().await.acquire().await?;
let mut assets: Vec<V2AssetOp> = vec![];
let page = page.0.unwrap_or(1);
let page_size = page_size.0.unwrap_or(10);
let sql_total = format!(
"SELECT count(*) as cnt from assets WHERE asset='{}'",
address.0
);
let row_count = sqlx::query(sql_total.as_str())
.fetch_one(&mut *conn)
.await?;
let total: i64 = row_count.try_get("cnt")?;
let sql_query = format!(
"SELECT asset,tx,block,issuer,height,timestamp,ty,content from assets WHERE asset='{}' order by height desc limit {} offset {}",
address.0,
page_size,
(page - 1) * page_size
);

let rows = sqlx::query(sql_query.as_str())
.fetch_all(&mut *conn)
.await?;
for row in rows {
let asset: String = row.try_get("asset")?;
let tx: String = row.try_get("tx")?;
let block: String = row.try_get("block")?;
let issuer: String = row.try_get("issuer")?;
let height: i64 = row.try_get("height")?;
let timestamp: i64 = row.try_get("timestamp")?;
let ty: i32 = row.try_get("ty")?;
let value: Value = row.try_get("content")?;
assets.push(V2AssetOp {
asset,
tx,
block,
issuer,
height,
timestamp,
ty,
value,
});
}
pub async fn get_assets(
State(state): State<Arc<AppState>>,
Query(params): Query<GetAssetsParams>,
) -> Result<Json<QueryResult<Vec<AssetResponse>>>> {
let mut conn = state.pool.acquire().await.map_err(internal_error)?;
let page = params.page.unwrap_or(1);
let page_size = params.page_size.unwrap_or(10);

Ok(V2AssetTxResponse::Ok(Json(V2AssetTxResult {
code: StatusCode::OK.as_u16(),
message: "".to_string(),
data: Some(V2AssetData {
page,
let mut sql_total = "SELECT count(*) FROM assets ".to_string();
let mut sql_query =
"SELECT asset,tx,block,issuer,height,timestamp,ty,content FROM assets ".to_string();
let mut query_params: Vec<String> = vec![];
if let Some(addr) = params.address {
query_params.push(format!("asset='{}' ", addr));
}
if !query_params.is_empty() {
sql_query = sql_query
.add("WHERE ")
.add(query_params.join("AND ").as_str());
sql_total = sql_total
.add("WHERE ")
.add(query_params.join("AND ").as_str());
}
sql_query = sql_query.add(
format!(
"ORDER BY timestamp DESC LIMIT {} OFFSET {} ",
page_size,
total,
assets,
}),
})))
}
#[allow(dead_code)]
pub async fn v2_get_asset_list(
api: &Api,
page: Query<Option<i32>>,
page_size: Query<Option<i32>>,
) -> Result<V2AssetTxResponse> {
let mut conn = api.storage.lock().await.acquire().await?;
let mut assets: Vec<V2AssetOp> = vec![];
let page = page.0.unwrap_or(1);
let page_size = page_size.0.unwrap_or(10);
(page - 1) * page_size
)
.as_str(),
);

let sql_total = "SELECT count(*) AS cnt FROM assets".to_string();
let row_count = sqlx::query(sql_total.as_str())
let row = sqlx::query(&sql_total)
.fetch_one(&mut *conn)
.await?;
let total: i64 = row_count.try_get("cnt")?;
.await
.map_err(internal_error)?;
let total: i64 = row.try_get("count").map_err(internal_error)?;

let sql_query = format!(
"SELECT asset,tx,block,issuer,height,timestamp,ty,content FROM assets ORDER BY height desc limit {} offset {}",
page_size,
(page - 1) * page_size
);
let rows = sqlx::query(sql_query.as_str())
.fetch_all(&mut *conn)
.await?;
.await
.map_err(internal_error)?;

let mut assets: Vec<AssetResponse> = vec![];
for row in rows {
let asset: String = row.try_get("asset")?;
let tx: String = row.try_get("tx")?;
let block: String = row.try_get("block")?;
let issuer: String = row.try_get("issuer")?;
let height: i64 = row.try_get("height")?;
let timestamp: i64 = row.try_get("timestamp")?;
let ty: i32 = row.try_get("ty")?;
let value: Value = row.try_get("content")?;
assets.push(V2AssetOp {
let asset: String = row.try_get("asset").map_err(internal_error)?;
let tx: String = row.try_get("tx").map_err(internal_error)?;
let block: String = row.try_get("block").map_err(internal_error)?;
let issuer: String = row.try_get("issuer").map_err(internal_error)?;
let height: i64 = row.try_get("height").map_err(internal_error)?;
let timestamp: i64 = row.try_get("timestamp").map_err(internal_error)?;
let ty: i32 = row.try_get("ty").map_err(internal_error)?;
let value: Value = row.try_get("content").map_err(internal_error)?;
assets.push(AssetResponse {
asset,
tx,
block,
Expand All @@ -150,14 +94,10 @@ pub async fn v2_get_asset_list(
});
}

Ok(V2AssetTxResponse::Ok(Json(V2AssetTxResult {
code: 200,
message: "".to_string(),
data: Some(V2AssetData {
page,
page_size,
total,
assets,
}),
})))
Ok(Json(QueryResult {
total,
page,
page_size,
data: assets,
}))
}
16 changes: 14 additions & 2 deletions explorer/src/service/v2/block.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
use crate::service::v2::error::internal_error;
use crate::service::v2::error::Result;
use crate::service::v2::{BlockResponse, QueryResult};
use crate::service::v2::QueryResult;
use crate::AppState;
use axum::extract::{Query, State};
use axum::Json;
use module::rpc::block::BlockRPC;
use module::rpc::block::{BlockHeader, BlockId, BlockRPC};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use sqlx::Row;
use std::sync::Arc;

#[derive(Serialize, Deserialize, Debug)]
pub struct BlockResponse {
pub block_hash: String,
pub block_num: i64,
pub app_hash: String,
pub proposer: String,
pub num_txs: i64,
pub block_size: i64,
pub block_id: BlockId,
pub block_header: BlockHeader,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct GetBlockByHeightParams {
pub num: i64,
Expand Down
2 changes: 1 addition & 1 deletion explorer/src/service/v2/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ where
E: std::error::Error,
{
let err_msg = err.to_string();
if err_msg.contains("now rows") {
if err_msg.contains("no rows") {
return (StatusCode::NOT_FOUND, "not found".to_string());
}

Expand Down
13 changes: 0 additions & 13 deletions explorer/src/service/v2/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use module::rpc::block::{BlockHeader, BlockId};
use serde::{Deserialize, Serialize};

pub mod asset;
Expand Down Expand Up @@ -39,15 +38,3 @@ pub struct QueryResult<T> {
pub page_size: i32,
pub data: T,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct BlockResponse {
pub block_hash: String,
pub block_num: i64,
pub app_hash: String,
pub proposer: String,
pub num_txs: i64,
pub block_size: i64,
pub block_id: BlockId,
pub block_header: BlockHeader,
}
39 changes: 16 additions & 23 deletions explorer/src/service/v2/other.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,31 +44,26 @@ pub async fn v2_statistics(api: &Api, ty: Query<Option<i32>>) -> Result<V2ChainS
let start_time = Local::now().date_naive().and_hms_opt(0, 0, 0).unwrap();

if let Some(tx_type) = ty.0 {
let sql_txs_count = format!(
"select count(*) as cnt from transaction where ty={}",
tx_type
);
let sql_txs_count = format!("SELECT count(*) FROM transaction WHERE ty={}", tx_type);
let row_txs_count = sqlx::query(sql_txs_count.as_str())
.fetch_one(&mut *conn)
.await?;
let txs_count = row_txs_count.try_get("cnt")?;
let txs_count = row_txs_count.try_get("count")?;

let sql_addrs_count: String;
let sql_daily_txs: String;
match tx_type {
0 => {
sql_addrs_count =
"select count(distinct address) as cnt from native_addrs".to_string();
sql_addrs_count = "SELECT count(distinct address) FROM native_addrs".to_string();
sql_daily_txs = format!(
"select count(*) as cnt from transaction where ty=0 and timestamp>={}",
"SELECT count(*) FROM transaction WHERE ty=0 AND timestamp>={}",
start_time.and_utc().timestamp()
);
}
_ => {
sql_addrs_count =
"select count(distinct address) as cnt from evm_addrs".to_string();
sql_addrs_count = "SELECT count(distinct address) FROM evm_addrs".to_string();
sql_daily_txs = format!(
"select count(*) as cnt from transaction where ty=1 and timestamp>={}",
"SELECT count(*) FROM transaction WHERE ty=1 AND timestamp>={}",
start_time.and_utc().timestamp()
);
}
Expand All @@ -77,45 +72,43 @@ pub async fn v2_statistics(api: &Api, ty: Query<Option<i32>>) -> Result<V2ChainS
let row_addr_count = sqlx::query(sql_addrs_count.as_str())
.fetch_one(&mut *conn)
.await?;
let addr_count: i64 = row_addr_count.try_get("cnt")?;
let addr_count: i64 = row_addr_count.try_get("count")?;

let row_daily = sqlx::query(sql_daily_txs.as_str())
.fetch_one(&mut *conn)
.await?;
let daily_txs = row_daily.try_get("cnt")?;
let daily_txs = row_daily.try_get("count")?;

stat.active_addrs = addr_count;
stat.total_txs = txs_count;
stat.daily_txs = daily_txs
} else {
let sql_txs_count = "select count(*) as cnt from transaction".to_string();
let sql_txs_count = "SELECT count(*) FROM transaction".to_string();
let row_txs_count = sqlx::query(sql_txs_count.as_str())
.fetch_one(&mut *conn)
.await?;
let txs_count = row_txs_count.try_get("cnt")?;
let txs_count = row_txs_count.try_get("count")?;

let sql_evm_addrs_count =
"select count(distinct address) as cnt from evm_addrs".to_string();
let sql_evm_addrs_count = "SELECT count(distinct address) FROM evm_addrs".to_string();
let row_evm_addr = sqlx::query(sql_evm_addrs_count.as_str())
.fetch_one(&mut *conn)
.await?;
let evm_addrs: i64 = row_evm_addr.try_get("cnt")?;
let evm_addrs: i64 = row_evm_addr.try_get("count")?;

let sql_native_addrs_count =
"select count(distinct address) as cnt from native_addrs".to_string();
let sql_native_addrs_count = "SELECT count(distinct address) FROM native_addrs".to_string();
let row_native_addr = sqlx::query(sql_native_addrs_count.as_str())
.fetch_one(&mut *conn)
.await?;
let native_addrs: i64 = row_native_addr.try_get("cnt")?;
let native_addrs: i64 = row_native_addr.try_get("count")?;

let sql_daily_txs = format!(
"select count(*) as cnt from transaction where timestamp>={}",
"SELECT count(*) FROM transaction WHERE timestamp>={}",
start_time.and_utc().timestamp()
);
let row_daily = sqlx::query(sql_daily_txs.as_str())
.fetch_one(&mut *conn)
.await?;
let daily_txs = row_daily.try_get("cnt")?;
let daily_txs = row_daily.try_get("count")?;

stat.active_addrs = native_addrs + evm_addrs;
stat.total_txs = txs_count;
Expand Down

0 comments on commit 75371e6

Please sign in to comment.