From 78ab9e1a9478c549b68f58c66da8a861edf9baa1 Mon Sep 17 00:00:00 2001 From: mindesbunister Date: Fri, 14 Nov 2025 20:42:59 +0100 Subject: [PATCH] fix: Increase transaction confirmation timeout to 60s for Alchemy Growth - Alchemy Growth (10,000 CU/s) can handle longer confirmation waits - Increased timeout from 30s to 60s in both openPosition() and closePosition() - Added debug logging to execute endpoint to trace hang points - Configured dual RPC: Alchemy primary (transactions), Helius fallback (subscriptions) - Previous 30s timeout was causing premature failures during Solana congestion - This should resolve 'Transaction was not confirmed in 30.00 seconds' errors Related: User reported n8n webhook returning 500 with timeout error --- .env | 12 ++++++++---- app/api/trading/execute/route.ts | 20 ++++++++++++++++++++ lib/drift/orders.ts | 20 ++++++++++++++------ 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/.env b/.env index 40cae68..7a321ef 100644 --- a/.env +++ b/.env @@ -31,11 +31,15 @@ API_SECRET_KEY=2a344f0149442c857fb56c038c0c7d1b113883b830bec792c76f1e0efa15d6bb # Solana RPC URL (Required for blockchain access) # -# RECOMMENDED: Helius (best performance, free tier available) -# Get free API key at: https://helius.dev -SOLANA_RPC_URL=https://mainnet.helius-rpc.com/?api-key=5e236449-f936-4af7-ae38-f15e2f1a3757 +# PRIMARY: Alchemy Growth (10,000 CU/s, best for transactions) +# Used for: Transaction submission and confirmation +SOLANA_RPC_URL=https://solana-mainnet.g.alchemy.com/v2/5A0iA5UYpsmP9gkuezYeg -# Alternative RPC providers (if not using Helius): +# FALLBACK: Helius (for WebSocket subscriptions if needed) +# Used for: Account subscriptions (Drift SDK initialization) +SOLANA_FALLBACK_RPC_URL=https://mainnet.helius-rpc.com/?api-key=5e236449-f936-4af7-ae38-f15e2f1a3757 + +# Alternative RPC providers (reference): # # QuickNode: https://solana-mainnet.quiknode.pro/YOUR_ENDPOINT/ # Alchemy: https://solana-mainnet.g.alchemy.com/v2/YOUR_ALCHEMY_KEY diff --git a/app/api/trading/execute/route.ts b/app/api/trading/execute/route.ts index f783170..bf29b78 100644 --- a/app/api/trading/execute/route.ts +++ b/app/api/trading/execute/route.ts @@ -567,6 +567,17 @@ export async function POST(request: NextRequest): Promise + setTimeout(() => reject(new Error('Transaction confirmation timeout')), 60000) + ) + + const confirmation = await Promise.race([confirmationPromise, timeoutPromise]) as any if (confirmation.value.err) { console.error(`❌ Transaction failed on-chain:`, confirmation.value.err) @@ -558,13 +565,14 @@ export async function closePosition( // CRITICAL: Confirm transaction on-chain to prevent phantom closes // BUT: Use timeout to prevent API hangs during network congestion - console.log('⏳ Confirming transaction on-chain (30s timeout)...') + console.log('⏳ Confirming transaction on-chain (60s timeout for Alchemy Growth)...') const connection = driftService.getConnection() try { + // Increased timeout from 30s to 60s for Alchemy Growth reliability const confirmationPromise = connection.confirmTransaction(txSig, 'confirmed') const timeoutPromise = new Promise((_, reject) => - setTimeout(() => reject(new Error('Transaction confirmation timeout')), 30000) + setTimeout(() => reject(new Error('Transaction confirmation timeout')), 60000) ) const confirmation = await Promise.race([confirmationPromise, timeoutPromise]) as any @@ -577,7 +585,7 @@ export async function closePosition( console.log('✅ Transaction confirmed on-chain') } catch (timeoutError: any) { if (timeoutError.message === 'Transaction confirmation timeout') { - console.warn('⚠️ Transaction confirmation timed out after 30s') + console.warn('⚠️ Transaction confirmation timed out after 60s') console.warn(' Order may still execute - check Drift UI') console.warn(` Transaction signature: ${txSig}`) // Continue anyway - order was submitted and will likely execute @@ -654,7 +662,7 @@ export async function closePosition( async function retryWithBackoff( fn: () => Promise, maxRetries: number = 3, - baseDelay: number = 5000 // Increased from 2s to 5s: 5s → 10s → 20s progression + baseDelay: number = 8000 // Increased from 5s to 8s: 8s → 16s → 32s progression for better RPC recovery ): Promise { const startTime = Date.now()