Updated on 2026-08-14

This commit is contained in:
Tangem 2024-01-19 18:22:59 +03:00
parent 895af6c0a6
commit b2726d153c
28 changed files with 197 additions and 40 deletions

View file

@ -186,7 +186,6 @@ internal class DefaultNetworksRepository(
is UpdateWalletManagerResult.NoAccount,
-> Unit
is UpdateWalletManagerResult.Unreachable,
is UpdateWalletManagerResult.UnreachableWithoutAddresses,
is UpdateWalletManagerResult.MissedDerivation,
-> {
Timber.w(

View file

@ -19,9 +19,8 @@ internal class NetworkStatusFactory {
network = network,
value = when (result) {
is UpdateWalletManagerResult.MissedDerivation -> NetworkStatus.MissedDerivation
is UpdateWalletManagerResult.UnreachableWithoutAddresses -> NetworkStatus.UnreachableWithoutAddresses
is UpdateWalletManagerResult.Unreachable -> NetworkStatus.Unreachable(
address = getNetworkAddress(result.selectedAddress, result.addresses),
address = getNetworkAddressOrNull(result.selectedAddress, result.addresses),
)
is UpdateWalletManagerResult.NoAccount -> NetworkStatus.NoAccount(
address = getNetworkAddress(result.selectedAddress, result.addresses),
@ -96,6 +95,14 @@ internal class NetworkStatusFactory {
return transactions.mapTo(hashSetOf()) { it.txHistoryItem }
}
private fun getNetworkAddressOrNull(selectedAddress: String?, availableAddresses: Set<Address>?): NetworkAddress? {
if (selectedAddress == null || availableAddresses == null) {
return null
}
return getNetworkAddress(selectedAddress, availableAddresses)
}
private fun getNetworkAddress(selectedAddress: String, availableAddresses: Set<Address>): NetworkAddress {
val defaultAddress = availableAddresses
.firstOrNull { it.value == selectedAddress }

View file

@ -132,7 +132,7 @@ class DefaultWalletManagersFacade(
val walletManager = getOrCreateWalletManager(userWalletId, blockchain, derivationPath)
if (walletManager == null || blockchain == Blockchain.Unknown) {
Timber.w("Unable to get a wallet manager for blockchain: $blockchain")
return UpdateWalletManagerResult.UnreachableWithoutAddresses
return UpdateWalletManagerResult.Unreachable()
}
return getLastWalletManagerResult(walletManager)
@ -246,7 +246,7 @@ class DefaultWalletManagersFacade(
)
if (walletManager == null || blockchain == Blockchain.Unknown) {
Timber.w("Unable to create or find a wallet manager for blockchain: $blockchain")
return UpdateWalletManagerResult.UnreachableWithoutAddresses
return UpdateWalletManagerResult.Unreachable()
}
updateWalletManagerTokensIfNeeded(walletManager, extraTokens)

View file

@ -6,11 +6,9 @@ sealed class UpdateWalletManagerResult {
object MissedDerivation : UpdateWalletManagerResult()
object UnreachableWithoutAddresses : UpdateWalletManagerResult()
data class Unreachable(
val selectedAddress: String,
val addresses: Set<Address>,
val selectedAddress: String? = null,
val addresses: Set<Address>? = null,
) : UpdateWalletManagerResult()
data class Verified(

View file

@ -50,8 +50,6 @@ data class CryptoCurrencyStatus(
/** Represents the Loading state of a cryptocurrency, typically while fetching its details. */
object Loading : Status(isError = false)
object UnreachableWithoutAddresses : Status(isError = true)
/**
* Represents a state where the cryptocurrency is not reachable.
*
@ -62,7 +60,7 @@ data class CryptoCurrencyStatus(
data class Unreachable(
override val priceChange: BigDecimal?,
override val fiatRate: BigDecimal?,
override val networkAddress: NetworkAddress,
override val networkAddress: NetworkAddress?,
) : Status(isError = true)
/** Represents a state where the cryptocurrency's network amount not found. */

View file

@ -21,14 +21,12 @@ data class NetworkStatus(
*/
sealed class Status
object UnreachableWithoutAddresses : Status()
/**
* Represents the state where the network is unreachable.
*
* @property address Network addresses.
*/
data class Unreachable(val address: NetworkAddress) : Status()
data class Unreachable(val address: NetworkAddress?) : Status()
/**
* Represents the state where a derivation has been missed.

View file

@ -16,7 +16,6 @@ internal class CurrencyStatusOperations(
return when (val status = networkStatus?.value) {
null -> CryptoCurrencyStatus.Loading
is NetworkStatus.MissedDerivation -> createMissedDerivationStatus()
is NetworkStatus.UnreachableWithoutAddresses -> CryptoCurrencyStatus.UnreachableWithoutAddresses
is NetworkStatus.Unreachable -> createUnreachableStatus(status)
is NetworkStatus.NoAccount -> createNoAccountStatus(status)
is NetworkStatus.Verified -> createStatus(status)

View file

@ -22,7 +22,6 @@ internal class TokenListFiatBalanceOperations(
}
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.UnreachableWithoutAddresses,
is CryptoCurrencyStatus.NoAmount,
is CryptoCurrencyStatus.NoQuote,
-> {

View file

@ -45,7 +45,7 @@ internal object MockNetworks {
val networkStatus1 = NetworkStatus(
network = network1,
value = NetworkStatus.UnreachableWithoutAddresses,
value = NetworkStatus.Unreachable(address = null),
)
val networkStatus2 = NetworkStatus(

View file

@ -0,0 +1,27 @@
package com.tangem.feature.tokendetails.presentation.tokendetails.analytics
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.feature.tokendetails.presentation.tokendetails.analytics.utils.toAnalyticsParams
internal open class TokenDetailsAnalyticsEvent(
event: String,
params: Map<String, String> = mapOf(),
) : AnalyticsEvent(category = "Token", event, params) {
open class Notice(
event: String,
params: Map<String, String> = mapOf(),
) : TokenDetailsAnalyticsEvent(event = "Notice - $event", params) {
class NetworkUnreachable(currency: CryptoCurrency) : Notice(
event = "Network Unreachable",
params = currency.toAnalyticsParams(),
)
class NotEnoughFee(currency: CryptoCurrency) : Notice(
event = "Not Enough Fee",
params = currency.toAnalyticsParams(),
)
}
}

View file

@ -0,0 +1,38 @@
package com.tangem.feature.tokendetails.presentation.tokendetails.analytics
import arrow.core.Either
import arrow.core.getOrElse
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.domain.tokens.error.CurrencyStatusError
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
internal class TokenDetailsCurrencyStatusAnalyticsSender(
private val analyticsEventHandler: AnalyticsEventHandler,
) {
fun send(maybeCurrencyStatus: Either<CurrencyStatusError, CryptoCurrencyStatus>) {
val currencyStatus = maybeCurrencyStatus.getOrElse { return }
val event = getEvent(currencyStatus)
if (event != null) {
analyticsEventHandler.send(event)
}
}
private fun getEvent(currencyStatus: CryptoCurrencyStatus): AnalyticsEvent? {
return when (currencyStatus.value) {
is CryptoCurrencyStatus.Custom,
is CryptoCurrencyStatus.Loaded,
is CryptoCurrencyStatus.Loading,
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.NoAccount,
is CryptoCurrencyStatus.NoAmount,
is CryptoCurrencyStatus.NoQuote,
-> null
is CryptoCurrencyStatus.Unreachable -> TokenDetailsAnalyticsEvent.Notice.NetworkUnreachable(
currency = currencyStatus.currency,
)
}
}
}

View file

@ -0,0 +1,45 @@
package com.tangem.feature.tokendetails.presentation.tokendetails.analytics
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification
internal class TokenDetailsNotificationsAnalyticsSender(
private val cryptoCurrency: CryptoCurrency,
private val analyticsEventHandler: AnalyticsEventHandler,
) {
fun send(displayedUiState: TokenDetailsState, newNotifications: List<TokenDetailsNotification>) {
if (newNotifications.isEmpty()) return
if (displayedUiState.pullToRefreshConfig.isRefreshing) return
val eventsFromNewWarnings = getEvents(newNotifications)
val eventsFromDisplayedWarnings = getEvents(displayedUiState.notifications)
val eventsToSend = eventsFromNewWarnings.filter { it !in eventsFromDisplayedWarnings }
eventsToSend.forEach { event ->
analyticsEventHandler.send(event)
}
}
private fun getEvents(notifications: List<TokenDetailsNotification>): Set<AnalyticsEvent> {
return notifications.mapNotNullTo(mutableSetOf(), ::getEvent)
}
private fun getEvent(notification: TokenDetailsNotification): AnalyticsEvent? {
return when (notification) {
is TokenDetailsNotification.NetworkFee -> TokenDetailsAnalyticsEvent.Notice.NotEnoughFee(
currency = cryptoCurrency,
)
is TokenDetailsNotification.NetworksUnreachable,
is TokenDetailsNotification.ExistentialDeposit,
is TokenDetailsNotification.HasPendingTransactions,
is TokenDetailsNotification.NetworksNoAccount,
is TokenDetailsNotification.RentInfo,
is TokenDetailsNotification.SwapPromo,
-> null
}
}
}

View file

@ -0,0 +1,10 @@
package com.tangem.feature.tokendetails.presentation.tokendetails.analytics.utils
import com.tangem.domain.tokens.model.CryptoCurrency
internal fun CryptoCurrency.toAnalyticsParams(): Map<String, String> {
return mapOf(
"Token" to symbol,
"Blockchain" to network.currencySymbol,
)
}

View file

@ -78,7 +78,6 @@ internal class TokenDetailsLoadedBalanceConverter(
is CryptoCurrencyStatus.Loading -> TokenDetailsBalanceBlockState.Loading(currentState.actionButtons)
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.UnreachableWithoutAddresses,
is CryptoCurrencyStatus.NoAmount,
-> TokenDetailsBalanceBlockState.Error(currentState.actionButtons)
}
@ -102,7 +101,6 @@ internal class TokenDetailsLoadedBalanceConverter(
is CryptoCurrencyStatus.Custom,
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.UnreachableWithoutAddresses,
is CryptoCurrencyStatus.NoAmount,
-> status.toContentConfig(currencySymbol)
}

View file

@ -40,6 +40,8 @@ import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
import com.tangem.feature.swap.domain.SwapTransactionRepository
import com.tangem.feature.swap.domain.api.SwapRepository
import com.tangem.feature.tokendetails.presentation.router.InnerTokenDetailsRouter
import com.tangem.feature.tokendetails.presentation.tokendetails.analytics.TokenDetailsCurrencyStatusAnalyticsSender
import com.tangem.feature.tokendetails.presentation.tokendetails.analytics.TokenDetailsNotificationsAnalyticsSender
import com.tangem.feature.tokendetails.presentation.tokendetails.state.SwapTransactionsState
import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState
import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.TokenDetailsStateFactory
@ -57,7 +59,6 @@ import kotlinx.coroutines.launch
import timber.log.Timber
import java.math.BigDecimal
import javax.inject.Inject
import kotlin.properties.Delegates
@Suppress("LongParameterList", "LargeClass", "TooManyFunctions")
@HiltViewModel
@ -95,7 +96,7 @@ internal class TokenDetailsViewModel @Inject constructor(
private val cryptoCurrency: CryptoCurrency = savedStateHandle[TokenDetailsRouter.CRYPTO_CURRENCY_KEY]
?: error("This screen can't open without `CryptoCurrency`")
var router by Delegates.notNull<InnerTokenDetailsRouter>()
lateinit var router: InnerTokenDetailsRouter
private val marketPriceJobHolder = JobHolder()
private val refreshStateJobHolder = JobHolder()
@ -115,7 +116,7 @@ internal class TokenDetailsViewModel @Inject constructor(
decimals = cryptoCurrency.decimals,
)
private val exchangeStatusFactory by lazy {
private val exchangeStatusFactory by lazy(mode = LazyThreadSafetyMode.NONE) {
ExchangeStatusFactory(
swapTransactionRepository = swapTransactionRepository,
swapRepository = swapRepository,
@ -132,6 +133,17 @@ internal class TokenDetailsViewModel @Inject constructor(
)
}
private val notificationsAnalyticsSender by lazy(mode = LazyThreadSafetyMode.NONE) {
TokenDetailsNotificationsAnalyticsSender(
cryptoCurrency = cryptoCurrency,
analyticsEventHandler = analyticsEventsHandler,
)
}
private val currencyStatusAnalyticsSender by lazy(mode = LazyThreadSafetyMode.NONE) {
TokenDetailsCurrencyStatusAnalyticsSender(analyticsEventsHandler)
}
var uiState: TokenDetailsState by mutableStateOf(stateFactory.getInitialState(cryptoCurrency))
private set
@ -188,7 +200,11 @@ internal class TokenDetailsViewModel @Inject constructor(
isSingleWalletWithTokens = wallet.scanResponse.cardTypesResolver.isSingleWalletWithToken(),
)
.distinctUntilChanged()
.onEach { uiState = stateFactory.getStateWithNotifications(it) }
.onEach {
val updatedState = stateFactory.getStateWithNotifications(it)
notificationsAnalyticsSender.send(uiState, updatedState.notifications)
uiState = updatedState
}
.launchIn(viewModelScope)
.saveIn(warningsJobHolder)
}
@ -203,13 +219,14 @@ internal class TokenDetailsViewModel @Inject constructor(
isSingleWalletWithTokens = wallet.scanResponse.cardTypesResolver.isSingleWalletWithToken(),
)
.distinctUntilChanged()
.onEach { either ->
uiState = stateFactory.getCurrencyLoadedBalanceState(either)
either.onRight { status ->
.onEach { maybeCurrencyStatus ->
uiState = stateFactory.getCurrencyLoadedBalanceState(maybeCurrencyStatus)
maybeCurrencyStatus.onRight { status ->
cryptoCurrencyStatus = status
updateButtons(userWalletId = userWalletId, currencyStatus = status)
updateWarnings(status)
}
currencyStatusAnalyticsSender.send(maybeCurrencyStatus)
}
.flowOn(dispatchers.io)
.launchIn(viewModelScope)

View file

@ -56,6 +56,7 @@ internal class DefaultWalletRouter(
if (walletFeatureToggles.isWalletsScrollingPreviewEnabled) {
val viewModel = hiltViewModel<WalletViewModelV2>().apply {
setWalletRouter(router = this@DefaultWalletRouter)
subscribeToLifecycle(LocalLifecycleOwner.current)
}
WalletScreenV2(state = viewModel.uiState.collectAsStateWithLifecycle().value)

View file

@ -12,6 +12,7 @@ import com.tangem.domain.wallets.models.UserWallet
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.Basic
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.MainScreen
import com.tangem.feature.wallet.presentation.wallet.state2.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
import dagger.hilt.android.scopes.ViewModelScoped
import java.math.BigDecimal
import javax.inject.Inject
@ -20,9 +21,11 @@ import javax.inject.Inject
internal class TokenListAnalyticsSender @Inject constructor(
private val analyticsEventHandler: AnalyticsEventHandler,
private val checkIsWalletToppedUpUseCase: CheckIsWalletToppedUpUseCase,
private val screenLifecycleProvider: ScreenLifecycleProvider,
) {
suspend fun send(displayedUiState: WalletState?, userWallet: UserWallet, tokenList: TokenList) {
if (screenLifecycleProvider.isBackground) return
if (displayedUiState == null || displayedUiState.pullToRefreshConfig.isRefreshing) return
if (tokenList.totalFiatBalance is TokenList.FiatBalance.Loading) return
@ -117,8 +120,7 @@ internal class TokenListAnalyticsSender @Inject constructor(
private fun sendUnreachableNetworksEventIfNeeded(currenciesStatuses: List<CryptoCurrencyStatus>) {
val hasUnreachableCurrencies = currenciesStatuses.any {
it.value is CryptoCurrencyStatus.Unreachable ||
it.value is CryptoCurrencyStatus.UnreachableWithoutAddresses
it.value is CryptoCurrencyStatus.Unreachable
}
if (hasUnreachableCurrencies) {

View file

@ -5,15 +5,18 @@ import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.feature.wallet.presentation.wallet.analytics.WalletScreenAnalyticsEvent.MainScreen
import com.tangem.feature.wallet.presentation.wallet.state.components.WalletNotification
import com.tangem.feature.wallet.presentation.wallet.state2.model.WalletState
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
import dagger.hilt.android.scopes.ViewModelScoped
import javax.inject.Inject
@ViewModelScoped
internal class WalletWarningsAnalyticsSender @Inject constructor(
private val analyticsEventHandler: AnalyticsEventHandler,
private val screenLifecycleProvider: ScreenLifecycleProvider,
) {
fun send(displayedUiState: WalletState?, newWarnings: List<WalletNotification>) {
if (screenLifecycleProvider.isBackground) return
if (newWarnings.isEmpty()) return
if (displayedUiState == null || displayedUiState.pullToRefreshConfig.isRefreshing) return

View file

@ -73,7 +73,6 @@ internal class WalletSingleCurrencyLoadedBalanceConverter(
is CryptoCurrencyStatus.Custom,
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.UnreachableWithoutAddresses,
is CryptoCurrencyStatus.NoQuote,
-> MarketPriceBlockState.Error(currencySymbol)
}
@ -117,7 +116,6 @@ internal class WalletSingleCurrencyLoadedBalanceConverter(
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.Custom,
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.UnreachableWithoutAddresses,
-> {
WalletCardState.Error(
id = selectedWallet.id,

View file

@ -21,7 +21,6 @@ internal class SingleWalletCardStateConverter(
is CryptoCurrencyStatus.Custom,
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.UnreachableWithoutAddresses,
-> value.toErrorState()
is CryptoCurrencyStatus.NoQuote,
is CryptoCurrencyStatus.Loaded,

View file

@ -25,7 +25,6 @@ internal class SingleWalletMarketPriceConverter(
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.NoQuote,
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.UnreachableWithoutAddresses,
-> MarketPriceBlockState.Error(value.currencySymbol)
}
}

View file

@ -28,7 +28,6 @@ internal class TokenItemStateConverter(
-> value.mapToTokenItemState()
is CryptoCurrencyStatus.MissedDerivation -> value.mapToNoAddressTokenItemState()
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.UnreachableWithoutAddresses,
is CryptoCurrencyStatus.NoAmount,
-> value.mapToUnreachableTokenItemState()
}

View file

@ -22,7 +22,6 @@ internal class VisaWalletCardStateConverter(
is CryptoCurrencyStatus.Custom,
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.UnreachableWithoutAddresses,
-> value.toErrorState()
is CryptoCurrencyStatus.NoQuote,
is CryptoCurrencyStatus.Loaded,

View file

@ -73,7 +73,6 @@ internal class PrimaryCurrencySubscriber(
-> createCardBalanceState(fiatAmount)
is CryptoCurrencyStatus.NoQuote -> AnalyticsParam.CardBalanceState.NoRate
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.UnreachableWithoutAddresses,
-> AnalyticsParam.CardBalanceState.BlockchainError
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.Loading,

View file

@ -28,7 +28,6 @@ internal class CryptoCurrencyStatusToTokenItemConverter(
-> value.mapToTokenItemState()
is CryptoCurrencyStatus.MissedDerivation -> value.mapToNoAddressTokenItemState()
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.UnreachableWithoutAddresses,
is CryptoCurrencyStatus.NoAmount,
-> value.mapToUnreachableTokenItemState()
}

View file

@ -0,0 +1,21 @@
package com.tangem.feature.wallet.presentation.wallet.utils
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import dagger.hilt.android.scopes.ViewModelScoped
import javax.inject.Inject
@ViewModelScoped
internal class ScreenLifecycleProvider @Inject constructor() : DefaultLifecycleObserver {
var isBackground: Boolean = true
private set
override fun onResume(owner: LifecycleOwner) {
isBackground = false
}
override fun onPause(owner: LifecycleOwner) {
isBackground = true
}
}

View file

@ -1231,7 +1231,6 @@ internal class WalletViewModel @Inject constructor(
}
is CryptoCurrencyStatus.NoQuote -> AnalyticsParam.CardBalanceState.NoRate
is CryptoCurrencyStatus.Unreachable,
is CryptoCurrencyStatus.UnreachableWithoutAddresses,
-> AnalyticsParam.CardBalanceState.BlockchainError
is CryptoCurrencyStatus.MissedDerivation,
is CryptoCurrencyStatus.Loading,

View file

@ -1,5 +1,6 @@
package com.tangem.feature.wallet.presentation.wallet.viewmodels
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.tangem.core.analytics.api.AnalyticsEventHandler
@ -21,6 +22,7 @@ import com.tangem.feature.wallet.presentation.wallet.state2.WalletStateControlle
import com.tangem.feature.wallet.presentation.wallet.state2.model.WalletScreenState
import com.tangem.feature.wallet.presentation.wallet.state2.transformers.*
import com.tangem.feature.wallet.presentation.wallet.state2.utils.WalletEventSender
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntentsV2
import com.tangem.utils.Provider
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@ -33,7 +35,6 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import javax.inject.Inject
import kotlin.properties.Delegates
@Suppress("LongParameterList")
@HiltViewModel
@ -53,11 +54,12 @@ internal class WalletViewModelV2 @Inject constructor(
analyticsEventsHandler: AnalyticsEventHandler,
private val dispatchers: CoroutineDispatcherProvider,
private val reduxStateHolder: ReduxStateHolder,
private val screenLifecycleProvider: ScreenLifecycleProvider,
) : ViewModel() {
val uiState: StateFlow<WalletScreenState> = stateHolder.uiState
private var router: InnerWalletRouter by Delegates.notNull()
private lateinit var router: InnerWalletRouter
private var walletsUpdateJobHolder: JobHolder = JobHolder()
init {
@ -75,6 +77,10 @@ internal class WalletViewModelV2 @Inject constructor(
clickIntents.initialize(router, viewModelScope)
}
fun subscribeToLifecycle(lifecycleOwner: LifecycleOwner) {
lifecycleOwner.lifecycle.addObserver(screenLifecycleProvider)
}
override fun onCleared() {
super.onCleared()
stateHolder.clear()