uploader-bot/app/core/transactions.py

74 lines
2.8 KiB
Python

from datetime import datetime
from sqlalchemy import select, and_, func
from app.core.logger import make_log
from app.core.models import Memory, User, UserBalance, Asset, InternalTransaction
from app.core.storage import db_session
async def get_user_balance(session, user: User, asset: Asset) -> UserBalance:
assert user, "No user"
assert asset, "No asset"
result = await session.execute(select(UserBalance).where(
and_(UserBalance.user_id == user.id, UserBalance.asset_id == asset.id)
))
row = result.scalars().first()
if not row:
user_balance = UserBalance(
user_id=user.id,
asset_id=asset.id,
balance=0,
created=datetime.now(),
)
session.add(user_balance)
await session.commit()
return await get_user_balance(session, user, asset)
return row
async def make_internal_transaction(
memory: Memory, user_id: int, asset_id: int, amount: float,
is_spent: bool, type: str = "NOT_SPECIFIED", spent_transaction_id: int = None
) -> InternalTransaction:
amount = float(amount)
is_spent = bool(is_spent)
type = str(type)[:256]
if amount < 0:
if not is_spent:
raise Exception(f"Invalid is_spent: {is_spent}, amount: {amount}")
elif amount > 0:
if is_spent:
raise Exception(f"Invalid is_spent: {is_spent}, amount: {amount}")
else:
raise Exception(f"Invalid amount: {amount}")
abs_amount = abs(amount)
async with db_session(auto_commit=False) as session:
async with memory.transaction():
user = (await session.execute(select(User).where(User.id == user_id))).scalars().first()
assert user, "No user"
asset = (await session.execute(select(Asset).where(Asset.id == asset_id))).scalars().first()
assert asset, "No asset"
user_balance = await get_user_balance(session, user, asset)
assert user_balance, "No user balance"
if is_spent is True:
if abs_amount > user_balance.balance:
raise Exception(f"Insufficient balance: {user_balance.balance} < {abs_amount}")
user_balance.balance = float(user_balance.balance) + amount
user_balance.updated = datetime.now()
internal_transaction = InternalTransaction(
user_id=user.id,
asset_id=asset.id,
amount=abs_amount,
is_spent=is_spent,
type=type,
spent_transaction_id=spent_transaction_id,
created=datetime.now(),
)
session.add(internal_transaction)
await session.commit()
make_log(user, f"Made internal transaction: {'-' if is_spent else ''}{abs_amount} {asset.symbol}, type: {type}")