Skip to main content

Documentation Index

Fetch the complete documentation index at: https://cowswap-mintlify-docs-quality-audit-1774257282.mintlify.app/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.

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
All order management methods require an order UID (unique identifier) returned when creating an order.

Retrieving Order Details

Use getOrder to fetch complete information about an order:

Method Signature

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

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:
StatusDescription
openOrder is active and waiting to be filled
fulfilledOrder has been completely filled
cancelledOrder has been cancelled
expiredOrder has passed its expiration time
presignaturePendingOrder is waiting for pre-signature (smart contract wallets)

EnrichedOrder Properties

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

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

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

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

  1. Sign cancellation message - The SDK creates and signs a cancellation message using EIP-712
  2. Send to order book - The signed cancellation is sent to the CoW Protocol order book API
  3. Order removed - The order book marks the order as cancelled and stops including it in solutions
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.

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

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

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:
Order TypeGas UsageEstimated Cost (50 gwei, $2000 ETH)
Regular orders~45,000-60,000~4.504.50-6.00
ETH-Flow orders~50,000-70,000~5.005.00-7.00

Comparing Cancellation Methods

FeatureOff-ChainOn-Chain
CostFree (no gas)Requires gas payment
SpeedInstantMust wait for tx confirmation
GuaranteeSoft cancel onlyHard cancel with on-chain proof
SecurityRequires order book cooperationCannot be bypassed
Best forRegular cancellationsHigh-value or security-critical

Complete Example: Order Lifecycle

Here’s a complete example showing order creation, tracking, and cancellation:
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:
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

Last modified on March 23, 2026