From 0f3d03d832a642c3ab62e10dcc57a01252812018 Mon Sep 17 00:00:00 2001 From: hailin Date: Mon, 2 Feb 2026 09:13:40 -0800 Subject: [PATCH] =?UTF-8?q?fix(wallet-service):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=8F=90=E7=8E=B0=E5=A4=B1=E8=B4=A5=E6=97=B6=E4=B8=8D=E5=86=99?= =?UTF-8?q?=20UNFREEZE=20ledger=20=E6=B5=81=E6=B0=B4=E7=9A=84=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题描述: withdrawal-status.handler.ts 的 executeWithdrawalFailed() 方法在处理 提现失败事件时,虽然正确地将冻结余额退回到可用余额(usdt_frozen → usdt_available), 但没有在 wallet_ledger_entries 表中写入 UNFREEZE 类型的流水记录,导致审计缺口。 对比 system-withdrawal-application.service.ts 中的同名方法 handleWithdrawalFailed(), 后者在退回余额时正确地写入了 UNFREEZE ledger entry。两者逻辑应保持一致。 影响范围: 所有通过 blockchain-service Kafka 事件触发的提现失败场景(包括链上提现和内部转账), 余额变动不会被记录到流水表中,无法审计追踪。 修复内容: 在 wallet_accounts 余额更新成功后,新增 tx.ledgerEntry.create() 调用, 写入 UNFREEZE 类型的流水记录,包含: - amount: 实际退回金额(newAvailable - currentAvailable,兼容冻结不足的边缘情况) - memo: "提现失败退款: {error}" - payloadJson: toAddress, chainType, error 便于排查 Co-Authored-By: Claude Opus 4.5 --- .../withdrawal-status.handler.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/backend/services/wallet-service/src/application/event-handlers/withdrawal-status.handler.ts b/backend/services/wallet-service/src/application/event-handlers/withdrawal-status.handler.ts index ab5f529e..f1964b0c 100644 --- a/backend/services/wallet-service/src/application/event-handlers/withdrawal-status.handler.ts +++ b/backend/services/wallet-service/src/application/event-handlers/withdrawal-status.handler.ts @@ -464,6 +464,25 @@ export class WithdrawalStatusHandler implements OnModuleInit { } this.logger.log(`[FAILED] Refunded ${totalAmount.toString()} USDT (amount + fee) to account ${orderRecord.accountSequence} (version: ${currentVersion} -> ${currentVersion + 1})`); + + // 记录 UNFREEZE 流水(修复:之前缺失导致审计缺口) + await tx.ledgerEntry.create({ + data: { + accountSequence: orderRecord.accountSequence, + userId: orderRecord.userId, + entryType: LedgerEntryType.UNFREEZE, + amount: newAvailable.minus(currentAvailable), + assetType: 'USDT', + balanceAfter: newAvailable, + refOrderId: orderRecord.orderNo, + memo: `提现失败退款: ${payload.error}`, + payloadJson: { + toAddress: orderRecord.toAddress, + chainType: orderRecord.chainType, + error: payload.error, + }, + }, + }); } else { this.logger.error(`[FAILED] Wallet not found for accountSequence: ${orderRecord.accountSequence}, userId: ${orderRecord.userId}`); }