Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize: get assets. #250

Merged
merged 1 commit into from
Apr 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading