forked from bitcoinafterlife/bal-electrum-plugin
init
This commit is contained in:
384
balqt/closedialog.py
Normal file
384
balqt/closedialog.py
Normal file
@@ -0,0 +1,384 @@
|
||||
from .baldialog import BalDialog
|
||||
from . import qt_resources
|
||||
|
||||
if qt_resources.QT_VERSION == 5:
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QLabel, QVBoxLayout, QCheckBox,QWidget
|
||||
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject,QEventLoop
|
||||
else:
|
||||
from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject,QEventLoop
|
||||
from PyQt6.QtCore import Qt
|
||||
from PyQt6.QtWidgets import QLabel, QVBoxLayout, QCheckBox, QWidget
|
||||
import time
|
||||
from electrum.i18n import _
|
||||
from electrum.gui.qt.util import WindowModalDialog, TaskThread
|
||||
from electrum.network import Network,TxBroadcastError, BestEffortRequestFailed
|
||||
from electrum.logging import get_logger
|
||||
|
||||
|
||||
from functools import partial
|
||||
import copy
|
||||
|
||||
from .. import util as Util
|
||||
from .. import will as Will
|
||||
|
||||
from .. import willexecutors as Willexecutors
|
||||
_logger = get_logger(__name__)
|
||||
|
||||
|
||||
class BalCloseDialog(BalDialog):
|
||||
updatemessage=pyqtSignal()
|
||||
def __init__(self,bal_window):
|
||||
BalDialog.__init__(self,bal_window.window,"Closing BAL")
|
||||
self.updatemessage.connect(self.update)
|
||||
self.bal_window=bal_window
|
||||
self.message_label = QLabel("Closing BAL:")
|
||||
self.vbox = QVBoxLayout(self)
|
||||
self.vbox.addWidget(self.message_label)
|
||||
self.qwidget=QWidget()
|
||||
self.vbox.addWidget(self.qwidget)
|
||||
self.labels=[]
|
||||
#self.checking.connect(self.msg_set_checking)
|
||||
#self.invalidating.connect(self.msg_set_invalidating)
|
||||
#self.building.connect(self.msg_set_building)
|
||||
#self.signing.connect(self.msg_set_signing)
|
||||
#self.pushing.connect(self.msg_set_pushing)
|
||||
|
||||
#self.askpassword.connect(self.ask_password)
|
||||
#self.passworddone.connect(self.password_done)
|
||||
self.check_row = None
|
||||
self.inval_row = None
|
||||
self.build_row = None
|
||||
self.sign_row = None
|
||||
self.push_row = None
|
||||
self.network = Network.get_instance()
|
||||
self._stopping = False
|
||||
self.thread = TaskThread(self)
|
||||
self.thread.finished.connect(self.task_finished) # see #3956
|
||||
def task_finished(self):
|
||||
pass
|
||||
#_logger.trace("task finished")
|
||||
|
||||
def close_plugin_task(self):
|
||||
_logger.debug("close task to be started")
|
||||
self.thread.add(self.task_phase1,on_success=self.on_success_phase1,on_done=self.on_accept,on_error=self.on_error_phase1)
|
||||
self.show()
|
||||
self.exec()
|
||||
|
||||
def task_phase1(self):
|
||||
_logger.debug("close plugin phase 1 started")
|
||||
try:
|
||||
self.bal_window.init_class_variables()
|
||||
except Will.NoHeirsException:
|
||||
return False, None
|
||||
self.msg_set_status("checking variables","Waiting")
|
||||
try:
|
||||
Will.check_amounts(self.bal_window.heirs,self.bal_window.willexecutors,self.bal_window.window.wallet.get_utxos(),self.bal_window.date_to_check,self.bal_window.window.wallet.dust_threshold())
|
||||
except Will.AmountException:
|
||||
self.msg_edit_row('<font color="#ff0000">'+_("In the inheritance process, the entire wallet will always be fully emptied. Your settings require an adjustment of the amounts"+"</font>"))
|
||||
#self.bal_window.show_warning(_("In the inheritance process, the entire wallet will always be fully emptied. Your settings require an adjustment of the amounts"),parent=self)
|
||||
|
||||
self.msg_set_checking()
|
||||
have_to_build=False
|
||||
try:
|
||||
self.bal_window.check_will()
|
||||
self.msg_set_checking('Ok')
|
||||
except Will.WillExpiredException as e:
|
||||
self.msg_set_checking("Expired")
|
||||
fee_per_byte=self.bal_window.will_settings.get('tx_fees',1)
|
||||
return None, Will.invalidate_will(self.bal_window.willitems,self.bal_window.wallet,fee_per_byte)
|
||||
except Will.NoHeirsException:
|
||||
self.msg_set_checking("No Heirs")
|
||||
except Will.NotCompleteWillException as e:
|
||||
message = False
|
||||
have_to_build=True
|
||||
if isinstance(e,Will.HeirChangeException):
|
||||
message ="Heirs changed:"
|
||||
elif isinstance(e,Will.WillExecutorNotPresent):
|
||||
message = "Will-Executor not present"
|
||||
elif isinstance(e,Will.WillexecutorChangeException):
|
||||
message = "Will-Executor changed"
|
||||
elif isinstance(e,Will.TxFeesChangedException):
|
||||
message = "Txfees are changed"
|
||||
elif isinstance(e,Will.HeirNotFoundException):
|
||||
message = "Heir not found"
|
||||
if message:
|
||||
self.msg_set_checking(message)
|
||||
else:
|
||||
self.msg_set_checking("New")
|
||||
|
||||
if have_to_build:
|
||||
self.msg_set_building()
|
||||
try:
|
||||
self.bal_window.build_will()
|
||||
self.bal_window.check_will()
|
||||
for wid in Will.only_valid(self.bal_window.willitems):
|
||||
self.bal_window.wallet.set_label(wid,"BAL Transaction")
|
||||
self.msg_set_building("Ok")
|
||||
except Exception as e:
|
||||
self.msg_set_building(self.msg_error(e))
|
||||
return False,None
|
||||
have_to_sign = False
|
||||
for wid in Will.only_valid(self.bal_window.willitems):
|
||||
if not self.bal_window.willitems[wid].get_status("COMPLETE"):
|
||||
have_to_sign = True
|
||||
break
|
||||
return have_to_sign, None
|
||||
|
||||
def on_accept(self):
|
||||
pass
|
||||
|
||||
def on_accept_phase2(self):
|
||||
pass
|
||||
|
||||
def on_error_push(self):
|
||||
pass
|
||||
|
||||
def wait(self,secs):
|
||||
wait_row=None
|
||||
for i in range(secs,0,-1):
|
||||
if self._stopping:
|
||||
return
|
||||
wait_row = self.msg_edit_row(f"Please wait {i}secs", wait_row)
|
||||
time.sleep(1)
|
||||
self.msg_del_row(wait_row)
|
||||
|
||||
def loop_broadcast_invalidating(self,tx):
|
||||
self.msg_set_invalidating("Broadcasting")
|
||||
try:
|
||||
tx.add_info_from_wallet(self.bal_window.wallet)
|
||||
self.network.run_from_another_thread(tx.add_info_from_network(self.network))
|
||||
txid = self.network.run_from_another_thread(self.network.broadcast_transaction(tx,timeout=120),timeout=120)
|
||||
self.msg_set_invalidating("Ok")
|
||||
if not txid:
|
||||
_logger.debug(f"should not be none txid: {txid}")
|
||||
|
||||
|
||||
except TxBroadcastError as e:
|
||||
_logger.error(e)
|
||||
msg = e.get_message_for_gui()
|
||||
self.msg_set_invalidating(self.msg_error(msg))
|
||||
except BestEffortRequestFailed as e:
|
||||
self.msg_set_invalidating(self.msg_error(e))
|
||||
# self.loop_broadcast_invalidating(tx)
|
||||
|
||||
def loop_push(self):
|
||||
self.msg_set_pushing("Broadcasting")
|
||||
retry = False
|
||||
try:
|
||||
willexecutors=Willexecutors.get_willexecutor_transactions(self.bal_window.willitems)
|
||||
for url,willexecutor in willexecutors.items():
|
||||
try:
|
||||
if Willexecutors.is_selected(self.bal_window.willexecutors.get(url)):
|
||||
_logger.debug(f"{url}: {willexecutor}")
|
||||
if not Willexecutors.push_transactions_to_willexecutor(willexecutor):
|
||||
for wid in willexecutor['txsids']:
|
||||
self.bal_window.willitems[wid].set_status('PUSH_FAIL',True)
|
||||
retry=True
|
||||
else:
|
||||
for wid in willexecutor['txsids']:
|
||||
self.bal_window.willitems[wid].set_status('PUSHED',True)
|
||||
except Willexecutors.AlreadyPresentException:
|
||||
for wid in willexecutor['txsids']:
|
||||
row = self.msg_edit_row("checking {} - {} : {}".format(self.bal_window.willitems[wid].we['url'],wid, "Waiting"))
|
||||
self.bal_window.willitems[wid].check_willexecutor()
|
||||
row = self.msg_edit_row("checked {} - {} : {}".format(self.bal_window.willitems[wid].we['url'],wid,self.bal_window.willitems[wid].get_status("CHECKED" )),row)
|
||||
|
||||
|
||||
except Exception as e:
|
||||
|
||||
_logger.error(e)
|
||||
raise e
|
||||
if retry:
|
||||
raise Exception("retry")
|
||||
|
||||
except Exception as e:
|
||||
self.msg_set_pushing(self.msg_error(e))
|
||||
self.wait(10)
|
||||
if not self._stopping:
|
||||
self.loop_push()
|
||||
|
||||
|
||||
def invalidate_task(self,tx,password):
|
||||
_logger.debug(f"invalidate tx: {tx}")
|
||||
tx = self.bal_window.wallet.sign_transaction(tx,password)
|
||||
try:
|
||||
if tx:
|
||||
if tx.is_complete():
|
||||
self.loop_broadcast_invalidating(tx)
|
||||
self.wait(5)
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
raise
|
||||
except Exception as e:
|
||||
self.msg_set_invalidating("Error")
|
||||
raise Exception("Impossible to sign")
|
||||
def on_success_invalidate(self,success):
|
||||
self.thread.add(self.task_phase1,on_success=self.on_success_phase1,on_done=self.on_accept,on_error=self.on_error_phase1)
|
||||
def on_error(self,error):
|
||||
_logger.error(error)
|
||||
pass
|
||||
def on_success_phase1(self,result):
|
||||
self.have_to_sign,tx = list(result)
|
||||
#if have_to_sign is False and tx is None:
|
||||
#self._stopping=True
|
||||
#self.on_success_phase2()
|
||||
# return
|
||||
print("have to sign",self.have_to_sign)
|
||||
password=None
|
||||
if self.have_to_sign is None:
|
||||
self.msg_set_invalidating()
|
||||
#need to sign invalidate and restart phase 1
|
||||
|
||||
password = self.bal_window.get_wallet_password("Invalidate your old will",parent=self.bal_window.window)
|
||||
if password is False:
|
||||
self.msg_set_invalidating("Aborted")
|
||||
self.wait(3)
|
||||
self.close()
|
||||
return
|
||||
self.thread.add(partial(self.invalidate_task,tx,password),on_success=self.on_success_invalidate, on_done=self.on_accept, on_error=self.on_error)
|
||||
|
||||
return
|
||||
|
||||
elif self.have_to_sign:
|
||||
password = self.bal_window.get_wallet_password("Sign your will",parent=self.bal_window.window)
|
||||
if password is False:
|
||||
self.msg_set_signing('Aborted')
|
||||
else:
|
||||
self.msg_set_signing('Nothing to do')
|
||||
self.thread.add(partial(self.task_phase2,password),on_success=self.on_success_phase2,on_done=self.on_accept_phase2,on_error=self.on_error_phase2)
|
||||
return
|
||||
|
||||
def on_success_phase2(self,arg=False):
|
||||
self.thread.stop()
|
||||
self.bal_window.save_willitems()
|
||||
self.msg_edit_row("Finished")
|
||||
self.close()
|
||||
|
||||
def closeEvent(self,event):
|
||||
self._stopping=True
|
||||
self.thread.stop()
|
||||
|
||||
def task_phase2(self,password):
|
||||
if self.have_to_sign:
|
||||
try:
|
||||
if txs:=self.bal_window.sign_transactions(password):
|
||||
for txid,tx in txs.items():
|
||||
self.bal_window.willitems[txid].tx = copy.deepcopy(tx)
|
||||
self.bal_window.save_willitems()
|
||||
self.msg_set_signing("Ok")
|
||||
except Exception as e:
|
||||
self.msg_set_signing(self.msg_error(e))
|
||||
|
||||
self.msg_set_pushing()
|
||||
have_to_push = False
|
||||
for wid in Will.only_valid(self.bal_window.willitems):
|
||||
w=self.bal_window.willitems[wid]
|
||||
if w.we and w.get_status("COMPLETE") and not w.get_status("PUSHED"):
|
||||
have_to_push = True
|
||||
if not have_to_push:
|
||||
self.msg_set_pushing("Nothing to do")
|
||||
else:
|
||||
try:
|
||||
self.loop_push()
|
||||
self.msg_set_pushing("Ok")
|
||||
|
||||
except Exception as e:
|
||||
self.msg_set_pushing(self.msg_error(e))
|
||||
self.msg_edit_row("Ok")
|
||||
self.wait(5)
|
||||
|
||||
def on_error_phase1(self,error):
|
||||
_logger.error(f"error phase1: {error}")
|
||||
|
||||
def on_error_phase2(self,error):
|
||||
_logger.error("error phase2: { error}")
|
||||
|
||||
|
||||
def msg_set_checking(self, status = None, row = None):
|
||||
row = self.check_row if row is None else row
|
||||
self.check_row = self.msg_set_status("Checking your will", row, status)
|
||||
|
||||
def msg_set_invalidating(self, status = None, row = None):
|
||||
row = self.inval_row if row is None else row
|
||||
self.inval_row = self.msg_set_status("Invalidating old will", self.inval_row, status)
|
||||
|
||||
def msg_set_building(self, status = None, row = None):
|
||||
row = self.build_row if row is None else row
|
||||
self.build_row = self.msg_set_status("Building your will", self.build_row, status)
|
||||
|
||||
def msg_set_signing(self, status = None, row = None):
|
||||
row = self.sign_row if row is None else row
|
||||
self.sign_row = self.msg_set_status("Signing your will", self.sign_row, status)
|
||||
|
||||
def msg_set_pushing(self, status = None, row = None):
|
||||
row = self.push_row if row is None else row
|
||||
self.push_row = self.msg_set_status("Broadcasting your will to executors", self.push_row, status)
|
||||
|
||||
def msg_set_waiting(self, status = None, row = None):
|
||||
row = self.wait_row if row is None else row
|
||||
self.wait_row = self.msg_edit_row(f"Please wait {status}secs", self.wait_row)
|
||||
|
||||
def msg_error(self,e):
|
||||
return "Error: {}".format(e)
|
||||
|
||||
def msg_set_status(self,msg,row,status=None):
|
||||
status= "Wait" if status is None else status
|
||||
line="{}:\t{}".format(_(msg), status)
|
||||
return self.msg_edit_row(line,row)
|
||||
|
||||
#return v$msg_edit_row("{}:\t{}".format(_(msg), status), row)
|
||||
|
||||
def ask_password(self,msg=None):
|
||||
self.password=self.bal_window.get_wallet_password(msg,parent=self)
|
||||
|
||||
def msg_edit_row(self,line,row=None):
|
||||
_logger.debug(f"{row},{line}")
|
||||
|
||||
#msg=self.get_text()
|
||||
#rows=msg.split("\n")
|
||||
#try:
|
||||
# rows[row]=line
|
||||
#except Exception as e:
|
||||
# rows.append(line)
|
||||
#row=len(rows)-1
|
||||
#self.update("\n".join(rows))
|
||||
|
||||
#return row
|
||||
|
||||
#def msg_edit_label(self,line,row=None):
|
||||
#_logger.trace(f"{row},{line}")
|
||||
|
||||
#msg=self.get_text()
|
||||
#rows=msg.split("\n")
|
||||
try:
|
||||
self.labels[row]=line
|
||||
except Exception as e:
|
||||
self.labels.append(line)
|
||||
row=len(self.labels)-1
|
||||
|
||||
self.updatemessage.emit()
|
||||
|
||||
return row
|
||||
|
||||
def msg_del_row(self,row):
|
||||
#_logger.trace(f"del row: {row}")
|
||||
try:
|
||||
del self.labels[row]
|
||||
except Exception as e:
|
||||
pass
|
||||
self.updatemessage.emit()
|
||||
|
||||
def update(self):
|
||||
self.vbox.removeWidget(self.qwidget)
|
||||
self.qwidget=QWidget(self)
|
||||
labelsbox = QVBoxLayout(self.qwidget)
|
||||
for label in self.labels:
|
||||
labelsbox.addWidget(QLabel(label))
|
||||
self.vbox.addWidget(self.qwidget)
|
||||
|
||||
def get_text(self):
|
||||
return self.message_label.text()
|
||||
def ThreadStopped(Exception):
|
||||
pass
|
||||
Reference in New Issue
Block a user