use std::collections::HashMap;
use alloy::primitives::U256;
use tycho_client::feed::{synchronizer::ComponentWithState, BlockHeader};
use tycho_common::{models::token::Token, Bytes};
use crate::{
evm::protocol::etherfi::state::{BucketLimit, EtherfiState, RedemptionInfo, EETH_ADDRESS},
protocol::{
errors::InvalidSnapshotError,
models::{DecoderContext, TryFromWithBlock},
},
};
impl TryFromWithBlock<ComponentWithState, BlockHeader> for EtherfiState {
type Error = InvalidSnapshotError;
async fn try_from_with_header(
snapshot: ComponentWithState,
block: BlockHeader,
_account_balances: &HashMap<Bytes, HashMap<Bytes, Bytes>>,
_all_tokens: &HashMap<Bytes, Token>,
_decoder_context: &DecoderContext,
) -> Result<Self, Self::Error> {
let total_value_out_of_lp = U256::from_be_slice(
snapshot
.state
.attributes
.get("totalValueOutOfLp")
.ok_or_else(|| {
InvalidSnapshotError::MissingAttribute("totalValueOutOfLp".to_string())
})?,
);
let total_value_in_lp = U256::from_be_slice(
snapshot
.state
.attributes
.get("totalValueInLp")
.ok_or_else(|| {
InvalidSnapshotError::MissingAttribute("totalValueInLp".to_string())
})?,
);
let total_shares = U256::from_be_slice(
snapshot
.state
.attributes
.get("totalShares")
.ok_or_else(|| InvalidSnapshotError::MissingAttribute("totalShares".to_string()))?,
);
let mut liquidity_pool_native_balance: Option<U256> = None;
let mut eth_amount_locked_for_withdrawl: Option<U256> = None;
let mut eth_redemption_info: Option<RedemptionInfo> = None;
if snapshot.component.id == format!("0x{}", hex::encode(EETH_ADDRESS)) {
liquidity_pool_native_balance = Some(U256::from_be_slice(
snapshot
.state
.attributes
.get("liquidityPoolNativeBalance")
.ok_or_else(|| {
InvalidSnapshotError::MissingAttribute(
"liquidityPoolNativeBalance".to_string(),
)
})?,
));
eth_amount_locked_for_withdrawl = Some(U256::from_be_slice(
snapshot
.state
.attributes
.get("ethAmountLockedForWithdrawl")
.ok_or_else(|| {
InvalidSnapshotError::MissingAttribute(
"ethAmountLockedForWithdrawl".to_string(),
)
})?,
));
let eth_bucket_limiter_raw = snapshot
.state
.attributes
.get("ethBucketLimiter")
.ok_or_else(|| {
InvalidSnapshotError::MissingAttribute("ethBucketLimiter".to_string())
})?;
let eth_bucket_limiter_value = U256::from_be_slice(eth_bucket_limiter_raw);
let eth_redemption_info_raw = snapshot
.state
.attributes
.get("ethRedemptionInfo")
.ok_or_else(|| {
InvalidSnapshotError::MissingAttribute("ethRedemptionInfo".to_string())
})?;
let eth_redemption_info_value = U256::from_be_slice(eth_redemption_info_raw);
eth_redemption_info = Some(RedemptionInfo::from_u256(
BucketLimit::from_u256(eth_bucket_limiter_value),
eth_redemption_info_value,
));
}
Ok(EtherfiState::new(
block.timestamp,
total_value_out_of_lp,
total_value_in_lp,
total_shares,
eth_amount_locked_for_withdrawl,
eth_redemption_info,
liquidity_pool_native_balance,
))
}
}