commit 7c4d6c4a518b242e299b27fd5e8550dae25a4cd3
parent ec5d8d1d80f1d1137930d1435f98f4c6c342e121
Author: triesap <triesap@radroots.dev>
Date: Tue, 6 Jan 2026 18:09:05 +0000
nip46: add jsonrpc sign_event
- add nip46.sign_event rpc method
- sign events via nip46 client request flow
- validate session perms and signer pubkey
- register sign_event endpoint
Diffstat:
2 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/src/transport/jsonrpc/methods/nip46/mod.rs b/src/transport/jsonrpc/methods/nip46/mod.rs
@@ -8,6 +8,7 @@ use crate::transport::jsonrpc::{MethodRegistry, RpcContext};
pub mod connect;
pub mod get_public_key;
pub mod ping;
+pub mod sign_event;
pub mod session_close;
pub mod session_status;
pub mod status;
@@ -18,6 +19,7 @@ pub fn module(ctx: RpcContext, registry: MethodRegistry) -> Result<RpcModule<Rpc
connect::register(&mut m, ®istry)?;
ping::register(&mut m, ®istry)?;
get_public_key::register(&mut m, ®istry)?;
+ sign_event::register(&mut m, ®istry)?;
session_status::register(&mut m, ®istry)?;
session_close::register(&mut m, ®istry)?;
Ok(m)
diff --git a/src/transport/jsonrpc/methods/nip46/sign_event.rs b/src/transport/jsonrpc/methods/nip46/sign_event.rs
@@ -0,0 +1,49 @@
+use anyhow::Result;
+use jsonrpsee::server::RpcModule;
+use serde::{Deserialize, Serialize};
+
+use crate::core::nip46::session::Nip46Session;
+use crate::transport::jsonrpc::nip46::client;
+use crate::transport::jsonrpc::{MethodRegistry, RpcContext, RpcError};
+use nostr::UnsignedEvent;
+
+#[derive(Debug, Deserialize)]
+struct Nip46SignEventParams {
+ session_id: String,
+ event: UnsignedEvent,
+}
+
+#[derive(Clone, Debug, Serialize)]
+struct Nip46SignEventResponse {
+ event: nostr::Event,
+}
+
+pub fn register(m: &mut RpcModule<RpcContext>, registry: &MethodRegistry) -> Result<()> {
+ registry.track("nip46.sign_event");
+ m.register_async_method("nip46.sign_event", |params, ctx, _| async move {
+ let Nip46SignEventParams { session_id, event } = params
+ .parse()
+ .map_err(|e| RpcError::InvalidParams(e.to_string()))?;
+ let session = ctx
+ .state
+ .nip46_sessions
+ .get(&session_id)
+ .await
+ .ok_or_else(|| RpcError::InvalidParams("unknown session".to_string()))?;
+ if !has_permission(&session, "sign_event") {
+ return Err(RpcError::Other("unauthorized sign_event".to_string()));
+ }
+ if event.pubkey != session.remote_signer_pubkey {
+ return Err(RpcError::InvalidParams(
+ "event pubkey does not match remote signer".to_string(),
+ ));
+ }
+ let event = client::sign_event(&session, event, "sign_event").await?;
+ Ok::<Nip46SignEventResponse, RpcError>(Nip46SignEventResponse { event })
+ })?;
+ Ok(())
+}
+
+fn has_permission(session: &Nip46Session, perm: &str) -> bool {
+ session.perms.iter().any(|entry| entry == perm)
+}