diff --git a/backend/src/main/kotlin/com/wrbug/polymarketbot/service/copytrading/orders/OrderSigningService.kt b/backend/src/main/kotlin/com/wrbug/polymarketbot/service/copytrading/orders/OrderSigningService.kt index 90a0dde..9705264 100644 --- a/backend/src/main/kotlin/com/wrbug/polymarketbot/service/copytrading/orders/OrderSigningService.kt +++ b/backend/src/main/kotlin/com/wrbug/polymarketbot/service/copytrading/orders/OrderSigningService.kt @@ -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) // 转换为 wei(6 位小数) 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()) } diff --git a/backend/src/main/kotlin/com/wrbug/polymarketbot/service/copytrading/statistics/CopyOrderTrackingService.kt b/backend/src/main/kotlin/com/wrbug/polymarketbot/service/copytrading/statistics/CopyOrderTrackingService.kt index efd219c..fade4c3 100644 --- a/backend/src/main/kotlin/com/wrbug/polymarketbot/service/copytrading/statistics/CopyOrderTrackingService.kt +++ b/backend/src/main/kotlin/com/wrbug/polymarketbot/service/copytrading/statistics/CopyOrderTrackingService.kt @@ -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,