forked from bitcoinafterlife/bal-electrum-plugin
partial commit to fix wallet utils
this commit provide a lot of changes in will-settings including export to ics calendar file.
This commit is contained in:
68
util.py
68
util.py
@@ -1,15 +1,13 @@
|
||||
import bisect
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from electrum.gui.qt.util import getSaveFileName
|
||||
from electrum.i18n import _
|
||||
from electrum.transaction import PartialTxOutput
|
||||
from electrum.util import FileExportFailed
|
||||
|
||||
LOCKTIME_THRESHOLD = 500000000
|
||||
|
||||
|
||||
class Util:
|
||||
@staticmethod
|
||||
def locktime_to_str(locktime):
|
||||
try:
|
||||
locktime = int(locktime)
|
||||
@@ -21,6 +19,7 @@ class Util:
|
||||
pass
|
||||
return str(locktime)
|
||||
|
||||
@staticmethod
|
||||
def str_to_locktime(locktime):
|
||||
try:
|
||||
if locktime[-1] in ("y", "d", "b"):
|
||||
@@ -33,6 +32,7 @@ class Util:
|
||||
timestamp = dt_object.timestamp()
|
||||
return int(timestamp)
|
||||
|
||||
@staticmethod
|
||||
def parse_locktime_string(locktime, w=None):
|
||||
try:
|
||||
return int(locktime)
|
||||
@@ -60,6 +60,7 @@ class Util:
|
||||
pass
|
||||
return 0
|
||||
|
||||
@staticmethod
|
||||
def int_locktime(seconds=0, minutes=0, hours=0, days=0, blocks=0):
|
||||
return int(
|
||||
seconds
|
||||
@@ -69,6 +70,7 @@ class Util:
|
||||
+ blocks * 600
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def encode_amount(amount, decimal_point):
|
||||
if Util.is_perc(amount):
|
||||
return amount
|
||||
@@ -78,6 +80,7 @@ class Util:
|
||||
except Exception:
|
||||
return 0
|
||||
|
||||
@staticmethod
|
||||
def decode_amount(amount, decimal_point):
|
||||
if Util.is_perc(amount):
|
||||
return amount
|
||||
@@ -88,12 +91,14 @@ class Util:
|
||||
except Exception:
|
||||
return str(amount)
|
||||
|
||||
@staticmethod
|
||||
def is_perc(value):
|
||||
try:
|
||||
return value[-1] == "%"
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def cmp_array(heira, heirb):
|
||||
try:
|
||||
if len(heira) != len(heirb):
|
||||
@@ -105,11 +110,13 @@ class Util:
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def cmp_heir(heira, heirb):
|
||||
if heira[0] == heirb[0] and heira[1] == heirb[1]:
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def cmp_willexecutor(willexecutora, willexecutorb):
|
||||
if willexecutora == willexecutorb:
|
||||
return True
|
||||
@@ -124,6 +131,7 @@ class Util:
|
||||
return False
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def search_heir_by_values(heirs, heir, values):
|
||||
for h, v in heirs.items():
|
||||
found = False
|
||||
@@ -135,12 +143,14 @@ class Util:
|
||||
return h
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def cmp_heir_by_values(heira, heirb, values):
|
||||
for v in values:
|
||||
if heira[v] != heirb[v]:
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def cmp_heirs_by_values(
|
||||
heirsa, heirsb, values, exclude_willexecutors=False, reverse=True
|
||||
):
|
||||
@@ -165,6 +175,7 @@ class Util:
|
||||
else:
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def cmp_heirs(
|
||||
heirsa,
|
||||
heirsb,
|
||||
@@ -187,6 +198,7 @@ class Util:
|
||||
raise e
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def cmp_inputs(inputsa, inputsb):
|
||||
if len(inputsa) != len(inputsb):
|
||||
return False
|
||||
@@ -195,6 +207,7 @@ class Util:
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def cmp_outputs(outputsa, outputsb, willexecutor_output=None):
|
||||
if len(outputsa) != len(outputsb):
|
||||
return False
|
||||
@@ -204,6 +217,7 @@ class Util:
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def cmp_txs(txa, txb):
|
||||
if not Util.cmp_inputs(txa.inputs(), txb.inputs()):
|
||||
return False
|
||||
@@ -211,6 +225,7 @@ class Util:
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def get_value_amount(txa, txb):
|
||||
outputsa = txa.outputs()
|
||||
# outputsb = txb.outputs()
|
||||
@@ -229,6 +244,7 @@ class Util:
|
||||
|
||||
return value_amount
|
||||
|
||||
@staticmethod
|
||||
def chk_locktime(timestamp_to_check, block_height_to_check, locktime):
|
||||
# TODO BUG: WHAT HAPPEN AT THRESHOLD?
|
||||
locktime = int(locktime)
|
||||
@@ -239,6 +255,7 @@ class Util:
|
||||
else:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def anticipate_locktime(locktime, blocks=0, hours=0, days=0):
|
||||
locktime = int(locktime)
|
||||
out = 0
|
||||
@@ -255,6 +272,7 @@ class Util:
|
||||
out = 1
|
||||
return out
|
||||
|
||||
@staticmethod
|
||||
def cmp_locktime(locktimea, locktimeb):
|
||||
if locktimea == locktimeb:
|
||||
return 0
|
||||
@@ -268,17 +286,20 @@ class Util:
|
||||
else:
|
||||
return int(locktimea) - (locktimeb)
|
||||
|
||||
@staticmethod
|
||||
def get_lowest_valid_tx(available_utxos, will):
|
||||
will = sorted(will.items(), key=lambda x: x[1]["tx"].locktime)
|
||||
for txid, willitem in will.items():
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def get_locktimes(will):
|
||||
locktimes = {}
|
||||
for txid, willitem in will.items():
|
||||
locktimes[willitem["tx"].locktime] = True
|
||||
return locktimes.keys()
|
||||
|
||||
@staticmethod
|
||||
def get_lowest_locktimes(locktimes):
|
||||
sorted_timestamp = []
|
||||
sorted_block = []
|
||||
@@ -291,18 +312,22 @@ class Util:
|
||||
|
||||
return sorted(sorted_timestamp), sorted(sorted_block)
|
||||
|
||||
@staticmethod
|
||||
def get_lowest_locktimes_from_will(will):
|
||||
return Util.get_lowest_locktimes(Util.get_locktimes(will))
|
||||
|
||||
@staticmethod
|
||||
def search_willtx_per_io(will, tx):
|
||||
for wid, w in will.items():
|
||||
if Util.cmp_txs(w["tx"], tx["tx"]):
|
||||
return wid, w
|
||||
return None, None
|
||||
|
||||
@staticmethod
|
||||
def invalidate_will(will):
|
||||
raise Exception("not implemented")
|
||||
|
||||
@staticmethod
|
||||
def get_will_spent_utxos(will):
|
||||
utxos = []
|
||||
for txid, willitem in will.items():
|
||||
@@ -310,6 +335,7 @@ class Util:
|
||||
|
||||
return utxos
|
||||
|
||||
@staticmethod
|
||||
def utxo_to_str(utxo):
|
||||
try:
|
||||
return utxo.to_str()
|
||||
@@ -321,6 +347,7 @@ class Util:
|
||||
pass
|
||||
return str(utxo)
|
||||
|
||||
@staticmethod
|
||||
def cmp_utxo(utxoa, utxob):
|
||||
utxoa = Util.utxo_to_str(utxoa)
|
||||
utxob = Util.utxo_to_str(utxob)
|
||||
@@ -329,21 +356,25 @@ class Util:
|
||||
else:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def in_utxo(utxo, utxos):
|
||||
for s_u in utxos:
|
||||
if Util.cmp_utxo(s_u, utxo):
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def txid_in_utxo(txid, utxos):
|
||||
for s_u in utxos:
|
||||
if s_u.prevout.txid == txid:
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def cmp_output(outputa, outputb):
|
||||
return outputa.address == outputb.address and outputa.value == outputb.value
|
||||
|
||||
@staticmethod
|
||||
def in_output(output, outputs):
|
||||
for s_o in outputs:
|
||||
if Util.cmp_output(s_o, output):
|
||||
@@ -355,6 +386,7 @@ class Util:
|
||||
# return true false same amount different address
|
||||
# return false false different amount, different address not found
|
||||
|
||||
@staticmethod
|
||||
def din_output(out, outputs):
|
||||
same_amount = []
|
||||
for s_o in outputs:
|
||||
@@ -370,6 +402,7 @@ class Util:
|
||||
else:
|
||||
return False, False
|
||||
|
||||
@staticmethod
|
||||
def get_change_output(wallet, in_amount, out_amount, fee):
|
||||
change_amount = int(in_amount - out_amount - fee)
|
||||
if change_amount > wallet.dust_threshold():
|
||||
@@ -380,6 +413,7 @@ class Util:
|
||||
out.is_change = True
|
||||
return out
|
||||
|
||||
@staticmethod
|
||||
def get_current_height(network):
|
||||
# if no network or not up to date, just set locktime to zero
|
||||
if not network:
|
||||
@@ -401,6 +435,7 @@ class Util:
|
||||
height = min(chain_height, server_height)
|
||||
return height
|
||||
|
||||
@staticmethod
|
||||
def print_var(var, name="", veryverbose=False):
|
||||
print(f"---{name}---")
|
||||
if var is not None:
|
||||
@@ -435,6 +470,7 @@ class Util:
|
||||
|
||||
print(f"---end {name}---")
|
||||
|
||||
@staticmethod
|
||||
def print_utxo(utxo, name=""):
|
||||
print(f"---utxo-{name}---")
|
||||
Util.print_var(utxo, name)
|
||||
@@ -446,36 +482,20 @@ class Util:
|
||||
print("_TxInput__value_sats:", utxo._TxInput__value_sats)
|
||||
print(f"---utxo-end {name}---")
|
||||
|
||||
@staticmethod
|
||||
def print_prevout(prevout, name=""):
|
||||
print(f"---prevout-{name}---")
|
||||
Util.print_var(prevout, f"{name}-prevout")
|
||||
Util.print_var(prevout._asdict())
|
||||
print(f"---prevout-end {name}---")
|
||||
|
||||
def export_meta_gui(electrum_window, title, exporter):
|
||||
filter_ = "All files (*)"
|
||||
filename = getSaveFileName(
|
||||
parent=electrum_window,
|
||||
title=_("Select file to save your {}".format(title)),
|
||||
filename="BALplugin_{}".format(title),
|
||||
filter=filter_,
|
||||
config=electrum_window.config,
|
||||
)
|
||||
if not filename:
|
||||
return
|
||||
try:
|
||||
exporter(filename)
|
||||
except FileExportFailed as e:
|
||||
electrum_window.show_critical(str(e))
|
||||
else:
|
||||
electrum_window.show_message(
|
||||
_("Your {0} were exported to '{1}'".format(title, str(filename)))
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def copy(dicto, dictfrom):
|
||||
for k, v in dictfrom.items():
|
||||
dicto[k] = v
|
||||
|
||||
@staticmethod
|
||||
def fix_will_settings_tx_fees(will_settings):
|
||||
tx_fees = will_settings.get("tx_fees", False)
|
||||
have_to_update = False
|
||||
@@ -485,6 +505,7 @@ class Util:
|
||||
have_to_update = True
|
||||
return have_to_update
|
||||
|
||||
@staticmethod
|
||||
def fix_will_tx_fees(will):
|
||||
have_to_update = False
|
||||
for txid, willitem in will.items():
|
||||
@@ -495,15 +516,18 @@ class Util:
|
||||
have_to_update = True
|
||||
return have_to_update
|
||||
|
||||
@staticmethod
|
||||
def text_to_hex(text: str) -> str:
|
||||
"""Convert text to hexadecimal string"""
|
||||
hex_string = text.encode('utf-8').hex()
|
||||
return hex_string
|
||||
|
||||
|
||||
@staticmethod
|
||||
def hex_to_text(hex_string: str) -> str:
|
||||
"""Convert hexadecimal string back to text (for verification)"""
|
||||
try:
|
||||
return bytes.fromhex(hex_string).decode('utf-8')
|
||||
except Exception:
|
||||
return "Error: Invalid hex string"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user