Skip to content

feat: Unified BIP321 URI and 3-way toggle for payments#203

Open
a1denvalu3 wants to merge 21 commits intomainfrom
feat/bip321-uri
Open

feat: Unified BIP321 URI and 3-way toggle for payments#203
a1denvalu3 wants to merge 21 commits intomainfrom
feat/bip321-uri

Conversation

@a1denvalu3
Copy link
Collaborator

@a1denvalu3 a1denvalu3 commented Mar 7, 2026

Summary

  • Bumps cdk-kotlin to 0.15.2-rc.0 to utilize toBech32String (NUT-26).
  • Adds a new "Unified" tab (default) alongside Cashu and Lightning tabs with a shrinking/expanding UI animation.
  • Starts Cashu WebSocket listener and Lightning poll listener concurrently so they are both ready.
  • Constructs a unified BIP321 URI (bitcoin:?creq=...&lightning=...) explicitly using the new Bech32 creqB format for the Unified QR and NFC HCE payloads.
  • Backward Compatibility: Specifically retains the legacy creqA format for the dedicated "Cashu" tab (both QR and NFC payloads) and Share button when on that tab, ensuring existing functionality is preserved.
  • Fixes UI loading stutter by preventing an unnecessary coroutine switch when resuming a Lightning payment from history.

@github-project-automation github-project-automation bot moved this to Backlog in Numo Mar 7, 2026
@a1denvalu3 a1denvalu3 changed the title feat: Unified BIP21 URI and 3-way toggle for payments feat: Unified BIP321 URI and 3-way toggle for payments Mar 7, 2026
@Kelbie
Copy link

Kelbie commented Mar 7, 2026

Just a visual thing but it might be nice if the tab container isn't changing width constantly. I know in CSS you can use flex box for the two smaller tabs to fill the remaining space evenly. Then have the tabs be the maximum size always that way its width isn't constantly changing.

It's hard to tell if that would look better than the way it is now but I thought I'd mention it.

@Kelbie
Copy link

Kelbie commented Mar 7, 2026

or maybe if the selected tab always is the same maximum size, that might look good too!

@a1denvalu3
Copy link
Collaborator Author

@Kelbie addressed

@swedishfrenchpress
Copy link
Collaborator

swedishfrenchpress commented Mar 7, 2026

Tested tap-to-pay on Sunmi v2 POS and Pixel 6awith Macadamia, Sovran on both Cashu tab and Unified tabs.

Results:

Wallet Payment type Pixel 6a Sunmi v2
Macadamia Cashu tab
Macadamia Unified
Sovran Cashu tab
Sovran Unified

Errors:

  • Macadamia + Unified (both devices), error on paying side: Invalid payment request: CashuSwift.CashuError error 22
  • Sovran + Unified (both devices), error on Numo: NFC payment failed: unsupported pr: invalid prefix
  • Sovran + Cashu tab + Sunmi v2, error on Numo: Connection failed. Could not connect to the terminal. Make sure NFC is enabled.

unified failure expected as they have no updated to support bip321. minibits works, but that's paying via ln according to @a1denvalu3.

@swedishfrenchpress
Copy link
Collaborator

i have explored a slight ui improvement in this branch: https://github.com/cashubtc/Numo/tree/feat/bip321-uri-tab-ui-fix

unified-example.mp4

It replaced the icon and text tables tabs with a text only design. I think it works better to address these two issues:

  1. Layout instability,. "Unified", "Cashu", and "Lightning" are all different widths than their icons, so the container shifted on every tap. We had a commit just for this (27c9b4d).
  2. Tapping an icon makes it disappear. That feel backwards to me. The indicator should move to you, not vanish what you touched.

@Kelbie
Copy link

Kelbie commented Mar 7, 2026

Tabs look much better now!

@swedishfrenchpress
Copy link
Collaborator

@a1denvalu3 opened up a PR for tab UI updates #208

@Egge21M
Copy link
Contributor

Egge21M commented Mar 9, 2026

Bug report related to this PR

When fetching an invoice fails (e.g. network error) the resulting request string is no longer a BIP 321 string, but instead a regular CREQ.

Steps top reproduce:

  1. Enable airplane mode
  2. Create a request in Numo
  3. You will see a error modal about the HTTP transport failing
  4. Unified tab will encode "CREQ..."

@a1denvalu3
Copy link
Collaborator Author

I did this deliberately. It's not a bug.

- Update CDK to 0.15.2-rc.0 to access `toBech32String` for NUT-26 encoded payment requests.
- Add 'Unified' tab alongside Cashu and Lightning tabs. Unselected tabs now visually shrink down to just display their respective icons.
- Simplify WebSocket listeners logic to always fetch both Cashu and Lightning payment updates simultaneously in the background.
- Construct unified BIP21 URI combining `creq=` and `lightning=` parameters when generating the Unified QR Code and supplying the Unified HCE NDEF tag.
- Apply smooth LayoutTransitions when toggling tabs.
- Start NFC reading animation immediately upon any APDU interaction
- Distinguish between read-only interactions and write transactions
- Return to payment request screen without error if payer only reads
- Surface failure screen only if connection drops during token write
- Distinguish successful NDEF completion from reading timeout
- Suppress onNfcReadingStopped callback when payment finishes successfully
- Ensures PaymentRequestActivity transitions directly to processing animation without flashing the failure screen or hiding the overlay
- Increases HCE service timeout from 2s to 10s to allow wallets like Minibits more time to process unified URIs and write the Cashu token without dropping the connection prematurely.
- Increases the Activity's safety timeout from 5s to 15s accordingly to avoid racing against the extended HCE timeout.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

4 participants