import browser from 'webextension-polyfill' import React, { useState, useEffect, useContext } from 'react' import { toast } from 'react-toastify' import { privateKeyFromSeedWords } from 'nostr-tools/nip06' import { bytesToHex, hexToBytes } from 'nostr-tools/utils' import { getPublicKey, finalizeEvent } from 'nostr-tools/pure' import { getSessionVault, setSessionVault, pool, DEFAULT_RELAYS } from '../common' import Modal from './Modal' import MainContext from '../contexts/MainContext' import { ensureRelayListExists, fetchRelayList } from '../helpers/outbox' const DeriveAccountModal = ({ isOpen, onClose, callBack }) => { const { updateAccounts } = useContext(MainContext) const [showModal, setShowModal] = useState(isOpen) const [name, setName] = useState('') useEffect(() => { setShowModal(isOpen) }, [isOpen]) const closeModal = () => { setShowModal(false) onClose() } const addAccount = async (e) => { e.preventDefault() const vault = await getSessionVault() if (!vault) { toast.error('Session expired. Please unlock your vault again.') return } vault.accountIndex++ const prvKey = bytesToHex(privateKeyFromSeedWords(vault.mnemonic, vault.passphrase, vault.accountIndex)) const prvKeyBytes = hexToBytes(prvKey) const pubkey = getPublicKey(prvKeyBytes) vault.accounts.push({ prvKey, }) vault.accountDefault = prvKey // Encrypt via background (key stays in background memory) const response = await browser.runtime.sendMessage({ type: 'ENCRYPT_VAULT', data: vault }) if (!response.success) { toast.error('Failed to save vault. Please unlock again.') return } await browser.storage.local.set({ encryptedVault: response.encryptedData }) await setSessionVault(vault) await updateAccounts() // Ensure relay list exists first (publishes default relays if none exist) await ensureRelayListExists(pubkey, prvKeyBytes, finalizeEvent) // Publish profile using outbox model (write relays) if (name && name !== '') { let relays = DEFAULT_RELAYS try { const { relays: relayList } = await fetchRelayList(pubkey) const writeRelays = relayList.filter(r => r.write).map(r => r.url) if (writeRelays.length > 0) { relays = writeRelays } } catch (err) { console.error('Failed to fetch relay list, using defaults:', err) } const event = { kind: 0, created_at: Math.floor(Date.now() / 1000), tags: [], content: JSON.stringify({ name: name, display_name: name, }), } const signedEvent = finalizeEvent(event, hexToBytes(prvKey)) await Promise.any(pool.publish(relays, signedEvent)) } setName('') toast.success('Account created successfully') callBack() } return (