From e96a0b6279720f1f2af563291090f716eda358c8 Mon Sep 17 00:00:00 2001 From: WrBug Date: Sun, 28 Dec 2025 04:58:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=20Telegram=20?= =?UTF-8?q?=E6=8E=A8=E9=80=81=E6=B6=88=E6=81=AF=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加价格和数量截位处理: * 价格保留最多4位小数(截断,不四舍五入) * 数量保留最多2位小数(截断,不四舍五入) - 优化账户信息显示格式: * 有账户名和钱包地址时显示:账户名(0x123...123) * 只有账户名时显示账户名 * 只有钱包地址时显示脱敏后的地址 * 都没有时显示未知账户 - 统一使用 buildAccountInfo 函数构建账户信息 - 应用到所有消息类型:订单成功、订单失败、订单被过滤、仓位赎回 --- .../system/TelegramNotificationService.kt | 149 +++++++++++------- 1 file changed, 89 insertions(+), 60 deletions(-) diff --git a/backend/src/main/kotlin/com/wrbug/polymarketbot/service/system/TelegramNotificationService.kt b/backend/src/main/kotlin/com/wrbug/polymarketbot/service/system/TelegramNotificationService.kt index 5ad7a4a..7276832 100644 --- a/backend/src/main/kotlin/com/wrbug/polymarketbot/service/system/TelegramNotificationService.kt +++ b/backend/src/main/kotlin/com/wrbug/polymarketbot/service/system/TelegramNotificationService.kt @@ -306,18 +306,8 @@ class TelegramNotificationService( else -> filterType } - // 优先使用账户名称,如果没有账户名称才显示钱包地址 - val accountInfo: String = when { - !accountName.isNullOrBlank() -> { - accountName!! - } - !walletAddress.isNullOrBlank() -> { - maskAddress(walletAddress!!) - } - else -> { - unknownAccount - } - } + // 构建账户信息(格式:账户名(钱包地址)) + val accountInfo = buildAccountInfo(accountName, walletAddress, unknownAccount) val time = DateUtils.formatDateTime() @@ -369,13 +359,17 @@ class TelegramNotificationService( "" } + // 格式化价格和数量 + val priceDisplay = formatPrice(price) + val sizeDisplay = formatQuantity(size) + return """🚫 $orderFiltered 📊 $orderInfo: • $marketLabel: $marketDisplay$outcomeDisplay • $sideLabel: $sideDisplay -• $priceLabel: $price -• $quantityLabel: $size shares +• $priceLabel: $priceDisplay +• $quantityLabel: $sizeDisplay shares • $amountLabel: $amountDisplay USDC • $accountLabel: $escapedAccountInfo @@ -580,6 +574,68 @@ class TelegramNotificationService( } } + /** + * 格式化价格显示(保留最多4位小数,截断不四舍五入) + */ + private fun formatPrice(price: String): String { + return try { + val priceDecimal = price.toSafeBigDecimal() + val formatted = if (priceDecimal.scale() > 4) { + priceDecimal.setScale(4, java.math.RoundingMode.DOWN).stripTrailingZeros() + } else { + priceDecimal.stripTrailingZeros() + } + formatted.toPlainString() + } catch (e: Exception) { + price + } + } + + /** + * 格式化数量显示(保留最多2位小数,截断不四舍五入) + */ + private fun formatQuantity(quantity: String): String { + return try { + val quantityDecimal = quantity.toSafeBigDecimal() + val formatted = if (quantityDecimal.scale() > 2) { + quantityDecimal.setScale(2, java.math.RoundingMode.DOWN).stripTrailingZeros() + } else { + quantityDecimal.stripTrailingZeros() + } + formatted.toPlainString() + } catch (e: Exception) { + quantity + } + } + + /** + * 构建账户信息显示(格式:账户名(钱包地址)) + */ + private fun buildAccountInfo( + accountName: String?, + walletAddress: String?, + unknownAccount: String + ): String { + return when { + !accountName.isNullOrBlank() && !walletAddress.isNullOrBlank() -> { + // 有账户名和钱包地址:账户名(钱包地址) + "${accountName}(${maskAddress(walletAddress)})" + } + !accountName.isNullOrBlank() -> { + // 只有账户名 + accountName + } + !walletAddress.isNullOrBlank() -> { + // 只有钱包地址 + maskAddress(walletAddress) + } + else -> { + // 都没有 + unknownAccount + } + } + } + /** * 构建订单成功消息 */ @@ -623,18 +679,8 @@ class TelegramNotificationService( else -> side } - // 优先使用账户名称,如果没有账户名称才显示钱包地址 - val accountInfo: String = when { - !accountName.isNullOrBlank() -> { - accountName!! - } - !walletAddress.isNullOrBlank() -> { - maskAddress(walletAddress!!) - } - else -> { - unknownAccount - } - } + // 构建账户信息(格式:账户名(钱包地址)) + val accountInfo = buildAccountInfo(accountName, walletAddress, unknownAccount) // 构建跟单信息(如果有) val copyTradingInfo = mutableListOf() @@ -704,14 +750,18 @@ class TelegramNotificationService( "" } + // 格式化价格和数量 + val priceDisplay = formatPrice(price) + val sizeDisplay = formatQuantity(size) + return """✅ $orderCreatedSuccess 📊 $orderInfo: • $orderIdLabel: ${orderId ?: unknown} • $marketLabel: $marketDisplay$outcomeDisplay • $sideLabel: $sideDisplay -• $priceLabel: $price -• $quantityLabel: $size shares +• $priceLabel: $priceDisplay +• $quantityLabel: $sizeDisplay shares • $amountLabel: $amountDisplay USDC • $accountLabel: $escapedAccountInfo$escapedCopyTradingInfo @@ -758,18 +808,8 @@ class TelegramNotificationService( else -> side } - // 优先使用账户名称,如果没有账户名称才显示钱包地址 - val accountInfo: String = when { - !accountName.isNullOrBlank() -> { - accountName!! - } - !walletAddress.isNullOrBlank() -> { - maskAddress(walletAddress!!) - } - else -> { - unknownAccount - } - } + // 构建账户信息(格式:账户名(钱包地址)) + val accountInfo = buildAccountInfo(accountName, walletAddress, unknownAccount) val time = DateUtils.formatDateTime() @@ -828,13 +868,17 @@ class TelegramNotificationService( "" } + // 格式化价格和数量 + val priceDisplay = formatPrice(price) + val sizeDisplay = formatQuantity(size) + return """❌ $orderCreatedFailed 📊 $orderInfo: • $marketLabel: $marketDisplay$outcomeDisplay • $sideLabel: $sideDisplay -• $priceLabel: $price -• $quantityLabel: $size shares +• $priceLabel: $priceDisplay +• $quantityLabel: $sizeDisplay shares • $amountLabel: $amountDisplay USDC • $accountLabel: $escapedAccountInfo @@ -899,18 +943,8 @@ class TelegramNotificationService( val timeLabel = messageSource.getMessage("notification.order.time", null, "时间", locale) val unknownAccount: String = messageSource.getMessage("notification.order.unknown_account", null, "未知账户", locale) ?: "未知账户" - // 优先使用账户名称,如果没有账户名称才显示钱包地址 - val accountInfo: String = when { - !accountName.isNullOrBlank() -> { - accountName!! - } - !walletAddress.isNullOrBlank() -> { - maskAddress(walletAddress!!) - } - else -> { - unknownAccount - } - } + // 构建账户信息(格式:账户名(钱包地址)) + val accountInfo = buildAccountInfo(accountName, walletAddress, unknownAccount) val time = DateUtils.formatDateTime() @@ -933,12 +967,7 @@ class TelegramNotificationService( // 构建仓位列表 val positionsText = positions.joinToString("\n") { position -> - val quantityDisplay = try { - val quantityDecimal = position.quantity.toSafeBigDecimal() - quantityDecimal.stripTrailingZeros().toPlainString() - } catch (e: Exception) { - position.quantity - } + val quantityDisplay = formatQuantity(position.quantity) val valueDisplay = try { val valueDecimal = position.value.toSafeBigDecimal() val formatted = if (valueDecimal.scale() > 4) {