feat: Add production logging gating (Phase 1, Task 1.1)

- Created logger utility with environment-based gating (lib/utils/logger.ts)
- Replaced 517 console.log statements with logger.log (71% reduction)
- Fixed import paths in 15 files (resolved comment-trapped imports)
- Added DEBUG_LOGS=false to .env
- Achieves 71% immediate log reduction (517/731 statements)
- Expected 90% reduction in production when deployed

Impact: Reduced I/O blocking, lower log volume in production
Risk: LOW (easy rollback, non-invasive)
Phase: Phase 1, Task 1.1 (Quick Wins - Console.log Production Gating)

Files changed:
- NEW: lib/utils/logger.ts (production-safe logging)
- NEW: scripts/replace-console-logs.js (automation tool)
- Modified: 15 lib/*.ts files (console.log → logger.log)
- Modified: .env (DEBUG_LOGS=false)

Next: Task 1.2 (Image Size Optimization)
This commit is contained in:
mindesbunister
2025-12-05 00:32:41 +01:00
parent cc3a0a85a0
commit 302511293c
20 changed files with 2223 additions and 518 deletions

View File

@@ -5,6 +5,7 @@
*/
import { getDriftService, initializeDriftService } from './client'
import { logger } from '../utils/logger'
import { getMarketConfig } from '../../config/trading'
import BN from 'bn.js'
import {
@@ -81,7 +82,7 @@ export async function openPosition(
params: OpenPositionParams
): Promise<OpenPositionResult> {
try {
console.log('📊 Opening position:', params)
logger.log('📊 Opening position:', params)
const driftService = getDriftService()
const marketConfig = getMarketConfig(params.symbol)
@@ -89,7 +90,7 @@ export async function openPosition(
// Get current oracle price
const oraclePrice = await driftService.getOraclePrice(marketConfig.driftMarketIndex)
console.log(`💰 Current ${params.symbol} price: $${oraclePrice.toFixed(4)}`)
logger.log(`💰 Current ${params.symbol} price: $${oraclePrice.toFixed(4)}`)
// Calculate position size in base asset
const baseAssetSize = params.sizeUSD / oraclePrice
@@ -107,17 +108,17 @@ export async function openPosition(
: 1 - (params.slippageTolerance / 100)
const worstPrice = oraclePrice * slippageMultiplier
console.log(`📝 Order details:`)
console.log(` Size: ${baseAssetSize.toFixed(4)} ${params.symbol.split('-')[0]}`)
console.log(` Notional: $${params.sizeUSD.toFixed(2)}`)
console.log(` Oracle price: $${oraclePrice.toFixed(4)}`)
console.log(` Worst price (${params.slippageTolerance}% slippage): $${worstPrice.toFixed(4)}`)
logger.log(`📝 Order details:`)
logger.log(` Size: ${baseAssetSize.toFixed(4)} ${params.symbol.split('-')[0]}`)
logger.log(` Notional: $${params.sizeUSD.toFixed(2)}`)
logger.log(` Oracle price: $${oraclePrice.toFixed(4)}`)
logger.log(` Worst price (${params.slippageTolerance}% slippage): $${worstPrice.toFixed(4)}`)
// Check DRY_RUN mode
const isDryRun = process.env.DRY_RUN === 'true'
if (isDryRun) {
console.log('🧪 DRY RUN MODE: Simulating order (not executing on blockchain)')
logger.log('🧪 DRY RUN MODE: Simulating order (not executing on blockchain)')
const mockTxSig = `DRY_RUN_${Date.now()}_${Math.random().toString(36).substring(7)}`
return {
@@ -141,13 +142,13 @@ export async function openPosition(
}
// Place market order using simple placePerpOrder (like v3)
console.log('🚀 Placing REAL market order...')
logger.log('🚀 Placing REAL market order...')
const txSig = await driftClient.placePerpOrder(orderParams)
console.log(`📝 Transaction submitted: ${txSig}`)
logger.log(`📝 Transaction submitted: ${txSig}`)
// CRITICAL: Confirm transaction actually executed on-chain
console.log('⏳ Confirming transaction on-chain...')
logger.log('⏳ Confirming transaction on-chain...')
const connection = driftService.getTradeConnection() // Use Alchemy for trade operations
try {
@@ -161,7 +162,7 @@ export async function openPosition(
}
}
console.log(`✅ Transaction confirmed on-chain: ${txSig}`)
logger.log(`✅ Transaction confirmed on-chain: ${txSig}`)
} catch (confirmError) {
console.error(`❌ Failed to confirm transaction:`, confirmError)
@@ -172,7 +173,7 @@ export async function openPosition(
}
// Wait a moment for position to update
console.log('⏳ Waiting for position to update...')
logger.log('⏳ Waiting for position to update...')
await new Promise(resolve => setTimeout(resolve, 2000))
// Get actual fill price from position
@@ -188,12 +189,12 @@ export async function openPosition(
const expectedSizeUSD = params.sizeUSD
const sizeRatio = actualSizeUSD / expectedSizeUSD
console.log(`💰 Fill details:`)
console.log(` Fill price: $${fillPrice.toFixed(4)}`)
console.log(` Slippage: ${slippage.toFixed(3)}%`)
console.log(` Expected size: $${expectedSizeUSD.toFixed(2)}`)
console.log(` Actual size: $${actualSizeUSD.toFixed(2)}`)
console.log(` Size ratio: ${(sizeRatio * 100).toFixed(1)}%`)
logger.log(`💰 Fill details:`)
logger.log(` Fill price: $${fillPrice.toFixed(4)}`)
logger.log(` Slippage: ${slippage.toFixed(3)}%`)
logger.log(` Expected size: $${expectedSizeUSD.toFixed(2)}`)
logger.log(` Actual size: $${actualSizeUSD.toFixed(2)}`)
logger.log(` Size ratio: ${(sizeRatio * 100).toFixed(1)}%`)
// Flag as phantom if actual size is less than 50% of expected
const isPhantom = sizeRatio < 0.5
@@ -216,8 +217,8 @@ export async function openPosition(
}
} else {
// Position not found yet (may be DRY_RUN mode)
console.log(`⚠️ Position not immediately visible (may be DRY_RUN mode)`)
console.log(` Using oracle price as estimate: $${oraclePrice.toFixed(4)}`)
logger.log(`⚠️ Position not immediately visible (may be DRY_RUN mode)`)
logger.log(` Using oracle price as estimate: $${oraclePrice.toFixed(4)}`)
return {
success: true,
@@ -250,7 +251,7 @@ export async function openPosition(
*/
export async function placeExitOrders(options: PlaceExitOrdersOptions): Promise<PlaceExitOrdersResult> {
try {
console.log('🛡️ Placing exit orders on-chain:', options.symbol)
logger.log('🛡️ Placing exit orders on-chain:', options.symbol)
const driftService = getDriftService()
const driftClient = driftService.getClient()
@@ -258,7 +259,7 @@ export async function placeExitOrders(options: PlaceExitOrdersOptions): Promise<
const isDryRun = process.env.DRY_RUN === 'true'
if (isDryRun) {
console.log('🧪 DRY RUN: Simulating placement of exit orders')
logger.log('🧪 DRY RUN: Simulating placement of exit orders')
return {
success: true,
signatures: [
@@ -285,11 +286,11 @@ export async function placeExitOrders(options: PlaceExitOrdersOptions): Promise<
const remainingAfterTP1 = options.positionSizeUSD - tp1USD
const tp2USD = (remainingAfterTP1 * options.tp2SizePercent) / 100
console.log(`📊 Exit order sizes:`)
console.log(` TP1: ${options.tp1SizePercent}% of $${options.positionSizeUSD.toFixed(2)} = $${tp1USD.toFixed(2)}`)
console.log(` Remaining after TP1: $${remainingAfterTP1.toFixed(2)}`)
console.log(` TP2: ${options.tp2SizePercent}% of remaining = $${tp2USD.toFixed(2)}`)
console.log(` Runner (if any): $${(remainingAfterTP1 - tp2USD).toFixed(2)}`)
logger.log(`📊 Exit order sizes:`)
logger.log(` TP1: ${options.tp1SizePercent}% of $${options.positionSizeUSD.toFixed(2)} = $${tp1USD.toFixed(2)}`)
logger.log(` Remaining after TP1: $${remainingAfterTP1.toFixed(2)}`)
logger.log(` TP2: ${options.tp2SizePercent}% of remaining = $${tp2USD.toFixed(2)}`)
logger.log(` Runner (if any): $${(remainingAfterTP1 - tp2USD).toFixed(2)}`)
// For orders that close a long, the order direction should be SHORT (sell)
const orderDirection = options.direction === 'long' ? PositionDirection.SHORT : PositionDirection.LONG
@@ -307,14 +308,14 @@ export async function placeExitOrders(options: PlaceExitOrdersOptions): Promise<
reduceOnly: true,
}
console.log('🚧 Placing TP1 limit order (reduce-only)...')
logger.log('🚧 Placing TP1 limit order (reduce-only)...')
const sig = await retryWithBackoff(async () =>
await (driftClient as any).placePerpOrder(orderParams)
)
console.log('✅ TP1 order placed:', sig)
logger.log('✅ TP1 order placed:', sig)
signatures.push(sig)
} else {
console.log('⚠️ TP1 size below market min, skipping on-chain TP1')
logger.log('⚠️ TP1 size below market min, skipping on-chain TP1')
}
}
@@ -331,14 +332,14 @@ export async function placeExitOrders(options: PlaceExitOrdersOptions): Promise<
reduceOnly: true,
}
console.log('🚧 Placing TP2 limit order (reduce-only)...')
logger.log('🚧 Placing TP2 limit order (reduce-only)...')
const sig = await retryWithBackoff(async () =>
await (driftClient as any).placePerpOrder(orderParams)
)
console.log('✅ TP2 order placed:', sig)
logger.log('✅ TP2 order placed:', sig)
signatures.push(sig)
} else {
console.log('⚠️ TP2 size below market min, skipping on-chain TP2')
logger.log('⚠️ TP2 size below market min, skipping on-chain TP2')
}
}
@@ -356,7 +357,7 @@ export async function placeExitOrders(options: PlaceExitOrdersOptions): Promise<
if (useDualStops && options.softStopPrice && options.hardStopPrice) {
// ============== DUAL STOP SYSTEM ==============
console.log('🛡️🛡️ Placing DUAL STOP SYSTEM...')
logger.log('🛡️🛡️ Placing DUAL STOP SYSTEM...')
// 1. Soft Stop (TRIGGER_LIMIT) - Avoids wicks
const softStopBuffer = options.softStopBuffer ?? 0.4
@@ -377,15 +378,15 @@ export async function placeExitOrders(options: PlaceExitOrdersOptions): Promise<
reduceOnly: true,
}
console.log(` 1⃣ Soft Stop (TRIGGER_LIMIT):`)
console.log(` Trigger: $${options.softStopPrice.toFixed(4)}`)
console.log(` Limit: $${(options.softStopPrice * softStopMultiplier).toFixed(4)}`)
console.log(` Purpose: Avoid false breakouts/wicks`)
logger.log(` 1⃣ Soft Stop (TRIGGER_LIMIT):`)
logger.log(` Trigger: $${options.softStopPrice.toFixed(4)}`)
logger.log(` Limit: $${(options.softStopPrice * softStopMultiplier).toFixed(4)}`)
logger.log(` Purpose: Avoid false breakouts/wicks`)
const softStopSig = await retryWithBackoff(async () =>
await (driftClient as any).placePerpOrder(softStopParams)
)
console.log(` ✅ Soft stop placed: ${softStopSig}`)
logger.log(` ✅ Soft stop placed: ${softStopSig}`)
signatures.push(softStopSig)
// 2. Hard Stop (TRIGGER_MARKET) - Guarantees exit
@@ -401,17 +402,17 @@ export async function placeExitOrders(options: PlaceExitOrdersOptions): Promise<
reduceOnly: true,
}
console.log(` 2⃣ Hard Stop (TRIGGER_MARKET):`)
console.log(` Trigger: $${options.hardStopPrice.toFixed(4)}`)
console.log(` Purpose: Guaranteed exit if soft stop doesn't fill`)
logger.log(` 2⃣ Hard Stop (TRIGGER_MARKET):`)
logger.log(` Trigger: $${options.hardStopPrice.toFixed(4)}`)
logger.log(` Purpose: Guaranteed exit if soft stop doesn't fill`)
const hardStopSig = await retryWithBackoff(async () =>
await (driftClient as any).placePerpOrder(hardStopParams)
)
console.log(` ✅ Hard stop placed: ${hardStopSig}`)
logger.log(` ✅ Hard stop placed: ${hardStopSig}`)
signatures.push(hardStopSig)
console.log(`🎯 Dual stop system active: Soft @ $${options.softStopPrice.toFixed(2)} | Hard @ $${options.hardStopPrice.toFixed(2)}`)
logger.log(`🎯 Dual stop system active: Soft @ $${options.softStopPrice.toFixed(2)} | Hard @ $${options.hardStopPrice.toFixed(2)}`)
} else {
// ============== SINGLE STOP SYSTEM ==============
@@ -437,15 +438,15 @@ export async function placeExitOrders(options: PlaceExitOrdersOptions): Promise<
reduceOnly: true,
}
console.log(`🛡️ Placing SL as TRIGGER_LIMIT (${stopLimitBuffer}% buffer)...`)
console.log(` Trigger: ${options.direction === 'long' ? 'BELOW' : 'ABOVE'} $${options.stopLossPrice.toFixed(4)}`)
console.log(` Limit: $${(options.stopLossPrice * limitPriceMultiplier).toFixed(4)}`)
console.log(` ⚠️ May not fill during fast moves - use for liquid markets only!`)
logger.log(`🛡️ Placing SL as TRIGGER_LIMIT (${stopLimitBuffer}% buffer)...`)
logger.log(` Trigger: ${options.direction === 'long' ? 'BELOW' : 'ABOVE'} $${options.stopLossPrice.toFixed(4)}`)
logger.log(` Limit: $${(options.stopLossPrice * limitPriceMultiplier).toFixed(4)}`)
logger.log(` ⚠️ May not fill during fast moves - use for liquid markets only!`)
const sig = await retryWithBackoff(async () =>
await (driftClient as any).placePerpOrder(orderParams)
)
console.log('✅ SL trigger-limit order placed:', sig)
logger.log('✅ SL trigger-limit order placed:', sig)
signatures.push(sig)
} else {
// TRIGGER_MARKET: Default, guaranteed execution
@@ -461,19 +462,19 @@ export async function placeExitOrders(options: PlaceExitOrdersOptions): Promise<
reduceOnly: true,
}
console.log(`🛡️ Placing SL as TRIGGER_MARKET (guaranteed execution - RECOMMENDED)...`)
console.log(` Trigger: ${options.direction === 'long' ? 'BELOW' : 'ABOVE'} $${options.stopLossPrice.toFixed(4)}`)
console.log(` ✅ Will execute at market price when triggered (may slip but WILL fill)`)
logger.log(`🛡️ Placing SL as TRIGGER_MARKET (guaranteed execution - RECOMMENDED)...`)
logger.log(` Trigger: ${options.direction === 'long' ? 'BELOW' : 'ABOVE'} $${options.stopLossPrice.toFixed(4)}`)
logger.log(` ✅ Will execute at market price when triggered (may slip but WILL fill)`)
const sig = await retryWithBackoff(async () =>
await (driftClient as any).placePerpOrder(orderParams)
)
console.log('✅ SL trigger-market order placed:', sig)
logger.log('✅ SL trigger-market order placed:', sig)
signatures.push(sig)
}
}
} else {
console.log('⚠️ SL size below market min, skipping on-chain SL')
logger.log('⚠️ SL size below market min, skipping on-chain SL')
}
return { success: true, signatures }
@@ -490,7 +491,7 @@ export async function closePosition(
params: ClosePositionParams
): Promise<ClosePositionResult> {
try {
console.log('📊 Closing position:', params)
logger.log('📊 Closing position:', params)
const driftService = getDriftService()
const marketConfig = getMarketConfig(params.symbol)
@@ -509,26 +510,26 @@ export async function closePosition(
// CRITICAL FIX: If calculated size is below minimum, close 100% instead
// This prevents "runner" positions from being too small to close
if (sizeToClose < marketConfig.minOrderSize) {
console.log(`⚠️ Calculated close size ${sizeToClose.toFixed(4)} is below minimum ${marketConfig.minOrderSize}`)
console.log(` Forcing 100% close to avoid Drift rejection`)
logger.log(`⚠️ Calculated close size ${sizeToClose.toFixed(4)} is below minimum ${marketConfig.minOrderSize}`)
logger.log(` Forcing 100% close to avoid Drift rejection`)
sizeToClose = position.size // Close entire position
}
console.log(`📝 Close order details:`)
console.log(` Current position: ${position.size.toFixed(4)} ${position.side}`)
console.log(` Closing: ${params.percentToClose}% (${sizeToClose.toFixed(4)})`)
console.log(` Entry price: $${position.entryPrice.toFixed(4)}`)
console.log(` Unrealized P&L: $${position.unrealizedPnL.toFixed(2)}`)
logger.log(`📝 Close order details:`)
logger.log(` Current position: ${position.size.toFixed(4)} ${position.side}`)
logger.log(` Closing: ${params.percentToClose}% (${sizeToClose.toFixed(4)})`)
logger.log(` Entry price: $${position.entryPrice.toFixed(4)}`)
logger.log(` Unrealized P&L: $${position.unrealizedPnL.toFixed(2)}`)
// Get current oracle price
const oraclePrice = await driftService.getOraclePrice(marketConfig.driftMarketIndex)
console.log(` Current price: $${oraclePrice.toFixed(4)}`)
logger.log(` Current price: $${oraclePrice.toFixed(4)}`)
// Check DRY_RUN mode
const isDryRun = process.env.DRY_RUN === 'true'
if (isDryRun) {
console.log('🧪 DRY RUN MODE: Simulating close order (not executing on blockchain)')
logger.log('🧪 DRY RUN MODE: Simulating close order (not executing on blockchain)')
// Calculate realized P&L with leverage (default 10x in dry run)
const profitPercent = ((oraclePrice - position.entryPrice) / position.entryPrice) * 100 * (position.side === 'long' ? 1 : -1)
@@ -538,10 +539,10 @@ export async function closePosition(
const mockTxSig = `DRY_RUN_CLOSE_${Date.now()}_${Math.random().toString(36).substring(7)}`
console.log(`💰 Simulated close:`)
console.log(` Close price: $${oraclePrice.toFixed(4)}`)
console.log(` Profit %: ${profitPercent.toFixed(3)}% → Account P&L (10x): ${accountPnLPercent.toFixed(2)}%`)
console.log(` Realized P&L: $${realizedPnL.toFixed(2)}`)
logger.log(`💰 Simulated close:`)
logger.log(` Close price: $${oraclePrice.toFixed(4)}`)
logger.log(` Profit %: ${profitPercent.toFixed(3)}% → Account P&L (10x): ${accountPnLPercent.toFixed(2)}%`)
logger.log(` Realized P&L: $${realizedPnL.toFixed(2)}`)
return {
success: true,
@@ -565,16 +566,16 @@ export async function closePosition(
// Place market close order using simple placePerpOrder (like v3)
// CRITICAL: Wrap in retry logic for rate limit protection
console.log('🚀 Placing REAL market close order with retry protection...')
logger.log('🚀 Placing REAL market close order with retry protection...')
const txSig = await retryWithBackoff(async () => {
return await driftClient.placePerpOrder(orderParams)
}, 3, 8000) // 8s base delay, 3 max retries
console.log(`✅ Close order placed! Transaction: ${txSig}`)
logger.log(`✅ Close order placed! Transaction: ${txSig}`)
// 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)...')
logger.log('⏳ Confirming transaction on-chain (30s timeout)...')
const connection = driftService.getTradeConnection() // Use Alchemy for trade operations
try {
@@ -590,7 +591,7 @@ export async function closePosition(
throw new Error(`Transaction failed: ${JSON.stringify(confirmation.value.err)}`)
}
console.log('✅ Transaction confirmed on-chain')
logger.log('✅ Transaction confirmed on-chain')
} catch (timeoutError: any) {
if (timeoutError.message === 'Transaction confirmation timeout') {
console.warn('⚠️ Transaction confirmation timed out after 30s')
@@ -615,7 +616,7 @@ export async function closePosition(
leverage = 10000 / Number(userAccount.maxMarginRatio)
}
} catch (err) {
console.log('⚠️ Could not determine leverage from account, using 10x default')
logger.log('⚠️ Could not determine leverage from account, using 10x default')
}
// Calculate closed notional value (USD)
@@ -623,24 +624,24 @@ export async function closePosition(
const realizedPnL = (closedNotional * profitPercent) / 100
const accountPnLPercent = profitPercent * leverage
console.log(`💰 Close details:`)
console.log(` Close price: $${oraclePrice.toFixed(4)}`)
console.log(` Profit %: ${profitPercent.toFixed(3)}% | Account P&L (${leverage}x): ${accountPnLPercent.toFixed(2)}%`)
console.log(` Closed notional: $${closedNotional.toFixed(2)}`)
console.log(` Realized P&L: $${realizedPnL.toFixed(2)}`)
logger.log(`💰 Close details:`)
logger.log(` Close price: $${oraclePrice.toFixed(4)}`)
logger.log(` Profit %: ${profitPercent.toFixed(3)}% | Account P&L (${leverage}x): ${accountPnLPercent.toFixed(2)}%`)
logger.log(` Closed notional: $${closedNotional.toFixed(2)}`)
logger.log(` Realized P&L: $${realizedPnL.toFixed(2)}`)
// If closing 100%, verify position actually closed and cancel remaining orders
if (params.percentToClose === 100) {
console.log('🗑️ Position fully closed, cancelling remaining orders...')
logger.log('🗑️ Position fully closed, cancelling remaining orders...')
const cancelResult = await cancelAllOrders(params.symbol)
if (cancelResult.success && cancelResult.cancelledCount! > 0) {
console.log(`✅ Cancelled ${cancelResult.cancelledCount} orders`)
logger.log(`✅ Cancelled ${cancelResult.cancelledCount} orders`)
}
// CRITICAL: Verify position actually closed on Drift (Nov 16, 2025)
// Transaction confirmed ≠ Drift state updated immediately
// Wait 5 seconds for Drift internal state to propagate
console.log('⏳ Waiting 5s for Drift state to propagate...')
logger.log('⏳ Waiting 5s for Drift state to propagate...')
await new Promise(resolve => setTimeout(resolve, 5000))
try {
@@ -661,7 +662,7 @@ export async function closePosition(
needsVerification: true, // Flag for Position Manager
}
} else {
console.log('✅ Position verified closed on Drift')
logger.log('✅ Position verified closed on Drift')
}
} catch (verifyError) {
console.warn('⚠️ Could not verify position closure:', verifyError)
@@ -712,7 +713,7 @@ async function retryWithBackoff<T>(
// Log successful execution time for rate limit monitoring
if (attempt > 0) {
const totalTime = Date.now() - startTime
console.log(`✅ Retry successful after ${totalTime}ms (${attempt} retries)`)
logger.log(`✅ Retry successful after ${totalTime}ms (${attempt} retries)`)
// Log to database for analytics
try {
@@ -756,8 +757,8 @@ async function retryWithBackoff<T>(
}
const delay = baseDelay * Math.pow(2, attempt)
console.log(`⏳ Rate limited (429), retrying in ${delay / 1000}s... (attempt ${attempt + 1}/${maxRetries})`)
console.log(` Error context: ${errorMessage.substring(0, 100)}`)
logger.log(`⏳ Rate limited (429), retrying in ${delay / 1000}s... (attempt ${attempt + 1}/${maxRetries})`)
logger.log(` Error context: ${errorMessage.substring(0, 100)}`)
// Log rate limit hit to database
try {
@@ -783,12 +784,12 @@ export async function cancelAllOrders(
symbol: string
): Promise<{ success: boolean; cancelledCount?: number; error?: string }> {
try {
console.log(`🗑️ Cancelling all orders for ${symbol}...`)
logger.log(`🗑️ Cancelling all orders for ${symbol}...`)
// Ensure Drift service is initialized
let driftService = getDriftService()
if (!driftService) {
console.log('⚠️ Drift service not initialized, initializing now...')
logger.log('⚠️ Drift service not initialized, initializing now...')
driftService = await initializeDriftService()
}
@@ -797,7 +798,7 @@ export async function cancelAllOrders(
const isDryRun = process.env.DRY_RUN === 'true'
if (isDryRun) {
console.log('🧪 DRY RUN: Simulating order cancellation')
logger.log('🧪 DRY RUN: Simulating order cancellation')
return { success: true, cancelledCount: 0 }
}
@@ -827,12 +828,12 @@ export async function cancelAllOrders(
)
if (ordersToCancel.length === 0) {
console.log('✅ No open orders to cancel')
logger.log('✅ No open orders to cancel')
return { success: true, cancelledCount: 0 }
}
console.log(`📋 Found ${ordersToCancel.length} open orders to cancel (including trigger orders)`)
console.log(` (checked ${userAccount.orders.length} total order slots)`)
logger.log(`📋 Found ${ordersToCancel.length} open orders to cancel (including trigger orders)`)
logger.log(` (checked ${userAccount.orders.length} total order slots)`)
// Cancel all orders with retry logic for rate limits
const txSig = await retryWithBackoff(async () => {
@@ -843,7 +844,7 @@ export async function cancelAllOrders(
)
})
console.log(`✅ Orders cancelled! Transaction: ${txSig}`)
logger.log(`✅ Orders cancelled! Transaction: ${txSig}`)
return {
success: true,
@@ -883,21 +884,21 @@ export async function emergencyCloseAll(): Promise<{
result: ClosePositionResult
}>
}> {
console.log('🚨 EMERGENCY: Closing all positions')
logger.log('🚨 EMERGENCY: Closing all positions')
try {
const driftService = getDriftService()
const positions = await driftService.getAllPositions()
if (positions.length === 0) {
console.log('✅ No positions to close')
logger.log('✅ No positions to close')
return { success: true, results: [] }
}
const results = []
for (const position of positions) {
console.log(`🔴 Emergency closing ${position.symbol}...`)
logger.log(`🔴 Emergency closing ${position.symbol}...`)
const result = await closeEntirePosition(position.symbol, 2.0) // Allow 2% slippage
results.push({
symbol: position.symbol,
@@ -905,7 +906,7 @@ export async function emergencyCloseAll(): Promise<{
})
}
console.log('✅ Emergency close complete')
logger.log('✅ Emergency close complete')
return {
success: true,