Skip to main content

Create your first order

This guide walks you through creating and signing a CoW Protocol order using the TypeScript SDK.

Prerequisites

Make sure you have:
  • Installed @cowprotocol/contracts and ethers@^5.4.0 (see installation)
  • A wallet or signer (private key, mnemonic, or provider-connected signer)
  • Token addresses for the tokens you want to trade

Setup

First, import the required functions and types:
import { ethers } from "ethers";
import {
  domain,
  Order,
  OrderKind,
  OrderBalance,
  signOrder,
  SigningScheme,
  computeOrderUid,
} from "@cowprotocol/contracts";

Define your order

Create an order object specifying what you want to trade:
// Example: Selling 1 DAI for at least 0.0005 WETH
const order: Order = {
  sellToken: "0x6B175474E89094C44Da98b954EedeAC495271d0F", // DAI on mainnet
  buyToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",  // WETH on mainnet
  receiver: ethers.constants.AddressZero, // Optional: defaults to order owner
  sellAmount: ethers.utils.parseEther("1"),
  buyAmount: ethers.utils.parseEther("0.0005"),
  validTo: Math.floor(Date.now() / 1000) + 3600, // Valid for 1 hour
  appData: "0x0000000000000000000000000000000000000000000000000000000000000000",
  feeAmount: "0", // Fee paid to the protocol
  kind: OrderKind.SELL,
  partiallyFillable: false,
  sellTokenBalance: OrderBalance.ERC20,
  buyTokenBalance: OrderBalance.ERC20,
};
Order kinds:
  • OrderKind.SELL: Sell exactly sellAmount, receive at least buyAmount
  • OrderKind.BUY: Buy exactly buyAmount, spend at most sellAmount

Create the domain separator

The domain separator ensures orders are valid only for a specific chain and contract:
const chainId = 1; // Mainnet
const settlementContract = "0x9008D19f58AAbD9eD0D60971565AA8510560ab41"; // GPv2Settlement on mainnet

const domainSeparator = domain(chainId, settlementContract);
Always use the correct settlement contract address for your target network. Using the wrong address will result in invalid signatures.

Sign the order

Sign the order using your wallet:
// Using a wallet from private key
const wallet = new ethers.Wallet("0x...");

const signature = await signOrder(
  domainSeparator,
  order,
  wallet,
  SigningScheme.EIP712
);

console.log("Signature:", signature);
// { scheme: 0, data: "0x..." }

Compute the order UID

Every order has a unique identifier used for tracking:
const owner = await wallet.getAddress();
const orderUid = computeOrderUid(domainSeparator, order, owner);

console.log("Order UID:", orderUid);
// "0x..." (56 bytes)
The order UID is derived from the order hash, owner address, and validity timestamp. It uniquely identifies the order on-chain.

Complete example

Here’s a complete working example:
import { ethers } from "ethers";
import {
  domain,
  Order,
  OrderKind,
  OrderBalance,
  signOrder,
  SigningScheme,
  computeOrderUid,
} from "@cowprotocol/contracts";

async function createAndSignOrder() {
  // Setup
  const wallet = new ethers.Wallet("YOUR_PRIVATE_KEY");
  const chainId = 1;
  const settlementContract = "0x9008D19f58AAbD9eD0D60971565AA8510560ab41";
  
  // Create domain
  const domainSeparator = domain(chainId, settlementContract);
  
  // Define order
  const order: Order = {
    sellToken: "0x6B175474E89094C44Da98b954EedeAC495271d0F",
    buyToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    receiver: ethers.constants.AddressZero,
    sellAmount: ethers.utils.parseEther("1"),
    buyAmount: ethers.utils.parseEther("0.0005"),
    validTo: Math.floor(Date.now() / 1000) + 3600,
    appData: "0x0000000000000000000000000000000000000000000000000000000000000000",
    feeAmount: "0",
    kind: OrderKind.SELL,
    partiallyFillable: false,
    sellTokenBalance: OrderBalance.ERC20,
    buyTokenBalance: OrderBalance.ERC20,
  };
  
  // Sign order
  const signature = await signOrder(
    domainSeparator,
    order,
    wallet,
    SigningScheme.EIP712
  );
  
  // Compute order UID
  const owner = await wallet.getAddress();
  const orderUid = computeOrderUid(domainSeparator, order, owner);
  
  console.log("Order created and signed successfully!");
  console.log("Order UID:", orderUid);
  console.log("Signature:", signature);
  
  return { order, signature, orderUid };
}

createAndSignOrder().catch(console.error);

Signing schemes

CoW Protocol supports multiple signing schemes:
1

EIP712 (recommended)

SigningScheme.EIP712
Provides the best UX with structured data visible to users in their wallet.
2

ETHSIGN

SigningScheme.ETHSIGN
Falls back to eth_sign for wallets that don’t support EIP-712.
3

EIP1271

SigningScheme.EIP1271
For smart contract wallets that implement EIP-1271.
4

PRESIGN

SigningScheme.PRESIGN
For on-chain order placement without off-chain signatures.

Next steps

Now that you can create and sign orders, explore advanced features:
  • Partially fillable orders: Allow orders to be filled in multiple trades
  • Balancer Vault integration: Use internal balances for cheaper trading
  • Settlement encoding: Build complete settlement calldata for solvers
  • Order cancellation: Cancel orders on-chain when needed

View on GitHub

Explore the full source code and examples

Build docs developers (and LLMs) love