Skip to content

fix(wallet): keep self-send legs distinct + deterministic tx order#586

Open
dmnyc wants to merge 1 commit into
barrydeen:mainfrom
dmnyc:fix/wallet-self-send-tx-order
Open

fix(wallet): keep self-send legs distinct + deterministic tx order#586
dmnyc wants to merge 1 commit into
barrydeen:mainfrom
dmnyc:fix/wallet-self-send-tx-order

Conversation

@dmnyc

@dmnyc dmnyc commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Summary

A self-payment (e.g. paying your own lightning address) surfaces in the wallet provider's transaction list as two records sharing one payment hash — one outgoing leg and one incoming leg. Two problems followed on Android:

  1. One leg vanished from the UI. LazyColumn { items(transactions) } falls back to identity equality. Because both legs share the same paymentHash and equal in most other fields, Compose treated them as the same item and only rendered one.
  2. Order was non-deterministic. Some providers (notably NWC) return the legs in send-then-receive order; Spark returns receive-then-send. The displayed order followed whatever the provider gave us, so the same self-send rendered differently across wallet backends.

This PR ports the iOS WalletStore.dedupTransactions hardening so Android matches.

Changes

  • WalletViewModel.kt — adds dedupTransactions():
    • drops exact (paymentHash, type) repeats the backend returns
    • sorts newest-first
    • on a timestamp tie, places the incoming "received" leg above its outgoing "sent" leg
    • applied on initial load, post-enrichment, and load-more
  • WalletScreen.kt — keys the transaction LazyColumn by "$paymentHash|$type" so the two legs of a self-send keep distinct Compose identities and both render. Mirrors iOS WalletTransaction.id.

Verified on device

Before: NWC wallet self-send pair rendered with the sent leg above the received leg (opposite of Spark).
After: both wallets show received above sent for self-send pairs, and both legs are visible.

(Screenshots in the comment that triggered this fix.)

Reference

iOS: WalletStore.swiftdedupTransactions + WalletTransaction.id.

A self-payment surfaces as two transaction records sharing one payment
hash — one outgoing, one incoming. Port the iOS WalletStore.dedupTransactions
hardening so they render correctly:

- Add dedupTransactions(): drop exact (paymentHash, type) repeats the
  backend returns, and sort newest-first with the incoming "received" leg
  above its outgoing "sent" leg on a timestamp tie. Apply on initial load,
  re-enrich, and load-more.
- Key the transaction LazyColumn by "paymentHash|type" so the two legs of a
  self-send keep distinct identities and both render (mirrors iOS
  WalletTransaction.id).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant