fix: resolve SL/TP order placement and orphaned cleanup issues
- Fixed Drift SDK initialization in place-order endpoint (NodeWallet vs Wallet) - Added 2% minimum trigger distance validation in execute-drift endpoint - Corrected orphaned order cleanup logic to cancel ALL orders when no position - Resolved issue where SL/TP orders were immediately canceled due to insufficient distance - Tested complete cycle: position entry → protective orders → orphaned cleanup Orders now maintain proper 2% distance from market price and stay active. Cleanup system correctly identifies and removes orphaned orders when positions close.
This commit is contained in:
@@ -99,13 +99,9 @@ export async function POST() {
|
|||||||
// Check if this order is for a market where we have no position
|
// Check if this order is for a market where we have no position
|
||||||
const hasPosition = positionMarkets.has(order.marketIndex)
|
const hasPosition = positionMarkets.has(order.marketIndex)
|
||||||
|
|
||||||
// CRITICAL FIX: Only cancel reduce-only orders if there's NO position
|
// CORRECTED LOGIC: Cancel ALL orders when no position exists
|
||||||
// Stop Loss and Take Profit orders are reduce-only but should EXIST when we have a position
|
// If we have no position, then ALL orders (including SL/TP) are orphaned
|
||||||
const isReduceOnly = order.reduceOnly
|
return !hasPosition
|
||||||
|
|
||||||
// Only cancel orders that are truly orphaned (no position for that market)
|
|
||||||
// Do NOT cancel reduce-only orders when we have a position (these are SL/TP!)
|
|
||||||
return !hasPosition && !isReduceOnly
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Additionally, find lingering SL/TP orders when position has changed significantly
|
// Additionally, find lingering SL/TP orders when position has changed significantly
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export async function POST(request) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Import Drift SDK
|
// Import Drift SDK
|
||||||
const { DriftClient, initialize, MarketType, PositionDirection, OrderType, OrderTriggerCondition, Wallet, BN } = await import('@drift-labs/sdk');
|
const { DriftClient, initialize, MarketType, PositionDirection, OrderType, OrderTriggerCondition, BN } = await import('@drift-labs/sdk');
|
||||||
const { Connection, Keypair } = await import('@solana/web3.js');
|
const { Connection, Keypair } = await import('@solana/web3.js');
|
||||||
|
|
||||||
// Setup connection and wallet
|
// Setup connection and wallet
|
||||||
@@ -40,7 +40,10 @@ export async function POST(request) {
|
|||||||
|
|
||||||
const privateKeyArray = JSON.parse(process.env.SOLANA_PRIVATE_KEY);
|
const privateKeyArray = JSON.parse(process.env.SOLANA_PRIVATE_KEY);
|
||||||
const keypair = Keypair.fromSecretKey(new Uint8Array(privateKeyArray));
|
const keypair = Keypair.fromSecretKey(new Uint8Array(privateKeyArray));
|
||||||
const wallet = new Wallet(keypair);
|
|
||||||
|
// Use the correct Wallet class like in cleanup endpoint
|
||||||
|
const { default: NodeWallet } = await import('@coral-xyz/anchor/dist/cjs/nodewallet.js');
|
||||||
|
const wallet = new NodeWallet(keypair);
|
||||||
|
|
||||||
// Initialize Drift client
|
// Initialize Drift client
|
||||||
const env = 'mainnet-beta';
|
const env = 'mainnet-beta';
|
||||||
@@ -49,12 +52,9 @@ export async function POST(request) {
|
|||||||
connection,
|
connection,
|
||||||
wallet,
|
wallet,
|
||||||
programID: sdkConfig.DRIFT_PROGRAM_ID,
|
programID: sdkConfig.DRIFT_PROGRAM_ID,
|
||||||
accountSubscription: {
|
opts: {
|
||||||
type: 'polling',
|
commitment: 'confirmed',
|
||||||
accountLoader: {
|
},
|
||||||
commitment: 'confirmed'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await driftClient.subscribe();
|
await driftClient.subscribe();
|
||||||
|
|||||||
@@ -216,11 +216,28 @@ export async function POST(request) {
|
|||||||
|
|
||||||
console.log('✅ Drift order placed:', txSig)
|
console.log('✅ Drift order placed:', txSig)
|
||||||
|
|
||||||
|
// Validate trigger distances before placing SL/TP orders
|
||||||
|
const MIN_TRIGGER_DISTANCE_PERCENT = 2.0; // Minimum 2% distance from current price
|
||||||
|
|
||||||
// Set up stop loss and take profit if specified
|
// Set up stop loss and take profit if specified
|
||||||
let stopLossOrderId = null
|
let stopLossOrderId = null
|
||||||
let takeProfitOrderId = null
|
let takeProfitOrderId = null
|
||||||
|
|
||||||
if (stopLoss) {
|
if (stopLoss) {
|
||||||
|
// Validate stop loss distance
|
||||||
|
const slDistance = Math.abs(stopLoss - currentPrice) / currentPrice * 100;
|
||||||
|
|
||||||
|
if (slDistance < MIN_TRIGGER_DISTANCE_PERCENT) {
|
||||||
|
console.warn(`⚠️ Stop loss too close: ${slDistance.toFixed(2)}% < ${MIN_TRIGGER_DISTANCE_PERCENT}% minimum`);
|
||||||
|
// Adjust stop loss to minimum distance
|
||||||
|
if (direction === PositionDirection.LONG) {
|
||||||
|
stopLoss = currentPrice * (1 - MIN_TRIGGER_DISTANCE_PERCENT / 100);
|
||||||
|
} else {
|
||||||
|
stopLoss = currentPrice * (1 + MIN_TRIGGER_DISTANCE_PERCENT / 100);
|
||||||
|
}
|
||||||
|
console.log(`🔧 Adjusted stop loss to: $${stopLoss.toFixed(4)} (${MIN_TRIGGER_DISTANCE_PERCENT}% distance)`);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const stopLossParams = {
|
const stopLossParams = {
|
||||||
orderType: OrderType.TRIGGER_LIMIT,
|
orderType: OrderType.TRIGGER_LIMIT,
|
||||||
@@ -243,6 +260,20 @@ export async function POST(request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (takeProfit) {
|
if (takeProfit) {
|
||||||
|
// Validate take profit distance
|
||||||
|
const tpDistance = Math.abs(takeProfit - currentPrice) / currentPrice * 100;
|
||||||
|
|
||||||
|
if (tpDistance < MIN_TRIGGER_DISTANCE_PERCENT) {
|
||||||
|
console.warn(`⚠️ Take profit too close: ${tpDistance.toFixed(2)}% < ${MIN_TRIGGER_DISTANCE_PERCENT}% minimum`);
|
||||||
|
// Adjust take profit to minimum distance
|
||||||
|
if (direction === PositionDirection.LONG) {
|
||||||
|
takeProfit = currentPrice * (1 + MIN_TRIGGER_DISTANCE_PERCENT / 100);
|
||||||
|
} else {
|
||||||
|
takeProfit = currentPrice * (1 - MIN_TRIGGER_DISTANCE_PERCENT / 100);
|
||||||
|
}
|
||||||
|
console.log(`🔧 Adjusted take profit to: $${takeProfit.toFixed(4)} (${MIN_TRIGGER_DISTANCE_PERCENT}% distance)`);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const takeProfitParams = {
|
const takeProfitParams = {
|
||||||
orderType: OrderType.TRIGGER_LIMIT,
|
orderType: OrderType.TRIGGER_LIMIT,
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user