diff --git a/backend/services/identity-service/src/api/api.module.ts b/backend/services/identity-service/src/api/api.module.ts index ace347a2..1e8f92cc 100644 --- a/backend/services/identity-service/src/api/api.module.ts +++ b/backend/services/identity-service/src/api/api.module.ts @@ -2,11 +2,10 @@ import { Module } from '@nestjs/common'; import { UserAccountController } from './controllers/user-account.controller'; import { AuthController } from './controllers/auth.controller'; import { ReferralsController } from './controllers/referrals.controller'; -import { DepositController } from './controllers/deposit.controller'; import { ApplicationModule } from '@/application/application.module'; @Module({ imports: [ApplicationModule], - controllers: [UserAccountController, AuthController, ReferralsController, DepositController], + controllers: [UserAccountController, AuthController, ReferralsController], }) export class ApiModule {} diff --git a/backend/services/identity-service/src/api/controllers/deposit.controller.ts b/backend/services/identity-service/src/api/controllers/deposit.controller.ts deleted file mode 100644 index 81276b57..00000000 --- a/backend/services/identity-service/src/api/controllers/deposit.controller.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { Controller, Get, UseGuards, Request, Logger } from '@nestjs/common'; -import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth } from '@nestjs/swagger'; -import { JwtAuthGuard } from '@/shared/guards/jwt-auth.guard'; -import { DepositService } from '@/application/services/deposit.service'; - -/** - * 充值地址响应 DTO - */ -class DepositAddressResponseDto { - kavaAddress: string | null; - bscAddress: string | null; - isValid: boolean; - message?: string; -} - -/** - * USDT 余额响应 DTO - */ -class UsdtBalanceDto { - chainType: string; - address: string; - balance: string; - rawBalance: string; - decimals: number; -} - -class BalanceResponseDto { - kava: UsdtBalanceDto | null; - bsc: UsdtBalanceDto | null; -} - -/** - * 充值控制器 - * - * 提供充值地址获取和余额查询 API - */ -@ApiTags('Deposit') -@Controller('api/deposit') -export class DepositController { - private readonly logger = new Logger(DepositController.name); - - constructor(private readonly depositService: DepositService) {} - - /** - * 获取充值地址 - * - * 返回用户的 KAVA 和 BSC 充值地址 - * 会验证地址签名,确保地址未被篡改 - */ - @Get('addresses') - @UseGuards(JwtAuthGuard) - @ApiBearerAuth() - @ApiOperation({ summary: '获取充值地址' }) - @ApiResponse({ - status: 200, - description: '成功获取充值地址', - type: DepositAddressResponseDto, - }) - @ApiResponse({ status: 400, description: '获取失败' }) - @ApiResponse({ status: 401, description: '未授权' }) - async getDepositAddresses(@Request() req: any): Promise { - const userId = req.user.userId; - this.logger.log(`获取充值地址: userId=${userId}`); - - return this.depositService.getDepositAddresses(userId); - } - - /** - * 查询 USDT 余额 - * - * 实时查询 KAVA 和 BSC 链上的 USDT 余额 - */ - @Get('balances') - @UseGuards(JwtAuthGuard) - @ApiBearerAuth() - @ApiOperation({ summary: '查询 USDT 余额' }) - @ApiResponse({ - status: 200, - description: '成功获取余额', - type: BalanceResponseDto, - }) - @ApiResponse({ status: 400, description: '查询失败' }) - @ApiResponse({ status: 401, description: '未授权' }) - async getUsdtBalances(@Request() req: any): Promise { - const userId = req.user.userId; - this.logger.log(`查询 USDT 余额: userId=${userId}`); - - return this.depositService.getUsdtBalances(userId); - } -} diff --git a/backend/services/identity-service/src/application/application.module.ts b/backend/services/identity-service/src/application/application.module.ts index a42644dd..7918f6b0 100644 --- a/backend/services/identity-service/src/application/application.module.ts +++ b/backend/services/identity-service/src/application/application.module.ts @@ -1,7 +1,6 @@ import { Module } from '@nestjs/common'; import { UserApplicationService } from './services/user-application.service'; import { TokenService } from './services/token.service'; -import { DepositService } from './services/deposit.service'; import { AutoCreateAccountHandler } from './commands/auto-create-account/auto-create-account.handler'; import { RecoverByMnemonicHandler } from './commands/recover-by-mnemonic/recover-by-mnemonic.handler'; import { RecoverByPhoneHandler } from './commands/recover-by-phone/recover-by-phone.handler'; @@ -18,7 +17,6 @@ import { InfrastructureModule } from '@/infrastructure/infrastructure.module'; providers: [ UserApplicationService, TokenService, - DepositService, AutoCreateAccountHandler, RecoverByMnemonicHandler, RecoverByPhoneHandler, @@ -33,7 +31,6 @@ import { InfrastructureModule } from '@/infrastructure/infrastructure.module'; exports: [ UserApplicationService, TokenService, - DepositService, AutoCreateAccountHandler, RecoverByMnemonicHandler, RecoverByPhoneHandler, diff --git a/backend/services/identity-service/src/application/services/deposit.service.ts b/backend/services/identity-service/src/application/services/deposit.service.ts deleted file mode 100644 index b0c57009..00000000 --- a/backend/services/identity-service/src/application/services/deposit.service.ts +++ /dev/null @@ -1,194 +0,0 @@ -import { Injectable, Logger, BadRequestException } from '@nestjs/common'; -import { UserAccountRepositoryImpl } from '@/infrastructure/persistence/repositories/user-account.repository.impl'; -import { BlockchainQueryService, UsdtBalance } from '@/infrastructure/external/blockchain/blockchain-query.service'; -import { UserId, ChainType } from '@/domain/value-objects'; -import { WalletAddress } from '@/domain/entities/wallet-address.entity'; - -/** - * 充值地址响应 - */ -export interface DepositAddressResponse { - kavaAddress: string | null; - bscAddress: string | null; - isValid: boolean; - message?: string; -} - -/** - * 余额响应 - */ -export interface BalanceResponse { - kava: UsdtBalance | null; - bsc: UsdtBalance | null; -} - -/** - * 充值服务 - * - * 提供充值地址获取和余额查询功能 - */ -@Injectable() -export class DepositService { - private readonly logger = new Logger(DepositService.name); - - constructor( - private readonly userAccountRepository: UserAccountRepositoryImpl, - private readonly blockchainQueryService: BlockchainQueryService, - ) {} - - /** - * 获取用户的充值地址 - * - * 验证地址签名是否有效,防止使用被篡改的地址 - */ - async getDepositAddresses(userId: string): Promise { - this.logger.log(`获取充值地址: userId=${userId}`); - - const userAccount = await this.userAccountRepository.findById(UserId.create(userId)); - if (!userAccount) { - throw new BadRequestException('用户不存在'); - } - - const walletAddresses = userAccount.getAllWalletAddresses(); - if (!walletAddresses || walletAddresses.length === 0) { - return { - kavaAddress: null, - bscAddress: null, - isValid: false, - message: '充值账户异常:未找到钱包地址,请联系客服', - }; - } - - // 查找 KAVA 和 BSC 地址 - const kavaWallet = walletAddresses.find((w: WalletAddress) => w.chainType === ChainType.KAVA); - const bscWallet = walletAddresses.find((w: WalletAddress) => w.chainType === ChainType.BSC); - - // 验证地址签名 - const validationResults = await Promise.all([ - kavaWallet ? this.validateWalletAddress(kavaWallet) : Promise.resolve(true), - bscWallet ? this.validateWalletAddress(bscWallet) : Promise.resolve(true), - ]); - - const [kavaValid, bscValid] = validationResults; - - // 如果有任何一个地址验证失败,返回错误 - if (!kavaValid || !bscValid) { - this.logger.warn(`地址验证失败: userId=${userId}, kavaValid=${kavaValid}, bscValid=${bscValid}`); - return { - kavaAddress: null, - bscAddress: null, - isValid: false, - message: '充值账户异常:地址验证失败,请重试或联系客服', - }; - } - - // 检查地址状态 - if (kavaWallet && kavaWallet.status !== 'ACTIVE') { - this.logger.warn(`KAVA 地址状态异常: userId=${userId}, status=${kavaWallet.status}`); - return { - kavaAddress: null, - bscAddress: null, - isValid: false, - message: '充值账户异常:KAVA 地址已禁用,请联系客服', - }; - } - - if (bscWallet && bscWallet.status !== 'ACTIVE') { - this.logger.warn(`BSC 地址状态异常: userId=${userId}, status=${bscWallet.status}`); - return { - kavaAddress: null, - bscAddress: null, - isValid: false, - message: '充值账户异常:BSC 地址已禁用,请联系客服', - }; - } - - return { - kavaAddress: kavaWallet?.address || null, - bscAddress: bscWallet?.address || null, - isValid: true, - }; - } - - /** - * 查询用户的 USDT 余额 - */ - async getUsdtBalances(userId: string): Promise { - this.logger.log(`查询 USDT 余额: userId=${userId}`); - - // 先获取充值地址 - const depositAddresses = await this.getDepositAddresses(userId); - - if (!depositAddresses.isValid) { - throw new BadRequestException(depositAddresses.message || '获取充值地址失败'); - } - - const results: BalanceResponse = { - kava: null, - bsc: null, - }; - - // 查询 KAVA 余额 - if (depositAddresses.kavaAddress) { - try { - results.kava = await this.blockchainQueryService.getUsdtBalance( - 'KAVA', - depositAddresses.kavaAddress, - ); - } catch (error) { - this.logger.error(`查询 KAVA USDT 余额失败: ${error.message}`); - results.kava = { - chainType: 'KAVA', - address: depositAddresses.kavaAddress, - balance: '0', - rawBalance: '0', - decimals: 6, - }; - } - } - - // 查询 BSC 余额 - if (depositAddresses.bscAddress) { - try { - results.bsc = await this.blockchainQueryService.getUsdtBalance( - 'BSC', - depositAddresses.bscAddress, - ); - } catch (error) { - this.logger.error(`查询 BSC USDT 余额失败: ${error.message}`); - results.bsc = { - chainType: 'BSC', - address: depositAddresses.bscAddress, - balance: '0', - rawBalance: '0', - decimals: 18, - }; - } - } - - return results; - } - - /** - * 验证钱包地址签名 - */ - private async validateWalletAddress(wallet: any): Promise { - try { - // 如果没有签名数据 (旧版本创建的地址),暂时允许通过 - if (!wallet.publicKey || !wallet.mpcSignature?.r) { - this.logger.warn(`钱包地址无签名数据: chainType=${wallet.chainType}`); - return true; - } - - // 验证签名 - const isValid = await wallet.verifySignature(); - if (!isValid) { - this.logger.error(`钱包地址签名验证失败: chainType=${wallet.chainType}, address=${wallet.address}`); - } - return isValid; - } catch (error) { - this.logger.error(`验证钱包地址签名异常: ${error.message}`); - return false; - } - } -} diff --git a/backend/services/identity-service/src/infrastructure/external/blockchain/blockchain-query.service.ts b/backend/services/identity-service/src/infrastructure/external/blockchain/blockchain-query.service.ts deleted file mode 100644 index 0711a659..00000000 --- a/backend/services/identity-service/src/infrastructure/external/blockchain/blockchain-query.service.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { Injectable, Logger } from '@nestjs/common'; -import { HttpService } from '@nestjs/axios'; -import { ConfigService } from '@nestjs/config'; -import { firstValueFrom } from 'rxjs'; - -/** - * USDT 余额查询结果 - */ -export interface UsdtBalance { - chainType: string; - address: string; - balance: string; // 格式化后的余额 (带小数) - rawBalance: string; // 原始余额 (wei) - decimals: number; -} - -/** - * blockchain-service 余额响应 - */ -interface BlockchainBalanceResponse { - chainType: string; - address: string; - usdtBalance: string; - nativeBalance: string; - nativeSymbol: string; -} - -/** - * blockchain-service 多链余额响应 - */ -interface BlockchainMultiChainResponse { - address: string; - balances: BlockchainBalanceResponse[]; -} - -/** - * 区块链查询服务 - * - * 通过 HTTP 调用 blockchain-service 查询余额 - */ -@Injectable() -export class BlockchainQueryService { - private readonly logger = new Logger(BlockchainQueryService.name); - private readonly blockchainServiceUrl: string; - - // 链的 decimals 配置 - private readonly chainDecimals: Record = { - KAVA: 6, - BSC: 18, - }; - - constructor( - private readonly httpService: HttpService, - private readonly configService: ConfigService, - ) { - this.blockchainServiceUrl = this.configService.get( - 'BLOCKCHAIN_SERVICE_URL', - 'http://blockchain-service:3000', - ); - this.logger.log(`BlockchainQueryService initialized, URL: ${this.blockchainServiceUrl}`); - } - - /** - * 查询单个地址的 USDT 余额 - * - * @param chainType 链类型 (KAVA 或 BSC) - * @param address EVM 地址 - */ - async getUsdtBalance(chainType: string, address: string): Promise { - try { - this.logger.debug(`查询 ${chainType} USDT 余额: ${address}`); - - const response = await firstValueFrom( - this.httpService.get( - `${this.blockchainServiceUrl}/balance`, - { - params: { - chainType, - address, - }, - }, - ), - ); - - const data = response.data; - this.logger.debug(`${chainType} USDT 余额: ${data.usdtBalance}`); - - return { - chainType: data.chainType, - address: data.address, - balance: data.usdtBalance, - rawBalance: this.toRawBalance(data.usdtBalance, chainType), - decimals: this.chainDecimals[chainType] || 6, - }; - } catch (error) { - this.logger.error(`查询 ${chainType} USDT 余额失败: ${error.message}`); - throw new Error(`查询余额失败: ${error.message}`); - } - } - - /** - * 批量查询多个地址的 USDT 余额 - * - * @param addresses 地址列表 { chainType, address }[] - */ - async getMultipleUsdtBalances( - addresses: Array<{ chainType: string; address: string }>, - ): Promise { - const results = await Promise.allSettled( - addresses.map(({ chainType, address }) => this.getUsdtBalance(chainType, address)), - ); - - return results.map((result, index) => { - if (result.status === 'fulfilled') { - return result.value; - } - // 失败时返回零余额 - this.logger.warn(`查询余额失败 [${addresses[index].chainType}:${addresses[index].address}]: ${result.reason}`); - return { - chainType: addresses[index].chainType, - address: addresses[index].address, - balance: '0', - rawBalance: '0', - decimals: this.chainDecimals[addresses[index].chainType] || 6, - }; - }); - } - - /** - * 查询原生代币余额 (KAVA / BNB) - */ - async getNativeBalance(chainType: string, address: string): Promise { - try { - const response = await firstValueFrom( - this.httpService.get( - `${this.blockchainServiceUrl}/balance`, - { - params: { - chainType, - address, - }, - }, - ), - ); - - return response.data.nativeBalance; - } catch (error) { - this.logger.error(`查询 ${chainType} 原生代币余额失败: ${error.message}`); - throw new Error(`查询余额失败: ${error.message}`); - } - } - - /** - * 将格式化余额转换为原始余额 (wei) - */ - private toRawBalance(formattedBalance: string, chainType: string): string { - try { - const decimals = this.chainDecimals[chainType] || 6; - const [intPart, decPart = ''] = formattedBalance.split('.'); - const paddedDecPart = decPart.padEnd(decimals, '0').slice(0, decimals); - const rawValue = BigInt(intPart + paddedDecPart); - return rawValue.toString(); - } catch { - return '0'; - } - } -} diff --git a/backend/services/identity-service/src/infrastructure/infrastructure.module.ts b/backend/services/identity-service/src/infrastructure/infrastructure.module.ts index fd9fc3de..496ac6f4 100644 --- a/backend/services/identity-service/src/infrastructure/infrastructure.module.ts +++ b/backend/services/identity-service/src/infrastructure/infrastructure.module.ts @@ -1,6 +1,5 @@ import { Module, Global } from '@nestjs/common'; import { HttpModule } from '@nestjs/axios'; -import { ConfigModule } from '@nestjs/config'; import { PrismaService } from './persistence/prisma/prisma.service'; import { UserAccountRepositoryImpl } from './persistence/repositories/user-account.repository.impl'; import { MpcKeyShareRepositoryImpl } from './persistence/repositories/mpc-key-share.repository.impl'; @@ -10,7 +9,6 @@ import { EventPublisherService } from './kafka/event-publisher.service'; import { MpcEventConsumerService } from './kafka/mpc-event-consumer.service'; import { SmsService } from './external/sms/sms.service'; import { WalletGeneratorServiceImpl } from './external/blockchain/wallet-generator.service.impl'; -import { BlockchainQueryService } from './external/blockchain/blockchain-query.service'; import { MpcClientService, MpcWalletService } from './external/mpc'; import { MPC_KEY_SHARE_REPOSITORY } from '@/domain/repositories/mpc-key-share.repository.interface'; import { WalletGeneratorService } from '@/domain/services/wallet-generator.service'; @@ -18,7 +16,6 @@ import { WalletGeneratorService } from '@/domain/services/wallet-generator.servi @Global() @Module({ imports: [ - ConfigModule, HttpModule.register({ timeout: 300000, maxRedirects: 5, @@ -42,7 +39,6 @@ import { WalletGeneratorService } from '@/domain/services/wallet-generator.servi provide: WalletGeneratorService, useExisting: WalletGeneratorServiceImpl, }, - BlockchainQueryService, MpcClientService, MpcWalletService, ], @@ -60,7 +56,6 @@ import { WalletGeneratorService } from '@/domain/services/wallet-generator.servi SmsService, WalletGeneratorServiceImpl, WalletGeneratorService, - BlockchainQueryService, MpcClientService, MpcWalletService, ],