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:
parent
d6bbe2c980
commit
fa64b4302e
@ -474,7 +474,7 @@
|
||||
|
||||
- [x] **IDENT-01** — Auto-generate Nostr keypair during identity creation. In `core/archipelago/src/identity_manager.rs` `create()` method, after generating the Ed25519 keypair, immediately call `create_nostr_key()` on the same identity so every identity gets both Ed25519 (DID) and secp256k1 (Nostr) keys from creation. Update the `IdentityInfo` struct returned by `identity.create` and `identity.list` RPC to always include `nostr_pubkey` (hex) and `nostr_npub` (bech32) fields when present. **Acceptance**: Call `identity.create`, then `identity.get` — response includes both `did` and `nostr_npub`. Deploy and verify.
|
||||
|
||||
- [ ] **IDENT-02** — Update onboarding to show DID + npub. In `neode-ui/src/views/OnboardingDid.vue`, after fetching the node DID, also fetch `node.nostr-pubkey` (already exists as RPC endpoint). Display both: "Your DID: did:key:z..." and "Your Nostr ID: npub1..." with copy buttons for each. Add a brief explanation: DID for Web5/federation, npub for Nostr apps. Store `nostr_npub` in localStorage alongside `neode_did`. **Acceptance**: Fresh onboarding flow shows both DID and npub on the identity screen. Deploy and verify at http://192.168.1.228.
|
||||
- [x] **IDENT-02** — Update onboarding to show DID + npub. In `neode-ui/src/views/OnboardingDid.vue`, after fetching the node DID, also fetch `node.nostr-pubkey` (already exists as RPC endpoint). Display both: "Your DID: did:key:z..." and "Your Nostr ID: npub1..." with copy buttons for each. Add a brief explanation: DID for Web5/federation, npub for Nostr apps. Store `nostr_npub` in localStorage alongside `neode_did`. **Acceptance**: Fresh onboarding flow shows both DID and npub on the identity screen. Deploy and verify at http://192.168.1.228.
|
||||
|
||||
- [ ] **IDENT-03** — Wire real signature verification in onboarding. In `neode-ui/src/views/OnboardingVerify.vue`, replace `generateMockSignature()` with a real call to `rpcClient.signChallenge(challenge)`. Generate a random challenge string, send it to the backend, display the real Ed25519 signature. Add a "Verify" button that calls `identity.verify` with the DID, challenge, and signature to prove the node controls its keys. Show green checkmark on success. **Acceptance**: Onboarding verify step shows real cryptographic signature and verification succeeds. Deploy and verify.
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user