fix(ipc): lazily initialize the NIP-46 client signer handle
App startup defaults signer_mode to Nip46Client but only SignerModeSet
builds the handle, so a fresh backend answered every nip46_* request
('Show QR' included) with 'not initialized' until the user re-saved the
mode. All nip46_* handlers now ensure the handle exists first.
This commit is contained in:
parent
c5004ebb26
commit
dc58f3889f
1 changed files with 40 additions and 38 deletions
78
src/ipc.rs
78
src/ipc.rs
|
|
@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
|
|||
use serde_json::json;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::app::App;
|
||||
use crate::app::{App, Nip46ClientSignerHandle};
|
||||
use crate::errors::AppError;
|
||||
use crate::feed;
|
||||
use crate::profiles;
|
||||
|
|
@ -337,6 +337,22 @@ fn error_code(err: &AppError) -> String {
|
|||
.unwrap_or_else(|_| "error".to_string())
|
||||
}
|
||||
|
||||
/// Lazily ensure the NIP-46 client signer handle exists and return it.
|
||||
///
|
||||
/// App startup defaults to `signer_mode = Nip46Client` but leaves the handle
|
||||
/// `None` (only SignerModeSet builds one), so a fresh backend answers
|
||||
/// nip46_* requests with "not initialized" until the user re-saves the mode.
|
||||
/// Any nip46_* request initializes the handle when the mode is the NIP-46
|
||||
/// client mode, matching what SignerModeSet would do. The guard is dropped
|
||||
/// before returning so callers can await on the handle without deadlocking.
|
||||
async fn ensure_nip46_signer(app: &Arc<Mutex<App>>) -> Option<Nip46ClientSignerHandle> {
|
||||
let mut guard = app.lock().await;
|
||||
if guard.nip46_signer.is_none() && matches!(guard.signer_mode, SignerMode::Nip46Client) {
|
||||
guard.nip46_signer = Some(Arc::new(Nip46ClientSigner::new(app.clone())));
|
||||
}
|
||||
guard.nip46_signer.clone()
|
||||
}
|
||||
|
||||
/// Main request dispatcher.
|
||||
async fn run(app: &Arc<Mutex<App>>, request: Request) -> Result<serde_json::Value, AppError> {
|
||||
match request {
|
||||
|
|
@ -402,15 +418,11 @@ async fn run(app: &Arc<Mutex<App>>, request: Request) -> Result<serde_json::Valu
|
|||
|
||||
// NIP-46 client signer
|
||||
Request::Nip46Connect { uri, label } => {
|
||||
// Take the signer handle under the lock, then drop the guard
|
||||
// before awaiting: connect() re-locks the App internally (to
|
||||
// persist the connection and resolve its secret), so holding the
|
||||
// guard across the await would deadlock.
|
||||
let signer = {
|
||||
let guard = app.lock().await;
|
||||
guard.nip46_signer.clone()
|
||||
};
|
||||
let Some(signer) = signer else {
|
||||
// Take the signer handle (initializing it if needed), then drop
|
||||
// the guard before awaiting: connect() re-locks the App
|
||||
// internally (to persist the connection and resolve its secret),
|
||||
// so holding the guard across the await would deadlock.
|
||||
let Some(signer) = ensure_nip46_signer(app).await else {
|
||||
return Err(AppError::config(
|
||||
"NIP-46 signer not initialized. Set signer mode to nip46 first.",
|
||||
));
|
||||
|
|
@ -422,11 +434,7 @@ async fn run(app: &Arc<Mutex<App>>, request: Request) -> Result<serde_json::Valu
|
|||
// Same lock discipline as Nip46Connect: pairing persists to the
|
||||
// vault from its background task, so the guard must not be held
|
||||
// across the await.
|
||||
let signer = {
|
||||
let guard = app.lock().await;
|
||||
guard.nip46_signer.clone()
|
||||
};
|
||||
let Some(signer) = signer else {
|
||||
let Some(signer) = ensure_nip46_signer(app).await else {
|
||||
return Err(AppError::config(
|
||||
"NIP-46 signer not initialized. Set signer mode to nip46 first.",
|
||||
));
|
||||
|
|
@ -435,33 +443,27 @@ async fn run(app: &Arc<Mutex<App>>, request: Request) -> Result<serde_json::Valu
|
|||
Ok(json!(status))
|
||||
}
|
||||
Request::Nip46Disconnect => {
|
||||
let guard = app.lock().await;
|
||||
if let Some(signer) = &guard.nip46_signer {
|
||||
signer.disconnect().await?;
|
||||
let status = signer.status().await;
|
||||
Ok(json!(status))
|
||||
} else {
|
||||
Err(AppError::config("NIP-46 signer not initialized"))
|
||||
}
|
||||
let Some(signer) = ensure_nip46_signer(app).await else {
|
||||
return Err(AppError::config("NIP-46 signer not initialized"));
|
||||
};
|
||||
signer.disconnect().await?;
|
||||
let status = signer.status().await;
|
||||
Ok(json!(status))
|
||||
}
|
||||
Request::Nip46Status => {
|
||||
let guard = app.lock().await;
|
||||
if let Some(signer) = &guard.nip46_signer {
|
||||
let status = signer.status().await;
|
||||
Ok(json!(status))
|
||||
} else {
|
||||
Ok(json!({ "connected": false, "error": "Not initialized" }))
|
||||
}
|
||||
let Some(signer) = ensure_nip46_signer(app).await else {
|
||||
return Ok(json!({ "connected": false, "error": "Not initialized" }));
|
||||
};
|
||||
let status = signer.status().await;
|
||||
Ok(json!(status))
|
||||
}
|
||||
Request::Nip46Approve { id, approved } => {
|
||||
let guard = app.lock().await;
|
||||
if let Some(signer) = &guard.nip46_signer {
|
||||
signer.respond_to_approval(&id, approved).await?;
|
||||
let status = signer.status().await;
|
||||
Ok(json!(status))
|
||||
} else {
|
||||
Err(AppError::config("NIP-46 signer not initialized"))
|
||||
}
|
||||
let Some(signer) = ensure_nip46_signer(app).await else {
|
||||
return Err(AppError::config("NIP-46 signer not initialized"));
|
||||
};
|
||||
signer.respond_to_approval(&id, approved).await?;
|
||||
let status = signer.status().await;
|
||||
Ok(json!(status))
|
||||
}
|
||||
|
||||
// Legacy NIP-46 bunker (server mode)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue