docs: (WIP) In-code docs for encoders

- TODO double check all this, look for missing docs
This commit is contained in:
TAMARA LIPOWSKI
2025-02-04 18:11:32 -05:00
parent 25a26f21be
commit 52cce5f5c6
10 changed files with 72 additions and 6 deletions

View File

@@ -1,6 +1,6 @@
# Tycho Execution # 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 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. Its custom code for each DEX, you get a simple, ready-to-use tool that generates the necessary data to execute trades. Its

BIN
banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 KiB

View File

@@ -12,6 +12,7 @@ use tokio::runtime::Runtime;
use crate::encoding::{errors::EncodingError, evm::utils::encode_input}; 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 { pub struct ProtocolApprovalsManager {
client: Arc<RootProvider<BoxTransport>>, client: Arc<RootProvider<BoxTransport>>,
runtime: Runtime, runtime: Runtime,
@@ -23,6 +24,9 @@ impl ProtocolApprovalsManager {
let client = runtime.block_on(get_client())?; let client = runtime.block_on(get_client())?;
Ok(Self { client, runtime }) 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( pub fn approval_needed(
&self, &self,
token: Address, token: Address,

View File

@@ -12,6 +12,12 @@ use crate::encoding::{
strategy_encoder::{StrategyEncoder, StrategyEncoderRegistry}, 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 { pub struct EVMStrategyEncoderRegistry {
strategies: HashMap<String, Box<dyn StrategyEncoder>>, strategies: HashMap<String, Box<dyn StrategyEncoder>>,
} }

View File

@@ -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 { pub struct SplitSwapStrategyEncoder {
swap_encoder_registry: SwapEncoderRegistry, swap_encoder_registry: SwapEncoderRegistry,
permit2: Permit2, permit2: Permit2,
@@ -213,7 +220,11 @@ impl StrategyEncoder for SplitSwapStrategyEncoder {
} }
/// This strategy encoder is used for solutions that are sent directly to the pool. /// 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 { pub struct ExecutorStrategyEncoder {
swap_encoder_registry: SwapEncoderRegistry, swap_encoder_registry: SwapEncoderRegistry,
} }

View File

@@ -12,6 +12,12 @@ use crate::encoding::{
swap_encoder::SwapEncoder, 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)] #[derive(Clone)]
pub struct UniswapV2SwapEncoder { pub struct UniswapV2SwapEncoder {
executor_address: String, 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)] #[derive(Clone)]
pub struct UniswapV3SwapEncoder { pub struct UniswapV3SwapEncoder {
executor_address: String, 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)] #[derive(Clone)]
pub struct BalancerV2SwapEncoder { pub struct BalancerV2SwapEncoder {
executor_address: String, executor_address: String,

View File

@@ -11,8 +11,15 @@ use crate::encoding::{
tycho_encoder::TychoEncoder, 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<S: StrategyEncoderRegistry> { pub struct EVMTychoEncoder<S: StrategyEncoderRegistry> {
strategy_selector: S, strategy_registry: S,
router_address: Bytes, router_address: Bytes,
} }
@@ -20,7 +27,7 @@ impl<S: StrategyEncoderRegistry> EVMTychoEncoder<S> {
pub fn new(strategy_selector: S, router_address: String) -> Result<Self, EncodingError> { pub fn new(strategy_selector: S, router_address: String) -> Result<Self, EncodingError> {
let router_address = Bytes::from_str(&router_address) let router_address = Bytes::from_str(&router_address)
.map_err(|_| EncodingError::FatalError("Invalid router address".to_string()))?; .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<S: StrategyEncoderRegistry> TychoEncoder<S> for EVMTychoEncoder<S> {
.unwrap_or(self.router_address.clone()); .unwrap_or(self.router_address.clone());
let strategy = self let strategy = self
.strategy_selector .strategy_registry
.get_encoder(solution)?; .get_encoder(solution)?;
let (contract_interaction, target_address) = let (contract_interaction, target_address) =
strategy.encode_strategy(solution.clone(), router_address)?; strategy.encode_strategy(solution.clone(), router_address)?;

View File

@@ -1,6 +1,8 @@
use num_bigint::BigUint; use num_bigint::BigUint;
use tycho_core::{dto::ProtocolComponent, Bytes}; use tycho_core::{dto::ProtocolComponent, Bytes};
/// Represents a solution containing details describing an order, and instructions for filling
/// the order.
#[derive(Clone, Default, Debug)] #[derive(Clone, Default, Debug)]
pub struct Solution { pub struct Solution {
/// Address of the sender. /// Address of the sender.
@@ -35,12 +37,17 @@ pub struct Solution {
pub direct_execution: bool, 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)] #[derive(Clone, PartialEq, Debug)]
pub enum NativeAction { pub enum NativeAction {
Wrap, Wrap,
Unwrap, Unwrap,
} }
/// Represents a swap operation to be performed on a pool.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Swap { pub struct Swap {
/// Protocol component from tycho indexer /// Protocol component from tycho indexer
@@ -49,10 +56,16 @@ pub struct Swap {
pub token_in: Bytes, pub token_in: Bytes,
/// Token being output from the pool. /// Token being output from the pool.
pub token_out: Bytes, 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, 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)] #[derive(Clone, Debug)]
pub struct Transaction { pub struct Transaction {
// Address of the contract to call with the calldata // Address of the contract to call with the calldata
@@ -63,6 +76,8 @@ pub struct Transaction {
pub data: Vec<u8>, pub data: Vec<u8>,
} }
/// Represents necessary attributes for encoding an order.
pub struct EncodingContext { pub struct EncodingContext {
pub receiver: Bytes, pub receiver: Bytes,
pub exact_out: bool, pub exact_out: bool,

View File

@@ -13,6 +13,9 @@ pub trait StrategyEncoder {
fn get_swap_encoder(&self, protocol_system: &str) -> Option<&Box<dyn SwapEncoder>>; fn get_swap_encoder(&self, protocol_system: &str) -> Option<&Box<dyn SwapEncoder>>;
} }
/// 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 { pub trait StrategyEncoderRegistry {
fn new( fn new(
chain: Chain, chain: Chain,
@@ -21,6 +24,8 @@ pub trait StrategyEncoderRegistry {
) -> Result<Self, EncodingError> ) -> Result<Self, EncodingError>
where where
Self: Sized; Self: Sized;
/// Returns the strategy encoder that should be used to encode the given solution.
#[allow(clippy::borrowed_box)] #[allow(clippy::borrowed_box)]
fn get_encoder(&self, solution: &Solution) -> Result<&Box<dyn StrategyEncoder>, EncodingError>; fn get_encoder(&self, solution: &Solution) -> Result<&Box<dyn StrategyEncoder>, EncodingError>;
} }

View File

@@ -2,6 +2,8 @@ use crate::encoding::{
errors::EncodingError, errors::EncodingError,
models::{EncodingContext, Swap}, models::{EncodingContext, Swap},
}; };
/// This trait must be implemented in order to encode a swap for a specific protocol.
pub trait SwapEncoder: Sync + Send { pub trait SwapEncoder: Sync + Send {
fn new(executor_address: String) -> Self fn new(executor_address: String) -> Self
where where