feat: Add EncodingError
Change method signatures to expect it and raise it where it makes sense --- don't change below this line --- ENG-4076 <#DTT#>
This commit is contained in:
31
src/encoding/errors.rs
Normal file
31
src/encoding/errors.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use std::io;
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
/// Represents the outer-level, user-facing errors of the tycho-execution encoding package.
|
||||
///
|
||||
/// `EncodingError` encompasses all possible errors that can occur in the package,
|
||||
/// wrapping lower-level errors in a user-friendly way for easier handling and display.
|
||||
/// Variants:
|
||||
/// - `InvalidInput`: Indicates that the encoding has failed due to bad input parameters.
|
||||
/// - `FatalError`: There is problem with the application setup.
|
||||
#[derive(Error, Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum EncodingError {
|
||||
#[error("Invalid input: {0}")]
|
||||
InvalidInput(String),
|
||||
#[error("Fatal error: {0}")]
|
||||
FatalError(String),
|
||||
}
|
||||
|
||||
impl From<io::Error> for EncodingError {
|
||||
fn from(err: io::Error) -> Self {
|
||||
EncodingError::FatalError(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::Error> for EncodingError {
|
||||
fn from(err: serde_json::Error) -> Self {
|
||||
EncodingError::FatalError(err.to_string())
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
use anyhow::Error;
|
||||
use alloy_sol_types::SolValue;
|
||||
use num_bigint::BigUint;
|
||||
|
||||
use crate::encoding::{
|
||||
errors::EncodingError,
|
||||
evm::utils::encode_input,
|
||||
models::{NativeAction, Solution, Transaction, PROPELLER_ROUTER_ADDRESS},
|
||||
router_encoder::RouterEncoder,
|
||||
@@ -22,7 +23,10 @@ impl<S: StrategySelector, A: UserApprovalsManager> EVMRouterEncoder<S, A> {
|
||||
}
|
||||
}
|
||||
impl<S: StrategySelector, A: UserApprovalsManager> RouterEncoder<S, A> for EVMRouterEncoder<S, A> {
|
||||
fn encode_router_calldata(&self, solutions: Vec<Solution>) -> Result<Vec<Transaction>, Error> {
|
||||
fn encode_router_calldata(
|
||||
&self,
|
||||
solutions: Vec<Solution>,
|
||||
) -> Result<Vec<Transaction>, EncodingError> {
|
||||
let _approvals_calldata = self.handle_approvals(&solutions)?; // TODO: where should we append this?
|
||||
let mut transactions: Vec<Transaction> = Vec::new();
|
||||
for solution in solutions.iter() {
|
||||
@@ -50,7 +54,7 @@ impl<S: StrategySelector, A: UserApprovalsManager> RouterEncoder<S, A> for EVMRo
|
||||
Ok(transactions)
|
||||
}
|
||||
|
||||
fn handle_approvals(&self, solutions: &[Solution]) -> Result<Vec<Vec<u8>>, Error> {
|
||||
fn handle_approvals(&self, solutions: &[Solution]) -> Result<Vec<Vec<u8>>, EncodingError> {
|
||||
let mut approvals = Vec::new();
|
||||
for solution in solutions.iter() {
|
||||
approvals.push(Approval {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use alloy_primitives::Address;
|
||||
use alloy_sol_types::SolValue;
|
||||
use anyhow::Error;
|
||||
use num_bigint::BigUint;
|
||||
use num_traits::Zero;
|
||||
|
||||
use crate::encoding::{
|
||||
errors::EncodingError,
|
||||
evm::swap_encoder::SWAP_ENCODER_REGISTRY,
|
||||
models::{EncodingContext, Solution},
|
||||
strategy_encoder::StrategyEncoder,
|
||||
@@ -27,7 +29,7 @@ pub trait EVMStrategyEncoder: StrategyEncoder {
|
||||
pub struct SplitSwapStrategyEncoder {}
|
||||
impl EVMStrategyEncoder for SplitSwapStrategyEncoder {}
|
||||
impl StrategyEncoder for SplitSwapStrategyEncoder {
|
||||
fn encode_strategy(&self, _solution: Solution) -> Result<Vec<u8>, Error> {
|
||||
fn encode_strategy(&self, _solution: Solution) -> Result<Vec<u8>, EncodingError> {
|
||||
todo!()
|
||||
}
|
||||
fn selector(&self, _exact_out: bool) -> &str {
|
||||
@@ -40,17 +42,26 @@ impl StrategyEncoder for SplitSwapStrategyEncoder {
|
||||
pub struct StraightToPoolStrategyEncoder {}
|
||||
impl EVMStrategyEncoder for StraightToPoolStrategyEncoder {}
|
||||
impl StrategyEncoder for StraightToPoolStrategyEncoder {
|
||||
fn encode_strategy(&self, solution: Solution) -> Result<Vec<u8>, Error> {
|
||||
fn encode_strategy(&self, solution: Solution) -> Result<Vec<u8>, EncodingError> {
|
||||
if solution.router_address.is_none() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Router address is required for straight to pool solutions"
|
||||
return Err(EncodingError::InvalidInput(
|
||||
"Router address is required for straight to pool solutions".to_string(),
|
||||
));
|
||||
}
|
||||
let swap = solution.swaps.first().unwrap();
|
||||
let registry = SWAP_ENCODER_REGISTRY.read().unwrap();
|
||||
let registry = SWAP_ENCODER_REGISTRY
|
||||
.read()
|
||||
.map_err(|_| {
|
||||
EncodingError::FatalError("Failed to read the swap encoder registry".to_string())
|
||||
})?;
|
||||
let swap_encoder = registry
|
||||
.get_encoder(&swap.component.protocol_system)
|
||||
.expect("Swap encoder not found");
|
||||
.ok_or_else(|| {
|
||||
EncodingError::InvalidInput(format!(
|
||||
"Swap encoder not found for protocol: {}",
|
||||
swap.component.protocol_system
|
||||
))
|
||||
})?;
|
||||
let router_address = solution.router_address.unwrap();
|
||||
|
||||
let encoding_context = EncodingContext {
|
||||
|
||||
@@ -2,9 +2,9 @@ use std::str::FromStr;
|
||||
|
||||
use alloy_primitives::Address;
|
||||
use alloy_sol_types::SolValue;
|
||||
use anyhow::Error;
|
||||
|
||||
use crate::encoding::{
|
||||
errors::EncodingError,
|
||||
evm::{
|
||||
approvals::protocol_approvals_manager::ProtocolApprovalsManager, utils::bytes_to_address,
|
||||
},
|
||||
@@ -25,7 +25,7 @@ impl SwapEncoder for UniswapV2SwapEncoder {
|
||||
&self,
|
||||
_swap: Swap,
|
||||
_encoding_context: EncodingContext,
|
||||
) -> Result<Vec<u8>, Error> {
|
||||
) -> Result<Vec<u8>, EncodingError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@@ -47,7 +47,11 @@ impl SwapEncoder for BalancerV2SwapEncoder {
|
||||
.expect("Invalid string for balancer vault address"),
|
||||
}
|
||||
}
|
||||
fn encode_swap(&self, swap: Swap, encoding_context: EncodingContext) -> Result<Vec<u8>, Error> {
|
||||
fn encode_swap(
|
||||
&self,
|
||||
swap: Swap,
|
||||
encoding_context: EncodingContext,
|
||||
) -> Result<Vec<u8>, EncodingError> {
|
||||
let token_approvals_manager = ProtocolApprovalsManager::new();
|
||||
let runtime = tokio::runtime::Handle::try_current()
|
||||
.is_err()
|
||||
|
||||
@@ -3,7 +3,10 @@ use std::{collections::HashMap, fs};
|
||||
use serde::Deserialize;
|
||||
use tycho_core::dto::Chain;
|
||||
|
||||
use crate::encoding::{evm::swap_encoder::builder::SwapEncoderBuilder, swap_encoder::SwapEncoder};
|
||||
use crate::encoding::{
|
||||
errors::EncodingError, evm::swap_encoder::builder::SwapEncoderBuilder,
|
||||
swap_encoder::SwapEncoder,
|
||||
};
|
||||
|
||||
pub struct SwapEncoderRegistry {
|
||||
encoders: HashMap<String, Box<dyn SwapEncoder>>,
|
||||
@@ -40,7 +43,7 @@ pub struct Config {
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn from_file(path: &str) -> Result<Self, anyhow::Error> {
|
||||
pub fn from_file(path: &str) -> Result<Self, EncodingError> {
|
||||
let config_str = fs::read_to_string(path)?;
|
||||
let config: Config = serde_json::from_str(&config_str)?;
|
||||
Ok(config)
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
use alloy_primitives::{Address, Keccak256, U256};
|
||||
use alloy_sol_types::SolValue;
|
||||
use anyhow::Error;
|
||||
use num_bigint::BigUint;
|
||||
use tycho_core::Bytes;
|
||||
|
||||
use crate::encoding::errors::EncodingError;
|
||||
|
||||
/// Safely converts a `Bytes` object to an `Address` object.
|
||||
///
|
||||
/// Checks the length of the `Bytes` before attempting to convert, and returns a `SimulationError`
|
||||
/// Checks the length of the `Bytes` before attempting to convert, and returns an `EncodingError`
|
||||
/// if not 20 bytes long.
|
||||
pub fn bytes_to_address(address: &Bytes) -> Result<Address, Error> {
|
||||
pub fn bytes_to_address(address: &Bytes) -> Result<Address, EncodingError> {
|
||||
if address.len() == 20 {
|
||||
Ok(Address::from_slice(address))
|
||||
} else {
|
||||
Err(anyhow::format_err!("Invalid ERC20 token address: {:?}", address))
|
||||
Err(EncodingError::InvalidInput(format!("Invalid ERC20 token address: {:?}", address)))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
mod errors;
|
||||
#[cfg(feature = "evm")]
|
||||
mod evm;
|
||||
mod models;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use anyhow::Error;
|
||||
|
||||
use crate::encoding::{
|
||||
errors::EncodingError,
|
||||
models::{Solution, Transaction},
|
||||
strategy_encoder::StrategySelector,
|
||||
user_approvals_manager::UserApprovalsManager,
|
||||
@@ -8,6 +7,9 @@ use crate::encoding::{
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub trait RouterEncoder<S: StrategySelector, A: UserApprovalsManager> {
|
||||
fn encode_router_calldata(&self, solutions: Vec<Solution>) -> Result<Vec<Transaction>, Error>;
|
||||
fn handle_approvals(&self, solutions: &[Solution]) -> Result<Vec<Vec<u8>>, Error>;
|
||||
fn encode_router_calldata(
|
||||
&self,
|
||||
solutions: Vec<Solution>,
|
||||
) -> Result<Vec<Transaction>, EncodingError>;
|
||||
fn handle_approvals(&self, solutions: &[Solution]) -> Result<Vec<Vec<u8>>, EncodingError>;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use anyhow::Error;
|
||||
|
||||
use crate::encoding::models::Solution;
|
||||
use crate::encoding::{
|
||||
errors::EncodingError,
|
||||
models::{ActionType, Solution},
|
||||
};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub trait StrategyEncoder {
|
||||
fn encode_strategy(&self, to_encode: Solution) -> Result<Vec<u8>, Error>;
|
||||
fn encode_strategy(&self, to_encode: Solution) -> Result<Vec<u8>, EncodingError>;
|
||||
fn selector(&self, exact_out: bool) -> &str;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
use anyhow::Error;
|
||||
|
||||
use crate::encoding::models::{EncodingContext, Swap};
|
||||
use crate::encoding::{
|
||||
errors::EncodingError,
|
||||
models::{EncodingContext, Swap},
|
||||
};
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub trait SwapEncoder: Sync + Send {
|
||||
fn new(executor_address: String) -> Self
|
||||
where
|
||||
Self: Sized;
|
||||
fn encode_swap(&self, swap: Swap, encoding_context: EncodingContext) -> Result<Vec<u8>, Error>;
|
||||
fn encode_swap(
|
||||
&self,
|
||||
swap: Swap,
|
||||
encoding_context: EncodingContext,
|
||||
) -> Result<Vec<u8>, EncodingError>;
|
||||
fn executor_address(&self) -> &str;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user