use crate::common::errors::PoolError;
use crate::common::maths::{div_down_fixed, div_up_fixed, mul_down_fixed, mul_up_fixed};
use crate::common::types::PoolState;
use alloy_primitives::U256;
pub fn find_case_insensitive_index_in_list(strings: &[String], target: &str) -> Option<usize> {
let lowercase_target = target.to_lowercase();
for (index, string) in strings.iter().enumerate() {
if string.to_lowercase() == lowercase_target {
return Some(index);
}
}
None
}
pub fn to_scaled_18_apply_rate_round_down(
amount: &U256,
scaling_factor: &U256,
rate: &U256,
) -> Result<U256, PoolError> {
mul_down_fixed(&(amount * scaling_factor), rate)
}
pub fn to_scaled_18_apply_rate_round_up(
amount: &U256,
scaling_factor: &U256,
rate: &U256,
) -> Result<U256, PoolError> {
mul_up_fixed(&(amount * scaling_factor), rate)
}
pub fn to_raw_undo_rate_round_down(
amount: &U256,
scaling_factor: &U256,
token_rate: &U256,
) -> Result<U256, PoolError> {
let denominator = scaling_factor * token_rate;
let result = div_down_fixed(amount, &denominator)?;
Ok(result)
}
pub fn to_raw_undo_rate_round_up(
amount: &U256,
scaling_factor: &U256,
token_rate: &U256,
) -> Result<U256, PoolError> {
div_up_fixed(amount, &(scaling_factor * token_rate))
}
pub fn is_same_address(address_one: &str, address_two: &str) -> bool {
address_one.to_lowercase() == address_two.to_lowercase()
}
pub fn copy_to_scaled18_apply_rate_round_down_array(
amounts: &[U256],
scaling_factors: &[U256],
token_rates: &[U256],
) -> Result<Vec<U256>, PoolError> {
let mut scaled_amounts = Vec::with_capacity(amounts.len());
for (i, amount) in amounts.iter().enumerate() {
let scaled_amount =
to_scaled_18_apply_rate_round_down(amount, &scaling_factors[i], &token_rates[i])?;
scaled_amounts.push(scaled_amount);
}
Ok(scaled_amounts)
}
pub fn copy_to_scaled18_apply_rate_round_up_array(
amounts: &[U256],
scaling_factors: &[U256],
token_rates: &[U256],
) -> Result<Vec<U256>, PoolError> {
let mut scaled_amounts = Vec::with_capacity(amounts.len());
for (i, amount) in amounts.iter().enumerate() {
let scaled_amount =
to_scaled_18_apply_rate_round_up(amount, &scaling_factors[i], &token_rates[i])?;
scaled_amounts.push(scaled_amount);
}
Ok(scaled_amounts)
}
pub fn compute_and_charge_aggregate_swap_fees_raw(
swap_fee_amount_scaled18: &U256,
aggregate_swap_fee_percentage: &U256,
decimal_scaling_factors: &[U256],
token_rates: &[U256],
index: usize,
) -> Result<U256, PoolError> {
if swap_fee_amount_scaled18 > &U256::ZERO && aggregate_swap_fee_percentage > &U256::ZERO {
let total_swap_fee_amount_raw = to_raw_undo_rate_round_down(
swap_fee_amount_scaled18,
&decimal_scaling_factors[index],
&token_rates[index],
)?;
Ok(mul_down_fixed(
&total_swap_fee_amount_raw,
aggregate_swap_fee_percentage,
)?)
} else {
Ok(U256::ZERO)
}
}
pub fn get_single_input_index(max_amounts_in: &[U256]) -> Result<usize, PoolError> {
let length = max_amounts_in.len();
let mut input_index = length;
for (i, amount) in max_amounts_in.iter().enumerate() {
if amount != &U256::ZERO {
if input_index != length {
return Err(PoolError::Custom(
"Multiple non-zero inputs for single token add".to_string(),
));
}
input_index = i;
}
}
if input_index >= length {
return Err(PoolError::Custom(
"All zero inputs for single token add".to_string(),
));
}
Ok(input_index)
}
pub fn require_unbalanced_liquidity_enabled(pool_state: &PoolState) -> Result<(), PoolError> {
if !pool_state.base().supports_unbalanced_liquidity {
return Err(PoolError::Custom(
"DoesNotSupportUnbalancedLiquidity".to_string(),
));
}
Ok(())
}