use std::{collections::HashMap, str::FromStr};
use alloy::primitives::Address as AlloyAddress;
use tycho_client::feed::synchronizer::ComponentWithState;
use tycho_common::{models::token::Token, Bytes};
use crate::{
evm::{
engine_db::{create_engine, SHARED_TYCHO_DB},
protocol::{
balancer_v3::{state::BalancerV3State, vm},
vm::utils::load_stateless_contracts,
},
},
protocol::{
errors::InvalidSnapshotError,
models::{DecoderContext, TryFromWithBlock},
},
};
impl TryFromWithBlock<ComponentWithState, tycho_client::feed::BlockHeader> for BalancerV3State {
type Error = InvalidSnapshotError;
async fn try_from_with_header(
value: ComponentWithState,
block: tycho_client::feed::BlockHeader,
_account_balances: &HashMap<Bytes, HashMap<Bytes, Bytes>>,
_all_tokens: &HashMap<Bytes, Token>,
decoder_context: &DecoderContext,
) -> Result<Self, Self::Error> {
let pool_address = Bytes::from_str(value.component.id.as_str()).map_err(|e| {
InvalidSnapshotError::ValueError(format!(
"expected balancer_v3 component id to be the pool address: {e}"
))
})?;
let pool = AlloyAddress::from_slice(pool_address.as_ref());
let pool_type = vm::resolve_pool_type(&value.component.static_attributes, &pool)
.map_err(|e| InvalidSnapshotError::ValueError(e.to_string()))?;
let engine = create_engine(
SHARED_TYCHO_DB.clone(),
decoder_context
.vm_traces
.unwrap_or_default(),
)
.expect("Infallible");
load_stateless_contracts(&engine, &value.state.attributes)
.await
.map_err(|e| InvalidSnapshotError::ValueError(e.to_string()))?;
let tokens = value.component.tokens.clone();
let state = vm::read_pool_state(
&engine,
&pool,
pool_type,
&tokens,
&value.component.static_attributes,
block.timestamp,
)
.map_err(|e| InvalidSnapshotError::ValueError(e.to_string()))?;
let min_token_balances = match pool_type {
vm::BalancerPoolType::Weighted => vm::read_weighted_min_token_balances(&engine, &pool),
vm::BalancerPoolType::Stable |
vm::BalancerPoolType::Reclamm |
vm::BalancerPoolType::QuantAmm => Vec::new(),
};
Ok(BalancerV3State::new(pool_address, tokens, min_token_balances, block.timestamp, state))
}
}