fix(c2c-bot): 调整purchaseOrder操作顺序,先扣余额再链上转账
问题:原流程先执行不可逆的链上dUSDT转账,再扣减卖家DB余额。 若转账成功但扣减失败(余额不足、DB异常),会导致: - dUSDT已转出(链上不可回退) - 订单仍为PENDING(可能被重复处理) - 卖家余额未扣减 修复: 1. 将deductSellerBalance移至transferDusdt之前(可逆操作先行) 2. 链上转账失败时调用restoreSellerBalance回补余额 3. 新增restoreSellerBalance方法,失败时记录CRITICAL级别日志 修改后流程:扣余额(可逆) → 链上转账(不可逆) → 更新订单状态(DB) 任何步骤失败都不会导致资金损失。 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
251e37f772
commit
c802519ec2
|
|
@ -47,15 +47,24 @@ export class C2cBotService {
|
|||
}
|
||||
this.logger.log(`[BOT] Seller Kava address: ${kavaAddress}`);
|
||||
|
||||
// 2. 计算 dUSDT 支付金额(积分值 = dUSDT,1:1 兑换)
|
||||
// 2. 先扣减卖家积分值余额(可逆的DB操作,放在不可逆的链上转账之前)
|
||||
const paymentAmount = order.totalAmount;
|
||||
this.logger.log(`[BOT] Payment amount: ${paymentAmount} dUSDT`);
|
||||
await this.deductSellerBalance(order.makerAccountSequence, paymentAmount);
|
||||
this.logger.log(`[BOT] Deducted seller balance, proceeding with on-chain transfer`);
|
||||
|
||||
// 3. 调用 mining-blockchain-service 转账 dUSDT
|
||||
const transferResult = await this.blockchainClient.transferDusdt(kavaAddress, paymentAmount);
|
||||
// 3. 调用 mining-blockchain-service 转账 dUSDT(不可逆)
|
||||
let transferResult;
|
||||
try {
|
||||
transferResult = await this.blockchainClient.transferDusdt(kavaAddress, paymentAmount);
|
||||
} catch (error: any) {
|
||||
this.logger.error(`[BOT] Transfer exception: ${error.message}, restoring seller balance`);
|
||||
await this.restoreSellerBalance(order.makerAccountSequence, paymentAmount);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!transferResult.success) {
|
||||
this.logger.error(`[BOT] Transfer failed: ${transferResult.error}`);
|
||||
this.logger.error(`[BOT] Transfer failed: ${transferResult.error}, restoring seller balance`);
|
||||
await this.restoreSellerBalance(order.makerAccountSequence, paymentAmount);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -67,9 +76,6 @@ export class C2cBotService {
|
|||
paymentTxHash: transferResult.txHash!,
|
||||
});
|
||||
|
||||
// 5. 扣减卖家的积分值余额
|
||||
await this.deductSellerBalance(order.makerAccountSequence, order.totalAmount);
|
||||
|
||||
this.logger.log(`[BOT] Order ${order.orderNo} completed successfully`);
|
||||
return true;
|
||||
} catch (error: any) {
|
||||
|
|
@ -96,7 +102,6 @@ export class C2cBotService {
|
|||
throw new Error(`Insufficient cash balance for ${accountSequence}`);
|
||||
}
|
||||
|
||||
// 扣减余额
|
||||
await this.tradingAccountRepository.updateCashBalance(
|
||||
accountSequence,
|
||||
amountDecimal.negated().toString(),
|
||||
|
|
@ -105,6 +110,22 @@ export class C2cBotService {
|
|||
this.logger.log(`[BOT] Deducted ${amount} from ${accountSequence}'s cash balance`);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回补卖家的积分值余额(链上转账失败时的补偿操作)
|
||||
*/
|
||||
private async restoreSellerBalance(accountSequence: string, amount: string): Promise<void> {
|
||||
try {
|
||||
await this.tradingAccountRepository.updateCashBalance(
|
||||
accountSequence,
|
||||
amount, // 正数,加回余额
|
||||
);
|
||||
this.logger.log(`[BOT] Restored ${amount} to ${accountSequence}'s cash balance`);
|
||||
} catch (error: any) {
|
||||
// 回补失败是严重问题,必须告警
|
||||
this.logger.error(`[BOT] CRITICAL: Failed to restore ${amount} to ${accountSequence}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查 Bot 服务是否可用
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue