fix: 修复 RPC 错误时误创建自动卖出记录的问题

- 当链上查询市场条件出现 RPC 错误(execution reverted)时,不再降级到其他数据源
- 抛出异常让调用方决定如何处理,避免在市场不存在或尚未创建时误判为已卖出
- 修改 getPriceFromChainCondition 返回 Pair<BigDecimal?, Boolean>,第二个值表示是否发生 RPC 错误
- 在 getCurrentMarketPrice 中检测到 RPC 错误时抛出异常,PositionCheckService 会捕获并跳过该市场的处理
This commit is contained in:
WrBug
2026-01-07 10:55:11 +08:00
parent f257457ad3
commit 3d603cac32
@@ -43,12 +43,20 @@ class MarketPriceService(
*/ */
suspend fun getCurrentMarketPrice(marketId: String, outcomeIndex: Int): BigDecimal { suspend fun getCurrentMarketPrice(marketId: String, outcomeIndex: Int): BigDecimal {
// 1. 优先从链上查询市场结算结果 // 1. 优先从链上查询市场结算结果
val chainPrice = getPriceFromChainCondition(marketId, outcomeIndex) val (chainPrice, hasRpcError) = getPriceFromChainCondition(marketId, outcomeIndex)
if (chainPrice != null) { if (chainPrice != null) {
// 截位到 4 位小数(向下截断,不四舍五入) // 截位到 4 位小数(向下截断,不四舍五入)
return chainPrice.setScale(4, java.math.RoundingMode.DOWN) return chainPrice.setScale(4, java.math.RoundingMode.DOWN)
} }
// 如果链上查询出现 RPC 错误(execution reverted),说明市场可能不存在或尚未创建
// 在这种情况下,不应该继续处理,应该抛出异常,让调用方决定如何处理
if (hasRpcError) {
val errorMsg = "链上查询市场条件出现 RPC 错误(execution reverted),市场可能不存在或尚未创建: marketId=$marketId, outcomeIndex=$outcomeIndex"
logger.warn(errorMsg)
throw IllegalStateException(errorMsg)
}
// 2. 从 CLOB API 查询订单簿价格(最准确,优先使用) // 2. 从 CLOB API 查询订单簿价格(最准确,优先使用)
val orderbookPrice = getPriceFromClobOrderbook(marketId, outcomeIndex) val orderbookPrice = getPriceFromClobOrderbook(marketId, outcomeIndex)
if (orderbookPrice != null) { if (orderbookPrice != null) {
@@ -75,8 +83,10 @@ class MarketPriceService(
* - payout > 0(赢了)→ 返回 1.0 * - payout > 0(赢了)→ 返回 1.0
* - payout == 0(输了)→ 返回 0.0 * - payout == 0(输了)→ 返回 0.0
* 如果市场未结算或查询失败,返回 null * 如果市场未结算或查询失败,返回 null
*
* @return Pair<BigDecimal?, Boolean> 第一个值是价格(如果已结算),第二个值表示是否发生了 RPC 错误(execution reverted
*/ */
private suspend fun getPriceFromChainCondition(marketId: String, outcomeIndex: Int): BigDecimal? { private suspend fun getPriceFromChainCondition(marketId: String, outcomeIndex: Int): Pair<BigDecimal?, Boolean> {
return try { return try {
val chainResult = blockchainService.getCondition(marketId) val chainResult = blockchainService.getCondition(marketId)
chainResult.fold( chainResult.fold(
@@ -87,30 +97,41 @@ class MarketPriceService(
when { when {
payout > BigInteger.ZERO -> { payout > BigInteger.ZERO -> {
logger.info("从链上查询到市场已结算,该 outcome 赢了: marketId=$marketId, outcomeIndex=$outcomeIndex, payout=$payout") logger.info("从链上查询到市场已结算,该 outcome 赢了: marketId=$marketId, outcomeIndex=$outcomeIndex, payout=$payout")
return BigDecimal.ONE return Pair(BigDecimal.ONE, false)
} }
payout == BigInteger.ZERO -> { payout == BigInteger.ZERO -> {
logger.info("从链上查询到市场已结算,该 outcome 输了: marketId=$marketId, outcomeIndex=$outcomeIndex, payout=$payout") logger.info("从链上查询到市场已结算,该 outcome 输了: marketId=$marketId, outcomeIndex=$outcomeIndex, payout=$payout")
return BigDecimal.ZERO return Pair(BigDecimal.ZERO, false)
} }
else -> { else -> {
logger.warn("从链上查询到异常的 payout 值: marketId=$marketId, outcomeIndex=$outcomeIndex, payout=$payout") logger.warn("从链上查询到异常的 payout 值: marketId=$marketId, outcomeIndex=$outcomeIndex, payout=$payout")
null Pair(null, false)
} }
} }
} else { } else {
logger.debug("从链上查询到市场尚未结算: marketId=$marketId, payouts=${payouts.size}") logger.debug("从链上查询到市场尚未结算: marketId=$marketId, payouts=${payouts.size}")
null Pair(null, false)
} }
}, },
onFailure = { e -> onFailure = { e ->
logger.debug("链上查询市场条件失败,降级到 API 查询: marketId=$marketId, error=${e.message}") // 检查是否是 execution reverted 错误
null val isRpcError = e.message?.contains("execution reverted", ignoreCase = true) == true
if (isRpcError) {
logger.warn("链上查询市场条件出现 RPC 错误(execution reverted),可能市场不存在或尚未创建: marketId=$marketId, error=${e.message}")
} else {
logger.debug("链上查询市场条件失败,降级到 API 查询: marketId=$marketId, error=${e.message}")
}
Pair(null, isRpcError)
} }
) )
} catch (e: Exception) { } catch (e: Exception) {
logger.debug("链上查询市场条件异常: marketId=$marketId, outcomeIndex=$outcomeIndex, error=${e.message}") val isRpcError = e.message?.contains("execution reverted", ignoreCase = true) == true
null if (isRpcError) {
logger.warn("链上查询市场条件异常(execution reverted: marketId=$marketId, outcomeIndex=$outcomeIndex, error=${e.message}")
} else {
logger.debug("链上查询市场条件异常: marketId=$marketId, outcomeIndex=$outcomeIndex, error=${e.message}")
}
Pair(null, isRpcError)
} }
} }