From d4c3ce06cf5bb27d5693551ea6f8c9053b55df6e Mon Sep 17 00:00:00 2001 From: laincy Date: Wed, 30 Jul 2025 20:23:11 -0400 Subject: [PATCH 1/4] fix: make krist transaction endpoints respect excludeMined param Added new struct field and an SQL WHERE clause to filter out mined transactions in relevant endpoints. Partially closes #9. --- src/database/transaction.rs | 7 ++++++- src/routes/mod.rs | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/database/transaction.rs b/src/database/transaction.rs index 8544779..d6c794c 100644 --- a/src/database/transaction.rs +++ b/src/database/transaction.rs @@ -135,11 +135,16 @@ impl<'q> Model { pool: &Pool, pagination: &PaginationParams, ) -> Result> { + tracing::info!("Limit was {:?}", pagination.limit); let limit = pagination.limit.unwrap_or(50); let offset = pagination.offset.unwrap_or(0); let limit = limit.clamp(1, 1000); - let q = r#"SELECT * FROM transactions ORDER BY date DESC LIMIT $1 OFFSET $2;"#; + let q = if pagination.exclude_mined == Some(true) { + r#"SELECT * FROM transactions WHERE transaction_type != 'mined' ORDER BY date DESC LIMIT $1 OFFSET $2;"# + } else { + r#"SELECT * FROM transactions ORDER BY date DESC LIMIT $1 OFFSET $2;"# + }; sqlx::query_as(q) .bind(limit) diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 509a5f9..8ec3507 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -41,6 +41,9 @@ pub fn config(cfg: &mut web::ServiceConfig) { #[derive(Debug, serde::Deserialize, serde::Serialize)] pub struct PaginationParams { + #[serde(alias = "excludeMined")] + // Only used on /transactions routes + pub exclude_mined: Option, pub limit: Option, pub offset: Option, } @@ -48,6 +51,7 @@ pub struct PaginationParams { impl Default for PaginationParams { fn default() -> Self { Self { + exclude_mined: None, limit: Some(50), offset: Some(0), } From ebdf9b78273117ab3b044875cdaa6c7f6fc53d02 Mon Sep 17 00:00:00 2001 From: laincy Date: Wed, 30 Jul 2025 22:05:20 -0400 Subject: [PATCH 2/4] fix: make /addresses/{address} endpoint respect the fetchNames param Added a struct defining the query parameters for the krist /addresses/{address} endpoint and implemented a DB query similar to the one used in the address lookup API. Should close #9. --- src/database/wallet.rs | 20 ++++++++++++++++++++ src/models/krist/addresses.rs | 6 ++++++ src/routes/krist/wallet.rs | 11 +++++++++-- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/database/wallet.rs b/src/database/wallet.rs index 0e21742..fe6b519 100644 --- a/src/database/wallet.rs +++ b/src/database/wallet.rs @@ -296,4 +296,24 @@ impl<'q> Model { Ok(models) } + + pub async fn fetch_by_address_names(pool: E, address: S) -> Result> + where + S: AsRef, + E: 'q + Executor<'q, Database = Postgres>, + { + let address = address.as_ref(); + + let q = r#"SELECT wallets.*, + COUNT(names.id) AS NAMES + FROM wallets + LEFT JOIN NAMES ON wallets.address = names.owner + WHERE wallets.address = $1 GROUP BY wallets.id + ORDER BY NAMES DESC"#; + sqlx::query_as(q) + .bind(address) + .fetch_optional(pool) + .await + .map_err(DatabaseError::Sqlx) + } } diff --git a/src/models/krist/addresses.rs b/src/models/krist/addresses.rs index f7a6b95..f3c5899 100644 --- a/src/models/krist/addresses.rs +++ b/src/models/krist/addresses.rs @@ -58,6 +58,12 @@ impl From for AddressJson { } } +#[derive(Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize, Default)] +pub struct AddressGetQuery { + #[serde(alias = "fetchNames")] + pub fetch_names: Option, +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/routes/krist/wallet.rs b/src/routes/krist/wallet.rs index ab27594..3279e14 100644 --- a/src/routes/krist/wallet.rs +++ b/src/routes/krist/wallet.rs @@ -5,7 +5,9 @@ use crate::AppState; use crate::database::{ModelExt, name::Model as Name, wallet::Model as Wallet}; use crate::errors::krist::KristError; use crate::errors::krist::address::AddressError; -use crate::models::krist::addresses::{AddressJson, AddressListResponse, AddressResponse}; +use crate::models::krist::addresses::{ + AddressGetQuery, AddressJson, AddressListResponse, AddressResponse, +}; use crate::models::krist::names::{NameJson, NameListResponse}; use crate::models::krist::transactions::{ AddressTransactionQuery, TransactionJson, TransactionListResponse, @@ -46,10 +48,15 @@ async fn wallet_list( async fn wallet_get( state: web::Data, address: web::Path, + query: web::Query, ) -> Result { let address = address.into_inner(); - let wallet = Wallet::fetch_by_address(&state.pool, &address).await?; + let wallet = if query.0.fetch_names == Some(true) { + Wallet::fetch_by_address_names(&state.pool, &address).await? + } else { + Wallet::fetch_by_address(&state.pool, &address).await? + }; wallet .map(|addr| AddressResponse { From b58b48862a9845abdacc7ec73c51eeb5ee2384a6 Mon Sep 17 00:00:00 2001 From: laincy Date: Wed, 30 Jul 2025 23:47:26 -0400 Subject: [PATCH 3/4] fix: remove extra debug trace I forgot to remove an info trace I was using during debugging and should not have been committed. --- src/database/transaction.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/database/transaction.rs b/src/database/transaction.rs index d6c794c..57bade4 100644 --- a/src/database/transaction.rs +++ b/src/database/transaction.rs @@ -135,7 +135,6 @@ impl<'q> Model { pool: &Pool, pagination: &PaginationParams, ) -> Result> { - tracing::info!("Limit was {:?}", pagination.limit); let limit = pagination.limit.unwrap_or(50); let offset = pagination.offset.unwrap_or(0); let limit = limit.clamp(1, 1000); From 258d115bf0cdb4aa0ac71b4877c35a9da3b0eb20 Mon Sep 17 00:00:00 2001 From: laincy Date: Thu, 31 Jul 2025 12:04:58 -0400 Subject: [PATCH 4/4] fix: replace if statements with matches Genuinely not sure why I made these if statements in the first place lmao --- src/database/transaction.rs | 9 +++++---- src/routes/krist/wallet.rs | 7 +++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/database/transaction.rs b/src/database/transaction.rs index 57bade4..867f4f1 100644 --- a/src/database/transaction.rs +++ b/src/database/transaction.rs @@ -139,10 +139,11 @@ impl<'q> Model { let offset = pagination.offset.unwrap_or(0); let limit = limit.clamp(1, 1000); - let q = if pagination.exclude_mined == Some(true) { - r#"SELECT * FROM transactions WHERE transaction_type != 'mined' ORDER BY date DESC LIMIT $1 OFFSET $2;"# - } else { - r#"SELECT * FROM transactions ORDER BY date DESC LIMIT $1 OFFSET $2;"# + let q = match pagination.exclude_mined { + Some(true) => { + r#"SELECT * FROM transactions WHERE transaction_type != 'mined' ORDER BY date DESC LIMIT $1 OFFSET $2;"# + } + _ => r#"SELECT * FROM transactions ORDER BY date DESC LIMIT $1 OFFSET $2;"#, }; sqlx::query_as(q) diff --git a/src/routes/krist/wallet.rs b/src/routes/krist/wallet.rs index 3279e14..3d68c93 100644 --- a/src/routes/krist/wallet.rs +++ b/src/routes/krist/wallet.rs @@ -52,10 +52,9 @@ async fn wallet_get( ) -> Result { let address = address.into_inner(); - let wallet = if query.0.fetch_names == Some(true) { - Wallet::fetch_by_address_names(&state.pool, &address).await? - } else { - Wallet::fetch_by_address(&state.pool, &address).await? + let wallet = match query.0.fetch_names { + Some(true) => Wallet::fetch_by_address_names(&state.pool, &address).await?, + _ => Wallet::fetch_by_address(&state.pool, &address).await?, }; wallet