feat: fix orphaned order detection and enhance automation UI
- Fixed Drift orders API to handle new object-based status format
- Updated cleanup API to properly detect orphaned TAKE PROFIT orders
- Changed status filtering from order.status === 0 to order.status.hasOwnProperty('open')
- Restored automation-v2 page with emergency stop functionality
- Added position monitor integration with real-time cleanup status
- Enhanced UI with emoji indicators and better status display
- Added emergency stop API endpoint for immediate trading halt
- Enhanced orphaned order detection for lingering SL/TP orders
- Added comprehensive debug logging for order processing
- Improved error handling and status reporting
- Real-time cleanup reporting in position monitor
Verified working:
- Orders API correctly detects active orders with new Drift format
- Cleanup system successfully processes orphaned orders
- Position monitor shows accurate cleanup status
- Emergency stop functionality integrated
This commit is contained in:
@@ -60,12 +60,37 @@ export async function GET() {
|
||||
// Get open orders
|
||||
const orders = userAccount.orders || []
|
||||
|
||||
// Filter for active orders (status 0 = open)
|
||||
const activeOrders = orders.filter(order =>
|
||||
order.status === 0 && !order.baseAssetAmount.isZero()
|
||||
)
|
||||
// Debug: log ALL orders to see what we have
|
||||
console.log(`📋 Raw orders length: ${orders.length}`)
|
||||
orders.forEach((order, index) => {
|
||||
if (!order.baseAssetAmount.isZero()) {
|
||||
console.log(`📋 Order ${index}:`, {
|
||||
orderId: order.orderId,
|
||||
status: order.status,
|
||||
orderType: order.orderType,
|
||||
baseAssetAmount: order.baseAssetAmount.toString(),
|
||||
price: order.price ? order.price.toString() : null,
|
||||
triggerPrice: order.triggerPrice ? order.triggerPrice.toString() : null,
|
||||
reduceOnly: order.reduceOnly,
|
||||
marketIndex: order.marketIndex
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Filter for active orders - handle both numeric and object status formats
|
||||
const activeOrders = orders.filter(order => {
|
||||
if (order.baseAssetAmount.isZero()) return false
|
||||
|
||||
// Handle object-based status (new format)
|
||||
if (typeof order.status === 'object') {
|
||||
return order.status.hasOwnProperty('open')
|
||||
}
|
||||
|
||||
// Handle numeric status (old format)
|
||||
return order.status === 0
|
||||
})
|
||||
|
||||
// Show ALL orders for debugging - not just active ones
|
||||
// Show ALL orders with non-zero amounts for debugging
|
||||
const allOrders = orders.filter(order =>
|
||||
!order.baseAssetAmount.isZero() // Only filter out empty orders
|
||||
)
|
||||
@@ -74,28 +99,61 @@ export async function GET() {
|
||||
|
||||
// Debug: log all order statuses
|
||||
const statusCounts = orders.reduce((acc, order) => {
|
||||
acc[order.status] = (acc[order.status] || 0) + 1
|
||||
if (!order.baseAssetAmount.isZero()) {
|
||||
acc[order.status] = (acc[order.status] || 0) + 1
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
console.log('📊 Order status breakdown:', statusCounts)
|
||||
|
||||
const formattedOrders = activeOrders.map(order => {
|
||||
const formattedOrders = allOrders.map(order => {
|
||||
const marketIndex = order.marketIndex
|
||||
const symbol = ['SOL', 'BTC', 'ETH', 'APT', 'AVAX', 'BNB', 'MATIC', 'ARB', 'DOGE', 'OP'][marketIndex] || `UNKNOWN_${marketIndex}`
|
||||
|
||||
let orderType = 'UNKNOWN'
|
||||
switch (order.orderType) {
|
||||
case 0: orderType = 'MARKET'; break
|
||||
case 1: orderType = 'LIMIT'; break
|
||||
case 2: orderType = 'TRIGGER_MARKET'; break
|
||||
case 3: orderType = 'TRIGGER_LIMIT'; break
|
||||
case 4: orderType = 'ORACLE'; break
|
||||
// Handle object-based orderType
|
||||
if (typeof order.orderType === 'object') {
|
||||
if (order.orderType.market !== undefined) orderType = 'MARKET'
|
||||
else if (order.orderType.limit !== undefined) orderType = 'LIMIT'
|
||||
else if (order.orderType.triggerMarket !== undefined) orderType = 'TRIGGER_MARKET'
|
||||
else if (order.orderType.triggerLimit !== undefined) orderType = 'TRIGGER_LIMIT'
|
||||
else if (order.orderType.oracle !== undefined) orderType = 'ORACLE'
|
||||
} else {
|
||||
// Handle numeric orderType
|
||||
switch (order.orderType) {
|
||||
case 0: orderType = 'MARKET'; break
|
||||
case 1: orderType = 'LIMIT'; break
|
||||
case 2: orderType = 'TRIGGER_MARKET'; break
|
||||
case 3: orderType = 'TRIGGER_LIMIT'; break
|
||||
case 4: orderType = 'ORACLE'; break
|
||||
}
|
||||
}
|
||||
|
||||
let direction = 'UNKNOWN'
|
||||
switch (order.direction) {
|
||||
case 0: direction = 'LONG'; break
|
||||
case 1: direction = 'SHORT'; break
|
||||
// Handle object-based direction
|
||||
if (typeof order.direction === 'object') {
|
||||
if (order.direction.long !== undefined) direction = 'LONG'
|
||||
else if (order.direction.short !== undefined) direction = 'SHORT'
|
||||
} else {
|
||||
// Handle numeric direction
|
||||
switch (order.direction) {
|
||||
case 0: direction = 'LONG'; break
|
||||
case 1: direction = 'SHORT'; break
|
||||
}
|
||||
}
|
||||
|
||||
// Get status as string
|
||||
let statusString = 'UNKNOWN'
|
||||
if (typeof order.status === 'object') {
|
||||
if (order.status.open !== undefined) statusString = 'OPEN'
|
||||
else if (order.status.filled !== undefined) statusString = 'FILLED'
|
||||
else if (order.status.canceled !== undefined) statusString = 'CANCELED'
|
||||
} else {
|
||||
switch (order.status) {
|
||||
case 0: statusString = 'OPEN'; break
|
||||
case 1: statusString = 'FILLED'; break
|
||||
case 2: statusString = 'CANCELED'; break
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -107,21 +165,30 @@ export async function GET() {
|
||||
price: order.price ? (Number(order.price) / 1e6).toFixed(4) : null,
|
||||
triggerPrice: order.triggerPrice ? (Number(order.triggerPrice) / 1e6).toFixed(4) : null,
|
||||
reduceOnly: order.reduceOnly,
|
||||
status: order.status,
|
||||
marketIndex
|
||||
status: statusString,
|
||||
marketIndex,
|
||||
isActive: typeof order.status === 'object' ? order.status.hasOwnProperty('open') : order.status === 0,
|
||||
raw: {
|
||||
status: order.status,
|
||||
orderType: order.orderType,
|
||||
direction: order.direction,
|
||||
baseAssetAmount: order.baseAssetAmount.toString()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const ordersResult = {
|
||||
success: true,
|
||||
orders: formattedOrders,
|
||||
totalOrders: activeOrders.length,
|
||||
totalOrders: allOrders.length, // Return ALL orders, not just active
|
||||
activeOrders: activeOrders.length, // But also show active count
|
||||
timestamp: Date.now(),
|
||||
rpcEndpoint: getRpcStatus().currentEndpoint,
|
||||
details: {
|
||||
wallet: keypair.publicKey.toString(),
|
||||
totalOrderSlots: orders.length,
|
||||
activeOrderSlots: activeOrders.length
|
||||
activeOrderSlots: activeOrders.length,
|
||||
allOrderSlots: allOrders.length
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user