@@ -9,6 +9,7 @@ import com.synonym.bitkitcore.CoinSelection
99import com.synonym.bitkitcore.ComposeOutput
1010import com.synonym.bitkitcore.ComposeParams
1111import com.synonym.bitkitcore.ComposeResult
12+ import com.synonym.bitkitcore.EventListener
1213import com.synonym.bitkitcore.SingleAddressInfoResult
1314import com.synonym.bitkitcore.TransactionHistoryResult
1415import com.synonym.bitkitcore.TrezorAddressResponse
@@ -22,18 +23,25 @@ import com.synonym.bitkitcore.TrezorSignedTx
2223import com.synonym.bitkitcore.TrezorTransportType
2324import com.synonym.bitkitcore.WalletParams
2425import com.synonym.bitkitcore.WalletSelection
26+ import com.synonym.bitkitcore.WatcherEvent
27+ import com.synonym.bitkitcore.WatcherParams
2528import dagger.hilt.android.qualifiers.ApplicationContext
2629import kotlinx.collections.immutable.ImmutableList
2730import kotlinx.collections.immutable.persistentListOf
2831import kotlinx.collections.immutable.toImmutableList
2932import kotlinx.coroutines.CoroutineDispatcher
3033import kotlinx.coroutines.CoroutineScope
34+ import kotlinx.coroutines.SupervisorJob
3135import kotlinx.coroutines.delay
36+ import kotlinx.coroutines.flow.MutableSharedFlow
3237import kotlinx.coroutines.flow.MutableStateFlow
38+ import kotlinx.coroutines.flow.SharedFlow
39+ import kotlinx.coroutines.flow.asSharedFlow
3340import kotlinx.coroutines.flow.asStateFlow
3441import kotlinx.coroutines.flow.launchIn
3542import kotlinx.coroutines.flow.onEach
3643import kotlinx.coroutines.flow.update
44+ import kotlinx.coroutines.launch
3745import kotlinx.coroutines.withContext
3846import kotlinx.serialization.SerialName
3947import kotlinx.serialization.Serializable
@@ -65,6 +73,7 @@ class TrezorRepo @Inject constructor(
6573) {
6674 companion object {
6775 private const val TAG = " TrezorRepo"
76+ private const val WATCHER_TAG = " WATCHER"
6877 private const val DEFAULT_ADDRESS_PATH = " m/84'/0'/0'/0/0"
6978 private const val DEFAULT_ACCOUNT_PATH = " m/84'/0'/0'"
7079 private const val WALLET_MODE_RECONNECT_DELAY_MS = 1_000L
@@ -73,6 +82,18 @@ class TrezorRepo @Inject constructor(
7382 private val _state = MutableStateFlow (TrezorState ())
7483 val state = _state .asStateFlow()
7584
85+ private val watcherCleanupScope = CoroutineScope (SupervisorJob () + ioDispatcher)
86+
87+ private val _watcherEvents = MutableSharedFlow <Pair <String , WatcherEvent >>(extraBufferCapacity = 64 )
88+ val watcherEvents: SharedFlow <Pair <String , WatcherEvent >> = _watcherEvents .asSharedFlow()
89+
90+ private val eventBridge: EventListener = object : EventListener {
91+ override fun onEvent (watcherId : String , event : WatcherEvent ) {
92+ TrezorDebugLog .log(WATCHER_TAG , " [$watcherId ] ${event::class .simpleName} " )
93+ _watcherEvents .tryEmit(watcherId to event)
94+ }
95+ }
96+
7697 /* *
7798 * Flow indicating when a pairing code needs to be entered.
7899 * UI should show a dialog when this emits true.
@@ -551,6 +572,56 @@ class TrezorRepo @Inject constructor(
551572 }
552573 }
553574
575+ suspend fun startWatcher (
576+ watcherId : String ,
577+ extendedKey : String ,
578+ network : BitkitCoreNetwork ,
579+ gapLimit : UInt = 20u,
580+ accountType : AccountType ? = null,
581+ ): Result <Unit > = withContext(ioDispatcher) {
582+ runCatching {
583+ val params = WatcherParams (
584+ watcherId = watcherId,
585+ extendedKey = extendedKey,
586+ electrumUrl = electrumUrlForNetwork(network),
587+ network = network,
588+ accountType = accountType,
589+ gapLimit = gapLimit,
590+ )
591+ trezorService.startWatcher(params, eventBridge)
592+ TrezorDebugLog .log(WATCHER_TAG , " Started watcher '$watcherId ' for '${extendedKey.take(12 )} ...'" )
593+ Logger .info(" Started watcher '$watcherId '" , context = TAG )
594+ }.onFailure {
595+ Logger .error(" Start watcher failed" , it, context = TAG )
596+ _state .update { s -> s.copy(error = it.message) }
597+ }
598+ }
599+
600+ suspend fun stopWatcher (watcherId : String ): Result <Unit > = withContext(ioDispatcher) {
601+ runCatching {
602+ trezorService.stopWatcher(watcherId)
603+ TrezorDebugLog .log(WATCHER_TAG , " Stopped watcher '$watcherId '" )
604+ Logger .info(" Stopped watcher '$watcherId '" , context = TAG )
605+ }.onFailure {
606+ Logger .error(" Stop watcher failed" , it, context = TAG )
607+ _state .update { s -> s.copy(error = it.message) }
608+ }
609+ }
610+
611+ fun stopWatcherOnCleared (watcherId : String ) {
612+ watcherCleanupScope.launch { stopWatcher(watcherId) }
613+ }
614+
615+ suspend fun stopAllWatchers (): Result <Unit > = withContext(ioDispatcher) {
616+ runCatching {
617+ trezorService.stopAllWatchers()
618+ TrezorDebugLog .log(WATCHER_TAG , " Stopped all watchers" )
619+ }.onFailure {
620+ Logger .error(" Stop all watchers failed" , it, context = TAG )
621+ _state .update { s -> s.copy(error = it.message) }
622+ }
623+ }
624+
554625 fun clearError () {
555626 _state .update { it.copy(error = null ) }
556627 }
0 commit comments