145 lines
4.5 KiB
Python
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,
|
|
},
|
|
} |