From 9a518db7b89581176de8e702af9a99b06e48482d Mon Sep 17 00:00:00 2001 From: archipelago Date: Tue, 16 Jun 2026 09:37:09 -0400 Subject: [PATCH] feat(settings): show DID on every node + add seed-derived node npub (#13) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - DID: the Identity card read the DID only from localStorage('neode_did'), so nodes/browsers that never cached it (e.g. .116/.228) showed no DID. Fall back to the node.did RPC and cache it — the DID now shows everywhere. - npub: add the node's seed-derived Nostr public key (npub) to the Identity card next to the DID + onion, fetched from node.nostr-pubkey, with a copy button. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/views/settings/AccountInfoSection.vue | 72 +++++++++++++++++-- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/neode-ui/src/views/settings/AccountInfoSection.vue b/neode-ui/src/views/settings/AccountInfoSection.vue index 2d365d42..9e55510d 100644 --- a/neode-ui/src/views/settings/AccountInfoSection.vue +++ b/neode-ui/src/views/settings/AccountInfoSection.vue @@ -50,13 +50,19 @@ useBodyScrollLock(showReleaseNotes) const serverTorAddressFromStore = computed(() => store.serverInfo?.['tor-address'] || null) const torAddressFromRpc = ref(null) const serverTorAddress = computed(() => serverTorAddressFromStore.value || torAddressFromRpc.value) +// Fallback DID fetched from the backend when localStorage doesn't have one +// (e.g. a browser/node where onboarding never stored `neode_did`). +const didFromRpc = ref(null) const userDid = computed(() => { try { - return localStorage.getItem('neode_did') || null + return localStorage.getItem('neode_did') || didFromRpc.value } catch { - return null + return didFromRpc.value } }) +// The node's seed-derived Nostr public key (npub), fetched from the backend. +const userNpub = ref(null) +const copiedNpub = ref(false) const copiedOnion = ref(false) const copiedDid = ref(false) @@ -100,6 +106,17 @@ async function copyDid() { setTimeout(() => { copiedDid.value = false }, 2000) } +async function copyNpub() { + if (!userNpub.value) return + try { + await navigator.clipboard.writeText(userNpub.value) + } catch { + return + } + copiedNpub.value = true + setTimeout(() => { copiedNpub.value = false }, 2000) +} + // Load Tor address on mount if not in store async function init() { if (!serverTorAddressFromStore.value) { @@ -110,6 +127,29 @@ async function init() { if (import.meta.env.DEV) console.warn('Tor address may not be available yet', e) } } + // DID: fall back to the node.did RPC when localStorage doesn't have one, so + // the Identity card shows the DID on every node (not just ones where the + // browser cached it during onboarding). + let storedDid: string | null = null + try { storedDid = localStorage.getItem('neode_did') } catch { /* unavailable */ } + if (!storedDid) { + try { + const res = await rpcClient.call<{ did?: string }>({ method: 'node.did' }) + if (res?.did) { + didFromRpc.value = res.did + try { localStorage.setItem('neode_did', res.did) } catch { /* unavailable */ } + } + } catch (e) { + if (import.meta.env.DEV) console.warn('node.did unavailable', e) + } + } + // The node's seed-derived Nostr public key (npub) for the Identity card. + try { + const res = await rpcClient.call<{ nostr_npub?: string }>({ method: 'node.nostr-pubkey' }) + if (res?.nostr_npub) userNpub.value = res.nostr_npub + } catch (e) { + if (import.meta.env.DEV) console.warn('node.nostr-pubkey unavailable', e) + } } init() @@ -1516,8 +1556,8 @@ init()

{{ t('settings.loggedIn') }}

- -
+ +
@@ -1540,7 +1580,29 @@ init()

{{ userDid }}

{{ t('settings.didHelper') }}

-
+
+
+
+ + + +

Node npub

+
+ +
+

{{ userNpub }}

+

Your node's Nostr public key, derived from its seed.

+
+