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 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 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 let Some(user_public_key) = request_event.public_keys().next() else {
106 return self.poll_next(cx);
108 };
109
110 let Some(user_secret_key) = self.key_manager.get_secret_key(user_public_key) else {
111 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 {}