From 4ff47cd3c3d9f879765ae172a674d3c61620fe9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B9=E7=89=9B=E5=95=A4?= Date: Wed, 26 Jun 2024 23:50:41 +0800 Subject: [PATCH] optimize: market. (#267) --- docs/api.md | 129 +++++++++++++ explorer/src/main.rs | 3 +- explorer/src/service/error.rs | 84 ++++++++- explorer/src/service/v2/asset.rs | 30 ++-- explorer/src/service/v2/block.rs | 138 +++++++------- explorer/src/service/v2/claim.rs | 47 +++-- explorer/src/service/v2/delegation.rs | 57 +++--- explorer/src/service/v2/other.rs | 170 +++++++++++------- .../src/service/v2/prism_evm_to_native.rs | 61 +++---- .../src/service/v2/prism_native_to_evm.rs | 55 +++--- explorer/src/service/v2/transaction.rs | 65 +++---- explorer/src/service/v2/undelegation.rs | 53 +++--- 12 files changed, 545 insertions(+), 347 deletions(-) diff --git a/docs/api.md b/docs/api.md index 656863e..6140092 100644 --- a/docs/api.md +++ b/docs/api.md @@ -12,9 +12,13 @@ ## Chain * [3.1 统计交易量](#3.1) * [3.2 地址总量](#3.2) + ## Asset * [4.1 获取资产信息](#4.1) +## 其他 +* [5.1 获取FRA市场信息](#5.1) +

1.1 根据交易哈希获取交易

* `GET /api/tx` @@ -522,3 +526,128 @@ }] } ``` + +

5.1 获取FRA市场信息

+ +* `GET /api/coins/:id/market_chart` + + +| 参数 | 类型 | 必传 | 说明 | +|-------------|--------|----|--------------------| +| id | string | Y | 币种 | +| vs_currency | string | N | 计价货币,缺省值为"usd" | +| interval | string | N | 时间间隔,缺省为"daily" | +| days | number | N | 天数,缺省值为7,即列表中有7条数据 | + +* Request: `/api/coins/findora/market_chart?vs_currency=usd&days=7&interval=daily` +* Response: +```json +{ + "code":200, + "message":"", + "data":{ + "market_caps":[ + [ + 1718841600000, + 12076960.654386723 + ], + [ + 1718928000000, + 12502620.19204148 + ], + [ + 1719014400000, + 12518619.67665847 + ], + [ + 1719100800000, + 12756431.19328877 + ], + [ + 1719187200000, + 12478551.446567249 + ], + [ + 1719273600000, + 10902644.116966683 + ], + [ + 1719360000000, + 10841063.701286633 + ], + [ + 1719415382000, + 10689314.764516797 + ] + ], + "prices":[ + [ + 1718841600000, + 0.0010421953662283902 + ], + [ + 1718928000000, + 0.0010786349850002864 + ], + [ + 1719014400000, + 0.001075916897093825 + ], + [ + 1719100800000, + 0.0011022425089767258 + ], + [ + 1719187200000, + 0.0010769704462329777 + ], + [ + 1719273600000, + 0.0009381464216474152 + ], + [ + 1719360000000, + 0.0009336248576932378 + ], + [ + 1719415382000, + 0.0009218445536291912 + ] + ], + "total_volumes":[ + [ + 1718841600000, + 255031.1386785886 + ], + [ + 1718928000000, + 77237.26698759367 + ], + [ + 1719014400000, + 353159.57762952574 + ], + [ + 1719100800000, + 439593.60549064353 + ], + [ + 1719187200000, + 430793.7394006403 + ], + [ + 1719273600000, + 357770.9091104639 + ], + [ + 1719360000000, + 466249.0112276624 + ], + [ + 1719415382000, + 480190.8136610133 + ] + ] + } +} +``` \ No newline at end of file diff --git a/explorer/src/main.rs b/explorer/src/main.rs index 414e83f..0fce87b 100644 --- a/explorer/src/main.rs +++ b/explorer/src/main.rs @@ -7,7 +7,7 @@ use crate::service::v2::block::{ }; use crate::service::v2::claim::{get_claim_by_tx_hash, get_claims}; use crate::service::v2::delegation::{get_delegation_by_tx_hash, get_delegations}; -use crate::service::v2::other::{get_address_count, get_statistics, get_tx_distribute}; +use crate::service::v2::other::{get_address_count, get_market, get_statistics, get_tx_distribute}; use crate::service::v2::prism_evm_to_native::{get_e2n_by_tx_hash, get_e2n_txs}; use crate::service::v2::prism_native_to_evm::{get_n2e_by_tx_hash, get_n2e_txs}; use crate::service::v2::transaction::{get_tx_by_hash, get_txs}; @@ -83,6 +83,7 @@ async fn main() -> Result<()> { .route("/api/e2ns", get(get_e2n_txs)) // asset .route("/api/assets", get(get_assets)) + .route("/api/coins/:id/market_chart", get(get_market)) .layer(cors) .with_state(app_state); let listener = tokio::net::TcpListener::bind(&addr).await.unwrap(); diff --git a/explorer/src/service/error.rs b/explorer/src/service/error.rs index ee213c9..d4b34f9 100644 --- a/explorer/src/service/error.rs +++ b/explorer/src/service/error.rs @@ -1,15 +1,81 @@ use axum::http::StatusCode; +use axum::response::{IntoResponse, Response}; -pub type Result = core::result::Result; +#[derive(Debug)] +pub enum ExplorerError { + Custom(String), + DBError(sqlx::Error), + IOError(std::io::Error), + TomlDeError(toml::de::Error), + HexError(rustc_hex::FromHexError), + ParseUrlError(url::ParseError), + SerdeJsonError(serde_json::Error), + ReqwestError(reqwest::Error), +} + +impl From for ExplorerError { + fn from(e: reqwest::Error) -> Self { + ExplorerError::ReqwestError(e) + } +} + +impl From for ExplorerError { + fn from(e: serde_json::Error) -> Self { + ExplorerError::SerdeJsonError(e) + } +} + +impl From for ExplorerError { + fn from(e: String) -> Self { + ExplorerError::Custom(e) + } +} + +impl From for ExplorerError { + fn from(e: url::ParseError) -> Self { + ExplorerError::ParseUrlError(e) + } +} -pub fn internal_error(err: E) -> (StatusCode, String) -where - E: std::error::Error, -{ - let err_msg = err.to_string(); - if err_msg.contains("no rows") { - return (StatusCode::NOT_FOUND, "not found".to_string()); +impl From for ExplorerError { + fn from(e: rustc_hex::FromHexError) -> Self { + ExplorerError::HexError(e) } +} + +impl From for ExplorerError { + fn from(e: std::io::Error) -> Self { + ExplorerError::IOError(e) + } +} + +impl From for ExplorerError { + fn from(e: toml::de::Error) -> Self { + ExplorerError::TomlDeError(e) + } +} - (StatusCode::INTERNAL_SERVER_ERROR, err_msg) +impl From for ExplorerError { + fn from(e: sqlx::Error) -> Self { + ExplorerError::DBError(e) + } +} + +pub type Result = core::result::Result; + +impl IntoResponse for ExplorerError { + fn into_response(self) -> Response { + let err_msg = match self { + ExplorerError::Custom(e) => e, + ExplorerError::DBError(e) => e.to_string(), + ExplorerError::IOError(e) => e.to_string(), + ExplorerError::TomlDeError(e) => e.to_string(), + ExplorerError::HexError(e) => e.to_string(), + ExplorerError::ParseUrlError(e) => e.to_string(), + ExplorerError::SerdeJsonError(e) => e.to_string(), + ExplorerError::ReqwestError(e) => e.to_string(), + }; + + (StatusCode::INTERNAL_SERVER_ERROR, err_msg).into_response() + } } diff --git a/explorer/src/service/v2/asset.rs b/explorer/src/service/v2/asset.rs index 52872e9..3f72ac4 100644 --- a/explorer/src/service/v2/asset.rs +++ b/explorer/src/service/v2/asset.rs @@ -1,4 +1,4 @@ -use crate::service::error::{internal_error, Result}; +use crate::service::error::Result; use crate::service::QueryResult; use crate::AppState; use axum::extract::{Query, State}; @@ -32,7 +32,7 @@ pub async fn get_assets( State(state): State>, Query(params): Query, ) -> Result>>> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let page = params.page.unwrap_or(1); let page_size = params.page_size.unwrap_or(10); @@ -60,27 +60,23 @@ pub async fn get_assets( .as_str(), ); - let row = sqlx::query(&sql_total) - .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let total: i64 = row.try_get("count").map_err(internal_error)?; + let row = sqlx::query(&sql_total).fetch_one(&mut *conn).await?; + let total: i64 = row.try_get("count")?; let rows = sqlx::query(sql_query.as_str()) .fetch_all(&mut *conn) - .await - .map_err(internal_error)?; + .await?; let mut assets: Vec = vec![]; for row in rows { - 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)?; + 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(AssetResponse { asset, tx, diff --git a/explorer/src/service/v2/block.rs b/explorer/src/service/v2/block.rs index f736c91..ffa2cce 100644 --- a/explorer/src/service/v2/block.rs +++ b/explorer/src/service/v2/block.rs @@ -1,4 +1,4 @@ -use crate::service::error::{internal_error, Result}; +use crate::service::error::Result; use crate::service::QueryResult; use crate::AppState; use axum::extract::{Path, Query, State}; @@ -31,16 +31,15 @@ pub async fn get_full_block_by_height( State(state): State>, Path(num): Path, ) -> Result> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let sql_query = r#"SELECT block_data FROM block WHERE height=$1"#; let row = sqlx::query(sql_query) .bind(num) .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let block_data = row.try_get("block_data").map_err(internal_error)?; - let block_rpc: BlockRPC = serde_json::from_value(block_data).map_err(internal_error)?; + .await?; + let block_data = row.try_get("block_data")?; + let block_rpc: BlockRPC = serde_json::from_value(block_data)?; let full_block = FullBlockResponse { block_id: block_rpc.block_id, block: block_rpc.block, @@ -53,24 +52,23 @@ pub async fn get_simple_block_by_height( State(state): State>, Path(num): Path, ) -> Result> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let sql_query = "SELECT block_hash,height,size,tx_count,time,app_hash,proposer,block_data FROM block WHERE height=$1"; let row = sqlx::query(sql_query) .bind(num) .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - - let block_hash: String = row.try_get("block_hash").map_err(internal_error)?; - let block_num: i64 = row.try_get("height").map_err(internal_error)?; - let app_hash: String = row.try_get("app_hash").map_err(internal_error)?; - let proposer: String = row.try_get("proposer").map_err(internal_error)?; - let block_size: i64 = row.try_get("size").map_err(internal_error)?; - let num_txs: i64 = row.try_get("tx_count").map_err(internal_error)?; - let block_data: Value = row.try_get("block_data").map_err(internal_error)?; - let block_rpc: BlockRPC = serde_json::from_value(block_data).map_err(internal_error)?; + .await?; + + let block_hash: String = row.try_get("block_hash")?; + let block_num: i64 = row.try_get("height")?; + let app_hash: String = row.try_get("app_hash")?; + let proposer: String = row.try_get("proposer")?; + let block_size: i64 = row.try_get("size")?; + let num_txs: i64 = row.try_get("tx_count")?; + let block_data: Value = row.try_get("block_data")?; + let block_rpc: BlockRPC = serde_json::from_value(block_data)?; let block = BlockResponse { block_hash, @@ -90,16 +88,15 @@ pub async fn get_full_block_by_hash( State(state): State>, Path(hash): Path, ) -> Result> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let sql_query = "SELECT block_data FROM block WHERE block_hash=$1"; let row = sqlx::query(sql_query) .bind(hash) .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let block_data = row.try_get("block_data").map_err(internal_error)?; - let block_rpc: BlockRPC = serde_json::from_value(block_data).map_err(internal_error)?; + .await?; + let block_data = row.try_get("block_data")?; + let block_rpc: BlockRPC = serde_json::from_value(block_data)?; let full_block = FullBlockResponse { block_id: block_rpc.block_id, block: block_rpc.block, @@ -112,22 +109,21 @@ pub async fn get_simple_block_by_hash( State(state): State>, Path(hash): Path, ) -> Result> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let sql_query = r#"SELECT block_hash,height,size,tx_count,time,app_hash,proposer,block_data FROM block WHERE block_hash=$1"#; let row = sqlx::query(sql_query) .bind(hash) .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let block_hash: String = row.try_get("block_hash").map_err(internal_error)?; - let block_num: i64 = row.try_get("height").map_err(internal_error)?; - let app_hash: String = row.try_get("app_hash").map_err(internal_error)?; - let proposer: String = row.try_get("proposer").map_err(internal_error)?; - let block_size: i64 = row.try_get("size").map_err(internal_error)?; - let num_txs: i64 = row.try_get("tx_count").map_err(internal_error)?; - let block_data: Value = row.try_get("block_data").map_err(internal_error)?; - let block_rpc: BlockRPC = serde_json::from_value(block_data).map_err(internal_error)?; + .await?; + let block_hash: String = row.try_get("block_hash")?; + let block_num: i64 = row.try_get("height")?; + let app_hash: String = row.try_get("app_hash")?; + let proposer: String = row.try_get("proposer")?; + let block_size: i64 = row.try_get("size")?; + let num_txs: i64 = row.try_get("tx_count")?; + let block_data: Value = row.try_get("block_data")?; + let block_rpc: BlockRPC = serde_json::from_value(block_data)?; let block = BlockResponse { block_hash, num_txs, @@ -152,23 +148,22 @@ pub async fn get_block_by_num( State(state): State>, Query(params): Query, ) -> Result> { - let mut pool = state.pool.acquire().await.map_err(internal_error)?; + let mut pool = state.pool.acquire().await?; let sql_query = r#"SELECT block_hash,height,size,tx_count,time,app_hash,proposer,block_data FROM block WHERE height=$1"#; let row = sqlx::query(sql_query) .bind(params.num) .fetch_one(&mut *pool) - .await - .map_err(internal_error)?; - - let block_hash: String = row.try_get("block_hash").map_err(internal_error)?; - let block_num: i64 = row.try_get("height").map_err(internal_error)?; - let app_hash: String = row.try_get("app_hash").map_err(internal_error)?; - let proposer: String = row.try_get("proposer").map_err(internal_error)?; - let block_size: i64 = row.try_get("size").map_err(internal_error)?; - let num_txs: i64 = row.try_get("tx_count").map_err(internal_error)?; - let block_data: Value = row.try_get("block_data").map_err(internal_error)?; - let block_rpc: BlockRPC = serde_json::from_value(block_data).map_err(internal_error)?; + .await?; + + let block_hash: String = row.try_get("block_hash")?; + let block_num: i64 = row.try_get("height")?; + let app_hash: String = row.try_get("app_hash")?; + let proposer: String = row.try_get("proposer")?; + let block_size: i64 = row.try_get("size")?; + let num_txs: i64 = row.try_get("tx_count")?; + let block_data: Value = row.try_get("block_data")?; + let block_rpc: BlockRPC = serde_json::from_value(block_data)?; Ok(Json(BlockResponse { block_hash, @@ -191,7 +186,7 @@ pub async fn get_block_by_hash( State(state): State>, Query(params): Query, ) -> Result> { - let mut pool = state.pool.acquire().await.map_err(internal_error)?; + let mut pool = state.pool.acquire().await?; let sql_query = r#"SELECT block_hash,height,size,tx_count,time,app_hash,proposer,block_data FROM block WHERE block_hash=$1"#; @@ -199,17 +194,16 @@ pub async fn get_block_by_hash( let row = sqlx::query(sql_query) .bind(params.hash.to_uppercase()) .fetch_one(&mut *pool) - .await - .map_err(internal_error)?; - - let block_hash: String = row.try_get("block_hash").map_err(internal_error)?; - let block_num: i64 = row.try_get("height").map_err(internal_error)?; - let app_hash: String = row.try_get("app_hash").map_err(internal_error)?; - let proposer: String = row.try_get("proposer").map_err(internal_error)?; - let block_size: i64 = row.try_get("size").map_err(internal_error)?; - let num_txs: i64 = row.try_get("tx_count").map_err(internal_error)?; - let block_data: Value = row.try_get("block_data").map_err(internal_error)?; - let block_rpc: BlockRPC = serde_json::from_value(block_data).map_err(internal_error)?; + .await?; + + let block_hash: String = row.try_get("block_hash")?; + let block_num: i64 = row.try_get("height")?; + let app_hash: String = row.try_get("app_hash")?; + let proposer: String = row.try_get("proposer")?; + let block_size: i64 = row.try_get("size")?; + let num_txs: i64 = row.try_get("tx_count")?; + let block_data: Value = row.try_get("block_data")?; + let block_rpc: BlockRPC = serde_json::from_value(block_data)?; Ok(Json(BlockResponse { block_hash, @@ -233,16 +227,13 @@ pub async fn get_blocks( State(state): State>, Query(params): Query, ) -> Result>>> { - let mut pool = state.pool.acquire().await.map_err(internal_error)?; + let mut pool = state.pool.acquire().await?; let page = params.page.unwrap_or(1); let page_size = params.page_size.unwrap_or(10); let sql_total = "SELECT max(height) FROM block"; - let row = sqlx::query(sql_total) - .fetch_one(&mut *pool) - .await - .map_err(internal_error)?; - let total = row.try_get("max").map_err(internal_error)?; + let row = sqlx::query(sql_total).fetch_one(&mut *pool).await?; + let total = row.try_get("max")?; let sql_query = r#"SELECT block_hash,height,size,tx_count,time,app_hash,proposer,block_data FROM block ORDER BY height DESC LIMIT $1 OFFSET $2"#; @@ -251,19 +242,18 @@ pub async fn get_blocks( .bind(page_size) .bind((page - 1) * page_size) .fetch_all(&mut *pool) - .await - .map_err(internal_error)?; + .await?; let mut blocks: Vec = vec![]; for row in rows { - let block_hash: String = row.try_get("block_hash").map_err(internal_error)?; - let block_num: i64 = row.try_get("height").map_err(internal_error)?; - let app_hash: String = row.try_get("app_hash").map_err(internal_error)?; - let proposer: String = row.try_get("proposer").map_err(internal_error)?; - let block_size: i64 = row.try_get("size").map_err(internal_error)?; - let num_txs: i64 = row.try_get("tx_count").map_err(internal_error)?; - let block_data: Value = row.try_get("block_data").map_err(internal_error)?; - let block_rpc: BlockRPC = serde_json::from_value(block_data).map_err(internal_error)?; + let block_hash: String = row.try_get("block_hash")?; + let block_num: i64 = row.try_get("height")?; + let app_hash: String = row.try_get("app_hash")?; + let proposer: String = row.try_get("proposer")?; + let block_size: i64 = row.try_get("size")?; + let num_txs: i64 = row.try_get("tx_count")?; + let block_data: Value = row.try_get("block_data")?; + let block_rpc: BlockRPC = serde_json::from_value(block_data)?; blocks.push(BlockResponse { block_hash, diff --git a/explorer/src/service/v2/claim.rs b/explorer/src/service/v2/claim.rs index 71935b9..734e502 100644 --- a/explorer/src/service/v2/claim.rs +++ b/explorer/src/service/v2/claim.rs @@ -1,4 +1,4 @@ -use crate::service::error::{internal_error, Result}; +use crate::service::error::Result; use crate::service::QueryResult; use crate::AppState; use axum::extract::{Query, State}; @@ -29,7 +29,7 @@ pub async fn get_claim_by_tx_hash( State(state): State>, Query(params): Query, ) -> Result> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let sql_query = r#"SELECT tx,block,sender,amount,height,timestamp,content FROM claims WHERE tx=$1"#; @@ -37,16 +37,15 @@ pub async fn get_claim_by_tx_hash( let row = sqlx::query(sql_query) .bind(params.hash) .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; + .await?; - let tx_hash: String = row.try_get("tx").map_err(internal_error)?; - let block_hash: String = row.try_get("block").map_err(internal_error)?; - let from: String = row.try_get("sender").map_err(internal_error)?; - let amount: i64 = row.try_get("amount").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 value: Value = row.try_get("content").map_err(internal_error)?; + let tx_hash: String = row.try_get("tx")?; + let block_hash: String = row.try_get("block")?; + let from: String = row.try_get("sender")?; + let amount: i64 = row.try_get("amount")?; + let height: i64 = row.try_get("height")?; + let timestamp: i64 = row.try_get("timestamp")?; + let value: Value = row.try_get("content")?; let claim = ClaimResponse { tx_hash, @@ -73,7 +72,7 @@ pub async fn get_claims( State(state): State>, Query(params): Query, ) -> Result>>> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let page = params.page.unwrap_or(1); let page_size = params.page_size.unwrap_or(10); @@ -93,25 +92,21 @@ pub async fn get_claims( )) }; - let row_cnt = sqlx::query(&sql_count) - .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let total: i64 = row_cnt.try_get("count").map_err(internal_error)?; + let row_cnt = sqlx::query(&sql_count).fetch_one(&mut *conn).await?; + let total: i64 = row_cnt.try_get("count")?; let mut claims: Vec = vec![]; let rows = sqlx::query(sql_query.as_str()) .fetch_all(&mut *conn) - .await - .map_err(internal_error)?; + .await?; for row in rows { - let tx_hash: String = row.try_get("tx").map_err(internal_error)?; - let block_hash: String = row.try_get("block").map_err(internal_error)?; - let from: String = row.try_get("sender").map_err(internal_error)?; - let amount: i64 = row.try_get("amount").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 value: Value = row.try_get("content").map_err(internal_error)?; + let tx_hash: String = row.try_get("tx")?; + let block_hash: String = row.try_get("block")?; + let from: String = row.try_get("sender")?; + let amount: i64 = row.try_get("amount")?; + let height: i64 = row.try_get("height")?; + let timestamp: i64 = row.try_get("timestamp")?; + let value: Value = row.try_get("content")?; claims.push(ClaimResponse { tx_hash, block_hash, diff --git a/explorer/src/service/v2/delegation.rs b/explorer/src/service/v2/delegation.rs index 13aa280..180009c 100644 --- a/explorer/src/service/v2/delegation.rs +++ b/explorer/src/service/v2/delegation.rs @@ -1,4 +1,4 @@ -use crate::service::error::{internal_error, Result}; +use crate::service::error::Result; use crate::service::QueryResult; use crate::AppState; use axum::extract::{Query, State}; @@ -30,25 +30,24 @@ pub async fn get_delegation_by_tx_hash( State(state): State>, Query(params): Query, ) -> Result> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let sql_query = r#"SELECT tx,block,amount,sender,validator,new_validator,height,timestamp,content FROM delegations WHERE tx=$1"#; let row = sqlx::query(sql_query) .bind(params.hash) .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; + .await?; - let tx_hash: String = row.try_get("tx").map_err(internal_error)?; - let block_hash: String = row.try_get("block").map_err(internal_error)?; - let amount: i64 = row.try_get("amount").map_err(internal_error)?; - let from: String = row.try_get("sender").map_err(internal_error)?; - let validator: String = row.try_get("validator").map_err(internal_error)?; - let new_validator: String = row.try_get("new_validator").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 value: Value = row.try_get("content").map_err(internal_error)?; + let tx_hash: String = row.try_get("tx")?; + let block_hash: String = row.try_get("block")?; + let amount: i64 = row.try_get("amount")?; + let from: String = row.try_get("sender")?; + let validator: String = row.try_get("validator")?; + let new_validator: String = row.try_get("new_validator")?; + let height: i64 = row.try_get("height")?; + let timestamp: i64 = row.try_get("timestamp")?; + let value: Value = row.try_get("content")?; let delegation = DelegationResponse { tx_hash, @@ -77,7 +76,7 @@ pub async fn get_delegations( State(state): State>, Query(params): Query, ) -> Result>>> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let page = params.page.unwrap_or(1); let page_size = params.page_size.unwrap_or(10); @@ -107,28 +106,22 @@ pub async fn get_delegations( ) }; - let row_cnt = sqlx::query(&sql_count) - .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let total: i64 = row_cnt.try_get("count").map_err(internal_error)?; + let row_cnt = sqlx::query(&sql_count).fetch_one(&mut *conn).await?; + let total: i64 = row_cnt.try_get("count")?; let mut delegations: Vec = vec![]; - let rows = sqlx::query(&sql_query) - .fetch_all(&mut *conn) - .await - .map_err(internal_error)?; + let rows = sqlx::query(&sql_query).fetch_all(&mut *conn).await?; for row in rows { - let tx_hash: String = row.try_get("tx").map_err(internal_error)?; - let block_hash: String = row.try_get("block").map_err(internal_error)?; - let amount: i64 = row.try_get("amount").map_err(internal_error)?; - let from: String = row.try_get("sender").map_err(internal_error)?; - let validator: String = row.try_get("validator").map_err(internal_error)?; - let new_validator: String = row.try_get("new_validator").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 value: Value = row.try_get("content").map_err(internal_error)?; + let tx_hash: String = row.try_get("tx")?; + let block_hash: String = row.try_get("block")?; + let amount: i64 = row.try_get("amount")?; + let from: String = row.try_get("sender")?; + let validator: String = row.try_get("validator")?; + let new_validator: String = row.try_get("new_validator")?; + let height: i64 = row.try_get("height")?; + let timestamp: i64 = row.try_get("timestamp")?; + let value: Value = row.try_get("content")?; delegations.push(DelegationResponse { tx_hash, diff --git a/explorer/src/service/v2/other.rs b/explorer/src/service/v2/other.rs index c37711f..d546cb2 100644 --- a/explorer/src/service/v2/other.rs +++ b/explorer/src/service/v2/other.rs @@ -1,10 +1,13 @@ -use crate::service::error::{internal_error, Result}; +use crate::service::error::Result; +use crate::service::v1::price::{FraMarketChart, MarketChartResult}; use crate::AppState; -use axum::extract::{Query, State}; +use axum::extract::{Path, Query, State}; use axum::Json; use serde::{Deserialize, Serialize}; +use serde_json::Value; +use sqlx::pool::PoolConnection; use sqlx::types::chrono::Local; -use sqlx::Row; +use sqlx::{Postgres, Row}; use std::ops::Add; use std::sync::Arc; @@ -25,7 +28,7 @@ pub async fn get_statistics( State(state): State>, Query(params): Query, ) -> Result> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let mut stat = StatisticsResponse { active_addrs: 0, @@ -39,9 +42,8 @@ pub async fn get_statistics( 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 - .map_err(internal_error)?; - let txs_count = row_txs_count.try_get("count").map_err(internal_error)?; + .await?; + let txs_count = row_txs_count.try_get("count")?; let sql_addrs_count: String; let sql_daily_txs: String; @@ -64,15 +66,13 @@ pub async fn get_statistics( let row_addr_count = sqlx::query(sql_addrs_count.as_str()) .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let addr_count: i64 = row_addr_count.try_get("count").map_err(internal_error)?; + .await?; + 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 - .map_err(internal_error)?; - let daily_txs = row_daily.try_get("count").map_err(internal_error)?; + .await?; + let daily_txs = row_daily.try_get("count")?; stat.active_addrs = addr_count; stat.total_txs = txs_count; @@ -81,23 +81,20 @@ pub async fn get_statistics( 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 - .map_err(internal_error)?; - let txs_count = row_txs_count.try_get("count").map_err(internal_error)?; + .await?; + let txs_count = row_txs_count.try_get("count")?; 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 - .map_err(internal_error)?; - let evm_addrs: i64 = row_evm_addr.try_get("count").map_err(internal_error)?; + .await?; + let evm_addrs: i64 = row_evm_addr.try_get("count")?; 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 - .map_err(internal_error)?; - let native_addrs: i64 = row_native_addr.try_get("count").map_err(internal_error)?; + .await?; + let native_addrs: i64 = row_native_addr.try_get("count")?; let sql_daily_txs = format!( "SELECT count(*) FROM transaction WHERE timestamp>={}", @@ -105,9 +102,8 @@ pub async fn get_statistics( ); let row_daily = sqlx::query(sql_daily_txs.as_str()) .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let daily_txs = row_daily.try_get("count").map_err(internal_error)?; + .await?; + let daily_txs = row_daily.try_get("count")?; stat.active_addrs = native_addrs + evm_addrs; stat.total_txs = txs_count; @@ -129,42 +125,27 @@ pub struct TxsDistributeResponse { pub async fn get_tx_distribute( State(state): State>, ) -> Result> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let sql_native = "SELECT count(*) FROM transaction WHERE ty=0"; - let row_native = sqlx::query(sql_native) - .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let native_count: i64 = row_native.try_get("count").map_err(internal_error)?; + let row_native = sqlx::query(sql_native).fetch_one(&mut *conn).await?; + let native_count: i64 = row_native.try_get("count")?; let sql_privacy = "SELECT count(*) FROM transaction WHERE ty_sub=2 or ty_sub=3 or ty_sub=4"; - let row_privacy = sqlx::query(sql_privacy) - .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let privacy: i64 = row_privacy.try_get("count").map_err(internal_error)?; + let row_privacy = sqlx::query(sql_privacy).fetch_one(&mut *conn).await?; + let privacy: i64 = row_privacy.try_get("count")?; let sql_evm = "SELECT count(*) FROM transaction WHERE ty=1"; - let row_evm = sqlx::query(sql_evm) - .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let evm_count: i64 = row_evm.try_get("count").map_err(internal_error)?; + let row_evm = sqlx::query(sql_evm).fetch_one(&mut *conn).await?; + let evm_count: i64 = row_evm.try_get("count")?; let sql_prism_n2e = "SELECT count(*) FROM n2e"; - let row_n2e = sqlx::query(sql_prism_n2e) - .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let n2e_count: i64 = row_n2e.try_get("count").map_err(internal_error)?; + let row_n2e = sqlx::query(sql_prism_n2e).fetch_one(&mut *conn).await?; + let n2e_count: i64 = row_n2e.try_get("count")?; let sql_prism_e2n = "SELECT count(*) FROM e2n"; - let row_e2n = sqlx::query(sql_prism_e2n) - .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let e2n_count: i64 = row_e2n.try_get("count").map_err(internal_error)?; + let row_e2n = sqlx::query(sql_prism_e2n).fetch_one(&mut *conn).await?; + let e2n_count: i64 = row_e2n.try_get("count")?; Ok(Json(TxsDistributeResponse { transparent: native_count - privacy, @@ -189,7 +170,7 @@ pub async fn get_address_count( State(state): State>, Query(params): Query, ) -> Result> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let mut query_params: Vec = vec![]; if let Some(start_time) = params.start_time { @@ -213,17 +194,86 @@ pub async fn get_address_count( let row_native = sqlx::query(sql_native.as_str()) .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let native_count: i64 = row_native.try_get("count").map_err(internal_error)?; + .await?; + let native_count: i64 = row_native.try_get("count")?; - let row_evm = sqlx::query(sql_evm.as_str()) - .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let evm_count: i64 = row_evm.try_get("count").map_err(internal_error)?; + let row_evm = sqlx::query(sql_evm.as_str()).fetch_one(&mut *conn).await?; + let evm_count: i64 = row_evm.try_get("count")?; Ok(Json(AddressCountResponse { count: native_count + evm_count, })) } + +//https://mainnet.backend.findorascan.io/api/coins/findora/market_chart?vs_currency=usd&days=7&interval=daily + +#[derive(Serialize, Deserialize)] +pub struct MarketParams { + pub vs_currency: Option, + pub days: Option, + pub interval: Option, +} + +async fn get_market_data(mut conn: PoolConnection) -> Result { + let row = sqlx::query("SELECT val FROM market") + .fetch_one(&mut *conn) + .await?; + let val: Value = row.try_get("val")?; + let fmc: FraMarketChart = serde_json::from_value(val).unwrap(); + Ok(fmc) +} + +async fn upsert_market_data(mut conn: PoolConnection, val: Value) -> Result<()> { + sqlx::query("INSERT INTO market VALUES($1,$2) ON CONFLICT(name) DO UPDATE SET val=$2") + .bind("fra") + .bind(val) + .execute(&mut *conn) + .await?; + Ok(()) +} + +pub async fn get_market( + State(state): State>, + Path(id): Path, + Query(params): Query, +) -> Result> { + let conn = state.pool.acquire().await?; + + let vs_currency = params.vs_currency.unwrap_or("usd".to_string()); + let days = params.days.unwrap_or(7); + let interval = params.interval.unwrap_or("daily".to_string()); + + let url = format!( + "https://api.coingecko.com/api/v3/coins/{}/market_chart?vs_currency={}&days={}&interval={}", + id, vs_currency, days, interval + ); + + let resp1 = reqwest::get(url).await; + if resp1.is_err() { + let fmc = get_market_data(conn).await?; + return Ok(Json(MarketChartResult { + code: 200, + message: "".to_string(), + data: Some(fmc), + })); + } + let resp2 = resp1?.json::().await; + if resp2.is_err() { + let fmc = get_market_data(conn).await?; + return Ok(Json(MarketChartResult { + code: 200, + message: "".to_string(), + data: Some(fmc), + })); + } + + let fmc = resp2?; + let v = serde_json::to_value(&fmc)?; + upsert_market_data(conn, v).await?; + + Ok(Json(MarketChartResult { + code: 200, + message: "".to_string(), + data: Some(fmc), + })) +} diff --git a/explorer/src/service/v2/prism_evm_to_native.rs b/explorer/src/service/v2/prism_evm_to_native.rs index bd6ba5f..bfc0690 100644 --- a/explorer/src/service/v2/prism_evm_to_native.rs +++ b/explorer/src/service/v2/prism_evm_to_native.rs @@ -1,4 +1,4 @@ -use crate::service::error::{internal_error, Result}; +use crate::service::error::Result; use crate::service::QueryResult; use crate::AppState; use axum::extract::{Query, State}; @@ -32,24 +32,23 @@ pub async fn get_e2n_by_tx_hash( State(state): State>, Query(params): Query, ) -> Result> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let sql_query = r#"SELECT tx_hash,block_hash,sender,receiver,asset,amount,decimal,height,timestamp,value FROM e2n WHERE tx_hash=$1"#; let row = sqlx::query(sql_query) .bind(params.hash) .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; + .await?; - let tx_hash: String = row.try_get("tx_hash").map_err(internal_error)?; - let block_hash: String = row.try_get("block_hash").map_err(internal_error)?; - let from: String = row.try_get("sender").map_err(internal_error)?; - let to: String = row.try_get("receiver").map_err(internal_error)?; - let asset: String = row.try_get("asset").map_err(internal_error)?; - let decimal: i32 = row.try_get("decimal").map_err(internal_error)?; - let amount: String = row.try_get("amount").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 value: Value = row.try_get("value").map_err(internal_error)?; + let tx_hash: String = row.try_get("tx_hash")?; + let block_hash: String = row.try_get("block_hash")?; + let from: String = row.try_get("sender")?; + let to: String = row.try_get("receiver")?; + let asset: String = row.try_get("asset")?; + let decimal: i32 = row.try_get("decimal")?; + let amount: String = row.try_get("amount")?; + let height: i64 = row.try_get("height")?; + let timestamp: i64 = row.try_get("timestamp")?; + let value: Value = row.try_get("value")?; let tx = E2NTxResponse { tx_hash, block_hash, @@ -78,7 +77,7 @@ pub async fn get_e2n_txs( State(state): State>, Query(params): Query, ) -> Result>>> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let page = params.page.unwrap_or(1); let page_size = params.page_size.unwrap_or(10); @@ -109,28 +108,22 @@ pub async fn get_e2n_txs( .as_str(), ); - let row = sqlx::query(&sql_total) - .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let total: i64 = row.try_get("count").map_err(internal_error)?; + let row = sqlx::query(&sql_total).fetch_one(&mut *conn).await?; + let total: i64 = row.try_get("count")?; let mut txs: Vec = vec![]; - let rows = sqlx::query(&sql_query) - .fetch_all(&mut *conn) - .await - .map_err(internal_error)?; + let rows = sqlx::query(&sql_query).fetch_all(&mut *conn).await?; for row in rows { - let tx_hash: String = row.try_get("tx_hash").map_err(internal_error)?; - let block_hash: String = row.try_get("block_hash").map_err(internal_error)?; - let from: String = row.try_get("sender").map_err(internal_error)?; - let to: String = row.try_get("receiver").map_err(internal_error)?; - let asset: String = row.try_get("asset").map_err(internal_error)?; - let decimal: i32 = row.try_get("decimal").map_err(internal_error)?; - let amount: String = row.try_get("amount").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 value: Value = row.try_get("value").map_err(internal_error)?; + let tx_hash: String = row.try_get("tx_hash")?; + let block_hash: String = row.try_get("block_hash")?; + let from: String = row.try_get("sender")?; + let to: String = row.try_get("receiver")?; + let asset: String = row.try_get("asset")?; + let decimal: i32 = row.try_get("decimal")?; + let amount: String = row.try_get("amount")?; + let height: i64 = row.try_get("height")?; + let timestamp: i64 = row.try_get("timestamp")?; + let value: Value = row.try_get("value")?; txs.push(E2NTxResponse { tx_hash, block_hash, diff --git a/explorer/src/service/v2/prism_native_to_evm.rs b/explorer/src/service/v2/prism_native_to_evm.rs index a4e15fa..2bd9974 100644 --- a/explorer/src/service/v2/prism_native_to_evm.rs +++ b/explorer/src/service/v2/prism_native_to_evm.rs @@ -1,4 +1,4 @@ -use crate::service::error::{internal_error, Result}; +use crate::service::error::Result; use crate::service::QueryResult; use crate::AppState; use axum::extract::{Query, State}; @@ -34,7 +34,7 @@ pub async fn get_n2e_txs( State(state): State>, Query(params): Query, ) -> Result>>> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let page = params.page.unwrap_or(1); let page_size = params.page_size.unwrap_or(10); let mut sql_total = "SELECT count(*) FROM n2e ".to_string(); @@ -65,27 +65,23 @@ pub async fn get_n2e_txs( .as_str(), ); - let row = sqlx::query(&sql_total) - .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let total: i64 = row.try_get("count").map_err(internal_error)?; + let row = sqlx::query(&sql_total).fetch_one(&mut *conn).await?; + let total: i64 = row.try_get("count")?; let mut txs: Vec = vec![]; let rows = sqlx::query(sql_query.as_str()) .fetch_all(&mut *conn) - .await - .map_err(internal_error)?; + .await?; for row in rows { - let tx_hash: String = row.try_get("tx").map_err(internal_error)?; - let block_hash: String = row.try_get("block").map_err(internal_error)?; - let from: String = row.try_get("sender").map_err(internal_error)?; - let to: String = row.try_get("receiver").map_err(internal_error)?; - let asset: String = row.try_get("asset").map_err(internal_error)?; - let amount: String = row.try_get("amount").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 value: Value = row.try_get("content").map_err(internal_error)?; + let tx_hash: String = row.try_get("tx")?; + let block_hash: String = row.try_get("block")?; + let from: String = row.try_get("sender")?; + let to: String = row.try_get("receiver")?; + let asset: String = row.try_get("asset")?; + let amount: String = row.try_get("amount")?; + let height: i64 = row.try_get("height")?; + let timestamp: i64 = row.try_get("timestamp")?; + let value: Value = row.try_get("content")?; txs.push(NativeToEvmTxResponse { tx_hash, block_hash, @@ -117,24 +113,23 @@ pub async fn get_n2e_by_tx_hash( State(state): State>, Query(params): Query, ) -> Result> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let sql_query = r#"SELECT tx,block,sender,receiver,asset,amount,height,timestamp,content FROM n2e WHERE tx=$1"#; let row = sqlx::query(sql_query) .bind(params.hash) .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; + .await?; - let tx_hash: String = row.try_get("tx").map_err(internal_error)?; - let block_hash: String = row.try_get("block").map_err(internal_error)?; - let from: String = row.try_get("sender").map_err(internal_error)?; - let to: String = row.try_get("receiver").map_err(internal_error)?; - let asset: String = row.try_get("asset").map_err(internal_error)?; - let amount: String = row.try_get("amount").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 value: Value = row.try_get("content").map_err(internal_error)?; + let tx_hash: String = row.try_get("tx")?; + let block_hash: String = row.try_get("block")?; + let from: String = row.try_get("sender")?; + let to: String = row.try_get("receiver")?; + let asset: String = row.try_get("asset")?; + let amount: String = row.try_get("amount")?; + let height: i64 = row.try_get("height")?; + let timestamp: i64 = row.try_get("timestamp")?; + let value: Value = row.try_get("content")?; let tx = NativeToEvmTxResponse { tx_hash, diff --git a/explorer/src/service/v2/transaction.rs b/explorer/src/service/v2/transaction.rs index d7df259..eaf25db 100644 --- a/explorer/src/service/v2/transaction.rs +++ b/explorer/src/service/v2/transaction.rs @@ -1,4 +1,4 @@ -use crate::service::error::{internal_error, Result}; +use crate::service::error::Result; use crate::service::QueryResult; use crate::AppState; use axum::extract::{Query, State}; @@ -24,7 +24,7 @@ pub async fn get_txs( State(state): State>, Query(params): Query, ) -> Result>>> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let page = params.page.unwrap_or(1); let page_size = params.page_size.unwrap_or(10); @@ -58,28 +58,22 @@ pub async fn get_txs( .as_str(), ); - let row = sqlx::query(&sql_total) - .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let total: i64 = row.try_get("count").map_err(internal_error)?; - - let rows = sqlx::query(&sql_query) - .fetch_all(&mut *conn) - .await - .map_err(internal_error)?; + let row = sqlx::query(&sql_total).fetch_one(&mut *conn).await?; + let total: i64 = row.try_get("count")?; + + let rows = sqlx::query(&sql_query).fetch_all(&mut *conn).await?; let mut txs: Vec = vec![]; for row in rows { - let tx_hash: String = row.try_get("tx_hash").map_err(internal_error)?; - let block_hash: String = row.try_get("block_hash").map_err(internal_error)?; - let ty: i32 = row.try_get("ty").map_err(internal_error)?; - let timestamp: i64 = row.try_get("timestamp").map_err(internal_error)?; - let height: i64 = row.try_get("height").map_err(internal_error)?; - let code: i64 = row.try_get("code").map_err(internal_error)?; - let log: String = row.try_get("log").map_err(internal_error)?; - let origin: String = row.try_get("origin").map_err(internal_error)?; - let result: Value = row.try_get("result").map_err(internal_error)?; - let value: Value = row.try_get("value").map_err(internal_error)?; + let tx_hash: String = row.try_get("tx_hash")?; + let block_hash: String = row.try_get("block_hash")?; + let ty: i32 = row.try_get("ty")?; + let timestamp: i64 = row.try_get("timestamp")?; + let height: i64 = row.try_get("height")?; + let code: i64 = row.try_get("code")?; + let log: String = row.try_get("log")?; + let origin: String = row.try_get("origin")?; + let result: Value = row.try_get("result")?; + let value: Value = row.try_get("value")?; let evm_tx_hash = if ty == 1 { let evm_tx: FindoraEVMTxWrap = serde_json::from_value(value.clone()).unwrap(); @@ -121,7 +115,7 @@ pub async fn get_tx_by_hash( State(state): State>, Query(params): Query, ) -> Result> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let sql_query = r#"SELECT tx_hash,block_hash,height,timestamp,ty,code,log,origin,result,value FROM transaction WHERE tx_hash=$1"#; @@ -129,19 +123,18 @@ pub async fn get_tx_by_hash( let row = sqlx::query(sql_query) .bind(params.hash) .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - - let tx_hash: String = row.try_get("tx_hash").map_err(internal_error)?; - let block_hash: String = row.try_get("block_hash").map_err(internal_error)?; - let ty: i32 = row.try_get("ty").map_err(internal_error)?; - let timestamp: i64 = row.try_get("timestamp").map_err(internal_error)?; - let height: i64 = row.try_get("height").map_err(internal_error)?; - let code: i64 = row.try_get("code").map_err(internal_error)?; - let log: String = row.try_get("log").map_err(internal_error)?; - let origin: String = row.try_get("origin").map_err(internal_error)?; - let result: Value = row.try_get("result").map_err(internal_error)?; - let value: Value = row.try_get("value").map_err(internal_error)?; + .await?; + + let tx_hash: String = row.try_get("tx_hash")?; + let block_hash: String = row.try_get("block_hash")?; + let ty: i32 = row.try_get("ty")?; + let timestamp: i64 = row.try_get("timestamp")?; + let height: i64 = row.try_get("height")?; + let code: i64 = row.try_get("code")?; + let log: String = row.try_get("log")?; + let origin: String = row.try_get("origin")?; + let result: Value = row.try_get("result")?; + let value: Value = row.try_get("value")?; let evm_tx_hash = if ty == 1 { let evm_tx: FindoraEVMTxWrap = serde_json::from_value(value.clone()).unwrap(); diff --git a/explorer/src/service/v2/undelegation.rs b/explorer/src/service/v2/undelegation.rs index 921cb8c..f4543f2 100644 --- a/explorer/src/service/v2/undelegation.rs +++ b/explorer/src/service/v2/undelegation.rs @@ -1,4 +1,4 @@ -use crate::service::error::{internal_error, Result}; +use crate::service::error::Result; use crate::service::QueryResult; use crate::AppState; use axum::extract::{Query, State}; @@ -30,25 +30,24 @@ pub async fn get_undelegation_by_tx_hash( State(state): State>, Query(params): Query, ) -> Result> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let sql_query = r#"SELECT tx,block,sender,amount,target_validator,new_delegator,height,timestamp,content FROM undelegations WHERE tx=$1"#; let row = sqlx::query(sql_query) .bind(params.hash) .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; + .await?; - let tx_hash: String = row.try_get("tx").map_err(internal_error)?; - let block_hash: String = row.try_get("block").map_err(internal_error)?; - let from: String = row.try_get("sender").map_err(internal_error)?; - let amount: i64 = row.try_get("amount").map_err(internal_error)?; - let target_validator: String = row.try_get("target_validator").map_err(internal_error)?; - let new_delegator: String = row.try_get("new_delegator").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 value: Value = row.try_get("content").map_err(internal_error)?; + let tx_hash: String = row.try_get("tx")?; + let block_hash: String = row.try_get("block")?; + let from: String = row.try_get("sender")?; + let amount: i64 = row.try_get("amount")?; + let target_validator: String = row.try_get("target_validator")?; + let new_delegator: String = row.try_get("new_delegator")?; + let height: i64 = row.try_get("height")?; + let timestamp: i64 = row.try_get("timestamp")?; + let value: Value = row.try_get("content")?; let undelegation = UndelegationResponse { tx_hash, @@ -76,7 +75,7 @@ pub async fn get_undelegations( State(state): State>, Query(params): Query, ) -> Result>>> { - let mut conn = state.pool.acquire().await.map_err(internal_error)?; + let mut conn = state.pool.acquire().await?; let page = params.page.unwrap_or(1); let page_size = params.page_size.unwrap_or(10); @@ -101,25 +100,23 @@ pub async fn get_undelegations( let row_cnt = sqlx::query(sql_count.as_str()) .fetch_one(&mut *conn) - .await - .map_err(internal_error)?; - let total: i64 = row_cnt.try_get("count").map_err(internal_error)?; + .await?; + let total: i64 = row_cnt.try_get("count")?; let mut undelegations: Vec = vec![]; let rows = sqlx::query(sql_query.as_str()) .fetch_all(&mut *conn) - .await - .map_err(internal_error)?; + .await?; for row in rows { - let tx_hash: String = row.try_get("tx").map_err(internal_error)?; - let block_hash: String = row.try_get("block").map_err(internal_error)?; - let from: String = row.try_get("sender").map_err(internal_error)?; - let amount: i64 = row.try_get("amount").map_err(internal_error)?; - let target_validator: String = row.try_get("target_validator").map_err(internal_error)?; - let new_delegator: String = row.try_get("new_delegator").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 value: Value = row.try_get("content").map_err(internal_error)?; + let tx_hash: String = row.try_get("tx")?; + let block_hash: String = row.try_get("block")?; + let from: String = row.try_get("sender")?; + let amount: i64 = row.try_get("amount")?; + let target_validator: String = row.try_get("target_validator")?; + let new_delegator: String = row.try_get("new_delegator")?; + let height: i64 = row.try_get("height")?; + let timestamp: i64 = row.try_get("timestamp")?; + let value: Value = row.try_get("content")?; undelegations.push(UndelegationResponse { tx_hash, block_hash,