NWC: instant payments work, also add QR code

This commit is contained in:
Thomas Farstrike
2025-05-30 08:24:00 +02:00
parent a3739e242e
commit f1ad24a330
2 changed files with 63 additions and 59 deletions
@@ -199,13 +199,19 @@ def build_main_ui():
balance_label.align(lv.ALIGN.TOP_LEFT, 0, 0)
balance_label.set_style_text_font(lv.font_montserrat_22, 0)
balance_label.set_text(lv.SYMBOL.REFRESH)
receive_qr = lv.qrcode(main_screen)
receive_qr.set_size(50)
receive_qr.set_dark_color(lv.color_black())
receive_qr.set_light_color(lv.color_white())
receive_qr.update("tfar@getalby.com", len("tfar@getalby.com"))
receive_qr.align(lv.ALIGN.TOP_RIGHT,0,0)
style_line = lv.style_t()
style_line.init()
style_line.set_line_width(2)
style_line.set_line_color(lv.palette_main(lv.PALETTE.PINK))
style_line.set_line_rounded(True)
balance_line = lv.line(main_screen)
balance_line.set_points([{'x':0,'y':35},{'x':300,'y':35}],2)
balance_line.set_points([{'x':0,'y':35},{'x':200,'y':35}],2)
balance_line.add_style(style_line, 0)
payments_label = lv.label(main_screen)
payments_label.align_to(balance_line,lv.ALIGN.OUT_BOTTOM_LEFT,0,10)
@@ -57,6 +57,46 @@ class UniqueSortedList:
return all(p1 == p2 for p1, p2 in zip(self._items, other))
class Payment:
def __init__(self, epoch_time, amount_sats, comment):
self.epoch_time = epoch_time
self.amount_sats = amount_sats
self.comment = comment
def __str__(self):
sattext = "sats"
if self.amount_sats == 1:
sattext = "sat"
return f"{self.amount_sats} {sattext}: {self.comment}"
def __eq__(self, other):
if not isinstance(other, Payment):
return False
return self.epoch_time == other.epoch_time and self.amount_sats == other.amount_sats and self.comment == other.comment
def __lt__(self, other):
if not isinstance(other, Payment):
return NotImplemented
return (self.epoch_time, self.amount_sats, self.comment) < (other.epoch_time, other.amount_sats, other.comment)
def __le__(self, other):
if not isinstance(other, Payment):
return NotImplemented
return (self.epoch_time, self.amount_sats, self.comment) <= (other.epoch_time, other.amount_sats, other.comment)
def __gt__(self, other):
if not isinstance(other, Payment):
return NotImplemented
return (self.epoch_time, self.amount_sats, self.comment) > (other.epoch_time, other.amount_sats, other.comment)
def __ge__(self, other):
if not isinstance(other, Payment):
return NotImplemented
return (self.epoch_time, self.amount_sats, self.comment) >= (other.epoch_time, other.amount_sats, other.comment)
class Wallet:
@@ -84,6 +124,11 @@ class Wallet:
print("Refreshing payments...")
self.fetch_payments() # if the balance changed, then re-list transactions
def handle_new_payment(self, new_payment):
print("handle_new_payment")
self.payment_list.add(new_payment)
self.payments_updated_cb()
def handle_new_payments(self, new_payments):
print("handle_new_payments")
if self.payment_list != new_payments:
@@ -142,11 +187,9 @@ class LNBitsWallet(Wallet):
if new_balance:
self.handle_new_balance(new_balance, False) # handle new balance BUT don't trigger a full fetch_payments
transaction = payment_notification.get("payment")
new_payments = UniqueSortedList()
print(f"Got transaction: {transaction}")
paymentObj = parseLNBitsPayment(transaction)
new_payments.add(paymentObj)
self.handle_new_payments(new_payments)
self.handle_new_payment(paymentObj)
except Exception as e:
print(f"websocket on_message got exception: {e}")
@@ -222,12 +265,10 @@ class LNBitsWallet(Wallet):
try:
payments_reply = json.loads(response_text)
#print(f"Got payments: {payments_reply}")
new_payments = UniqueSortedList()
for transaction in payments_reply:
#print(f"Got transaction: {transaction}")
paymentObj = parseLNBitsPayment(transaction)
new_payments.add(paymentObj)
self.handle_new_payments(new_payments)
self.handle_new_payment(paymentObj)
except Exception as e:
print(f"Could not parse reponse text '{response_text}' as JSON: {e}")
raise e
@@ -310,22 +351,21 @@ class NWCWallet(Wallet):
result = response.get("result")
if result:
if result.get("balance"):
new_balance = round(int(response["result"]["balance"]) / 1000)
new_balance = round(int(result["balance"]) / 1000)
print(f"Got balance: {new_balance}")
self.handle_new_balance(new_balance)
elif result.get("transactions"):
print("Response contains transactions!")
new_payments = UniqueSortedList()
for transaction in result["transactions"]:
amount = transaction["amount"]
amount = round(amount / 1000)
comment = self.getCommentFromTransaction(transaction)
epoch_time = transaction["created_at"]
payment = Payment(epoch_time, amount, comment)
new_payments.add(payment)
self.handle_new_payments(new_payments)
elif result.get("notification"): # it's a notification
notification = result.get("notification")
paymentObj = Payment(epoch_time, amount, comment)
self.handle_new_payment(paymentObj)
else:
notification = response.get("notification")
if notification:
amount = notification["amount"]
amount = round(amount / 1000)
type = notification["type"]
@@ -334,17 +374,14 @@ class NWCWallet(Wallet):
elif type != "incoming":
print(f"WARNING: invalid notification type {type}, ignoring.")
continue
new_balance = self.balance + amount
self.handle_new_balance(new_balance, False)
epoch_time = transaction["created_at"]
comment = self.getCommentFromTransaction(notification)
payment = Payment(epoch_time, amount, comment)
new_payments = UniqueSortedList()
new_payments.add(payment)
self.handle_new_payments(new_payments)
paymentObj = Payment(epoch_time, amount, comment)
self.handle_new_payment(paymentObj)
else:
print("Unsupported response, ignoring.")
else:
print("Event doesn't contain result, ignoring.")
except Exception as e:
print(f"DEBUG: Error processing response: {e}")
time.sleep(1)
@@ -440,42 +477,3 @@ class NWCWallet(Wallet):
except Exception as e:
print(f"DEBUG: Error parsing NWC URL: {e}")
class Payment:
def __init__(self, epoch_time, amount_sats, comment):
self.epoch_time = epoch_time
self.amount_sats = amount_sats
self.comment = comment
def __str__(self):
sattext = "sats"
if self.amount_sats == 1:
sattext = "sat"
return f"{self.amount_sats} {sattext}: {self.comment}"
def __eq__(self, other):
if not isinstance(other, Payment):
return False
return self.epoch_time == other.epoch_time and self.amount_sats == other.amount_sats and self.comment == other.comment
def __lt__(self, other):
if not isinstance(other, Payment):
return NotImplemented
return (self.epoch_time, self.amount_sats, self.comment) < (other.epoch_time, other.amount_sats, other.comment)
def __le__(self, other):
if not isinstance(other, Payment):
return NotImplemented
return (self.epoch_time, self.amount_sats, self.comment) <= (other.epoch_time, other.amount_sats, other.comment)
def __gt__(self, other):
if not isinstance(other, Payment):
return NotImplemented
return (self.epoch_time, self.amount_sats, self.comment) > (other.epoch_time, other.amount_sats, other.comment)
def __ge__(self, other):
if not isinstance(other, Payment):
return NotImplemented
return (self.epoch_time, self.amount_sats, self.comment) >= (other.epoch_time, other.amount_sats, other.comment)