@@ -52,6 +52,7 @@ import to.bitkit.data.HwWalletStore
5252import to.bitkit.di.IoDispatcher
5353import to.bitkit.env.Env
5454import to.bitkit.ext.nowMs
55+ import to.bitkit.ext.runSuspendCatching
5556import to.bitkit.models.ALL_ADDRESS_TYPES
5657import to.bitkit.models.TransportType
5758import to.bitkit.models.toAccountDerivationPath
@@ -190,7 +191,6 @@ class TrezorRepo @Inject constructor(
190191 hwWalletStore.reset()
191192 _state .update {
192193 it.copy(
193- isInitialized = false ,
194194 isScanning = false ,
195195 isConnecting = false ,
196196 isAutoReconnecting = false ,
@@ -242,16 +242,16 @@ class TrezorRepo @Inject constructor(
242242 isSetup = CompletableDeferred ()
243243 }
244244 if (isSetup.isCompleted) {
245- if (runCatching { isSetup.await() }.isSuccess) return @withLock Result .success(Unit )
245+ if (runSuspendCatching { isSetup.await() }.isSuccess) return @withLock Result .success(Unit )
246246 isSetup = CompletableDeferred ()
247247 }
248248
249- runCatching {
249+ runSuspendCatching {
250250 val credentialPath = " ${Env .bitkitCoreStoragePath(walletIndex)} /trezor-credentials.json"
251251 Logger .debug(" Initializing Trezor with credential path: '$credentialPath '" , context = TAG )
252252 trezorService.initialize(credentialPath)
253253 val known = loadKnownDevices()
254- _state .update { it.copy(isInitialized = true , knownDevices = known.toImmutableList(), error = null ) }
254+ _state .update { it.copy(knownDevices = known.toImmutableList(), error = null ) }
255255 isSetup.complete(Unit )
256256 Unit
257257 }.onFailure { e ->
@@ -264,7 +264,7 @@ class TrezorRepo @Inject constructor(
264264
265265 suspend fun scan (includeBluetooth : Boolean = true): Result <List <TrezorDeviceInfo >> = withContext(ioDispatcher) {
266266 runCatching {
267- ensureInitialized ()
267+ awaitSetup ()
268268 _state .update { it.copy(isScanning = true , error = null ) }
269269 val devices = trezorService.scan(includeBluetooth = includeBluetooth)
270270 val knownIds = _state .value.knownDevices.map { it.id }.toSet()
@@ -279,7 +279,7 @@ class TrezorRepo @Inject constructor(
279279
280280 suspend fun listDevices (): Result <List <TrezorDeviceInfo >> = withContext(ioDispatcher) {
281281 runCatching {
282- ensureInitialized ()
282+ awaitSetup ()
283283 val devices = trezorService.listDevices()
284284 val knownIds = _state .value.knownDevices.map { it.id }.toSet()
285285 val nearby = devices.filter { it.id !in knownIds }
@@ -296,7 +296,7 @@ class TrezorRepo @Inject constructor(
296296 requestUsbPermission : Boolean = true,
297297 ): Result <TrezorFeatures > = withContext(ioDispatcher) {
298298 runCatching {
299- ensureInitialized ()
299+ awaitSetup ()
300300 _state .update { it.copy(isConnecting = true , error = null ) }
301301 TrezorDebugLog .log(" CONNECT" , " connect() called for deviceId=$deviceId " )
302302 val features = connectWithThpRetry(
@@ -382,6 +382,7 @@ class TrezorRepo @Inject constructor(
382382 scriptType : AccountType ? = null,
383383 ): Result <TransactionHistoryResult > = withContext(ioDispatcher) {
384384 runCatching {
385+ awaitSetup()
385386 trezorService.getTransactionHistory(
386387 extendedKey = extendedKey,
387388 electrumUrl = electrumUrlForNetwork(network),
@@ -400,6 +401,7 @@ class TrezorRepo @Inject constructor(
400401 scriptType : AccountType ? = null,
401402 ): Result <AccountInfoResult > = withContext(ioDispatcher) {
402403 runCatching {
404+ awaitSetup()
403405 trezorService.getAccountInfo(
404406 extendedKey = extendedKey,
405407 electrumUrl = electrumUrlForNetwork(network),
@@ -417,6 +419,7 @@ class TrezorRepo @Inject constructor(
417419 network : BitkitCoreNetwork = Env .network.toCoreNetwork(),
418420 ): Result <SingleAddressInfoResult > = withContext(ioDispatcher) {
419421 runCatching {
422+ awaitSetup()
420423 trezorService.getAddressInfo(
421424 address = address,
422425 electrumUrl = electrumUrlForNetwork(network),
@@ -438,6 +441,7 @@ class TrezorRepo @Inject constructor(
438441 coinSelection : CoinSelection ,
439442 ): Result <List <ComposeResult >> = withContext(ioDispatcher) {
440443 runCatching {
444+ awaitSetup()
441445 val fingerprint = trezorService.getDeviceFingerprint()
442446 val params = ComposeParams (
443447 wallet = WalletParams (
@@ -478,6 +482,7 @@ class TrezorRepo @Inject constructor(
478482 network : BitkitCoreNetwork ,
479483 ): Result <String > = withContext(ioDispatcher) {
480484 runCatching {
485+ awaitSetup()
481486 trezorService.broadcastRawTx(
482487 serializedTx = serializedTx,
483488 electrumUrl = electrumUrlForNetwork(network),
@@ -577,7 +582,7 @@ class TrezorRepo @Inject constructor(
577582
578583 _state .update { it.copy(isAutoReconnecting = true , error = null ) }
579584 runCatching {
580- ensureInitialized (walletIndex)
585+ awaitSetup (walletIndex)
581586 val cachedFeatures = if (trezorService.isConnected()) _state .value.connectedDevice else null
582587 if (cachedFeatures != null ) {
583588 cachedFeatures
@@ -629,11 +634,9 @@ class TrezorRepo @Inject constructor(
629634 _state .update { it.copy(isConnecting = true , error = null ) }
630635 TrezorDebugLog .log(" RECONNECT" , " === connectKnownDevice START ===" )
631636 TrezorDebugLog .log(" RECONNECT" , " deviceId=$deviceId " )
632- TrezorDebugLog .log(" RECONNECT" , " isInitialized=${_state .value.isInitialized} " )
633- val needsInitialization = ! _state .value.isInitialized
634- if (needsInitialization) TrezorDebugLog .log(" RECONNECT" , " Initializing..." )
635- ensureInitialized()
636- if (needsInitialization) TrezorDebugLog .log(" RECONNECT" , " Initialized OK" )
637+ TrezorDebugLog .log(" RECONNECT" , " Awaiting setup..." )
638+ awaitSetup()
639+ TrezorDebugLog .log(" RECONNECT" , " Setup OK" )
637640 TrezorDebugLog .log(" RECONNECT" , " Scanning for devices..." )
638641 val scannedDevices = trezorService.scan()
639642 TrezorDebugLog .log(
@@ -704,6 +707,7 @@ class TrezorRepo @Inject constructor(
704707 electrumUrl : String = electrumUrlForNetwork(network),
705708 ): Result <Unit > = withContext(ioDispatcher) {
706709 runCatching {
710+ awaitSetup()
707711 val params = WatcherParams (
708712 watcherId = watcherId,
709713 extendedKey = extendedKey,
@@ -723,6 +727,7 @@ class TrezorRepo @Inject constructor(
723727
724728 suspend fun stopWatcher (watcherId : String ): Result <Unit > = withContext(ioDispatcher) {
725729 runCatching {
730+ awaitSetup()
726731 trezorService.stopWatcher(watcherId)
727732 TrezorDebugLog .log(WATCHER_TAG , " Stopped watcher '$watcherId '" )
728733 Logger .info(" Stopped watcher '$watcherId '" , context = TAG )
@@ -738,6 +743,7 @@ class TrezorRepo @Inject constructor(
738743
739744 suspend fun stopAllWatchers (): Result <Unit > = withContext(ioDispatcher) {
740745 runCatching {
746+ awaitSetup()
741747 trezorService.stopAllWatchers()
742748 TrezorDebugLog .log(WATCHER_TAG , " Stopped all watchers" )
743749 }.onFailure {
@@ -888,18 +894,23 @@ class TrezorRepo @Inject constructor(
888894 val deviceId = _state .value.connectedDeviceId
889895 ? : _state .value.knownDevices.firstOrNull()?.id
890896 ? : throw AppError (" No device to reconnect" )
891- ensureInitialized ()
897+ awaitSetup ()
892898 val devices = trezorService.scan()
893899 val device = devices.find { it.id == deviceId }
894900 ? : throw AppError (" Device not found during reconnect" )
895901 val features = connectWithThpRetry(device.id, trezorUiHandler.currentSelection())
896902 _state .update { it.copy(connected = ConnectedTrezorDevice (id = deviceId, features = features)) }
897903 }
898904
899- private suspend fun ensureInitialized (walletIndex : Int = 0) {
900- if (! _state .value.isInitialized ) {
905+ private suspend fun awaitSetup (walletIndex : Int = 0) {
906+ if (isSetup.isCancelled || ! isSetup.isCompleted ) {
901907 initialize(walletIndex).getOrThrow()
902908 }
909+ val setup = runSuspendCatching { isSetup.await() }
910+ if (setup.isSuccess) return
911+
912+ initialize(walletIndex).getOrThrow()
913+ isSetup.await()
903914 }
904915
905916 private suspend fun resetSetup () {
@@ -980,7 +991,6 @@ class TrezorRepo @Inject constructor(
980991
981992@Stable
982993data class TrezorState (
983- val isInitialized : Boolean = false ,
984994 val isScanning : Boolean = false ,
985995 val isConnecting : Boolean = false ,
986996 val isAutoReconnecting : Boolean = false ,
0 commit comments