|
|
@ -36,7 +36,8 @@ import base64 |
|
|
|
from functools import partial |
|
|
|
import queue |
|
|
|
import asyncio |
|
|
|
from typing import Optional, TYPE_CHECKING, Sequence, List, Union |
|
|
|
from typing import Optional, TYPE_CHECKING, Sequence, List, Union, Dict, Set |
|
|
|
import concurrent.futures |
|
|
|
|
|
|
|
from PyQt5.QtGui import QPixmap, QKeySequence, QIcon, QCursor, QFont |
|
|
|
from PyQt5.QtCore import Qt, QRect, QStringListModel, QSize, pyqtSignal, QPoint |
|
|
@ -203,6 +204,9 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger): |
|
|
|
self.pending_invoice = None |
|
|
|
Logger.__init__(self) |
|
|
|
|
|
|
|
self._coroutines_scheduled = set() # type: Set[concurrent.futures.Future] |
|
|
|
self.thread = TaskThread(self, self.on_error) |
|
|
|
|
|
|
|
self.tx_notification_queue = queue.Queue() |
|
|
|
self.tx_notification_last_time = 0 |
|
|
|
|
|
|
@ -318,16 +322,23 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger): |
|
|
|
self._update_check_thread.start() |
|
|
|
|
|
|
|
def run_coroutine_from_thread(self, coro, on_result=None): |
|
|
|
def task(): |
|
|
|
if self._cleaned_up: |
|
|
|
self.logger.warning(f"stopping or already stopped but run_coroutine_from_thread was called.") |
|
|
|
return |
|
|
|
async def wrapper(): |
|
|
|
try: |
|
|
|
f = asyncio.run_coroutine_threadsafe(coro, self.network.asyncio_loop) |
|
|
|
r = f.result() |
|
|
|
if on_result: |
|
|
|
on_result(r) |
|
|
|
res = await coro |
|
|
|
except Exception as e: |
|
|
|
self.logger.exception("exception in coro scheduled via window.wallet") |
|
|
|
self.show_error_signal.emit(str(e)) |
|
|
|
self.wallet.thread.add(task) |
|
|
|
self.show_error_signal.emit(repr(e)) |
|
|
|
else: |
|
|
|
if on_result: |
|
|
|
on_result(res) |
|
|
|
finally: |
|
|
|
self._coroutines_scheduled.discard(fut) |
|
|
|
|
|
|
|
fut = asyncio.run_coroutine_threadsafe(wrapper(), self.network.asyncio_loop) |
|
|
|
self._coroutines_scheduled.add(fut) |
|
|
|
|
|
|
|
def on_fx_history(self): |
|
|
|
self.history_model.refresh('fx_history') |
|
|
@ -400,7 +411,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger): |
|
|
|
|
|
|
|
def on_error(self, exc_info): |
|
|
|
e = exc_info[1] |
|
|
|
if isinstance(e, UserCancelled): |
|
|
|
if isinstance(e, (UserCancelled, concurrent.futures.CancelledError)): |
|
|
|
pass |
|
|
|
elif isinstance(e, UserFacingException): |
|
|
|
self.show_error(str(e)) |
|
|
@ -502,7 +513,6 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger): |
|
|
|
|
|
|
|
@profiler |
|
|
|
def load_wallet(self, wallet: Abstract_Wallet): |
|
|
|
wallet.thread = TaskThread(self, self.on_error) |
|
|
|
self.update_recently_visited(wallet.storage.path) |
|
|
|
if wallet.has_lightning(): |
|
|
|
util.trigger_callback('channels_updated', wallet) |
|
|
@ -1592,11 +1602,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger): |
|
|
|
if not self.question(msg): |
|
|
|
return |
|
|
|
self.save_pending_invoice() |
|
|
|
def task(): |
|
|
|
coro = self.wallet.lnworker.pay_invoice(invoice, amount_msat=amount_msat, attempts=LN_NUM_PAYMENT_ATTEMPTS) |
|
|
|
fut = asyncio.run_coroutine_threadsafe(coro, self.network.asyncio_loop) |
|
|
|
return fut.result() |
|
|
|
self.wallet.thread.add(task) |
|
|
|
coro = self.wallet.lnworker.pay_invoice(invoice, amount_msat=amount_msat, attempts=LN_NUM_PAYMENT_ATTEMPTS) |
|
|
|
self.run_coroutine_from_thread(coro) |
|
|
|
|
|
|
|
def on_request_status(self, wallet, key, status): |
|
|
|
if wallet != self.wallet: |
|
|
@ -2709,7 +2716,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger): |
|
|
|
# (signature) wrapped C/C++ object has been deleted |
|
|
|
pass |
|
|
|
|
|
|
|
self.wallet.thread.add(task, on_success=show_signed_message) |
|
|
|
self.thread.add(task, on_success=show_signed_message) |
|
|
|
|
|
|
|
def do_verify(self, address, message, signature): |
|
|
|
address = address.text().strip() |
|
|
@ -2782,7 +2789,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger): |
|
|
|
# (message_e) wrapped C/C++ object has been deleted |
|
|
|
pass |
|
|
|
|
|
|
|
self.wallet.thread.add(task, on_success=setText) |
|
|
|
self.thread.add(task, on_success=setText) |
|
|
|
|
|
|
|
def do_encrypt(self, message_e, pubkey_e, encrypted_e): |
|
|
|
message = message_e.toPlainText() |
|
|
@ -3234,9 +3241,11 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger): |
|
|
|
if self._cleaned_up: |
|
|
|
return |
|
|
|
self._cleaned_up = True |
|
|
|
if self.wallet.thread: |
|
|
|
self.wallet.thread.stop() |
|
|
|
self.wallet.thread = None |
|
|
|
if self.thread: |
|
|
|
self.thread.stop() |
|
|
|
self.thread = None |
|
|
|
for fut in self._coroutines_scheduled: |
|
|
|
fut.cancel() |
|
|
|
util.unregister_callback(self.on_network) |
|
|
|
self.config.set_key("is_maximized", self.isMaximized()) |
|
|
|
if not self.isMaximized(): |
|
|
|