reown_relay_client/websocket/
outbound.rs

1use {
2    crate::{error::Error, ClientError},
3    pin_project::pin_project,
4    reown_relay_rpc::rpc::{Params, ServiceRequest},
5    std::{
6        future::Future,
7        marker::PhantomData,
8        pin::Pin,
9        task::{ready, Context, Poll},
10    },
11    tokio::sync::oneshot,
12};
13
14/// An outbound request wrapper created by [`create_request()`]. Intended be
15/// used with [`ClientStream`][crate::client::ClientStream].
16#[derive(Debug)]
17pub struct OutboundRequest {
18    pub(super) params: Params,
19    pub(super) tx: oneshot::Sender<Result<serde_json::Value, ClientError>>,
20}
21
22impl OutboundRequest {
23    pub(super) fn new(
24        params: Params,
25        tx: oneshot::Sender<Result<serde_json::Value, ClientError>>,
26    ) -> Self {
27        Self { params, tx }
28    }
29}
30
31/// Future that resolves with the RPC response for the specified request.
32#[must_use = "futures do nothing unless you `.await` or poll them"]
33#[pin_project]
34pub struct ResponseFuture<T> {
35    #[pin]
36    rx: oneshot::Receiver<Result<serde_json::Value, ClientError>>,
37    _marker: PhantomData<T>,
38}
39
40impl<T> ResponseFuture<T> {
41    pub(super) fn new(rx: oneshot::Receiver<Result<serde_json::Value, ClientError>>) -> Self {
42        Self {
43            rx,
44            _marker: PhantomData,
45        }
46    }
47}
48
49impl<T> Future for ResponseFuture<T>
50where
51    T: ServiceRequest,
52{
53    type Output = Result<T::Response, Error<T::Error>>;
54
55    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
56        let this = self.project();
57
58        let result = ready!(this.rx.poll(cx)).map_err(|_| ClientError::ChannelClosed)?;
59
60        let result = match result {
61            Ok(value) => serde_json::from_value(value).map_err(ClientError::Deserialization),
62
63            Err(err) => Err(err),
64        };
65
66        Poll::Ready(result.map_err(Into::into))
67    }
68}
69
70/// Future that resolves with the RPC response, consuming it and returning
71/// `Result<(), Error>`.
72#[must_use = "futures do nothing unless you `.await` or poll them"]
73#[pin_project]
74pub struct EmptyResponseFuture<T> {
75    #[pin]
76    rx: ResponseFuture<T>,
77}
78
79impl<T> EmptyResponseFuture<T> {
80    pub(super) fn new(rx: ResponseFuture<T>) -> Self {
81        Self { rx }
82    }
83}
84
85impl<T> Future for EmptyResponseFuture<T>
86where
87    T: ServiceRequest,
88{
89    type Output = Result<(), Error<T::Error>>;
90
91    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
92        Poll::Ready(ready!(self.project().rx.poll(cx)).map(|_| ()))
93    }
94}
95
96/// Creates an RPC request and returns a tuple of the request and a response
97/// future. The request is intended to be used with
98/// [`ClientStream`][crate::client::ClientStream].
99pub fn create_request<T>(data: T) -> (OutboundRequest, ResponseFuture<T>)
100where
101    T: ServiceRequest,
102{
103    let (tx, rx) = oneshot::channel();
104
105    (
106        OutboundRequest::new(data.into_params(), tx),
107        ResponseFuture::new(rx),
108    )
109}