use super::nip04_jsonrpc::{
jsonrpc_response_to_nip04_encrypted_event, nip04_encrypted_event_to_jsonrpc_request,
};
use crate::json_rpc::{JsonRpcServer, JsonRpcServerHandler};
use crate::uds_req_res::UdsResponse;
use crate::{
json_rpc::{JsonRpcRequest, JsonRpcResponse, JsonRpcServerTransport},
uds_req_res::server::UnixDomainSocketServerTransport,
};
use futures::{FutureExt, StreamExt};
use nostr_sdk::{Event, Keys, PublicKey, SecretKey};
use std::sync::Arc;
use std::task::Poll;
pub trait KeyManager: Send + Sync {
fn get_secret_key(&self, public_key: &PublicKey) -> Option<SecretKey>;
}
pub struct Nip55Server {
server: JsonRpcServer,
}
impl Nip55Server {
pub fn start(
uds_address: impl Into<String>,
key_manager: Arc<dyn KeyManager>,
handler: impl JsonRpcServerHandler<(JsonRpcRequest, SecretKey)> + 'static,
) -> std::io::Result<Self> {
let transport = Nip55ServerTransport::connect_and_start(uds_address, key_manager)?;
let server = JsonRpcServer::start(transport, handler);
Ok(Self { server })
}
pub fn stop(self) {
self.server.stop();
}
}
struct Nip55ServerTransport {
transport_server: UnixDomainSocketServerTransport<Event, Event>,
key_manager: Arc<dyn KeyManager>,
}
impl Nip55ServerTransport {
fn connect_and_start(
uds_address: impl Into<String>,
key_manager: Arc<dyn KeyManager>,
) -> std::io::Result<Self> {
Ok(Self {
transport_server: UnixDomainSocketServerTransport::connect_and_start(uds_address)?,
key_manager,
})
}
}
impl futures::Stream for Nip55ServerTransport {
type Item = (
(JsonRpcRequest, SecretKey),
futures::channel::oneshot::Sender<JsonRpcResponse>,
);
fn poll_next(
mut self: std::pin::Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> Poll<Option<Self::Item>> {
let (request_event, response_event_sender) = match self.transport_server.poll_next_unpin(cx)
{
Poll::Ready(Some((request_event, response_event_sender))) => {
(request_event, response_event_sender)
}
Poll::Ready(None) => return Poll::Pending,
Poll::Pending => return Poll::Pending,
};
let request_event_kind = request_event.kind();
let request_event_author = request_event.author();
let user_public_key = match request_event.public_keys().next() {
Some(user_public_key) => user_public_key,
None => {
return Poll::Pending;
}
};
let user_secret_key = match self.key_manager.get_secret_key(user_public_key) {
Some(user_secret_key) => user_secret_key,
None => {
return Poll::Pending;
}
};
let user_keypair = Keys::new(user_secret_key.clone());
let request = match nip04_encrypted_event_to_jsonrpc_request(&request_event, &user_keypair)
{
Ok(request) => request,
Err(_) => return Poll::Pending,
};
let (response_sender, response_receiver) = futures::channel::oneshot::channel();
tokio::spawn(async move {
response_receiver
.then(|response| async {
match response {
Ok(response) => {
let response_event = jsonrpc_response_to_nip04_encrypted_event(
request_event_kind,
&response,
request_event_author,
&user_keypair,
)
.unwrap();
response_event_sender.send(response_event).unwrap();
}
Err(_) => {
let response_event = jsonrpc_response_to_nip04_encrypted_event(
request_event_kind,
&JsonRpcResponse::internal_error_response(
"Internal error.".to_string(),
),
request_event_author,
&user_keypair,
)
.unwrap();
response_event_sender.send(response_event).unwrap();
}
}
})
.await;
});
Poll::Ready(Some(((request, user_secret_key), response_sender)))
}
}
impl AsRef<JsonRpcRequest> for (JsonRpcRequest, SecretKey) {
fn as_ref(&self) -> &JsonRpcRequest {
&self.0
}
}
impl JsonRpcServerTransport<(JsonRpcRequest, SecretKey)> for Nip55ServerTransport {}