Expand description
§Odos SDK
A production-ready Rust SDK for the Odos protocol - a decentralized exchange aggregator that provides optimal routing for token swaps across multiple EVM chains.
§Features
- Multi-chain Support: 16+ EVM chains including Ethereum, Arbitrum, Optimism, Polygon, Base, etc.
- Type-safe: Leverages Rust’s type system with Alloy primitives for addresses, chain IDs, and amounts
- Production-ready: Built-in retry logic, circuit breakers, timeouts, and error handling
- Builder Pattern: Ergonomic API using the
boncrate for request building - Comprehensive Error Handling: Detailed error types for different failure scenarios
§Quick Start
§High-Level API with SwapBuilder
The easiest way to get started is with the SwapBuilder API:
use odos_sdk::prelude::*;
use std::str::FromStr;
// Create a client
let client = OdosClient::new()?;
// Define tokens and amount
let usdc = Address::from_str("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")?; // USDC on Ethereum
let weth = Address::from_str("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")?; // WETH on Ethereum
let my_address = Address::from_str("0x742d35Cc6634C0532925a3b8D35f3e7a5edD29c0")?;
// Build and execute swap in one go
let transaction = client.swap()
.chain(Chain::ethereum())
.from_token(usdc, U256::from(1_000_000)) // 1 USDC (6 decimals)
.to_token(weth)
.slippage(Slippage::percent(0.5).unwrap()) // 0.5% slippage
.signer(my_address)
.build_transaction()
.await?;
println!("Transaction ready: {:?}", transaction);§Low-Level API
For more control, use the low-level API with quote() and assemble():
use odos_sdk::prelude::*;
use alloy_primitives::address;
use std::str::FromStr;
let client = OdosClient::new()?;
let usdc = Address::from_str("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48")?;
let weth = Address::from_str("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2")?;
// Step 1: Get a quote
let quote_request = QuoteRequest::builder()
.chain_id(1)
.input_tokens(vec![(usdc, U256::from(1_000_000)).into()])
.output_tokens(vec![(weth, 1).into()])
.slippage_limit_percent(0.5)
.user_addr(address!("742d35Cc6634C0532925a3b8D35f3e7a5edD29c0"))
.compact(false)
.simple(false)
.referral_code(0)
.disable_rfqs(false)
.build();
let quote = client.quote("e_request).await?;
println!("Expected output: {} WETH", quote.out_amount().unwrap_or(&"0".to_string()));
// Step 2: Assemble transaction
let assembly_request = AssemblyRequest::builder()
.chain(alloy_chains::NamedChain::Mainnet)
.router_address(alloy_chains::NamedChain::Mainnet.v2_router_address()?)
.signer_address(Address::from_str("0x742d35Cc6634C0532925a3b8D35f3e7a5edD29c0")?)
.output_recipient(Address::from_str("0x742d35Cc6634C0532925a3b8D35f3e7a5edD29c0")?)
.token_address(usdc)
.token_amount(U256::from(1_000_000))
.path_id(quote.path_id().to_string())
.build();
let transaction = client.assemble(&assembly_request).await?;§Configuration
The SDK supports extensive configuration for production use:
use odos_sdk::*;
use std::time::Duration;
// Full configuration
let config = ClientConfig {
timeout: Duration::from_secs(30),
connect_timeout: Duration::from_secs(10),
retry_config: RetryConfig {
max_retries: 3,
initial_backoff_ms: 100,
retry_server_errors: true,
retry_predicate: None,
},
max_connections: 20,
pool_idle_timeout: Duration::from_secs(90),
api_key: None,
..Default::default()
};
let client = OdosClient::with_config(config)?;
// Or use convenience constructors
let client = OdosClient::with_retry_config(RetryConfig::conservative())?;§Error Handling
The SDK provides comprehensive error types with strongly-typed error codes:
use odos_sdk::*;
use alloy_primitives::Address;
match client.quote("e_request).await {
Ok(quote) => {
// Handle successful quote
println!("Got quote with path ID: {}", quote.path_id());
}
Err(err) => {
// Check for specific error codes
if let Some(code) = err.error_code() {
if code.is_invalid_chain_id() {
eprintln!("Invalid chain ID - check configuration");
} else if code.is_no_viable_path() {
eprintln!("No routing path found");
} else if code.is_timeout() {
eprintln!("Service timeout: {}", code);
}
}
// Log trace ID for support
if let Some(trace_id) = err.trace_id() {
eprintln!("Trace ID: {}", trace_id);
}
// Handle by error type
match err {
OdosError::Api { status, message, .. } => {
eprintln!("API error {}: {}", status, message);
}
OdosError::Timeout(msg) => {
eprintln!("Request timed out: {}", msg);
}
OdosError::RateLimit { message, retry_after, .. } => {
if let Some(duration) = retry_after {
eprintln!("Rate limited: {}. Retry after {} seconds", message, duration.as_secs());
} else {
eprintln!("Rate limited: {}", message);
}
}
_ => eprintln!("Error: {}", err),
}
}
}§Strongly-Typed Error Codes
The SDK provides error codes matching the Odos API documentation:
- General (1XXX):
ApiError - Algo/Quote (2XXX):
NoViablePath,AlgoTimeout,AlgoInternal - Internal Service (3XXX):
TxnAssemblyTimeout,GasUnavailable - Validation (4XXX):
InvalidChainId,BlockedUserAddr,InvalidTokenAmount - Internal (5XXX):
InternalError,SwapUnavailable
use odos_sdk::{OdosError, error_code::OdosErrorCode};
if let Some(code) = error.error_code() {
// Check categories
if code.is_validation_error() {
println!("Validation error - check request parameters");
}
// Check retryability
if code.is_retryable() {
println!("Error can be retried: {}", code);
}
}§Rate Limiting
The Odos API enforces rate limits to ensure fair usage. The SDK handles rate limits intelligently:
- HTTP 429 responses are detected and classified as
OdosError::RateLimit - Rate limit errors are NOT retried (return immediately with
Retry-Afterheader) - The SDK captures
Retry-Afterheaders for application-level handling - Applications should handle rate limits globally with proper backoff coordination
§Best Practices for Avoiding Rate Limits
- Share a single client across your application instead of creating new clients per request
- Implement application-level rate limiting if making many concurrent requests
- Handle rate limit errors gracefully and back off at the application level if needed
§Example: Handling Rate Limits
use odos_sdk::*;
use alloy_primitives::{Address, U256};
use std::time::Duration;
match client.quote("e_request).await {
Ok(quote) => {
println!("Got quote: {}", quote.path_id());
}
Err(e) if e.is_rate_limit() => {
// Rate limit exceeded even after SDK retries
// Consider backing off at application level
eprintln!("Rate limited - waiting before retry");
tokio::time::sleep(Duration::from_secs(5)).await;
// Retry or handle accordingly
}
Err(e) => {
eprintln!("Error: {}", e);
}
}§Configuring Retry Behavior
You can customize retry behavior for your use case:
use odos_sdk::*;
// Conservative: only retry network errors
let client = OdosClient::with_retry_config(RetryConfig::conservative())?;
// No retries: handle all errors at application level
let client = OdosClient::with_retry_config(RetryConfig::no_retries())?;
// Custom configuration
let retry_config = RetryConfig {
max_retries: 5,
initial_backoff_ms: 200,
retry_server_errors: false, // Don't retry 5xx errors
retry_predicate: None,
};
let client = OdosClient::with_retry_config(retry_config)?;Note: Rate limit errors (429) are never retried regardless of configuration. This prevents retry cascades that make rate limiting worse.
Modules§
- IOdos
Router V3 - Module containing a contract’s types and functions.
- Odos
Router V2 - Module containing a contract’s types and functions.
- Odos
V2Router - Generated by the following Solidity interface…
- Odos
V3Router - Generated by the following Solidity interface…
- error_
code - Strongly-typed Odos API error codes
- prelude
- Prelude module for convenient imports
Structs§
- ApiKey
- API key for authenticating with the Odos API
- Assemble
Request - Request to the Odos Assemble API: https://docs.odos.xyz/build/api-docs
- Assembly
Request - Request for assembling a transaction from a quote
- Assembly
Response - Response from the Odos Assemble API: https://docs.odos.xyz/build/api-docs
- Chain
- Type-safe chain identifier with convenient constructors
- Client
Config - Configuration for the HTTP client
- Endpoint
- Complete API endpoint configuration combining host tier and API version
- Input
Token - Input token for the Odos quote API
- Odos
ApiError Response - Error response from the Odos API
- Odos
Client - The Odos API client
- Odos
Http Client - Enhanced HTTP client with retry logic and timeouts
- Output
Token - Output token for the Odos quote API
- Quote
Request - Request to the Odos quote API: https://docs.odos.xyz/build/api-docs
- Referral
Code - Type-safe referral code
- Retry
Config - Configuration for retry behavior
- Router
Availability - Represents which routers are available on a specific chain
- Simulation
- Simulation from the Odos Assemble API: https://docs.odos.xyz/build/api-docs
- Simulation
Error - Simulation error from the Odos Assemble API: https://docs.odos.xyz/build/api-docs
- Single
Quote Response - Single quote response from the Odos quote API: https://docs.odos.xyz/build/api-docs
- Slippage
- Type-safe slippage percentage with validation
- Swap
Builder - High-level swap builder for common use cases
- Swap
Inputs - Swap inputs for the Odos assemble API
- Transaction
Data - Transaction data from the Odos Assemble API: https://docs.odos.xyz/build/api-docs
- Transfer
Router Funds - A transfer of a token from one address to another.
- V2Router
- The V2 SOR Router contract.
- V3Router
- The V2 SOR Router contract.
Enums§
- ApiHost
- API host tier for the Odos API
- ApiVersion
- Version of the Odos API
- Odos
Chain Error - Errors that can occur when working with Odos chains
- Odos
Error - Comprehensive error types for the Odos SDK
- Router
Type - Represents the different types of Odos routers
Constants§
- ODOS_
LO_ ARBITRUM_ ROUTER - Arbitrum One - Limit Order V2 Router contract address
- ODOS_
LO_ AVALANCHE_ ROUTER - Avalanche C-Chain - Limit Order V2 Router contract address
- ODOS_
LO_ BASE_ ROUTER - Base - Limit Order V2 Router contract address
- ODOS_
LO_ BSC_ ROUTER - BNB Smart Chain - Limit Order V2 Router contract address
- ODOS_
LO_ ETHEREUM_ ROUTER - Ethereum Mainnet - Limit Order V2 Router contract address
- ODOS_
LO_ FRAXTAL_ ROUTER - Fraxtal - Limit Order V2 Router contract address
- ODOS_
LO_ LINEA_ ROUTER - Linea - Limit Order V2 Router contract address
- ODOS_
LO_ MANTLE_ ROUTER - Mantle - Limit Order V2 Router contract address
- ODOS_
LO_ MODE_ ROUTER - Mode - Limit Order V2 Router contract address
- ODOS_
LO_ OP_ ROUTER - Optimism - Limit Order V2 Router contract address
- ODOS_
LO_ POLYGON_ ROUTER - Polygon - Limit Order V2 Router contract address
- ODOS_
LO_ SCROLL_ ROUTER - Scroll - Limit Order V2 Router contract address
- ODOS_
LO_ SONIC_ ROUTER - Sonic - Limit Order V2 Router contract address
- ODOS_
LO_ UNICHAIN_ ROUTER - Unichain - Limit Order V2 Router contract address
- ODOS_
LO_ ZKSYNC_ ROUTER - zkSync Era - Limit Order V2 Router contract address
- ODOS_V3
- Odos V3 Router - Next-generation router contract
- ODOS_
V2_ ARBITRUM_ ROUTER - Arbitrum One - V2 Router contract address
- ODOS_
V2_ AVALANCHE_ ROUTER - Avalanche C-Chain - V2 Router contract address
- ODOS_
V2_ BASE_ ROUTER - Base - V2 Router contract address
- ODOS_
V2_ BSC_ ROUTER - BNB Smart Chain - V2 Router contract address
- ODOS_
V2_ ETHEREUM_ ROUTER - Ethereum Mainnet - V2 Router contract address
- ODOS_
V2_ FRAXTAL_ ROUTER - Fraxtal - V2 Router contract address
- ODOS_
V2_ LINEA_ ROUTER - Linea - V2 Router contract address
- ODOS_
V2_ MANTLE_ ROUTER - Mantle - V2 Router contract address
- ODOS_
V2_ MODE_ ROUTER - Mode - V2 Router contract address
- ODOS_
V2_ OP_ ROUTER - Optimism - V2 Router contract address
- ODOS_
V2_ POLYGON_ ROUTER - Polygon - V2 Router contract address
- ODOS_
V2_ SCROLL_ ROUTER - Scroll - V2 Router contract address
- ODOS_
V2_ SONIC_ ROUTER - Sonic - V2 Router contract address
- ODOS_
V2_ UNICHAIN_ ROUTER - Unichain - V2 Router contract address
- ODOS_
V2_ ZKSYNC_ ROUTER - zkSync Era - V2 Router contract address
Traits§
- Odos
Chain - Trait for chains that support Odos protocol
- Odos
Router Selection - Extension trait for easy router selection
Functions§
- get_
lo_ router_ by_ chain_ id - Get the Limit Order V2 router address for a specific chain ID
- get_
supported_ chains - Get all supported chains
- get_
supported_ lo_ chains - Get all chains that support Limit Order V2 routers
- get_
supported_ v2_ chains - Get all chains that support V2 routers
- get_
supported_ v3_ chains - Get all chains that support V3 routers
- get_
v2_ router_ by_ chain_ id - Get the V2 router address for a specific chain ID
- get_
v3_ router_ by_ chain_ id - Get the V3 router address for a specific chain ID
- parse_
value - Parse a value string as U256, supporting both decimal and hexadecimal formats
Type Aliases§
- Odos
Chain Result - Result type for Odos chain operations
- OdosSor
Deprecated - Deprecated alias for
OdosClient - Result
- Result type alias for Odos SDK operations
- Swap
Context Deprecated - Deprecated alias for
AssemblyRequest