feat(wallet): cross-platform NWC connection backup via NIP-78 + parity polish#563
Open
dmnyc wants to merge 4 commits into
Open
feat(wallet): cross-platform NWC connection backup via NIP-78 + parity polish#563dmnyc wants to merge 4 commits into
dmnyc wants to merge 4 commits into
Conversation
Publish the active NWC URI as a NIP-44 v2 self-encrypted kind-30078 event on every successful connect, and surface a one-tap "Restore previous wallet" affordance on the NWC setup screen when an existing backup is found on relays. Implements the cross-platform contract documented in NWC_BACKUP_PARITY.md (PR barrydeen#560) so an NWC connection published from iOS restores on Android — and vice versa — with no re-paste. Contract honored: - kind 30078, d-tag "nwc-wallet-backup" (flat, no namespacing) - NIP-44 v2 self-to-self encryption, plaintext = raw NWC URI - Publish best-effort on every connect; no NIP-09 on disconnect - Restore search runs when the NWC setup screen opens; suppressed if the backup matches the active connection
Layers iOS-parity polish on top of the bare cross-platform NWC
backup feature so the connect screen, restore affordance, and the
broader wallet dashboard all match the iOS 1:1 visual contract.
NWC setup screen polish
- Replace the single-line "Restore previous wallet" pill with the
iOS-style "Backup found" card: cloud icon + title row, body copy
showing the backup date ("A connection backed up on <date> is
available. Restore it to reconnect without pasting a string."),
and a full-width orange "Restore connection" button.
- Add a "Searching for backup…" indicator that renders while the
relay query is in flight, between the subtitle and paste/scan
card. Disappears as soon as the state moves to Found / NotFound.
- Add a cloud-shield footer line under the paste/scan card:
"Connecting saves an encrypted backup to your Nostr relays so you
can restore this connection on other devices."
- Surface the backup's `created_at` via `NwcRestoreState.Found` so
the card can format the date with `DateFormat.MEDIUM`.
- Drop the verbose per-relay status-line stream on the NWC setup
screen — the Connect button's spinner + "Connecting…" label
covers the happy path and any real failure surfaces via
`WalletState.Error`. Looked like noise after a one-tap restore.
Wallet-mode picker
- Spark row renders as a full-bleed orange card with white text +
icon and a layered shadow glow (24dp outer halo + 10dp tighter
inner, both tinted with the brand accent). Subtitle reads
"Self-custody, embedded. Recommended." NWC row keeps its dark
surface-variant peer treatment.
Spark setup screen
- "Use my default wallet" gets the same orange + layered-glow
treatment so the nsec-derived recovery path reads as the obvious
first choice.
- Create / Restore-from-seed / Restore-from-relays collapse under a
"More options" disclosure with a chevron that rotates 0→180°
via `animateFloatAsState`. `AnimatedVisibility` wraps the inner
Column for the expand/collapse transition. Defaults to open when
the default-wallet primary isn't visible.
Wallet Settings dropdown
- `WalletInfoRow` uses a fixed-width label column (`widthIn(min =
110.dp)` + trailing padding) and right-aligns values with
`maxLines = 1 + TextOverflow.Ellipsis + TextAlign.End`. Long relay
URLs / lightning addresses truncate cleanly; labels align across
rows like the iOS settings panel.
- Backup-to-relay button is offered for default Spark wallets too —
matches iOS, gives users belt-and-braces durability beyond the
nsec.
- Recoverable wallets (default Spark + NWC) get an iOS-red soft
card row with SwapHoriz + "Switch to a different wallet", a
section header ("Disconnect Wallet"), and an explanatory caption.
Non-default Spark keeps the filled-red Delete CTA because its
seed can't be re-derived.
- Delete confirmation page unifies on `#FF3B30` across all three
flows (switch / disconnect / delete) instead of mixing Material
primary orange and `#D32F2F`.
Dashboard
- Lightning-address pill renders for any wallet mode that carries
a `lud16` (Spark via Breez, NWC via parsed URI). Removes the
redundant "Nostr Wallet Connect" footer below the balance — the
in-page top row already brands the connection.
- Recent-transactions list scales with `LocalConfiguration.
screenHeightDp` (5 / 4 / 3 / 2 rows by tier) so smaller phones
don't crowd out the balance + Send/Receive controls.
- `BalanceUnit` toggle (sats / ₿ / ⚡) is wired through the
tri-state cycle's SATS branch so the Wallet Settings unit picker
actually changes what the dashboard shows. Symbols rendered in
`onSurfaceVariant` so the number stays the prominent reading.
- Balance container reserves a fixed 96dp min height with vertical-
center arrangement so single-line variants (BITCOIN, LIGHTNING,
FIAT) don't shift the lightning-address pill or Send / Receive
row off their Y as the user cycles modes. Hidden state drops
"tap to reveal" — the asterisks make the action obvious.
Dependencies
- Stacks on top of barrydeen#561 (NWC connect redesign) and assumes barrydeen#562
(BalanceUnit tri-state cycle) merges first. The `WalletBalance
DisplayMode.kt` source file is included here so this PR builds
standalone; the file is identical to barrydeen#562's and will merge cleanly.
3 tasks
The default Spark wallet derives from the user's nsec, so the nsec already serves as the cross-device backup — the "Backup to Nostr Relays" affordance is redundant and noisy alongside the equivalent nsec-based recovery path. Recovery Phrase view is unchanged. Hides the relay backup button + status section for default wallets; non-default wallets keep both, since they have no nsec-derived fallback.
0ec005f to
5de27af
Compare
# Conflicts: # app/src/main/kotlin/com/wisp/app/ui/screen/WalletScreen.kt
5de27af to
12a5b75
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Cross-platform NWC connection backup via NIP-78 kind 30078 — publishes the active NWC URI as a NIP-44 v2 self-encrypted event on every successful connect, and surfaces a one-tap "Restore previous wallet" affordance on the NWC setup screen when an existing backup is found on relays. Implements the contract documented in #560 (`NWC_BACKUP_PARITY.md`) so an NWC connection published from iOS restores on Android and vice versa with no re-paste.
Also bundles wallet-dashboard / settings / mode-picker parity polish that was lost during the conflict resolution between #561 (NWC redesign) and the earlier wallet-setup work on `feat/one-tap-zap` (#556), and ports a few iOS UX fixes that round out the redesign.
Contract (locked decisions from #560)
Dependencies
Stacks on top of #561 (NWC connect screen redesign). Assumes #562 (BalanceUnit tri-state cycle) merges first; the `WalletBalanceDisplayMode.kt` source file is included here so this PR builds standalone but is identical to #562's copy and will merge cleanly.
#560 is the docs companion for this feature and can close in favor of this PR.
Test plan
🤖 Generated with Claude Code