diff --git a/README.md b/README.md index 49b15fe..692109b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Tycho Execution -TODO: add banner +![img.png](banner.png) Tycho Execution makes it easy to trade on different DEXs by handling the complex encoding for you. Instead of creating custom code for each DEX, you get a simple, ready-to-use tool that generates the necessary data to execute trades. It’s diff --git a/banner.png b/banner.png new file mode 100644 index 0000000..688bfe6 Binary files /dev/null and b/banner.png differ diff --git a/src/encoding/evm/approvals/protocol_approvals_manager.rs b/src/encoding/evm/approvals/protocol_approvals_manager.rs index 8d1d16f..ff4e1ce 100644 --- a/src/encoding/evm/approvals/protocol_approvals_manager.rs +++ b/src/encoding/evm/approvals/protocol_approvals_manager.rs @@ -12,6 +12,7 @@ use tokio::runtime::Runtime; use crate::encoding::{errors::EncodingError, evm::utils::encode_input}; +/// A manager for checking if an approval is needed for interacting with a certain spender. pub struct ProtocolApprovalsManager { client: Arc>, runtime: Runtime, @@ -23,6 +24,9 @@ impl ProtocolApprovalsManager { let client = runtime.block_on(get_client())?; Ok(Self { client, runtime }) } + + /// Checks the current allowance for the given token, owner, and spender, and returns True + /// if the current allowance is zero. pub fn approval_needed( &self, token: Address, diff --git a/src/encoding/evm/strategy_encoder/strategy_encoder_registry.rs b/src/encoding/evm/strategy_encoder/strategy_encoder_registry.rs index 5554c9d..88960e7 100644 --- a/src/encoding/evm/strategy_encoder/strategy_encoder_registry.rs +++ b/src/encoding/evm/strategy_encoder/strategy_encoder_registry.rs @@ -12,6 +12,12 @@ use crate::encoding::{ strategy_encoder::{StrategyEncoder, StrategyEncoderRegistry}, }; + +/// Contains all supported strategies to encode a solution. +/// +/// # Fields +/// * `strategies` - A hashmap containing the name of the strategy as a key and the strategy +/// encoder as a value. pub struct EVMStrategyEncoderRegistry { strategies: HashMap>, } diff --git a/src/encoding/evm/strategy_encoder/strategy_encoders.rs b/src/encoding/evm/strategy_encoder/strategy_encoders.rs index 62a873e..1c2b2a9 100644 --- a/src/encoding/evm/strategy_encoder/strategy_encoders.rs +++ b/src/encoding/evm/strategy_encoder/strategy_encoders.rs @@ -54,6 +54,13 @@ pub trait EVMStrategyEncoder: StrategyEncoder { } } +/// Represents the encoder for a swap strategy which supports single, sequential and split swaps. +/// +/// # Fields +/// +/// * `swap_encoder_registry`: SwapEncoderRegistry, containing all possible swap encoders +/// * `permit2`: Permit2, the object containing necessary information for managing permit2 operations +/// * `selector`: String, the selector for the swap function in the router contract pub struct SplitSwapStrategyEncoder { swap_encoder_registry: SwapEncoderRegistry, permit2: Permit2, @@ -213,7 +220,11 @@ impl StrategyEncoder for SplitSwapStrategyEncoder { } /// This strategy encoder is used for solutions that are sent directly to the pool. -/// Only 1 solution with 1 swap is supported. +/// Only one solution with one swap is supported. +/// +/// # Fields +/// +/// * `swap_encoder_registry`: SwapEncoderRegistry, containing all possible swap encoders pub struct ExecutorStrategyEncoder { swap_encoder_registry: SwapEncoderRegistry, } diff --git a/src/encoding/evm/swap_encoder/swap_encoders.rs b/src/encoding/evm/swap_encoder/swap_encoders.rs index e3c573f..f1bf64a 100644 --- a/src/encoding/evm/swap_encoder/swap_encoders.rs +++ b/src/encoding/evm/swap_encoder/swap_encoders.rs @@ -12,6 +12,12 @@ use crate::encoding::{ swap_encoder::SwapEncoder, }; + +/// Encodes a swap on a Uniswap V2 pool through the given executor address. +/// +/// # Fields +/// * `executor_address` - The address of the executor contract that will perform the swap. +/// * `executor_selector` - The selector of the swap function in the executor contract. #[derive(Clone)] pub struct UniswapV2SwapEncoder { executor_address: String, @@ -66,6 +72,11 @@ impl SwapEncoder for UniswapV2SwapEncoder { } } +/// Encodes a swap on a Uniswap V3 pool through the given executor address. +/// +/// # Fields +/// * `executor_address` - The address of the executor contract that will perform the swap. +/// * `executor_selector` - The selector of the swap function in the executor contract. #[derive(Clone)] pub struct UniswapV3SwapEncoder { executor_address: String, @@ -140,6 +151,11 @@ impl SwapEncoder for UniswapV3SwapEncoder { } } +/// Encodes a swap on a Balancer pool through the given executor address. +/// +/// # Fields +/// * `executor_address` - The address of the executor contract that will perform the swap. +/// * `executor_selector` - The selector of the swap function in the executor contract. #[derive(Clone)] pub struct BalancerV2SwapEncoder { executor_address: String, diff --git a/src/encoding/evm/tycho_encoder.rs b/src/encoding/evm/tycho_encoder.rs index 1a93400..ec4e378 100644 --- a/src/encoding/evm/tycho_encoder.rs +++ b/src/encoding/evm/tycho_encoder.rs @@ -11,8 +11,15 @@ use crate::encoding::{ tycho_encoder::TychoEncoder, }; +/// Represents an encoder for a swap through the given router address using any strategy supported +/// by the strategy registry. +/// +/// # Fields +/// * `strategy_registry`: S, the strategy registry to use to select the best strategy to encode a +/// solution, based on its supported strategies and the solution attributes. +/// * `router_address`: Bytes, the address of the router to use to execute the swaps. pub struct EVMTychoEncoder { - strategy_selector: S, + strategy_registry: S, router_address: Bytes, } @@ -20,7 +27,7 @@ impl EVMTychoEncoder { pub fn new(strategy_selector: S, router_address: String) -> Result { let router_address = Bytes::from_str(&router_address) .map_err(|_| EncodingError::FatalError("Invalid router address".to_string()))?; - Ok(EVMTychoEncoder { strategy_selector, router_address }) + Ok(EVMTychoEncoder { strategy_registry: strategy_selector, router_address }) } } @@ -82,7 +89,7 @@ impl TychoEncoder for EVMTychoEncoder { .unwrap_or(self.router_address.clone()); let strategy = self - .strategy_selector + .strategy_registry .get_encoder(solution)?; let (contract_interaction, target_address) = strategy.encode_strategy(solution.clone(), router_address)?; diff --git a/src/encoding/models.rs b/src/encoding/models.rs index 24c7c9d..18a034b 100644 --- a/src/encoding/models.rs +++ b/src/encoding/models.rs @@ -1,6 +1,8 @@ use num_bigint::BigUint; use tycho_core::{dto::ProtocolComponent, Bytes}; +/// Represents a solution containing details describing an order, and instructions for filling +/// the order. #[derive(Clone, Default, Debug)] pub struct Solution { /// Address of the sender. @@ -35,12 +37,17 @@ pub struct Solution { pub direct_execution: bool, } +/// Represents an action to be performed on the native token either before or after the swap. +/// `Wrap` means that the native token will be wrapped before the first swap, and `Unwrap` +/// means that the native token will be unwrapped after the last swap, before being sent to the +/// receiver. #[derive(Clone, PartialEq, Debug)] pub enum NativeAction { Wrap, Unwrap, } +/// Represents a swap operation to be performed on a pool. #[derive(Clone, Debug)] pub struct Swap { /// Protocol component from tycho indexer @@ -49,10 +56,16 @@ pub struct Swap { pub token_in: Bytes, /// Token being output from the pool. pub token_out: Bytes, - /// Percentage of the amount to be swapped in this operation (for example, 0.5 means 50%) + /// Decimal of the amount to be swapped in this operation (for example, 0.5 means 50%) pub split: f64, } +/// Represents a transaction to be executed on the Ethereum network. +/// +/// # Fields +/// * `to`: Address of the contract to call with the calldata +/// * `value`: ETH value to be sent with the transaction. +/// * `data`: Encoded calldata for the transaction. #[derive(Clone, Debug)] pub struct Transaction { // Address of the contract to call with the calldata @@ -63,6 +76,8 @@ pub struct Transaction { pub data: Vec, } + +/// Represents necessary attributes for encoding an order. pub struct EncodingContext { pub receiver: Bytes, pub exact_out: bool, diff --git a/src/encoding/strategy_encoder.rs b/src/encoding/strategy_encoder.rs index 04d23e7..8ab7b96 100644 --- a/src/encoding/strategy_encoder.rs +++ b/src/encoding/strategy_encoder.rs @@ -13,6 +13,9 @@ pub trait StrategyEncoder { fn get_swap_encoder(&self, protocol_system: &str) -> Option<&Box>; } + +/// Contains the supported strategies to encode a solution, and chooses the best strategy to encode +/// a solution based on the solution's attributes. pub trait StrategyEncoderRegistry { fn new( chain: Chain, @@ -21,6 +24,8 @@ pub trait StrategyEncoderRegistry { ) -> Result where Self: Sized; + + /// Returns the strategy encoder that should be used to encode the given solution. #[allow(clippy::borrowed_box)] fn get_encoder(&self, solution: &Solution) -> Result<&Box, EncodingError>; } diff --git a/src/encoding/swap_encoder.rs b/src/encoding/swap_encoder.rs index 4247de5..356086e 100644 --- a/src/encoding/swap_encoder.rs +++ b/src/encoding/swap_encoder.rs @@ -2,6 +2,8 @@ use crate::encoding::{ errors::EncodingError, models::{EncodingContext, Swap}, }; + +/// This trait must be implemented in order to encode a swap for a specific protocol. pub trait SwapEncoder: Sync + Send { fn new(executor_address: String) -> Self where