Skip to content

Add xpub announce UI and peer xpubs display to desktop#287

Merged
kwsantiago merged 3 commits intomainfrom
desktop-xpub-announce
Feb 27, 2026
Merged

Add xpub announce UI and peer xpubs display to desktop#287
kwsantiago merged 3 commits intomainfrom
desktop-xpub-announce

Conversation

@kwsantiago
Copy link
Contributor

@kwsantiago kwsantiago commented Feb 27, 2026

Summary by CodeRabbit

Release Notes

  • New Features
    • Added recovery key announcement feature to the wallet, enabling users to announce extended public keys with fingerprints and optional labels
    • New announcement form with input validation and submission capability
    • Display section for announced recovery keys from other network participants with error handling

@kwsantiago kwsantiago self-assigned this Feb 27, 2026
@coderabbitai
Copy link

coderabbitai bot commented Feb 27, 2026

Warning

Rate limit exceeded

@kwsantiago has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 2 minutes and 45 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 774cd3c and 3c129b9.

📒 Files selected for processing (4)
  • keep-desktop/src/app.rs
  • keep-desktop/src/frost.rs
  • keep-desktop/src/message.rs
  • keep-desktop/src/screen/wallet.rs

Walkthrough

The PR adds an XPub announcement workflow to the Keep desktop application. New message types and state structures enable users to announce recovery keys to a FROST node with fingerprint and label metadata. Event handling merges incoming announced xpubs into the wallet screen state.

Changes

Cohort / File(s) Summary
Message Infrastructure
keep-desktop/src/message.rs
Added 7 new public Message variants for announce workflow: WalletStartAnnounce, WalletAnnounceXpubChanged, WalletAnnounceFingerprintChanged, WalletAnnounceLabelChanged, WalletCancelAnnounce, WalletSubmitAnnounce, and WalletAnnounceResult. Updated Debug formatting for all variants.
Announce Workflow
keep-desktop/src/app.rs, keep-desktop/src/frost.rs
Added AnnounceState export and extended wallet message handling with full announce lifecycle including initialization, field updates, fingerprint sanitization, FROST node submission, and result processing. Added event handling to merge recovery xpubs into peer_xpubs state when XpubAnnounced events are received.
Wallet UI & State
keep-desktop/src/screen/wallet.rs
Added public AnnounceState struct and extended WalletScreen with announce and peer_xpubs fields. Implemented view_announce UI with input fields for xpub, fingerprint, and label. Added Announce Recovery Keys button and peer_xpubs card rendering with conditional display logic.

Sequence Diagram

sequenceDiagram
    actor User
    participant App as App<br/>(Message Handler)
    participant Wallet as Wallet<br/>(UI & State)
    participant FROST as FROST Node
    
    User->>App: WalletStartAnnounce
    App->>Wallet: Initialize AnnounceState
    Note over Wallet: announce = Some(AnnounceState)
    
    User->>App: WalletAnnounceXpubChanged(xpub)
    App->>Wallet: Update announce.xpub
    
    User->>App: WalletAnnounceFingerprintChanged(fp)
    App->>Wallet: Update & sanitize announce.fingerprint
    
    User->>App: WalletAnnounceLabelChanged(label)
    App->>Wallet: Update announce.label
    
    User->>App: WalletSubmitAnnounce
    App->>FROST: Submit AnnouncedXpub
    FROST-->>App: XpubAnnounced event
    App->>Wallet: WalletAnnounceResult(Ok)
    Wallet->>Wallet: Clear announce state
    App->>Wallet: Merge recovery_xpubs → peer_xpubs
    
    Note over Wallet: Display announced xpubs
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 twitches nose excitedly
Keys announce with hoppy flair,
Fingerprints through FROST nodes sail,
Recovery paths we proudly share,
Xpub whispers never fail! 🔐✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately summarizes the main changes: adding xpub announcement UI and peer xpubs display functionality to the desktop application.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch desktop-xpub-announce

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
keep-desktop/src/app.rs (1)

1481-1523: Add defensive validation in submit handler (not just UI).

Message::WalletSubmitAnnounce should reject obviously invalid payloads before calling announce_xpubs, even if the button is normally disabled in the view.

✅ Proposed hardening
             Message::WalletSubmitAnnounce => {
                 let (xpub, fingerprint, label) = if let Screen::Wallet(WalletScreen {
                     announce: Some(a),
                     ..
                 }) = &mut self.screen
                 {
                     a.submitting = true;
                     a.error = None;
                     (
                         a.xpub.trim().to_string(),
                         a.fingerprint.trim().to_string(),
                         a.label.trim().to_string(),
                     )
                 } else {
                     return Task::none();
                 };
+
+                let valid_prefixes = [
+                    "xpub", "tpub", "ypub", "zpub", "upub", "vpub", "Ypub", "Zpub", "Upub", "Vpub",
+                ];
+                let xpub_valid = valid_prefixes.iter().any(|p| xpub.starts_with(p));
+                let fp_valid =
+                    fingerprint.len() == 8 && fingerprint.chars().all(|c| c.is_ascii_hexdigit());
+                if !xpub_valid || !fp_valid {
+                    if let Screen::Wallet(WalletScreen { announce: Some(a), .. }) = &mut self.screen {
+                        a.error = Some("Invalid xpub or fingerprint".into());
+                        a.submitting = false;
+                    }
+                    return Task::none();
+                }
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@keep-desktop/src/frost.rs`:
- Around line 823-827: The current loop that inserts into ws.peer_xpubs at
share_index only checks xpub.xpub and skips already-existing entries, which
prevents metadata updates; modify the logic in the block handling
ws.peer_xpubs.entry(share_index) and the for xpub in recovery_xpubs loop to
perform an upsert: search entry for an existing item where .xpub == xpub.xpub,
and if found update its metadata fields (e.g., label, fingerprint or other
refreshed fields) by assigning them from the incoming xpub, otherwise push the
new xpub into entry; make sure to reference and update the exact struct fields
used elsewhere in the code so UI reflects re-announcements.

In `@keep-desktop/src/message.rs`:
- Around line 539-546: The Debug implementation is currently exposing sensitive
user-entered metadata for the enum variants WalletAnnounceFingerprintChanged and
WalletAnnounceLabelChanged; update the Debug branch for those variants in the
Debug impl so they do not print the raw fp or l values (e.g., emit a constant
redacted placeholder like "<redacted>" or a masked representation such as
showing only length/last 4 chars) instead of .field(fp) / .field(l), ensuring
other variants remain unchanged and the enum name still appears in the debug
output.

In `@keep-desktop/src/screen/wallet.rs`:
- Around line 603-605: The code constructs truncated via byte-slicing
xpub.xpub[..32], which can panic on UTF-8 multibyte characters; change the logic
that builds truncated (the truncated variable using xpub.xpub) to operate on
characters instead of bytes: check character count with
xpub.xpub.chars().count() and build the prefix with
xpub.xpub.chars().take(32).collect::<String>(), then append "..." when
truncated, ensuring you return the original string when not truncated.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 17da874 and 774cd3c.

📒 Files selected for processing (4)
  • keep-desktop/src/app.rs
  • keep-desktop/src/frost.rs
  • keep-desktop/src/message.rs
  • keep-desktop/src/screen/wallet.rs

@kwsantiago kwsantiago merged commit a55972a into main Feb 27, 2026
9 checks passed
@kwsantiago kwsantiago deleted the desktop-xpub-announce branch February 27, 2026 03: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