Skip to content

Commit

Permalink
Decouple Withdraw structure from request handling.
Browse files Browse the repository at this point in the history
  • Loading branch information
koxu1996 committed Mar 26, 2024
1 parent 17fcb9a commit cf3b9fc
Showing 1 changed file with 23 additions and 21 deletions.
44 changes: 23 additions & 21 deletions kairos-server/src/routes/withdraw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,36 +21,37 @@ pub struct Withdrawal {
pub async fn withdraw_handler(
_: WithdrawPath,
State(state): State<LockedBatchState>,
Json(withdrawal): Json<Withdrawal>,
Json(Withdrawal {
public_key,
signature,
amount,
}): Json<Withdrawal>,
) -> 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,
)
Expand All @@ -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
);

Expand All @@ -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,
));
Expand Down

0 comments on commit cf3b9fc

Please sign in to comment.