feat: Hybrid RPC strategy (Helius init + Alchemy trades)

CRITICAL: Fix rate limiting by using dual RPC approach

Problem:
- Helius RPC gets overwhelmed during trade execution (429 errors)
- Exit orders fail to place, leaving positions UNPROTECTED
- No on-chain TP/SL orders = unlimited risk if container crashes

Solution: Hybrid RPC Strategy
- Helius for Drift SDK initialization (handles burst subscriptions well)
- Alchemy for trade operations (better sustained rate limits)
- Falls back to Helius if Alchemy not configured

Implementation:
- DriftService now has two connections: connection (Helius) + tradeConnection (Alchemy)
- Added getTradeConnection() method for trade operations
- Updated openPosition() and closePosition() to use trade connection
- Added ALCHEMY_RPC_URL to .env (optional, falls back to Helius)

Benefits:
- Helius: 0 subscription errors during init (proven reliable for SDK setup)
- Alchemy: 300M compute units/month for sustained trade operations
- Best of both worlds: reliable init + reliable trades

Files:
- lib/drift/client.ts: Dual connection support
- lib/drift/orders.ts: Use getTradeConnection() for confirmations
- .env: Added ALCHEMY_RPC_URL

Testing: Deploy and execute test trade to verify orders place successfully
This commit is contained in:
mindesbunister
2025-11-15 12:00:57 +01:00
parent f8141009a8
commit 0ef6b82106
3 changed files with 35 additions and 2 deletions

View File

@@ -17,12 +17,14 @@ interface ManualWallet {
export interface DriftConfig {
rpcUrl: string
alchemyRpcUrl?: string // Optional: Use Alchemy for trade operations (better sustained rate limits)
walletPrivateKey: string
env: 'mainnet-beta' | 'devnet'
}
export class DriftService {
private connection: Connection
private tradeConnection: Connection // Separate connection for trade operations (uses Alchemy if available)
private wallet: ManualWallet
private keypair: Keypair
private driftClient: DriftClient | null = null
@@ -32,8 +34,21 @@ export class DriftService {
private reconnectIntervalMs: number = 4 * 60 * 60 * 1000 // 4 hours (prevent memory leak)
constructor(private config: DriftConfig) {
// Helius connection for Drift SDK initialization (handles burst subscriptions well)
this.connection = new Connection(config.rpcUrl, 'confirmed')
// Alchemy connection for trade operations (better sustained rate limits)
// Falls back to Helius if Alchemy not configured
this.tradeConnection = config.alchemyRpcUrl
? new Connection(config.alchemyRpcUrl, 'confirmed')
: this.connection
if (config.alchemyRpcUrl) {
console.log('🔀 Hybrid RPC mode: Helius for init, Alchemy for trades')
} else {
console.log('📡 Single RPC mode: Helius for all operations')
}
// Create wallet from private key
// Support both formats:
// 1. JSON array: [91,24,199,...] (from Phantom export as array)
@@ -233,6 +248,21 @@ export class DriftService {
}
}
/**
* Get the Solana connection (Helius - for SDK operations)
*/
getConnection(): Connection {
return this.connection
}
/**
* Get the trade connection (Alchemy if configured, otherwise Helius)
* Use this for all trade operations (open, close, place orders)
*/
getTradeConnection(): Connection {
return this.tradeConnection
}
/**
* Get current USDC balance
*/
@@ -465,6 +495,7 @@ export function getDriftService(): DriftService {
if (!driftServiceInstance) {
const config: DriftConfig = {
rpcUrl: process.env.SOLANA_RPC_URL || 'https://api.mainnet-beta.solana.com',
alchemyRpcUrl: process.env.ALCHEMY_RPC_URL, // Optional: Alchemy for trade operations
walletPrivateKey: process.env.DRIFT_WALLET_PRIVATE_KEY || '',
env: (process.env.DRIFT_ENV as 'mainnet-beta' | 'devnet') || 'mainnet-beta',
}