📚 Docs website
Statements | Branches | Functions | Lines |
---|---|---|---|
Usage examples:
- React (ethers v5): https://github.com/cowprotocol/cow-sdk/tree/main/examples/react/ethers5
- React (ethers v6): https://github.com/cowprotocol/cow-sdk/tree/main/examples/react/ethers6
- React (viem): https://github.com/cowprotocol/cow-sdk/tree/main/examples/react/viem
- Node.js (ethers v5): https://github.com/cowprotocol/cow-sdk/blob/main/examples/nodejs/ethers5/src/index.ts
- Node.js (ethers v6): https://github.com/cowprotocol/cow-sdk/blob/main/examples/nodejs/ethers6/src/index.ts
- Node.js (viem): https://github.com/cowprotocol/cow-sdk/blob/main/examples/nodejs/viem/src/index.ts
pnpm add @cowprotocol/cow-sdk
The CoW SDK offers a unified interface through CowSdk
that provides access to all modules in a single instance:
import { CowSdk, SupportedChainId, OrderKind } from '@cowprotocol/cow-sdk'
import { ViemAdapter } from '@cowprotocol/sdk-viem-adapter'
import { createPublicClient, http, privateKeyToAccount } from 'viem'
import { sepolia } from 'viem/chains'
// There are EthersV5Adapter and EthersV6Adapter as well
// @cowprotocol/sdk-ethers-v5-adapter, @cowprotocol/sdk-ethers-v6-adapter
const adapter = new ViemAdapter({
provider: createPublicClient({
chain: sepolia,
transport: http('YOUR_RPC_URL')
}),
signer: privateKeyToAccount('YOUR_PRIVATE_KEY' as `0x${string}`)
})
// Initialize the unified SDK
const sdk = new CowSdk({
chainId: SupportedChainId.SEPOLIA,
adapter,
tradingOptions: {
traderParams: {
appCode: 'YOUR_APP_CODE',
},
options: {
chainId: SupportedChainId.SEPOLIA,
},
},
})
const orderId = await sdk.trading.postSwapOrder(parameters)
const orders = await sdk.orderBook.getOrders({ owner: address })
const totals = await sdk.subgraph?.getTotals()
You can also import specific modules directly from the umbrella SDK:
import { TradingSdk, SupportedChainId } from '@cowprotocol/cow-sdk'
import { ViemAdapter } from '@cowprotocol/sdk-viem-adapter'
import { createPublicClient, http, privateKeyToAccount } from 'viem'
import { sepolia } from 'viem/chains'
// There are EthersV5Adapter and EthersV6Adapter as well
// @cowprotocol/sdk-ethers-v5-adapter, @cowprotocol/sdk-ethers-v6-adapter
const adapter = new ViemAdapter({
provider: createPublicClient({
chain: sepolia,
transport: http('YOUR_RPC_URL')
}),
signer: privateKeyToAccount('YOUR_PRIVATE_KEY' as `0x${string}`)
})
const trading = new TradingSdk(
{ appCode: 'YOUR_APP_CODE' }, // trader params
{ chainId: SupportedChainId.SEPOLIA }, // options
adapter, // adapter required
)
const orderId = await trading.postSwapOrder(parameters)
For direct use of individual packages:
import { TradingSdk } from '@cowprotocol/sdk-trading'
import { EthersV6Adapter } from '@cowprotocol/sdk-ethers-v6-adapter'
import { JsonRpcProvider, Wallet } from 'ethers'
const provider = new JsonRpcProvider('YOUR_RPC_URL')
const wallet = new Wallet('YOUR_PRIVATE_KEY', provider)
const adapter = new EthersV6Adapter({ provider, signer: wallet })
const trading = new TradingSdk(
{ appCode: 'YOUR_APP_CODE' }, // trader params
{ chainId: SupportedChainId.SEPOLIA }, // options
adapter, // adapter required
)
const orderId = await trading.postSwapOrder(parameters)
The CoW SDK supports multiple blockchain adapters to work with different Web3 libraries. You need to install and configure one of the following adapters:
- EthersV6Adapter - For ethers.js v6
- EthersV5Adapter - For ethers.js v5
- ViemAdapter - For viem
# For ethers v6
pnpm add @cowprotocol/sdk-ethers-v6-adapter ethers
# For ethers v5
pnpm add @cowprotocol/sdk-ethers-v5-adapter ethers@^5.7.0
# For viem
pnpm add @cowprotocol/sdk-viem-adapter viem
import { EthersV6Adapter } from '@cowprotocol/sdk-ethers-v6-adapter'
import { JsonRpcProvider, Wallet } from 'ethers'
const provider = new JsonRpcProvider('YOUR_RPC_URL')
const wallet = new Wallet('YOUR_PRIVATE_KEY', provider)
const adapter = new EthersV6Adapter({ provider, signer: wallet })
import { EthersV5Adapter } from '@cowprotocol/sdk-ethers-v5-adapter'
import { ethers } from 'ethers'
const provider = new ethers.providers.JsonRpcProvider('YOUR_RPC_URL')
const wallet = new ethers.Wallet('YOUR_PRIVATE_KEY', provider)
const adapter = new EthersV5Adapter({ provider, signer: wallet })
import { ViemAdapter } from '@cowprotocol/sdk-viem-adapter'
import { http, createPublicClient, privateKeyToAccount } from 'viem'
import { sepolia } from 'viem/chains'
const account = privateKeyToAccount('YOUR_PRIVATE_KEY' as `0x${string}`)
const transport = http('YOUR_RPC_URL')
const provider = createPublicClient({ chain: sepolia, transport })
const adapter = new ViemAdapter({ provider, signer: account })
CoW Protocol is intent based, decentralized trading protocol that allows users to trade ERC-20 tokens.
The basic swap flow:
- 🔎 Get a quote (price) for a trade (or define your own price with a limit order)
- ✍️ Sign the order
- âś… Post the order to the order-book
The easiest way to start trading is to use the TradingSdk
:
import { SupportedChainId, OrderKind, TradeParameters, TradingSdk } from '@cowprotocol/cow-sdk'
import { EthersV6Adapter } from '@cowprotocol/sdk-ethers-v6-adapter'
import { JsonRpcProvider, Wallet } from 'ethers'
// Configure the adapter
const provider = new JsonRpcProvider('YOUR_RPC_URL')
const wallet = new Wallet('YOUR_PRIVATE_KEY', provider)
const adapter = new EthersV6Adapter({ provider, signer: wallet })
// Initialize the SDK
const sdk = new TradingSdk(
{
appCode: '<YOUR_APP_CODE>',
},
{
chainId: SupportedChainId.SEPOLIA,
},
adapter,
)
// Define trade parameters
const parameters: TradeParameters = {
kind: OrderKind.BUY,
sellToken: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14',
sellTokenDecimals: 18,
buyToken: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59',
buyTokenDecimals: 18,
amount: '120000000000000000',
}
// Post the order
const orderId = await sdk.postSwapOrder(parameters)
console.log('Order created, id: ', orderId)
This example is the simplest way to trade on CoW Protocol.
You might want to use more advanced parameters like receiver
, partiallyFillable
, validTo
and others.
Check the Trading SDK documentation for more details.
OrderBookApi
- provides the ability to retrieve orders and trades from the CoW Protocol order-book, as well as add and cancel themOrderSigningUtils
- serves to sign orders and cancel them using EIP-712SubgraphApi
- provides statistics data about CoW protocol from Subgraph, such as trading volume, trade count and others
import { CowSdk, SupportedChainId } from '@cowprotocol/cow-sdk'
import { EthersV6Adapter } from '@cowprotocol/sdk-ethers-v6-adapter'
import { JsonRpcProvider, Wallet } from 'ethers'
const provider = new JsonRpcProvider('YOUR_RPC_URL')
const wallet = new Wallet('YOUR_PRIVATE_KEY', provider)
const adapter = new EthersV6Adapter({ provider, signer: wallet })
const sdk = new CowSdk({
chainId: SupportedChainId.SEPOLIA,
adapter,
})
// All modules are available automatically
const orderBookApi = sdk.orderBook
const subgraphApi = sdk.subgraph
const orderSigningUtils = sdk.orderSigning
To use packages individually without the umbrella SDK, you must configure the adapter globally or pass it explicitly:
import { OrderBookApi, SubgraphApi, OrderSigningUtils, setGlobalAdapter } from '@cowprotocol/cow-sdk'
import { EthersV6Adapter } from '@cowprotocol/sdk-ethers-v6-adapter'
import { JsonRpcProvider, Wallet } from 'ethers'
const chainId = SupportedChainId.SEPOLIA
const provider = new JsonRpcProvider('YOUR_RPC_URL')
const wallet = new Wallet('YOUR_PRIVATE_KEY', provider)
const adapter = new EthersV6Adapter({ provider, signer: wallet })
// Option 1: Configure the adapter globally
setGlobalAdapter(adapter)
const orderBookApi = new OrderBookApi({ chainId })
const subgraphApi = new SubgraphApi('API_KEY', { chainId })
// Use OrderSigningUtils static methods directly
const signingResult = await OrderSigningUtils.signOrder(order, chainId, adapter.signer)
// Or via CowSdk
const sdk = new CowSdk({ adapter, chainId })
const signingResult2 = await sdk.orderSigning.signOrder(order, chainId, adapter.signer)
For clarity, let's look at the use of the API with a practical example:
Exchanging 0.4 GNO
to WETH
on Gnosis chain
network.
We will do the following operations:
- Get a quote
- Sign the order
- Send the order to the order-book
- Get the data of the created order
- Get trades of the order
- Cancel the order (signing + sending)
import { OrderBookApi, OrderSigningUtils, SupportedChainId } from '@cowprotocol/cow-sdk'
import { EthersV6Adapter } from '@cowprotocol/sdk-ethers-v6-adapter'
import { JsonRpcProvider, Wallet } from 'ethers'
const account = 'YOUR_WALLET_ADDRESS'
const chainId = 100 // Gnosis chain
const provider = new JsonRpcProvider('YOUR_RPC_URL')
const wallet = new Wallet('YOUR_PRIVATE_KEY', provider)
const adapter = new EthersV6Adapter({ provider, signer: wallet })
const quoteRequest = {
sellToken: '0x6a023ccd1ff6f2045c3309768ead9e68f978f6e1', // WETH gnosis chain
buyToken: '0x9c58bacc331c9aa871afd802db6379a98e80cedb', // GNO gnosis chain
from: account,
receiver: account,
sellAmountBeforeFee: (0.4 * 10 ** 18).toString(), // 0.4 WETH
kind: OrderQuoteSide.kind.SELL,
}
const orderBookApi = new OrderBookApi({ chainId: SupportedChainId.GNOSIS_CHAIN })
async function main() {
const { quote } = await orderBookApi.getQuote(quoteRequest)
const orderSigningResult = await OrderSigningUtils.signOrder(quote, chainId, adapter)
const orderId = await orderBookApi.sendOrder({ ...quote, ...orderSigningResult })
const order = await orderBookApi.getOrder(orderId)
const trades = await orderBookApi.getTrades({ orderId })
const orderCancellationSigningResult = await OrderSigningUtils.signOrderCancellations([orderId], chainId, adapter)
const cancellationResult = await orderBookApi.sendSignedOrderCancellations({
...orderCancellationSigningResult,
orderUids: [orderId],
})
console.log('Results: ', { orderId, order, trades, orderCancellationSigningResult, cancellationResult })
}
OrderBookApi
is the main tool for working with CoW Protocol API.
You can use it with the global adapter (recommended):
import { OrderBookApi, SupportedChainId, setGlobalAdapter } from '@cowprotocol/cow-sdk'
import { EthersV6Adapter } from '@cowprotocol/sdk-ethers-v6-adapter'
import { JsonRpcProvider, Wallet } from 'ethers'
const provider = new JsonRpcProvider('YOUR_RPC_URL')
const wallet = new Wallet('YOUR_PRIVATE_KEY', provider)
const adapter = new EthersV6Adapter({ provider, signer: wallet })
setGlobalAdapter(adapter)
const orderBookApi = new OrderBookApi({ chainId: SupportedChainId.GNOSIS_CHAIN })
Since the API supports different networks and environments, there are some options to configure it.
chainId
- can be one of SupportedChainId.MAINNET
, SupportedChainId.GNOSIS_CHAIN
, SupportedChainId.ARBITRUM_ONE
, SupportedChainId.BASE
, SupportedChainId.AVALANCHE
, SupportedChainId.POLYGON
, or SupportedChainId.SEPOLIA
env
- this parameter affects which environment will be used:
https://api.cow.fi
forprod
(default)https://barn.api.cow.fi
forstaging
import { OrderBookApi } from '@cowprotocol/cow-sdk'
const orderBookApi = new OrderBookApi({
chainId: SupportedChainId.GNOSIS_CHAIN,
env: 'staging', // <-----
})
In case you need to use custom endpoints (e.g. you use a proxy), you can do it this way:
import { OrderBookApi } from '@cowprotocol/cow-sdk'
const orderBookApi = new OrderBookApi({
chainId: SupportedChainId.GNOSIS_CHAIN,
baseUrls: {
// <-----
[SupportedChainId.MAINNET]: 'https://YOUR_ENDPOINT/mainnet',
[SupportedChainId.GNOSIS_CHAIN]: 'https://YOUR_ENDPOINT/gnosis_chain',
[SupportedChainId.ARBITRUM]: 'https://YOUR_ENDPOINT/arbitrum_one',
[SupportedChainId.BASE]: 'https://YOUR_ENDPOINT/base',
[SupportedChainId.SEPOLIA]: 'https://YOUR_ENDPOINT/sepolia',
[SupportedChainId.POLYGON]: 'https://YOUR_ENDPOINT/polygon',
[SupportedChainId.AVALANCHE]: 'https://YOUR_ENDPOINT/avalanche',
},
})
The CoW Protocol API has restrictions on the backend side to protect against DDOS and other issues.
The main restriction is request rate limit of: 5 requests per second for each IP address
The client's limiter settings can be configured as well:
import { OrderBookApi } from '@cowprotocol/cow-sdk'
import { BackoffOptions } from 'exponential-backoff'
import { RateLimiterOpts } from 'limiter'
const limiterOpts: RateLimiterOpts = {
tokensPerInterval: 5,
interval: 'second',
}
const backOffOpts: BackoffOptions = {
numOfAttempts: 5,
maxDelay: Infinity,
jitter: 'none',
}
const orderBookApi = new OrderBookApi({ chainId: SupportedChainId.GNOSIS_CHAIN, limiterOpts, backOffOpts })
pnpm install
pnpm build
# Build in watch mode
pnpm start
pnpm test
Some parts of the SDK are automatically generated. This is the case for the Order Book API and the Subgraph API
# Re-create automatically generated code
pnpm codegen