chore(wallet-service): 移除已执行的OTP修复脚本

This commit is contained in:
hailin 2025-12-25 20:55:08 -08:00
parent c2ff11bd6d
commit dbeef0a80b
2 changed files with 1 additions and 188 deletions

View File

@ -20,8 +20,6 @@ import {
import { RedisModule } from './redis';
import { KafkaModule } from './kafka';
import { IdentityModule } from './external/identity';
// OTP: One-Time fix for D25122600004 -> D25122600006 transfer (remove after fix)
import { TransferFixService } from './otp/transfer-fix.service';
const repositories = [
{
@ -54,7 +52,7 @@ const repositories = [
@Global()
@Module({
imports: [RedisModule, KafkaModule, IdentityModule],
providers: [PrismaService, ...repositories, TransferFixService], // OTP: remove TransferFixService after fix
providers: [PrismaService, ...repositories],
exports: [PrismaService, RedisModule, KafkaModule, IdentityModule, FeeConfigRepositoryImpl, ...repositories],
})
export class InfrastructureModule {}

View File

@ -1,185 +0,0 @@
/**
* One-Time-Fix: 修复 D25122600004 -> D25122600006
*
* 2 USDT ()
*
*
* CONFIRMED
* infrastructure.module.ts
*/
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { PrismaService } from '@/infrastructure/persistence/prisma/prisma.service';
import { LedgerEntryType, WithdrawalStatus } from '@/domain/value-objects';
import Decimal from 'decimal.js';
@Injectable()
export class TransferFixService implements OnModuleInit {
private readonly logger = new Logger(TransferFixService.name);
// 需要修复的订单号
private readonly ORDER_NO = 'WD1766719397843H90GUW';
private readonly SENDER_ACCOUNT = 'D25122600004';
private readonly RECEIVER_ACCOUNT = 'D25122600006';
private readonly MISSING_FEE = new Decimal('2'); // 缺失的手续费
constructor(private readonly prisma: PrismaService) {}
async onModuleInit() {
// 延迟 5 秒执行,确保所有服务都已启动
setTimeout(() => this.executeFixOnce(), 5000);
}
private async executeFixOnce(): Promise<void> {
this.logger.log('========================================');
this.logger.log('[OTP-FIX] Starting one-time transfer fix');
this.logger.log(`[OTP-FIX] Order: ${this.ORDER_NO}`);
this.logger.log(`[OTP-FIX] From: ${this.SENDER_ACCOUNT} -> To: ${this.RECEIVER_ACCOUNT}`);
this.logger.log('========================================');
try {
// 检查订单状态
const order = await this.prisma.withdrawalOrder.findUnique({
where: { orderNo: this.ORDER_NO },
});
if (!order) {
this.logger.log('[OTP-FIX] Order not found, skipping (may be wrong environment)');
return;
}
// 如果已经确认,说明已修复过(幂等性)
if (order.status === WithdrawalStatus.CONFIRMED) {
this.logger.log('[OTP-FIX] Order already CONFIRMED, skipping');
return;
}
if (order.status !== WithdrawalStatus.FROZEN) {
this.logger.warn(`[OTP-FIX] Unexpected order status: ${order.status}, skipping`);
return;
}
// 执行修复
await this.prisma.$transaction(async (tx) => {
// 1. 获取发送方钱包
const senderWallet = await tx.walletAccount.findUnique({
where: { accountSequence: this.SENDER_ACCOUNT },
});
if (!senderWallet) {
throw new Error(`Sender wallet not found: ${this.SENDER_ACCOUNT}`);
}
// 2. 获取接收方钱包
const receiverWallet = await tx.walletAccount.findUnique({
where: { accountSequence: this.RECEIVER_ACCOUNT },
});
if (!receiverWallet) {
throw new Error(`Receiver wallet not found: ${this.RECEIVER_ACCOUNT}`);
}
const amount = new Decimal(order.amount.toString());
const fee = new Decimal(order.fee.toString());
const totalAmount = amount.add(fee);
this.logger.log(`[OTP-FIX] Amount: ${amount}, Fee: ${fee}, Total: ${totalAmount}`);
// 3. 修复发送方冻结余额 (加上缺失的手续费) 并同时扣除
const senderCurrentFrozen = new Decimal(senderWallet.usdtFrozen.toString());
// 加上缺失的手续费后再扣除全部
const senderNewFrozen = senderCurrentFrozen.add(this.MISSING_FEE).minus(totalAmount);
this.logger.log(`[OTP-FIX] Sender frozen: ${senderCurrentFrozen} + ${this.MISSING_FEE} - ${totalAmount} = ${senderNewFrozen}`);
await tx.walletAccount.update({
where: { id: senderWallet.id },
data: {
usdtFrozen: senderNewFrozen,
version: senderWallet.version + 1,
updatedAt: new Date(),
},
});
// 4. 增加接收方余额
const receiverCurrentAvailable = new Decimal(receiverWallet.usdtAvailable.toString());
const receiverNewAvailable = receiverCurrentAvailable.add(amount);
this.logger.log(`[OTP-FIX] Receiver available: ${receiverCurrentAvailable} + ${amount} = ${receiverNewAvailable}`);
await tx.walletAccount.update({
where: { id: receiverWallet.id },
data: {
usdtAvailable: receiverNewAvailable,
version: receiverWallet.version + 1,
updatedAt: new Date(),
},
});
// 5. 创建发送方流水 (TRANSFER_OUT)
await tx.ledgerEntry.create({
data: {
accountSequence: order.accountSequence,
userId: order.userId,
entryType: LedgerEntryType.TRANSFER_OUT,
amount: amount.negated(),
assetType: 'USDT',
balanceAfter: senderWallet.usdtAvailable,
refOrderId: order.orderNo,
refTxHash: 'OTP-FIX-INTERNAL',
memo: `转账至 ${order.toAccountSequence} (OTP修复)`,
payloadJson: {
toAccountSequence: order.toAccountSequence,
toUserId: order.toUserId?.toString(),
fee: order.fee.toString(),
fixNote: 'One-time fix for concurrent modification issue',
},
},
});
// 6. 创建接收方流水 (TRANSFER_IN)
await tx.ledgerEntry.create({
data: {
accountSequence: order.toAccountSequence!,
userId: order.toUserId!,
entryType: LedgerEntryType.TRANSFER_IN,
amount: amount,
assetType: 'USDT',
balanceAfter: receiverNewAvailable,
refOrderId: order.orderNo,
refTxHash: 'OTP-FIX-INTERNAL',
memo: `来自 ${order.accountSequence} 的转账 (OTP修复)`,
payloadJson: {
fromAccountSequence: order.accountSequence,
fromUserId: order.userId.toString(),
fixNote: 'One-time fix for concurrent modification issue',
},
},
});
// 7. 更新订单状态为 CONFIRMED
await tx.withdrawalOrder.update({
where: { id: order.id },
data: {
status: WithdrawalStatus.CONFIRMED,
txHash: 'OTP-FIX-INTERNAL',
broadcastedAt: new Date(),
confirmedAt: new Date(),
},
});
this.logger.log('[OTP-FIX] Transaction completed successfully');
});
this.logger.log('========================================');
this.logger.log('[OTP-FIX] Transfer fix completed!');
this.logger.log(`[OTP-FIX] ${this.SENDER_ACCOUNT} -> ${this.RECEIVER_ACCOUNT}: ${this.prisma}`);
this.logger.log('[OTP-FIX] Order status: CONFIRMED');
this.logger.log('[OTP-FIX] Please remove this file after deployment');
this.logger.log('========================================');
} catch (error) {
this.logger.error('[OTP-FIX] Failed to execute fix', error);
}
}
}