feat: show Nostr npub alongside DID in onboarding

OnboardingDid.vue now fetches node.nostr-pubkey after DID is
retrieved and displays it with a copy button. Both identities
are cached in localStorage. Added missing copyNpub function.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-12 22:50:35 +00:00
parent d6bbe2c980
commit fa64b4302e
2 changed files with 45 additions and 4 deletions

View File

@@ -69,9 +69,30 @@
</svg>
</button>
</div>
<p class="text-base text-white/60">
This is your sovereign digital identity. It proves you are you, without any company in the middle.
</p>
<p class="text-xs text-white/50 mb-3">For Web5, federation, and verifiable credentials</p>
</div>
<!-- Nostr ID -->
<div v-if="nostrNpub" class="text-left mt-4">
<h3 class="text-sm font-semibold text-white/80 mb-2 uppercase tracking-wide">Your Nostr ID</h3>
<div class="bg-black/40 rounded-lg p-4 mb-3 backdrop-blur-sm border border-white/10 flex items-start gap-3">
<p class="text-white/95 font-mono text-sm break-all leading-relaxed flex-1">
{{ nostrNpub }}
</p>
<button
@click="copyNpub"
class="shrink-0 p-1.5 rounded hover:bg-white/10 transition-colors text-white/50 hover:text-white/90"
:title="npubCopied ? 'Copied!' : 'Copy npub'"
>
<svg v-if="!npubCopied" class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" />
</svg>
<svg v-else class="w-4 h-4 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7" />
</svg>
</button>
</div>
<p class="text-xs text-white/50">For Nostr social apps and NIP-07 signing</p>
</div>
</div>
</div>
@@ -104,10 +125,12 @@ import { rpcClient } from '@/api/rpc-client'
const router = useRouter()
const generatedDid = ref<string>('')
const nostrNpub = ref<string>('')
const isGenerating = ref(false)
const waitingForServer = ref(false)
const autoAdvancing = ref(false)
const didCopied = ref(false)
const npubCopied = ref(false)
const elapsedSeconds = ref(0)
const elapsedDisplay = ref('0:00')
let retryTimer: ReturnType<typeof setTimeout> | null = null
@@ -147,6 +170,15 @@ async function fetchDid() {
storeDidState(did, pubkey)
isGenerating.value = false
waitingForServer.value = false
// Fetch Nostr npub in parallel (non-blocking)
rpcClient.getNostrPubkey().then(({ nostr_npub }) => {
if (nostr_npub) {
nostrNpub.value = nostr_npub
localStorage.setItem('neode_nostr_npub', nostr_npub)
}
}).catch(() => { /* Nostr key may not exist yet */ })
autoAdvanceAfterDelay()
} catch {
isGenerating.value = false
@@ -167,6 +199,8 @@ function autoAdvanceAfterDelay() {
onMounted(() => {
const cached = localStorage.getItem('neode_did')
const cachedNpub = localStorage.getItem('neode_nostr_npub')
if (cachedNpub) nostrNpub.value = cachedNpub
if (cached && !cached.includes('...')) {
generatedDid.value = cached
} else {
@@ -194,6 +228,13 @@ function copyDid() {
didCopied.value = true
setTimeout(() => { didCopied.value = false }, 2000)
}
function copyNpub() {
if (!nostrNpub.value) return
navigator.clipboard.writeText(nostrNpub.value).catch(() => {})
npubCopied.value = true
setTimeout(() => { npubCopied.value = false }, 2000)
}
</script>
<style scoped>