Explorar o código

fix: 修正交易对和区间范围显示顺序,基于 baseIn 判断 base/quote

通过 QUOTE_MINTS 识别稳定币作为报价币,确保交易对显示为 base/quote
(如 MNT/USDC 而非 USDC/MNT),价格区间在 base 为 mintB 时取倒数。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
lushdog@outlook.com hai 1 semana
pai
achega
018cd1a167
Modificáronse 1 ficheiros con 43 adicións e 4 borrados
  1. 43 4
      src/discord/index.ts

+ 43 - 4
src/discord/index.ts

@@ -1,6 +1,27 @@
 import type { OpenPositionEvent } from '../solana/openPositionListener.js'
 import { loadConfig } from '../config.js'
 
+// 常见稳定币/报价币 mint 地址
+const QUOTE_MINTS = new Set([
+	'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC
+	'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB', // USDT
+	'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',   // USD1
+	'So11111111111111111111111111111111111111112',      // SOL
+])
+
+/**
+ * 判断 mintA 是否为 base token(baseIn=true 表示 mintA 是 base)。
+ * 如果 mintA 是稳定币/报价币,则 base 是 mintB(baseIn=false)。
+ */
+function isBaseIn(mintA: { address: string; price: string }, mintB: { address: string; price: string }): boolean {
+	const aIsQuote = QUOTE_MINTS.has(mintA.address)
+	const bIsQuote = QUOTE_MINTS.has(mintB.address)
+	if (aIsQuote && !bIsQuote) return false  // mintA 是报价币 → base 是 mintB
+	if (!aIsQuote && bIsQuote) return true   // mintB 是报价币 → base 是 mintA
+	// 都不是或都是报价币,用价格高的作为 base
+	return Number(mintA.price || 0) >= Number(mintB.price || 0)
+}
+
 export async function sendDiscordMessage(positionDetails: OpenPositionEvent['positionDetails']) {
 	if (!positionDetails) {
 		return
@@ -16,7 +37,12 @@ export async function sendDiscordMessage(positionDetails: OpenPositionEvent['pos
 	const mintB = positionDetails.mintB
 	const mintASymbol = mintA?.symbol || 'Unknown'
 	const mintBSymbol = mintB?.symbol || 'Unknown'
-	const tokenPair = `${mintASymbol}/${mintBSymbol}`
+
+	// 确定 base/quote 顺序:base 在前,quote 在后
+	const baseIn = mintA && mintB ? isBaseIn(mintA, mintB) : true
+	const baseSymbol = baseIn ? mintASymbol : mintBSymbol
+	const quoteSymbol = baseIn ? mintBSymbol : mintASymbol
+	const tokenPair = `${baseSymbol}/${quoteSymbol}`
 	const providerAddress = positionDetails.providerAddress
 	const positionAddress = positionDetails.positionAddress
 
@@ -55,11 +81,24 @@ export async function sendDiscordMessage(positionDetails: OpenPositionEvent['pos
 	// 添加区间信息
 	if (positionDetails.lowerTick !== undefined && positionDetails.upperTick !== undefined && mintA && mintB) {
 		const decimalsAdj = Math.pow(10, mintB.decimals - mintA.decimals)
-		const priceLower = Math.pow(1.0001, positionDetails.lowerTick) * decimalsAdj
-		const priceUpper = Math.pow(1.0001, positionDetails.upperTick) * decimalsAdj
+		const rawPriceLower = Math.pow(1.0001, positionDetails.lowerTick) * decimalsAdj
+		const rawPriceUpper = Math.pow(1.0001, positionDetails.upperTick) * decimalsAdj
+
+		let priceLower: number
+		let priceUpper: number
+		if (baseIn) {
+			// mintA 是 base,价格已经是 quote/base (mintB per mintA)
+			priceLower = rawPriceLower
+			priceUpper = rawPriceUpper
+		} else {
+			// mintB 是 base,需要取倒数,且上下界交换
+			priceLower = 1 / rawPriceUpper
+			priceUpper = 1 / rawPriceLower
+		}
+
 		embed.fields.push({
 			name: '📊 区间范围',
-			value: `${priceLower.toPrecision(6)} ~ ${priceUpper.toPrecision(6)} ${mintBSymbol}/${mintASymbol}`,
+			value: `${priceLower.toPrecision(6)} ~ ${priceUpper.toPrecision(6)} ${quoteSymbol}/${baseSymbol}`,
 			inline: false
 		})
 	}