|
|
@@ -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
|
|
|
})
|
|
|
}
|