This commit is contained in:
bitcoinafterlife 2025-10-14 07:50:27 -04:00
parent fd7e849158
commit 7c1fc04add
Signed by: bitcoinafterlife
GPG Key ID: FE756706E833E0D1
7 changed files with 127 additions and 91 deletions

View File

@ -1,20 +1 @@
from electrum.i18n import _
import subprocess
from . import bal_resources
BUILD_NUMBER = 3
REVISION_NUMBER = 2
VERSION_NUMBER = 0
def _version():
return f'{VERSION_NUMBER}.{REVISION_NUMBER}-{BUILD_NUMBER}'
version = _version()
author = "Bal Enterprise inc."
fullname = _('B.A.L.')
description = ''.join([
"<img src='",bal_resources.icon_path('bal16x16.png'),"'>", _("Bitcoin After Life"), '<br/>',
_("For more information, visit"),
" <a href=\"https://bitcoin-after.life/\">https://bitcoin-after.life/</a><br/>",
"<p style='font-size:8pt;vertialAlign:bottom'>Version: ", _version(),"</p>"
])
#available_for = ['qt', 'cmdline', 'qml']
available_for = ['qt']

51
bal.py
View File

@ -1,5 +1,6 @@
import random import random
import os import os
import zipfile as zipfile_lib
from electrum.plugin import BasePlugin from electrum.plugin import BasePlugin
from electrum import json_db from electrum import json_db
@ -56,31 +57,39 @@ class BalPlugin(BasePlugin):
BasePlugin.__init__(self, parent, config, name) BasePlugin.__init__(self, parent, config, name)
self.base_dir = os.path.join(config.electrum_path(), 'bal') self.base_dir = os.path.join(config.electrum_path(), 'bal')
self.plugin_dir = os.path.split(os.path.realpath(__file__))[0] self.plugin_dir = os.path.split(os.path.realpath(__file__))[0]
self.logger.info(self.base_dir) zipfile="/".join(self.plugin_dir.split("/")[:-1])
#print("real path",os.path.realpath(__file__))
#self.logger.info(self.base_dir)
#print("base_dir:", self.base_dir)
#print("suca:",zipfile)
#print("plugin_dir:", self.plugin_dir)
import sys
sys.path.insert(0, zipfile)
#print("sono state listate?")
self.parent = parent self.parent = parent
self.config = config self.config = config
self.name = name self.name = name
self.ASK_BROADCAST = BalConfig(config, "bal_ask_broadcast",True) self.ASK_BROADCAST = BalConfig(config, "bal_ask_broadcast", True)
self.BROADCAST = BalConfig(config, "bal_broadcast",True) self.BROADCAST = BalConfig(config, "bal_broadcast", True)
self.LOCKTIME_TIME = BalConfig(config, "bal_locktime_time",90) self.LOCKTIME_TIME = BalConfig(config, "bal_locktime_time", 90)
self.LOCKTIME_BLOCKS = BalConfig(config, "bal_locktime_blocks",144*90) self.LOCKTIME_BLOCKS = BalConfig(config, "bal_locktime_blocks", 144*90)
self.LOCKTIMEDELTA_TIME = BalConfig(config, "bal_locktimedelta_time",7) self.LOCKTIMEDELTA_TIME = BalConfig(config, "bal_locktimedelta_time", 7)
self.LOCKTIMEDELTA_BLOCKS = BalConfig(config, "bal_locktimedelta_blocks",144*7) self.LOCKTIMEDELTA_BLOCKS = BalConfig(config, "bal_locktimedelta_blocks", 144*7)
self.TX_FEES = BalConfig(config, "bal_tx_fees",100) self.ENABLE_MULTIVERSE = BalConfig(config, "bal_enable_multiverse", False)
self.INVALIDATE = BalConfig(config, "bal_invalidate",True) self.TX_FEES = BalConfig(config, "bal_tx_fees", 100)
self.ASK_INVALIDATE = BalConfig(config, "bal_ask_invalidate",True) self.INVALIDATE = BalConfig(config, "bal_invalidate", True)
self.PREVIEW = BalConfig(config, "bal_preview",True) self.ASK_INVALIDATE = BalConfig(config, "bal_ask_invalidate", True)
self.SAVE_TXS = BalConfig(config, "bal_save_txs",True) self.PREVIEW = BalConfig(config, "bal_preview", True)
self.WILLEXECUTORS = BalConfig(config, "bal_willexecutors",True) self.SAVE_TXS = BalConfig(config, "bal_save_txs", True)
self.PING_WILLEXECUTORS = BalConfig(config, "bal_ping_willexecutors",True) self.WILLEXECUTORS = BalConfig(config, "bal_willexecutors", True)
self.ASK_PING_WILLEXECUTORS = BalConfig(config, "bal_ask_ping_willexecutors",True) self.PING_WILLEXECUTORS = BalConfig(config, "bal_ping_willexecutors", True)
self.NO_WILLEXECUTOR = BalConfig(config, "bal_no_willexecutor",True) self.ASK_PING_WILLEXECUTORS = BalConfig(config, "bal_ask_ping_willexecutors", True)
self.HIDE_REPLACED = BalConfig(config, "bal_hide_replaced",True) self.NO_WILLEXECUTOR = BalConfig(config, "bal_no_willexecutor", True)
self.HIDE_INVALIDATED = BalConfig(config, "bal_hide_invalidated",True) self.HIDE_REPLACED = BalConfig(config, "bal_hide_replaced", True)
self.ALLOW_REPUSH = BalConfig(config, "bal_allow_repush",True) self.HIDE_INVALIDATED = BalConfig(config, "bal_hide_invalidated", True)
self.FIRST_EXECUTION = BalConfig(config, "bal_first_execution",True) self.ALLOW_REPUSH = BalConfig(config, "bal_allow_repush", True)
self.FIRST_EXECUTION = BalConfig(config, "bal_first_execution", True)
self.WILLEXECUTORS = BalConfig(config, "bal_willexecutors", { self.WILLEXECUTORS = BalConfig(config, "bal_willexecutors", {
"mainnet": { "mainnet": {
'https://we.bitcoin-after.life': { 'https://we.bitcoin-after.life': {

View File

@ -2,7 +2,7 @@ import os
PLUGIN_DIR = os.path.split(os.path.realpath(__file__))[0] PLUGIN_DIR = os.path.split(os.path.realpath(__file__))[0]
DEFAULT_ICON = 'bal32x32.png' DEFAULT_ICON = 'bal32x32.png'
DEFAULT_ICON_PATH = 'icons' DEFAULT_ICON_PATH = ''
def icon_path(icon_basename: str = DEFAULT_ICON): def icon_path(icon_basename: str = DEFAULT_ICON):

View File

@ -563,10 +563,7 @@ class Heirs(dict, Logger):
def validate_amount(amount): def validate_amount(amount):
try: try:
if Util.is_perc(amount): famount = float(amount[:-1]) if Util.is_perc(amount) else float(amount)
famount = float(amount[:-1])
else:
famount = float(amount)
if famount <= 0.00000001: if famount <= 0.00000001:
raise AmountNotValid(f"amount have to be positive {famount} < 0") raise AmountNotValid(f"amount have to be positive {famount} < 0")
except Exception as e: except Exception as e:
@ -575,9 +572,8 @@ class Heirs(dict, Logger):
def validate_locktime(locktime,timestamp_to_check=False): def validate_locktime(locktime,timestamp_to_check=False):
try: try:
locktime = Util.parse_locktime_string(locktime,None)
if timestamp_to_check: if timestamp_to_check:
if locktime < timestamp_to_check: if Util.parse_locktime_string(locktime,None) < timestamp_to_check:
raise HeirExpiredException() raise HeirExpiredException()
except Exception as e: except Exception as e:
raise LocktimeNotValid(f"locktime string not properly formatted, {e}") raise LocktimeNotValid(f"locktime string not properly formatted, {e}")

119
qt.py
View File

@ -259,6 +259,8 @@ from electrum.gui.qt.util import (
TaskThread, TaskThread,
WindowModalDialog, WindowModalDialog,
WWLabel, WWLabel,
read_QIcon_from_bytes,
read_QPixmap_from_bytes,
) )
from electrum.gui.qt.main_window import StatusBarButton from electrum.gui.qt.main_window import StatusBarButton
from electrum.gui.qt.my_treeview import ( from electrum.gui.qt.my_treeview import (
@ -372,7 +374,7 @@ class Plugin(BalPlugin,Logger):
def create_status_bar(self, sb): def create_status_bar(self, sb):
self.logger.info("HOOK create status bar") self.logger.info("HOOK create status bar")
return return
b = StatusBarButton(read_bal_QIcon('bal32x32.png'), "Bal "+_("Bitcoin After Life"), b = StatusBarButton(read_QIcon_from_bytes(self.bal_plugin.read_file('bal32x32.png')), "Bal "+_("Bitcoin After Life"),
partial(self.setup_dialog, sb), sb.height()) partial(self.setup_dialog, sb), sb.height())
sb.addPermanentWidget(b) sb.addPermanentWidget(b)
@ -436,9 +438,9 @@ class Plugin(BalPlugin,Logger):
def settings_dialog(self,window,wallet): def settings_dialog(self,window,wallet):
d = BalDialog(window, self.get_window_title("Settings")) d = BalDialog(window,self,self.get_window_title("Settings"))
d.setMinimumSize(100, 200) d.setMinimumSize(100, 200)
qicon=read_bal_QPixmap("bal32x32.png") qicon=read_QPixmap_from_bytes(self.read_file("bal32x32.png"))
lbl_logo = QLabel() lbl_logo = QLabel()
lbl_logo.setPixmap(qicon) lbl_logo.setPixmap(qicon)
@ -446,10 +448,15 @@ class Plugin(BalPlugin,Logger):
heir_ask_ping_willexecutors = bal_checkbox(self.ASK_PING_WILLEXECUTORS) heir_ask_ping_willexecutors = bal_checkbox(self.ASK_PING_WILLEXECUTORS)
heir_no_willexecutor = bal_checkbox(self.NO_WILLEXECUTOR) heir_no_willexecutor = bal_checkbox(self.NO_WILLEXECUTOR)
def on_multiverse_change():
heir_hide_replaced = bal_checkbox(self.HIDE_REPLACED,self) self.update_all()
#heir_enable_multiverse = bal_checkbox(self.ENABLE_MULTIVERSE,on_multiverse_change)
heir_hide_replaced = bal_checkbox(self.HIDE_REPLACED,on_multiverse_change)
heir_hide_invalidated = bal_checkbox(self.HIDE_INVALIDATED,on_multiverse_change)
heir_hide_invalidated = bal_checkbox(self.HIDE_INVALIDATED,self)
heir_repush = QPushButton("Rebroadcast transactions") heir_repush = QPushButton("Rebroadcast transactions")
heir_repush.clicked.connect(partial(self.broadcast_transactions,True)) heir_repush.clicked.connect(partial(self.broadcast_transactions,True))
grid=QGridLayout(d) grid=QGridLayout(d)
@ -458,8 +465,9 @@ class Plugin(BalPlugin,Logger):
add_widget(grid,"Ping Willexecutors",heir_ping_willexecutors,3,"Ping willexecutors to get payment info before compiling will") add_widget(grid,"Ping Willexecutors",heir_ping_willexecutors,3,"Ping willexecutors to get payment info before compiling will")
add_widget(grid," - Ask before",heir_ask_ping_willexecutors,4,"Ask before to ping willexecutor") add_widget(grid," - Ask before",heir_ask_ping_willexecutors,4,"Ask before to ping willexecutor")
add_widget(grid,"Backup Transaction",heir_no_willexecutor,5,"Add transactions without willexecutor") add_widget(grid,"Backup Transaction",heir_no_willexecutor,5,"Add transactions without willexecutor")
grid.addWidget(heir_repush,6,0) #add_widget(grid,"Enable Multiverse(EXPERIMENTAL/BROKEN)",heir_enable_multiverse,6,"enable multiple locktimes, will import.... ")
grid.addWidget(HelpButton("Broadcast all transactions to willexecutors including those already pushed"),6,2) grid.addWidget(heir_repush,7,0)
grid.addWidget(HelpButton("Broadcast all transactions to willexecutors including those already pushed"),7,2)
if ret := bool(d.exec()): if ret := bool(d.exec()):
try: try:
@ -526,8 +534,8 @@ class BalWindow(Logger):
add_optional_tab(self.window.tabs, self.heirs_tab, read_bal_QIcon("heir.png"), _("&Heirs")) add_optional_tab(self.window.tabs, self.heirs_tab, read_QIcon_from_bytes(self.bal_plugin.read_file("heir.png")), _("&Heirs"))
add_optional_tab(self.window.tabs, self.will_tab, read_bal_QIcon("will.png"), _("&Will")) add_optional_tab(self.window.tabs, self.will_tab, read_QIcon_from_bytes(self.bal_plugin.read_file("will.png")), _("&Will"))
tools_menu.addSeparator() tools_menu.addSeparator()
self.tools_menu.willexecutors_action = tools_menu.addAction(_("&Will-Executors"), self.show_willexecutor_dialog) self.tools_menu.willexecutors_action = tools_menu.addAction(_("&Will-Executors"), self.show_willexecutor_dialog)
self.window.view_menu.addSeparator() self.window.view_menu.addSeparator()
@ -605,7 +613,7 @@ class BalWindow(Logger):
if heir: if heir:
title = f"Edit: {heir_key}" title = f"Edit: {heir_key}"
d = BalDialog(self.window, self.bal_plugin.get_window_title(_(title))) d = BalDialog(self.window, self.bal_plugin,self.bal_plugin.get_window_title(_(title)))
vbox = QVBoxLayout(d) vbox = QVBoxLayout(d)
grid = QGridLayout() grid = QGridLayout()
@ -620,7 +628,7 @@ class BalWindow(Logger):
heir_address.setText(str(heir[0])) heir_address.setText(str(heir[0]))
heir_amount = PercAmountEdit(self.window.get_decimal_point) heir_amount = PercAmountEdit(self.window.get_decimal_point)
if heir: if heir:
heir_amount.setText(str(heir[1])) heir_amount.setText(str(Util.decode_amount(heir[1],self.bal_plugin.config.get_decimal_point())))
heir_locktime = HeirsLockTimeEdit(self.window,0) heir_locktime = HeirsLockTimeEdit(self.window,0)
if heir: if heir:
heir_locktime.set_locktime(heir[2]) heir_locktime.set_locktime(heir[2])
@ -648,6 +656,13 @@ class BalWindow(Logger):
grid.addWidget(heir_amount,3,1) grid.addWidget(heir_amount,3,1)
grid.addWidget(HelpButton(_("Fixed or Percentage amount if end with %")),3,2) grid.addWidget(HelpButton(_("Fixed or Percentage amount if end with %")),3,2)
locktime_label=QLabel(_("Locktime"))
enable_multiverse=self.bal_plugin.ENABLE_MULTIVERSE.get()
if enable_multiverse:
grid.addWidget(locktime_label,4,0)
grid.addWidget(heir_locktime,4,1)
grid.addWidget(HelpButton(_("locktime")),4,2)
vbox.addLayout(grid) vbox.addLayout(grid)
buttons=[CancelButton(d), OkButton(d)] buttons=[CancelButton(d), OkButton(d)]
if not heir: if not heir:
@ -659,7 +674,7 @@ class BalWindow(Logger):
heir_name.text(), heir_name.text(),
heir_address.text(), heir_address.text(),
Util.encode_amount(heir_amount.text(),self.bal_plugin.config.get_decimal_point()), Util.encode_amount(heir_amount.text(),self.bal_plugin.config.get_decimal_point()),
str(heir_locktime.get_locktime()), str(heir_locktime.get_locktime()),
] ]
try: try:
self.set_heir(heir) self.set_heir(heir)
@ -679,7 +694,8 @@ class BalWindow(Logger):
def set_heir(self,heir): def set_heir(self,heir):
heir=list(heir) heir=list(heir)
heir[3]=self.will_settings['locktime'] if not self.bal_plugin.ENABLE_MULTIVERSE.get():
heir[3]=self.will_settings['locktime']
h=Heirs.validate_heir(heir[0],heir[1:]) h=Heirs.validate_heir(heir[0],heir[1:])
self.heirs[heir[0]]=h self.heirs[heir[0]]=h
@ -721,6 +737,7 @@ class BalWindow(Logger):
self.willexecutors = Willexecutors.get_willexecutors(self.bal_plugin, update=False, bal_window=self) self.willexecutors = Willexecutors.get_willexecutors(self.bal_plugin, update=False, bal_window=self)
if not self.no_willexecutor: if not self.no_willexecutor:
f=False f=False
for u,w in self.willexecutors.items(): for u,w in self.willexecutors.items():
if Willexecutors.is_selected(w): if Willexecutors.is_selected(w):
@ -763,10 +780,11 @@ class BalWindow(Logger):
def show_critical(self,text): def show_critical(self,text):
self.window.show_critical(text) self.window.show_critical(text)
def init_heirs_to_locktime(self): def init_heirs_to_locktime(self,multiverse=False):
for heir in self.heirs: for heir in self.heirs:
h=self.heirs[heir] h=self.heirs[heir]
self.heirs[heir]=[h[0],h[1],self.will_settings['locktime']] if not multiverse:
self.heirs[heir]=[h[0],h[1],self.will_settings['locktime']]
def init_class_variables(self): def init_class_variables(self):
if not self.heirs: if not self.heirs:
@ -780,7 +798,7 @@ class BalWindow(Logger):
self.block_to_check = self.current_block + self.locktime_blocks self.block_to_check = self.current_block + self.locktime_blocks
self.no_willexecutor = self.bal_plugin.NO_WILLEXECUTOR.get() self.no_willexecutor = self.bal_plugin.NO_WILLEXECUTOR.get()
self.willexecutors = Willexecutors.get_willexecutors(self.bal_plugin,update=True,bal_window=self,task=False) self.willexecutors = Willexecutors.get_willexecutors(self.bal_plugin,update=True,bal_window=self,task=False)
self.init_heirs_to_locktime() self.init_heirs_to_locktime(self.bal_plugin.ENABLE_MULTIVERSE.get())
except Exception as e: except Exception as e:
self.logger.error(e) self.logger.error(e)
@ -872,7 +890,7 @@ class BalWindow(Logger):
external_keypairs=external_keypairs, external_keypairs=external_keypairs,
#payment_identifier=payment_identifier, #payment_identifier=payment_identifier,
) )
d.setWindowIcon(read_bal_QIcon("bal32x32.png")) d.setWindowIcon(read_QIcon_from_bytes(self.bal_plugin.read_file("bal32x32.png")))
except SerializationError as e: except SerializationError as e:
self.logger.error('unable to deserialize the transaction') self.logger.error('unable to deserialize the transaction')
parent.show_critical(_("Electrum was unable to deserialize the transaction:") + "\n" + str(e)) parent.show_critical(_("Electrum was unable to deserialize the transaction:") + "\n" + str(e))
@ -1206,7 +1224,6 @@ class HeirsLockTimeEdit(QWidget):
hbox.addWidget(self.combo) hbox.addWidget(self.combo)
for w in self.editors: for w in self.editors:
#print("addwidget")
hbox.addWidget(w) hbox.addWidget(w)
hbox.addStretch(1) hbox.addStretch(1)
#spacer_widget = QWidget() #spacer_widget = QWidget()
@ -1456,20 +1473,16 @@ class PercAmountEdit(BTCAmountEdit):
painter.drawText(textRect, int(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter), self.base_unit() + " or perc value") painter.drawText(textRect, int(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter), self.base_unit() + " or perc value")
class BalDialog(WindowModalDialog): class BalDialog(WindowModalDialog):
def __init__(self,parent,title=None, icon = 'bal32x32.png'): def __init__(self,parent,bal_plugin,title=None, icon = 'bal32x32.png'):
#print("éééééééééééé")
#print(parent)
#print(dir(parent))
#print("éééééééééééééééééé")
self.parent=parent self.parent=parent
WindowModalDialog.__init__(self,parent,title) WindowModalDialog.__init__(self,parent,title)
#WindowModalDialog.__init__(self,parent) #WindowModalDialog.__init__(self,parent)
self.setWindowIcon(read_bal_QIcon(icon)) self.setWindowIcon(read_QIcon_from_bytes(bal_plugin.read_file(icon)))
class BalWizardDialog(BalDialog): class BalWizardDialog(BalDialog):
def __init__(self,bal_window: 'BalWindow' ): def __init__(self,bal_window: 'BalWindow' ):
assert bal_window assert bal_window
BalDialog.__init__(self, bal_window.window, _("Bal Wizard Setup")) BalDialog.__init__(self, bal_window.window, bal_window.bal_plugin, _("Bal Wizard Setup"))
self.setMinimumSize(800, 400) self.setMinimumSize(800, 400)
self.bal_window = bal_window self.bal_window = bal_window
self.parent = bal_window.window self.parent = bal_window.window
@ -1504,18 +1517,14 @@ class BalWizardDialog(BalDialog):
def on_next_locktimeandfee(self): def on_next_locktimeandfee(self):
self.next_widget(BalWizardWEDownloadWidget(self.bal_window,self,self.on_next_wedonwload,self.on_next_heir,self.on_cancel_heir)) self.next_widget(BalWizardWEDownloadWidget(self.bal_window,self,self.on_next_wedonwload,self.on_next_heir,self.on_cancel_heir))
def on_accept(self): def on_accept(self):
print("accepted")
pass pass
def on_reject(self): def on_reject(self):
print("rejected")
pass pass
def on_close(self): def on_close(self):
print("close")
pass pass
def closeEvent(self,event): def closeEvent(self,event):
self.bal_window.update_all() self.bal_window.update_all()
self.bal_window.heir_list.update_will_settings() self.bal_window.heir_list.update_will_settings()
print("close event")
pass pass
class BalWizardWidget(QWidget): class BalWizardWidget(QWidget):
@ -1650,7 +1659,7 @@ class BalWizardWEDownloadWidget(BalWizardWidget):
self.bal_window.willexecutors[we]['selected']=True self.bal_window.willexecutors[we]['selected']=True
Willexecutors.save(self.bal_window.bal_plugin,self.bal_window.willexecutors) Willexecutors.save(self.bal_window.bal_plugin,self.bal_window.willexecutors)
def on_failure(fail): def on_failure(fail):
print(f"fail") _logger.debug(f"Failed to download willexecutors list {fail}")
pass pass
task = partial(Willexecutors.download_list,self.bal_window.bal_plugin) task = partial(Willexecutors.download_list,self.bal_window.bal_plugin)
@ -1758,7 +1767,7 @@ class BalWaitingDialog(BalDialog):
updatemessage=pyqtSignal([str], arguments=['message']) updatemessage=pyqtSignal([str], arguments=['message'])
def __init__(self, bal_window: 'BalWindow', message: str, task, on_success=None, on_error=None, on_cancel=None,exe=True): def __init__(self, bal_window: 'BalWindow', message: str, task, on_success=None, on_error=None, on_cancel=None,exe=True):
assert bal_window assert bal_window
BalDialog.__init__(self, bal_window.window, _("Please wait")) BalDialog.__init__(self, bal_window.window,bal_window.bal_plugin, _("Please wait"))
self.message_label = QLabel(message) self.message_label = QLabel(message)
vbox = QVBoxLayout(self) vbox = QVBoxLayout(self)
vbox.addWidget(self.message_label) vbox.addWidget(self.message_label)
@ -1805,7 +1814,7 @@ class BalWaitingDialog(BalDialog):
class BalBlockingWaitingDialog(BalDialog): class BalBlockingWaitingDialog(BalDialog):
def __init__(self, bal_window: 'BalWindow', message: str, task: Callable[[], Any]): def __init__(self, bal_window: 'BalWindow', message: str, task: Callable[[], Any]):
BalDialog.__init__(self, bal_window, _("Please wait")) BalDialog.__init__(self, bal_window, bal_window.bal_plugin,_("Please wait"))
self.message_label = QLabel(message) self.message_label = QLabel(message)
vbox = QVBoxLayout(self) vbox = QVBoxLayout(self)
vbox.addWidget(self.message_label) vbox.addWidget(self.message_label)
@ -1823,12 +1832,15 @@ class BalBlockingWaitingDialog(BalDialog):
self.accept() self.accept()
class bal_checkbox(QCheckBox): class bal_checkbox(QCheckBox):
def __init__(self, variable,window=None): def __init__(self, variable,on_click=None):
QCheckBox.__init__(self) QCheckBox.__init__(self)
self.setChecked(variable.get()) self.setChecked(variable.get())
self.on_click=on_click
def on_check(v): def on_check(v):
variable.set(v == 2) variable.set(v == 2)
variable.get() variable.get()
if self.on_click:
self.on_click()
self.stateChanged.connect(on_check) self.stateChanged.connect(on_check)
class BalBuildWillDialog(BalDialog): class BalBuildWillDialog(BalDialog):
@ -1836,7 +1848,7 @@ class BalBuildWillDialog(BalDialog):
def __init__(self,bal_window,parent=None): def __init__(self,bal_window,parent=None):
if not parent: if not parent:
parent = bal_window.window parent = bal_window.window
BalDialog.__init__(self,parent,"Building Will") BalDialog.__init__(self,parent,babl_window.bal_plugin, "Building Will")
self.updatemessage.connect(self.update) self.updatemessage.connect(self.update)
self.bal_window=bal_window self.bal_window=bal_window
self.message_label = QLabel("Building Will:") self.message_label = QLabel("Building Will:")
@ -2493,6 +2505,17 @@ class PreviewList(MyTreeView):
self.update() self.update()
def update(self): def update(self):
try:
self.menu.removeAction(self.importaction)
except Exception as e:
pass
finally:
if self.bal_plugin.ENABLE_MULTIVERSE.get():
try:
self.importaction=self.menu.addAction(_("Import"), self.import_will)
except Exception as ex:
pass
if self.will is None: if self.will is None:
return return
@ -2510,8 +2533,11 @@ class PreviewList(MyTreeView):
if self.bal_window.bal_plugin._hide_invalidated and bal_tx.get_status('INVALIDATED'): if self.bal_window.bal_plugin._hide_invalidated and bal_tx.get_status('INVALIDATED'):
continue continue
if not isinstance(bal_tx,WillItem):
bal_tx=WillItem(bal_tx)
tx=bal_tx.tx tx=bal_tx.tx
labels = [""] * len(self.Columns) labels = [""] * len(self.Columns)
labels[self.Columns.LOCKTIME] = Util.locktime_to_str(tx.locktime) labels[self.Columns.LOCKTIME] = Util.locktime_to_str(tx.locktime)
labels[self.Columns.TXID] = txid labels[self.Columns.TXID] = txid
@ -2551,21 +2577,29 @@ class PreviewList(MyTreeView):
menu.addAction(_("Display"), self.bal_window.preview_modal_dialog) menu.addAction(_("Display"), self.bal_window.preview_modal_dialog)
menu.addAction(_("Sign"), self.ask_password_and_sign_transactions) menu.addAction(_("Sign"), self.ask_password_and_sign_transactions)
menu.addAction(_("Export"), self.export_will) menu.addAction(_("Export"), self.export_will)
menu.addAction(_("Import"), self.import_will) if self.bal_plugin.ENABLE_MULTIVERSE.get():
self.importaction=menu.addAction(_("Import"), self.import_will)
menu.addAction(_("Broadcast"), self.broadcast) menu.addAction(_("Broadcast"), self.broadcast)
menu.addAction(_("Check"), self.check) menu.addAction(_("Check"), self.check)
menu.addAction(_("Invalidate"), self.invalidate_will) menu.addAction(_("Invalidate"), self.invalidate_will)
wizard=QPushButton(_("Setup Wizard")) wizard=QPushButton(_("Setup Wizard"))
wizard.clicked.connect(self.bal_window.init_wizard) wizard.clicked.connect(self.bal_window.init_wizard)
display = QPushButton(_("Display"))
display.clicked.connect(self.bal_window.preview_modal_dialog)
widget = QWidget() widget = QWidget()
hlayout = QHBoxLayout(widget) hlayout = QHBoxLayout(widget)
hlayout.addWidget(wizard) hlayout.addWidget(wizard)
hlayout.addWidget(display)
toolbar.insertWidget(2,widget) toolbar.insertWidget(2,widget)
self.menu=menu
self.toolbar=toolbar
return toolbar return toolbar
def hide_replaced(self): def hide_replaced(self):
self.bal_window.bal_plugin.hide_replaced() self.bal_window.bal_plugin.hide_replaced()
self.update() self.update()
@ -2607,7 +2641,7 @@ class PreviewList(MyTreeView):
class PreviewDialog(BalDialog,MessageBoxMixin): class PreviewDialog(BalDialog,MessageBoxMixin):
def __init__(self, bal_window, will): def __init__(self, bal_window, will):
self.parent = bal_window.window self.parent = bal_window.window
BalDialog.__init__(self,bal_window = bal_window) BalDialog.__init__(self,bal_window = bal_window,bal_plugin=bal_window.bal_plugin)
self.bal_plugin = bal_window.bal_plugin self.bal_plugin = bal_window.bal_plugin
self.gui_object = self.bal_plugin.gui_object self.gui_object = self.bal_plugin.gui_object
self.config = self.bal_plugin.config self.config = self.bal_plugin.config
@ -2679,9 +2713,11 @@ class PreviewDialog(BalDialog,MessageBoxMixin):
def read_bal_QIcon(icon_basename: str=DEFAULT_ICON) -> QIcon: def read_bal_QIcon(icon_basename: str=DEFAULT_ICON) -> QIcon:
return QIcon(icon_path(icon_basename)) return QIcon(icon_path(icon_basename))
def read_bal_QPixmap(icon_basename: str=DEFAULT_ICON) -> QPixmap: def read_bal_QPixmap(icon_basename: str=DEFAULT_ICON) -> QPixmap:
return QPixmap(icon_path(icon_basename)) return QPixmap(icon_path(icon_basename))
class WillDetailDialog(BalDialog): class WillDetailDialog(BalDialog):
def __init__(self, bal_window): def __init__(self, bal_window):
@ -2689,7 +2725,7 @@ class WillDetailDialog(BalDialog):
self.threshold = Util.parse_locktime_string(bal_window.will_settings['threshold']) self.threshold = Util.parse_locktime_string(bal_window.will_settings['threshold'])
self.bal_window = bal_window self.bal_window = bal_window
Will.add_willtree(self.will) Will.add_willtree(self.will)
super().__init__(bal_window.window) super().__init__(bal_window.window,bal_window.bal_plugin)
self.config = bal_window.window.config self.config = bal_window.window.config
self.wallet = bal_window.wallet self.wallet = bal_window.wallet
self.format_amount = bal_window.window.format_amount self.format_amount = bal_window.window.format_amount
@ -2806,7 +2842,10 @@ class WillWidget(QWidget):
return QLabel(label) return QLabel(label)
detaillayout.addWidget(qlabel("Locktime",locktime)) detaillayout.addWidget(qlabel("Locktime",locktime))
detaillayout.addWidget(qlabel("Creation Time",creation)) detaillayout.addWidget(qlabel("Creation Time",creation))
total_fees = self.will[w].tx.input_value() - self.will[w].tx.output_value() try:
total_fees = self.will[w].tx.input_value() - self.will[w].tx.output_value()
except:
total_fees = -1
decoded_fees = total_fees decoded_fees = total_fees
fee_per_byte = round(total_fees/self.will[w].tx.estimated_size(),3) fee_per_byte = round(total_fees/self.will[w].tx.estimated_size(),3)
fees_str = str(decoded_fees) + " ("+ str(fee_per_byte) + " sats/vbyte)" fees_str = str(decoded_fees) + " ("+ str(fee_per_byte) + " sats/vbyte)"
@ -3102,7 +3141,7 @@ class WillExecutorDialog(BalDialog,MessageBoxMixin):
def __init__(self, bal_window,parent=None): def __init__(self, bal_window,parent=None):
if not parent: if not parent:
parent=bal_window.window parent=bal_window.window
BalDialog.__init__(self,parent) BalDialog.__init__(self,parent,bal_window.bal_plugin)
self.bal_plugin = bal_window.bal_plugin self.bal_plugin = bal_window.bal_plugin
self.config = self.bal_plugin.config self.config = self.bal_plugin.config
self.bal_window = bal_window self.bal_window = bal_window

View File

@ -72,6 +72,8 @@ class Will:
for txin in will[wid].tx.inputs(): for txin in will[wid].tx.inputs():
txid = txin.prevout.txid.hex() txid = txin.prevout.txid.hex()
if txid in will: if txid in will:
#print(will[txid].tx.outputs())
#print(txin.prevout.out_idx)
change = will[txid].tx.outputs()[txin.prevout.out_idx] change = will[txid].tx.outputs()[txin.prevout.out_idx]
txin._trusted_value_sats = change.value txin._trusted_value_sats = change.value
try: try:
@ -88,8 +90,11 @@ class Will:
to_delete = [] to_delete = []
to_add = {} to_add = {}
#add info from wallet #add info from wallet
willitems={}
for wid in will: for wid in will:
Will.add_info_from_will(will,wid,wallet) Will.add_info_from_will(will,wid,wallet)
willitems[wid]=WillItem(will[wid])
will=willitems
errors ={} errors ={}
for wid in will: for wid in will:
@ -110,7 +115,7 @@ class Will:
outputs = will[wid].tx.outputs() outputs = will[wid].tx.outputs()
ow=will[wid] ow=will[wid]
ow.normalize_locktime(others_inputs) ow.normalize_locktime(others_inputs)
will[wid]=ow.to_dict() will[wid]=WillItem(ow.to_dict())
for i in range(0,len(outputs)): for i in range(0,len(outputs)):
Will.change_input(will,wid,i,outputs[i],others_inputs,to_delete,to_add) Will.change_input(will,wid,i,outputs[i],others_inputs,to_delete,to_add)
@ -319,7 +324,6 @@ class Will:
locktime = Util.get_current_height(wallet.network) locktime = Util.get_current_height(wallet.network)
tx = PartialTransaction.from_io(utxo_to_spend, [out], locktime=locktime, version=2) tx = PartialTransaction.from_io(utxo_to_spend, [out], locktime=locktime, version=2)
tx.set_rbf(True) tx.set_rbf(True)
print("fees_per_byte:",fees_per_byte)
fee=tx.estimated_size()*fees_per_byte fee=tx.estimated_size()*fees_per_byte
if balance -fee >0: if balance -fee >0:
out = PartialTxOutput.from_address_and_value(change_addresses[0],balance - fee) out = PartialTxOutput.from_address_and_value(change_addresses[0],balance - fee)

View File

@ -23,9 +23,15 @@ class Willexecutors:
def get_willexecutors(bal_plugin, update = False,bal_window=False,force=False,task=True): def get_willexecutors(bal_plugin, update = False,bal_window=False,force=False,task=True):
willexecutors = bal_plugin.WILLEXECUTORS.get() willexecutors = bal_plugin.WILLEXECUTORS.get()
willexecutors=willexecutors.get(constants.net.NET_NAME,{}) willexecutors=willexecutors.get(constants.net.NET_NAME,{})
to_del=[]
for w in willexecutors: for w in willexecutors:
if not isinstance(willexecutors[w],dict):
to_del.append(w)
continue
Willexecutors.initialize_willexecutor(willexecutors[w],w) Willexecutors.initialize_willexecutor(willexecutors[w],w)
for w in to_del:
print("ERROR: WILLEXECUTOR TO DELETE:", w)
del willexecutors[w]
bal = bal_plugin.WILLEXECUTORS.default.get(constants.net.NET_NAME,{}) bal = bal_plugin.WILLEXECUTORS.default.get(constants.net.NET_NAME,{})
for bal_url,bal_executor in bal.items(): for bal_url,bal_executor in bal.items():
if not bal_url in willexecutors: if not bal_url in willexecutors:
@ -172,6 +178,7 @@ class Willexecutors:
if constants.net.NET_NAME!="mainnet": if constants.net.NET_NAME!="mainnet":
netname=constants.net.NET_NAME netname=constants.net.NET_NAME
w = Willexecutors.send_request('get',url+"/"+netname+"/info") w = Willexecutors.send_request('get',url+"/"+netname+"/info")
willexecutor['url']=url willexecutor['url']=url
willexecutor['status'] = w['status'] willexecutor['status'] = w['status']
willexecutor['base_fee'] = w['base_fee'] willexecutor['base_fee'] = w['base_fee']
@ -204,7 +211,7 @@ class Willexecutors:
return l return l
except Exception as e: except Exception as e:
_logger.error(f"error downloading willexecutors list:{e}") _logger.error(f"Failed to download willexecutors list: {e}")
return {} return {}
def get_willexecutors_list_from_json(bal_plugin): def get_willexecutors_list_from_json(bal_plugin):
try: try: