Răsfoiți Sursa

fix(jupiter): swap 前检查现有余额,只兑换差额

- ensureSufficientBalances 检查用户现有代币余额,只 swap 差额
- swapIfNeeded 只跳过 USDC->USDC,允许 USDC->USDT/USD1
- 更新 lp-copy 和 lp-add 传递 priceUsd 和 decimals 参数
lushdog@outlook.com 4 săptămâni în urmă
părinte
comite
fc4d4956d4
3 a modificat fișierele cu 43 adăugiri și 20 ștergeri
  1. 10 5
      src/app/api/lp-copy/route.ts
  2. 4 0
      src/app/api/lp-index/lp-add/route.ts
  3. 29 15
      src/lib/jupiter.ts

+ 10 - 5
src/app/api/lp-copy/route.ts

@@ -506,19 +506,21 @@ async function copyLPPosition(
 		const userKeypair = Keypair.fromSecretKey(bs58.decode(secretKey))
 		const userAddress = userKeypair.publicKey
 
-		const tokenAValueUsd =
-			finalUiAmountA.toNumber() * tokenAPriceUsd
-		const tokenBValueUsd =
-			finalUiAmountB.toNumber() * tokenBPriceUsd
+		const tokenAValueUsd = finalUiAmountA.toNumber() * tokenAPriceUsd
+		const tokenBValueUsd = finalUiAmountB.toNumber() * tokenBPriceUsd
 
 		const tokenAInfo = {
 			mint: poolInfo.mintA.toBase58(),
 			valueUsd: tokenAValueUsd,
+			priceUsd: tokenAPriceUsd,
+			decimals: poolInfo.mintDecimalsA,
 		}
 
 		const tokenBInfo = {
 			mint: poolInfo.mintB.toBase58(),
 			valueUsd: tokenBValueUsd,
+			priceUsd: tokenBPriceUsd,
+			decimals: poolInfo.mintDecimalsB,
 		}
 
 		const rpcUrl =
@@ -534,7 +536,10 @@ async function copyLPPosition(
 			)
 
 			if (!balanceCheck.success) {
-				console.error('Failed to ensure sufficient balances:', balanceCheck.error)
+				console.error(
+					'Failed to ensure sufficient balances:',
+					balanceCheck.error
+				)
 				return NextResponse.json(
 					{
 						error: '余额不足且自动换币失败',

+ 4 - 0
src/app/api/lp-index/lp-add/route.ts

@@ -325,10 +325,14 @@ export async function POST(request: NextRequest) {
 		const tokenAInfo = {
 			mint: tokenAAddress,
 			valueUsd: tokenAValueUsd,
+			priceUsd: tokenAPriceUsd,
+			decimals: poolInfo.mintDecimalsA,
 		}
 		const tokenBInfo = {
 			mint: tokenBAddress,
 			valueUsd: tokenBValueUsd,
+			priceUsd: tokenBPriceUsd,
+			decimals: poolInfo.mintDecimalsB,
 		}
 
 		if (needSwap) {

+ 29 - 15
src/lib/jupiter.ts

@@ -351,11 +351,8 @@ export async function swapIfNeeded(
 	}
 
 	const mint = String(outputMint ?? '').trim()
-	const isStablecoin = STABLECOIN_MINTS.includes(mint) || mint === USDC_MINT
-	if (isStablecoin) {
-		console.log(
-			`Skip swap: output is stablecoin (USDC/USDT), no need to swap USDC -> same`
-		)
+	if (mint === USDC_MINT) {
+		console.log(`Skip swap: output is USDC, no need to swap USDC -> USDC`)
 		return { success: true }
 	}
 
@@ -439,28 +436,40 @@ export async function swapIfNeeded(
 /**
  * 确保 LP 所需的两种代币都有足够余额
  * 按 valueUsd 换币:使用 ExactIn,花 $valueUsd USDC 换目标代币,不使用 amount
+ * 会先检查用户现有余额,如有则扣除相应的 swap 金额
  */
 export async function ensureSufficientBalances(
 	connection: Connection,
 	keypair: Keypair,
-	tokenA: { mint: string; valueUsd: number },
-	tokenB: { mint: string; valueUsd: number }
+	tokenA: {
+		mint: string
+		valueUsd: number
+		priceUsd: number
+		decimals: number
+	},
+	tokenB: { mint: string; valueUsd: number; priceUsd: number; decimals: number }
 ): Promise<{
 	success: boolean
 	swapTxids: string[]
 	error?: string
 }> {
 	const swapTxids: string[] = []
+	const walletAddress = keypair.publicKey
+
+	// Token A:检查现有余额,计算需要 swap 的金额
+	const balanceA = await getTokenBalance(connection, walletAddress, tokenA.mint)
+	const existingValueA = balanceA * tokenA.priceUsd
+	const needSwapA = Math.max(0, tokenA.valueUsd - existingValueA)
 
-	// Token A:按 valueUsd 换
 	console.log(
-		`\n--- Token A (${tokenA.mint.slice(0, 8)}...): swap $${tokenA.valueUsd} USDC ---`
+		`\n--- Token A (${tokenA.mint.slice(0, 8)}...): need $${tokenA.valueUsd}, have $${existingValueA.toFixed(4)}, swap $${needSwapA.toFixed(4)} ---`
 	)
+
 	const resultA = await swapIfNeeded(
 		connection,
 		keypair,
 		tokenA.mint,
-		tokenA.valueUsd,
+		needSwapA,
 		USDC_MINT
 	)
 
@@ -470,7 +479,7 @@ export async function ensureSufficientBalances(
 			connection,
 			keypair,
 			tokenA.mint,
-			tokenA.valueUsd,
+			needSwapA,
 			USDT_MINT
 		)
 
@@ -487,15 +496,20 @@ export async function ensureSufficientBalances(
 		swapTxids.push(resultA.txid)
 	}
 
-	// Token B:按 valueUsd 换
+	// Token B:检查现有余额,计算需要 swap 的金额
+	const balanceB = await getTokenBalance(connection, walletAddress, tokenB.mint)
+	const existingValueB = balanceB * tokenB.priceUsd
+	const needSwapB = Math.max(0, tokenB.valueUsd - existingValueB)
+
 	console.log(
-		`\n--- Token B (${tokenB.mint.slice(0, 8)}...): swap $${tokenB.valueUsd} USDC ---`
+		`\n--- Token B (${tokenB.mint.slice(0, 8)}...): need $${tokenB.valueUsd}, have $${existingValueB.toFixed(4)}, swap $${needSwapB.toFixed(4)} ---`
 	)
+
 	const resultB = await swapIfNeeded(
 		connection,
 		keypair,
 		tokenB.mint,
-		tokenB.valueUsd,
+		needSwapB,
 		USDC_MINT
 	)
 
@@ -505,7 +519,7 @@ export async function ensureSufficientBalances(
 			connection,
 			keypair,
 			tokenB.mint,
-			tokenB.valueUsd,
+			needSwapB,
 			USDT_MINT
 		)