Skip to main content

Adapters

Connect CoW Protocol SDK with different Ethereum libraries

Overview

Adapters provide a unified interface for the CoW Protocol SDK to work with different Ethereum libraries. They abstract away library-specific implementations, allowing you to use your preferred web3 library while maintaining consistent SDK functionality.

Available Adapters

The SDK provides three official adapters:
  • Viem: Modern, lightweight TypeScript library
  • Ethers v6: Latest version of the popular Ethers library
  • Ethers v5: Legacy Ethers version for existing projects

ViemAdapter

The ViemAdapter connects the SDK to Viem, a modern TypeScript Ethereum library with excellent type safety and tree-shaking support.

Installation

npm install @cowprotocol/sdk-viem-adapter viem

Setup

import { createPublicClient, http } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { mainnet } from 'viem/chains'
import { ViemAdapter } from '@cowprotocol/sdk-viem-adapter'
import { setGlobalAdapter } from '@cowprotocol/cow-sdk'

// Create a public client (provider)
const publicClient = createPublicClient({
  chain: mainnet,
  transport: http('https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY'),
})

// Create an account from private key
const account = privateKeyToAccount('0x...')

// Create the adapter
const adapter = new ViemAdapter({
  provider: publicClient,
  signer: account,
})

// Set as global adapter
setGlobalAdapter(adapter)

Using with WalletClient

If you already have a WalletClient (e.g., from Wagmi or RainbowKit):
import { createWalletClient, custom } from 'viem'
import { ViemAdapter } from '@cowprotocol/sdk-viem-adapter'

const walletClient = createWalletClient({
  chain: mainnet,
  transport: custom(window.ethereum),
})

const adapter = new ViemAdapter({
  provider: publicClient,
  walletClient,
})

EthersV6Adapter

The EthersV6Adapter integrates with Ethers.js v6, the latest major version with improved TypeScript support and modern JavaScript features.

Installation

npm install @cowprotocol/sdk-ethers-v6-adapter ethers@^6

Setup

import { JsonRpcProvider, Wallet } from 'ethers'
import { EthersV6Adapter } from '@cowprotocol/sdk-ethers-v6-adapter'
import { setGlobalAdapter } from '@cowprotocol/cow-sdk'

// Create provider
const provider = new JsonRpcProvider('https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY')

// Create wallet
const wallet = new Wallet('0x...', provider)

// Create adapter
const adapter = new EthersV6Adapter({
  provider,
  signer: wallet,
})

setGlobalAdapter(adapter)

Using RPC URL Directly

You can pass an RPC URL string instead of a provider instance:
const adapter = new EthersV6Adapter({
  provider: 'https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY',
  signer: wallet,
})

Browser Wallet Integration

import { BrowserProvider } from 'ethers'

const provider = new BrowserProvider(window.ethereum)
const signer = await provider.getSigner()

const adapter = new EthersV6Adapter({
  provider,
  signer,
})

EthersV5Adapter

The EthersV5Adapter supports Ethers.js v5 for projects that haven’t migrated to v6.

Installation

npm install @cowprotocol/sdk-ethers-v5-adapter ethers@^5

Setup

import { ethers } from 'ethers'
import { EthersV5Adapter } from '@cowprotocol/sdk-ethers-v5-adapter'
import { setGlobalAdapter } from '@cowprotocol/cow-sdk'

// Create provider
const provider = new ethers.providers.JsonRpcProvider(
  'https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY'
)

// Create wallet
const wallet = new ethers.Wallet('0x...', provider)

// Create adapter
const adapter = new EthersV5Adapter({
  provider,
  signer: wallet,
})

setGlobalAdapter(adapter)

Browser Integration (v5)

const provider = new ethers.providers.Web3Provider(window.ethereum)
const signer = provider.getSigner()

const adapter = new EthersV5Adapter({
  provider,
  signer,
})

Adapter Interface

All adapters implement a common interface from @cowprotocol/sdk-common:

Common Methods

// Get network chain ID
await adapter.getChainId()

// Get contract bytecode
await adapter.getCode(address)

// Get transaction receipt
await adapter.getTransactionReceipt(hash)

// Read contract data
await adapter.readContract({
  address: contractAddress,
  abi: contractAbi,
  functionName: 'balanceOf',
  args: [userAddress],
})

// Get contract instance
const contract = adapter.getContract(address, abi)

Signer Methods

// Access the signer
const signer = adapter.signer

// Get signer address
const address = await signer.getAddress()

// Sign typed data (EIP-712)
const signature = await signer.signTypedData(
  domain,
  types,
  message
)

// Send transaction
const tx = await signer.sendTransaction({
  to: recipientAddress,
  value: amount,
})

Dynamic Signer Management

All adapters support changing the signer after initialization:
// Create adapter without signer
const adapter = new ViemAdapter({ provider: publicClient })
setGlobalAdapter(adapter)

// Later, set the signer
const account = privateKeyToAccount('0x...')
adapter.setSigner(account)

Choosing an Adapter

  • Starting a new project with modern TypeScript
  • Bundle size is a concern (Viem is smaller)
  • You want the best TypeScript experience
  • Using Next.js, Wagmi, or RainbowKit
  • You’re already using Ethers v6 in your project
  • You need the latest Ethers features
  • Migrating from v5 to v6
  • You have an existing project on Ethers v5
  • Dependencies require Ethers v5
  • You’re not ready to migrate to v6

Best Practices

Set Global Adapter Early

Call setGlobalAdapter() before initializing any SDK classes to ensure all components use the correct adapter.

Reuse Adapter Instances

Create one adapter instance and reuse it across your application to avoid unnecessary overhead.

Handle Provider Changes

When users switch networks or accounts, update the adapter using setProvider() or setSigner() methods.

Type Safety

Leverage TypeScript’s type inference with adapters for compile-time safety when working with contract ABIs.

Next Steps

Last modified on March 4, 2026