diff --git a/src/signer/nip46_client.rs b/src/signer/nip46_client.rs index ec4c3e1..30105ba 100644 --- a/src/signer/nip46_client.rs +++ b/src/signer/nip46_client.rs @@ -38,6 +38,13 @@ const REQUEST_TIMEOUT: Duration = Duration::from_secs(30); /// How long the connect handshake can involve a human approving the app on /// the signer's screen, so it gets a far longer leash than ordinary RPCs. const HANDSHAKE_TIMEOUT: Duration = Duration::from_secs(120); +/// How long a `sign_event` may wait for the signer's answer. Like the +/// handshake, every sign waits for a human to notice and approve the prompt +/// on the signer's device, so it needs the same long leash rather than the +/// 30s ordinary-RPC one: live pairing (Sep 23) showed a perfectly valid +/// signature arriving after the 30s leash expired, discarded as +/// "stale/duplicate response: no waiter" while the user watched failures. +const SIGN_TIMEOUT: Duration = Duration::from_secs(120); /// How long a pairing QR (client-initiated `nostrconnect://`) stays live /// while a human opens their signer and scans it. const PAIRING_TIMEOUT: Duration = Duration::from_secs(300); @@ -1153,12 +1160,16 @@ impl Nip46ClientSigner { /// return [`SigningError`] rather than falling back to any local key. The /// waiter is always removed from the pending map, even on timeout, so a /// late response to an abandoned request finds nothing to wake. + /// + /// Uses the human-approval leash ([`SIGN_TIMEOUT`]), not the 30s + /// ordinary-RPC one: every call here asks a human to approve on the + /// signer's device. async fn send_remote_request( &self, method: &str, params: Vec, ) -> Result { - self.send_rpc(method, params, REQUEST_TIMEOUT, true).await + self.send_rpc(method, params, SIGN_TIMEOUT, true).await } /// Send an encrypted NIP-46 RPC and await its response.