fix: 修复跟单卖出订单的 API 凭证解密和精度问题

- 修复 processSellTrade 中 API 凭证未解密的问题,与 processBuyTrade 保持一致
- 修复 SELL 订单的 makerAmount 和 takerAmount 精度问题:
  - makerAmount (shares) 最多 2 位小数(符合 API 要求)
  - takerAmount (USDC) 最多 4 位小数(符合 API 要求)
This commit is contained in:
WrBug
2025-12-26 01:50:03 +08:00
parent c4ac3a8fe0
commit d1f351108f
2 changed files with 30 additions and 15 deletions
@@ -100,8 +100,9 @@ class OrderSigningService {
return OrderAmounts(makerAmount.toString(), takerAmount.toString())
} else {
// SELL: makerAmount = size (shares), takerAmount = price * size (USDC)
// makerAmount 是 shares 数量,最多 4 位小数
// takerAmount 是 USDC 金额,需要使用原始价格计算(与SDK保持一致)
// 根据 Polymarket API 要求:
// - makerAmount (shares) 最多 2 位小数
// - takerAmount (USDC) 最多 4 位小数
val rawMakerAmt = roundDown(sizeDecimal, roundConfig.size)
// takerAmount = price * size,使用原始价格计算(不使用舍入后的价格)
@@ -109,16 +110,15 @@ class OrderSigningService {
// 例如:0.9596 * 16.09 = 15.439964,而不是 0.96 * 16.09 = 15.4464
val rawTakerAmt = rawMakerAmt.multiply(priceDecimal)
// 确保 makerAmount 精度(shares,最多 4 位小数)
val finalMakerAmt = roundDown(rawMakerAmt, TAKER_AMOUNT_DECIMALS)
// 确保 makerAmount 精度(shares,最多 2 位小数,符合 API 要求
val finalMakerAmt = roundDown(rawMakerAmt, MAKER_AMOUNT_DECIMALS)
// takerAmount 不进行舍入,直接使用精确计算结果转换为 wei
// parseUnits 会将 BigDecimal 转换为 wei(6 位小数),自动处理精度
// 使用原始价格计算可以确保与SDK的结果一致
// 确保 takerAmount 精度(USDC,最多 4 位小数,符合 API 要求)
val finalTakerAmt = roundDown(rawTakerAmt, TAKER_AMOUNT_DECIMALS)
// 转换为 wei6 位小数)
val makerAmount = parseUnits(finalMakerAmt, COLLATERAL_TOKEN_DECIMALS)
val takerAmount = parseUnits(rawTakerAmt, COLLATERAL_TOKEN_DECIMALS)
val takerAmount = parseUnits(finalTakerAmt, COLLATERAL_TOKEN_DECIMALS)
return OrderAmounts(makerAmount.toString(), takerAmount.toString())
}
@@ -848,9 +848,24 @@ open class CopyOrderTrackingService(
return
}
// 7. 解密私钥(在方法开始时解密一次,后续复用)
// 7. 解密 API 凭证
val apiSecret = try {
decryptApiSecret(account)
} catch (e: Exception) {
logger.warn("解密 API 凭证失败,跳过创建卖出订单: accountId=${account.id}, error=${e.message}")
return
}
val apiPassphrase = try {
decryptApiPassphrase(account)
} catch (e: Exception) {
logger.warn("解密 API 凭证失败,跳过创建卖出订单: accountId=${account.id}, error=${e.message}")
return
}
// 8. 解密私钥(在方法开始时解密一次,后续复用)
val decryptedPrivateKey = decryptPrivateKey(account)
// 8. 创建并签名卖出订单
// 9. 创建并签名卖出订单
val signedOrder = try {
orderSigningService.createAndSignOrder(
privateKey = decryptedPrivateKey,
@@ -869,7 +884,7 @@ open class CopyOrderTrackingService(
return
}
// 9. 构建订单请求
// 10. 构建订单请求
// 跟单订单使用 FAK (Fill-And-Kill),允许部分成交,未成交部分立即取消
// 这样可以快速响应 Leader 的交易,避免订单长期挂单导致价格不匹配
val orderRequest = NewOrderRequest(
@@ -879,15 +894,15 @@ open class CopyOrderTrackingService(
deferExec = false
)
// 10. 创建带认证的CLOB API客户端
// 11. 创建带认证的CLOB API客户端(使用解密后的凭证)
val clobApi = retrofitFactory.createClobApi(
account.apiKey,
account.apiSecret,
account.apiPassphrase,
apiSecret,
apiPassphrase,
account.walletAddress
)
// 11. 调用API创建卖出订单(带重试机制,重试时会重新生成salt并重新签名)
// 12. 调用API创建卖出订单(带重试机制,重试时会重新生成salt并重新签名)
val createOrderResult = createOrderWithRetry(
clobApi = clobApi,