Expand description
§cow-sdk
Primary Rust SDK facade for CoW Protocol.
⚠️ Alpha —
0.1.0-alpha. Pre-release and not security-audited; the public API may change before0.1.0. It is published as a pre-release, so Cargo selects it only when you opt in (cow-sdk = "0.1.0-alpha.10"). Review it yourself before relying on it with real funds.
cow-sdk is the curated first-touch entry point of the cow-rs crate
family. It re-exports the core types, signing helpers, contract helpers,
orderbook client, app-data helpers, and the high-level trading
orchestration surface from one place.
The cow-named identity and numeric primitive types (Address, Hash32,
AppDataHash, HexData, OrderUid, Amount)
re-export through the facade as cow-owned
#[repr(transparent)] newtypes over alloy_primitives per
ADR 0052.
§Install
[dependencies]
cow-sdk = "0.1.0-alpha.10"§Feature flags
Every optional surface is off by default (default = []); enable only what you
use. The HTTP retry, rate-limit, and Retry-After transport policy is always on.
| Feature | Enables |
|---|---|
subgraph | Read-only subgraph analytics as cow_sdk::subgraph; lifts SubgraphError into CowError. |
cow-shed | COW Shed account-abstraction hooks as cow_sdk::cow_shed (proxy derivation, EIP-712 hook signing, factory calldata). |
alloy-provider | Native Alloy read-only Provider adapter as cow_sdk::alloy_provider. |
alloy-signer | Native Alloy local-key Signer adapter as cow_sdk::alloy_signer. |
alloy | The composed native Alloy client as cow_sdk::alloy; implies alloy-provider and alloy-signer. |
testing | In-memory test doubles (MockOrderbook, MockSigner, MockProvider) as cow_sdk::testing for downstream integration tests. Dev-dependency only. |
tracing | tracing spans and structured events across the SDK; see the Observability guide. |
[dependencies]
cow-sdk = { version = "0.1.0-alpha.10", features = ["subgraph", "cow-shed"] }§Native default example
The shortest ready-state path uses the native default orderbook transport. Browser targets use the same trading API but must inject a browser transport; see the workspace Getting Started guide for that wiring.
use cow_sdk::core::SupportedChainId;
use cow_sdk::trading::Trading;
let _trading = Trading::builder()
.chain_id(SupportedChainId::Sepolia)
.app_code("your-app-code")
.build()
.unwrap();Once constructed, a single call quotes, signs, and posts a swap. The order owner defaults to the signer’s address:
use cow_sdk::core::{address, Address, Amount, SupportedChainId};
use cow_sdk::trading::Trading;
// Tokens are compile-time validated `Address` literals, not raw strings. The
// literal is the lowercase wire form; a mixed-case literal rejects at build time.
const WETH: Address = address!("0xfff9976782d46cc05630d1f6ebab18b2324d6b14");
const COW: Address = address!("0x0625afb445c3b6b7b929342a04a22599fd5dbb59");
let trading = Trading::builder()
.chain_id(SupportedChainId::Sepolia)
.app_code("your-app-code")
.build()?;
// The named setters keep the sell and buy legs from being transposed, and
// `execute` becomes callable only once both tokens and an amount are set. The
// owner defaults to the signer address and slippage uses the quote-aware
// tolerance unless either is set.
let posted = trading
.swap()
.sell_token(WETH)
.buy_token(COW)
.sell_amount(Amount::parse_units("0.1", 18)?)
.execute(signer)
.await?;
println!("https://explorer.cow.fi/sepolia/orders/{}", posted.order_id);For allowance, approval, pre-sign, or on-chain cancellation that does not need
an app code, call the crate’s free functions directly —
cow_protocol_allowance, approval_transaction, pre_sign_transaction,
and onchain_cancel_order — without constructing a trading client. The native
wrap_transaction and unwrap_transaction builders resolve the chain’s
wrapped-native token from the chain id and need neither a client nor a provider.
§Handling errors
Every fallible call returns a typed error. The facade aggregates the per-crate
errors into CowError, and every error type — facade or leaf — exposes a coarse
ErrorClass (Validation, Transport, Remote, RateLimited, Signing,
Cancelled, Internal) for telemetry. Orderbook failures add a status-precise
retry verdict: is_retryable() returns the same decision the SDK’s own transport
retry loop reaches, and backoff_hint() surfaces the server’s Retry-After
cooldown when present.
use std::time::Duration;
use cow_sdk::{CowError, ErrorClass};
/// Decide whether a failed SDK call should be retried, and how long to wait.
fn retry_delay(error: &CowError) -> Option<Duration> {
// `class()` is the coarse telemetry bucket; `is_retryable()` is the
// status-precise retry decision — a retryable `503` and a non-retryable
// `400` are both `ErrorClass::Remote`, so class alone cannot tell them apart.
let _telemetry_bucket: ErrorClass = error.class();
error
.is_retryable()
.then(|| error.backoff_hint().unwrap_or(Duration::from_millis(500)))
}CowError is the convenience aggregate for consumers that ?-propagate every
SDK call into one type. A consumer with its own error type — or that needs
rejection-specific handling — matches the leaf error directly instead: each
leaf carries the same class() and is_retryable(), plus the finer-grained
OrderbookRejection::category() that names the action a rejection calls for. The
native error_classification example walks every ErrorClass bucket and the
category() refinement end to end.
On-chain submission has its own verdict. The receipt-wait helpers return
WaitError, which is generic over the caller’s signer and provider error types,
so it stays out of CowError; use WaitError::reverted() to tell a real
on-chain revert from a transient broadcast, lookup, timeout, or cancellation.
§Examples
The workspace ships runnable, deterministic scenarios for every facade workflow — quoting, posting, signing, app-data, transport, subgraph access, and the Alloy adapters — cataloged by goal in Examples. Getting Started walks the recommended first session.
§Where to next
§License
Licensed under GPL-3.0-or-later. See the workspace
LICENSE
file for the full text.
Primary Rust SDK facade for CoW Protocol.
This crate re-exports the main public surface for:
- shared core and config types
- signing helpers
- contracts helpers
- orderbook client types
- app-data helpers
- trading orchestration
The facade is trading-first: the high-level trading flow is the primary surface.
Read-only subgraph analytics are available behind the off-by-default
subgraph feature as cow_sdk::subgraph; the full subgraph contract stays
in cow-sdk-subgraph.
Native/default ready-state setup:
use cow_sdk::core::{Address, SupportedChainId, address};
use cow_sdk::trading::Trading;
// Compile-time validated address literal — no runtime parse, no unwrap.
// The literal is the lowercase wire form; mixed-case literals reject at
// build time because EIP-55 checksums cannot be verified in const eval.
const SETTLEMENT: Address = address!("0x9008d19f58aabd9ed0d60971565aa8510560ab41");
let _trading = Trading::builder()
.chain_id(SupportedChainId::Sepolia)
.app_code("your-app-code")
.build()
.unwrap();Once constructed, the fluent swap builder quotes, signs, and posts in one call. Its named token setters cannot be transposed, and the order owner defaults to the signer’s address:
use cow_sdk::core::{Address, Amount, SupportedChainId, address};
use cow_sdk::trading::Trading;
// Sell 0.1 WETH for COW on Sepolia.
const WETH: Address = address!("0xfff9976782d46cc05630d1f6ebab18b2324d6b14");
const COW: Address = address!("0x0625afb445c3b6b7b929342a04a22599fd5dbb59");
let trading = Trading::builder()
.chain_id(SupportedChainId::Sepolia)
.app_code("your-app-code")
.build()?;
// One call quotes, signs with `signer`, and posts to the orderbook.
let posted = trading
.swap()
.sell_token(WETH)
.buy_token(COW)
.sell_amount(Amount::from(100_000_000_000_000_000u128))
.execute(signer)
.await?;
println!("posted order: {}", posted.order_id);The flat trading.post_swap_order(params, signer, None) method and the
standalone post_swap_order(..) free function remain available for callers
that assemble TradeParams directly or compose without a bound client.
For a resting limit order with an explicit price, trading.limit() opens the
matching builder: named sell_amount / buy_amount setters, then post(signer)
(or post_presign() for the smart-account path that needs no signer).
For allowance, approval, pre-sign, or on-chain cancellation that does not
need an app code, call the crate’s free functions directly
(cow_protocol_allowance, approval_transaction,
pre_sign_transaction, onchain_cancel_order) without constructing a
trading client.
Re-exports§
pub use cow_sdk_app_data as app_data;pub use cow_sdk_contracts as contracts;pub use cow_sdk_core as core;pub use cow_sdk_orderbook as orderbook;pub use cow_sdk_signing as signing;pub use cow_sdk_test as testing;testingpub use cow_sdk_trading as trading;
Modules§
- composable
composable - Opt-in composable conditional orders: the
ComposableCoWframework and the TWAP builder, encoders, and gas-free transaction builder. Behind the off-by-defaultcomposablefeature (ADR 0048); enable it withcow-sdk = { features = ["composable"] }. Composable conditional orders (ComposableCoWframework + TWAP). - cow_
shed cow-shed - Opt-in COW Shed account-abstraction hook helpers (proxy derivation,
EIP-712 signing, factory calldata, and the
cow_shed::CowShedHooksorchestrator). Behind the off-by-defaultcow-shedfeature, so the defaultcow-sdksurface stays trading-first; enable it withcow-sdk = { features = ["cow-shed"] }. COW Shed account-abstraction proxy, EIP-712, and hook-signing helpers. - http
- Shared HTTP retry, rate-limit, and classification policy.
Enums§
- CowError
- Aggregate error type for the root facade crate.
- Error
Class - Coarse-grained failure classification, re-exported from
cow-sdk-core.