Skip to content

feat(clink): pay CLINK noffer offers from notes, profiles & wallet#360

Draft
dmnyc wants to merge 1 commit into
mainfrom
feat/clink-offer-payments
Draft

feat(clink): pay CLINK noffer offers from notes, profiles & wallet#360
dmnyc wants to merge 1 commit into
mainfrom
feat/clink-offer-payments

Conversation

@dmnyc

@dmnyc dmnyc commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds CLINK Offers (noffer1…) payment support so users can pay self-custodial Lightning offers advertised in notes, on profiles, and from the wallet — matching the established "scan to pay" UX in Wisp style.

  • Decoder + RPCNoffer: bech32 + TLV decoder, pricing types (fixed / variable-range / spontaneous), isNofferString / stripNostrPrefix. NofferClient: kind-21001 NIP-44 RPC (publish request → await the encrypted invoice on the offer's relay → pay), with code-3 "expired/moved" latest-retry.
  • Pay modalNofferPaySheet + NofferButton: a shared "Pay offer" sheet that pays via the active wallet, or falls back to a scannable bare-noffer QR for an external CLINK-aware wallet. The inline card resolves the recipient's name itself so it reads consistently across feed and thread.
  • NotesContentParser detects noffer tokens (incl. nostr: prefix); RichContentView renders the Pay-offer card.
  • Profiles — parse clink_offer / noffer / offer from kind-0 (tolerant read); Pay-offer button on the profile header; a CLINK offer field in the profile editor's Advanced section.
  • Profile QR sheet — the offer lives inside the Lightning tab (not a separate tab); when a profile has both a Lightning address and an offer, a single contextual button switches between them. Gated away entirely when no offer is set.
  • Wallet Send sheet — detects a pasted/scanned noffer and opens the pay flow; the input placeholder now reads "Lightning address, invoice, or CLINK offer".
  • Tests — round-trip decoder coverage mirroring the CLINK spec TLV layout.

Spec: https://github.com/shocknet/CLINK/blob/main/specs/clink-offers.md

Test plan

  • Note "Pay offer" card → in-app payment settles
  • Note "Pay offer" card → external QR scans/pays from a CLINK-aware wallet
  • Wallet Send sheet → pasted/scanned noffer opens the pay flow
  • Profile header Pay-offer button → opens the sheet and pays
  • Profile QR sheet → offer shows in the Lightning tab with the contextual switch
  • CLINK offer round-trips through kind-0 (set in profile, renders everywhere)
  • Recipient name resolves consistently (feed + thread)
  • Fixed-amount and variable-range pricing variants (only "pay what you want" exercised so far — to verify over time)

Android port to follow.

…wallet

Add CLINK Offers (noffer1…) payment support, matching the zap.cooking UX in
wisp style.

- Noffer: bech32 + TLV decoder, pricing types, isNofferString/stripNostrPrefix
- NofferClient: kind-21001 NIP-44 RPC (publish request, await encrypted invoice
  response on the offer's relay), with code-3 "expired/moved" latest-retry
- NofferPaySheet + NofferButton: shared "Pay offer" modal — pay via the active
  wallet, or fall back to a scannable bare noffer QR for an external wallet
- Notes: ContentParser detects noffer tokens; RichContentView renders the card
- Profiles: parse clink_offer/noffer/offer from kind-0; show a Pay-offer button
  on the profile header; add a CLINK offer field to the profile editor
- Wallet: detect a pasted/scanned noffer in the Send sheet and open the pay flow
- Tests: round-trip decoder coverage mirroring the CLINK spec TLV layout

Spec: https://github.com/shocknet/CLINK/blob/main/specs/clink-offers.md
Android port to follow after the iOS merge.
@dmnyc

dmnyc commented Jun 13, 2026

Copy link
Copy Markdown
Collaborator Author

Changing to draft mode so this can deploy in Dark Wisp first. barrydeen/dark-wisp-android#25

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