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