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,