#[macro_export]
macro_rules! impl_v4_multi_pool_viewer {
($struct_name:ident) => {
impl $struct_name {
#[tracing::instrument(skip(self), fields(pool_count = self.pools().len()))]
pub async fn get_slot0s(
&self,
block_id: Option<alloy::eips::BlockId>,
) -> anyhow::Result<
Vec<(
alloy::primitives::aliases::U160,
alloy::primitives::aliases::I24,
alloy::primitives::aliases::U24,
alloy::primitives::aliases::U24,
)>,
> {
let state_view = self.get_state_view();
let mut multicall = alloy::providers::Provider::multicall(&self.provider).dynamic();
if let Some(block_id) = block_id {
multicall = multicall.block(block_id);
}
tracing::debug!("Building multicall for {} pools", self.pools().len());
for (_, pool_id) in self.pools() {
multicall = multicall.add_dynamic(state_view.getSlot0(*pool_id));
}
let result = multicall.aggregate().await?;
tracing::debug!("Multicall completed with {} results", result.len());
let slot0s: Vec<(
alloy::primitives::aliases::U160,
alloy::primitives::aliases::I24,
alloy::primitives::aliases::U24,
alloy::primitives::aliases::U24,
)> = result
.into_iter()
.map(|slot0| (slot0.sqrtPriceX96, slot0.tick, slot0.protocolFee, slot0.lpFee))
.collect();
Ok(slot0s)
}
}
#[async_trait::async_trait]
impl $crate::traits::pool_viewer::MultiPoolViewer for $struct_name {
async fn currency0_prices(
&self,
block_id: Option<alloy::eips::BlockId>,
) -> anyhow::Result<
Vec<
uniswap_sdk_core::prelude::Price<
uniswap_sdk_core::prelude::Currency,
uniswap_sdk_core::prelude::Currency,
>,
>,
> {
let slot0s = self.get_slot0s(block_id).await?;
tracing::debug!("Calculating prices for {} pools", slot0s.len());
let prices: Vec<
uniswap_sdk_core::prelude::Price<
uniswap_sdk_core::prelude::Currency,
uniswap_sdk_core::prelude::Currency,
>,
> = slot0s
.into_iter()
.zip(self.pools().iter())
.map(|(slot0, (pool_key, _))| {
let price = $crate::common::v4_utils::calculate_price_from_sqrt_price_x96(
slot0.0,
pool_key.token_a.clone(),
pool_key.token_b.clone(),
);
price
})
.collect();
tracing::debug!("All currency0 prices calculated");
Ok(prices)
}
async fn currency1_prices(
&self,
block_id: Option<alloy::eips::BlockId>,
) -> anyhow::Result<
Vec<
uniswap_sdk_core::prelude::Price<
uniswap_sdk_core::prelude::Currency,
uniswap_sdk_core::prelude::Currency,
>,
>,
> {
let prices = self.currency0_prices(block_id).await?;
Ok(prices.into_iter().map(|price| price.invert()).collect())
}
}
};
}