> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/cowprotocol/cow-sdk/llms.txt
> Use this file to discover all available pages before exploring further.

# Order Management

> Track, monitor, and cancel orders using the CoW Protocol SDK

# Order Management

The SDK provides methods to retrieve order details and cancel orders both off-chain and on-chain.

## Overview

After creating an order, you can:

* **Retrieve order details** - Get full information about an order
* **Cancel off-chain** - Free and fast soft cancellation
* **Cancel on-chain** - Gas-required hard cancellation

<Note>
  All order management methods require an order UID (unique identifier) returned when creating an order.
</Note>

## Retrieving Order Details

Use `getOrder` to fetch complete information about an order:

### Method Signature

```typescript theme={null}
getOrder(params: {
  orderUid: string
  chainId?: SupportedChainId
}): Promise<EnrichedOrder>
```

### Parameters

* `orderUid` - The unique identifier of the order
* `chainId` - (Optional) Chain ID, uses trader params if not provided

### Returns

* `Promise<EnrichedOrder>` - Full order details including status, amounts, and metadata

### Example

```typescript theme={null}
import { TradingSdk, SupportedChainId } from '@cowprotocol/sdk-trading'
import { ViemAdapter } from '@cowprotocol/sdk-viem-adapter'

const sdk = new TradingSdk({
  chainId: SupportedChainId.MAINNET,
  appCode: 'YOUR_APP_CODE',
}, {}, adapter)

const orderUid = '0xd64389693b6cf89ad6c140a113b10df08073e5ef3063d05a02f3f42e1a42f0ad...'

const order = await sdk.getOrder({ orderUid })

console.log('Order status:', order.status)
console.log('Sell amount:', order.sellAmount)
console.log('Buy amount:', order.buyAmount)
console.log('Creation time:', new Date(order.creationDate))
console.log('Expiration:', new Date(order.validTo * 1000))
```

### Order Status Values

The `status` field can be one of:

* `open` - Order is active and waiting to be filled
* `fulfilled` - Order has been completely filled
* `cancelled` - Order has been cancelled
* `expired` - Order has passed its expiration time
* `presignaturePending` - Order is waiting for pre-signature (smart contract wallets)

### EnrichedOrder Properties

```typescript theme={null}
interface EnrichedOrder {
  uid: string
  status: OrderStatus
  owner: string
  creationDate: string
  sellToken: string
  sellAmount: string
  sellAmountBeforeFee: string
  buyToken: string
  buyAmount: string
  validTo: number
  appData: string
  feeAmount: string
  kind: 'sell' | 'buy'
  partiallyFillable: boolean
  signature: string
  signingScheme: SigningScheme
  receiver: string
  // ... and more fields
}
```

### Tracking Order Progress

```typescript theme={null}
async function trackOrder(sdk: TradingSdk, orderUid: string) {
  const order = await sdk.getOrder({ orderUid })
  
  console.log(`Order ${orderUid}:`)
  console.log(`  Status: ${order.status}`)
  console.log(`  Sell Token: ${order.sellToken}`)
  console.log(`  Sell Amount: ${order.sellAmount}`)
  console.log(`  Buy Token: ${order.buyToken}`)
  console.log(`  Buy Amount: ${order.buyAmount}`)
  
  // Check if order is partially filled
  if (order.partiallyFillable && order.status === 'open') {
    const executedAmount = BigInt(order.sellAmount) - BigInt(order.sellAmountBeforeFee)
    console.log(`  Executed: ${executedAmount}`)
  }
  
  // Check time until expiration
  const now = Math.floor(Date.now() / 1000)
  const timeLeft = order.validTo - now
  
  if (timeLeft > 0) {
    console.log(`  Time remaining: ${timeLeft} seconds`)
  } else {
    console.log(`  Order expired`)
  }
  
  return order
}
```

## Off-Chain Order Cancellation

Off-chain cancellation is the recommended way to cancel orders. It's free, fast, and doesn't require gas.

### Method Signature

```typescript theme={null}
offChainCancelOrder(params: {
  orderUid: string
  chainId?: SupportedChainId
  signer?: SignerLike
}): Promise<boolean>
```

### Parameters

* `orderUid` - The unique identifier of the order to cancel
* `chainId` - (Optional) Chain ID, uses trader params if not provided
* `signer` - (Optional) Custom signer, uses trader params signer if not provided

### Returns

* `Promise<boolean>` - True if cancellation was successful

### Example

```typescript theme={null}
import { TradingSdk, SupportedChainId } from '@cowprotocol/sdk-trading'

const sdk = new TradingSdk({
  chainId: SupportedChainId.MAINNET,
  appCode: 'YOUR_APP_CODE',
}, {}, adapter)

const orderUid = '0xd64389693b6cf89ad6c140a113b10df08073e5ef3063d05a02f3f42e1a42f0ad...'

try {
  const success = await sdk.offChainCancelOrder({ orderUid })
  
  if (success) {
    console.log('Order cancelled successfully (off-chain)')
  }
} catch (error) {
  console.error('Failed to cancel order:', error)
}
```

### How It Works

<Steps>
  <Step title="Sign cancellation message">
    The SDK creates and signs a cancellation message using EIP-712
  </Step>

  <Step title="Send to order book">
    The signed cancellation is sent to the CoW Protocol order book API
  </Step>

  <Step title="Order removed">
    The order book marks the order as cancelled and stops including it in solutions
  </Step>
</Steps>

<Note>
  **Soft cancel**: Off-chain cancellation is a "soft" cancel. While the order book will stop trying to fill the order, the order signature remains valid on-chain. For complete security, use on-chain cancellation.
</Note>

### When to Use Off-Chain Cancellation

* ✅ Regular orders that you want to cancel quickly
* ✅ When you need to update order parameters (cancel and recreate)
* ✅ When minimizing costs is important
* ❌ Not suitable if you need absolute guarantee the order won't be filled

## On-Chain Order Cancellation

On-chain cancellation provides a hard guarantee that the order cannot be filled. It requires gas but is the most secure method.

### Method Signature

```typescript theme={null}
onChainCancelOrder(params: {
  orderUid: string
  chainId?: SupportedChainId
  signer?: SignerLike
}): Promise<string>
```

### Parameters

* `orderUid` - The unique identifier of the order to cancel
* `chainId` - (Optional) Chain ID, uses trader params if not provided
* `signer` - (Optional) Custom signer, uses trader params signer if not provided

### Returns

* `Promise<string>` - Transaction hash of the cancellation

### Example

```typescript theme={null}
import { TradingSdk, SupportedChainId } from '@cowprotocol/sdk-trading'

const sdk = new TradingSdk({
  chainId: SupportedChainId.MAINNET,
  appCode: 'YOUR_APP_CODE',
}, {}, adapter)

const orderUid = '0xd64389693b6cf89ad6c140a113b10df08073e5ef3063d05a02f3f42e1a42f0ad...'

try {
  const txHash = await sdk.onChainCancelOrder({ orderUid })
  
  console.log('Cancellation transaction:', txHash)
  
  // Wait for transaction confirmation
  await publicClient.waitForTransactionReceipt({ hash: txHash })
  console.log('Order cancelled on-chain')
} catch (error) {
  console.error('Failed to cancel order on-chain:', error)
}
```

### How It Works

The SDK automatically detects the order type and uses the appropriate contract:

* **Regular orders**: Calls `invalidateOrder()` on the Settlement contract
* **ETH-Flow orders**: Calls `invalidateOrder()` on the EthFlow contract

### Gas Costs

On-chain cancellation costs gas:

* **Regular orders**: \~45,000-60,000 gas
* **ETH-Flow orders**: \~50,000-70,000 gas

At 50 gwei gas price and \$2000 ETH:

* Regular: \~$4.50-$6.00
* ETH-Flow: \~$5.00-$7.00

### When to Use On-Chain Cancellation

* ✅ When you need absolute certainty the order won't execute
* ✅ For high-value orders where security is paramount
* ✅ When you suspect your off-chain cancellation might not be respected
* ✅ For orders that others might try to fill maliciously
* ❌ Not cost-effective for small orders

## Comparing Cancellation Methods

<Tabs>
  <Tab title="Off-Chain">
    **Advantages:**

    * Free (no gas cost)
    * Instant
    * Simple to use
    * Recommended for most cases

    **Disadvantages:**

    * "Soft" cancel only
    * Requires order book cooperation
    * Signature remains valid on-chain

    **Best for:**

    * Regular order cancellations
    * Cost-sensitive applications
    * Quick order updates
  </Tab>

  <Tab title="On-Chain">
    **Advantages:**

    * "Hard" cancel with on-chain guarantee
    * Cannot be bypassed
    * Most secure method
    * Works without order book

    **Disadvantages:**

    * Requires gas payment
    * Slower (must wait for tx confirmation)
    * More complex

    **Best for:**

    * High-value orders
    * Security-critical situations
    * When off-chain cancel fails
  </Tab>
</Tabs>

## Complete Example: Order Lifecycle

Here's a complete example showing order creation, tracking, and cancellation:

```typescript theme={null}
import { 
  TradingSdk, 
  SupportedChainId, 
  OrderKind,
  TradeParameters 
} from '@cowprotocol/sdk-trading'
import { parseUnits } from 'viem'
import { ViemAdapter } from '@cowprotocol/sdk-viem-adapter'

const sdk = new TradingSdk({
  chainId: SupportedChainId.MAINNET,
  appCode: 'YOUR_APP_CODE',
}, {}, adapter)

// Step 1: Create an order
const parameters: TradeParameters = {
  kind: OrderKind.SELL,
  sellToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
  sellTokenDecimals: 6,
  buyToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
  buyTokenDecimals: 18,
  amount: parseUnits('1000', 6).toString(), // 1000 USDC
  validFor: 3600, // 1 hour
}

const { orderId } = await sdk.postSwapOrder(parameters)
console.log('Order created:', orderId)

// Step 2: Monitor the order
const checkOrder = async () => {
  const order = await sdk.getOrder({ orderUid: orderId })
  console.log('Order status:', order.status)
  return order
}

// Check order status every 30 seconds
const intervalId = setInterval(async () => {
  const order = await checkOrder()
  
  if (order.status === 'fulfilled') {
    console.log('Order filled!')
    clearInterval(intervalId)
  } else if (order.status === 'expired') {
    console.log('Order expired')
    clearInterval(intervalId)
  }
}, 30000)

// Step 3: Cancel the order if needed
const cancelOrder = async () => {
  try {
    // Try off-chain cancellation first (free)
    console.log('Attempting off-chain cancellation...')
    const success = await sdk.offChainCancelOrder({ orderUid: orderId })
    
    if (success) {
      console.log('Order cancelled (off-chain)')
      clearInterval(intervalId)
    }
  } catch (error) {
    console.error('Off-chain cancellation failed, trying on-chain...')
    
    // Fall back to on-chain cancellation
    const txHash = await sdk.onChainCancelOrder({ orderUid: orderId })
    console.log('On-chain cancellation transaction:', txHash)
    
    await publicClient.waitForTransactionReceipt({ hash: txHash })
    console.log('Order cancelled (on-chain)')
    clearInterval(intervalId)
  }
}

// Call cancelOrder() when user clicks cancel button
```

## Batch Order Monitoring

Monitor multiple orders efficiently:

```typescript theme={null}
interface OrderTracker {
  orderId: string
  status: string
  checkCount: number
}

async function monitorOrders(
  sdk: TradingSdk,
  orderIds: string[]
): Promise<Map<string, OrderTracker>> {
  const trackers = new Map<string, OrderTracker>()
  
  for (const orderId of orderIds) {
    trackers.set(orderId, {
      orderId,
      status: 'unknown',
      checkCount: 0,
    })
  }
  
  const updateStatuses = async () => {
    for (const [orderId, tracker] of trackers) {
      try {
        const order = await sdk.getOrder({ orderUid: orderId })
        tracker.status = order.status
        tracker.checkCount++
        
        console.log(`Order ${orderId.slice(0, 10)}... - ${order.status}`)
      } catch (error) {
        console.error(`Failed to get order ${orderId}:`, error)
      }
    }
  }
  
  // Check every minute
  const intervalId = setInterval(updateStatuses, 60000)
  
  // Initial check
  await updateStatuses()
  
  return trackers
}

// Usage
const orderIds = [
  '0xabc123...',
  '0xdef456...',
  '0xghi789...',
]

const trackers = await monitorOrders(sdk, orderIds)
```

## Best Practices

1. **Always store order IDs**: Save order UIDs for future reference
2. **Monitor important orders**: Track order status for large trades
3. **Try off-chain first**: Start with off-chain cancellation to save gas
4. **Handle errors gracefully**: Orders might already be filled when you try to cancel
5. **Set reasonable expiration**: Don't set validFor too long if you might want to cancel
6. **Check status before operations**: Verify order state before cancelling
7. **Use appropriate cancellation**: Choose based on order value and security needs

## Common Issues and Solutions

### Order Not Found

**Problem**: `getOrder` throws "Order not found" error.

**Solution**:

* Verify the order UID is correct
* Ensure the order has been created (wait a few seconds after posting)
* Check you're using the correct chain ID

### Cancellation Fails

**Problem**: Off-chain cancellation returns false or throws error.

**Solution**:

* Check if the order is already filled or expired
* Verify you're using the same signer that created the order
* Try on-chain cancellation as a fallback

### Order Still Executes After Cancellation

**Problem**: Order filled despite cancellation.

**Solution**:

* This can happen with off-chain cancellation if there's a race condition
* Use on-chain cancellation for critical orders
* Always wait for confirmation before assuming cancellation succeeded

## Next Steps

* Learn about [Creating Swap Orders](/guides/creating-swap-orders) to create orders
* See [Creating Limit Orders](/guides/creating-limit-orders) for price-specific orders
* Explore [Token Approvals](/guides/token-approvals) for managing approvals
