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}`);
|
this.logger.log(`[BOT] Seller Kava address: ${kavaAddress}`);
|
||||||
|
|
||||||
// 2. 计算 dUSDT 支付金额(积分值 = dUSDT,1:1 兑换)
|
// 2. 先扣减卖家积分值余额(可逆的DB操作,放在不可逆的链上转账之前)
|
||||||
const paymentAmount = order.totalAmount;
|
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
|
// 3. 调用 mining-blockchain-service 转账 dUSDT(不可逆)
|
||||||
const transferResult = await this.blockchainClient.transferDusdt(kavaAddress, paymentAmount);
|
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) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,9 +76,6 @@ export class C2cBotService {
|
||||||
paymentTxHash: transferResult.txHash!,
|
paymentTxHash: transferResult.txHash!,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 5. 扣减卖家的积分值余额
|
|
||||||
await this.deductSellerBalance(order.makerAccountSequence, order.totalAmount);
|
|
||||||
|
|
||||||
this.logger.log(`[BOT] Order ${order.orderNo} completed successfully`);
|
this.logger.log(`[BOT] Order ${order.orderNo} completed successfully`);
|
||||||
return true;
|
return true;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
|
@ -96,7 +102,6 @@ export class C2cBotService {
|
||||||
throw new Error(`Insufficient cash balance for ${accountSequence}`);
|
throw new Error(`Insufficient cash balance for ${accountSequence}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 扣减余额
|
|
||||||
await this.tradingAccountRepository.updateCashBalance(
|
await this.tradingAccountRepository.updateCashBalance(
|
||||||
accountSequence,
|
accountSequence,
|
||||||
amountDecimal.negated().toString(),
|
amountDecimal.negated().toString(),
|
||||||
|
|
@ -105,6 +110,22 @@ export class C2cBotService {
|
||||||
this.logger.log(`[BOT] Deducted ${amount} from ${accountSequence}'s cash balance`);
|
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 服务是否可用
|
* 检查 Bot 服务是否可用
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue