Repro steps:
- in qt gui, with network enabled, open wallet1
- open wizard, create wallet2 (restore from seed something that has mined history)
- close both wallets, stop electrum
- start electrum with "-o" offline flag, open wallet2
- observe all txs in history tab show up as "unconfirmed"
The cause is that "stored_height" only gets updated ~on new blocks.
So if you created a wallet and closed it soon, its db would not contain "stored_height."
Fixes the issue described in #10406.
When scanning a lightning invoice we would pass it to
`QEInvoiceParser.fromResolvedPaymentIdentifier()`, however
`fromResolvedPaymentIdentifier()` doesn't reset the state of
`QEInvoiceParser._lnurlData` which is used in QML to evaluate
`payImmediately: invoiceParser.isLnurlPay` in the `onValidationSuccess`
connection.
This change calls `clear()` in `fromResolvedPaymentIdentifier()` to
ensure that `QEInvoiceParser` state gets reset when loading a new invoice.
However when retrieving a bolt11 from a lnurl-pay callback we don't
wan't to reset `QEInvoiceParser._lnurlData` so that `payImmediately` is
true when confirming the lnurl pay dialog, for that I skip calling
`fromResolvedPaymentIdentifier()` and instead call `validateRecipient()`
directly so the `QEInvoiceParser` state doesn't get reset in this case.
Prevent DivisionByZero exceptions by returning `Decimal('NaN')
instead of `Decimal(0)` if the exchange rate is 0.
Fixes https://github.com/spesmilo/electrum/issues/10403
```
>>> bool(Decimal(0))
False
```
ec65c53 replaces the usage of `PeerInTest` with `Peer` in
test_lnpeer.py.
PeerInTests sets `Peer.DELAY_INC_MSG_PROCESSING_SLEEP` to 0 so all
incoming messages get processed immediately. Because `Peer` instead of
`TestInPeer` was used the delay caused `test_reestablish_with_old_state`
to fail regularly because bob receives the old channel state and kills
the OldTaskGroup of the unittest with GracefulDisconnect before Alice
processed the answer of Bob and is still in ChannelState.REESTABLISHING.
```
FAILED tests/test_lnpeer.py::TestPeerDirect::test_reestablish_with_old_state - AssertionError: <PeerState.REESTABLISHING: 1> != <PeerState.BAD: 3>
```
Adds close() no-op method to QEQRScanner to prevent type errors like
this:
```
01-02 17:28:09.645 10543 10565 I python : 162.27 | W | gui.qml.qeapp | file:///data/data/org.electrum.electrum/files/app/electrum/gui/qml/components/SweepDialog.qml:123: TypeError: Property 'close' of object QEQRScanner(0xdd32f66fb600)
is not a function
```
There was a race incorrectly counting transactions with one
confirmations to the unconfirmed balance instead of the confirmed
balance.
This happened because the balance cache of AddressSynchronizer got
invalidated after `on_event_blockchain_updated` and then again after
`receive_history_callback`->`add_transaction`, however when calling
`AddressSynchronizer.get_balance()` before the tx got spv verified the
height would still be counted as 0 (unconfirmed), populating the balance
cache again with the unconfirmed balance.
I noticed this only on QML due to timing differences to Qt.
Invalidating the cache in `AddressSynchronizer.add_verified_tx()` after
the tx got verified causes the balance to get recalculated and shown
correctly.
- LNWallet no longer "is-an" LNWorker, instead LNWallet "has-an" LNWorker
- the motivation is to make the unit tests nicer, and allow writing unit tests for more things
- I hope this makes it possible to e.g. test lnsweep in the unit tests
- some stuff we would previously have to write a regtest for, maybe we can write a unit test for, now
- in unit tests, MockLNWallet now
- inherits LNWallet
- the Wallet is no longer being mocked
on_event_channels_updated doesn't get fired if channels change their
state to OPEN. TxEditor needs to use on_event_channel to notice channels
coming online.
I got confused how on_event_proxy_set can even work if CosignerWallet
doesn't inherit from EventListener until i figured out its children use
the EventListener too. To avoid this confusion i added two comments.
Fixes:
```
Traceback (most recent call last):
File "/home/user/code/electrum-fork/electrum/plugins/psbt_nostr/qt.py", line 149, in on_receive
self.mark_pending_event_rcvd(event_id)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^
File "/home/user/code/electrum-fork/electrum/plugins/psbt_nostr/psbt_nostr.py", line 254, in mark_pending_event_rcvd
self.pending.set()
~~~~~~~~~~~~~~~~^^
File "/usr/lib64/python3.14/asyncio/locks.py", line 192, in set
fut.set_result(True)
~~~~~~~~~~~~~~^^^^^^
File "/usr/lib64/python3.14/asyncio/base_events.py", line 829, in call_soon
self._check_thread()
~~~~~~~~~~~~~~~~~~^^
File "/usr/lib64/python3.14/asyncio/base_events.py", line 866, in _check_thread
raise RuntimeError(
"Non-thread-safe operation invoked on an event loop other "
"than the current one")
RuntimeError: Non-thread-safe operation invoked on an event loop other than the current one
```
Bump the python version used on Android from 3.10 to 3.11.
The substance is the backport of the corresponding commit [0] from upstream p4a.
Tested that apk is still reproducible by doing two full builds.
I also used the apk a bit and it seems to work at runtime. :)
[0]: 78db83223f (which got squashed into 83e74cac0f)
Lightning addresses with 'lightning:' do occur in the wild and make
sense (how else would e.g. the smartphone know to open a lightning
wallet instead of the e-mail client). So we should allow this.