Compare commits

..

No commits in common. "461b0cb368c91109556ca1d6af4b713d202b1980" and "a7b778e0b23f027e2eda1745de5639a9e3f8ca1e" have entirely different histories.

6 changed files with 181 additions and 528 deletions

143
bal.py
View File

@ -9,111 +9,112 @@ import os
json_db.register_dict('heirs', tuple, None) json_db.register_dict('heirs', tuple, None)
json_db.register_dict('will', lambda x: get_will(x), None) json_db.register_dict('will', lambda x: get_will(x), None)
json_db.register_dict('will_settings', lambda x:x, None) json_db.register_dict('will_settings', lambda x:x, None)
from electrum.logging import get_logger from electrum.logging import get_logger
def get_will(x): def get_will(x):
try: try:
x['tx']=tx_from_any(x['tx']) x['tx']=tx_from_any(x['tx'])
except Exception as e: except Exception as e:
raise e raise e
return x return x
class BalConfig():
def __init__(self, config, name, default):
self.config = config
self.name = name
self.default = default
def get(self,default=None):
v = self.config.get(self.name, default)
if v is None:
if not default is None:
v = default
else:
v = v.default
return v
def set(self,value,save=True):
self.config.set_key(self.name,value,save=save)
class BalPlugin(BasePlugin): class BalPlugin(BasePlugin):
LATEST_VERSION = '1' LOCKTIME_TIME = "bal_locktime_time"
KNOWN_VERSIONS = ('0', '1') LOCKTIME_BLOCKS = "bal_locktime_blocks"
assert LATEST_VERSION in KNOWN_VERSIONS LOCKTIMEDELTA_TIME = "bal_locktimedelta_time"
def version(): LOCKTIMEDELTA_BLOCKS = "bal_locktimedelta_blocks"
try: TX_FEES = "bal_tx_fees"
f="" BROADCAST = "bal_broadcast"
with open("VERSION","r") as f: ASK_BROADCAST = "bal_ask_broadcast"
f = str(f.readline()) INVALIDATE = "bal_invalidate"
return f ASK_INVALIDATE = "bal_ask_invalidate"
except: PREVIEW = "bal_preview"
return "unknown" SAVE_TXS = "bal_save_txs"
SIZE = (159, 97) WILLEXECUTORS = "bal_willexecutors"
PING_WILLEXECUTORS = "bal_ping_willexecutors"
ASK_PING_WILLEXECUTORS = "bal_ask_ping_willexecutors"
NO_WILLEXECUTOR = "bal_no_willexecutor"
HIDE_REPLACED = "bal_hide_replaced"
HIDE_INVALIDATED = "bal_hide_invalidated"
ALLOW_REPUSH = "bal_allow_repush"
def __init__(self, parent, config, name):
self.logger = get_logger(__name__)
BasePlugin.__init__(self, parent, config, name)
self.base_dir = os.path.join(config.electrum_path(), 'bal')
self.plugin_dir = os.path.split(os.path.realpath(__file__))[0]
self.logger.info(self.base_dir)
self.parent = parent
self.config = config
self.name = name
self.ASK_BROADCAST = BalConfig(config, "bal_ask_broadcast",True) DEFAULT_SETTINGS={
self.BROADCAST = BalConfig(config, "bal_broadcast",True) LOCKTIME_TIME: 90,
self.LOCKTIME_TIME = BalConfig(config, "bal_locktime_time",90) LOCKTIME_BLOCKS: 144*90,
self.LOCKTIME_BLOCKS = BalConfig(config, "bal_locktime_blocks",144*90) LOCKTIMEDELTA_TIME: 7,
self.LOCKTIMEDELTA_TIME = BalConfig(config, "bal_locktimedelta_time",7) LOCKTIMEDELTA_BLOCKS:144*7,
self.LOCKTIMEDELTA_BLOCKS = BalConfig(config, "bal_locktimedelta_blocks",144*7) TX_FEES: 100,
self.TX_FEES = BalConfig(config, "bal_tx_fees",100) BROADCAST: True,
self.INVALIDATE = BalConfig(config, "bal_invalidate",True) ASK_BROADCAST: True,
self.ASK_INVALIDATE = BalConfig(config, "bal_ask_invalidate",True) INVALIDATE: True,
self.PREVIEW = BalConfig(config, "bal_preview",True) ASK_INVALIDATE: True,
self.SAVE_TXS = BalConfig(config, "bal_save_txs",True) PREVIEW: True,
self.WILLEXECUTORS = BalConfig(config, "bal_willexecutors",True) SAVE_TXS: True,
self.PING_WILLEXECUTORS = BalConfig(config, "bal_ping_willexecutors",True) PING_WILLEXECUTORS: False,
self.ASK_PING_WILLEXECUTORS = BalConfig(config, "bal_ask_ping_willexecutors",True) ASK_PING_WILLEXECUTORS: False,
self.NO_WILLEXECUTOR = BalConfig(config, "bal_no_willexecutor",True) NO_WILLEXECUTOR: False,
self.HIDE_REPLACED = BalConfig(config, "bal_hide_replaced",True) HIDE_REPLACED:True,
self.HIDE_INVALIDATED = BalConfig(config, "bal_hide_invalidated",True) HIDE_INVALIDATED:True,
self.ALLOW_REPUSH = BalConfig(config, "bal_allow_repush",True) ALLOW_REPUSH: False,
self.FIRST_EXECUTION = BalConfig(config, "bal_first_execution",True) WILLEXECUTORS: {
self.WILLEXECUTORS = BalConfig(config, "bal_willexecutors", { 'https://bitcoin-after.life:9137': {
"mainnet": {
'https://we.bitcoin-after.life': {
"base_fee": 100000, "base_fee": 100000,
"status": "New", "status": "New",
"info":"Bitcoin After Life Will Executor", "info":"Bitcoin After Life Will Executor",
"address":"bcrt1qa5cntu4hgadw8zd3n6sq2nzjy34sxdtd9u0gp7", "address":"bcrt1qa5cntu4hgadw8zd3n6sq2nzjy34sxdtd9u0gp7",
"selected":True "selected":True
} }
},
} }
})
self.WILL_SETTINGS = BalConfig(config, "bal_will_settings", {
'tx_fees':100,
'threshold':'180d',
'locktime':'1y',
})
LATEST_VERSION = '1'
KNOWN_VERSIONS = ('0', '1')
assert LATEST_VERSION in KNOWN_VERSIONS
self._hide_invalidated= self.HIDE_INVALIDATED.get() SIZE = (159, 97)
self._hide_replaced= self.HIDE_REPLACED.get()
def __init__(self, parent, config, name):
self.logger= get_logger(__name__)
BasePlugin.__init__(self, parent, config, name)
self.base_dir = os.path.join(config.electrum_path(), 'bal')
self.logger.info(self.base_dir)
self.parent = parent
self.config = config
self.name = name
self._hide_invalidated= self.config_get(self.HIDE_INVALIDATED)
self._hide_replaced= self.config_get(self.HIDE_REPLACED)
self.plugin_dir = os.path.split(os.path.realpath(__file__))[0]
def resource_path(self,*parts): def resource_path(self,*parts):
return os.path.join(self.plugin_dir, *parts) return os.path.join(self.plugin_dir, *parts)
def config_get(self,key):
v = self.config.get(key,None)
if v is None:
self.config.set_key(key,self.DEFAULT_SETTINGS[key])
v = self.DEFAULT_SETTINGS[key]
return v
def hide_invalidated(self): def hide_invalidated(self):
self._hide_invalidated = not self._hide_invalidated self._hide_invalidated = not self._hide_invalidated
self.HIDE_INVALIDATED.set(self._hide_invalidated) self.config.set_key(BalPlugin.HIDE_INVALIDATED,self.hide_invalidated,save=True)
def hide_replaced(self): def hide_replaced(self):
self._hide_replaced = not self._hide_replaced self._hide_replaced = not self._hide_replaced
self.HIDE_REPLACED.set(self._hide_replaced) self.config.set_key(BalPlugin.HIDE_REPLACED,self.hide_invalidated,save=True)
def default_will_settings(self):
return {
'tx_fees':100,
'threshold':'180d',
'locktime':'1y',
}
def validate_will_settings(self,will_settings): def validate_will_settings(self,will_settings):
if int(will_settings.get('tx_fees',1))<1: if int(will_settings.get('tx_fees',1))<1:
will_settings['tx_fees']=1 will_settings['tx_fees']=1

View File

@ -14,6 +14,7 @@ from electrum.transaction import PartialTxInput, PartialTxOutput,TxOutpoint,Part
import datetime import datetime
import urllib.request import urllib.request
import urllib.parse import urllib.parse
from .bal import BalPlugin
from .util import Util from .util import Util
from .willexecutors import Willexecutors from .willexecutors import Willexecutors
if TYPE_CHECKING: if TYPE_CHECKING:
@ -386,7 +387,7 @@ class Heirs(dict, Logger):
utxos = wallet.get_utxos() utxos = wallet.get_utxos()
willexecutors = Willexecutors.get_willexecutors(bal_plugin) or {} willexecutors = Willexecutors.get_willexecutors(bal_plugin) or {}
self.decimal_point=bal_plugin.config.get_decimal_point() self.decimal_point=bal_plugin.config.get_decimal_point()
no_willexecutors = bal_plugin.NO_WILLEXECUTOR.get() no_willexecutors = bal_plugin.config_get(BalPlugin.NO_WILLEXECUTOR)
for utxo in utxos: for utxo in utxos:
if utxo.value_sats()> 0*tx_fees: if utxo.value_sats()> 0*tx_fees:
balance += utxo.value_sats() balance += utxo.value_sats()

View File

@ -1,9 +1,8 @@
{ {
"name": "BAL", "name": "BAL",
"fullname": "Bitcoin After Life", "fullname": "Bitcoin After Life",
"description": "Provides free and decentralized inheritance support<br> Version: 0.2.1b", "description": "Provides free and decentralized inheritance support<br> Version: 0.2.0b",
"author":"Svatantrya", "author":"Svatantrya",
"available_for": ["qt"], "available_for": ["qt"],
"icon":"icons/bal32x32.png" "icon":"icons/bal32x32.png"
} }

475
qt.py
View File

@ -244,18 +244,24 @@ if TYPE_CHECKING:
from electrum.gui.qt.main_window import ElectrumWindow from electrum.gui.qt.main_window import ElectrumWindow
from electrum.gui.qt.util import ( from electrum.gui.qt.util import (
Buttons,
read_QIcon,
import_meta_gui,
export_meta_gui,
MessageBoxMixin,
Buttons,
export_meta_gui,
MessageBoxMixin,
char_width_in_lineedit,
ColorScheme,
Buttons, Buttons,
CancelButton, CancelButton,
char_width_in_lineedit, char_width_in_lineedit,
CloseButton, CloseButton,
ColorScheme,
EnterButton, EnterButton,
export_meta_gui,
HelpButton, HelpButton,
import_meta_gui,
MessageBoxMixin, MessageBoxMixin,
OkButton, OkButton,
read_QIcon,
TaskThread, TaskThread,
WindowModalDialog, WindowModalDialog,
WWLabel, WWLabel,
@ -412,11 +418,8 @@ class Plugin(BalPlugin,Logger):
def settings_widget(self, window): def settings_widget(self, window):
w=self.get_window(window.window) w=self.get_window(window.window)
widget=QWidget() return EnterButton(_('Settings'), partial(w.settings_dialog,window))
enterbutton=EnterButton(_('Settings'), partial(w.settings_dialog,window))
widget.setLayout(Buttons(enterbutton,widget))
return widget
def password_dialog(self, msg=None, parent=None): def password_dialog(self, msg=None, parent=None):
parent = parent or self parent = parent or self
d = PasswordDialog(parent, msg) d = PasswordDialog(parent, msg)
@ -443,14 +446,14 @@ class Plugin(BalPlugin,Logger):
lbl_logo = QLabel() lbl_logo = QLabel()
lbl_logo.setPixmap(qicon) lbl_logo.setPixmap(qicon)
heir_ping_willexecutors = bal_checkbox(self.PING_WILLEXECUTORS) heir_ping_willexecutors = bal_checkbox(self, BalPlugin.PING_WILLEXECUTORS)
heir_ask_ping_willexecutors = bal_checkbox(self.ASK_PING_WILLEXECUTORS) heir_ask_ping_willexecutors = bal_checkbox(self, BalPlugin.ASK_PING_WILLEXECUTORS)
heir_no_willexecutor = bal_checkbox(self.NO_WILLEXECUTOR) heir_no_willexecutor = bal_checkbox(self, BalPlugin.NO_WILLEXECUTOR)
heir_hide_replaced = bal_checkbox(self.HIDE_REPLACED,self) heir_hide_replaced = bal_checkbox(self,BalPlugin.HIDE_REPLACED,self)
heir_hide_invalidated = bal_checkbox(self.HIDE_INVALIDATED,self) heir_hide_invalidated = bal_checkbox(self,BalPlugin.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)
@ -579,55 +582,36 @@ class BalWindow(Logger):
self.bal_plugin.validate_will_settings(self.will_settings) self.bal_plugin.validate_will_settings(self.will_settings)
self.heir_list.update_will_settings() self.heir_list.update_will_settings()
def init_wizard(self):
wizard_dialog = BalWizardDialog(self)
wizard_dialog.exec()
def show_willexecutor_dialog(self): def show_willexecutor_dialog(self):
self.willexecutor_dialog = WillExecutorDialog(self) self.willexecutor_dialog = WillExecutorDialog(self)
self.willexecutor_dialog.show() self.willexecutor_dialog.show()
def create_heirs_tab(self): def create_heirs_tab(self):
self.heir_list = l = HeirList(self,self.window) self.heir_list = l = HeirList(self)
tab = self.window.create_list_tab(l) tab = self.window.create_list_tab(l)
tab.is_shown_cv = shown_cv(True) tab.is_shown_cv = shown_cv(True)
return tab return tab
def create_will_tab(self): def create_will_tab(self):
self.will_list = l = PreviewList(self,self.window,None) self.will_list = l = PreviewList(self,None)
tab = self.window.create_list_tab(l) tab = self.window.create_list_tab(l)
tab.is_shown_cv = shown_cv(True) tab.is_shown_cv = shown_cv(True)
return tab return tab
def new_heir_dialog(self,heir=None): def new_heir_dialog(self):
d = BalDialog(self.window, self.bal_plugin.get_window_title("New heir")) d = BalDialog(self.window, self.bal_plugin.get_window_title("New heir"))
vbox = QVBoxLayout(d) vbox = QVBoxLayout(d)
grid = QGridLayout() grid = QGridLayout()
heir_name = QLineEdit() heir_name = QLineEdit()
heir_name.setFixedWidth(32 * char_width_in_lineedit()) heir_name.setFixedWidth(32 * char_width_in_lineedit())
if heir:
heir_name.setText(heir[0])
heir_address = QLineEdit() heir_address = QLineEdit()
heir_address.setFixedWidth(32 * char_width_in_lineedit()) heir_address.setFixedWidth(32 * char_width_in_lineedit())
if heir:
heir_address.setText(heir[1])
heir_amount = PercAmountEdit(self.window.get_decimal_point) heir_amount = PercAmountEdit(self.window.get_decimal_point)
if heir:
heir_amount.setText(heir[2])
heir_locktime = HeirsLockTimeEdit(self.window,0) heir_locktime = HeirsLockTimeEdit(self.window,0)
if heir:
heir_locktime.setText(heir[3])
heir_is_xpub = QCheckBox() heir_is_xpub = QCheckBox()
new_heir_button=QPushButton(_("Add another heir"))
self.add_another_heir=False
def new_heir():
self.add_another_heir=True
d.accept()
new_heir_button.clicked.connect(new_heir)
new_heir_button.setDefault(True)
grid.addWidget(QLabel(_("Name")), 1, 0) grid.addWidget(QLabel(_("Name")), 1, 0)
grid.addWidget(heir_name, 1, 1) grid.addWidget(heir_name, 1, 1)
@ -642,7 +626,7 @@ class BalWindow(Logger):
grid.addWidget(HelpButton("Fixed or Percentage amount if end with %"),3,2) grid.addWidget(HelpButton("Fixed or Percentage amount if end with %"),3,2)
vbox.addLayout(grid) vbox.addLayout(grid)
vbox.addLayout(Buttons(CancelButton(d), OkButton(d),new_heir_button)) vbox.addLayout(Buttons(CancelButton(d), OkButton(d)))
while d.exec(): while d.exec():
#TODO SAVE HEIR #TODO SAVE HEIR
heir = [ heir = [
@ -653,19 +637,17 @@ class BalWindow(Logger):
] ]
try: try:
self.set_heir(heir) self.set_heir(heir)
if self.add_another_heir:
self.new_heir_dialog()
break break
except Exception as e: except Exception as e:
self.show_error(str(e)) self.show_error(str(e))
#def export_inheritance_handler(self,path): def export_inheritance_handler(self,path):
# txs = self.build_inheritance_transaction(ignore_duplicate=True, keep_original=False) txs = self.build_inheritance_transaction(ignore_duplicate=True, keep_original=False)
# with open(path,"w") as f: with open(path,"w") as f:
# for tx in txs: for tx in txs:
# tx['status']+="."+BalPlugin.STATUS_EXPORTED tx['status']+="."+BalPlugin.STATUS_EXPORTED
# f.write(str(tx['tx'])) f.write(str(tx['tx']))
# f.write('\n') f.write('\n')
def set_heir(self,heir): def set_heir(self,heir):
heir=list(heir) heir=list(heir)
@ -768,10 +750,10 @@ class BalWindow(Logger):
try: try:
self.date_to_check = Util.parse_locktime_string(self.will_settings['threshold']) self.date_to_check = Util.parse_locktime_string(self.will_settings['threshold'])
found = False found = False
self.locktime_blocks=self.bal_plugin.LOCKTIME_BLOCKS.get() self.locktime_blocks=self.bal_plugin.config_get(BalPlugin.LOCKTIME_BLOCKS)
self.current_block = Util.get_current_height(self.wallet.network) self.current_block = Util.get_current_height(self.wallet.network)
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.config_get(BalPlugin.NO_WILLEXECUTOR)
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()
@ -961,8 +943,8 @@ class BalWindow(Logger):
def on_close(self): def on_close(self):
try: try:
if not self.disable_plugin: if not self.disable_plugin:
close_window=BalBuildWillDialog(self) close_window=BalCloseDialog(self)
close_window.build_will_task() close_window.close_plugin_task()
self.save_willitems() self.save_willitems()
self.heirs_tab.close() self.heirs_tab.close()
self.will_tab.close() self.will_tab.close()
@ -1458,256 +1440,6 @@ class BalDialog(WindowModalDialog):
WindowModalDialog.__init__(self,self.parent,title) WindowModalDialog.__init__(self,self.parent,title)
self.setWindowIcon(read_bal_QIcon(icon)) self.setWindowIcon(read_bal_QIcon(icon))
class BalWizardDialog(BalDialog):
def __init__(self,bal_window: 'BalWindow' ):
assert bal_window
BalDialog.__init__(self, bal_window.window, _("Bal Wizard Setup"))
self.setMinimumSize(800, 400)
self.bal_window = bal_window
self.parent = bal_window.window
self.layout=QVBoxLayout(self)
self.widget = BalWizardHeirsWidget(bal_window,self,self.on_next_heir,None,self.on_cancel_heir)
self.layout.addWidget(self.widget)
def next_widget(self,widget):
self.layout.removeWidget(self.widget)
self.widget.close()
self.widget=widget
self.layout.addWidget(self.widget)
#self.update()
#self.repaint()
def on_next_heir(self):
self.next_widget(BalWizardLocktimeAndFeeWidget(self.bal_window,self,self.on_next_locktimeandfee,self.on_previous_heir,self.on_cancel_heir))
def on_previous_heir(self):
self.next_widget(BalWizardHeirsWidget(self.bal_window,self,self.on_next_heir,None,self.on_cancel_heir))
def on_cancel_heir(self):
pass
def on_next_wedonwload(self):
self.next_widget(BalWizardWEWidget(self.bal_window,self,self.on_next_we,self.on_next_locktimeandfee,self.on_cancel_heir))
def on_next_we(self):
close_window=BalBuildWillDialog(self.bal_window,self)
close_window.build_will_task()
self.close()
#self.next_widget(BalWizardLocktimeAndFeeWidget(self.bal_window,self,self.on_next_locktimeandfee,self.on_next_wedonwload,self.on_next_wedonwload.on_cancel_heir))
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))
def on_accept(self):
print("accepted")
def on_reject(self):
print("rejected")
def on_close(self):
print("close")
def closeEvent(self,event):
self.bal_window.update_all()
self.bal_window.heir_list.update_will_settings()
print("close event")
class BalWizardWidget(QWidget):
title = None
message = None
def __init__(self,bal_window: 'BalWindow',parent,on_next,on_previous,on_cancel):
QWidget.__init__(self,parent)
self.vbox=QVBoxLayout(self)
self.bal_window=bal_window
self.parent=parent
self.on_next=on_next
self.on_cancel=on_cancel
self.titleLabel = QLabel(self.title)
self.vbox.addWidget(self.titleLabel)
self.messageLabel = QLabel(_(self.message))
self.vbox.addWidget(self.messageLabel)
self.content = self.get_content()
self.content_container= QWidget()
self.containrelayout=QVBoxLayout(self.content_container)
self.containrelayout.addWidget(self.content)
self.vbox.addWidget(self.content_container)
spacer_widget = QWidget()
spacer_widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
self.vbox.addWidget(spacer_widget)
self.buttons=[]
if on_previous:
self.on_previous=on_previous
self.previous_button = QPushButton(_("Previous"))
self.previous_button.clicked.connect(self._on_previous)
self.buttons.append(self.previous_button)
self.next_button = QPushButton(_("Next"))
self.next_button.clicked.connect(self._on_next)
self.buttons.append(self.next_button)
self.abort_button = QPushButton(_("Cancel"))
self.abort_button.clicked.connect(self._on_cancel)
self.buttons.append(self.abort_button)
self.vbox.addLayout(Buttons(*self.buttons))
def _on_cancel(self):
self.on_cancel()
self.parent.close()
def _on_next(self):
if self.validate():
self.on_next()
def _on_previous(self):
self.on_previous()
def get_content(self):
pass
def validate(self):
return True
class BalWizardHeirsWidget(BalWizardWidget):
title="Bitcoin After Life Heirs"
message="Please add your heirs\n remember that 100% of wallet balance will be spent"
def get_content(self):
self.heirs_list=HeirList(self.bal_window,self.parent)
button_add=QPushButton(_("Add"))
button_add.clicked.connect(self.add_heir)
button_import=QPushButton(_("Import from file"))
button_import.clicked.connect(self.import_from_file)
widget=QWidget()
vbox=QVBoxLayout(widget)
vbox.addWidget(self.heirs_list)
vbox.addLayout(Buttons(button_add,button_import))
return widget
def import_from_file(self):
self.bal_window.import_heirs()
self.heirs_list.update()
def add_heir(self):
self.bal_window.new_heir_dialog()
self.heirs_list.update()
def validate(self):
return True
class BalWizardWEDownloadWidget(BalWizardWidget):
title=_("Bitcoin After Life Will-Executors")
message=_("Choose willexecutors download method")
def get_content(self):
question=QLabel()
self.combo=QComboBox()
self.combo.addItems([
"Automatically download and select willexecutors",
"Only download willexecutors list",
"Import willexecutor list from file",
"Manual"])
#heir_name.setFixedWidth(32 * char_width_in_lineedit())
return self.combo
def validate(self):
return True
def _on_next(self):
index = self.combo.currentIndex()
_logger.debug(f"selected index:{index}")
if index < 2:
willexecutors = Willexecutors.download_list(self.bal_window.bal_plugin)
if index < 1:
for we in willexecutors.values():
we['selected']=True
elif index == 2:
#TODO import from file
pass
elif index == 3:
#TODO DO NOTHING
pass
if self.validate():
return self.on_next()
class BalWizardWEWidget(BalWizardWidget):
title=("Bitcoin After Life Will-Executors")
message=_("Configure and select your willexecutors")
def get_content(self):
widget=QWidget()
vbox=QVBoxLayout(widget)
vbox.addWidget(WillExecutorWidget(self,self.bal_window,Willexecutors.get_willexecutors(self.bal_window.bal_plugin)))
return widget
class BalWizardLocktimeAndFeeWidget(BalWizardWidget):
title=("Bitcoin After Life Will Settings")
message=_("")
def get_content(self):
widget=QWidget()
self.heir_locktime = HeirsLockTimeEdit(widget,0)
will_settings=self.bal_window.bal_plugin.WILL_SETTINGS.get()
self.heir_locktime.set_locktime(will_settings['locktime'])
def on_heir_locktime():
if not self.heir_locktime.get_locktime():
self.heir_locktime.set_locktime('1y')
self.bal_window.will_settings['locktime'] = self.heir_locktime.get_locktime() if self.heir_locktime.get_locktime() else "1y"
self.bal_window.bal_plugin.WILL_SETTINGS.set(self.bal_window.will_settings)
self.heir_locktime.valueEdited.connect(on_heir_locktime)
self.heir_threshold = HeirsLockTimeEdit(widget,0)
self.heir_threshold.set_locktime(will_settings['threshold'])
def on_heir_threshold():
if not self.heir_threshold.get_locktime():
self.heir_threshold.set_locktime('180d')
self.bal_window.will_settings['threshold'] = self.heir_threshold.get_locktime()
self.bal_window.bal_plugin.WILL_SETTINGS.set(self.bal_window.will_settings)
self.heir_threshold.valueEdited.connect(on_heir_threshold)
self.heir_tx_fees = QSpinBox(widget)
self.heir_tx_fees.setMinimum(1)
self.heir_tx_fees.setMaximum(10000)
self.heir_tx_fees.setValue(will_settings['tx_fees'])
def on_heir_tx_fees():
if not self.heir_tx_fees.value():
self.heir_tx_fees.set_value(1)
self.bal_window.will_settings['tx_fees'] = self.heir_tx_fees.value()
self.bal_window.bal_plugin.WILL_SETTINGS.set(self.bal_window.will_settings)
self.heir_tx_fees.valueChanged.connect(on_heir_tx_fees)
def make_hlayout(label,twidget,help_text):
tw=QWidget()
hlayout=QHBoxLayout(tw)
hlayout.addWidget(QLabel(label))
hlayout.addWidget(twidget)
hlayout.addWidget(HelpButton(help_text))
return tw
layout = QVBoxLayout(widget)
layout.addWidget(make_hlayout(_("Delivery Time:"),self.heir_locktime,_("Locktime* to be used in the transaction\n"
+"if you choose Raw, you can insert various options based on suffix:\n"
+" - d: number of days after current day(ex: 1d means tomorrow)\n"
+" - y: number of years after currrent day(ex: 1y means one year from today)\n"
+"* locktime can be anticipated to update will\n")))
layout.addWidget(make_hlayout(_("Check Alive:"),self.heir_threshold,_("Check to ask for invalidation.\n"
+"When less then this time is missing, ask to invalidate.\n"
+"If you fail to invalidate during this time, your transactions will be delivered to your heirs.\n"
+"if you choose Raw, you can insert various options based on suffix:\n"
+" - d: number of days after current day(ex: 1d means tomorrow).\n"
+" - y: number of years after currrent day(ex: 1y means one year from today).\n\n")))
layout.addWidget(make_hlayout(_("Fees(sats/vbyte):"),self.heir_tx_fees,("Fee to be used in the transaction")))
spacer_widget = QWidget()
spacer_widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
layout.addWidget(spacer_widget)
return widget
class BalWaitingDialog(BalDialog): 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):
@ -1779,27 +1511,25 @@ class BalBlockingWaitingDialog(BalDialog):
self.accept() self.accept()
class bal_checkbox(QCheckBox): class bal_checkbox(QCheckBox):
def __init__(self, variable,window=None): def __init__(self, plugin,variable,window=None):
QCheckBox.__init__(self) QCheckBox.__init__(self)
self.setChecked(variable.get()) self.setChecked(plugin.config_get(variable))
def on_check(v): def on_check(v):
variable.set(v == 2) plugin.config.set_key(variable, v == 2)
variable.get() plugin.config_get(variable)
self.stateChanged.connect(on_check) self.stateChanged.connect(on_check)
class BalBuildWillDialog(BalDialog): class BalCloseDialog(BalDialog):
updatemessage=pyqtSignal() updatemessage=pyqtSignal()
def __init__(self,bal_window,parent=None): def __init__(self,bal_window):
if not parent: BalDialog.__init__(self,bal_window.window,"Closing BAL")
parent = bal_window.window
BalDialog.__init__(self,parent,"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("Closing BAL:")
self.vbox = QVBoxLayout(self) self.vbox = QVBoxLayout(self)
self.vbox.addWidget(self.message_label) self.vbox.addWidget(self.message_label)
self.qwidget=QWidget() self.qwidget=QWidget()
@ -1817,8 +1547,8 @@ class BalBuildWillDialog(BalDialog):
def task_finished(self): def task_finished(self):
pass pass
def build_will_task(self): def close_plugin_task(self):
_logger.debug("build will task to be started") _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.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.show()
self.exec() self.exec()
@ -1983,7 +1713,7 @@ class BalBuildWillDialog(BalDialog):
self.msg_set_invalidating() self.msg_set_invalidating()
#need to sign invalidate and restart phase 1 #need to sign invalidate and restart phase 1
password = self.bal_window.get_wallet_password("Invalidate your old will",parent=self) password = self.bal_window.get_wallet_password("Invalidate your old will",parent=self.bal_window.window)
if password is False: if password is False:
self.msg_set_invalidating("Aborted") self.msg_set_invalidating("Aborted")
self.wait(3) self.wait(3)
@ -1994,7 +1724,7 @@ class BalBuildWillDialog(BalDialog):
return return
elif self.have_to_sign: elif self.have_to_sign:
password = self.bal_window.get_wallet_password("Sign your will",parent=self) password = self.bal_window.get_wallet_password("Sign your will",parent=self.bal_window.window)
if password is False: if password is False:
self.msg_set_signing('Aborted') self.msg_set_signing('Aborted')
else: else:
@ -2009,7 +1739,6 @@ class BalBuildWillDialog(BalDialog):
self.close() self.close()
def closeEvent(self,event): def closeEvent(self,event):
self.bal_window.update_all()
self._stopping=True self._stopping=True
self.thread.stop() self.thread.stop()
@ -2139,9 +1868,9 @@ class HeirList(MyTreeView,MessageBoxMixin):
ROLE_HEIR_KEY = Qt.ItemDataRole.UserRole + 1001 ROLE_HEIR_KEY = Qt.ItemDataRole.UserRole + 1001
key_role = ROLE_HEIR_KEY key_role = ROLE_HEIR_KEY
def __init__(self, bal_window: 'BalWindow',parent): def __init__(self, bal_window: 'BalWindow'):
super().__init__( super().__init__(
parent=parent, parent=bal_window.window,
main_window=bal_window.window, main_window=bal_window.window,
stretch_column=self.Columns.NAME, stretch_column=self.Columns.NAME,
editable_columns=[self.Columns.NAME,self.Columns.ADDRESS,self.Columns.AMOUNT], editable_columns=[self.Columns.NAME,self.Columns.ADDRESS,self.Columns.AMOUNT],
@ -2210,12 +1939,6 @@ class HeirList(MyTreeView,MessageBoxMixin):
menu.addAction(_("Delete"), lambda: self.bal_window.delete_heirs(selected_keys)) menu.addAction(_("Delete"), lambda: self.bal_window.delete_heirs(selected_keys))
menu.exec(self.viewport().mapToGlobal(position)) menu.exec(self.viewport().mapToGlobal(position))
#def get_selected_keys(self):
# selected_keys = []
# for s_idx in self.selected_in_column(self.Columns.NAME):
# sel_key = self.model().itemFromIndex(s_idx).data(0)
# selected_keys.append(sel_key)
# return selected_keys
def update(self): def update(self):
if self.maybe_defer_update(): if self.maybe_defer_update():
return return
@ -2247,7 +1970,6 @@ class HeirList(MyTreeView,MessageBoxMixin):
# FIXME refresh loses sort order; so set "default" here: # FIXME refresh loses sort order; so set "default" here:
self.filter() self.filter()
run_hook('update_heirs_tab', self) run_hook('update_heirs_tab', self)
self.update_will_settings()
def refresh_row(self, key, row): def refresh_row(self, key, row):
# nothing to update here # nothing to update here
@ -2262,12 +1984,12 @@ class HeirList(MyTreeView,MessageBoxMixin):
menu.addAction(_("Import"), self.bal_window.import_heirs) menu.addAction(_("Import"), self.bal_window.import_heirs)
menu.addAction(_("Export"), lambda: self.bal_window.export_heirs()) menu.addAction(_("Export"), lambda: self.bal_window.export_heirs())
self.heir_locktime = HeirsLockTimeEdit(self,0) self.heir_locktime = HeirsLockTimeEdit(self.window(),0)
def on_heir_locktime(): def on_heir_locktime():
if not self.heir_locktime.get_locktime(): if not self.heir_locktime.get_locktime():
self.heir_locktime.set_locktime('1y') self.heir_locktime.set_locktime('1y')
self.bal_window.will_settings['locktime'] = self.heir_locktime.get_locktime() if self.heir_locktime.get_locktime() else "1y" self.bal_window.will_settings['locktime'] = self.heir_locktime.get_locktime() if self.heir_locktime.get_locktime() else "1y"
self.bal_window.bal_plugin.WILL_SETTINGS.set(self.bal_window.will_settings) self.bal_window.bal_plugin.config.set_key('will_settings',self.bal_window.will_settings,save = True)
self.heir_locktime.valueEdited.connect(on_heir_locktime) self.heir_locktime.valueEdited.connect(on_heir_locktime)
self.heir_threshold = HeirsLockTimeEdit(self,0) self.heir_threshold = HeirsLockTimeEdit(self,0)
@ -2276,7 +1998,7 @@ class HeirList(MyTreeView,MessageBoxMixin):
self.heir_threshold.set_locktime('180d') self.heir_threshold.set_locktime('180d')
self.bal_window.will_settings['threshold'] = self.heir_threshold.get_locktime() self.bal_window.will_settings['threshold'] = self.heir_threshold.get_locktime()
self.bal_window.bal_plugin.WILL_SETTINGS.set(self.bal_window.will_settings) self.bal_window.bal_plugin.config.set_key('will_settings',self.bal_window.will_settings,save = True)
self.heir_threshold.valueEdited.connect(on_heir_threshold) self.heir_threshold.valueEdited.connect(on_heir_threshold)
self.heir_tx_fees = QSpinBox() self.heir_tx_fees = QSpinBox()
@ -2286,7 +2008,7 @@ class HeirList(MyTreeView,MessageBoxMixin):
if not self.heir_tx_fees.value(): if not self.heir_tx_fees.value():
self.heir_tx_fees.set_value(1) self.heir_tx_fees.set_value(1)
self.bal_window.will_settings['tx_fees'] = self.heir_tx_fees.value() self.bal_window.will_settings['tx_fees'] = self.heir_tx_fees.value()
self.bal_window.bal_plugin.WILL_SETTINGS.set(self.bal_window.will_settings) self.bal_window.bal_plugin.config.set_key('will_settings',self.bal_window.will_settings,save = True)
self.heir_tx_fees.valueChanged.connect(on_heir_tx_fees) self.heir_tx_fees.valueChanged.connect(on_heir_tx_fees)
@ -2325,18 +2047,16 @@ class HeirList(MyTreeView,MessageBoxMixin):
return toolbar return toolbar
def update_will_settings(self): def update_will_settings(self):
try: self.heir_threshold.set_locktime(self.bal_window.will_settings['threshold'])
self.heir_locktime.set_locktime(self.bal_window.will_settings['locktime']) self.heir_locktime.set_locktime(self.bal_window.will_settings['locktime'])
self.heir_tx_fees.setValue(int(self.bal_window.will_settings['tx_fees'])) self.heir_tx_fees.setValue(int(self.bal_window.will_settings['tx_fees']))
self.heir_threshold.set_locktime(self.bal_window.will_settings['threshold'])
except Exception as e:
print("Exception update_will_settings",e)
def build_transactions(self): def build_transactions(self):
will = self.bal_window.prepare_will() will = self.bal_window.prepare_will()
class PreviewList(MyTreeView): class PreviewList(MyTreeView):
class Columns(MyTreeView.BaseColumnsEnum): class Columns(MyTreeView.BaseColumnsEnum):
LOCKTIME = enum.auto() LOCKTIME = enum.auto()
@ -2354,14 +2074,12 @@ class PreviewList(MyTreeView):
ROLE_HEIR_KEY = Qt.ItemDataRole.UserRole + 2000 ROLE_HEIR_KEY = Qt.ItemDataRole.UserRole + 2000
key_role = ROLE_HEIR_KEY key_role = ROLE_HEIR_KEY
def __init__(self, bal_window: 'BalWindow',parent,will): def __init__(self, parent: 'BalWindow',will):
super().__init__( super().__init__(
parent=parent, parent=parent.window,
stretch_column=self.Columns.TXID, stretch_column=self.Columns.TXID,
) )
self.parent=parent self.decimal_point=parent.bal_plugin.config.get_decimal_point
self.bal_window=bal_window
self.decimal_point=bal_window.bal_plugin.config.get_decimal_point
self.setModel(QStandardItemModel(self)) self.setModel(QStandardItemModel(self))
self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
@ -2369,13 +2087,14 @@ class PreviewList(MyTreeView):
if not will is None: if not will is None:
self.will = will self.will = will
else: else:
self.will = bal_window.willitems self.will = parent.willitems
self.wallet=bal_window.window.wallet self.bal_window = parent
self.wallet=parent.window.wallet
self.setModel(QStandardItemModel(self)) self.setModel(QStandardItemModel(self))
self.setSortingEnabled(True) self.setSortingEnabled(True)
self.std_model = self.model() self.std_model = self.model()
self.config = bal_window.bal_plugin.config self.config = parent.bal_plugin.config
self.bal_plugin=self.bal_window.bal_plugin self.bal_plugin=self.bal_window.bal_plugin
self.update() self.update()
@ -2401,7 +2120,6 @@ class PreviewList(MyTreeView):
menu.exec(self.viewport().mapToGlobal(position)) menu.exec(self.viewport().mapToGlobal(position))
def delete(self,selected_keys): def delete(self,selected_keys):
for key in selected_keys: for key in selected_keys:
del self.will[key] del self.will[key]
@ -2504,10 +2222,6 @@ class PreviewList(MyTreeView):
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.clicked.connect(self.bal_window.init_wizard)
prepareButton = QPushButton(_("Prepare")) prepareButton = QPushButton(_("Prepare"))
prepareButton.clicked.connect(self.build_transactions) prepareButton.clicked.connect(self.build_transactions)
signButton = QPushButton(_("Sign")) signButton = QPushButton(_("Sign"))
@ -2518,7 +2232,6 @@ class PreviewList(MyTreeView):
displayButton.clicked.connect(self.bal_window.preview_modal_dialog) displayButton.clicked.connect(self.bal_window.preview_modal_dialog)
hlayout = QHBoxLayout() hlayout = QHBoxLayout()
widget = QWidget() widget = QWidget()
hlayout.addWidget(wizard)
hlayout.addWidget(prepareButton) hlayout.addWidget(prepareButton)
hlayout.addWidget(signButton) hlayout.addWidget(signButton)
hlayout.addWidget(pushButton) hlayout.addWidget(pushButton)
@ -2645,8 +2358,9 @@ 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):
self.will = bal_window.willitems self.will = bal_window.willitems
@ -2870,10 +2584,8 @@ class WillExecutorList(MyTreeView):
for k in selected_keys: for k in selected_keys:
wout[k]=self.parent.willexecutors_list[k] wout[k]=self.parent.willexecutors_list[k]
self.parent.update_willexecutors(wout) self.parent.update_willexecutors(wout)
self.update() self.update()
def get_edit_key_from_coordinate(self, row, col): def get_edit_key_from_coordinate(self, row, col):
a= self.get_role_data_from_coordinate(row, col, role=self.ROLE_HEIR_KEY+col) a= self.get_role_data_from_coordinate(row, col, role=self.ROLE_HEIR_KEY+col)
return a return a
@ -2913,7 +2625,6 @@ class WillExecutorList(MyTreeView):
pass pass
def update(self): def update(self):
if self.parent.willexecutors_list is None: if self.parent.willexecutors_list is None:
return return
try: try:
@ -2965,41 +2676,27 @@ class WillExecutorList(MyTreeView):
idx = self.model().index(row_count, self.Columns.NAME) idx = self.model().index(row_count, self.Columns.NAME)
set_current = QPersistentModelIndex(idx) set_current = QPersistentModelIndex(idx)
self.set_current_idx(set_current) self.set_current_idx(set_current)
self.parent.save_willexecutors() self.parent.save_willexecutors()
except Exception as e: except Exception as e:
_logger.error(e) _logger.error(e)
class WillExecutorWidget(QWidget,MessageBoxMixin): class WillExecutorDialog(BalDialog,MessageBoxMixin):
def __init__(self,parent,bal_window,willexecutors=None): def __init__(self, bal_window):
self.bal_window=bal_window BalDialog.__init__(self,bal_window.window)
self.bal_plugin=bal_window.bal_plugin self.bal_plugin = bal_window.bal_plugin
self.parent=parent self.config = self.bal_plugin.config
MessageBoxMixin.__init__(self) self.window = bal_window.window
QWidget.__init__(self,parent) self.bal_window = bal_window
if willexecutors:
self.willexecutors_list=willexecutors
else:
self.willexecutors_list = Willexecutors.get_willexecutors(self.bal_plugin) self.willexecutors_list = Willexecutors.get_willexecutors(self.bal_plugin)
self.setWindowTitle(_('Will-Executor Service List'))
self.setMinimumSize(1000, 200)
self.size_label = QLabel() self.size_label = QLabel()
self.willexecutor_list = WillExecutorList(self) self.willexecutor_list = WillExecutorList(self)
vbox = QVBoxLayout(self) vbox = QVBoxLayout(self)
vbox.addWidget(self.size_label) vbox.addWidget(self.size_label)
widget = QWidget()
hbox=QHBoxLayout(widget)
hbox.addWidget(QLabel(_("Add transactions without willexecutor")))
heir_no_willexecutor = bal_checkbox(self.bal_plugin.NO_WILLEXECUTOR)
hbox.addWidget(heir_no_willexecutor)
spacer_widget = QWidget()
spacer_widget.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
hbox.addWidget(spacer_widget)
vbox.addWidget(widget)
vbox.addWidget(self.willexecutor_list) vbox.addWidget(self.willexecutor_list)
buttonbox = QHBoxLayout() buttonbox = QHBoxLayout()
@ -3023,8 +2720,14 @@ class WillExecutorWidget(QWidget,MessageBoxMixin):
b.clicked.connect(self.add) b.clicked.connect(self.add)
buttonbox.addWidget(b) buttonbox.addWidget(b)
b = QPushButton(_('Close'))
b.clicked.connect(self.close)
buttonbox.addWidget(b)
vbox.addLayout(buttonbox) vbox.addLayout(buttonbox)
self.willexecutor_list.update() self.willexecutor_list.update()
def add(self): def add(self):
self.willexecutors_list["http://localhost:8080"]={"info":"New Will Executor","base_fee":0,"status":"-1"} self.willexecutors_list["http://localhost:8080"]={"info":"New Will Executor","base_fee":0,"status":"-1"}
self.willexecutor_list.update() self.willexecutor_list.update()
@ -3032,13 +2735,13 @@ class WillExecutorWidget(QWidget,MessageBoxMixin):
self.willexecutors_list.update(Willexecutors.download_list(self.bal_plugin) ) self.willexecutors_list.update(Willexecutors.download_list(self.bal_plugin) )
self.willexecutor_list.update() self.willexecutor_list.update()
def export_file(self, path): def export_file(self, path):
Util.export_meta_gui(self.bal_window.window, _('willexecutors.json'), self.export_json_file) Util.export_meta_gui(self, _('willexecutors.json'), self.export_json_file)
def export_json_file(self,path): def export_json_file(self,path):
write_json_file(path, self.willexecutors_list) write_json_file(path, self.willexecutors_list)
def import_file(self): def import_file(self):
import_meta_gui(self.bal_window.window, _('willexecutors.json'), self.import_json_file, self.willexecutors_list.update) import_meta_gui(self, _('willexecutors.json'), self.import_json_file, self.willexecutors_list.update)
def update_willexecutors(self,wes=None): def update_willexecutors(self,wes=None):
if not wes: if not wes:
@ -3059,26 +2762,6 @@ class WillExecutorWidget(QWidget,MessageBoxMixin):
def _validate(self,data): def _validate(self,data):
return data return data
def save_willexecutors(self):
Willexecutors.save(self.bal_window.bal_plugin, self.willexecutors_list)
class WillExecutorDialog(BalDialog,MessageBoxMixin):
def __init__(self, bal_window):
BalDialog.__init__(self,bal_window.window)
self.bal_plugin = bal_window.bal_plugin
self.config = self.bal_plugin.config
self.window = bal_window.window
self.bal_window = bal_window
self.willexecutors_list = Willexecutors.get_willexecutors(self.bal_plugin)
self.setWindowTitle(_('Will-Executor Service List'))
self.setMinimumSize(1000, 200)
vbox = QVBoxLayout(self)
vbox.addWidget(WillExecutorWidget(self,self.bal_window,self.willexecutors_list))
def is_hidden(self): def is_hidden(self):
return self.isMinimized() or self.isHidden() return self.isMinimized() or self.isHidden()
@ -3095,4 +2778,6 @@ class WillExecutorDialog(BalDialog,MessageBoxMixin):
def closeEvent(self, event): def closeEvent(self, event):
event.accept() event.accept()
def save_willexecutors(self):
self.bal_plugin.config.set_key(self.bal_plugin.WILLEXECUTORS,self.willexecutors_list,save=True)

View File

@ -319,7 +319,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)
@ -330,7 +329,7 @@ class Will:
return tx return tx
else: else:
_logger.debug(f"balance({balance}) - fee({fee}) <=0") _logger.debug("balance - fee <=0")
pass pass
else: else:
_logger.debug("len utxo_to_spend <=0") _logger.debug("len utxo_to_spend <=0")

View File

@ -8,49 +8,39 @@ from electrum import constants
from electrum.logging import get_logger from electrum.logging import get_logger
from electrum.gui.qt.util import WaitingDialog from electrum.gui.qt.util import WaitingDialog
from electrum.i18n import _ from electrum.i18n import _
from .bal import BalPlugin
from .util import Util from .util import Util
DEFAULT_TIMEOUT = 5 DEFAULT_TIMEOUT = 5
_logger = get_logger(__name__) _logger = get_logger(__name__)
class Willexecutors: class Willexecutors:
def save(bal_plugin, willexecutors):
aw=bal_plugin.WILLEXECUTORS.get()
aw[constants.net.NET_NAME]=willexecutors
print("save",aw)
bal_plugin.WILLEXECUTORS.set(aw)
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.config_get(bal_plugin.WILLEXECUTORS)
willexecutors=willexecutors.get(constants.net.NET_NAME,{})
for w in willexecutors: for w in willexecutors:
Willexecutors.initialize_willexecutor(willexecutors[w],w) Willexecutors.initialize_willexecutor(willexecutors[w],w)
bal = bal_plugin.WILLEXECUTORS.default.get(constants.net.NET_NAME,{}) bal=bal_plugin.DEFAULT_SETTINGS[bal_plugin.WILLEXECUTORS]
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:
_logger.debug(f"force add {bal_url} willexecutor") _logger.debug("replace bal")
willexecutors[bal_url] = bal_executor willexecutors[bal_url]=bal_executor
if update: if update:
found = False found = False
for url,we in willexecutors.items(): for url,we in willexecutors.items():
if Willexecutors.is_selected(we): if Willexecutors.is_selected(we):
found = True found = True
if found or force: if found or force:
if bal_plugin.PING_WILLEXECUTORS.get() or force: if bal_plugin.config_get(bal_plugin.PING_WILLEXECUTORS) or force:
ping_willexecutors = True ping_willexecutors = True
if bal_plugin.ASK_PING_WILLEXECUTORS.get() and not force: if bal_plugin.config_get(bal_plugin.ASK_PING_WILLEXECUTORS) and not force:
if bal_window:
ping_willexecutors = bal_window.window.question(_("Contact willexecutors servers to update payment informations?")) ping_willexecutors = bal_window.window.question(_("Contact willexecutors servers to update payment informations?"))
if ping_willexecutors: if ping_willexecutors:
if task: if task:
bal_window.ping_willexecutors(willexecutors) bal_window.ping_willexecutors(willexecutors)
else: else:
bal_window.ping_willexecutors_task(willexecutors) bal_window.ping_willexecutors_task(willexecutors)
w_sorted = dict(sorted(willexecutors.items(), key=lambda w:w[1].get('sort',0),reverse=True)) return willexecutors
return w_sorted
def is_selected(willexecutor,value=None): def is_selected(willexecutor,value=None):
if not willexecutor: if not willexecutor:
return False return False
@ -100,7 +90,7 @@ class Willexecutors:
raise ErrorConnectingServer('You are offline.') raise ErrorConnectingServer('You are offline.')
_logger.debug(f'<-- {method} {url} {data}') _logger.debug(f'<-- {method} {url} {data}')
headers = {} headers = {}
headers['user-agent'] = f"BalPlugin v:{BalPlugin.version()}" headers['user-agent'] = 'BalPlugin'
headers['Content-Type']='text/plain' headers['Content-Type']='text/plain'
try: try:
@ -192,7 +182,6 @@ class Willexecutors:
if not status is None: if not status is None:
willexecutor['status'] = status willexecutor['status'] = status
willexecutor['selected'] = Willexecutors.is_selected(willexecutor,selected) willexecutor['selected'] = Willexecutors.is_selected(willexecutor,selected)
def download_list(bal_plugin): def download_list(bal_plugin):
try: try:
l = Willexecutors.send_request('get',"https://welist.bitcoin-after.life/data/bitcoin?page=0&limit=100") l = Willexecutors.send_request('get',"https://welist.bitcoin-after.life/data/bitcoin?page=0&limit=100")
@ -200,10 +189,8 @@ class Willexecutors:
for w in l: for w in l:
willexecutor=l[w] willexecutor=l[w]
Willexecutors.initialize_willexecutor(willexecutor,w,'New',False) Willexecutors.initialize_willexecutor(willexecutor,w,'New',False)
#bal_plugin.WILLEXECUTORS.set(l) bal_plugin.config.set_key(bal_plugin.WILLEXECUTORS,l,save=True)
#bal_plugin.config.set_key(bal_plugin.WILLEXECUTORS,l,save=True)
return l return l
except Exception as e: except Exception as e:
_logger.error(f"error downloading willexecutors list:{e}") _logger.error(f"error downloading willexecutors list:{e}")
return {} return {}
@ -214,7 +201,7 @@ class Willexecutors:
for w in willexecutors: for w in willexecutors:
willexecutor=willexecutors[w] willexecutor=willexecutors[w]
Willexecutors.initialize_willexecutor(willexecutor,w,'New',False) Willexecutors.initialize_willexecutor(willexecutor,w,'New',False)
#bal_plugin.WILLEXECUTORS.set(willexecutors) bal_plugin.config.set_key(bal_plugin.WILLEXECUTORS,willexecutors,save=True)
return h return h
except Exception as e: except Exception as e:
_logger.error(f"error opening willexecutors json: {e}") _logger.error(f"error opening willexecutors json: {e}")
@ -229,22 +216,3 @@ class Willexecutors:
except Exception as e: except Exception as e:
_logger.error(f"error contacting {url} for checking txs {e}") _logger.error(f"error contacting {url} for checking txs {e}")
raise e raise e
class WillExecutor:
def __init__(self,url,base_fee,chain,info,version):
self.url = url
self.base_fee = base_fee
self.chain = chain
self.info = info
self.version = version
def from_dict(d):
we = WillExecutor(
d['url'],
d['base_fee'],
d['chain'],
d['info'],
d['version']
)