Skip to main content

Overview

The common module provides core types, configuration, constants, and error handling used throughout the CoW Protocol Python SDK.

Chain

Enum representing supported blockchain networks.

Values

from cowdao_cowpy.common.chains import Chain

class Chain(Enum):
    MAINNET = (SupportedChainId.MAINNET, "ethereum", "https://etherscan.io")
    SEPOLIA = (SupportedChainId.SEPOLIA, "sepolia", "https://sepolia.etherscan.io")
    GNOSIS = (SupportedChainId.GNOSIS_CHAIN, "gnosis", "https://gnosisscan.io")
    ARBITRUM_ONE = (SupportedChainId.ARBITRUM_ONE, "arbitrum_one", "https://arbiscan.io")
    BASE = (SupportedChainId.BASE, "base", "https://basescan.org/")
    POLYGON = (SupportedChainId.POLYGON, "polygon", "https://polygonscan.com")
    AVALANCHE = (SupportedChainId.AVALANCHE, "avalanche", "https://snowtrace.io")
    BNB = (SupportedChainId.BNB, "bnb", "https://bscscan.com")
    LENS = (SupportedChainId.LENS, "lens", "https://explorer.lens.xyz/")
MAINNET
Chain
Ethereum Mainnet (Chain ID: 1)
SEPOLIA
Chain
Sepolia Testnet (Chain ID: 11155111)
GNOSIS
Chain
Gnosis Chain (Chain ID: 100)
ARBITRUM_ONE
Chain
Arbitrum One (Chain ID: 42161)
BASE
Chain
Base (Chain ID: 8453)
POLYGON
Chain
Polygon (Chain ID: 137)
AVALANCHE
Chain
Avalanche C-Chain (Chain ID: 43114)
BNB
Chain
BNB Smart Chain (Chain ID: 56)
LENS
Chain
Lens Network (Chain ID: 232)

Properties

chain = Chain.MAINNET

chain.chain_id      # SupportedChainId.MAINNET (value: 1)
chain.name          # "ethereum"
chain.explorer      # "https://etherscan.io"
chain_id
SupportedChainId
The numeric chain ID as a SupportedChainId enum value.
name
str
Human-readable network name.
explorer
str
Block explorer URL for the network.

Example

from cowdao_cowpy.common.chains import Chain

# Use in order creation
chain = Chain.MAINNET
print(f"Using {chain.name} (Chain ID: {chain.chain_id.value})")
print(f"Explorer: {chain.explorer}")

# Iterate all supported chains
from cowdao_cowpy.common.chains import SUPPORTED_CHAINS

for chain in SUPPORTED_CHAINS:
    print(f"{chain.name}: Chain ID {chain.chain_id.value}")

Configuration

SupportedChainId

Enum of supported chain IDs.
from cowdao_cowpy.common.config import SupportedChainId

class SupportedChainId(Enum):
    MAINNET = 1
    GNOSIS_CHAIN = 100
    SEPOLIA = 11155111
    ARBITRUM_ONE = 42161
    BASE = 8453
    POLYGON = 137
    AVALANCHE = 43114
    BNB = 56
    LENS = 232

CowEnv

Environment configuration for CoW Protocol API.
from cowdao_cowpy.common.config import CowEnv

class CowEnv(Enum):
    PROD = "prod"
    STAGING = "staging"
PROD
str
Production environment.
STAGING
str
Staging/testing environment.

ApiContext

Configuration context for API requests.
from cowdao_cowpy.common.config import ApiContext, SupportedChainId, CowEnv

context = ApiContext(
    chain_id=SupportedChainId.MAINNET,
    env=CowEnv.PROD,
    base_urls=None,
    max_tries=5
)
chain_id
SupportedChainId
required
The blockchain network to use.
env
CowEnv
required
The API environment (production or staging).
base_urls
Optional[ApiBaseUrls]
default:"None"
Custom base URLs for API endpoints. If not provided, uses default URLs.
max_tries
Optional[int]
default:"5"
Maximum number of retry attempts for API requests.

DEFAULT_COW_API_CONTEXT

Default API context configuration:
DEFAULT_COW_API_CONTEXT = ApiContext(
    env=CowEnv.PROD,
    chain_id=SupportedChainId.MAINNET
)

IPFSConfig

IPFS gateway configuration.
from cowdao_cowpy.common.config import IPFSConfig

class IPFSConfig(Enum):
    READ_URI = "https://gnosis.mypinata.cloud/ipfs"
    WRITE_URI = "https://api.pinata.cloud"
READ_URI
str
IPFS read gateway URL.
WRITE_URI
str
IPFS write/upload API URL.

Constants

Contract Addresses

CoW Protocol contract addresses across all supported networks.
from cowdao_cowpy.common.constants import (
    CowContractAddress,
    COW_PROTOCOL_SETTLEMENT_CONTRACT_CHAIN_ADDRESS_MAP,
    COW_PROTOCOL_VAULT_RELAYER_CHAIN_ADDRESS_MAP,
    COMPOSABLE_COW_CONTRACT_CHAIN_ADDRESS_MAP,
    EXTENSIBLE_FALLBACK_HANDLER_CONTRACT_CHAIN_ADDRESS_MAP,
)

CowContractAddress

class CowContractAddress(Enum):
    VAULT_RELAYER = "0xC92E8bdf79f0507f65a392b0ab4667716BFE0110"
    COMPOSABLE_COW = "0xfdaFc9d1902f4e0b84f65F49f244b32b31013b74"
    SETTLEMENT_CONTRACT = "0x9008D19f58AAbD9eD0D60971565AA8510560ab41"
    EXTENSIBLE_FALLBACK_HANDLER = "0x2f55e8b20D0B9FEFA187AA7d00B6Cbe563605bF5"
VAULT_RELAYER
str
GPv2VaultRelayer contract address (same across all networks).
COMPOSABLE_COW
str
ComposableCow contract address for conditional orders.
SETTLEMENT_CONTRACT
str
GPv2Settlement contract address for order settlement.
EXTENSIBLE_FALLBACK_HANDLER
str
ExtensibleFallbackHandler for Safe wallet integration.

Contract Address Maps

Dictionaries mapping chain IDs to contract addresses:
# Get settlement contract for mainnet
settlement_address = COW_PROTOCOL_SETTLEMENT_CONTRACT_CHAIN_ADDRESS_MAP[
    SupportedChainId.MAINNET
].value

# Get ComposableCow contract for Gnosis Chain
composable_cow = COMPOSABLE_COW_CONTRACT_CHAIN_ADDRESS_MAP[
    SupportedChainId.GNOSIS_CHAIN
].value

ZERO_APP_DATA

Zero hash constant for orders without app data:
ZERO_APP_DATA = "0x0000000000000000000000000000000000000000000000000000000000000000"

Example

from cowdao_cowpy.common.constants import (
    COW_PROTOCOL_SETTLEMENT_CONTRACT_CHAIN_ADDRESS_MAP,
    COMPOSABLE_COW_CONTRACT_CHAIN_ADDRESS_MAP,
)
from cowdao_cowpy.common.config import SupportedChainId

# Get contract addresses for Mainnet
chain_id = SupportedChainId.MAINNET
settlement = COW_PROTOCOL_SETTLEMENT_CONTRACT_CHAIN_ADDRESS_MAP[chain_id].value
composable_cow = COMPOSABLE_COW_CONTRACT_CHAIN_ADDRESS_MAP[chain_id].value

print(f"Settlement: {settlement}")
print(f"ComposableCow: {composable_cow}")

# Iterate all chains
for chain_id in SupportedChainId:
    address = COW_PROTOCOL_SETTLEMENT_CONTRACT_CHAIN_ADDRESS_MAP[chain_id].value
    print(f"{chain_id.name}: {address}")

Error Handling

CowError

Base exception class for CoW Protocol SDK errors.
from cowdao_cowpy.common.cow_error import CowError

class CowError(Exception):
    def __init__(self, message, error_code=None):
        super().__init__(message)
        self.error_code = error_code
message
str
required
Error message describing what went wrong.
error_code
Optional[Any]
default:"None"
Optional error code for programmatic error handling.

Usage

from cowdao_cowpy.common.cow_error import CowError

try:
    # Some SDK operation
    pass
except CowError as e:
    print(f"CoW SDK Error: {e}")
    if e.error_code:
        print(f"Error code: {e.error_code}")

Creating Custom Errors

from cowdao_cowpy.common.cow_error import CowError

class InvalidOrderError(CowError):
    def __init__(self, reason: str):
        super().__init__(f"Invalid order: {reason}", error_code="INVALID_ORDER")

# Usage
raise InvalidOrderError("Sell amount must be positive")

LOG_PREFIX

Logging prefix constant:
from cowdao_cowpy.common.cow_error import LOG_PREFIX

print(f"{LOG_PREFIX} Processing order...")  # "cow-sdk: Processing order..."

Complete Example

from cowdao_cowpy.common.chains import Chain, SUPPORTED_CHAINS
from cowdao_cowpy.common.config import (
    ApiContext,
    CowEnv,
    SupportedChainId,
    DEFAULT_COW_API_CONTEXT,
)
from cowdao_cowpy.common.constants import (
    COW_PROTOCOL_SETTLEMENT_CONTRACT_CHAIN_ADDRESS_MAP,
    COMPOSABLE_COW_CONTRACT_CHAIN_ADDRESS_MAP,
    ZERO_APP_DATA,
)
from cowdao_cowpy.common.cow_error import CowError, LOG_PREFIX

def setup_chain_config(chain: Chain):
    """Setup configuration for a specific chain."""
    try:
        # Get chain ID
        chain_id = chain.chain_id
        
        # Create API context
        context = ApiContext(
            chain_id=chain_id,
            env=CowEnv.PROD,
            max_tries=3
        )
        
        # Get contract addresses
        settlement = COW_PROTOCOL_SETTLEMENT_CONTRACT_CHAIN_ADDRESS_MAP[chain_id].value
        composable_cow = COMPOSABLE_COW_CONTRACT_CHAIN_ADDRESS_MAP[chain_id].value
        
        print(f"{LOG_PREFIX} Chain: {chain.name}")
        print(f"{LOG_PREFIX} Chain ID: {chain_id.value}")
        print(f"{LOG_PREFIX} Explorer: {chain.explorer}")
        print(f"{LOG_PREFIX} Settlement: {settlement}")
        print(f"{LOG_PREFIX} ComposableCow: {composable_cow}")
        
        return context
        
    except KeyError as e:
        raise CowError(
            f"Chain {chain.name} not supported for this contract",
            error_code="UNSUPPORTED_CHAIN"
        )

# Setup for mainnet
config = setup_chain_config(Chain.MAINNET)

# List all supported chains
print("\nSupported chains:")
for chain in SUPPORTED_CHAINS:
    print(f"  - {chain.name} (ID: {chain.chain_id.value})")

# Use zero app data for simple orders
app_data = ZERO_APP_DATA
print(f"\nUsing zero app data: {app_data}")

Type Aliases

ApiBaseUrls

ApiBaseUrls = Dict[SupportedChainId, str]
Mapping of chain IDs to API base URLs.

Environment Variables

The common module respects these environment variables:
IPFS_READ_URI
str
Custom IPFS read gateway. Defaults to https://cloudflare-ipfs.com/ipfs.
import os

# Set custom IPFS gateway
os.environ['IPFS_READ_URI'] = 'https://my-ipfs-gateway.com/ipfs'

Best Practices

Chain Selection

from cowdao_cowpy.common.chains import Chain

# ✅ Good: Use enum values
chain = Chain.MAINNET

# ❌ Bad: Don't use raw chain IDs
chain_id = 1  # Less readable and type-safe

Error Handling

from cowdao_cowpy.common.cow_error import CowError

try:
    # SDK operations
    pass
except CowError as e:
    # Handle SDK-specific errors
    print(f"SDK error: {e}")
except Exception as e:
    # Handle other errors
    print(f"Unexpected error: {e}")

Configuration

from cowdao_cowpy.common.config import ApiContext, CowEnv, SupportedChainId

# ✅ Good: Create explicit contexts for different environments
prod_context = ApiContext(
    chain_id=SupportedChainId.MAINNET,
    env=CowEnv.PROD
)

staging_context = ApiContext(
    chain_id=SupportedChainId.SEPOLIA,
    env=CowEnv.STAGING
)

Build docs developers (and LLMs) love