Skip to content

Commit 5088aad

Browse files
committed
fix: skip auto-reconnect during live hw handshake
1 parent ff9d4b9 commit 5088aad

2 files changed

Lines changed: 46 additions & 2 deletions

File tree

app/src/main/java/to/bitkit/repositories/TrezorRepo.kt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,12 @@ class TrezorRepo @Inject constructor(
486486
fun hasKnownDevices(): Boolean = _state.value.knownDevices.isNotEmpty()
487487

488488
suspend fun autoReconnect(walletIndex: Int = 0): Result<TrezorFeatures> = withContext(ioDispatcher) {
489+
if (isConnectInProgress()) {
490+
// A live handshake looks like a stale session (transport connected,
491+
// features pending), so resetting here would drop the session the
492+
// user is entering their PIN or pairing code into.
493+
return@withContext Result.failure(AppError("Connect already in progress"))
494+
}
489495
val knownDevices = _state.value.knownDevices.ifEmpty { loadKnownDevices() }
490496
if (knownDevices.isEmpty()) {
491497
return@withContext Result.failure(AppError("No known devices"))
@@ -689,14 +695,23 @@ class TrezorRepo @Inject constructor(
689695
*/
690696
private suspend fun retryAutoReconnect() {
691697
repeat(TRANSPORT_RESTORED_MAX_ATTEMPTS) { attempt ->
692-
val current = _state.value
693-
if (current.connected != null || current.isConnecting || current.isAutoReconnecting) return
698+
if (_state.value.connected != null || isConnectInProgress()) return
694699
delay(TRANSPORT_RESTORED_RECONNECT_DELAY * (attempt + 1))
700+
// A connect may have started while this attempt was waiting.
701+
if (_state.value.connected != null || isConnectInProgress()) return
695702
Logger.info("Attempting auto-reconnect after transport restored, attempt '${attempt + 1}'", context = TAG)
696703
if (autoReconnect().isSuccess) return
697704
}
698705
}
699706

707+
private fun isConnectInProgress(): Boolean = run {
708+
val current = _state.value
709+
current.isConnecting ||
710+
current.isAutoReconnecting ||
711+
needsPinEntry.value ||
712+
needsPairingCode.value
713+
}
714+
700715
private suspend fun addOrUpdateKnownDevice(deviceInfo: TrezorDeviceInfo, features: TrezorFeatures) {
701716
val existing = _state.value.knownDevices
702717
val previous = existing.find { it.id == deviceInfo.id }

app/src/test/java/to/bitkit/repositories/TrezorRepoTest.kt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import org.mockito.kotlin.anyOrNull
2121
import org.mockito.kotlin.argumentCaptor
2222
import org.mockito.kotlin.eq
2323
import org.mockito.kotlin.mock
24+
import org.mockito.kotlin.never
2425
import org.mockito.kotlin.times
2526
import org.mockito.kotlin.verify
2627
import org.mockito.kotlin.whenever
@@ -249,6 +250,34 @@ class TrezorRepoTest : BaseUnitTest() {
249250
verify(trezorService, times(2)).scan()
250251
}
251252

253+
@Test
254+
fun `autoReconnect bails while device awaits pin entry`() = test {
255+
whenever(trezorUiHandler.needsPinEntry).thenReturn(MutableStateFlow(true))
256+
whenever(hwWalletStore.loadKnownDevices()).thenReturn(listOf(mockKnownDevice()))
257+
sut = createSut()
258+
259+
val result = sut.autoReconnect()
260+
261+
assertTrue(result.isFailure)
262+
verify(trezorService, never()).disconnect()
263+
verify(trezorService, never()).scan()
264+
}
265+
266+
@Test
267+
fun `transport restored skips reconnect while device awaits pairing code`() = test {
268+
val transportRestored = MutableSharedFlow<Unit>()
269+
whenever(trezorTransport.transportRestored).thenReturn(transportRestored)
270+
whenever(trezorTransport.needsPairingCode).thenReturn(MutableStateFlow(true))
271+
whenever(hwWalletStore.loadKnownDevices()).thenReturn(listOf(mockKnownDevice()))
272+
sut = createSut()
273+
274+
transportRestored.emit(Unit)
275+
advanceUntilIdle()
276+
277+
verify(trezorService, never()).disconnect()
278+
verify(trezorService, never()).scan()
279+
}
280+
252281
@Test
253282
fun `onTransportRestored auto-reconnects to a known device`() = test {
254283
val features = mockFeatures()

0 commit comments

Comments
 (0)