|
|
@@ -91,6 +91,43 @@ function getJupiterHeaders(): Record<string, string> {
|
|
|
return headers
|
|
|
}
|
|
|
|
|
|
+/** Jupiter Price API v3 返回的单个代币价格(price.jup.ag 已弃用,请用 api.jup.ag/price/v3) */
|
|
|
+const JUPITER_PRICE_API_URL =
|
|
|
+ process.env.JUPITER_PRICE_API_URL || 'https://api.jup.ag/price/v3'
|
|
|
+
|
|
|
+/**
|
|
|
+ * 从 Jupiter Price API v3 获取代币 USD 价格(备用,避免使用已弃用的 price.jup.ag)
|
|
|
+ * @returns 成功时返回 { tokenAPriceUsd, tokenBPriceUsd },失败返回 null
|
|
|
+ */
|
|
|
+export async function getTokenPricesFromJupiter(
|
|
|
+ mintA: string,
|
|
|
+ mintB: string
|
|
|
+): Promise<{ tokenAPriceUsd: number; tokenBPriceUsd: number } | null> {
|
|
|
+ try {
|
|
|
+ const ids = [mintA, mintB].filter((m, i, arr) => arr.indexOf(m) === i).join(',')
|
|
|
+ const data = await ky
|
|
|
+ .get(`${JUPITER_PRICE_API_URL}?ids=${ids}`, {
|
|
|
+ headers: getJupiterHeaders(),
|
|
|
+ timeout: 10000,
|
|
|
+ })
|
|
|
+ .json<Record<string, { price?: number; usdPrice?: number }>>()
|
|
|
+ const priceOf = (mint: string): number | undefined => {
|
|
|
+ const row = data[mint]
|
|
|
+ if (!row) return undefined
|
|
|
+ return row.usdPrice ?? row.price
|
|
|
+ }
|
|
|
+ const pa = priceOf(mintA)
|
|
|
+ const pb = priceOf(mintB)
|
|
|
+ if (pa != null && pa > 0 && pb != null && pb > 0) {
|
|
|
+ return { tokenAPriceUsd: pa, tokenBPriceUsd: pb }
|
|
|
+ }
|
|
|
+ return null
|
|
|
+ } catch (error) {
|
|
|
+ console.warn('Jupiter price v3 fetch failed:', error)
|
|
|
+ return null
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* 从 Jupiter API 获取 quote
|
|
|
* @param restrictIntermediate - 为 false 时允许更多中间代币路由(用于 NO_ROUTES_FOUND 时重试)
|