use crate::blueprint::ActiveBlueprints;
use crate::config::BlueprintManagerContext;
use crate::error::Result;
use blueprint_runner::config::BlueprintEnvironment;
pub mod eigenlayer;
pub mod tangle;
pub mod types;
pub use types::{ProtocolEvent, ProtocolType};
pub enum ProtocolManager {
Tangle {
client: tangle::TangleProtocolClient,
handler: tangle::TangleEventHandler,
},
Eigenlayer {
client: eigenlayer::EigenlayerProtocolClient,
handler: eigenlayer::EigenlayerEventHandler,
},
}
impl ProtocolManager {
pub async fn new(
protocol: ProtocolType,
env: BlueprintEnvironment,
ctx: &BlueprintManagerContext,
) -> Result<Self> {
match protocol {
ProtocolType::Tangle => {
let client = tangle::TangleProtocolClient::new(env, ctx).await?;
#[allow(unused_mut)]
let mut handler = tangle::TangleEventHandler::new();
#[cfg(feature = "remote-providers")]
handler.init_remote_provider(ctx).await?;
Ok(Self::Tangle { client, handler })
}
ProtocolType::Eigenlayer => {
let client = eigenlayer::EigenlayerProtocolClient::new(env, ctx).await?;
let handler = eigenlayer::EigenlayerEventHandler::new();
Ok(Self::Eigenlayer { client, handler })
}
}
}
pub async fn initialize(
&mut self,
env: &BlueprintEnvironment,
ctx: &BlueprintManagerContext,
active_blueprints: &mut ActiveBlueprints,
) -> Result<()> {
match self {
Self::Tangle { client, handler } => {
handler
.initialize(client, env, ctx, active_blueprints)
.await
}
Self::Eigenlayer { client, handler } => {
handler
.initialize(client, env, ctx, active_blueprints)
.await
}
}
}
pub async fn next_event(&mut self) -> Option<ProtocolEvent> {
match self {
Self::Tangle { client, .. } => client.next_event().await,
Self::Eigenlayer { client, .. } => client.next_event().await,
}
}
pub async fn handle_event(
&mut self,
event: &ProtocolEvent,
env: &BlueprintEnvironment,
ctx: &BlueprintManagerContext,
active_blueprints: &mut ActiveBlueprints,
) -> Result<()> {
match self {
Self::Tangle { client, handler } => {
handler
.handle_event(client, event, env, ctx, active_blueprints)
.await
}
Self::Eigenlayer { handler, .. } => {
handler
.handle_event(event, env, ctx, active_blueprints)
.await
}
}
}
pub async fn run(
&mut self,
env: &BlueprintEnvironment,
ctx: &BlueprintManagerContext,
active_blueprints: &mut ActiveBlueprints,
) -> Result<()> {
self.initialize(env, ctx, active_blueprints).await?;
while let Some(event) = self.next_event().await {
self.handle_event(&event, env, ctx, active_blueprints)
.await?;
}
Err(crate::error::Error::ClientDied)
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::Address;
use blueprint_runner::config::ProtocolSettings;
use blueprint_runner::tangle::config::TangleProtocolSettings;
#[test]
fn test_protocol_type_from_settings() {
let tangle_settings = ProtocolSettings::Tangle(TangleProtocolSettings {
blueprint_id: 1,
service_id: Some(0),
tangle_contract: Address::ZERO,
restaking_contract: Address::ZERO,
status_registry_contract: Address::ZERO,
});
let protocol_type: ProtocolType = (&tangle_settings).into();
assert!(matches!(protocol_type, ProtocolType::Tangle));
let none_settings = ProtocolSettings::None;
let protocol_type: ProtocolType = (&none_settings).into();
assert!(matches!(protocol_type, ProtocolType::Tangle));
}
#[test]
fn test_protocol_event_variant_checking() {
use crate::protocol::types::EigenlayerProtocolEvent;
let eigenlayer_event = ProtocolEvent::Eigenlayer(EigenlayerProtocolEvent {
block_number: 100,
block_hash: vec![0u8; 32],
logs: vec![],
});
assert!(eigenlayer_event.as_tangle().is_none());
assert!(eigenlayer_event.as_eigenlayer().is_some());
assert_eq!(eigenlayer_event.block_number(), 100);
}
}