diff --git a/crates/context/config/src/client/protocol/near.rs b/crates/context/config/src/client/protocol/near.rs index 6454853c3..f90211c01 100644 --- a/crates/context/config/src/client/protocol/near.rs +++ b/crates/context/config/src/client/protocol/near.rs @@ -28,7 +28,9 @@ use thiserror::Error; use url::Url; use super::Protocol; -use crate::client::transport::{AssociatedTransport, Operation, Transport, TransportRequest}; +use crate::client::transport::{ + AssociatedTransport, Operation, Transport, TransportLike, TransportRequest, +}; #[derive(Copy, Clone, Debug)] pub enum Near {} @@ -41,6 +43,22 @@ impl AssociatedTransport for NearTransport<'_> { type Protocol = Near; } +impl TransportLike for NearTransport<'_> { + type Error = NearError; + + async fn try_send( + &self, + request: TransportRequest<'_>, + payload: &Vec, + ) -> Option, Self::Error>> { + if request.protocol == "near" { + Some(self.send(request, payload.to_vec()).await) + } else { + None + } + } +} + #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(try_from = "serde_creds::Credentials")] pub struct Credentials { diff --git a/crates/context/config/src/client/protocol/starknet.rs b/crates/context/config/src/client/protocol/starknet.rs index 9a940faea..5dacde3c9 100644 --- a/crates/context/config/src/client/protocol/starknet.rs +++ b/crates/context/config/src/client/protocol/starknet.rs @@ -18,7 +18,9 @@ use thiserror::Error; use super::Protocol; use crate::client::env::proxy::starknet::StarknetProposalWithApprovals; -use crate::client::transport::{AssociatedTransport, Operation, Transport, TransportRequest}; +use crate::client::transport::{ + AssociatedTransport, Operation, Transport, TransportLike, TransportRequest, +}; #[derive(Copy, Clone, Debug)] pub enum Starknet {} @@ -31,6 +33,22 @@ impl AssociatedTransport for StarknetTransport<'_> { type Protocol = Starknet; } +impl TransportLike for StarknetTransport<'_> { + type Error = StarknetError; + + async fn try_send( + &self, + request: TransportRequest<'_>, + payload: &Vec, + ) -> Option, Self::Error>> { + if request.protocol == "near" { + Some(self.send(request, payload.to_vec()).await) + } else { + None + } + } +} + #[derive(Copy, Clone, Debug, Deserialize, Serialize)] #[serde(try_from = "serde_creds::Credentials")] pub struct Credentials { diff --git a/crates/context/config/src/client/transport.rs b/crates/context/config/src/client/transport.rs index 3a5156137..8b90ca3bf 100644 --- a/crates/context/config/src/client/transport.rs +++ b/crates/context/config/src/client/transport.rs @@ -2,6 +2,7 @@ use core::error::Error; use std::borrow::Cow; use either::Either; +use serde::ser::StdError; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -18,7 +19,7 @@ pub trait Transport { ) -> Result, Self::Error>; } -#[derive(Debug)] +#[derive(Debug, Clone)] #[non_exhaustive] pub struct TransportRequest<'a> { pub protocol: Cow<'a, str>, @@ -72,13 +73,45 @@ impl Transport for Either { } } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Serialize, Deserialize, Clone)] #[expect(clippy::exhaustive_enums, reason = "Considered to be exhaustive")] pub enum Operation<'a> { Read { method: Cow<'a, str> }, Write { method: Cow<'a, str> }, } +pub trait TransportLike { + type Error; + + async fn try_send( + &self, + request: TransportRequest<'_>, + payload: &Vec, + ) -> Option, Self::Error>>; +} + +impl TransportLike for Both +where + L: TransportLike, + R: TransportLike, +{ + type Error = EitherError; + + async fn try_send( + &self, + request: TransportRequest<'_>, + payload: &Vec, + ) -> Option, Self::Error>> { + if let Some(result) = self.left.try_send(request.clone(), payload).await { + return Some(result.map_err(EitherError::Left)); + } + if let Some(result) = self.right.try_send(request, payload).await { + return Some(result.map_err(EitherError::Right)); + } + None + } +} + pub trait AssociatedTransport: Transport { type Protocol: Protocol; @@ -98,8 +131,10 @@ pub struct Both { impl Transport for Both where - L: AssociatedTransport, - R: AssociatedTransport, + L: TransportLike, + ::Error: StdError, + R: TransportLike, + ::Error: StdError, //no idea why { type Error = EitherError; @@ -108,20 +143,11 @@ where request: TransportRequest<'_>, payload: Vec, ) -> Result, Self::Error> { - if request.protocol == L::protocol() { - self.left - .send(request, payload) - .await - .map_err(EitherError::Left) - } else if request.protocol == R::protocol() { - self.right - .send(request, payload) - .await - .map_err(EitherError::Right) - } else { - return Err(EitherError::UnsupportedProtocol( + match self.try_send(request.clone(), &payload).await { + Some(result) => result, + None => Err(EitherError::UnsupportedProtocol( request.protocol.into_owned(), - )); + )), } } }