OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-wallet-desktop commits / f58b9e4

Fix: use dataset flag to prevent address selector cascade, remove reload from onchange
Deployment: testing (hyper-wallet-desktop-test) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
f58b9e43a3ad2e0995e076cf0468b92b27dd8ede
by plankatron <fleeky@gmail.com> · 2026-01-30T02:30:44.000Z

Changed files (2) +33 -16

.claude/deployment-history.json +2 -2
……@@ -4,7 +4,7 @@
44 "branch": "testing",
55 "version": "unknown",
66 "pear_key": "pear://unknown",
7 "deployed_at": "2026-01-29T21:21:51-05:00",
8 "commit_message": "Fix: tokens share ETH address - don't reload address selector for USDT/USDC",
7 "deployed_at": "2026-01-29T21:25:34-05:00",
8 "commit_message": "Fix: prevent address selector cascade, preserve unified view on address change",
99 "tmux": "pear-seed:5"
1010}
desktop/wallet.js +31 -14
……@@ -1625,14 +1625,17 @@ function updateWalletView() {
16251625}
16261626
16271627// Load wallet addresses into the selector dropdown
1628// Flag to prevent onchange cascade when programmatically updating selector
1629let isUpdatingAddressSelector = false
1628// Counter to prevent onchange cascade when programmatically updating selector
1629// Using a counter instead of boolean to handle concurrent/nested calls
1630let addressSelectorUpdateCount = 0
16301631
16311632async function loadWalletAddressSelector() {
16321633 const select = document.getElementById('wallet-address-select')
16331634
1634 // Set flag to prevent onchange from firing during programmatic update
1635 isUpdatingAddressSelector = true
1635 // Increment counter to prevent onchange from firing during programmatic update
1636 addressSelectorUpdateCount++
1637 const myUpdateId = addressSelectorUpdateCount
1638
16361639 select.innerHTML = '<option value="">Loading...</option>'
16371640
16381641 try {
……@@ -1641,15 +1644,16 @@ async function loadWalletAddressSelector() {
16411644 const res = await authFetch(`/api/addresses/${selectedNetwork}-${addressChain}`)
16421645 const data = await res.json()
16431646
1647 // Check if we're still the latest update (another call may have started)
1648 if (myUpdateId !== addressSelectorUpdateCount) return
1649
16441650 if (data.error) {
16451651 select.innerHTML = '<option value="">Error loading addresses</option>'
1646 isUpdatingAddressSelector = false
16471652 return
16481653 }
16491654
16501655 if (data.addresses.length === 0) {
16511656 select.innerHTML = '<option value="">No addresses yet</option>'
1652 isUpdatingAddressSelector = false
16531657 return
16541658 }
16551659
……@@ -1664,22 +1668,30 @@ async function loadWalletAddressSelector() {
16641668 html += `<option value="${addr.index}" ${addr.isCurrent ? 'selected' : ''}>${displayText}${currentMarker}</option>`
16651669 }
16661670
1671 // Store current value before update to detect programmatic vs user changes
1672 const previousValue = select.value
1673
16671674 select.innerHTML = html
1675
1676 // If the selected value changed due to our update (not user), mark as programmatic
1677 if (select.value !== previousValue) {
1678 select.dataset.programmaticChange = 'true'
1679 }
16681680 } catch (err) {
16691681 console.error('Load address selector error:', err)
16701682 select.innerHTML = '<option value="">Failed to load</option>'
16711683 }
1672
1673 // Clear flag after a tick to allow DOM to settle
1674 setTimeout(() => { isUpdatingAddressSelector = false }, 0)
16751684}
16761685
16771686// Handle wallet address selector change
16781687async function onWalletAddressChange() {
1679 // Ignore programmatic updates to prevent cascade
1680 if (isUpdatingAddressSelector) return
1681
16821688 const select = document.getElementById('wallet-address-select')
1689
1690 // Ignore programmatic updates to prevent cascade
1691 if (select.dataset.programmaticChange === 'true') {
1692 delete select.dataset.programmaticChange
1693 return
1694 }
16831695 const selectedIndex = parseInt(select.value)
16841696
16851697 if (isNaN(selectedIndex)) return
……@@ -1700,6 +1712,12 @@ async function onWalletAddressChange() {
17001712
17011713 showSuccess('Wallet address changed!')
17021714
1715 // Update star markers in the existing options (no reload needed)
1716 Array.from(select.options).forEach(option => {
1717 const text = option.textContent.replace(' ⭐', '')
1718 option.textContent = option.value === String(selectedIndex) ? text + ' ⭐' : text
1719 })
1720
17031721 // Reload balance - use unified view for Ethereum, standard for others
17041722 if (selectedChain === 'ethereum') {
17051723 await loadEthereumBalances()
……@@ -1709,8 +1727,7 @@ async function onWalletAddressChange() {
17091727 await loadCurrentQRCode()
17101728 await loadTransactions()
17111729
1712 // Reload the selector to update the star marker
1713 await loadWalletAddressSelector()
1730 // NOTE: Don't reload selector here - causes cascade. Star markers updated above.
17141731 } catch (err) {
17151732 showError(`Failed to change address: ${err.message}`)
17161733 }