Skip to content

Show the nostr pubkey in both encodings, not just npub - #6

Merged
nothing-stops-this-train merged 1 commit into
mainfrom
fix/show-hex-pubkey-alongside-npub
Jul 28, 2026
Merged

Show the nostr pubkey in both encodings, not just npub#6
nothing-stops-this-train merged 1 commit into
mainfrom
fix/show-hex-pubkey-alongside-npub

Conversation

@nothing-stops-this-train

Copy link
Copy Markdown
Owner

The report

The npub shown in the swapserver gui doesn't match the address shown when a
user clicks "swap" and sees swap providers.

Nothing was actually wrong — they are the same key in two encodings, which
look nothing alike:

Where Encoding Looks like
Swap Server tab (before this PR) bech32 NIP-19 npub1hdd8atxxf9tz284ecgqjpe3eht… (63 chars)
Choose Swap ProviderPubkey column raw hex bb5a7eacc64956251eb9c20120e639ba… (64 chars)

swap_dialog.py sets that column to SwapOffer.server_pubkey — the raw hex
event.pubkey off the nostr event — and keeps the npub only as hidden item
data (ROLE_NPUB), where it is used as the return value and written to
SWAPSERVER_NPUB. It is never rendered. Verified rather than assumed: the npub
decodes back to exactly the hex the provider list displays.

The change

Showing one encoding alone reasonably reads as "the GUI is displaying the wrong
key", so the identity box now shows both, each independently copyable, with a
dimmed one-liner explaining the relationship:

┌─ Nostr identity ────────────────────────────────────┐
│ ■  npub:  npub1hdd8atxxf9tz284ecgqjpe3ehtuc7…  [Copy] │
│    hex:   bb5a7eacc64956251eb9c20120e639baf9…  [Copy] │
│           Same key, two encodings. Takers list hex.   │
└──────────────────────────────────────────────────────┘

The hex was previously only in a tooltip, which is easy to miss.

The identicon is unchanged and remains the fastest visual check that a provider
entry is your server: both sides derive it from the hex via
pubkey_to_q_icon, so the coloured square matches.

Note found while testing

Feeding an npub to pubkey_to_q_icon is not merely a different colour — it is a
hard error, because pubkey_to_rgb_color asserts len == 64. A refactor that
passed the wrong form would crash rather than silently mismatch. There is now a
test pinning that behaviour.

Tests

163 total, green with and without PyQt6 (19 Qt tests, which skip cleanly when it
is absent). New coverage asserts the two rows cannot drift apart:

  • the displayed npub must decode back to the displayed hex;
  • that hex must equal keypair.pubkey.hex()[2:], the exact value
    SwapOffer.server_pubkey carries;
  • the hex Copy button copies the hex, not the npub;
  • the identicon is derived from the hex;
  • a wallet with no nostr key blanks both rows and makes copying a no-op rather
    than pasting an empty string.

🤖 Generated with Claude Code

https://claude.ai/code/session_013zETFC6MhnsCuxvQDGxqV5

The Swap Server tab showed only the bech32 npub, while Electrum's "Choose Swap
Provider" dialog lists the raw hex: swap_dialog.py sets the Pubkey column to
SwapOffer.server_pubkey (== event.pubkey) and keeps the npub only as hidden
item data, used as the return value and stored in SWAPSERVER_NPUB.

Same key, two encodings -- but they look nothing alike, so an operator
comparing the tab against a taker's provider list reasonably concludes the GUI
is displaying the wrong key.

The identity box now has an npub row and a hex row, each independently
copyable, plus a one-line note that takers list the hex form. The hex was
previously only in a tooltip, which is easy to miss.

The identicon is unchanged and remains the fastest check: both sides feed the
*hex* into pubkey_to_q_icon, so the coloured square beside the npub matches the
one beside this server in a taker's list. (Passing an npub there is not a
different colour but an outright error -- pubkey_to_rgb_color asserts len 64 --
which a new test pins down.)

Tests: both encodings render and stay in sync (the npub must decode back to the
displayed hex, and the hex must equal keypair.pubkey.hex()[2:], the value
SwapOffer.server_pubkey carries), the hex Copy button copies the hex, the
identicon is derived from the hex, and a wallet with no nostr key blanks both
rows and makes copying a no-op rather than pasting an empty string.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013zETFC6MhnsCuxvQDGxqV5
@nothing-stops-this-train
nothing-stops-this-train merged commit 8fad059 into main Jul 28, 2026
1 check passed
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