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()) return OrderAmounts(makerAmount.toString(), takerAmount.toString())
} else { } else {
// SELL: makerAmount = size (shares), takerAmount = price * size (USDC) // SELL: makerAmount = size (shares), takerAmount = price * size (USDC)
// makerAmount 是 shares 数量,最多 4 位小数 // 根据 Polymarket API 要求:
// takerAmount 是 USDC 金额,需要使用原始价格计算(与SDK保持一致) // - makerAmount (shares) 最多 2 位小数
// - takerAmount (USDC) 最多 4 位小数
val rawMakerAmt = roundDown(sizeDecimal, roundConfig.size) val rawMakerAmt = roundDown(sizeDecimal, roundConfig.size)
// takerAmount = price * size,使用原始价格计算(不使用舍入后的价格) // takerAmount = price * size,使用原始价格计算(不使用舍入后的价格)
@@ -109,16 +110,15 @@ class OrderSigningService {
// 例如:0.9596 * 16.09 = 15.439964,而不是 0.96 * 16.09 = 15.4464 // 例如:0.9596 * 16.09 = 15.439964,而不是 0.96 * 16.09 = 15.4464
val rawTakerAmt = rawMakerAmt.multiply(priceDecimal) val rawTakerAmt = rawMakerAmt.multiply(priceDecimal)
// 确保 makerAmount 精度(shares,最多 4 位小数) // 确保 makerAmount 精度(shares,最多 2 位小数,符合 API 要求
val finalMakerAmt = roundDown(rawMakerAmt, TAKER_AMOUNT_DECIMALS) val finalMakerAmt = roundDown(rawMakerAmt, MAKER_AMOUNT_DECIMALS)
// takerAmount 不进行舍入,直接使用精确计算结果转换为 wei // 确保 takerAmount 精度(USDC,最多 4 位小数,符合 API 要求)
// parseUnits 会将 BigDecimal 转换为 wei(6 位小数),自动处理精度 val finalTakerAmt = roundDown(rawTakerAmt, TAKER_AMOUNT_DECIMALS)
// 使用原始价格计算可以确保与SDK的结果一致
// 转换为 wei6 位小数) // 转换为 wei6 位小数)
val makerAmount = parseUnits(finalMakerAmt, COLLATERAL_TOKEN_DECIMALS) 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()) return OrderAmounts(makerAmount.toString(), takerAmount.toString())
} }
@@ -848,9 +848,24 @@ open class CopyOrderTrackingService(
return 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) val decryptedPrivateKey = decryptPrivateKey(account)
// 8. 创建并签名卖出订单
// 9. 创建并签名卖出订单
val signedOrder = try { val signedOrder = try {
orderSigningService.createAndSignOrder( orderSigningService.createAndSignOrder(
privateKey = decryptedPrivateKey, privateKey = decryptedPrivateKey,
@@ -869,7 +884,7 @@ open class CopyOrderTrackingService(
return return
} }
// 9. 构建订单请求 // 10. 构建订单请求
// 跟单订单使用 FAK (Fill-And-Kill),允许部分成交,未成交部分立即取消 // 跟单订单使用 FAK (Fill-And-Kill),允许部分成交,未成交部分立即取消
// 这样可以快速响应 Leader 的交易,避免订单长期挂单导致价格不匹配 // 这样可以快速响应 Leader 的交易,避免订单长期挂单导致价格不匹配
val orderRequest = NewOrderRequest( val orderRequest = NewOrderRequest(
@@ -879,15 +894,15 @@ open class CopyOrderTrackingService(
deferExec = false deferExec = false
) )
// 10. 创建带认证的CLOB API客户端 // 11. 创建带认证的CLOB API客户端(使用解密后的凭证)
val clobApi = retrofitFactory.createClobApi( val clobApi = retrofitFactory.createClobApi(
account.apiKey, account.apiKey,
account.apiSecret, apiSecret,
account.apiPassphrase, apiPassphrase,
account.walletAddress account.walletAddress
) )
// 11. 调用API创建卖出订单(带重试机制,重试时会重新生成salt并重新签名) // 12. 调用API创建卖出订单(带重试机制,重试时会重新生成salt并重新签名)
val createOrderResult = createOrderWithRetry( val createOrderResult = createOrderWithRetry(
clobApi = clobApi, clobApi = clobApi,