Эх сурвалжийг харах

fix: use correct token decimals for swap amount calculation

zhangchunrui 4 долоо хоног өмнө
parent
commit
6c354253d1
1 өөрчлөгдсөн 30 нэмэгдсэн , 8 устгасан
  1. 30 8
      src/solana/jupiter.ts

+ 30 - 8
src/solana/jupiter.ts

@@ -104,8 +104,8 @@ export class JupiterSwapper {
 		}
 	}
 
-	async getTokenPrices(tokenAddresses: string[]): Promise<Record<string, { price?: number; symbol?: string }>> {
-		const result: Record<string, { price?: number; symbol?: string }> = {}
+	async getTokenPrices(tokenAddresses: string[]): Promise<Record<string, { price?: number; symbol?: string; decimals?: number }>> {
+		const result: Record<string, { price?: number; symbol?: string; decimals?: number }> = {}
 
 		// 1. 先尝试 Jupiter Price API v3
 		try {
@@ -114,10 +114,10 @@ export class JupiterSwapper {
 				headers: this.getHeaders(),
 			})
 			if (response.ok) {
-				const data = (await response.json()) as Record<string, { usdPrice?: number }>
+				const data = (await response.json()) as Record<string, { usdPrice?: number; decimals?: number }>
 				for (const [mint, info] of Object.entries(data)) {
 					if (info.usdPrice) {
-						result[mint] = { price: info.usdPrice }
+						result[mint] = { price: info.usdPrice, decimals: info.decimals }
 					}
 				}
 			}
@@ -143,7 +143,7 @@ export class JupiterSwapper {
 		return result
 	}
 
-	private async getDexScreenerPrice(mint: string): Promise<{ price?: number; symbol?: string } | null> {
+	private async getDexScreenerPrice(mint: string): Promise<{ price?: number; symbol?: string; decimals?: number } | null> {
 		try {
 			const response = await fetch(`https://api.dexscreener.com/latest/dex/tokens/${mint}`)
 			if (!response.ok) return null
@@ -151,7 +151,7 @@ export class JupiterSwapper {
 			const data = (await response.json()) as {
 				pairs?: Array<{
 					priceUsd?: string
-					baseToken?: { symbol?: string }
+					baseToken?: { symbol?: string; decimals?: number }
 					liquidity?: { usd?: number }
 				}>
 			}
@@ -165,6 +165,7 @@ export class JupiterSwapper {
 					return {
 						price,
 						symbol: bestPair.baseToken?.symbol,
+						decimals: bestPair.baseToken?.decimals,
 					}
 				}
 			}
@@ -174,6 +175,19 @@ export class JupiterSwapper {
 		}
 	}
 
+	private async getTokenDecimals(mint: string): Promise<number> {
+		try {
+			const mintInfo = await this.connection.getParsedAccountInfo(new PublicKey(mint))
+			const data = mintInfo.value?.data
+			if (data && 'parsed' in data) {
+				return data.parsed.info.decimals || 9
+			}
+		} catch {
+			// ignore
+		}
+		return 9
+	}
+
 	private async sleep(ms: number): Promise<void> {
 		return new Promise((resolve) => setTimeout(resolve, ms))
 	}
@@ -395,7 +409,12 @@ export class JupiterSwapper {
 
 				console.log(`[Jupiter] Swapping $${swapValueUsd.toFixed(2)} worth to USDC (keeping $${keepUsdValue})`)
 
-				const swapAmountRaw = Math.floor((swapValueUsd / priceUsd) * Math.pow(10, 6))
+				// 获取代币 decimals,默认为 9
+				let decimals = prices[mint]?.decimals
+				if (decimals === undefined) {
+					decimals = await this.getTokenDecimals(mint)
+				}
+				const swapAmountRaw = Math.floor((swapValueUsd / priceUsd) * Math.pow(10, decimals))
 
 				try {
 					let quoteData: unknown
@@ -440,11 +459,14 @@ export class JupiterSwapper {
 
 					console.log(`[Jupiter] Swap confirmed: https://solscan.io/tx/${signature}`)
 
+					// 使用 quote.outAmount 计算实际获得的 USDC (USDC decimals = 6)
+					const actualUsdcReceived = quote.outAmount ? parseFloat(quote.outAmount) / 1e6 : swapValueUsd
+
 					swaps.push({
 						mint,
 						symbol,
 						amount: swapValueUsd / priceUsd,
-						swappedUsd: swapValueUsd,
+						swappedUsd: actualUsdcReceived,
 						txSignature: signature,
 					})
 				} catch (swapError) {