Skip to content

[Refactor] Xpub export: Replace the "coordinator" setting with "xpub_qr_type"#844

Merged
newtonick merged 3 commits intoSeedSigner:devfrom
kdmukai:xpub_export_replace_coordinators
Jan 20, 2026
Merged

[Refactor] Xpub export: Replace the "coordinator" setting with "xpub_qr_type"#844
newtonick merged 3 commits intoSeedSigner:devfrom
kdmukai:xpub_export_replace_coordinators

Conversation

@kdmukai
Copy link
Copy Markdown
Contributor

@kdmukai kdmukai commented Dec 14, 2025

Description

The current xpub export flow prompts the user for which software coordinator they're using. But most wallets that support xpub import have now coalesced around the BCUR crypto-address animated QR format.

So we can change the selection from a specific wallet-based prompt to focus instead on the format, with a strongly opinionated default that suits most cases.


Before:

SettingsEntryUpdateSelectionView_coordinators (1) SeedExportXpubCoordinatorView


After:
SettingsEntryUpdateSelectionView_xpub_qr SeedExportXpubQRFormatView


Design Consideration

I intentionally opted to use the more user-friendly term "animated" along with the "(default)" hint to minimize user confusion. No one is familiar at all with the phrase "BCUR crypto-account".

Unfortunately, in the future we will probably end up with new animated xpub QR formats which may eventually force us to be a bit more nerdy to differentiate them (e.g. "Animated (BCUR)" + "Animated (foo)"). But we'll deal with that when we have to.

And I kept the "Specter legacy" format but left it disabled by default. I doubt it's even used by any actual users anymore. In another year or so we can probably remove that format altogether.


How the formats map

format wallets
BCUR crypto-account Sparrow
Bull Bitcoin
Nunchuk
Specter Desktop (current)
Static BlueWallet
Keeper
Specter legacy Specter Desktop (old)

Other Notes

  • The new xpub_qr_format SettingsEntry was moved into the Advanced section of Settings. In its new form there is much less need for it to be a user-facing configuration (whereas before it would be expected that users would enable/disable which software coordinators they use).

  • test_missing_settings_get_defaults in test_controller.py was removed as it makes more sense as a Settings-specific test. But it was too fragile with too much hard-coding of expected defaults. It was refactored into the new test_settings_defaults in test_settings.py.

  • Multiselect options are vulnerable to the bug identified below. PR [Bugfix] Multiselect settings must have a selection #850 was filed separately to resolve this.


This pull request is categorized as a:

  • Code refactor

Checklist

  • I’ve run pytest and made sure all unit tests pass before submitting the PR

If you modified or added functionality/workflow, did you add new unit tests?

  • N/A

I have tested this PR on the following platforms/os:

Comment thread tests/test_flows_seed.py Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: Comment here should be updated, replacing "coordinator" with "qr_format" or "xpub_qr_format"

Comment thread tests/test_flows_seed.py Outdated
Comment on lines 224 to 233
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: coord_tuple should probably be replaced with something like qr_format_tuple across all occurrences in this test.

Comment thread tests/test_flows_settings.py Outdated
@Chaitanya-Keyal
Copy link
Copy Markdown
Contributor

Chaitanya-Keyal commented Dec 14, 2025

I have a general suggestion here:

With the replacement of the coordinator-based setting by the new xpub QR format setting in this PR, it might make sense to merge it with the existing xpub export enable/disable setting. Having two separate settings entries for what is effectively a single feature could be confusing or misleading for users.

This is especially true if a user has xpub export disabled but still sees a settings entry prompting them to choose between multiple Xpub QR formats. One possible simplification would be to drop the separate xpub export toggle entirely. If all options in the QR format setting are unchecked, that could implicitly indicate that xpub export is disabled.

Comment on lines +833 to 835
for display_name, setting_option in zip(self.settings.get_multiselect_value_display_names(SettingsConstants.SETTING__XPUB_QR_FORMAT), self.settings.get_value(SettingsConstants.SETTING__XPUB_QR_FORMAT)):
button_data.append(ButtonOption(display_name, return_data=setting_option))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

While writing my previous comment, I started wondering what currently happens if all options are unchecked. While testing this, I ran into an IndexError because the loop here doesn’t append anything to the button_data list.

Of course, this is largely user-induced and users wouldn’t deliberately unselect everything. However, this could become a realistic scenario if the mental model I mentioned earlier (unchecked implies disabled) is something other users naturally adopt as well.

This same index error also surfaces in the script type selection view, where users can unselect all available options. It does not occur in the sig type selection view, since that case is constrained to either one option selected or both available, and button_data there is predefined rather than derived from settings.

I think we should ensure that button_data has at least two options before passing it to the screen. If there is only one option, it can be selected by default as it is today. This logic could potentially live in the base ButtonListScreen component, which would simplify several call sites. An empty list could explicitly error, and a single-option list could immediately return that value.

If the list is empty, we have a few options:

  • Prompt the user to first select at least one option in settings.
  • List all available options, effectively treating "none selected" as "all selected" in settings.
  • Treat the "none selected" state (for script type or xpub format) as implicitly disabling xpub export, potentially also updating the setting automatically, although this might get confusing.

All of this likely belongs in a separate PR, but for now I think it would be good to at least ensure that button_data is never empty and that this potential IndexError does not surface through this view.

Apologies for the long comment!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

a single-option list could immediately return that value.

This won't work as we use (maybe mis-use) ButtonListScreen for single "Done" / "I understand" / etc acknowledgment screens.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

All of this likely belongs in a separate PR, but for now I think it would be good to at least ensure that button_data is never empty and that this potential IndexError does not surface through this view.

Yeah, I think multiselect SettingsEntry types can just verify that at least one option is selected when exiting their Settings screen. The three settings related to xpub export are the only ones that are multiselect so far. And they should all require at least one value selected.

But rather than add error-handling code here that will then become unnecessary once the Settings restrictions are in place, I'd prefer to make this PR depend upon the upcoming multiselect PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

see: #850

@kdmukai kdmukai force-pushed the xpub_export_replace_coordinators branch from b8634d1 to b90e3d9 Compare December 16, 2025 22:32
@kdmukai
Copy link
Copy Markdown
Contributor Author

kdmukai commented Dec 16, 2025

it might make sense to merge it with the existing xpub export enable/disable setting.

I had forgotten that we had that option until seeing it recently while working on this PR. I'm not sure there's a use case for deactivating such a core feature and I can't recall the original rationale for adding the option.

@newtonick
Copy link
Copy Markdown
Collaborator

newtonick commented Dec 19, 2025

Did some testing on this PR and this is what I found so far:

  • Blockstream BTC Wallet (Formally Green Wallet)

    • Animated and Static work for Single Sig Segwit (Setup as Jade Watch Only)
    • Could not find a way to do Multisig or P2TR
  • Blue Wallet

    • Animated and Static work
      • Single Sig Segwit
      • Single Sig Nested
      • Multi Sig Segwit
    • Multi Sig Nested did not appear to be supported
    • P2TR did not appear to be supported
  • Nunchuk:

    • Animated works for:
      • Single Sig Segwit
      • Single Sig Nested
      • Multi Sig Segwit
      • Multi Sig Nested
    • Not able to created a P2TR wallet
    • Not able to get static Xpub QR to work
  • Bull Wallet

    • Animated works for:
      • Single Sig Segwit
      • Nested Sig
    • Did not support P2TR
    • Did not see a way to do Multisig
  • Keeper

    • Animated did not work
    • Static works for:
      • Single Sig Segwit
      • Multi Sig Segwit
      • P2TR
  • Zeus:

    • Animated and Static works for:
      • Single Sig Segwit
      • Nested Sig Segwit
      • P2TR
  • Cove:

    • Anmimated worked for Single Sig Segwit
    • Static did not work
    • P2TR and Nested Single Sig did not work
  • Sparrow:

    • Animated and Static work for everything

Comment thread tests/test_settings.py Outdated
"""
settings_name = "Test SettingsQR"
settingsqr_data = f"""settings::v1 name={ settings_name.replace(" ", "_") } persistent=D coords=spa,spd denom=thr network=M qr_density=M xpub_export=E sigs=ss,ms scripts=nat,nes,tr xpub_details=E passphrase=E camera=180 compact_seedqr=E bip85=D priv_warn=E dire_warn=E partners=E"""
settingsqr_data = f"""settings::v1 name={ settings_name.replace(" ", "_") } persistent=D xpub_qr=urca,sta denom=thr network=M qr_density=M xpub_export=E sigs=ss,ms scripts=nat,nes,tr xpub_qr=urca,sta xpub_details=E passphrase=E camera=180 compact_seedqr=E bip85=D priv_warn=E dire_warn=E partners=E"""
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks like xpub_qr=urca,sta got duplicated here by mistake

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

After screwing this up so many times in this PR, I've written #861 to clean up this area.

But rather than create dependencies, each PR can stand on its own. I also didn't want to slow down acceptance of this "coordinator" Settings change.

Copy link
Copy Markdown
Contributor

@Chaitanya-Keyal Chaitanya-Keyal left a comment

Choose a reason for hiding this comment

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

Tested ACK.

  • Verified that all instances of Coordinator have been replaced with Xpub QR Format, along with the associated changes.
  • Verified that the updated tests are valid and all tests pass.
  • Also tested on my raspi and confirmed that the output formats work as expected (Although, this is trivial since there are no internal logic changes).

@newtonick
Copy link
Copy Markdown
Collaborator

tACK and reviewed. This PR is actually less code that I thought it would be to make this change. Most of the code changes were actually in the test suite.

@newtonick newtonick merged commit cf3f941 into SeedSigner:dev Jan 20, 2026
2 checks passed
@newtonick newtonick moved this from 0.8.7 Needs Code Review to 0.8.7 Merged in @SeedSigner Development Board Jan 20, 2026
@newtonick newtonick mentioned this pull request Jan 20, 2026
12 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 0.8.7 Merged

Development

Successfully merging this pull request may close these issues.

3 participants