OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-wallet-desktop commits / b16f7f1

Fix mnemonic export bug - show in modal instead of alert
BUGFIX: Export wallet/identity mnemonic was using alert() which could be blocked by browsers/Pear, resulting in no mnemonic being displayed. Changes: - Added dedicated mnemonic display modal with proper styling - Replaced alert() calls with modal display - Added copy-to-clipboard functionality for mnemonics - Added console logging for debugging export issues - Better error handling and user feedback Impact: - Users can now successfully export and view their recovery phrases - Modal provides better UX with copy button and warnings - Console logs help debug any future issues Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
b16f7f154a2fe6148e8372df0c8d493996f7a198
by plankatron <fleeky@gmail.com> · 2026-01-29T14:59:38.000Z

Changed files (2) +88 -6

desktop/index.html +28 -0
……@@ -995,6 +995,34 @@
995995 </div>
996996 </dialog>
997997
998 <!-- Mnemonic Display Modal -->
999 <dialog id="mnemonic-display-modal" class="modal-dialog">
1000 <div class="modal-header">
1001 <h3>🔐 Wallet Mnemonic</h3>
1002 <button class="modal-close" onclick="closeMnemonicDisplay()">×</button>
1003 </div>
1004 <div class="modal-body">
1005 <div class="warning-box" style="background: #fff3cd; border: 2px solid #ffc107; padding: 15px; border-radius: 8px; margin-bottom: 20px;">
1006 <strong style="color: #856404;">⚠️ CRITICAL: KEEP THIS SAFE!</strong>
1007 <ul style="margin: 10px 0; padding-left: 20px; text-align: left; color: #856404;">
1008 <li>This mnemonic controls your cryptocurrency funds</li>
1009 <li>Anyone with these words can steal your funds</li>
1010 <li>Write them down on paper and store securely</li>
1011 <li>Never share with anyone, never store digitally</li>
1012 </ul>
1013 </div>
1014
1015 <div class="mnemonic-display" style="background: #f5f5f5; padding: 20px; border-radius: 8px; margin-bottom: 20px;">
1016 <pre id="mnemonic-display-text" style="font-size: 16px; font-weight: bold; line-height: 1.8; word-wrap: break-word; white-space: pre-wrap;"></pre>
1017 </div>
1018
1019 <div class="form-actions">
1020 <button class="btn-secondary" onclick="copyMnemonicToClipboard()">📋 Copy to Clipboard</button>
1021 <button class="btn-primary" onclick="closeMnemonicDisplay()">Close</button>
1022 </div>
1023 </div>
1024 </dialog>
1025
9981026 <!-- Error Toast -->
9991027 <div id="error-toast" class="toast"></div>
10001028
desktop/wallet.js +60 -6
……@@ -603,22 +603,32 @@ async function exportIdentity() {
603603 }
604604
605605 try {
606 console.log('[Export] Requesting identity mnemonic...')
606607 const res = await authFetch(`/api/export-identity`, {
607608 method: 'POST',
608609 headers: { 'Content-Type': 'application/json' },
609610 body: JSON.stringify({ password })
610611 })
612
613 console.log('[Export] Response status:', res.status)
611614 const data = await res.json()
615 console.log('[Export] Response data:', data.error ? `Error: ${data.error}` : 'Success')
612616
613617 if (data.error) {
614618 showError(data.error)
615619 return
616620 }
617621
618 // Show mnemonic in alert (not ideal, but simple)
619 alert(`Your Identity Mnemonic (24 words):\n\n${data.mnemonic}\n\n⚠️ KEEP THIS SAFE!`)
622 // Show mnemonic in modal (better than alert)
623 if (data.mnemonic) {
624 showMnemonicDisplay(data.mnemonic, 'Identity Mnemonic (24 words)')
625 } else {
626 showError('No mnemonic returned from server')
627 console.error('[Export] No mnemonic in response:', data)
628 }
620629 } catch (err) {
621 showError('Failed to export identity mnemonic')
630 console.error('[Export] Error:', err)
631 showError('Failed to export identity mnemonic: ' + err.message)
622632 }
623633}
624634
……@@ -635,22 +645,32 @@ async function exportWalletMnemonic() {
635645 }
636646
637647 try {
648 console.log('[Export] Requesting wallet mnemonic...')
638649 const res = await authFetch(`/api/export-wallet`, {
639650 method: 'POST',
640651 headers: { 'Content-Type': 'application/json' },
641652 body: JSON.stringify({ password })
642653 })
654
655 console.log('[Export] Response status:', res.status)
643656 const data = await res.json()
657 console.log('[Export] Response data:', data.error ? `Error: ${data.error}` : 'Success')
644658
645659 if (data.error) {
646660 showError(data.error)
647661 return
648662 }
649663
650 // Show mnemonic in alert (not ideal, but simple)
651 alert(`Your Wallet Mnemonic (12 words):\n\n${data.mnemonic}\n\n⚠️ KEEP THIS SAFE!`)
664 // Show mnemonic in modal (better than alert)
665 if (data.mnemonic) {
666 showMnemonicDisplay(data.mnemonic, 'Wallet Mnemonic (12 words)')
667 } else {
668 showError('No mnemonic returned from server')
669 console.error('[Export] No mnemonic in response:', data)
670 }
652671 } catch (err) {
653 showError('Failed to export wallet mnemonic')
672 console.error('[Export] Error:', err)
673 showError('Failed to export wallet mnemonic: ' + err.message)
654674 }
655675}
656676
……@@ -3633,6 +3653,40 @@ window.setWalletAddressCurrent = setWalletAddressCurrent
36333653window.showAddWallet = showAddWallet
36343654window.showTxDetails = showTxDetails
36353655
3656// Mnemonic display modal functions
3657let currentMnemonic = ''
3658
3659function showMnemonicDisplay(mnemonic, title = 'Mnemonic') {
3660 const modal = document.getElementById('mnemonic-display-modal')
3661 const textEl = document.getElementById('mnemonic-display-text')
3662 const titleEl = modal.querySelector('h3')
3663
3664 currentMnemonic = mnemonic
3665 textEl.textContent = mnemonic
3666 titleEl.textContent = `🔐 ${title}`
3667
3668 modal.showModal()
3669}
3670
3671function closeMnemonicDisplay() {
3672 const modal = document.getElementById('mnemonic-display-modal')
3673 currentMnemonic = ''
3674 modal.close()
3675}
3676
3677async function copyMnemonicToClipboard() {
3678 try {
3679 await navigator.clipboard.writeText(currentMnemonic)
3680 showSuccess('Mnemonic copied to clipboard!')
3681 } catch (err) {
3682 showError('Failed to copy to clipboard')
3683 }
3684}
3685
3686window.showMnemonicDisplay = showMnemonicDisplay
3687window.closeMnemonicDisplay = closeMnemonicDisplay
3688window.copyMnemonicToClipboard = copyMnemonicToClipboard
3689
36363690// Start when DOM is ready
36373691if (document.readyState === 'loading') {
36383692 document.addEventListener('DOMContentLoaded', init)