145 lines
4.5 KiB
Python

from typing import Any, List
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from app import crud, models, schemas
from app.api import deps
from app.models.transaction import TransactionType
router = APIRouter()
@router.get("/", response_model=List[schemas.Wallet])
def read_wallets(
current_user: models.User = Depends(deps.get_current_active_verified_user),
db: Session = Depends(deps.get_db),
) -> Any:
"""
Retrieve user's wallets.
"""
wallets = crud.wallet.get_by_user(db, user_id=current_user.id)
return wallets
@router.get("/{wallet_type}", response_model=schemas.Wallet)
def read_wallet(
wallet_type: schemas.WalletType,
current_user: models.User = Depends(deps.get_current_active_verified_user),
db: Session = Depends(deps.get_db),
) -> Any:
"""
Get a specific wallet by type.
"""
wallet = crud.wallet.get_by_user_and_type(
db, user_id=current_user.id, wallet_type=wallet_type
)
if not wallet:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Wallet of type {wallet_type} not found",
)
return wallet
@router.post("/transfer", response_model=dict)
def transfer_funds(
*,
transfer_data: schemas.WalletTransfer,
current_user: models.User = Depends(deps.get_current_active_verified_user),
db: Session = Depends(deps.get_db),
) -> Any:
"""
Transfer funds between wallets.
"""
if transfer_data.from_wallet_type == transfer_data.to_wallet_type:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Cannot transfer between the same wallet type",
)
from_wallet = crud.wallet.get_by_user_and_type(
db, user_id=current_user.id, wallet_type=transfer_data.from_wallet_type
)
if not from_wallet:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Source wallet of type {transfer_data.from_wallet_type} not found",
)
if from_wallet.balance < transfer_data.amount:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Insufficient funds in source wallet",
)
to_wallet = crud.wallet.get_by_user_and_type(
db, user_id=current_user.id, wallet_type=transfer_data.to_wallet_type
)
if not to_wallet:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Destination wallet of type {transfer_data.to_wallet_type} not found",
)
from_wallet, to_wallet = crud.wallet.transfer(
db,
user_id=current_user.id,
from_type=transfer_data.from_wallet_type,
to_type=transfer_data.to_wallet_type,
amount=transfer_data.amount,
)
if not from_wallet or not to_wallet:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Transfer failed",
)
# Create transfer transaction records
# First, create the outgoing transaction
outgoing_transaction = crud.transaction.create(
db,
obj_in=schemas.TransactionCreate(
user_id=current_user.id,
wallet_id=from_wallet.id,
amount=-transfer_data.amount,
transaction_type=TransactionType.TRANSFER,
description=f"Transfer to {transfer_data.to_wallet_type} wallet",
),
)
# Then, create the incoming transaction
incoming_transaction = crud.transaction.create(
db,
obj_in=schemas.TransactionCreate(
user_id=current_user.id,
wallet_id=to_wallet.id,
amount=transfer_data.amount,
transaction_type=TransactionType.TRANSFER,
description=f"Transfer from {transfer_data.from_wallet_type} wallet",
related_transaction_id=outgoing_transaction.id,
),
)
# Update the related transaction ID for the outgoing transaction
crud.transaction.update(
db,
db_obj=outgoing_transaction,
obj_in={"related_transaction_id": incoming_transaction.id},
)
return {
"message": f"Successfully transferred {transfer_data.amount} USDT from {transfer_data.from_wallet_type} wallet to {transfer_data.to_wallet_type} wallet",
"from_wallet": {
"type": from_wallet.wallet_type,
"balance": from_wallet.balance,
},
"to_wallet": {
"type": to_wallet.wallet_type,
"balance": to_wallet.balance,
},
}