From ae728eeb07e5d35d2981ffb067b5e1a887501384 Mon Sep 17 00:00:00 2001 From: scx1332 Date: Tue, 19 Mar 2024 21:14:47 +0100 Subject: [PATCH] f --- crates/erc20_payment_lib/src/server/web.rs | 109 ++++++++++++++++++ .../src/db/model/chain_transfer_dao.rs | 4 +- src/actions/scan_chain.rs | 2 +- 3 files changed, 113 insertions(+), 2 deletions(-) diff --git a/crates/erc20_payment_lib/src/server/web.rs b/crates/erc20_payment_lib/src/server/web.rs index f44516ab..3e1faa55 100644 --- a/crates/erc20_payment_lib/src/server/web.rs +++ b/crates/erc20_payment_lib/src/server/web.rs @@ -20,8 +20,10 @@ use std::collections::BTreeMap; use std::str::FromStr; use std::sync::Arc; use std::time::Duration; +use chrono::{DateTime, Utc}; use tokio::sync::Mutex; use web3::types::{Address, BlockId, BlockNumber, U256}; +use erc20_payment_lib_common::model::ChainTransferDbObj; pub struct ServerData { pub shared_state: Arc>, @@ -662,6 +664,112 @@ async fn new_transfer( Ok("success".to_string()) } +#[derive(Deserialize)] +struct StatsTransferRequest { + account: Option, + from: Option, + chain: Option +} + + +#[derive(Debug, Serialize)] +struct StatsTransferResult { + transfers: Vec, +} + + +#[derive(Serialize, sqlx::FromRow, Debug, Clone)] +#[serde(rename_all = "camelCase")] +pub struct ChainTransferRespObj { + pub id: i64, + pub from_addr: String, + pub receiver_addr: String, + pub chain_id: i64, + pub token_addr: Option, + pub token_amount: String, + pub tx_hash: String, + pub block_number: i64, + pub fee_paid: Option, + pub block_date: DateTime, + pub block_timestamp: i64, +} + + +pub async fn stats_transfers( + data: Data>, + info: web::Query +) -> actix_web::Result> { + let account = Address::from_str( + &info.account.clone().ok_or(actix_web::error::ErrorBadRequest("account not found"))?, + ) + .map_err(|err| { + actix_web::error::ErrorBadRequest(format!("account has to be valid address {err}")) + })?; + + let from = chrono::DateTime::from_timestamp( + i64::from_str(&info.from.clone().ok_or(actix_web::error::ErrorBadRequest("From not found"))?).map_err( + |err| actix_web::error::ErrorBadRequest(format!("From is not a valid timestamp {err}")) + )?, 0 + ) + .ok_or( + actix_web::error::ErrorBadRequest(format!("From is not a valid timestamp.")) + )?; + let chain_id = + i64::from_str(&info.chain.clone().ok_or(actix_web::error::ErrorBadRequest("Chain id not found"))?).map_err( + |err| actix_web::error::ErrorBadRequest(format!("Chain id a valid {err}")) + )?; + + + let conn = data.db_connection.lock().await.clone(); + let transf = get_all_chain_transfers(&conn, None).await; + let transf = transf.map_err(|err| { + actix_web::error::ErrorBadRequest(format!("Unknown server error: {}", err)) + })?; + + let txs = get_chain_txs_by_chain_id(&conn, chain_id, None).await + .map_err( + |err| actix_web::error::ErrorBadRequest(format!("Unknown server error: {}", err)) + )?; + let map_txs = txs.iter().map(|tx| (tx.id, tx.clone())).collect::>(); + + + let account_str = format!("{:#x}", account); + let mut resp = Vec::new(); + for trans in transf.iter() { + let Some(blockchain_date) = trans.blockchain_date else { + continue; + }; + + if blockchain_date < from { + continue; + } + if trans.receiver_addr != account_str { + continue; + } + + let tx = map_txs.get(&trans.chain_tx_id).map(|tx| tx.clone()); + let Some(tx) = tx else { + continue; + }; + resp.push(ChainTransferRespObj { + id: trans.id, + from_addr: trans.from_addr.clone(), + receiver_addr: trans.receiver_addr.clone(), + chain_id: trans.chain_id, + token_addr: trans.token_addr.clone(), + token_amount: trans.token_amount.clone(), + tx_hash: tx.tx_hash, + block_number: tx.block_number, + fee_paid: trans.fee_paid.clone(), + block_date: blockchain_date.clone(), + block_timestamp: blockchain_date.timestamp() + }) + } + + //serialize + Ok(web::Json(StatsTransferResult { transfers: resp })) +} + pub async fn transfers(data: Data>, req: HttpRequest) -> impl Responder { let tx_id = req .match_info() @@ -1088,6 +1196,7 @@ pub fn runtime_web_scope( .route("/rpc_pool", web::get().to(rpc_pool)) .route("/rpc_pool/metrics", web::get().to(rpc_pool_metrics)) .route("/config", web::get().to(config_endpoint)) + .route("/stats/transfers", web::get().to(stats_transfers)) .route("/transactions", web::get().to(transactions)) .route("/transactions/count", web::get().to(transactions_count)) .route("/transactions/next", web::get().to(transactions_next)) diff --git a/crates/erc20_payment_lib_common/src/db/model/chain_transfer_dao.rs b/crates/erc20_payment_lib_common/src/db/model/chain_transfer_dao.rs index 55ea6432..ce0a4ea8 100644 --- a/crates/erc20_payment_lib_common/src/db/model/chain_transfer_dao.rs +++ b/crates/erc20_payment_lib_common/src/db/model/chain_transfer_dao.rs @@ -1,5 +1,5 @@ use chrono::{DateTime, Utc}; -use serde::Serialize; +use serde::{Serialize}; #[derive(Serialize, sqlx::FromRow, Debug, Clone)] #[serde(rename_all = "camelCase")] @@ -14,6 +14,8 @@ pub struct ChainTransferDbObj { pub fee_paid: Option, pub blockchain_date: Option>, } + + /* #[derive(Serialize, sqlx::FromRow, Debug, Clone)] #[serde(rename_all = "camelCase")] diff --git a/src/actions/scan_chain.rs b/src/actions/scan_chain.rs index 72edb311..e1b9e978 100644 --- a/src/actions/scan_chain.rs +++ b/src/actions/scan_chain.rs @@ -111,6 +111,7 @@ async fn scan_auto_step( (start_block, end_block, true) } else { if scan_info.start_block <= scan_blockchain_options.from_block.unwrap_or(1) as i64 { + tokio::time::sleep(std::time::Duration::from_secs(5)).await; return Ok(()); } @@ -127,7 +128,6 @@ async fn scan_auto_step( ); return Ok(()); } - }; log::info!(