feat: add KeysModal for managing private key accounts

- Introduced a new KeysModal component to display and manage nsec/npub for accounts with local private keys.
- Updated AppHeader and Profile views to include a "My Keys" button, conditionally rendered based on the presence of a private key.
- Enhanced the useAccounts composable to determine if the active account holds a local private key, enabling key management functionality.

These changes improve user access to their private key information and enhance the overall account management experience.
This commit is contained in:
Dorian
2026-02-14 12:18:48 +00:00
parent d1ac281ad9
commit 2a16802404
6 changed files with 375 additions and 1 deletions

View File

@@ -273,6 +273,48 @@ export function useAccounts() {
subscriptions.forEach((sub) => sub.unsubscribe())
})
/**
* Whether the active account holds a local private key
* (generated sovereign identity or imported nsec).
* When true, the user can view/export their keys.
*/
const hasPrivateKey = computed(() => {
const acct = activeAccount.value
if (!acct) return false
// PrivateKeyAccount has type 'local' and stores the secret key
// in its signer. Check the account type name set by applesauce.
const typeName = acct.constructor?.name ?? acct.type ?? ''
return typeName === 'PrivateKeyAccount' || typeName === 'local'
})
/**
* Retrieve the active account's nsec and npub.
* Only works for private-key-based accounts (generated or imported nsec).
* Returns null if the active account doesn't hold a local secret key.
*/
async function getAccountKeys(): Promise<{ nsec: string; npub: string; hexPub: string } | null> {
const acct = activeAccount.value
if (!acct?.pubkey) return null
try {
const nip19 = await import('nostr-tools/nip19')
const npub = nip19.npubEncode(acct.pubkey)
// The PrivateKeyAccount stores the secret key in its signer.
// Access it through the account's serialisation (toJSON includes secrets).
const signer = acct.signer ?? acct._signer
const secretKey: Uint8Array | undefined = signer?.key ?? signer?.secretKey ?? signer?._key
if (!secretKey) return null
const nsec = nip19.nsecEncode(secretKey)
return { nsec, npub, hexPub: acct.pubkey }
} catch (err) {
console.warn('[useAccounts] Failed to extract keys:', err)
return null
}
}
return {
// State
activeAccount,
@@ -285,6 +327,10 @@ export function useAccounts() {
activeProfile,
activeProfilePicture,
// Key management
hasPrivateKey,
getAccountKeys,
// Login methods
loginWithExtension,
loginWithPersona,