feat(signer): adopt real display name/picture for paired NIP-46 identities
A paired profile was stored under the generic pairing label (or a bare npub). adopt_identity now does a best-effort, 3s-capped kind-0 metadata lookup for the learned identity and stores display_name/name plus picture/nip05 on the profile row, falling back to the pairing label when relays are unavailable.
This commit is contained in:
parent
9cfab4bce6
commit
3d5302fbf3
2 changed files with 48 additions and 3 deletions
|
|
@ -561,7 +561,7 @@ fn publish_metadata_blocking(
|
||||||
|
|
||||||
/// Best-effort lookup of the account's latest kind-0 metadata. Import must
|
/// Best-effort lookup of the account's latest kind-0 metadata. Import must
|
||||||
/// still succeed when relays are unavailable, so lookup failures are ignored.
|
/// still succeed when relays are unavailable, so lookup failures are ignored.
|
||||||
fn fetch_profile_metadata(public_key: &PublicKey, relay_urls: &[String]) -> Option<Metadata> {
|
pub fn fetch_profile_metadata(public_key: &PublicKey, relay_urls: &[String]) -> Option<Metadata> {
|
||||||
if relay_urls.is_empty() {
|
if relay_urls.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -793,7 +793,7 @@ impl Nip46ClientSigner {
|
||||||
let message = message.into();
|
let message = message.into();
|
||||||
eprintln!("[nip46] session failed: {message}");
|
eprintln!("[nip46] session failed: {message}");
|
||||||
if let Ok(mut inner) = self.inner.try_lock() {
|
if let Ok(mut inner) = self.inner.try_lock() {
|
||||||
inner.phase = Nip46Phase::Error(message.into());
|
inner.phase = Nip46Phase::Error(message);
|
||||||
inner.task = None;
|
inner.task = None;
|
||||||
inner.client = None;
|
inner.client = None;
|
||||||
inner.conversation_key = None;
|
inner.conversation_key = None;
|
||||||
|
|
@ -1450,13 +1450,58 @@ impl Nip46ClientSigner {
|
||||||
.to_bech32()
|
.to_bech32()
|
||||||
.map_err(|e| format!("Could not encode identity npub: {e}"))?;
|
.map_err(|e| format!("Could not encode identity npub: {e}"))?;
|
||||||
|
|
||||||
|
// Best-effort: look up the identity's kind-0 metadata so the profile
|
||||||
|
// row carries the real display name / picture / nip05 instead of a
|
||||||
|
// bare npub or the generic pairing label. Relay hiccups fall back to
|
||||||
|
// the pairing label — the connection must not depend on them.
|
||||||
|
let relays_for_meta = {
|
||||||
|
let app = self.app.lock().await;
|
||||||
|
crate::relays::enabled_urls(&app.settings)
|
||||||
|
};
|
||||||
|
let meta_npub = identity;
|
||||||
|
let metadata = match tokio::time::timeout(
|
||||||
|
Duration::from_secs(3),
|
||||||
|
tokio::task::spawn_blocking(move || {
|
||||||
|
profiles::fetch_profile_metadata(&meta_npub, &relays_for_meta)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(joined) => joined.ok().flatten(),
|
||||||
|
Err(_elapsed) => None,
|
||||||
|
};
|
||||||
|
let display_label = metadata
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|m| m.display_name.as_deref().or(m.name.as_deref()))
|
||||||
|
.map(str::trim)
|
||||||
|
.filter(|name| !name.is_empty())
|
||||||
|
.map(str::to_string)
|
||||||
|
.unwrap_or(label);
|
||||||
|
|
||||||
// Persist: profile row for the identity, connection + secret store
|
// Persist: profile row for the identity, connection + secret store
|
||||||
// re-keyed under it. Refuses (fails the handshake) if the identity
|
// re-keyed under it. Refuses (fails the handshake) if the identity
|
||||||
// collides with a local profile.
|
// collides with a local profile.
|
||||||
{
|
{
|
||||||
let mut app = self.app.lock().await;
|
let mut app = self.app.lock().await;
|
||||||
profiles::store_remote_profile(&mut app.vault, &identity_npub, label)
|
profiles::store_remote_profile(&mut app.vault, &identity_npub, display_label)
|
||||||
.map_err(|e| e.message().to_string())?;
|
.map_err(|e| e.message().to_string())?;
|
||||||
|
// Carry the looked-up metadata (picture / nip05) onto the row so
|
||||||
|
// the profile shows its real identity, not just a name.
|
||||||
|
if let Some(meta) = &metadata {
|
||||||
|
if let Some(row) = app
|
||||||
|
.vault
|
||||||
|
.profiles
|
||||||
|
.iter_mut()
|
||||||
|
.find(|p| p.public_key == identity_npub)
|
||||||
|
{
|
||||||
|
if row.picture.is_none() {
|
||||||
|
row.picture = meta.picture.clone();
|
||||||
|
}
|
||||||
|
if row.nip05.is_none() {
|
||||||
|
row.nip05 = meta.nip05.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Re-key the stored secret under the identity npub so the
|
// Re-key the stored secret under the identity npub so the
|
||||||
// connection row, VaultRef, and secret store all agree.
|
// connection row, VaultRef, and secret store all agree.
|
||||||
let connect_ref = crate::signer::VaultRef::from_connection(&connection);
|
let connect_ref = crate::signer::VaultRef::from_connection(&connection);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue