Skip to content

Commit 1433066

Browse files
wallet: use UniqueSortedList
1 parent ba15368 commit 1433066

File tree

2 files changed

+96
-23
lines changed

2 files changed

+96
-23
lines changed

internal_filesystem/apps/com.lightningpiggy.displaywallet/assets/displaywallet.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ def redraw_balance_cb():
227227
def redraw_payments_cb():
228228
global payments_label
229229
print("redrawing payments")
230-
payments_label.set_text(wallet.payment_list_string())
230+
payments_label.set_text(str(wallet.payment_list))
231231

232232
def janitor_cb(timer):
233233
global wallet, config

internal_filesystem/apps/com.lightningpiggy.displaywallet/assets/wallet.py

Lines changed: 95 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,56 @@
1414
import mpos.time
1515
import mpos.util
1616

17+
# keeps a list of items
18+
# The .add() method ensures the list remains unique (via __eq__)
19+
# and sorted (via __lt__) by inserting new items in the correct position.
20+
class UniqueSortedList:
21+
def __init__(self):
22+
self._items = []
23+
24+
def add(self, item):
25+
# Check if item already exists (using __eq__)
26+
if item not in self._items:
27+
# Insert item in sorted position (using __lt__)
28+
for i, existing_item in enumerate(self._items):
29+
if item < existing_item:
30+
self._items.insert(i, item)
31+
return
32+
# If item is larger than all existing items, append it
33+
self._items.append(item)
34+
35+
def __iter__(self):
36+
# Return iterator for the internal list
37+
return iter(self._items)
38+
39+
def get(self, index_nr):
40+
# Retrieve item at given index, raise IndexError if invalid
41+
try:
42+
return self._items[index_nr]
43+
except IndexError:
44+
raise IndexError("Index out of range")
45+
46+
def __len__(self):
47+
# Return the number of items for len() calls
48+
return len(self._items)
49+
50+
def __str__(self):
51+
print("UniqueSortedList tostring called")
52+
return "\n".join(str(item) for item in self._items)
53+
54+
def __eq__(self, other):
55+
if len(self._items) != len(other):
56+
return False
57+
return all(p1 == p2 for p1, p2 in zip(self._items, other))
58+
59+
60+
1761
class Wallet:
1862

1963
# These values could be loading from a cache.json file at __init__
2064
last_known_balance = -1
2165
#last_known_balance_timestamp = 0
22-
payment_list = []
66+
payment_list = UniqueSortedList()
2367

2468
def __init__(self):
2569
self.keep_running = True
@@ -30,11 +74,6 @@ def __str__(self):
3074
elif isinstance(self, NWCWallet):
3175
return "NWCWallet"
3276

33-
def are_payment_lists_equal(self, list1, list2):
34-
if len(list1) != len(list2):
35-
return False
36-
return all(p1 == p2 for p1, p2 in zip(list1, list2))
37-
3877
def handle_new_balance(self, new_balance):
3978
if new_balance != self.last_known_balance:
4079
self.last_known_balance = new_balance
@@ -44,14 +83,11 @@ def handle_new_balance(self, new_balance):
4483

4584
def handle_new_payments(self, new_payments):
4685
print("handle_new_payments")
47-
if not self.are_payment_lists_equal(self.payment_list, new_payments):
86+
if self.payment_list != new_payments:
4887
print("new list of payments")
4988
self.payment_list = new_payments
5089
self.payments_updated_cb()
5190

52-
def payment_list_string(self):
53-
return "\n".join(f"{payment.amount_sats} sats: {payment.comment}" for payment in self.payment_list)
54-
5591
# Need callbacks for:
5692
# - started (so the user can show the UI)
5793
# - stopped (so the user can delete/free it)
@@ -128,19 +164,20 @@ def fetch_payments(self):
128164
try:
129165
payments_reply = json.loads(response_text)
130166
#print(f"Got payments: {payments_reply}")
131-
new_payments = []
167+
new_payments = UniqueSortedList()
132168
for payment in payments_reply:
133169
#print(f"Got payment: {payment}")
134170
amount = payment["amount"]
135171
amount = round(amount / 1000)
136172
comment = payment["memo"]
173+
epoch_time = payment["time"]
137174
extra = payment["extra"]
138175
if extra:
139176
extracomment = extra["comment"]
140177
if extracomment:
141178
comment = extracomment
142-
payment = Payment(amount, comment)
143-
new_payments.append(payment)
179+
payment = Payment(epoch_time, amount, comment)
180+
new_payments.add(payment)
144181
return new_payments
145182
except Exception as e:
146183
print(f"Could not parse reponse text '{response_text}' as JSON: {e}")
@@ -183,6 +220,10 @@ def wallet_manager_thread(self):
183220
)])
184221
print(f"DEBUG: Subscription filters: {self.filters.to_json_array()}")
185222
self.relay_manager.add_subscription(self.subscription_id, self.filters)
223+
print(f"DEBUG: Publishing subscription request")
224+
request_message = [ClientMessageType.REQUEST, self.subscription_id]
225+
request_message.extend(self.filters.to_json_array())
226+
self.relay_manager.publish_message(json.dumps(request_message))
186227
time.sleep(1)
187228

188229
self.fetch_balance()
@@ -235,16 +276,23 @@ def fetch_balance(self):
235276
)
236277
print(f"DEBUG: Signing DM {json.dumps(dm)} with private key")
237278
self.private_key.sign_event(dm) # sign also does encryption if it's a encrypted dm
238-
print(f"DEBUG: Publishing subscription request")
239-
request_message = [ClientMessageType.REQUEST, self.subscription_id]
240-
request_message.extend(self.filters.to_json_array())
241-
self.relay_manager.publish_message(json.dumps(request_message))
242279
print(f"DEBUG: Publishing encrypted DM")
243280
self.relay_manager.publish_event(dm)
244281

245282
def fetch_payments(self):
246-
# just send the message to request payments and they'll be handled by the main loop
247-
pass
283+
# Create get_balance request
284+
list_transactions = {
285+
"method": "list_transactions",
286+
"params": {
287+
"limit": 6
288+
}
289+
}
290+
dm = EncryptedDirectMessage(
291+
recipient_pubkey=self.wallet_pubkey,
292+
cleartext_content=json.dumps(list_transactions)
293+
)
294+
self.private_key.sign_event(dm) # sign also does encryption if it's a encrypted dm
295+
self.relay_manager.publish_event(dm)
248296

249297
def parse_nwc_url(self, nwc_url):
250298
"""Parse Nostr Wallet Connect URL to extract pubkey, relay, secret, and lud16."""
@@ -303,14 +351,39 @@ def parse_nwc_url(self, nwc_url):
303351

304352
class Payment:
305353

306-
def __init__(self, amount_sats, comment):
354+
def __init__(self, epoch_time, amount_sats, comment):
355+
self.epoch_time = epoch_time
307356
self.amount_sats = amount_sats
308357
self.comment = comment
309358

310359
def __str__(self):
311-
return f"Payment(amount_sats={self.amount_sats}, comment='{self.comment}')"
360+
sattext = "sats"
361+
if self.amount_sats is 1:
362+
sattext = "sat"
363+
return f"{self.amount_sats} {sattext}: {self.comment}"
312364

313365
def __eq__(self, other):
314366
if not isinstance(other, Payment):
315367
return False
316-
return self.amount_sats == other.amount_sats and self.comment == other.comment
368+
return self.epoch_time == other.epoch_time and self.amount_sats == other.amount_sats and self.comment == other.comment
369+
370+
def __lt__(self, other):
371+
if not isinstance(other, Payment):
372+
return NotImplemented
373+
return (self.epoch_time, self.amount_sats, self.comment) < (other.epoch_time, other.amount_sats, other.comment)
374+
375+
def __le__(self, other):
376+
if not isinstance(other, Payment):
377+
return NotImplemented
378+
return (self.epoch_time, self.amount_sats, self.comment) <= (other.epoch_time, other.amount_sats, other.comment)
379+
380+
def __gt__(self, other):
381+
if not isinstance(other, Payment):
382+
return NotImplemented
383+
return (self.epoch_time, self.amount_sats, self.comment) > (other.epoch_time, other.amount_sats, other.comment)
384+
385+
def __ge__(self, other):
386+
if not isinstance(other, Payment):
387+
return NotImplemented
388+
return (self.epoch_time, self.amount_sats, self.comment) >= (other.epoch_time, other.amount_sats, other.comment)
389+

0 commit comments

Comments
 (0)