Skip to content

Sync upstream (0.8.7)#371

Open
3rdIteration wants to merge 294 commits into
devfrom
sync-upstream-dev
Open

Sync upstream (0.8.7)#371
3rdIteration wants to merge 294 commits into
devfrom
sync-upstream-dev

Conversation

@3rdIteration

Copy link
Copy Markdown
Owner

Description

Describe the change simply. Provide a reason for the change.

Include screenshots of any new or modified screens (or at least explain why they were omitted)

This pull request is categorized as a:

  • New feature
  • Bug fix
  • Code refactor
  • Documentation
  • Other

Checklist

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

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

  • No, I’m a fool
  • Yes
  • N/A

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

Note: Keep your changes limited in scope; if you uncover other issues or improvements along the way, ideally submit those as a separate PR. The more complicated the PR the harder to review, test, and merge.

SeedSigner and others added 30 commits June 30, 2025 15:59
Update instances of 0.8.5 to 0.8.6
[Enhancement] Add support for BBQr PSBT decoding
Update encode_qr.py - Adds comments to code (Fixes SeedSigner#582)
Resolves issue 678 - Clean up else condition to catch ALL remaining possibilities
…r-docs

[Documentation] Clarify that SeedQR uses English BIP39 wordlist
[CI Fix] Modify CI to run test checks on all commits
…ng-software-docs

[Documentation] Mention `--ignore-missing` flag issue on older macOS versions
…ing-spinner

[Feature] Added 'Calculating...' spinner while generating seed from Image Entropy
Use PyPI version for urtypes lib
[l10n] Move Italian to the "Fully supported languages" list
[l10n] Remove libraqm workarounds and enforce libraqm dependency
Co-authored-by: notTanveer <101289209+notTanveer@users.noreply.github.com>
Disables the screensaver entirely while the SeedQR transcription routine is active. Any view can be configured to allow or disallow screensaver activation.
…s when the current view is SeedTranscribeSeedQRZoomedInView
newtonick and others added 17 commits June 9, 2026 22:09
…ranslations-submodule

Update seedsigner-translations submodule to latest dev (708961)
[Bugfix] Back Navigation in Seed Entry Views
Add pythonpath=["src"] to pyproject.toml and remove redundant pip install . from CI workflow. Rework view imports and exports so internal helpers (including underscore-prefixed symbols and shared TextQR/BIP85 helpers) are explicitly re-exported from tools_views for backward compatibility. Propagate shared helpers across gpg_views, password_generator_views, and smartcard_views (also fix a logging call and add hmac, seedkeeper utils, and seed-related imports). Update tests to patch the appropriate modules (smartcard_views and password_generator_views) so monkeypatches target the modules that actually import the helpers.
Add a Testing guidance section to AGENTS.md describing how to run pytest, expected platform-dependent failures, a star-import caveat for underscore-prefixed names, and guidance for adding tests. Re-export _check_future_key_creation from gpg_views in tools_views.py for backward compatibility with tests and callers. Update tests/test_gpg_message.py: improve _msys2_path to detect the installed gpg via shutil.which and only convert Windows paths to MSYS2 style when the GPG binary is from Git-for-Windows/MSYS2, leaving native Gpg4win paths unchanged to avoid writable keyring errors.
Define a MIN_RSA_KEY_BITS = 2048 constant in gpg_views.py (used by bip85_rsa_from_root) to enforce a minimum RSA key size. Update AGENTS.md to refresh the test table (clarify satochip test entry) and adjust the baseline test counts to 716 passing, 134 skipped, 7 failing, noting satochip tests require physical hardware.
Add missing imports and helpers to smartcard_views: binascii (hexlify/unhexlify), embit.descriptor.Descriptor, and embit_utils plus XprvSeed from models. Also reorder/clean imports and expose SeedExportXpubVerifyAddressView. Update unit test to patch HDKey in the smartcard_views module instead of tools_views to match the refactor. These changes prepare the smartcard view code for using embit utilities and the Xprv-backed seed model.
Refactor tests/test_bip85_gpg.py to import and reference seedsigner.views.gpg_views rather than the older tools_views alias. Update monkeypatch.setattr targets, class instantiations, and BIP85_DATA assertions to use gpg_views. Add seed_bytes attribute to test SeedObj classes and make a few related minor adjustments (imports and subprocess/microsd references) to ensure tests target the correct module.
Add multiple .cap applet binaries under javacard-cap/ to ship built applets. Refactor smartcard views: move the GlobalPlatform presence check into the BUILD_APPLETS path and show a clear warning when DIY tools are not available. Rewrite ToolsDIYInstallAppletView to gather .cap files from both the internal repo and the MicroSD javacard-cap directory, merge results, prefix duplicate names with (Internal)/(MicroSD) to disambiguate, and handle missing/unreadable MicroSD gracefully. Also add a docstring and improve selection logging.
Add a new javacard-cap/javacard-cap.sha256 manifest containing SHA256 sums for various CAP files. Update smartcard_views.py to detect the DIY toolchain by checking for the ANT executable path (ant/bin/ant) instead of looking for gp.jar, with host-specific path locations adjusted accordingly and the existence check updated to use the ant path.
Extracts the internal javacard-cap path into a module-level _get_internal_cap_dir() function and updates ToolsDIYInstallAppletView to use it. Tests updated to monkeypatch this helper (and adjust the logger target) so the test suite can isolate from the real filesystem. No behavioral change beyond making the internal cap directory retrieval testable.
# Conflicts:
#	.github/workflows/telegram.yml
Add robust validation and normalization for Settings QR parsing and multiselect handling (reject empty values, validate against selection_options, support free-text fields, handle legacy formats and restore-default cases). Add new XPUB QR format setting entry. Introduce optional import for pivideostream on platforms where it's available. Add a BaseDisplayDriver and small cleanup in ST7789 driver docstrings. Fix restart logic to call subprocess.call (and import subprocess). Make descriptor views handle single-sig descriptors (show "Single sig" instead of multisig policy). Update tests to flush deferred settings saves to disk before asserting file contents.
Copilot AI review requested due to automatic review settings June 15, 2026 11:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR syncs the SeedSigner codebase to upstream release 0.8.7, including substantial UI wording/i18n updates, new/updated QR and settings behaviors, expanded flow tests, and several infrastructure/documentation changes.

Changes:

  • Adds/extends QR handling (e.g., BBQR PSBT support) and updates xpub-export QR format behavior/settings.
  • Introduces/updates UI flows and screens (e.g., MicroSD removal blocking flow, screensaver gating, refined PSBT/transaction wording).
  • Updates tests, CI/config, and documentation/templates to match upstream structure and conventions.

Reviewed changes

Copilot reviewed 73 out of 89 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
tests/test_settingsqr_decoder.py Refactors SettingsQR decoder test to reuse a shared SettingsQR base.
tests/test_settings.py Adds tests for defaults, persistence load, and multiselect empty handling; introduces SettingsQRBase.
tests/test_settings_definition.py Adjusts imports for updated test needs.
tests/test_seedqr.py Sets ambiguous-QR preference during CompactSeedQR decode tests.
tests/test_seedkeeper_install.py Updates monkeypatching targets after view/module splits.
tests/test_password_generator_views.py Patches split module import site for dice entropy screen.
tests/test_javacard_mnemonic_tools.py Patches both tools_views and smartcard_views after module split.
tests/test_gpg_message.py Improves Windows GNUPG path handling for MSYS2 vs native GPG.
tests/test_flows.py Adds RemoveMicroSDWarning flow test and updates imports/wording.
tests/test_flows_view.py Updates flow tests for camera error view and import changes.
tests/test_flows_settings.py Updates multiselect flow behavior and SettingsQR constants.
tests/test_flows_seed.py Updates seed flows for xpub QR format selection and adds additional navigation tests.
tests/test_encodepsbtqr.py Updates encoder class name for Specter legacy xpub QR encoding.
tests/test_embit_utils.py Adds tests for multisig policy extraction and improves wording.
tests/test_controller.py Updates SettingsConstants import location and default assertions.
tests/test_bip85_gpg.py Updates patch targets to gpg_views and related module splits.
tests/screenshot_generator/utils.py Adds screenshot-generator renderer flags and mock context manager support.
tests/base.py Updates test environment mocking to accommodate new modules/features.
src/seedsigner/views/view.py Adds camera-specific error view and MicroSD removal warning view; UI wording tweaks.
src/seedsigner/views/settings_views.py Adds blocking/unblocking navigation logic for setting selection flow.
src/seedsigner/views/seed_views.py Large set of flow/UI changes including xpub export flow changes and screensaver gating.
src/seedsigner/views/screensaver.py Switches splash animation behavior based on screenshot-generator detection.
src/seedsigner/views/scan_views.py Updates PSBT scan wording and unknown QR exit button wording.
src/seedsigner/views/psbt_views.py Renames PSBT terminology to “transaction” across flow and screen strings; minor grammar fixes.
src/seedsigner/models/settings.py Tightens SettingsQR parsing/validation and multiselect normalization; persistence behaviors.
src/seedsigner/models/settings_definition.py Reworks constants/settings entries (xpub QR format setting, MicroSD toast timer, locale detection changes).
src/seedsigner/models/qr_type.py Adds BBQR PSBT QR type.
src/seedsigner/models/psbt_parser.py Adds missing fingerprint fill logic and minor refactors.
src/seedsigner/models/encode_qr.py Renames Specter xpub encoder to legacy and adds alias for compatibility; comments added.
src/seedsigner/models/decode_qr.py Adds BBQR PSBT decoder and segment-type detection; adds debug logging.
src/seedsigner/helpers/embit_utils.py Adds multisig policy extraction helper; minor comment cleanup.
src/seedsigner/hardware/displays/ST7789.py Adds BaseDisplayDriver and documentation tweaks.
src/seedsigner/hardware/displays/st7789_mpy.py Adjusts class definition/inheritance for display driver refactor.
src/seedsigner/hardware/displays/ili9341.py Adjusts class definition/inheritance and renames invert arg for clarity.
src/seedsigner/hardware/displays/display_driver.py Refactors display driver selection/initialization logic.
src/seedsigner/hardware/camera.py Introduces CameraConnectionError and expands cross-platform camera abstraction.
src/seedsigner/hardware/init.py Attempts optional import of pivideostream for platform flexibility.
src/seedsigner/gui/toast.py Adjusts toast rendering behavior and default MicroSD toast duration.
src/seedsigner/gui/screens/tools_screens.py Minor bbox variable name fix and descriptor text cleanup.
src/seedsigner/gui/screens/settings_screens.py Adjusts selection screen behavior for screenshots and checked-selection defaults.
src/seedsigner/gui/screens/seed_screens.py Removes passphrase-related UI variants and adjusts wording/translation notes.
src/seedsigner/gui/screens/screen.py Adds ButtonOptionWithoutTranslation, refines keyboard title updates, and removes some unused screens/flags.
src/seedsigner/gui/screens/scan_screens.py Refactors scan loop and return semantics for cancel behavior.
src/seedsigner/gui/screens/psbt_screens.py Renames PSBT terminology and refines change/receive address display.
src/seedsigner/gui/renderer.py Adds screenshot-generator detection property.
src/seedsigner/gui/keyboard.py Removes unused key definitions/fields and simplifies keyboard input signature.
src/seedsigner/controller.py Adds raqm availability warning, import timing tweaks, and screensaver gating property.
README.md Updates wording and release version references for downloads/verification.
pyproject.toml Bumps version to 0.8.7; updates coverage omit list and pytest pythonpath.
l10n/requirements-l10n.txt Adds setuptools requirement for l10n tooling.
l10n/messages.pot Updates translation template strings and copyright year.
javacard-cap/javacard-cap.sha256 Adds checksums for bundled CAP files.
docs/usb_relay.md Improves formatting, code fences, and wording for USB relay instructions.
docs/seed_qr/README.md Clarifies SeedQR assumptions (English wordlist) and improves explanations.
docs/raspberry_pi_os_build_instructions.md Updates USB/WiFi wording and static IP instructions.
docs/qr_formats.md Improves formatting and wording; clarifies supported formats.
docs/legacy_hardware.md Fixes typos and improves clarity.
docs/feature_roadmap.md Fixes wording and formatting.
docs/electrum.md Standardizes title/casing and improves clarity.
docs/dice_verification.md Fixes typos and improves clarity of verification steps.
docs/developer_tips.md Improves instructions formatting and clarity.
docs/debug_crash.md Improves formatting and step clarity.
docs/code_structure.md Improves MVC description and wording.
AGENTS.md Adds explicit test-running guidance and notes on module split caveats.
.github/workflows/tests.yml Adjusts CI triggers and removes pip install . step.
.github/workflows/telegram.yml Removes Telegram notification workflow.
.github/pull_request_template.md Replaces PR template with more structured checklist and sections.
Comments suppressed due to low confidence (4)

src/seedsigner/controller.py:22

  • controller.py now imports SettingsConstants from both seedsigner.models.settings and seedsigner.models.settings_definition. The second import overwrites the first, making the added import redundant/confusing and easy to break during future refactors.
from seedsigner.models.settings import Settings
from seedsigner.models.settings import SettingsConstants
from seedsigner.models.singleton import Singleton
from seedsigner.models.threads import BaseThread
from seedsigner.models.settings_definition import SettingsConstants
from seedsigner.views.screensaver import ScreensaverScreen

src/seedsigner/views/seed_views.py:2362

  • SeedExportXpubCustomDerivationView routes to SeedExportXpubQRFormatView, but that class does not exist in this file (the selection view class is still SeedExportXpubCoordinatorView). As-is, this will raise NameError when exporting an xpub with a custom derivation path.
    src/seedsigner/views/seed_views.py:2459
  • SeedExportXpubWarningView.run() passes xpub_qr_format in view_args when routing to SeedExportXpubDetailsView, but SeedExportXpubDetailsView.__init__ still expects coordinator (and will raise TypeError: __init__ got an unexpected keyword argument 'xpub_qr_format').
    src/seedsigner/views/seed_views.py:2560
  • When routing from SeedExportXpubDetailsView to SeedExportXpubQRDisplayView, the view_args key was changed to xpub_qr_format, but SeedExportXpubQRDisplayView.__init__ still expects coordinator. This will raise TypeError and break the xpub export flow.

Comment on lines 22 to 41
def __init__(self, display_type: str = DISPLAY_TYPE__ST7789, width: int = None, height: int = None):
if display_type not in ALL_DISPLAY_TYPES:
raise ValueError(f"Invalid display type: {display_type}")
self.display_type = display_type

if self.display_type == DISPLAY_TYPE__ST7789:
if display_type == DISPLAY_TYPE__ST7789:
if width not in [240, 320] or height != 240:
raise ValueError("ST7789 display only supports 240x240 or 320x240 resolutions")

if width == 240:
# TODO: For now the original ST7789 driver has to be used for 240x240.
# The mpy version below renders incorrectly (almost like each row of pixels
# is one pixel short, so the entire screen exhibits a diagonal skew).
from seedsigner.hardware.displays.ST7789 import ST7789
self.display = ST7789()
from seedsigner.hardware.displays.ST7789 import ST7789 as original_ST7789
return original_ST7789(_width=width, _height=height)

elif width == 320:
from seedsigner.hardware.displays.st7789_mpy import ST7789
from seedsigner.hardware.displays.st7789_mpy import ST7789 as mpy_ST7789
# Have to swap width and height; screen is natively 240x320
self.display = ST7789(width=height, height=width)

Comment on lines 48 to +52
elif self.display_type == DISPLAY_TYPE__ILI9341:
from seedsigner.hardware.displays.ili9341 import ILI9341
self.display = ILI9341()
self.display.begin()
display = ILI9341(_width=width, _height=height)
display.begin()
return display
Comment on lines +235 to 238
@dataclass
class ST7789(BaseDisplayDriver):
"""
ST7789 driver class
Comment on lines +138 to 140
@dataclass
class ILI9341(BaseDisplayDriver):
"""Representation of an ILI9341 TFT LCD."""
Comment thread tests/base.py
Comment on lines 12 to +18
sys.modules['seedsigner.hardware.buttons'] = MagicMock()
sys.modules['seedsigner.hardware.camera'] = MagicMock()
sys.modules['seedsigner.hardware.camera.Camera'] = MagicMock()
# Only mock pivideostream if the real module is unavailable (it's needed for luckfox camera tests)
try:
__import__("seedsigner.hardware.pivideostream")
except ImportError:
sys.modules['seedsigner.hardware.pivideostream'] = MagicMock()
Comment on lines 2567 to 2593
class SeedExportXpubQRDisplayView(View):
def __init__(self, seed_num: int, coordinator: str, derivation_path: str, sig_type: str = SettingsConstants.SINGLE_SIG, script_type: str = SettingsConstants.NATIVE_SEGWIT, coordinator_label: str = ""):
super().__init__()
self.seed = self.controller.get_seed(seed_num)
self.seed_num = seed_num
self.script_type = script_type
self.sig_type = sig_type
self.derivation_path = derivation_path
self.coordinator_label = coordinator_label

encoder_args = dict(
seed=self.seed,
derivation=derivation_path,
network=self.settings.get_value(SettingsConstants.SETTING__NETWORK),
qr_density=self.settings.get_value(SettingsConstants.SETTING__QR_DENSITY),
sig_type=sig_type
)

if coordinator == SettingsConstants.COORDINATOR__SPECTER_DESKTOP:
self.qr_encoder = SpecterXPubQrEncoder(**encoder_args)

elif coordinator in [SettingsConstants.COORDINATOR__BLUE_WALLET,
SettingsConstants.COORDINATOR__KEEPER]:
if xpub_qr_format == SettingsConstants.XPUB_QR_FORMAT__STATIC:
self.qr_encoder = StaticXpubQrEncoder(**encoder_args)

elif xpub_qr_format == SettingsConstants.XPUB_QR_FORMAT__SPECTER_LEGACY:
self.qr_encoder = SpecterLegacyXPubQrEncoder(**encoder_args)

else:
# Default: UR crypto-address
self.qr_encoder = UrXpubQrEncoder(**encoder_args)
Comment on lines +384 to +392
# If this selection view was opened from a blocking flow (e.g. RemoveMicroSDWarningView),
# prevent navigation away until the setting actually changes. If it hasn't changed,
# return to the blocking view so it can re-evaluate the state.
if self.blocking_view:
current_value = self.settings.get_value(self.settings_entry.attr_name)
if current_value == initial_value:
return Destination(self.blocking_view, clear_history=True)
elif self.unblocking_view:
return Destination(self.unblocking_view, clear_history=True)
Comment on lines +545 to +553
elif button_data[selected_menu_num] == self.SETTINGS:
from seedsigner.views.settings_views import SettingsEntryUpdateSelectionView
return Destination(
SettingsEntryUpdateSelectionView,
view_args=dict(
attr_name=SettingsConstants.SETTING__MICROSD_TOAST_TIMER,
blocking_view=RemoveMicroSDWarningView,
unblocking_view=MainMenuView
)
Comment on lines +440 to +446
# Treat empty/invalid multiselect values as "restore defaults"
current_val = new_settings[entry.attr_name]
if isinstance(current_val, list):
# Filter out empty strings and whitespace-only entries
cleaned = [v for v in current_val if isinstance(v, str) is False or v.strip()]
if len(cleaned) == 0:
new_settings[entry.attr_name] = entry.default_value
Comment thread src/seedsigner/models/settings.py Outdated
Comment on lines +296 to +301
# Validate that the value is a recognized option for this setting
if settings_entry.type != SettingsConstants.TYPE__MULTISELECT:
if isinstance(value, list):
raise InvalidSettingsQRData(f"Setting {settings_entry.attr_name} does not accept multiple values")
if value not in valid_values:
raise InvalidSettingsQRData(f"Unrecognized option '{value}' for setting {settings_entry.attr_name}")
Add `from embit.psbt import PSBT` to src/seedsigner/models/encode_qr.py and src/seedsigner/views/smartcard_views.py to enable PSBT handling in QR encoding and smartcard view code paths. Prepares these modules to work with PSBT objects for transaction-related functionality.
Rename and centralize XPUB QR format handling into a "coordinator" concept across seed and smartcard views. seed_views: replace xpub_qr_format variables with coordinator, switch to SETTINGS__XPUB_QR_FORMAT/ALL_XPUB_QR_FORMATS, and use SpecterXPubQrEncoder for the Specter format; adjust QR display and navigation arguments accordingly. smartcard_views: iterate ALL_XPUB_QR_FORMATS and check SETTING__XPUB_QR_FORMAT. settings_views: add a guard to keep the settings menu on-screen for invalid selections and add blocking_view/unblocking_view attributes to SettingsEntryUpdateSelectionView. Update tests to reflect the view and setting renames and the changed behavior. These changes unify naming, prevent invalid selection crashes, and update encoders for the new coordinator model.
Validate comma-separated multiselect values from Settings QR data: accept non-empty strings, split on commas, and verify each option against allowed values (conversion to list happens later in TYPE__MULTISELECT handling).

Also extend SettingsEntryUpdateSelectionView to accept and persist blocking_view/unblocking_view parameters, return to the blocking view on BACK, and propagate these parameters when reinvoking the view so blocking flows are preserved.
- Restore special case for persistent_settings=E when only D is allowed
  (SD card removed), silently coercing to DISABLED instead of raising.
- Add screen mocks and fix redirect flags in SeedQR transcribe flow tests.
…seScreen._run()

The _run() loop always started with the lowercase letter keyboard regardless of which keyboard was rendered initially, causing arrow key navigation to operate on a hidden letter overlay instead of the visible digits keyboard.

Also pass initial_keyboard='123' to all PIN/PUK entry screens so they start on digits.
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.