01 Refactor currency handling to store amounts in GTQ: Removed currency conversion utilities, updated models and API endpoints to directly handle GTQ amounts, and modified transaction processing logic for consistency. Enhanced frontend to reflect these changes, ensuring accurate display and submission of GTQ values across the application.

Refactor GTQ storage migration: Moved the conversion logic for centavo amounts to GTQ into a new migration function, m004_convert_to_gtq_storage, ensuring proper data type changes and updates across relevant tables. This enhances clarity and maintains the integrity of the migration process.
This commit is contained in:
padreug 2025-07-06 00:00:30 +02:00
parent aa71321c84
commit c83ebf43ab
8 changed files with 157 additions and 162 deletions

View file

@ -267,7 +267,7 @@ async def get_client_balance_summary(client_id: str, as_of_time: Optional[dateti
from loguru import logger
# Verify timezone consistency for temporal filtering
tz_info = "UTC" if as_of_time.tzinfo == timezone.utc else f"TZ: {as_of_time.tzinfo}"
logger.info(f"Client {client_id[:8]}... balance as of {as_of_time} ({tz_info}): deposits.confirmed_at <= cutoff, payments.transaction_time <= cutoff → {total_deposits - total_payments} centavos remaining")
logger.info(f"Client {client_id[:8]}... balance as of {as_of_time} ({tz_info}): deposits.confirmed_at <= cutoff, payments.transaction_time <= cutoff → {total_deposits - total_payments:.2f} GTQ remaining")
return ClientBalanceSummary(
client_id=client_id,

View file

@ -1,45 +0,0 @@
# Currency conversion utilities for API boundary
from decimal import Decimal
from typing import Union
def gtq_to_centavos(gtq_amount: Union[float, int, str]) -> int:
"""Convert GTQ to centavos for database storage"""
return int(Decimal(str(gtq_amount)) * 100)
def centavos_to_gtq(centavos: int) -> float:
"""Convert centavos to GTQ for API responses"""
return float(centavos) / 100
def format_gtq_currency(centavos: int) -> str:
"""Format centavos as GTQ currency string"""
gtq_amount = centavos_to_gtq(centavos)
return f"Q{gtq_amount:.2f}"
# Conversion helpers for API responses
def deposit_db_to_api(deposit_db) -> dict:
"""Convert database deposit model to API response"""
return {
"id": deposit_db.id,
"client_id": deposit_db.client_id,
"amount_gtq": centavos_to_gtq(deposit_db.amount),
"currency": deposit_db.currency,
"status": deposit_db.status,
"notes": deposit_db.notes,
"created_at": deposit_db.created_at,
"confirmed_at": deposit_db.confirmed_at
}
def balance_summary_db_to_api(balance_db) -> dict:
"""Convert database balance summary to API response"""
return {
"client_id": balance_db.client_id,
"total_deposits_gtq": centavos_to_gtq(balance_db.total_deposits),
"total_payments_gtq": centavos_to_gtq(balance_db.total_payments),
"remaining_balance_gtq": centavos_to_gtq(balance_db.remaining_balance),
"currency": balance_db.currency
}

View file

@ -134,4 +134,88 @@ async def m003_add_max_daily_limit_config(db):
ALTER TABLE satoshimachine.lamassu_config
ADD COLUMN max_daily_limit_gtq INTEGER NOT NULL DEFAULT 2000
"""
)
async def m004_convert_to_gtq_storage(db):
"""
Convert centavo storage to GTQ storage by changing data types and converting existing data.
"""
# Convert dca_deposits amounts from centavos to GTQ
await db.execute(
"""
UPDATE satoshimachine.dca_deposits
SET amount = CAST(amount AS DECIMAL(10,2)) / 100.0
WHERE currency = 'GTQ'
"""
)
# Convert dca_payments amounts from centavos to GTQ
await db.execute(
"""
UPDATE satoshimachine.dca_payments
SET amount_fiat = CAST(amount_fiat AS DECIMAL(10,2)) / 100.0
"""
)
# Convert lamassu_transactions amounts from centavos to GTQ
await db.execute(
"""
UPDATE satoshimachine.lamassu_transactions
SET fiat_amount = CAST(fiat_amount AS DECIMAL(10,2)) / 100.0
"""
)
# Convert fixed_mode_daily_limit from centavos to GTQ
await db.execute(
"""
UPDATE satoshimachine.dca_clients
SET fixed_mode_daily_limit = CAST(fixed_mode_daily_limit AS DECIMAL(10,2)) / 100.0
WHERE fixed_mode_daily_limit IS NOT NULL
"""
)
# Convert max_daily_limit_gtq in config (if already in centavos)
await db.execute(
"""
UPDATE satoshimachine.lamassu_config
SET max_daily_limit_gtq = CAST(max_daily_limit_gtq AS DECIMAL(10,2)) / 100.0
WHERE max_daily_limit_gtq > 1000
"""
)
# Change column types to DECIMAL
await db.execute(
"""
ALTER TABLE satoshimachine.dca_deposits
ALTER COLUMN amount TYPE DECIMAL(10,2)
"""
)
await db.execute(
"""
ALTER TABLE satoshimachine.dca_payments
ALTER COLUMN amount_fiat TYPE DECIMAL(10,2)
"""
)
await db.execute(
"""
ALTER TABLE satoshimachine.lamassu_transactions
ALTER COLUMN fiat_amount TYPE DECIMAL(10,2)
"""
)
await db.execute(
"""
ALTER TABLE satoshimachine.dca_clients
ALTER COLUMN fixed_mode_daily_limit TYPE DECIMAL(10,2)
"""
)
await db.execute(
"""
ALTER TABLE satoshimachine.lamassu_config
ALTER COLUMN max_daily_limit_gtq TYPE DECIMAL(10,2)
"""
)

View file

@ -3,7 +3,7 @@
from datetime import datetime
from typing import Optional
from pydantic import BaseModel
from pydantic import BaseModel, validator
# DCA Client Models
@ -12,7 +12,7 @@ class CreateDcaClientData(BaseModel):
wallet_id: str
username: str
dca_mode: str = "flow" # 'flow' or 'fixed'
fixed_mode_daily_limit: Optional[int] = None
fixed_mode_daily_limit: Optional[float] = None
class DcaClient(BaseModel):
@ -30,45 +30,29 @@ class DcaClient(BaseModel):
class UpdateDcaClientData(BaseModel):
username: Optional[str] = None
dca_mode: Optional[str] = None
fixed_mode_daily_limit: Optional[int] = None
fixed_mode_daily_limit: Optional[float] = None
status: Optional[str] = None
# API Models for Deposits (Frontend <-> Backend communication)
class CreateDepositAPI(BaseModel):
"""API model - frontend sends GTQ amounts"""
client_id: str
amount_gtq: float # Amount in GTQ (e.g., 150.75)
currency: str = "GTQ"
notes: Optional[str] = None
class DepositAPI(BaseModel):
"""API model - backend returns GTQ amounts"""
id: str
client_id: str
amount_gtq: float # Amount in GTQ (e.g., 150.75)
currency: str
status: str # 'pending' or 'confirmed'
notes: Optional[str]
created_at: datetime
confirmed_at: Optional[datetime]
# Database Models for Deposits (Internal storage in centavos)
# Deposit Models (Now storing GTQ directly)
class CreateDepositData(BaseModel):
"""Internal model - database stores centavos"""
client_id: str
amount: int # Amount in smallest currency unit (centavos for GTQ)
amount: float # Amount in GTQ (e.g., 150.75)
currency: str = "GTQ"
notes: Optional[str] = None
@validator('amount')
def round_amount_to_cents(cls, v):
"""Ensure amount is rounded to 2 decimal places for DECIMAL(10,2) storage"""
if v is not None:
return round(float(v), 2)
return v
class DcaDeposit(BaseModel):
"""Internal model - database stores centavos"""
id: str
client_id: str
amount: int
amount: float # Amount in GTQ (e.g., 150.75)
currency: str
status: str # 'pending' or 'confirmed'
notes: Optional[str]
@ -85,7 +69,7 @@ class UpdateDepositStatusData(BaseModel):
class CreateDcaPaymentData(BaseModel):
client_id: str
amount_sats: int
amount_fiat: int # Stored in centavos (GTQ * 100) for precision
amount_fiat: float # Amount in GTQ (e.g., 150.75)
exchange_rate: float
transaction_type: str # 'flow', 'fixed', 'manual', 'commission'
lamassu_transaction_id: Optional[str] = None
@ -97,7 +81,7 @@ class DcaPayment(BaseModel):
id: str
client_id: str
amount_sats: int
amount_fiat: int # Stored in centavos (GTQ * 100) for precision
amount_fiat: float # Amount in GTQ (e.g., 150.75)
exchange_rate: float
transaction_type: str
lamassu_transaction_id: Optional[str]
@ -107,30 +91,19 @@ class DcaPayment(BaseModel):
transaction_time: Optional[datetime] = None # Original ATM transaction time
# API Models for Client Balance Summary
class ClientBalanceSummaryAPI(BaseModel):
"""API model - returns GTQ amounts"""
client_id: str
total_deposits_gtq: float # Total confirmed deposits in GTQ
total_payments_gtq: float # Total payments made in GTQ
remaining_balance_gtq: float # Available balance for DCA in GTQ
currency: str
# Internal Models for Client Balance Summary
# Client Balance Summary (Now storing GTQ directly)
class ClientBalanceSummary(BaseModel):
"""Internal model - stores centavos"""
client_id: str
total_deposits: int # Total confirmed deposits
total_payments: int # Total payments made
remaining_balance: int # Available balance for DCA
total_deposits: float # Total confirmed deposits in GTQ
total_payments: float # Total payments made in GTQ
remaining_balance: float # Available balance for DCA in GTQ
currency: str
# Transaction Processing Models
class LamassuTransaction(BaseModel):
transaction_id: str
amount_fiat: int # Stored in centavos (GTQ * 100) for precision
amount_fiat: float # Amount in GTQ (e.g., 150.75)
amount_crypto: int
exchange_rate: float
transaction_type: str # 'cash_in' or 'cash_out'
@ -141,7 +114,7 @@ class LamassuTransaction(BaseModel):
# Lamassu Transaction Storage Models
class CreateLamassuTransactionData(BaseModel):
lamassu_transaction_id: str
fiat_amount: int # Stored in centavos (GTQ * 100) for precision
fiat_amount: float # Amount in GTQ (e.g., 150.75)
crypto_amount: int
commission_percentage: float
discount: float = 0.0
@ -158,7 +131,7 @@ class CreateLamassuTransactionData(BaseModel):
class StoredLamassuTransaction(BaseModel):
id: str
lamassu_transaction_id: str
fiat_amount: int
fiat_amount: float # Amount in GTQ (e.g., 150.75)
crypto_amount: int
commission_percentage: float
discount: float
@ -194,7 +167,14 @@ class CreateLamassuConfigData(BaseModel):
ssh_password: Optional[str] = None
ssh_private_key: Optional[str] = None # Path to private key file or key content
# DCA Client Limits
max_daily_limit_gtq: int = 2000 # Maximum daily limit for Fixed mode clients
max_daily_limit_gtq: float = 2000.0 # Maximum daily limit for Fixed mode clients
@validator('max_daily_limit_gtq')
def round_max_daily_limit(cls, v):
"""Ensure max daily limit is rounded to 2 decimal places"""
if v is not None:
return round(float(v), 2)
return v
class LamassuConfig(BaseModel):
@ -224,7 +204,7 @@ class LamassuConfig(BaseModel):
last_poll_time: Optional[datetime] = None
last_successful_poll: Optional[datetime] = None
# DCA Client Limits
max_daily_limit_gtq: int = 2000 # Maximum daily limit for Fixed mode clients
max_daily_limit_gtq: float = 2000.0 # Maximum daily limit for Fixed mode clients
class UpdateLamassuConfigData(BaseModel):

View file

@ -27,7 +27,7 @@ window.app = Vue.createApp({
depositsTable: {
columns: [
{ name: 'client_id', align: 'left', label: 'Client', field: 'client_id' },
{ name: 'amount_gtq', align: 'left', label: 'Amount', field: 'amount_gtq' },
{ name: 'amount', align: 'left', label: 'Amount', field: 'amount' },
{ name: 'currency', align: 'left', label: 'Currency', field: 'currency' },
{ name: 'status', align: 'left', label: 'Status', field: 'status' },
{ name: 'created_at', align: 'left', label: 'Created', field: 'created_at' },
@ -130,11 +130,11 @@ window.app = Vue.createApp({
///////////////////////////////////////////////////
methods: {
// Utility Methods - Simplified since API handles conversion
// Utility Methods
formatCurrency(amount) {
if (!amount) return 'Q 0.00';
// Amount is already in GTQ from API
// Amount is now stored as GTQ directly in database
return new Intl.NumberFormat('es-GT', {
style: 'currency',
currency: 'GTQ',
@ -279,7 +279,7 @@ window.app = Vue.createApp({
)
return {
...client,
remaining_balance: balance.remaining_balance_gtq
remaining_balance: balance.remaining_balance
}
} catch (error) {
console.error(`Error fetching balance for client ${client.id}:`, error)
@ -303,7 +303,7 @@ window.app = Vue.createApp({
try {
const data = {
client_id: this.quickDepositForm.selectedClient?.value,
amount_gtq: this.quickDepositForm.amount, // Send GTQ directly - API handles conversion
amount: this.quickDepositForm.amount, // Send GTQ directly - now stored as GTQ
currency: 'GTQ',
notes: this.quickDepositForm.notes
}
@ -376,7 +376,7 @@ window.app = Vue.createApp({
try {
const data = {
client_id: this.depositFormDialog.data.client_id,
amount_gtq: this.depositFormDialog.data.amount, // Send GTQ directly - API handles conversion
amount: this.depositFormDialog.data.amount, // Send GTQ directly - now stored as GTQ
currency: this.depositFormDialog.data.currency,
notes: this.depositFormDialog.data.notes
}

View file

@ -173,7 +173,7 @@
<q-tr :props="props">
<q-td v-for="col in props.cols" :key="col.name" :props="props">
<div v-if="col.field == 'client_id'">${ getClientUsername(col.value) }</div>
<div v-else-if="col.field == 'amount_gtq'">${ formatCurrency(col.value) }</div>
<div v-else-if="col.field == 'amount'">${ formatCurrency(col.value) }</div>
<div v-else-if="col.field == 'status'">
<q-badge :color="col.value === 'confirmed' ? 'green' : 'orange'">
${ col.value }
@ -470,9 +470,9 @@
<q-item-section>
<q-item-label caption>Balance Summary</q-item-label>
<q-item-label v-if="clientDetailsDialog.balance">
Deposits: ${ formatCurrency(clientDetailsDialog.balance.total_deposits_gtq) } |
Payments: ${ formatCurrency(clientDetailsDialog.balance.total_payments_gtq) } |
Remaining: ${ formatCurrency(clientDetailsDialog.balance.remaining_balance_gtq) }
Deposits: ${ formatCurrency(clientDetailsDialog.balance.total_deposits) } |
Payments: ${ formatCurrency(clientDetailsDialog.balance.total_payments) } |
Remaining: ${ formatCurrency(clientDetailsDialog.balance.remaining_balance) }
</q-item-label>
</q-item-section>
</q-item>

View file

@ -671,7 +671,7 @@ class LamassuTransactionProcessor:
# Since crypto_atoms already includes commission, we need to extract the base amount
# Formula: crypto_atoms = base_amount * (1 + effective_commission)
# Therefore: base_amount = crypto_atoms / (1 + effective_commission)
base_crypto_atoms = int(crypto_atoms / (1 + effective_commission))
base_crypto_atoms = round(crypto_atoms / (1 + effective_commission))
commission_amount_sats = crypto_atoms - base_crypto_atoms
else:
effective_commission = 0.0
@ -755,9 +755,8 @@ class LamassuTransactionProcessor:
client_sats_amount = calc['allocated_sats']
proportion = calc['proportion']
# Calculate equivalent fiat value in centavos for tracking purposes (industry standard)
# Store as centavos to maintain precision and avoid floating-point errors
client_fiat_amount = round(client_sats_amount * 100 / exchange_rate) if exchange_rate > 0 else 0
# Calculate equivalent fiat value in GTQ for tracking purposes
client_fiat_amount = round(client_sats_amount / exchange_rate, 2) if exchange_rate > 0 else 0.0
distributions[client_id] = {
"fiat_amount": client_fiat_amount,
@ -765,7 +764,7 @@ class LamassuTransactionProcessor:
"exchange_rate": exchange_rate
}
logger.info(f"Client {client_id[:8]}... gets {client_sats_amount} sats (≈{client_fiat_amount/100:.2f} GTQ, {proportion:.2%} share)")
logger.info(f"Client {client_id[:8]}... gets {client_sats_amount} sats (≈{client_fiat_amount:.2f} GTQ, {proportion:.2%} share)")
# Verification: ensure total distribution equals base amount
total_distributed = sum(dist["sats_amount"] for dist in distributions.values())
@ -781,9 +780,9 @@ class LamassuTransactionProcessor:
current_balance = await get_client_balance_summary(client_id)
if current_balance.remaining_balance > 0:
final_distributions[client_id] = distribution
logger.info(f"Client {client_id[:8]}... final balance check: {current_balance.remaining_balance} centavos - APPROVED for {distribution['sats_amount']} sats")
logger.info(f"Client {client_id[:8]}... final balance check: {current_balance.remaining_balance:.2f} GTQ - APPROVED for {distribution['sats_amount']} sats")
else:
logger.warning(f"Client {client_id[:8]}... final balance check: {current_balance.remaining_balance} centavos - REJECTED (negative balance)")
logger.warning(f"Client {client_id[:8]}... final balance check: {current_balance.remaining_balance:.2f} GTQ - REJECTED (negative balance)")
if len(final_distributions) != len(distributions):
logger.warning(f"Rejected {len(distributions) - len(final_distributions)} clients due to negative balances during final check")
@ -830,22 +829,22 @@ class LamassuTransactionProcessor:
# Final safety check: Verify client still has positive balance before payment
current_balance = await get_client_balance_summary(client_id)
if current_balance.remaining_balance <= 0:
logger.error(f"CRITICAL: Client {client_id[:8]}... has negative balance ({current_balance.remaining_balance} centavos) - REFUSING payment of {distribution['sats_amount']} sats")
logger.error(f"CRITICAL: Client {client_id[:8]}... has negative balance ({current_balance.remaining_balance:.2f} GTQ) - REFUSING payment of {distribution['sats_amount']} sats")
continue
# Verify balance is sufficient for this distribution
fiat_equivalent = distribution["fiat_amount"] # Already in centavos
fiat_equivalent = distribution["fiat_amount"] # Amount in GTQ
if current_balance.remaining_balance < fiat_equivalent:
logger.error(f"CRITICAL: Client {client_id[:8]}... insufficient balance ({current_balance.remaining_balance} < {fiat_equivalent} centavos) - REFUSING payment")
logger.error(f"CRITICAL: Client {client_id[:8]}... insufficient balance ({current_balance.remaining_balance:.2f} < {fiat_equivalent:.2f} GTQ) - REFUSING payment")
continue
logger.info(f"Client {client_id[:8]}... pre-payment balance check: {current_balance.remaining_balance} centavos - SUFFICIENT for {fiat_equivalent} centavos payment")
logger.info(f"Client {client_id[:8]}... pre-payment balance check: {current_balance.remaining_balance:.2f} GTQ - SUFFICIENT for {fiat_equivalent:.2f} GTQ payment")
# Create DCA payment record
payment_data = CreateDcaPaymentData(
client_id=client_id,
amount_sats=distribution["sats_amount"],
amount_fiat=distribution["fiat_amount"], # Still store centavos in DB
amount_fiat=distribution["fiat_amount"], # Amount in GTQ
exchange_rate=distribution["exchange_rate"],
transaction_type="flow",
lamassu_transaction_id=transaction_id,
@ -888,12 +887,9 @@ class LamassuTransactionProcessor:
return False
# Create descriptive memo with DCA metrics
fiat_amount_centavos = distribution.get("fiat_amount", 0)
fiat_amount_gtq = distribution.get("fiat_amount", 0.0)
exchange_rate = distribution.get("exchange_rate", 0)
# Convert centavos to GTQ for display
fiat_amount_gtq = fiat_amount_centavos / 100
# Calculate cost basis (fiat per BTC)
if exchange_rate > 0:
# exchange_rate is sats per fiat unit, so convert to fiat per BTC
@ -1011,7 +1007,7 @@ class LamassuTransactionProcessor:
# Calculate commission metrics
if commission_percentage > 0:
effective_commission = commission_percentage * (100 - discount) / 100
base_crypto_atoms = int(crypto_atoms / (1 + effective_commission))
base_crypto_atoms = round(crypto_atoms / (1 + effective_commission))
commission_amount_sats = crypto_atoms - base_crypto_atoms
else:
effective_commission = 0.0
@ -1021,10 +1017,10 @@ class LamassuTransactionProcessor:
# Calculate exchange rate
exchange_rate = base_crypto_atoms / fiat_amount if fiat_amount > 0 else 0
# Create transaction data (store fiat_amount in centavos for consistency)
# Create transaction data with GTQ amounts
transaction_data = CreateLamassuTransactionData(
lamassu_transaction_id=transaction["transaction_id"],
fiat_amount=int(fiat_amount * 100), # Convert GTQ to centavos
fiat_amount=round(fiat_amount, 2), # Store GTQ with 2 decimal places
crypto_amount=crypto_atoms,
commission_percentage=commission_percentage,
discount=discount,
@ -1137,7 +1133,7 @@ class LamassuTransactionProcessor:
if commission_percentage and commission_percentage > 0:
effective_commission = commission_percentage * (100 - discount) / 100
base_crypto_atoms = int(crypto_atoms / (1 + effective_commission))
base_crypto_atoms = round(crypto_atoms / (1 + effective_commission))
commission_amount_sats = crypto_atoms - base_crypto_atoms
else:
commission_amount_sats = 0

View file

@ -38,23 +38,14 @@ from .models import (
DcaClient,
UpdateDcaClientData,
CreateDepositData,
CreateDepositAPI,
DepositAPI,
DcaDeposit,
UpdateDepositStatusData,
ClientBalanceSummary,
ClientBalanceSummaryAPI,
CreateLamassuConfigData,
LamassuConfig,
UpdateLamassuConfigData,
StoredLamassuTransaction,
)
from .currency_utils import (
gtq_to_centavos,
centavos_to_gtq,
deposit_db_to_api,
balance_summary_db_to_api,
)
satmachineadmin_api_router = APIRouter()
@ -96,7 +87,7 @@ async def api_get_dca_client(
async def api_get_client_balance(
client_id: str,
wallet: WalletTypeInfo = Depends(check_super_user),
) -> ClientBalanceSummaryAPI:
) -> ClientBalanceSummary:
"""Get client balance summary"""
client = await get_dca_client(client_id)
if not client:
@ -104,8 +95,7 @@ async def api_get_client_balance(
status_code=HTTPStatus.NOT_FOUND, detail="DCA client not found."
)
balance_db = await get_client_balance_summary(client_id)
return ClientBalanceSummaryAPI(**balance_summary_db_to_api(balance_db))
return await get_client_balance_summary(client_id)
# DCA Deposit Endpoints
@ -114,31 +104,30 @@ async def api_get_client_balance(
@satmachineadmin_api_router.get("/api/v1/dca/deposits")
async def api_get_deposits(
wallet: WalletTypeInfo = Depends(check_super_user),
) -> list[DepositAPI]:
) -> list[DcaDeposit]:
"""Get all deposits"""
deposits_db = await get_all_deposits()
return [DepositAPI(**deposit_db_to_api(deposit)) for deposit in deposits_db]
return await get_all_deposits()
@satmachineadmin_api_router.get("/api/v1/dca/deposits/{deposit_id}")
async def api_get_deposit(
deposit_id: str,
wallet: WalletTypeInfo = Depends(check_super_user),
) -> DepositAPI:
) -> DcaDeposit:
"""Get a specific deposit"""
deposit_db = await get_deposit(deposit_id)
if not deposit_db:
deposit = await get_deposit(deposit_id)
if not deposit:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="Deposit not found."
)
return DepositAPI(**deposit_db_to_api(deposit_db))
return deposit
@satmachineadmin_api_router.post("/api/v1/dca/deposits", status_code=HTTPStatus.CREATED)
async def api_create_deposit(
data: CreateDepositAPI,
data: CreateDepositData,
user: User = Depends(check_super_user),
) -> DepositAPI:
) -> DcaDeposit:
"""Create a new deposit"""
# Verify client exists
client = await get_dca_client(data.client_id)
@ -147,16 +136,7 @@ async def api_create_deposit(
status_code=HTTPStatus.NOT_FOUND, detail="DCA client not found."
)
# Convert GTQ to centavos at API boundary
deposit_data = CreateDepositData(
client_id=data.client_id,
amount=gtq_to_centavos(data.amount_gtq),
currency=data.currency,
notes=data.notes
)
deposit_db = await create_deposit(deposit_data)
return DepositAPI(**deposit_db_to_api(deposit_db))
return await create_deposit(data)
@satmachineadmin_api_router.put("/api/v1/dca/deposits/{deposit_id}/status")
@ -164,7 +144,7 @@ async def api_update_deposit_status(
deposit_id: str,
data: UpdateDepositStatusData,
user: User = Depends(check_super_user),
) -> DepositAPI:
) -> DcaDeposit:
"""Update deposit status (e.g., confirm deposit)"""
deposit = await get_deposit(deposit_id)
if not deposit:
@ -172,13 +152,13 @@ async def api_update_deposit_status(
status_code=HTTPStatus.NOT_FOUND, detail="Deposit not found."
)
updated_deposit_db = await update_deposit_status(deposit_id, data)
if not updated_deposit_db:
updated_deposit = await update_deposit_status(deposit_id, data)
if not updated_deposit:
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail="Failed to update deposit.",
)
return DepositAPI(**deposit_db_to_api(updated_deposit_db))
return updated_deposit
# Transaction Polling Endpoints