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:
EIP712 (recommended)
Provides the best UX with structured data visible to users in their wallet. ETHSIGN
Falls back to eth_sign for wallets that don’t support EIP-712. EIP1271
For smart contract wallets that implement EIP-1271. 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