Skip to main content

Overview

CoW Protocol supports different order types to accommodate various trading strategies. Understanding these types is essential for building effective trading applications.

Order Kind

Every order has a kind that determines whether you’re specifying the exact sell or buy amount:

SELL Orders

A sell order specifies the exact amount of tokens you want to sell.
import { OrderKind } from '@cowprotocol/cow-sdk'

const sellOrder = {
  kind: OrderKind.SELL,
  sellToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
  buyToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',  // USDC
  sellAmount: '1000000000000000000', // Sell exactly 1 WETH
  buyAmount: '3000000000',            // Receive at least 3000 USDC
  // ...
}
For sell orders:
  • sellAmount is the exact amount you’re selling
  • buyAmount is the minimum amount you’ll accept
  • The actual execution may give you more than buyAmount (positive slippage)

BUY Orders

A buy order specifies the exact amount of tokens you want to receive.
import { OrderKind } from '@cowprotocol/cow-sdk'

const buyOrder = {
  kind: OrderKind.BUY,
  sellToken: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // WETH
  buyToken: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',  // USDC
  sellAmount: '1000000000000000000', // Spend at most 1 WETH
  buyAmount: '3000000000',            // Buy exactly 3000 USDC
  // ...
}
For buy orders:
  • buyAmount is the exact amount you’re buying
  • sellAmount is the maximum amount you’ll spend
  • The actual execution may cost less than sellAmount (positive slippage)

Execution Modes

Orders can be configured as either fill-or-kill or partially fillable:

Fill-or-Kill Orders

A fill-or-kill order must be executed entirely in a single settlement or not at all.
const fillOrKillOrder = {
  // ... other order parameters
  partiallyFillable: false,  // Default
}
Use fill-or-kill when:
  • You need the entire order executed atomically
  • Trading smaller amounts where partial fills aren’t practical
  • You want predictable, all-or-nothing execution

Partially Fillable Orders

A partially fillable order can be executed across multiple settlements until the full amount is filled or the order expires.
const partiallyFillableOrder = {
  // ... other order parameters
  partiallyFillable: true,
}
Use partially fillable when:
  • Trading large amounts that might be hard to fill at once
  • You want to capture liquidity as it becomes available
  • Building limit orders that execute over time

Swap Orders vs Limit Orders

Swap Orders (Market Orders)

Swap orders execute immediately at the best available price with slippage protection.
import { TradingSdk, OrderKind } from '@cowprotocol/cow-sdk'

const sdk = new TradingSdk({
  chainId: 1,
  appCode: 'MyApp',
  signer,
})

// Get a quote and post a swap order
const { postSwapOrderFromQuote } = await sdk.getQuote({
  chainId: 1,
  kind: OrderKind.SELL,
  owner: '0x...',
  amount: '1000000000000000000',
  sellToken: WETH_ADDRESS,
  sellTokenDecimals: 18,
  buyToken: USDC_ADDRESS,
  buyTokenDecimals: 6,
  slippageBps: 50, // 0.5% slippage tolerance
})

const orderId = await postSwapOrderFromQuote({})
Characteristics:
  • Execute at current market conditions
  • Have slippage tolerance (e.g., 0.5%)
  • Typically fill-or-kill
  • Short validity period (e.g., 20 minutes)
  • Class: "market"

Limit Orders

Limit orders execute only when your specified price is met or exceeded.
import { TradingSdk, OrderKind } from '@cowprotocol/cow-sdk'

const limitOrder = await sdk.postLimitOrder({
  chainId: 1,
  kind: OrderKind.SELL,
  owner: '0x...',
  sellToken: WETH_ADDRESS,
  sellTokenDecimals: 18,
  buyToken: USDC_ADDRESS,
  buyTokenDecimals: 6,
  sellAmount: '1000000000000000000', // Sell 1 WETH
  buyAmount: '3500000000',            // For at least 3500 USDC
  validTo: Math.floor(Date.now() / 1000) + 86400 * 7, // Valid for 7 days
  partiallyFillable: true, // Allow partial fills
})
Characteristics:
  • Execute at your specified limit price or better
  • No slippage tolerance
  • Can be partially fillable
  • Longer validity period (hours to days)
  • Class: "limit"

Order Parameters

All orders share these core parameters:
sellToken
string
required
Address of the token being sold
buyToken
string
required
Address of the token being bought
sellAmount
string
required
Amount of sell token (in wei/smallest unit)
buyAmount
string
required
Amount of buy token (in wei/smallest unit)
validTo
number
required
Unix timestamp when the order expires
appData
string
required
32-byte hash of order metadata. See App Data
feeAmount
string
required
Protocol fee amount in sell token
kind
OrderKind
required
Order kind: OrderKind.SELL or OrderKind.BUY
partiallyFillable
boolean
required
Whether the order can be partially filled
receiver
string
default:"owner"
Address to receive the bought tokens (defaults to order owner)
sellTokenBalance
OrderBalance
default:"erc20"
How to withdraw sell tokens: erc20, external, or internal (Balancer Vault)
buyTokenBalance
OrderBalance
default:"erc20"
How to receive buy tokens: erc20 or internal (Balancer Vault)

Token Balance Sources

Orders can interact with different token balance sources:

ERC20 Balance (Default)

import { OrderBalance } from '@cowprotocol/sdk-contracts-ts'

const order = {
  // ... other parameters
  sellTokenBalance: OrderBalance.ERC20, // Default
  buyTokenBalance: OrderBalance.ERC20,  // Default
}
Standard ERC20 token balances with direct allowance to the CoW Protocol settlement contract.

Balancer Vault Balances

For advanced use cases with Balancer Vault integration:
const order = {
  // ... other parameters
  sellTokenBalance: OrderBalance.INTERNAL, // Use Balancer internal balance
  buyTokenBalance: OrderBalance.INTERNAL,  // Receive to internal balance
}
Most applications use the default ERC20 balance mode. Balancer Vault integration is for advanced scenarios.

Order Lifecycle

1

Order Creation

Create and sign an order with your desired parameters
2

Order Submission

Submit the signed order to the CoW Protocol API
3

Order Discovery

Solvers discover your order and compete to find the best execution
4

Order Execution

The winning solver executes your order on-chain in a batch settlement
5

Order Completion

Tokens are transferred and the order is marked as filled

Practical Examples

// Sell exactly 1 WETH for at least 3000 USDC
const { postSwapOrderFromQuote } = await sdk.getQuote({
  kind: OrderKind.SELL,
  amount: '1000000000000000000', // 1 WETH
  sellToken: WETH,
  buyToken: USDC,
  slippageBps: 50,
  // ...
})

Best Practices

Use SELL for Market Orders

Most users know how much they want to sell. Use OrderKind.SELL for simpler UX.

Set Reasonable Validity

Market orders: 10-30 minutes. Limit orders: hours to days based on volatility.

Partial Fills for Large Orders

Enable partiallyFillable: true for large orders to improve fill rates.

Monitor Order Status

Poll the OrderBook API to track order status and fills over time.

Next Steps

Signing Schemes

Learn how orders are signed

App Data

Add metadata to your orders

Trading SDK

Start building with the SDK

Build docs developers (and LLMs) love