diff --git a/explorer/src/service/api.rs b/explorer/src/service/api.rs index 5a8a579..1fb74a6 100644 --- a/explorer/src/service/api.rs +++ b/explorer/src/service/api.rs @@ -33,7 +33,10 @@ use crate::service::v2::other::{ v2_address_count, v2_distribute, v2_statistics, V2ChainStatisticsResponse, V2DistributeResponse, }; use crate::service::v2::transaction::v2_get_txs; -use crate::service::v2::undelegation::{v2_get_undelegation_tx, V2UndelegationTxResponse}; +use crate::service::v2::undelegation::{ + v2_get_undelegation_tx, v2_get_undelegation_txs, V2UndelegationTxResponse, + V2UndelegationTxsResponse, +}; use crate::service::ApiTags; use poem_openapi::param::{Path, Query}; use poem_openapi::OpenApi; @@ -801,7 +804,21 @@ impl Api { .await .map_err(handle_fetch_one_err) } - + #[oai( + path = "/v2/tx/undelegations", + method = "get", + tag = "ApiTags::Transaction" + )] + async fn v2_get_undelegation_txs( + &self, + address: Query, + page: Query>, + page_size: Query>, + ) -> poem::Result { + v2_get_undelegation_txs(self, address, page, page_size) + .await + .map_err(handle_fetch_one_err) + } #[oai( path = "/v2/tx/claim/:tx_hash", method = "get", diff --git a/explorer/src/service/v2/undelegation.rs b/explorer/src/service/v2/undelegation.rs index e988914..7aa4443 100644 --- a/explorer/src/service/v2/undelegation.rs +++ b/explorer/src/service/v2/undelegation.rs @@ -1,5 +1,6 @@ use crate::service::api::Api; use anyhow::Result; +use poem_openapi::param::Query; use poem_openapi::{param::Path, payload::Json, ApiResponse, Object}; use reqwest::StatusCode; use serde::{Deserialize, Serialize}; @@ -42,7 +43,7 @@ pub async fn v2_get_undelegation_tx( ) -> Result { let mut conn = api.storage.lock().await.acquire().await?; let sql_query = format!( - "SELECT * FROM undelegations WHERE tx='{}'", + "SELECT tx,block,sender,amount,validator,new_validator,timestamp,height,content FROM undelegations WHERE tx='{}'", tx_hash.0.to_lowercase() ); @@ -76,3 +77,86 @@ pub async fn v2_get_undelegation_tx( data: Some(res), }))) } +#[derive(ApiResponse)] +pub enum V2UndelegationTxsResponse { + #[oai(status = 200)] + Ok(Json), + #[oai(status = 404)] + NotFound, + #[oai(status = 500)] + InternalError, +} +#[derive(Serialize, Deserialize, Debug, Object)] +pub struct V2UndelegationTxsResult { + pub code: u16, + pub message: String, + pub data: V2UndelegationTxsData, +} + +#[derive(Serialize, Deserialize, Debug, Object)] +pub struct V2UndelegationTxsData { + pub page: i64, + pub page_size: i64, + pub total: i64, + pub items: Option>, +} + +pub async fn v2_get_undelegation_txs( + api: &Api, + address: Query, + page: Query>, + page_size: Query>, +) -> Result { + let mut conn = api.storage.lock().await.acquire().await?; + let page = page.0.unwrap_or(1); + let page_size = page_size.0.unwrap_or(10); + let sql_count = format!( + "SELECT count(*) AS cnt FROM undelegations WHERE sender='{}'", + address.0.to_lowercase() + ); + let row_cnt = sqlx::query(sql_count.as_str()).fetch_one(&mut conn).await?; + let total: i64 = row_cnt.try_get("cnt")?; + + let sql_query = format!( + "SELECT tx,block,sender,amount,target_validator,new_delegator,height,timestamp,content FROM undelegations WHERE sender='{}' ORDER BY timestamp DESC LIMIT {} OFFSET {}", + address.0.to_lowercase(), page_size, (page-1)*page_size + ); + + let mut res: Vec = vec![]; + let rows = sqlx::query(sql_query.as_str()).fetch_all(&mut conn).await?; + for row in rows { + let tx: String = row.try_get("tx")?; + let block: String = row.try_get("block")?; + let sender: 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")?; + res.push(V2UndelegationTx { + tx_hash: tx, + block_hash: block, + from: sender, + new_delegator, + target_validator, + amount: amount as u64, + height, + timestamp, + value, + }); + } + + Ok(V2UndelegationTxsResponse::Ok(Json( + V2UndelegationTxsResult { + code: 200, + message: "".to_string(), + data: V2UndelegationTxsData { + page, + page_size, + total, + items: Some(res), + }, + }, + ))) +}