From cf3b9fc0f0725b0076414e67488553634b629670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Tue, 26 Mar 2024 13:32:16 +0100 Subject: [PATCH] Decouple `Withdraw` structure from request handling. --- kairos-server/src/routes/withdraw.rs | 44 +++++++++++++++------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/kairos-server/src/routes/withdraw.rs b/kairos-server/src/routes/withdraw.rs index 3fb72bc5..7f746331 100644 --- a/kairos-server/src/routes/withdraw.rs +++ b/kairos-server/src/routes/withdraw.rs @@ -21,36 +21,37 @@ pub struct Withdrawal { pub async fn withdraw_handler( _: WithdrawPath, State(state): State, - Json(withdrawal): Json, + Json(Withdrawal { + public_key, + signature, + amount, + }): Json, ) -> Result<(), AppErr> { tracing::info!("TODO: verifying withdrawal signature"); tracing::info!("verifying withdrawal sender has sufficient funds"); - check_sender_funds(&state, &withdrawal).await?; + check_sender_funds(&state, &public_key, amount).await?; tracing::info!("TODO: adding withdrawal to batch"); let mut state = state.write().await; - let from_balance = state - .balances - .get_mut(&withdrawal.public_key) - .ok_or_else(|| { - AppErr::set_status( - anyhow!( - "Sender no longer has an account. + let from_balance = state.balances.get_mut(&public_key).ok_or_else(|| { + AppErr::set_status( + anyhow!( + "Sender no longer has an account. The sender just removed all their funds." - ), - StatusCode::CONFLICT, - ) - })?; + ), + StatusCode::CONFLICT, + ) + })?; - let updated_balance = from_balance.checked_sub(withdrawal.amount).ok_or_else(|| { + let updated_balance = from_balance.checked_sub(amount).ok_or_else(|| { AppErr::set_status( anyhow!( "Sender no longer has sufficient funds, balance={}, withdrawal_amount={}. The sender just moved their funds in a concurrent request", from_balance, - withdrawal.amount + amount ), StatusCode::CONFLICT, ) @@ -59,12 +60,12 @@ pub async fn withdraw_handler( *from_balance = updated_balance; if updated_balance == 0 { - state.balances.remove(&withdrawal.public_key); + state.balances.remove(&public_key); } tracing::info!( "Updated account public_key={:?} balance={}", - withdrawal.public_key, + public_key, updated_balance ); @@ -73,19 +74,20 @@ pub async fn withdraw_handler( async fn check_sender_funds( state: &LockedBatchState, - withdrawal: &Withdrawal, + public_key: &PublicKey, + amount: u64, ) -> Result<(), AppErr> { let state = state.read().await; - let from_balance = state.balances.get(&withdrawal.public_key).ok_or_else(|| { + let from_balance = state.balances.get(public_key).ok_or_else(|| { AppErr::set_status(anyhow!("Withdrawer has no account."), StatusCode::CONFLICT) })?; - if *from_balance < withdrawal.amount { + if *from_balance < amount { return Err(AppErr::set_status( anyhow!( "Withdrawer has insufficient funds, balance={}, withdrawal_amount={}.", from_balance, - withdrawal.amount + amount ), StatusCode::FORBIDDEN, ));