use crate::{APIConfigResponse, APIGenesisResponse};
use alloy_eips::eip4844::IndexedBlobHash;
use alloy_node_bindings::{Anvil, AnvilInstance};
use alloy_provider::{network::Ethereum, ReqwestProvider};
use alloy_rpc_client::RpcClient;
use alloy_rpc_types_beacon::sidecar::{BeaconBlobBundle, BlobData};
use alloy_transport_http::Http;
use async_trait::async_trait;
use reqwest::Client;
pub fn spawn_anvil() -> (ReqwestProvider<Ethereum>, AnvilInstance) {
let anvil = Anvil::new().try_spawn().expect("could not spawn anvil");
(anvil_http_provider(&anvil), anvil)
}
pub fn anvil_http_provider(anvil: &AnvilInstance) -> ReqwestProvider<Ethereum> {
http_provider(&anvil.endpoint())
}
pub fn http_provider(url: &str) -> ReqwestProvider<Ethereum> {
let url = url.parse().unwrap();
let http = Http::<Client>::new(url);
ReqwestProvider::new(RpcClient::new(http, true))
}
#[derive(Debug, Default)]
pub struct MockBeaconClient {
pub node_version: Option<String>,
pub config_spec: Option<APIConfigResponse>,
pub beacon_genesis: Option<APIGenesisResponse>,
pub blob_sidecars: Option<BeaconBlobBundle>,
}
#[derive(Debug, derive_more::Display)]
pub enum MockBeaconClientError {
#[display("config_spec not set")]
ConfigSpecNotSet,
#[display("beacon_genesis not set")]
BeaconGenesisNotSet,
#[display("blob_sidecars not set")]
BlobSidecarsNotSet,
}
impl core::error::Error for MockBeaconClientError {}
#[async_trait]
impl crate::BeaconClient for MockBeaconClient {
type Error = MockBeaconClientError;
async fn config_spec(&self) -> Result<APIConfigResponse, Self::Error> {
self.config_spec.clone().ok_or_else(|| MockBeaconClientError::ConfigSpecNotSet)
}
async fn beacon_genesis(&self) -> Result<APIGenesisResponse, Self::Error> {
self.beacon_genesis.clone().ok_or_else(|| MockBeaconClientError::BeaconGenesisNotSet)
}
async fn beacon_blob_side_cars(
&self,
_: u64,
_: &[IndexedBlobHash],
) -> Result<Vec<BlobData>, Self::Error> {
self.blob_sidecars
.clone()
.ok_or_else(|| MockBeaconClientError::BlobSidecarsNotSet)
.map(|r| r.data)
}
}