use std::collections::{BTreeMap, BTreeSet};
use std::sync::Arc;
use fedimint_connectors::{DynGuaridianConnection, ServerResult};
use fedimint_core::core::ModuleInstanceId;
use fedimint_core::module::ApiRequestErased;
use fedimint_core::task::{MaybeSend, MaybeSync};
use fedimint_core::{PeerId, apply, async_trait_maybe_send, maybe_add_send_sync};
use futures::stream::BoxStream;
use serde_json::Value;
use super::super::{DynModuleApi, IRawFederationApi};
pub type ApiRequestHook =
Arc<maybe_add_send_sync!(dyn Fn(DynIRawFederationApi) -> DynIRawFederationApi + 'static)>;
pub type DynIRawFederationApi = Box<maybe_add_send_sync!(dyn IRawFederationApi + 'static)>;
pub trait RawFederationApiWithRequestHookExt
where
Self: Sized,
{
fn with_request_hook(self, hook: &ApiRequestHook) -> RawFederationApiWithRequestHook;
}
impl<T> RawFederationApiWithRequestHookExt for T
where
T: IRawFederationApi + MaybeSend + MaybeSync + 'static,
{
fn with_request_hook(self, hook: &ApiRequestHook) -> RawFederationApiWithRequestHook {
RawFederationApiWithRequestHook::new(self, hook)
}
}
#[derive(Debug)]
pub struct RawFederationApiWithRequestHook {
pub(crate) inner: DynIRawFederationApi,
}
impl RawFederationApiWithRequestHook {
pub fn new<T>(inner: T, hook: &ApiRequestHook) -> RawFederationApiWithRequestHook
where
T: IRawFederationApi + MaybeSend + MaybeSync + 'static,
{
RawFederationApiWithRequestHook {
inner: hook(Box::new(inner)),
}
}
}
#[apply(async_trait_maybe_send!)]
impl IRawFederationApi for RawFederationApiWithRequestHook {
fn all_peers(&self) -> &BTreeSet<PeerId> {
self.inner.all_peers()
}
fn self_peer(&self) -> Option<PeerId> {
self.inner.self_peer()
}
fn with_module(&self, id: ModuleInstanceId) -> DynModuleApi {
self.inner.with_module(id)
}
async fn request_raw(
&self,
peer_id: PeerId,
method: &str,
params: &ApiRequestErased,
) -> ServerResult<Value> {
self.inner.request_raw(peer_id, method, params).await
}
fn connection_status_stream(&self) -> BoxStream<'static, BTreeMap<PeerId, bool>> {
self.inner.connection_status_stream()
}
async fn wait_for_initialized_connections(&self) {
self.inner.wait_for_initialized_connections().await;
}
async fn get_peer_connection(&self, peer_id: PeerId) -> ServerResult<DynGuaridianConnection> {
self.inner.get_peer_connection(peer_id).await
}
}