diff --git a/bal.py b/bal.py index 62a5da2..1b4c75c 100644 --- a/bal.py +++ b/bal.py @@ -9,112 +9,109 @@ import os json_db.register_dict('heirs', tuple, None) json_db.register_dict('will', lambda x: get_will(x), None) json_db.register_dict('will_settings', lambda x:x, None) + from electrum.logging import get_logger + def get_will(x): try: - - x['tx']=tx_from_any(x['tx']) except Exception as e: raise e - 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): - LOCKTIME_TIME = "bal_locktime_time" - LOCKTIME_BLOCKS = "bal_locktime_blocks" - LOCKTIMEDELTA_TIME = "bal_locktimedelta_time" - LOCKTIMEDELTA_BLOCKS = "bal_locktimedelta_blocks" - TX_FEES = "bal_tx_fees" - BROADCAST = "bal_broadcast" - ASK_BROADCAST = "bal_ask_broadcast" - INVALIDATE = "bal_invalidate" - ASK_INVALIDATE = "bal_ask_invalidate" - PREVIEW = "bal_preview" - SAVE_TXS = "bal_save_txs" - 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" - - - - DEFAULT_SETTINGS={ - LOCKTIME_TIME: 90, - LOCKTIME_BLOCKS: 144*90, - LOCKTIMEDELTA_TIME: 7, - LOCKTIMEDELTA_BLOCKS:144*7, - TX_FEES: 100, - BROADCAST: True, - ASK_BROADCAST: True, - INVALIDATE: True, - ASK_INVALIDATE: True, - PREVIEW: True, - SAVE_TXS: True, - PING_WILLEXECUTORS: False, - ASK_PING_WILLEXECUTORS: False, - NO_WILLEXECUTOR: False, - HIDE_REPLACED:True, - HIDE_INVALIDATED:True, - ALLOW_REPUSH: False, - WILLEXECUTORS: { - 'https://bitcoin-after.life:9137': { - "base_fee": 100000, - "status": "New", - "info":"Bitcoin After Life Will Executor", - "address":"bcrt1qa5cntu4hgadw8zd3n6sq2nzjy34sxdtd9u0gp7", - "selected":True - } - }, - } - LATEST_VERSION = '1' KNOWN_VERSIONS = ('0', '1') assert LATEST_VERSION in KNOWN_VERSIONS - + def version(): + try: + f="" + with open("VERSION","r") as f: + f = str(f.readline()) + return f + except: + return "unknown" SIZE = (159, 97) def __init__(self, parent, config, name): - self.logger= get_logger(__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._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] + + self.ASK_BROADCAST = BalConfig(config, "bal_ask_broadcast",True) + self.BROADCAST = BalConfig(config, "bal_broadcast",True) + self.LOCKTIME_TIME = BalConfig(config, "bal_locktime_time",90) + self.LOCKTIME_BLOCKS = BalConfig(config, "bal_locktime_blocks",144*90) + self.LOCKTIMEDELTA_TIME = BalConfig(config, "bal_locktimedelta_time",7) + self.LOCKTIMEDELTA_BLOCKS = BalConfig(config, "bal_locktimedelta_blocks",144*7) + self.TX_FEES = BalConfig(config, "bal_tx_fees",100) + self.INVALIDATE = BalConfig(config, "bal_invalidate",True) + self.ASK_INVALIDATE = BalConfig(config, "bal_ask_invalidate",True) + self.PREVIEW = BalConfig(config, "bal_preview",True) + self.SAVE_TXS = BalConfig(config, "bal_save_txs",True) + self.WILLEXECUTORS = BalConfig(config, "bal_willexecutors",True) + self.PING_WILLEXECUTORS = BalConfig(config, "bal_ping_willexecutors",True) + self.ASK_PING_WILLEXECUTORS = BalConfig(config, "bal_ask_ping_willexecutors",True) + self.NO_WILLEXECUTOR = BalConfig(config, "bal_no_willexecutor",True) + self.HIDE_REPLACED = BalConfig(config, "bal_hide_replaced",True) + self.HIDE_INVALIDATED = BalConfig(config, "bal_hide_invalidated",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", { + 'https://we.bitcoin-after.life': { + "base_fee": 100000, + "status": "New", + "info":"Bitcoin After Life Will Executor", + "address":"bcrt1qa5cntu4hgadw8zd3n6sq2nzjy34sxdtd9u0gp7", + "selected":True + } + }) + self.WILL_SETTINGS = BalConfig(config, "bal_will_settings", { + 'tx_fees':100, + 'threshold':'180d', + 'locktime':'1y', + }) + + + self._hide_invalidated= self.HIDE_INVALIDATED.get() + self._hide_replaced= self.HIDE_REPLACED.get() + def resource_path(self,*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): self._hide_invalidated = not self._hide_invalidated - self.config.set_key(BalPlugin.HIDE_INVALIDATED,self.hide_invalidated,save=True) + self.HIDE_INVALIDATED.set(self._hide_invalidated) def hide_replaced(self): self._hide_replaced = not self._hide_replaced - self.config.set_key(BalPlugin.HIDE_REPLACED,self.hide_invalidated,save=True) + self.HIDE_REPLACED.set(self._hide_replaced) - def default_will_settings(self): - return { - 'tx_fees':100, - 'threshold':'180d', - 'locktime':'1y', - } def validate_will_settings(self,will_settings): if int(will_settings.get('tx_fees',1))<1: will_settings['tx_fees']=1 diff --git a/heirs.py b/heirs.py index 3a86be4..1b441c0 100644 --- a/heirs.py +++ b/heirs.py @@ -14,7 +14,6 @@ from electrum.transaction import PartialTxInput, PartialTxOutput,TxOutpoint,Part import datetime import urllib.request import urllib.parse -from .bal import BalPlugin from .util import Util from .willexecutors import Willexecutors if TYPE_CHECKING: @@ -387,7 +386,7 @@ class Heirs(dict, Logger): utxos = wallet.get_utxos() willexecutors = Willexecutors.get_willexecutors(bal_plugin) or {} self.decimal_point=bal_plugin.config.get_decimal_point() - no_willexecutors = bal_plugin.config_get(BalPlugin.NO_WILLEXECUTOR) + no_willexecutors = bal_plugin.NO_WILLEXECUTOR.get() for utxo in utxos: if utxo.value_sats()> 0*tx_fees: balance += utxo.value_sats() diff --git a/manifest.json b/manifest.json index 4ec37d9..f9cbf01 100644 --- a/manifest.json +++ b/manifest.json @@ -1,8 +1,9 @@ { - "name": "BAL", - "fullname": "Bitcoin After Life", - "description": "Provides free and decentralized inheritance support
Version: 0.2.0b", - "author":"Svatantrya", - "available_for": ["qt"], - "icon":"icons/bal32x32.png" -} + "name": "BAL", + "fullname": "Bitcoin After Life", + "description": "Provides free and decentralized inheritance support
Version: 0.2.1b", + "author":"Svatantrya", + "available_for": ["qt"], + "icon":"icons/bal32x32.png" + } + diff --git a/qt.py b/qt.py index 16812a5..6b6ca4f 100644 --- a/qt.py +++ b/qt.py @@ -446,14 +446,14 @@ class Plugin(BalPlugin,Logger): lbl_logo = QLabel() lbl_logo.setPixmap(qicon) - heir_ping_willexecutors = bal_checkbox(self, BalPlugin.PING_WILLEXECUTORS) - heir_ask_ping_willexecutors = bal_checkbox(self, BalPlugin.ASK_PING_WILLEXECUTORS) - heir_no_willexecutor = bal_checkbox(self, BalPlugin.NO_WILLEXECUTOR) + heir_ping_willexecutors = bal_checkbox(self.PING_WILLEXECUTORS) + heir_ask_ping_willexecutors = bal_checkbox(self.ASK_PING_WILLEXECUTORS) + heir_no_willexecutor = bal_checkbox(self.NO_WILLEXECUTOR) - heir_hide_replaced = bal_checkbox(self,BalPlugin.HIDE_REPLACED,self) + heir_hide_replaced = bal_checkbox(self.HIDE_REPLACED,self) - heir_hide_invalidated = bal_checkbox(self,BalPlugin.HIDE_INVALIDATED,self) + heir_hide_invalidated = bal_checkbox(self.HIDE_INVALIDATED,self) heir_repush = QPushButton("Rebroadcast transactions") heir_repush.clicked.connect(partial(self.broadcast_transactions,True)) grid=QGridLayout(d) @@ -641,13 +641,13 @@ class BalWindow(Logger): except Exception as e: self.show_error(str(e)) - def export_inheritance_handler(self,path): - txs = self.build_inheritance_transaction(ignore_duplicate=True, keep_original=False) - with open(path,"w") as f: - for tx in txs: - tx['status']+="."+BalPlugin.STATUS_EXPORTED - f.write(str(tx['tx'])) - f.write('\n') + #def export_inheritance_handler(self,path): + # txs = self.build_inheritance_transaction(ignore_duplicate=True, keep_original=False) + # with open(path,"w") as f: + # for tx in txs: + # tx['status']+="."+BalPlugin.STATUS_EXPORTED + # f.write(str(tx['tx'])) + # f.write('\n') def set_heir(self,heir): heir=list(heir) @@ -750,10 +750,10 @@ class BalWindow(Logger): try: self.date_to_check = Util.parse_locktime_string(self.will_settings['threshold']) found = False - self.locktime_blocks=self.bal_plugin.config_get(BalPlugin.LOCKTIME_BLOCKS) + self.locktime_blocks=self.bal_plugin.LOCKTIME_BLOCKS.get() self.current_block = Util.get_current_height(self.wallet.network) self.block_to_check = self.current_block + self.locktime_blocks - self.no_willexecutor = self.bal_plugin.config_get(BalPlugin.NO_WILLEXECUTOR) + 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.init_heirs_to_locktime() @@ -1511,12 +1511,12 @@ class BalBlockingWaitingDialog(BalDialog): self.accept() class bal_checkbox(QCheckBox): - def __init__(self, plugin,variable,window=None): + def __init__(self, variable,window=None): QCheckBox.__init__(self) - self.setChecked(plugin.config_get(variable)) + self.setChecked(variable.get()) def on_check(v): - plugin.config.set_key(variable, v == 2) - plugin.config_get(variable) + variable.set(v == 2) + variable.get() self.stateChanged.connect(on_check) @@ -2584,8 +2584,10 @@ class WillExecutorList(MyTreeView): for k in selected_keys: wout[k]=self.parent.willexecutors_list[k] self.parent.update_willexecutors(wout) + self.update() + def get_edit_key_from_coordinate(self, row, col): a= self.get_role_data_from_coordinate(row, col, role=self.ROLE_HEIR_KEY+col) return a @@ -2625,6 +2627,7 @@ class WillExecutorList(MyTreeView): pass def update(self): + if self.parent.willexecutors_list is None: return try: @@ -2676,7 +2679,9 @@ class WillExecutorList(MyTreeView): idx = self.model().index(row_count, self.Columns.NAME) set_current = QPersistentModelIndex(idx) self.set_current_idx(set_current) + self.parent.save_willexecutors() + except Exception as e: _logger.error(e) @@ -2779,5 +2784,5 @@ class WillExecutorDialog(BalDialog,MessageBoxMixin): event.accept() def save_willexecutors(self): - self.bal_plugin.config.set_key(self.bal_plugin.WILLEXECUTORS,self.willexecutors_list,save=True) + self.bal_plugin.WILLEXECUTORS.set(self.willexecutors_list) diff --git a/will.py b/will.py index 1cfdea8..430c2c4 100644 --- a/will.py +++ b/will.py @@ -319,6 +319,7 @@ class Will: locktime = Util.get_current_height(wallet.network) tx = PartialTransaction.from_io(utxo_to_spend, [out], locktime=locktime, version=2) tx.set_rbf(True) + print("fees_per_byte:",fees_per_byte) fee=tx.estimated_size()*fees_per_byte if balance -fee >0: out = PartialTxOutput.from_address_and_value(change_addresses[0],balance - fee) @@ -329,7 +330,7 @@ class Will: return tx else: - _logger.debug("balance - fee <=0") + _logger.debug(f"balance({balance}) - fee({fee}) <=0") pass else: _logger.debug("len utxo_to_spend <=0") diff --git a/willexecutors.py b/willexecutors.py index 5a89aa9..76d8f5f 100644 --- a/willexecutors.py +++ b/willexecutors.py @@ -8,31 +8,31 @@ from electrum import constants from electrum.logging import get_logger from electrum.gui.qt.util import WaitingDialog from electrum.i18n import _ - +from .bal import BalPlugin from .util import Util DEFAULT_TIMEOUT = 5 _logger = get_logger(__name__) class Willexecutors: def get_willexecutors(bal_plugin, update = False,bal_window=False,force=False,task=True): - willexecutors = bal_plugin.config_get(bal_plugin.WILLEXECUTORS) + willexecutors = bal_plugin.WILLEXECUTORS.get() for w in willexecutors: Willexecutors.initialize_willexecutor(willexecutors[w],w) - bal=bal_plugin.DEFAULT_SETTINGS[bal_plugin.WILLEXECUTORS] + bal = bal_plugin.WILLEXECUTORS.default for bal_url,bal_executor in bal.items(): if not bal_url in willexecutors: - _logger.debug("replace bal") - willexecutors[bal_url]=bal_executor + _logger.debug(f"force add {bal_url} willexecutor") + willexecutors[bal_url] = bal_executor if update: found = False for url,we in willexecutors.items(): if Willexecutors.is_selected(we): found = True if found or force: - if bal_plugin.config_get(bal_plugin.PING_WILLEXECUTORS) or force: + if bal_plugin.PING_WILLEXECUTORS.get() or force: ping_willexecutors = True - if bal_plugin.config_get(bal_plugin.ASK_PING_WILLEXECUTORS) and not force: + if bal_plugin.ASK_PING_WILLEXECUTORS.get() and not force: ping_willexecutors = bal_window.window.question(_("Contact willexecutors servers to update payment informations?")) if ping_willexecutors: if task: @@ -40,6 +40,9 @@ class Willexecutors: else: bal_window.ping_willexecutors_task(willexecutors) return willexecutors + def get_willexecutors_as_sorted_list(bal_plugin,update=False,bal_window=False,force=False,task=True): + willexecutors=Willexecutors.get_willexecutors(bal_plugin,update,bal_window,force,task) + return sorted(willexecutors,key=lambda w:w[1].get('sort',0)) def is_selected(willexecutor,value=None): if not willexecutor: @@ -90,7 +93,7 @@ class Willexecutors: raise ErrorConnectingServer('You are offline.') _logger.debug(f'<-- {method} {url} {data}') headers = {} - headers['user-agent'] = 'BalPlugin' + headers['user-agent'] = f"BalPlugin v:{BalPlugin.version()}" headers['Content-Type']='text/plain' try: @@ -216,3 +219,22 @@ class Willexecutors: except Exception as e: _logger.error(f"error contacting {url} for checking txs {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'] + ) + +