rwadurian/backend/services/blockchain-service/src/api/controllers/deposit.controller.ts

103 lines
3.0 KiB
TypeScript

/**
* Deposit Controller
*
* Provides deposit-related endpoints for the mobile app.
* Queries on-chain USDT balances for user's monitored addresses.
*/
import { Controller, Get, Logger, Inject, UseGuards, Req } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger';
import { Request } from 'express';
import { BalanceQueryService } from '@/application/services/balance-query.service';
import { ChainTypeEnum } from '@/domain/enums';
import {
IMonitoredAddressRepository,
MONITORED_ADDRESS_REPOSITORY,
} from '@/domain/repositories/monitored-address.repository.interface';
import { JwtAuthGuard } from '@/shared/guards/jwt-auth.guard';
interface JwtPayload {
userId: string;
accountSequence: string;
deviceId: string;
}
interface UsdtBalanceDto {
chainType: string;
address: string;
balance: string;
rawBalance: string;
decimals: number;
}
interface DepositBalancesResponseDto {
kava: UsdtBalanceDto | null;
bsc: UsdtBalanceDto | null;
}
@ApiTags('Deposit')
@Controller('deposit')
export class DepositController {
private readonly logger = new Logger(DepositController.name);
constructor(
private readonly balanceService: BalanceQueryService,
@Inject(MONITORED_ADDRESS_REPOSITORY)
private readonly monitoredAddressRepo: IMonitoredAddressRepository,
) {}
@Get('balances')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth()
@ApiOperation({ summary: '查询用户 USDT 余额' })
@ApiResponse({ status: 200, description: '余额信息' })
async getBalances(@Req() req: Request): Promise<DepositBalancesResponseDto> {
const user = (req as Request & { user: JwtPayload }).user;
const userId = BigInt(user.userId);
this.logger.log(`Querying deposit balances for user ${userId}`);
// Get user's monitored addresses
const addresses = await this.monitoredAddressRepo.findByUserId(userId);
const response: DepositBalancesResponseDto = {
kava: null,
bsc: null,
};
// Query balance for each chain
for (const addr of addresses) {
try {
const chainType = addr.chainType;
const addressStr = addr.address.toString();
const chainTypeStr = chainType.toString();
const balance = await this.balanceService.getBalance(chainType, addressStr);
const balanceDto: UsdtBalanceDto = {
chainType: chainTypeStr,
address: addressStr,
balance: balance.usdtBalance,
rawBalance: balance.usdtRawBalance,
decimals: balance.usdtDecimals,
};
if (chainTypeStr === ChainTypeEnum.KAVA) {
response.kava = balanceDto;
} else if (chainTypeStr === ChainTypeEnum.BSC) {
response.bsc = balanceDto;
}
} catch (error) {
this.logger.error(`Error querying balance for ${addr.chainType}:${addr.address}`, error);
}
}
this.logger.log(
`Balance query complete for user ${userId}: ` +
`KAVA=${response.kava?.balance || '0'}, BSC=${response.bsc?.balance || '0'}`,
);
return response;
}
}