nip_55/
server.rs

1use super::nip04_jsonrpc::{
2    jsonrpc_response_to_nip04_encrypted_event, nip04_encrypted_event_to_jsonrpc_request,
3};
4use crate::json_rpc::{JsonRpcResponseData, JsonRpcServerStream, SingleOrBatch};
5use crate::{
6    json_rpc::{JsonRpcRequest, JsonRpcResponse, JsonRpcServerTransport},
7    uds_req_res::server::UnixDomainSocketServerTransport,
8};
9use futures::{FutureExt, StreamExt};
10use nostr_sdk::{Event, Keys, PublicKey, SecretKey};
11use std::pin::Pin;
12use std::sync::Arc;
13use std::task::{Context, Poll};
14
15pub trait KeyManager: Send + Sync {
16    // TODO: Make this async.
17    fn get_secret_key(&self, public_key: &PublicKey) -> Option<SecretKey>;
18}
19
20pub struct Nip55ServerStream {
21    #[allow(clippy::type_complexity)]
22    stream: Pin<
23        Box<
24            dyn futures::Stream<
25                    Item = (
26                        SingleOrBatch<JsonRpcRequest>,
27                        SecretKey,
28                        futures::channel::oneshot::Sender<SingleOrBatch<JsonRpcResponseData>>,
29                    ),
30                > + Send,
31        >,
32    >,
33}
34
35impl futures::Stream for Nip55ServerStream {
36    type Item = (
37        SingleOrBatch<JsonRpcRequest>,
38        SecretKey,
39        futures::channel::oneshot::Sender<SingleOrBatch<JsonRpcResponseData>>,
40    );
41
42    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
43        self.stream.poll_next_unpin(cx)
44    }
45}
46
47impl Nip55ServerStream {
48    pub fn start<SingleOrBatchRequest: AsRef<SingleOrBatch<JsonRpcRequest>> + Send + 'static>(
49        uds_address: impl Into<String>,
50        key_manager: Arc<dyn KeyManager>,
51    ) -> std::io::Result<Self> {
52        Ok(Self {
53            stream: Box::pin(
54                JsonRpcServerStream::start(Nip55ServerTransport::connect_and_start(
55                    uds_address,
56                    key_manager,
57                )?)
58                .map(|((req, secret_key), res_sender)| (req, secret_key, res_sender)),
59            ),
60        })
61    }
62}
63
64struct Nip55ServerTransport {
65    transport_server: UnixDomainSocketServerTransport<Event, Event>,
66    key_manager: Arc<dyn KeyManager>,
67}
68
69impl Nip55ServerTransport {
70    /// Create a new `Nip55ServerTransport` and start listening for incoming
71    /// connections. **MUST** be called from within a tokio runtime.
72    fn connect_and_start(
73        uds_address: impl Into<String>,
74        key_manager: Arc<dyn KeyManager>,
75    ) -> std::io::Result<Self> {
76        Ok(Self {
77            transport_server: UnixDomainSocketServerTransport::connect_and_start(uds_address)?,
78            key_manager,
79        })
80    }
81}
82
83impl futures::Stream for Nip55ServerTransport {
84    type Item = (
85        (SingleOrBatch<JsonRpcRequest>, SecretKey),
86        futures::channel::oneshot::Sender<SingleOrBatch<JsonRpcResponse>>,
87    );
88
89    fn poll_next(
90        mut self: std::pin::Pin<&mut Self>,
91        cx: &mut std::task::Context<'_>,
92    ) -> Poll<Option<Self::Item>> {
93        let (request_event, response_event_sender) = match self.transport_server.poll_next_unpin(cx)
94        {
95            Poll::Ready(Some((request_event, response_event_sender))) => {
96                (request_event, response_event_sender)
97            }
98            Poll::Ready(None) | Poll::Pending => return Poll::Pending,
99        };
100
101        let request_event_kind = request_event.kind;
102        let request_event_author = request_event.pubkey;
103
104        // TODO: Should we attempt to NIP-04 decrypt the request for all public keys rather than just the first one?
105        let Some(user_public_key) = request_event.public_keys().next() else {
106            // TODO: Should we send a response to `response_event_sender`? What secret key should we use to sign it?
107            return self.poll_next(cx);
108        };
109
110        let Some(user_secret_key) = self.key_manager.get_secret_key(user_public_key) else {
111            // TODO: Should we send a response to `response_event_sender`? What secret key should we use to sign it?
112            return self.poll_next(cx);
113        };
114
115        let user_keypair = Keys::new(user_secret_key.clone());
116
117        let Ok(request) = nip04_encrypted_event_to_jsonrpc_request(&request_event, &user_keypair)
118        else {
119            return self.poll_next(cx);
120        };
121
122        let (response_sender, response_receiver) = futures::channel::oneshot::channel();
123
124        tokio::spawn(async move {
125            response_receiver
126                .then(|response| async {
127                    if let Ok(response) = response {
128                        let response_event = jsonrpc_response_to_nip04_encrypted_event(
129                            request_event_kind,
130                            &response,
131                            request_event_author,
132                            &user_keypair,
133                        )
134                        .unwrap();
135                        response_event_sender.send(response_event).unwrap();
136                    }
137                })
138                .await;
139        });
140
141        Poll::Ready(Some(((request, user_secret_key), response_sender)))
142    }
143}
144
145impl AsRef<SingleOrBatch<JsonRpcRequest>> for (SingleOrBatch<JsonRpcRequest>, SecretKey) {
146    fn as_ref(&self) -> &SingleOrBatch<JsonRpcRequest> {
147        &self.0
148    }
149}
150
151impl JsonRpcServerTransport<(SingleOrBatch<JsonRpcRequest>, SecretKey)> for Nip55ServerTransport {}