fix(bitbox): explain an unseeded device instead of looping#724
Merged
Conversation
A BitBox paired without a wallet set up (no seed) cannot derive an ETH address. The empty address read failed as a generic error and bounced the user into the silent re-scan loop with no explanation, so a brand-new device was effectively unusable with no hint why. After pairing, read the device's firmware status via the new bitbox_flutter getDeviceStatus and, when it reports `uninitialized`, emit a dedicated BitboxNotInitialized state that tells the user to set up or restore a wallet on the device first. The state offers a retry that re-checks the status without re-pairing and, crucially, does not arm the re-scan timer, so the device is no longer picked up and re-paired in a loop. Only `uninitialized` is treated as "no wallet"; other non-ready statuses keep the existing path. Temporarily pins bitbox_flutter to the fix branch; moves to the v0.0.9 tag once the plugin PR is merged and tagged.
7 tasks
Resolves the pubspec conflict from #723 (bump to v0.0.9, 16 KB alignment). Keeps the dependency pinned to the bitbox_flutter fix branch — which now carries BOTH the 16 KB alignment (merged from #30) and the new getDeviceStatus — at the updated commit. Moves to the v0.0.10 tag once the plugin PR lands.
Harden the new unseeded-device check so it can only ever ADD the dedicated "not set up" path, never break a device that would otherwise pair. The status read is wrapped so any failure or unexpected value falls through to the normal acquire path (the exact pre-change behaviour); only a clean, explicit `uninitialized` read diverts to BitboxNotInitialized. Adds a regression test asserting a throwing status read still reaches BitboxConnected.
Contributor
Author
|
Held as Draft pending: (1) plugin #29 merge + v0.0.10 tag, after which the pin moves from the fix branch to |
The status read is a local cached lookup, but it was the only device-facing call in the pairing path without a timeout. Cap it at 5s; on timeout the read is treated as "not uninitialized" (fail-open via the existing catch), so a hypothetical stall can never hang an otherwise-working pairing.
The plugin PR landed and tagged v0.0.10 (carries getDeviceStatus + the 16 KB alignment). Replaces the temporary fix-branch pin with the released tag.
A local pub get had downgraded SDK-pinned transitives (matcher, test, ...). Reset the lockfile to the staging baseline so the only delta is the bitbox_flutter v0.0.9 -> v0.0.10 bump.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Connecting a brand-new BitBox that has no wallet set up (no seed) left the user stuck. Pairing succeeds, but the device has no seed to derive an ETH address from, so
getETHAddresscomes back empty. That empty read failed as a generic error →BitboxNotConnected→ a SnackBar "something went wrong" → and because the re-scan timer is re-armed, the device is immediately found again and the user is walked through the pairing code → fail → SnackBar loop, with no hint that the real problem is simply an un-set-up device.(The earlier fix #710 stopped the empty address from being persisted — no more grey screen — but did not distinguish "no seed" from a transient empty read.)
What changed
After channel-hash verify, read the device's firmware status via the new
bitbox_fluttergetDeviceStatus()(cached read, no device round-trip). When it reportsuninitialized, emit a dedicatedBitboxNotInitializedstate that explains the user must set up / restore a wallet on the device first.recheckDeviceStatus) that re-reads the status — if the user has since set up a wallet, the connection continues without re-pairing.uninitializedis treated as "no wallet". Other non-ready statuses (e.g. firmware-upgrade-required) intentionally keep the existing failure path rather than being mislabelled.The address-derivation/observe/sign tail of
confirmPairingwas extracted into_acquireWalletAndConnect()so the initial flow and the retry share one path.Dependency
Requires
bitbox_fluttergetDeviceStatus()from DFXswiss/bitbox_flutter#29. This PR temporarily pins the plugin to that fix branch; it will be moved to thev0.0.9tag once #29 is merged and tagged. Kept as Draft until then.Test plan
flutter analyze— clean (only the pre-existing generated-i18n.dartwarning)flutter test— bitbox cubit / service / view suites all greenBitboxNotInitialized, no wallet created, no re-scan loop (state stays stable); retry continues once seeded; retry stays while still unseeded; no-op off-stategetDeviceStatuspass-through via the simulatorBitboxNotInitializedrenders retry + cancel; retry callsrecheckDeviceStatusde/enARBs (case-sensitive ASCII order), regenerated