From ef0ab56de47ab7439ab9512a434db224fca836b6 Mon Sep 17 00:00:00 2001 From: svatantrya Date: Thu, 5 Mar 2026 10:46:38 -0400 Subject: [PATCH] fixed refresh and some minor bug about dust amounts and empty wallet --- heirs.py | 126 +++++++++++++++++++++++++++++++++---------------------- qt.py | 61 ++++++++++++++++++--------- util.py | 8 ++-- will.py | 8 ++-- 4 files changed, 127 insertions(+), 76 deletions(-) diff --git a/heirs.py b/heirs.py index 6e93e57..4a83f73 100644 --- a/heirs.py +++ b/heirs.py @@ -96,9 +96,9 @@ def prepare_transactions(locktimes, available_utxos, fees, wallet): locktime = locktime[0] heirs = locktimes[locktime] - vero = True - while vero: - vero = False + true = True + while true: + true = False fee = fees.get(locktime, 0) out_amount = fee description = "" @@ -118,12 +118,12 @@ def prepare_transactions(locktimes, available_utxos, fees, wallet): out_amount += real_amount description += f"{name}\n" except BitcoinException as e: - _logger.info("exception decoding output{} - {}".format(type(e), e)) + _logger.info("exception decoding output {} - {}".format(type(e), e)) heir[HEIR_REAL_AMOUNT] = e except Exception as e: heir[HEIR_REAL_AMOUNT] = e - _logger.info(f"error preparing transactions {e}") + _logger.error(f"error preparing transactions: {e}") pass paid_heirs[name] = heir @@ -138,15 +138,15 @@ def prepare_transactions(locktimes, available_utxos, fees, wallet): break except IndexError as e: - _logger.info( + _logger.error( f"error preparing transactions index error {e} {in_amount}, {out_amount}" ) pass if int(in_amount) < int(out_amount): - _logger.info( + _logger.error( "error preparing transactions in_amount < out_amount ({} < {}) " ) - break + continue heirsvalue = out_amount change = get_change_output(wallet, in_amount, out_amount, fee) if change: @@ -319,7 +319,7 @@ class Heirs(dict, Logger): locktime = Util.parse_locktime_string(self[key][HEIR_LOCKTIME]) if locktime > from_locktime and not a or locktime <= from_locktime and a: locktimes[int(locktime)] = None - return locktimes.keys() + return list(locktimes.keys()) def check_locktime(self): return False @@ -333,6 +333,8 @@ class Heirs(dict, Logger): column = HEIR_AMOUNT if real: column = HEIR_REAL_AMOUNT + if "DUST" in str(v[column]): + column = HEIR_DUST_AMOUNT value = int( math.floor( total_balance @@ -366,27 +368,32 @@ class Heirs(dict, Logger): fixed_amount = 0.0 percent_heirs = {} percent_amount = 0.0 + fixed_amount_with_dust =0.0 for key in self.keys(): try: cmp = ( Util.parse_locktime_string(self[key][HEIR_LOCKTIME]) - from_locktime ) if cmp <= 0: + _logger.debug("cmp < 0 {} {} {} ".format(cmp, key, self[key][HEIR_LOCKTIME], from_locktime)) continue if Util.is_perc(self[key][HEIR_AMOUNT]): percent_amount += float(self[key][HEIR_AMOUNT][:-1]) percent_heirs[key] = list(self[key]) else: heir_amount = int(math.floor(float(self[key][HEIR_AMOUNT]))) + fixed_amount_with_dust += heir_amount + fixed_heirs[key] = list(self[key]) if heir_amount > dust_threshold: fixed_amount += heir_amount - fixed_heirs[key] = list(self[key]) fixed_heirs[key].insert(HEIR_REAL_AMOUNT, heir_amount) else: - pass + fixed_heirs[key] = list(self[key]) + fixed_heirs[key].insert(HEIR_REAL_AMOUNT, f"DUST: {heir_amount}") + fixed_heirs[key].insert(HEIR_DUST_AMOUNT, heir_amount) except Exception as e: _logger.error(e) - return fixed_heirs, fixed_amount, percent_heirs, percent_amount + return fixed_heirs, fixed_amount, percent_heirs, percent_amount, fixed_amount_with_dust def prepare_lists( self, balance, total_fees, wallet, willexecutor=False, from_locktime=0 @@ -419,9 +426,13 @@ class Heirs(dict, Logger): ), heir_list.update(willexecutors) newbalance -= willexecutors_amount - fixed_heirs, fixed_amount, percent_heirs, percent_amount = ( + if newbalance<0: + raise WillExecutorFeeException(willexecutor) + a=list(self.fixed_percent_lists_amount(from_locktime, wallet.dust_threshold())) + fixed_heirs, fixed_amount, percent_heirs, percent_amount,fixed_amount_with_dust = ( self.fixed_percent_lists_amount(from_locktime, wallet.dust_threshold()) ) + if fixed_amount > newbalance: fixed_amount = self.normalize_perc( fixed_heirs, newbalance, fixed_amount, wallet @@ -442,7 +453,7 @@ class Heirs(dict, Logger): if newbalance > 0: newbalance += fixed_amount fixed_amount = self.normalize_perc( - fixed_heirs, newbalance, fixed_amount, wallet, real=True + fixed_heirs, newbalance, fixed_amount_with_dust, wallet, real=True ) newbalance -= fixed_amount heir_list.update(fixed_heirs) @@ -509,7 +520,7 @@ class Heirs(dict, Logger): break fees = {} i = 0 - while True: + while i<10: txs = {} redo = False i += 1 @@ -517,47 +528,55 @@ class Heirs(dict, Logger): for fee in fees: total_fees += int(fees[fee]) newbalance = balance - locktimes, onlyfixed = self.prepare_lists( - balance, total_fees, wallet, willexecutor, from_locktime - ) try: - txs = prepare_transactions( - locktimes, available_utxos[:], fees, wallet + locktimes, onlyfixed = self.prepare_lists( + balance, total_fees, wallet, willexecutor, from_locktime ) - if not txs: - return {} - except Exception as e: - _logger.info(f"error preparing transactions{e}") + except WillExecutorFeeException as e: + i=10 + continue + if locktimes: try: - if "w!ll3x3c" in e.heirname: - Willexecutors.is_selected(willexecutors[w], False) - break - except: - raise e - total_fees = 0 - total_fees_real = 0 - total_in = 0 - for txid, tx in txs.items(): - tx.willexecutor = willexecutor - fee = tx.estimated_size() * tx_fees - txs[txid].tx_fees = tx_fees - total_fees += fee - total_fees_real += tx.get_fee() - total_in += tx.input_value() - rfee = tx.input_value() - tx.output_value() - if rfee < fee or rfee > fee + wallet.dust_threshold(): - redo = True - oldfees = fees.get(tx.my_locktime, 0) - fees[tx.my_locktime] = fee + txs = prepare_transactions( + locktimes, available_utxos[:], fees, wallet + ) + if not txs: + return {} + except Exception as e: + _logger.error(f"build transactions: error preparing transactions: {e}") + try: + if "w!ll3x3c" in e.heirname: + Willexecutors.is_selected(willexecutors[w], False) + break + except: + raise e + total_fees = 0 + total_fees_real = 0 + total_in = 0 + for txid, tx in txs.items(): + tx.willexecutor = willexecutor + fee = tx.estimated_size() * tx_fees + txs[txid].tx_fees = tx_fees + total_fees += fee + total_fees_real += tx.get_fee() + total_in += tx.input_value() + rfee = tx.input_value() - tx.output_value() + if rfee < fee or rfee > fee + wallet.dust_threshold(): + redo = True + oldfees = fees.get(tx.my_locktime, 0) + fees[tx.my_locktime] = fee - if balance - total_in > wallet.dust_threshold(): - redo = True - if not redo: - break - if i >= 10: + if balance - total_in > wallet.dust_threshold(): + redo = True + if not redo: + break + if i >= 10: + break + else: + _logger.info(f"no locktimes for willexecutor {willexecutor} skipped") break alltxs.update(txs) - + return alltxs def get_transactions( @@ -714,3 +733,10 @@ class HeirExpiredException(LocktimeNotValid): class HeirAmountIsDustException(Exception): pass +class NoHeirsException(Exception): + pass +class WillExecutorFeeException(Exception): + def __init__(self,willexecutor): + self.willexecutor=willexecutor + def __str__(self): + return "WillExecutorFeeException: {} fee:{}".format(self.willexecutor['url'],self.willexecutor['base_fee']) diff --git a/qt.py b/qt.py index fa3abe1..c738f71 100644 --- a/qt.py +++ b/qt.py @@ -500,6 +500,7 @@ class BalWindow(Logger): self.logger.debug("not_will_settings {}".format(self.will_settings)) self.bal_plugin.validate_will_settings(self.will_settings) self.heir_list.update_will_settings() + self.heir_list.update() def init_wizard(self): wizard_dialog = BalWizardDialog(self) @@ -710,6 +711,7 @@ class BalWindow(Logger): self.logger.info(f"will-settings: {self.will_settings}") self.logger.info(f"date_to_check:{self.date_to_check}") self.logger.info(f"heirs: {self.heirs}") + return {} except Exception as e: self.logger.info(f"Exception build_will: {e}") raise e @@ -2036,6 +2038,9 @@ class bal_checkbox(QCheckBox): class BalBuildWillDialog(BalDialog): updatemessage = pyqtSignal() + COLOR_WARNING='#cfa808' + COLOR_ERROR='#ff0000' + COLOR_OK='#05ad05' def __init__(self, bal_window, parent=None): if not parent: @@ -2092,25 +2097,24 @@ class BalBuildWillDialog(BalDialog): self.bal_window.window.wallet.dust_threshold(), ) _logger.debug("variables ok") - self.msg_set_status("checking variables:", varrow, "Ok") + self.msg_set_status("checking variables:", varrow, "Ok",self.COLOR_OK) except AmountException: self.msg_set_status( "checking variables", varrow, - '' - + _( + _( "In the inheritance process, " + "the entire wallet will always be fully emptied. \n" + "Your settings require an adjustment of the amounts" - ) - + "", + ), + self.COLOR_WARNING ) self.msg_set_checking() have_to_build = False try: self.bal_window.check_will() - self.msg_set_checking("Ok") + self.msg_set_checking(self.msg_ok()) except WillExpiredException: _logger.debug("expired") self.msg_set_checking("Expired") @@ -2144,11 +2148,23 @@ class BalBuildWillDialog(BalDialog): if have_to_build: self.msg_set_building() try: - self.bal_window.build_will() + if not self.bal_window.build_will(): + self.msg_set_status( + _("Balance is too low. No transaction was built"),None,_("Skipped"),self.COLOR_ERROR + ) + self.bal_window.check_will() for wid in Will.only_valid(self.bal_window.willitems): self.bal_window.wallet.set_label(wid, "BAL Transaction") - self.msg_set_building("Ok") + self.msg_set_building(self.msg_ok()) + except WillExecutorNotPresent as e: + self.msg_set_status( + _("Will-Executor excluded"), + None, + _("Skipped"), + self.COLOR_ERROR + ) + except Exception as e: self.msg_set_building(self.msg_error(e)) return False, None @@ -2159,9 +2175,10 @@ class BalBuildWillDialog(BalDialog): for hid, heir in heirs.items(): if "DUST" in str(heir[HEIR_REAL_AMOUNT]): self.msg_set_status( - f'{hid},{heir[HEIR_DUST_AMOUNT]} is DUST', + f'{hid},{heir[HEIR_DUST_AMOUNT]} is DUST', None, - f"Excluded from will {wid}", + f"Excluded from will {wid}", + self.COLOR_WARNING ) have_to_sign = False @@ -2197,7 +2214,7 @@ class BalBuildWillDialog(BalDialog): txid = self.network.run_from_another_thread( self.network.broadcast_transaction(tx, timeout=120), timeout=120 ) - self.msg_set_invalidating("Ok") + self.msg_set_invalidating(self.msg_ok()) if not txid: _logger.debug(f"should not be none txid: {txid}") @@ -2354,7 +2371,7 @@ class BalBuildWillDialog(BalDialog): for txid, tx in txs.items(): self.bal_window.willitems[txid].tx = copy.deepcopy(tx) self.bal_window.save_willitems() - self.msg_set_signing("Ok") + self.msg_set_signing(self.msg_ok()) except Exception as e: self.msg_set_signing(self.msg_error(e)) @@ -2369,11 +2386,11 @@ class BalBuildWillDialog(BalDialog): else: try: self.loop_push() - self.msg_set_pushing("Ok") + self.msg_set_pushing(self.msg_ok()) except Exception as e: self.msg_set_pushing(self.msg_error(e)) - self.msg_edit_row("Ok") + self.msg_edit_row(self.msg_ok()) self.wait(5) def on_error_phase1(self, error): @@ -2413,13 +2430,20 @@ class BalBuildWillDialog(BalDialog): self.wait_row = self.msg_edit_row(f"Please wait {status}secs", self.wait_row) def msg_error(self, e): - return "Error: {}".format(e) + return "{}".format(self.COLOR_ERROR,e) - def msg_set_status(self, msg, row=None, status=None): + def msg_ok(self, e="Ok"): + return "{}".format(self.COLOR_OK,e) + + def msg_warning(self, e): + return "{}= check_date: count_heirs += 1 if not h in heirs_found: @@ -643,7 +644,6 @@ class Will: raise NoHeirsException("there are not valid heirs") if self_willexecutor and no_willexecutor == 0: raise NoWillExecutorNotPresent("Backup tx") - for url, we in willexecutors.items(): if Willexecutors.is_selected(we): if not url in willexecutors_found: