process.env.TS_NODE_COMPILER_OPTIONS = JSON.stringify({ module: 'CommonJS', moduleResolution: 'node', esModuleInterop: true, allowSyntheticDefaultImports: true, }) const Module = require('module') const originalRequire = Module.prototype.require Module.prototype.require = function mockHelius(moduleId, ...args) { if (moduleId === 'helius-laserstream' || moduleId.startsWith('helius-laserstream/')) { console.log('⚠️ Mocking helius-laserstream module for dry run') return {} } return originalRequire.apply(this, [moduleId, ...args]) } require('ts-node/register') const { Keypair } = require('@solana/web3.js') const tradesModule = require('../lib/database/trades') // Stub Prisma interactions for dry run so we don't need a database tradesModule.getOpenTrades = async () => { console.log('ℹ️ Mock getOpenTrades returning empty list for dry run') return [] } tradesModule.updateTradeState = async () => { console.log('ℹ️ Mock updateTradeState no-op') } const { getInitializedPositionManager } = require('../lib/trading/position-manager') const driftOrders = require('../lib/drift/orders') // Stub Drift order helpers so we avoid needing an on-chain connection driftOrders.cancelAllOrders = async (symbol) => { console.log(`ℹ️ Mock cancelAllOrders invoked for ${symbol}`) return { success: true, cancelledCount: 0 } } driftOrders.placeExitOrders = async (options) => { console.log('ℹ️ Mock placeExitOrders called with:', options) return { success: true, signatures: ['MOCK_TP', 'MOCK_SL'] } } async function main() { process.env.DRY_RUN = 'true' process.env.DRIFT_ENV = 'devnet' process.env.SOLANA_RPC_URL = process.env.SOLANA_RPC_URL || 'https://api.devnet.solana.com' const kp = Keypair.generate() process.env.DRIFT_WALLET_PRIVATE_KEY = JSON.stringify(Array.from(kp.secretKey)) console.log('🧪 Starting TP1 refresh dry-run test') const manager = await getInitializedPositionManager() const entryPrice = 150 const trade = { id: `dry-run-${Date.now()}`, positionId: 'DRY_RUN_POSITION', symbol: 'SOL-PERP', direction: 'long', entryPrice, entryTime: Date.now(), positionSize: 200, leverage: 10, stopLossPrice: entryPrice * 0.985, tp1Price: entryPrice * 1.004, tp2Price: entryPrice * 1.007, emergencyStopPrice: entryPrice * 0.98, currentSize: 200 * 0.25, tp1Hit: true, tp2Hit: false, slMovedToBreakeven: false, slMovedToProfit: false, trailingStopActive: false, realizedPnL: 10, unrealizedPnL: 0, peakPnL: 12, peakPrice: entryPrice * 1.01, maxFavorableExcursion: 1.2, maxAdverseExcursion: -0.6, maxFavorablePrice: entryPrice * 1.01, maxAdversePrice: entryPrice * 0.99, priceCheckCount: 0, lastPrice: entryPrice, lastUpdateTime: Date.now(), } await manager.addTrade(trade) console.log('➡️ Invoking handlePostTp1Adjustments...') await manager.handlePostTp1Adjustments(trade, 'dry-run script') console.log('✅ Dry run complete. Review logs above for refreshed exit order placement.') process.exit(0) } main().catch((err) => { console.error('❌ Dry run test failed:', err) process.exit(1) })