Skip to main content

Crate cow_sdk

Crate cow_sdk 

Source
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 before 0.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.

FeatureEnables
subgraphRead-only subgraph analytics as cow_sdk::subgraph; lifts SubgraphError into CowError.
cow-shedCOW Shed account-abstraction hooks as cow_sdk::cow_shed (proxy derivation, EIP-712 hook signing, factory calldata).
alloy-providerNative Alloy read-only Provider adapter as cow_sdk::alloy_provider.
alloy-signerNative Alloy local-key Signer adapter as cow_sdk::alloy_signer.
alloyThe composed native Alloy client as cow_sdk::alloy; implies alloy-provider and alloy-signer.
testingIn-memory test doubles (MockOrderbook, MockSigner, MockProvider) as cow_sdk::testing for downstream integration tests. Dev-dependency only.
tracingtracing 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;testing
pub use cow_sdk_trading as trading;

Modules§

composablecomposable
Opt-in composable conditional orders: the ComposableCoW framework and the TWAP builder, encoders, and gas-free transaction builder. Behind the off-by-default composable feature (ADR 0048); enable it with cow-sdk = { features = ["composable"] }. Composable conditional orders (ComposableCoW framework + TWAP).
cow_shedcow-shed
Opt-in COW Shed account-abstraction hook helpers (proxy derivation, EIP-712 signing, factory calldata, and the cow_shed::CowShedHooks orchestrator). Behind the off-by-default cow-shed feature, so the default cow-sdk surface stays trading-first; enable it with cow-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.
ErrorClass
Coarse-grained failure classification, re-exported from cow-sdk-core.