use alloy::{
primitives::{aliases::I24, Address, TxHash, B256, U256},
rpc::types::TransactionReceipt,
};
use alloy_sol_types::sol;
use anyhow::{Context, Result};
use crate::pool_swappers::common::find_events;
sol! {
interface IPoolManager {
event Initialize(
bytes32 indexed id,
address indexed currency0,
address indexed currency1,
uint24 fee,
int24 tickSpacing,
address hooks,
uint160 sqrtPriceX96,
int24 tick
);
event ModifyLiquidity(
bytes32 indexed id,
address indexed sender,
int24 tickLower,
int24 tickUpper,
int256 liquidityDelta,
bytes32 salt
);
event Swap(
bytes32 indexed id,
address indexed sender,
int128 amount0,
int128 amount1,
uint160 sqrtPriceX96,
uint128 liquidity,
int24 tick,
uint24 fee
);
event Donate(
bytes32 indexed id,
address indexed sender,
uint256 amount0,
uint256 amount1
);
}
}
#[derive(Debug, Clone)]
pub struct LiquidityModification {
pub pool_id: B256,
pub token_id: U256,
pub sender: Address,
pub tick_lower: I24,
pub tick_upper: I24,
pub liquidity_delta: alloy::primitives::I256,
}
#[allow(clippy::unnecessary_fallible_conversions)]
pub fn decode_modify_liquidity_events(
receipt: &TransactionReceipt,
pool_manager_address: Address,
) -> Result<(Vec<LiquidityModification>, TxHash)> {
let tx_hash = receipt.transaction_hash;
let modify_events = find_events(receipt, |log, _| {
if log.address() != pool_manager_address {
return Err(anyhow::anyhow!(
"ModifyLiquidity event from unexpected address: expected {:?}, got {:?}",
pool_manager_address,
log.address()
));
}
let decoded = log.log_decode::<IPoolManager::ModifyLiquidity>()?;
Ok(LiquidityModification {
pool_id: B256::try_from(decoded.inner.id).expect("Failed to convert id to pool_id"),
token_id: U256::try_from(decoded.inner.salt)
.expect("Failed to convert salt to token_id"),
sender: decoded.inner.sender,
tick_lower: decoded.inner.tickLower,
tick_upper: decoded.inner.tickUpper,
liquidity_delta: decoded.inner.liquidityDelta,
})
})
.context(
"Failed to find ModifyLiquidity event with positive liquidityDelta in transaction receipt",
)?;
Ok((modify_events, tx_hash))
}
pub fn decode_modify_liquidity_event_with_pool_id(
receipt: &TransactionReceipt,
pool_manager_address: Address,
pool_id: B256,
) -> Result<(LiquidityModification, TxHash)> {
let (modify_events, tx_hash) = decode_modify_liquidity_events(receipt, pool_manager_address)?;
for event in modify_events {
if event.pool_id == pool_id {
return Ok((event, tx_hash));
}
}
Err(anyhow::anyhow!("ModifyLiquidity event with pool_id not found"))
}