fix(wallet-service): 修复提现失败时不写 UNFREEZE ledger 流水的 bug

问题描述:
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 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-02-02 09:13:40 -08:00
parent 758babfdf8
commit 0f3d03d832
1 changed files with 19 additions and 0 deletions

View File

@ -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}`);
}