Index request by ID instead of receiving address.
Replace get_key_for_outgoing_invoice, get_key_for_incoming_request with Invoice.get_id() When a new request is created, reuse addresses of expired requests (fixes #7927) The API is changed for the following commands: get_request, get_invoice, list_requests, list_invoices, delete_request, delete_invoice
This commit is contained in:
@@ -880,21 +880,27 @@ class Commands:
|
||||
return decrypted.decode('utf-8')
|
||||
|
||||
@command('w')
|
||||
async def getrequest(self, key, wallet: Abstract_Wallet = None):
|
||||
"""Return a payment request"""
|
||||
r = wallet.get_request(key)
|
||||
async def get_request(self, request_id, wallet: Abstract_Wallet = None):
|
||||
"""Returns a payment request"""
|
||||
r = wallet.get_request(request_id)
|
||||
if not r:
|
||||
raise Exception("Request not found")
|
||||
return wallet.export_request(r)
|
||||
|
||||
@command('w')
|
||||
async def get_invoice(self, invoice_id, wallet: Abstract_Wallet = None):
|
||||
"""Returns an invoice (request for outgoing payment)"""
|
||||
r = wallet.get_invoice(invoice_id)
|
||||
if not r:
|
||||
raise Exception("Request not found")
|
||||
return wallet.export_invoice(r)
|
||||
|
||||
#@command('w')
|
||||
#async def ackrequest(self, serialized):
|
||||
# """<Not implemented>"""
|
||||
# pass
|
||||
|
||||
@command('w')
|
||||
async def list_requests(self, pending=False, expired=False, paid=False, wallet: Abstract_Wallet = None):
|
||||
"""List the payment requests you made."""
|
||||
def _filter_invoices(self, _list, wallet, pending, expired, paid):
|
||||
if pending:
|
||||
f = PR_UNPAID
|
||||
elif expired:
|
||||
@@ -903,11 +909,23 @@ class Commands:
|
||||
f = PR_PAID
|
||||
else:
|
||||
f = None
|
||||
out = wallet.get_sorted_requests()
|
||||
if f is not None:
|
||||
out = [req for req in out
|
||||
if f == wallet.get_invoice_status(req)]
|
||||
return [wallet.export_request(x) for x in out]
|
||||
_list = [x for x in _list if f == wallet.get_invoice_status(x)]
|
||||
return _list
|
||||
|
||||
@command('w')
|
||||
async def list_requests(self, pending=False, expired=False, paid=False, wallet: Abstract_Wallet = None):
|
||||
"""Returns the list of incoming payment requests saved in the wallet."""
|
||||
l = wallet.get_sorted_requests()
|
||||
l = self._filter_invoices(l, wallet, pending, expired, paid)
|
||||
return [wallet.export_request(x) for x in l]
|
||||
|
||||
@command('w')
|
||||
async def list_invoices(self, pending=False, expired=False, paid=False, wallet: Abstract_Wallet = None):
|
||||
"""Returns the list of invoices (requests for outgoing payments) saved in the wallet."""
|
||||
l = wallet.get_invoices()
|
||||
l = self._filter_invoices(l, wallet, pending, expired, paid)
|
||||
return [wallet.export_invoice(x) for x in l]
|
||||
|
||||
@command('w')
|
||||
async def createnewaddress(self, wallet: Abstract_Wallet = None):
|
||||
@@ -971,9 +989,14 @@ class Commands:
|
||||
return tx.txid()
|
||||
|
||||
@command('w')
|
||||
async def delete_request(self, address, wallet: Abstract_Wallet = None):
|
||||
"""Remove a payment request"""
|
||||
return wallet.delete_request(address)
|
||||
async def delete_request(self, request_id, wallet: Abstract_Wallet = None):
|
||||
"""Remove an incoming payment request"""
|
||||
return wallet.delete_request(request_id)
|
||||
|
||||
@command('w')
|
||||
async def delete_invoice(self, invoice_id, wallet: Abstract_Wallet = None):
|
||||
"""Remove an outgoing payment invoice"""
|
||||
return wallet.delete_invoice(invoice_id)
|
||||
|
||||
@command('w')
|
||||
async def clear_requests(self, wallet: Abstract_Wallet = None):
|
||||
@@ -1175,11 +1198,6 @@ class Commands:
|
||||
if self.network.path_finder:
|
||||
self.network.path_finder.liquidity_hints.reset_liquidity_hints()
|
||||
|
||||
@command('w')
|
||||
async def list_invoices(self, wallet: Abstract_Wallet = None):
|
||||
l = wallet.get_invoices()
|
||||
return [wallet.export_invoice(x) for x in l]
|
||||
|
||||
@command('wnl')
|
||||
async def close_channel(self, channel_point, force=False, wallet: Abstract_Wallet = None):
|
||||
txid, index = channel_point.split(':')
|
||||
|
||||
@@ -272,7 +272,7 @@ class SendScreen(CScreen, Logger):
|
||||
status = self.app.wallet.get_invoice_status(item)
|
||||
status_str = item.get_status_str(status)
|
||||
is_lightning = item.is_lightning()
|
||||
key = self.app.wallet.get_key_for_outgoing_invoice(item)
|
||||
key = item.get_id()
|
||||
if is_lightning:
|
||||
address = item.rhash
|
||||
if self.app.wallet.lnworker:
|
||||
@@ -486,7 +486,7 @@ class ReceiveScreen(CScreen):
|
||||
self.address = addr
|
||||
|
||||
def on_address(self, addr):
|
||||
req = self.app.wallet.get_request(addr)
|
||||
req = self.app.wallet.get_request_by_addr(addr)
|
||||
self.status = ''
|
||||
if req:
|
||||
self.message = req.get('memo', '')
|
||||
@@ -539,7 +539,7 @@ class ReceiveScreen(CScreen):
|
||||
address = req.get_address()
|
||||
else:
|
||||
address = req.lightning_invoice
|
||||
key = self.app.wallet.get_key_for_receive_request(req)
|
||||
key = req.get_id()
|
||||
amount = req.get_amount_sat()
|
||||
description = req.message
|
||||
status = self.app.wallet.get_invoice_status(req)
|
||||
|
||||
@@ -389,7 +389,7 @@ class QEInvoiceParser(QEInvoice):
|
||||
if not self._effectiveInvoice:
|
||||
return
|
||||
# TODO detect duplicate?
|
||||
self.key = self._wallet.wallet.get_key_for_outgoing_invoice(self._effectiveInvoice)
|
||||
self.key = self._effectiveInvoice.get_id()
|
||||
self._wallet.wallet.save_invoice(self._effectiveInvoice)
|
||||
self.invoiceSaved.emit()
|
||||
|
||||
@@ -486,7 +486,7 @@ class QEUserEnteredPayment(QEInvoice):
|
||||
self.invoiceCreateError.emit('fatal', _('Error creating payment') + ':\n' + str(e))
|
||||
return
|
||||
|
||||
self.key = self._wallet.wallet.get_key_for_outgoing_invoice(invoice)
|
||||
self.key = invoice.get_id()
|
||||
self._wallet.wallet.save_invoice(invoice)
|
||||
self.invoiceSaved.emit()
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ class InvoiceList(MyTreeView):
|
||||
self.std_model.clear()
|
||||
self.update_headers(self.__class__.headers)
|
||||
for idx, item in enumerate(self.wallet.get_unpaid_invoices()):
|
||||
key = self.wallet.get_key_for_outgoing_invoice(item)
|
||||
key = item.get_id()
|
||||
if item.is_lightning():
|
||||
icon_name = 'lightning.png'
|
||||
else:
|
||||
|
||||
@@ -126,7 +126,7 @@ class RequestList(MyTreeView):
|
||||
self.std_model.clear()
|
||||
self.update_headers(self.__class__.headers)
|
||||
for req in self.wallet.get_unpaid_requests():
|
||||
key = self.wallet.get_key_for_receive_request(req)
|
||||
key = req.get_id()
|
||||
status = self.wallet.get_invoice_status(req)
|
||||
status_str = req.get_status_str(status)
|
||||
timestamp = req.get_time()
|
||||
|
||||
@@ -646,7 +646,7 @@ class SendTab(QWidget, MessageBoxMixin, Logger):
|
||||
|
||||
def pay_lightning_invoice(self, invoice: Invoice):
|
||||
amount_sat = invoice.get_amount_sat()
|
||||
key = self.wallet.get_key_for_outgoing_invoice(invoice)
|
||||
key = invoice.get_id()
|
||||
if amount_sat is None:
|
||||
raise Exception("missing amount for LN invoice")
|
||||
if not self.wallet.lnworker.can_pay_invoice(invoice):
|
||||
|
||||
@@ -267,7 +267,7 @@ class ElectrumGui(BaseElectrumGui, EventListener):
|
||||
fmt = self.format_column_width(x, [-20, '*', 15, 25])
|
||||
headers = fmt % ("Date", "Description", "Amount", "Status")
|
||||
for req in self.wallet.get_unpaid_invoices():
|
||||
key = self.wallet.get_key_for_outgoing_invoice(req)
|
||||
key = req.get_id()
|
||||
status = self.wallet.get_invoice_status(req)
|
||||
status_str = req.get_status_str(status)
|
||||
timestamp = req.get_time()
|
||||
@@ -287,7 +287,7 @@ class ElectrumGui(BaseElectrumGui, EventListener):
|
||||
fmt = self.format_column_width(x, [-20, '*', 15, 25])
|
||||
headers = fmt % ("Date", "Description", "Amount", "Status")
|
||||
for req in self.wallet.get_unpaid_requests():
|
||||
key = self.wallet.get_key_for_receive_request(req)
|
||||
key = req.get_id()
|
||||
status = self.wallet.get_invoice_status(req)
|
||||
status_str = req.get_status_str(status)
|
||||
timestamp = req.get_time()
|
||||
|
||||
@@ -137,6 +137,10 @@ class Invoice(StoredObject):
|
||||
# 0 means never
|
||||
return self.exp + self.time if self.exp else 0
|
||||
|
||||
def has_expired(self) -> bool:
|
||||
exp = self.get_expiration_date()
|
||||
return bool(exp) and exp < time.time()
|
||||
|
||||
def get_amount_msat(self) -> Union[int, str, None]:
|
||||
return self.amount_msat
|
||||
|
||||
|
||||
@@ -1934,13 +1934,12 @@ class LNWallet(LNWorker):
|
||||
return info.status if info else PR_UNPAID
|
||||
|
||||
def get_invoice_status(self, invoice: Invoice) -> int:
|
||||
key = invoice.rhash
|
||||
log = self.logs[key]
|
||||
if key in self.inflight_payments:
|
||||
invoice_id = invoice.rhash
|
||||
if invoice_id in self.inflight_payments:
|
||||
return PR_INFLIGHT
|
||||
# status may be PR_FAILED
|
||||
status = self.get_payment_status(bfh(key))
|
||||
if status == PR_UNPAID and log:
|
||||
status = self.get_payment_status(bytes.fromhex(invoice_id))
|
||||
if status == PR_UNPAID and invoice_id in self.logs:
|
||||
status = PR_FAILED
|
||||
return status
|
||||
|
||||
@@ -1957,11 +1956,11 @@ class LNWallet(LNWorker):
|
||||
if self.get_payment_status(payment_hash) == status:
|
||||
return
|
||||
self.set_payment_status(payment_hash, status)
|
||||
key = payment_hash.hex()
|
||||
req = self.wallet.get_request(key)
|
||||
request_id = payment_hash.hex()
|
||||
req = self.wallet.get_request(request_id)
|
||||
if req is None:
|
||||
return
|
||||
util.trigger_callback('request_status', self.wallet, key, status)
|
||||
util.trigger_callback('request_status', self.wallet, request_id, status)
|
||||
|
||||
def set_payment_status(self, payment_hash: bytes, status: int) -> None:
|
||||
info = self.get_payment_info(payment_hash)
|
||||
|
||||
@@ -987,7 +987,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
return invoice
|
||||
|
||||
def save_invoice(self, invoice: Invoice, *, write_to_disk: bool = True) -> None:
|
||||
key = self.get_key_for_outgoing_invoice(invoice)
|
||||
key = invoice.get_id()
|
||||
if not invoice.is_lightning():
|
||||
if self.is_onchain_invoice_paid(invoice)[0]:
|
||||
_logger.info("saving invoice... but it is already paid!")
|
||||
@@ -1004,7 +1004,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
|
||||
def clear_requests(self):
|
||||
self._receive_requests.clear()
|
||||
self._requests_addr_to_rhash.clear()
|
||||
self._requests_addr_to_key.clear()
|
||||
self.save_db()
|
||||
|
||||
def get_invoices(self):
|
||||
@@ -1016,8 +1016,8 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
invoices = self.get_invoices()
|
||||
return [x for x in invoices if self.get_invoice_status(x) != PR_PAID]
|
||||
|
||||
def get_invoice(self, key):
|
||||
return self._invoices.get(key)
|
||||
def get_invoice(self, invoice_id):
|
||||
return self._invoices.get(invoice_id)
|
||||
|
||||
def import_requests(self, path):
|
||||
data = read_json_file(path)
|
||||
@@ -1054,10 +1054,10 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
return invoices
|
||||
|
||||
def _init_requests_rhash_index(self):
|
||||
self._requests_addr_to_rhash = {}
|
||||
for key, req in self._receive_requests.items():
|
||||
if req.is_lightning() and (addr:=req.get_address()):
|
||||
self._requests_addr_to_rhash[addr] = req.rhash
|
||||
self._requests_addr_to_key = {}
|
||||
for req in self._receive_requests.values():
|
||||
if req.is_lightning() and not req.has_expired() and (addr:=req.get_address()):
|
||||
self._requests_addr_to_key[addr] = req.get_id()
|
||||
|
||||
def _prepare_onchain_invoice_paid_detection(self):
|
||||
self._invoices_from_txid_map = defaultdict(set) # type: Dict[str, Set[str]]
|
||||
@@ -1366,7 +1366,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
|
||||
def get_label_for_address(self, addr: str) -> str:
|
||||
label = self._labels.get(addr) or ''
|
||||
if not label and (request := self.get_request(addr)):
|
||||
if not label and (request := self.get_request_by_addr(addr)):
|
||||
label = request.get_message()
|
||||
return label
|
||||
|
||||
@@ -2278,7 +2278,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
|
||||
def get_unused_addresses(self) -> Sequence[str]:
|
||||
domain = self.get_receiving_addresses()
|
||||
in_use_by_request = set(req.get_address() for req in self.get_unpaid_requests())
|
||||
in_use_by_request = set(req.get_address() for req in self.get_unpaid_requests() if not req.has_expired())
|
||||
return [addr for addr in domain if not self.adb.is_used(addr)
|
||||
and addr not in in_use_by_request]
|
||||
|
||||
@@ -2303,7 +2303,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
choice = domain[0]
|
||||
for addr in domain:
|
||||
if not self.adb.is_used(addr):
|
||||
if self.get_request(addr) is None:
|
||||
if self.get_request_by_addr(addr) is None:
|
||||
return addr
|
||||
else:
|
||||
choice = addr
|
||||
@@ -2329,7 +2329,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
def check_expired_status(self, r: Invoice, status):
|
||||
#if r.is_lightning() and r.exp == 0:
|
||||
# status = PR_EXPIRED # for BOLT-11 invoices, exp==0 means 0 seconds
|
||||
if status == PR_UNPAID and r.get_expiration_date() and r.get_expiration_date() < time.time():
|
||||
if status == PR_UNPAID and r.has_expired():
|
||||
status = PR_EXPIRED
|
||||
return status
|
||||
|
||||
@@ -2350,15 +2350,15 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
status = PR_PAID
|
||||
return self.check_expired_status(invoice, status)
|
||||
|
||||
def get_request(self, key: str) -> Optional[Invoice]:
|
||||
if req := self._receive_requests.get(key):
|
||||
return req
|
||||
# try 'key' as a fallback address for lightning invoices
|
||||
if (rhash := self._requests_addr_to_rhash.get(key)) and (req := self._receive_requests.get(rhash)):
|
||||
return req
|
||||
def get_request_by_addr(self, addr: str) -> Optional[Invoice]:
|
||||
key = self._requests_addr_to_key.get(addr)
|
||||
return self._receive_requests.get(key)
|
||||
|
||||
def get_formatted_request(self, key):
|
||||
x = self.get_request(key)
|
||||
def get_request(self, request_id: str) -> Optional[Invoice]:
|
||||
return self._receive_requests.get(request_id)
|
||||
|
||||
def get_formatted_request(self, request_id):
|
||||
x = self.get_request(request_id)
|
||||
if x:
|
||||
return self.export_request(x)
|
||||
|
||||
@@ -2376,6 +2376,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
'expiration': x.get_expiration_date(),
|
||||
'status': status,
|
||||
'status_str': status_str,
|
||||
'request_id': key,
|
||||
}
|
||||
if is_lightning:
|
||||
d['rhash'] = x.rhash
|
||||
@@ -2404,6 +2405,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
return d
|
||||
|
||||
def export_invoice(self, x: Invoice) -> Dict[str, Any]:
|
||||
key = x.get_id()
|
||||
status = self.get_invoice_status(x)
|
||||
status_str = x.get_status_str(status)
|
||||
is_lightning = x.is_lightning()
|
||||
@@ -2415,6 +2417,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
'expiration': x.exp,
|
||||
'status': status,
|
||||
'status_str': status_str,
|
||||
'invoice_id': key,
|
||||
}
|
||||
if is_lightning:
|
||||
d['lightning_invoice'] = x.lightning_invoice
|
||||
@@ -2441,9 +2444,8 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
with self.transaction_lock:
|
||||
for txo in tx.outputs():
|
||||
addr = txo.address
|
||||
if self.get_request(addr):
|
||||
req = self.get_request(addr)
|
||||
status = self.get_invoice_status(req)
|
||||
if request:=self.get_request_by_addr(addr):
|
||||
status = self.get_invoice_status(request)
|
||||
util.trigger_callback('request_status', self, addr, status)
|
||||
for invoice_key in self._invoices_from_scriptpubkey_map.get(txo.scriptpubkey, set()):
|
||||
relevant_invoice_keys.add(invoice_key)
|
||||
@@ -2482,52 +2484,31 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
key = self.add_payment_request(req)
|
||||
return key
|
||||
|
||||
@classmethod
|
||||
def get_key_for_outgoing_invoice(cls, invoice: Invoice) -> str:
|
||||
"""Return the key to use for this invoice in self.invoices."""
|
||||
return invoice.get_id()
|
||||
|
||||
def get_key_for_receive_request(self, req: Invoice, *, sanity_checks: bool = False) -> str:
|
||||
"""Return the key to use for this invoice in self.receive_requests."""
|
||||
# FIXME: this should be a method of Invoice
|
||||
if not req.is_lightning():
|
||||
addr = req.get_address() or ""
|
||||
if sanity_checks:
|
||||
if not bitcoin.is_address(addr):
|
||||
raise Exception(_('Invalid Bitcoin address.'))
|
||||
if not self.is_mine(addr):
|
||||
raise Exception(_('Address not in wallet.'))
|
||||
key = addr
|
||||
else:
|
||||
key = req.rhash
|
||||
return key
|
||||
|
||||
def add_payment_request(self, req: Invoice, *, write_to_disk: bool = True):
|
||||
key = self.get_key_for_receive_request(req, sanity_checks=True)
|
||||
self._receive_requests[key] = req
|
||||
if req.is_lightning() and (addr:=req.get_address()):
|
||||
self._requests_addr_to_rhash[addr] = req.rhash
|
||||
request_id = req.get_id()
|
||||
self._receive_requests[request_id] = req
|
||||
if addr:=req.get_address():
|
||||
self._requests_addr_to_key[addr] = request_id
|
||||
if write_to_disk:
|
||||
self.save_db()
|
||||
return key
|
||||
return request_id
|
||||
|
||||
def delete_request(self, key, *, write_to_disk: bool = True):
|
||||
def delete_request(self, request_id, *, write_to_disk: bool = True):
|
||||
""" lightning or on-chain """
|
||||
req = self.get_request(key)
|
||||
req = self.get_request(request_id)
|
||||
if req is None:
|
||||
return
|
||||
key = self.get_key_for_receive_request(req)
|
||||
self._receive_requests.pop(key, None)
|
||||
if req.is_lightning() and (addr:=req.get_address()):
|
||||
self._requests_addr_to_rhash.pop(addr)
|
||||
self._receive_requests.pop(request_id, None)
|
||||
if addr:=req.get_address():
|
||||
self._requests_addr_to_key.pop(addr)
|
||||
if req.is_lightning() and self.lnworker:
|
||||
self.lnworker.delete_payment_info(req.rhash)
|
||||
if write_to_disk:
|
||||
self.save_db()
|
||||
|
||||
def delete_invoice(self, key, *, write_to_disk: bool = True):
|
||||
def delete_invoice(self, invoice_id, *, write_to_disk: bool = True):
|
||||
""" lightning or on-chain """
|
||||
inv = self._invoices.pop(key, None)
|
||||
inv = self._invoices.pop(invoice_id, None)
|
||||
if inv is None:
|
||||
return
|
||||
if inv.is_lightning() and self.lnworker:
|
||||
@@ -2810,7 +2791,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
|
||||
return allow_send, long_warning, short_warning
|
||||
|
||||
def get_help_texts_for_receive_request(self, req: Invoice) -> ReceiveRequestHelp:
|
||||
key = self.get_key_for_receive_request(req)
|
||||
key = req.get_id()
|
||||
addr = req.get_address() or ''
|
||||
amount_sat = req.get_amount_sat() or 0
|
||||
address_help = ''
|
||||
@@ -3013,7 +2994,8 @@ class Imported_Wallet(Simple_Wallet):
|
||||
for tx_hash in transactions_to_remove:
|
||||
self.adb._remove_transaction(tx_hash)
|
||||
self.set_label(address, None)
|
||||
self.delete_request(address)
|
||||
if req:= self.get_request_by_addr(address):
|
||||
self.delete_request(req.get_id())
|
||||
self.set_frozen_state_of_addresses([address], False)
|
||||
pubkey = self.get_public_key(address)
|
||||
self.db.remove_imported_address(address)
|
||||
|
||||
@@ -52,7 +52,7 @@ if TYPE_CHECKING:
|
||||
|
||||
OLD_SEED_VERSION = 4 # electrum versions < 2.0
|
||||
NEW_SEED_VERSION = 11 # electrum versions >= 2.0
|
||||
FINAL_SEED_VERSION = 49 # electrum >= 2.7 will set this to prevent
|
||||
FINAL_SEED_VERSION = 50 # electrum >= 2.7 will set this to prevent
|
||||
# old versions from overwriting new format
|
||||
|
||||
|
||||
@@ -198,6 +198,7 @@ class WalletDB(JsonDB):
|
||||
self._convert_version_47()
|
||||
self._convert_version_48()
|
||||
self._convert_version_49()
|
||||
self._convert_version_50()
|
||||
self.put('seed_version', FINAL_SEED_VERSION) # just to be sure
|
||||
|
||||
self._after_upgrade_tasks()
|
||||
@@ -904,17 +905,13 @@ class WalletDB(JsonDB):
|
||||
}
|
||||
self.data['seed_version'] = 45
|
||||
|
||||
def _convert_version_46(self):
|
||||
from .crypto import sha256d
|
||||
if not self._is_upgrade_method_needed(45, 45):
|
||||
return
|
||||
def _convert_invoices_keys(self, invoices):
|
||||
# recalc keys of outgoing on-chain invoices
|
||||
from .crypto import sha256d
|
||||
def get_id_from_onchain_outputs(raw_outputs, timestamp):
|
||||
outputs = [PartialTxOutput.from_legacy_tuple(*output) for output in raw_outputs]
|
||||
outputs_str = "\n".join(f"{txout.scriptpubkey.hex()}, {txout.value}" for txout in outputs)
|
||||
return sha256d(outputs_str + "%d" % timestamp).hex()[0:10]
|
||||
|
||||
invoices = self.data.get('invoices', {})
|
||||
for key, item in list(invoices.items()):
|
||||
is_lightning = item['lightning_invoice'] is not None
|
||||
if is_lightning:
|
||||
@@ -926,6 +923,12 @@ class WalletDB(JsonDB):
|
||||
if newkey != key:
|
||||
invoices[newkey] = item
|
||||
del invoices[key]
|
||||
|
||||
def _convert_version_46(self):
|
||||
if not self._is_upgrade_method_needed(45, 45):
|
||||
return
|
||||
invoices = self.data.get('invoices', {})
|
||||
self._convert_invoices_keys(invoices)
|
||||
self.data['seed_version'] = 46
|
||||
|
||||
def _convert_version_47(self):
|
||||
@@ -970,6 +973,13 @@ class WalletDB(JsonDB):
|
||||
)
|
||||
self.data['seed_version'] = 49
|
||||
|
||||
def _convert_version_50(self):
|
||||
if not self._is_upgrade_method_needed(49, 49):
|
||||
return
|
||||
requests = self.data.get('payment_requests', {})
|
||||
self._convert_invoices_keys(requests)
|
||||
self.data['seed_version'] = 50
|
||||
|
||||
def _convert_imported(self):
|
||||
if not self._is_upgrade_method_needed(0, 13):
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user