import { nostrAuthService } from '@/lib/nostrAuth' import { keyManagementService } from '@/lib/keyManagement' import { t } from '@/lib/i18n' import type { PublicKeys } from './types' import { extractKeyFromInput, isValidPrivateKeyFormat } from './keyImportParsing' export interface KeyManagementManagerState { publicKeys: PublicKeys | null accountExists: boolean loading: boolean error: string | null importKey: string importing: boolean showImportForm: boolean showReplaceWarning: boolean recoveryPhrase: string[] | null newNpub: string | null copiedNpub: boolean copiedPublicKey: boolean copiedRecoveryPhrase: boolean } export type PatchState = (patch: Partial) => void export const INITIAL_KEY_MANAGEMENT_STATE: KeyManagementManagerState = { publicKeys: null, accountExists: false, loading: true, error: null, importKey: '', importing: false, showImportForm: false, showReplaceWarning: false, recoveryPhrase: null, newNpub: null, copiedNpub: false, copiedPublicKey: false, copiedRecoveryPhrase: false, } export async function loadKeys(params: { patchState: PatchState }): Promise { try { params.patchState({ loading: true, error: null }) const exists = await nostrAuthService.accountExists() params.patchState({ accountExists: exists }) if (!exists) { params.patchState({ publicKeys: null }) return } const keys = await keyManagementService.getPublicKeys() params.patchState({ publicKeys: keys ?? null }) } catch (e) { const errorMessage = e instanceof Error ? e.message : t('settings.keyManagement.loading') params.patchState({ error: errorMessage }) console.error('[KeyManagement] Error loading keys:', e) } finally { params.patchState({ loading: false }) } } export async function handleImport(params: { state: KeyManagementManagerState patchState: PatchState }): Promise { const extractedKey = validateAndExtractImportKey({ importKey: params.state.importKey, patchState: params.patchState }) if (!extractedKey) { return } if (params.state.accountExists) { params.patchState({ showReplaceWarning: true }) return } await performImport({ key: extractedKey, accountExists: false, patchState: params.patchState }) } export async function confirmReplace(params: { state: KeyManagementManagerState patchState: PatchState }): Promise { const extractedKey = validateAndExtractImportKey({ importKey: params.state.importKey, patchState: params.patchState }) if (!extractedKey) { return } await performImport({ key: extractedKey, accountExists: true, patchState: params.patchState }) } function validateAndExtractImportKey(params: { importKey: string; patchState: PatchState }): string | null { if (!params.importKey.trim()) { params.patchState({ error: t('settings.keyManagement.import.error.required') }) return null } const extractedKey = extractKeyFromInput(params.importKey) if (!extractedKey) { params.patchState({ error: t('settings.keyManagement.import.error.invalid') }) return null } if (!isValidPrivateKeyFormat(extractedKey)) { params.patchState({ error: t('settings.keyManagement.import.error.invalid') }) return null } return extractedKey } async function performImport(params: { key: string accountExists: boolean patchState: PatchState }): Promise { try { params.patchState({ importing: true, error: null, showReplaceWarning: false }) if (params.accountExists) { await nostrAuthService.deleteAccount() } const result = await nostrAuthService.createAccount(params.key) params.patchState({ recoveryPhrase: result.recoveryPhrase, newNpub: result.npub, importKey: '', showImportForm: false, }) await loadKeys({ patchState: params.patchState }) await maybeStartUserSync({ publicKey: result.publicKey }) } catch (e) { const errorMessage = e instanceof Error ? e.message : t('settings.keyManagement.import.error.failed') params.patchState({ error: errorMessage }) console.error('[KeyManagement] Error importing key:', e) } finally { params.patchState({ importing: false }) } } async function maybeStartUserSync(params: { publicKey: string | undefined }): Promise { if (!params.publicKey) { return } const { swClient } = await import('@/lib/swClient') const isReady = await swClient.isReady() if (isReady) { void swClient.startUserSync(params.publicKey) } } export async function copyToClipboard(params: { text: string onCopied: () => void onCopyFailed: (error: unknown) => void }): Promise { try { await navigator.clipboard.writeText(params.text) params.onCopied() } catch (e) { params.onCopyFailed(e) } }