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
use odos_sdk::*;
use alloy_primitives::{Address, U256};
use std::str::FromStr;
// Create a client
let client = OdosSor::new()?;
// Build a quote request
let quote_request = QuoteRequest::builder()
.chain_id(1) // Ethereum mainnet
.input_tokens(vec![(
Address::from_str("0xA0b86a33E6441d35a6b083d5b02a8e3F6CE21a2E")?, // WETH
U256::from(1000000000000000000u64) // 1 ETH
).into()])
.output_tokens(vec![(
Address::from_str("0xA0b86a33E6441d35a6b083d5b02a8e3F6CE21a2E")?, // USDC
1
).into()])
.slippage_limit_percent(1.0)
.user_addr("0x742d35Cc6634C0532925a3b8D35f3e7a5edD29c0".to_string())
.compact(false)
.simple(false)
.referral_code(0)
.disable_rfqs(false)
.build();
// Get a quote
let quote = client.get_swap_quote("e_request).await?;
// Build transaction data
let swap_context = SwapContext::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(Address::from_str("0xA0b86a33E6441d35a6b083d5b02a8e3F6CE21a2E")?)
.token_amount(U256::from(1000000000000000000u64))
.path_id(quote.path_id().to_string())
.build();
let transaction = client.build_base_transaction(&swap_context).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 = OdosSor::with_config(config)?;
// Or use convenience constructors
let client = OdosSor::with_retry_config(RetryConfig::conservative())?;§Error Handling
The SDK provides comprehensive error types with strongly-typed error codes:
use odos_sdk::*;
match client.get_swap_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.get_swap_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 = OdosSor::with_retry_config(RetryConfig::conservative())?;
// No retries: handle all errors at application level
let client = OdosSor::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 = OdosSor::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
Limit Order Router - Module containing a contract’s types and functions.
- Odos
Limit Order V2 - Generated by the following Solidity interface…
- 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…
- Signature
Validator - Module containing a contract’s types and functions.
- error_
code - Strongly-typed Odos API error codes
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
Response - Response from the Odos Assemble API: https://docs.odos.xyz/build/api-docs
- Client
Config - Configuration for the HTTP client
- Input
Token - Input token for the Odos quote API
- Limit
Order V2 - The Limit Order Router contract.
- Odos
ApiError Response - Error response from the Odos API
- Odos
Http Client - Enhanced HTTP client with retry logic and timeouts
- OdosSor
- The Odos Smart Order Routing V2 API client
- Output
Token - Output token for the Odos quote API
- Quote
Request - Request to the Odos quote API: https://docs.odos.xyz/build/api-docs
- Quote
Request Builder - Use builder syntax to set the inputs and finish with
build(). - Retry
Config - Configuration for retry behavior
- 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
- Swap
Context - A token swap.
- Swap
Context Builder - Use builder syntax to set the inputs and finish with
build(). - 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.
- Transfer
Router Funds Builder - Use builder syntax to set the inputs and finish with
build(). - V2Router
- The V2 SOR Router contract.
- V3Router
- The V2 SOR Router contract.
Enums§
- Endpoint
- Odos API endpoints
- Odos
Chain Error - Errors that can occur when working with Odos chains
- Odos
Error - Comprehensive error types for the Odos SDK
Constants§
- ASSEMBLE_
URL Deprecated - The URL for the Odos Assemble API
- 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_
both_ router_ addresses - Check if both V2 and V3 are supported on a given chain
- get_
supported_ chains - Get all supported chain IDs
- get_
supported_ v2_ chains - Legacy alias for backward compatibility
- get_
supported_ v3_ chains - Legacy alias for backward compatibility
- 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
- Result
- Result type alias for Odos SDK operations