Skip to content

Stop-Loss Orders (CoW Protocol) #174

@premiumjibles

Description

@premiumjibles

Summary

Implement stop-loss orders using CoW Protocol. EOA compatible - no smart wallet required.

Background

Stop-loss orders are the inverse of limit orders: sell when price drops below a threshold (vs limit orders which execute when price rises to a target). This is essential for portfolio protection.

CoW Protocol supports stop-loss orders using the same EIP-712 signature flow as limit orders. The key difference is the price direction and order type.

Third-Party API

User Flow

User: "Set a stop-loss on my ETH at $3,000"

Agent: "I'll create a stop-loss order for you:

🛡️ Stop-Loss Order
• Sell: ETH
• Trigger: If ETH drops to $3,000 or below
• Receive: USDC
• Amount: How much ETH do you want to protect?"

User: "All 5 ETH, expire in 30 days"

Agent: [Creates stop-loss via CoW]

"✅ Stop-loss order created!

Selling 5 ETH if price drops to $3,000
Expires: Jan 14, 2026
Track your order: [CoW Explorer Link]

Your position is protected. I'll let you know if it triggers."

Tool Schema

const createStopLossSchema = z.object({
  sellAsset: assetInputSchema.describe('Asset to sell when stop triggers'),
  buyAsset: assetInputSchema.describe('Asset to receive (usually stablecoin)'),
  sellAmount: z.string().describe('Amount to sell in human-readable format'),
  stopPrice: z.string().describe('Price at which to trigger the sale (in buyAsset per sellAsset)'),
  expirationDays: z.number().optional().default(30).describe('Days until order expires. Default 30, max 365.'),
})

const getStopLossOrdersSchema = z.object({
  status: z.enum(['open', 'triggered', 'cancelled', 'expired', 'all']).optional(),
})

const cancelStopLossSchema = z.object({
  orderId: z.string().describe('Order ID to cancel'),
})

Tool Output

interface CreateStopLossOutput {
  success: boolean
  orderId: string
  orderUrl: string // CoW Explorer
  summary: {
    sellAsset: { symbol: string; amount: string; network: string }
    buyAsset: { symbol: string; estimatedAmount: string; network: string }
    stopPrice: string
    currentPrice: string // For context
    percentageFromCurrent: string // e.g., "-15%"
    expiresAt: string
    provider: 'cow'
  }
  signingData: CowOrderSigningData
  needsApproval: boolean
  approvalTx?: TransactionData
}

UI Card

┌─────────────────────────────────────────────┐
│ 🛡️ Stop-Loss Order               [Pending]  │
├─────────────────────────────────────────────┤
│ Sell 5 ETH if price drops to $3,000         │
│                                             │
│ Current: $3,450 (15% above trigger)         │
│ Receive: ~15,000 USDC                       │
│ Expires: Jan 14, 2026                       │
│                                             │
│ [Sign Order]              [Cancel]          │
└─────────────────────────────────────────────┘

Implementation Notes

  • Reuse existing CoW infrastructure from limit orders (SS-5290)
  • Stop-loss is essentially a limit order with kind: 'sell' and price below current market
  • May need to fetch current price to show "percentage from trigger" context
  • Consider adding price validation (warn if stop is very close to current price)

Acceptance Criteria

  • User can create stop-loss orders on ETH, Gnosis, Arbitrum
  • Order executes automatically when price drops to trigger
  • User can view active stop-loss orders
  • User can cancel stop-loss orders
  • UI shows current price vs trigger price context
  • Reuses CoW signing infrastructure from limit orders

Dependencies

  • SS-5290: Limit Order Tool (for CoW infrastructure)
  • SS-5295: Long-Running Order Infrastructure

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions