Skip to content

Hardware wallet connection reliability and UX polish #1030

Description

@ovitrif

Part of #998.

Automated emulator/E2E coverage has been split to #1038. This issue tracks runtime reliability and UX polish for the hardware-wallet flows.

Scope

Polish and harden hardware-wallet connection UX after the initial flows:

  • Improve reconnection reliability.
  • Optimise how often Bitkit pings the Trezor device; repeated pings can currently keep the device busy and prevent the user from unlocking it.
  • Improve pairing-code and PIN retry UX so wrong-code / device-confirmation states do not read as indefinite loading.
  • Handle passphrase-enabled Trezor wallets explicitly and safely.

Passphrase-enabled wallets

Passphrase-enabled Trezors need a deliberate UX and persistence model rather than accidentally inheriting state from another Trezor session.

  • Decide the user-facing model for pairing a passphrase-enabled device:
    • default to the standard wallet unless the user explicitly chooses a hidden/passphrase wallet;
    • if hidden wallets are supported in this flow, provide an explicit prompt/step for host-entered passphrase and/or on-device passphrase entry instead of silently reusing prior TrezorUiHandler state.
  • Treat the standard wallet and each hidden/passphrase wallet as separate hardware-wallet identities when their watched account xpubs/descriptors differ.
  • Ensure the paired record, label, walletId, activity metadata, and removal behavior all stay scoped to the selected wallet identity, not just the physical Trezor device.
  • Reconnect and Transfer to Spending must reconnect/sign with the same wallet identity the user paired; they must not fall back to another hidden wallet or accidentally sign from the standard wallet.
  • Never persist or log raw passphrases. Clear any cached host passphrase / wallet selection on cancel, disconnect, removal, and sheet dismissal unless the current session still intentionally needs it.

Pairing-code / PIN retry UX

Improve user-facing states while the device is waiting for code entry, device confirmation, or retry after a wrong code.

  • For THP pairing-code retry: when the user enters a wrong 6-digit pairing code and the Trezor asks for device confirmation / shows a new code, Bitkit should stop looking like a generic spinner-only loading state. Show explicit copy such as "Confirm on your Trezor and enter the new code" and reset the input when a new code is requested.
  • Investigate whether repeated needsPairingCode transitions are enough to model THP pairing-code retry in the app, or whether bitkit-core should expose a typed pairing-code retry / invalid-code signal.
  • For Trezor PIN retry: consume the typed PIN failure support from fix: surface typed trezor pin failures bitkit-core#105 once released, especially TrezorError.InvalidPin, so Bitkit can clear the submitted state, show "Incorrect PIN. Try again.", and allow deliberate retry without reconnect churn.
  • Keep PIN/pairing-code retry handling aligned with the device-busy/backoff rules below so retries do not trigger background reconnects, feature refreshes, or new transport opens while the Trezor is mid-flow.

Device-state / ping-cadence follow-ups

Use the current Trezor lock-state/busy-state work to avoid touching the device while it is waiting for the user.

  • Treat needsPinEntry, needsPairingCode, isConnecting, isAutoReconnecting, and features.pinProtection == true && features.unlocked == false as device-busy/backoff states. While any of these are true, Bitkit should not auto-reconnect, refresh features, or open a new transport unless the user explicitly requests it.
  • Use cached device state for UI status (trezorGetFeatures() / repo state) wherever possible. Reserve device-touching calls such as trezorRefreshFeatures(), trezorConnect(), and scans for explicit user actions or a controlled reconnect path.
  • When native transport open/read/write/call-message detects the Trezor is busy or already in an active handshake, return the structured callback busy code from bitkit-core instead of closing and reopening the connection.
  • For BLE/USB duplicate openDevice calls while a connection or handshake is already active, return busy/backoff rather than calling closeDevice(path) and creating a fresh session.
  • Ensure auto-reconnect retry loops are single-flight and cancel/skip attempts while the user is entering PIN or pairing code; repeated delayed attempts must not restart PIN entry.

Trezor logging

Reconsider the dedicated Trezor logging path so QA and device-debug captures do not require a second log source. Trezor-related repo, service, transport, bridge, and signing logs should be visible in the same app log file as normal Bitkit and LDK logs, similar to the existing ldk-node logging integration.

  • Audit current TrezorDebugLog and Trezor-specific logger usage and decide whether it should be removed, wrapped, or forwarded through the normal app Logger.
  • Ensure Trezor connection, reconnect, BLE/USB transport, bridge, pairing, PIN, and signing diagnostics are captured by the app log file used for support/QA debugging.
  • Keep sensitive values out of logs, including passphrases, PINs, pairing codes, private keys, and raw signing payloads; log only safe identifiers and state transitions.

Related work

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No fields configured for Task.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions