From 078e215ad7f69ff64d93568fecc9af30bbcec6fe Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 11 Mar 2025 14:03:37 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../local/token/DefaultStakingBalanceStore.kt | 152 ++++++++++++------ .../local/token/StakingBalanceStore.kt | 29 ++-- .../token/converter/YieldBalanceConverter.kt | 10 +- .../data/staking/DefaultStakingRepository.kt | 115 ++++++++----- .../CachedCurrenciesStatusesOperations.kt | 8 +- .../impl/presentation/model/StakingModel.kt | 65 +++++--- .../state/converters/BalanceItemConverter.kt | 3 +- .../RewardsValidatorStateConverter.kt | 4 +- .../converters/YieldBalancesConverter.kt | 6 +- .../state/helpers/StakingBalanceUpdater.kt | 2 +- .../SetConfirmationStateAssentTransformer.kt | 5 +- ...etConfirmationStateCompletedTransformer.kt | 11 +- .../SetConfirmationStateInitTransformer.kt | 4 +- ...ConfirmationStateResetAssentTransformer.kt | 9 +- .../SetInitialDataStateTransformer.kt | 37 +++-- ...firmationStateAssentApprovalTransformer.kt | 5 +- .../AddStakingNotificationsTransformer.kt | 6 +- ...TokenDetailsBalanceSelectStateConverter.kt | 7 +- 18 files changed, 318 insertions(+), 160 deletions(-) diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/token/DefaultStakingBalanceStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/token/DefaultStakingBalanceStore.kt index fbe1a1435b..15acc9d99b 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/token/DefaultStakingBalanceStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/token/DefaultStakingBalanceStore.kt @@ -3,6 +3,7 @@ package com.tangem.datasource.local.token import androidx.datastore.core.DataStore import com.tangem.datasource.api.stakekit.models.response.model.YieldBalanceWrapperDTO import com.tangem.datasource.local.datastore.RuntimeSharedStore +import com.tangem.datasource.local.token.StakingBalanceStore.StakingID import com.tangem.datasource.local.token.converter.YieldBalanceConverter import com.tangem.domain.models.StatusSource import com.tangem.domain.staking.model.stakekit.YieldBalance @@ -26,10 +27,16 @@ internal class DefaultStakingBalanceStore( private val runtimeStore: RuntimeSharedStore, ) : StakingBalanceStore { - override fun get(userWalletId: UserWalletId): Flow> = channelFlow { + override fun get(userWalletId: UserWalletId, stakingIds: List): Flow> = channelFlow { val cachedBalances = persistenceStore.data .map { val wrappers = it[userWalletId.stringValue].orEmpty() + .filter { wrapper -> + stakingIds.any { id -> + id.address == wrapper.addresses.address && id.integrationId == wrapper.integrationId + } + } + YieldBalanceConverter(isCached = true).convertSet(input = wrappers) } .firstOrNull() @@ -40,33 +47,64 @@ internal class DefaultStakingBalanceStore( } runtimeStore.get() - .map { it[userWalletId].orEmpty() } + .map { + it[userWalletId].orEmpty().filter { balance -> + stakingIds.any { id -> + id.address == balance.address && id.integrationId == balance.integrationId + } + } + .toSet() + } .onEach { - val mergedBalances = mergeYieldBalances(cachedBalances = cachedBalances, runtimeBalances = it) + val mergedBalances = mergeYieldBalances( + stakingIds = stakingIds, + cachedBalances = cachedBalances, + runtimeBalances = it, + ) send(mergedBalances) } .launchIn(scope = this) } - override fun get(userWalletId: UserWalletId, address: String, integrationId: String): Flow { - return get(userWalletId).map { balances -> - balances.getBalance(address = address, integrationId = integrationId) + override fun get(userWalletId: UserWalletId, stakingID: StakingID): Flow { + return get(userWalletId = userWalletId, stakingIds = listOf(stakingID)).map { balances -> + balances.getBalance(stakingID = stakingID) } } override suspend fun getSyncOrNull(userWalletId: UserWalletId): Set? { - return runtimeStore.getSyncOrNull()?.getValue(userWalletId) + val runtimeBalances = runtimeStore.getSyncOrNull()?.getValue(userWalletId).orEmpty() + val cachedBalances = persistenceStore.data.firstOrNull()?.get(userWalletId.stringValue).orEmpty() + + if (runtimeBalances.isEmpty() && cachedBalances.isEmpty()) return null + + return cachedBalances.mapTo(hashSetOf()) { + val cached = YieldBalanceConverter(source = StatusSource.ONLY_CACHE).convert(value = it) + val runtime = runtimeBalances.getBalance(address = cached.address, integrationId = cached.integrationId) + + if (runtime == null || runtime is YieldBalance.Error) cached else runtime + } } - override suspend fun getSyncOrNull( - userWalletId: UserWalletId, - address: String, - integrationId: String, - ): YieldBalance? { - val balances = getSyncOrNull(userWalletId) ?: return null + override suspend fun getSyncOrNull(userWalletId: UserWalletId, stakingIds: List): Set? { + val runtime = runtimeStore.getSyncOrNull()?.getValue(userWalletId) + val cached = persistenceStore.data.firstOrNull()?.get(userWalletId.stringValue) - return balances.getBalance(address, integrationId) + if (runtime.isNullOrEmpty() && cached.isNullOrEmpty()) return null + + return mergeYieldBalances( + cachedBalances = YieldBalanceConverter(source = StatusSource.ONLY_CACHE) + .convertSet(input = cached.orEmpty()), + runtimeBalances = runtime.orEmpty(), + stakingIds = stakingIds, + ) + } + + override suspend fun getSyncOrNull(userWalletId: UserWalletId, stakingID: StakingID): YieldBalance? { + val balances = getSyncOrNull(userWalletId = userWalletId, stakingIds = listOf(stakingID)) ?: return null + + return balances.getBalance(stakingID = stakingID) } override suspend fun store(userWalletId: UserWalletId, items: Set) { @@ -88,34 +126,52 @@ internal class DefaultStakingBalanceStore( } } - override suspend fun refresh(userWalletId: UserWalletId, addressWithIntegrationIdMap: Map) { + override suspend fun refresh(userWalletId: UserWalletId, stakingIds: List) { updateRuntimeStore(userWalletId = userWalletId) { saved -> - saved.mapTo(hashSetOf()) { balance -> - val refreshIntegrationId = addressWithIntegrationIdMap[balance.address] + saved.mapTo(hashSetOf()) { + val yieldBalance = it.takeIf { balance -> + stakingIds.any { id -> balance.integrationId == id.integrationId && balance.address == id.address } + } - if (balance.integrationId == refreshIntegrationId) { - when (balance) { - is YieldBalance.Data -> balance.copy(source = StatusSource.CACHE) - is YieldBalance.Empty -> balance.copy(source = StatusSource.CACHE) - is YieldBalance.Error -> balance + if (yieldBalance != null) { + when (yieldBalance) { + is YieldBalance.Data -> yieldBalance.copy(source = StatusSource.CACHE) + is YieldBalance.Empty -> yieldBalance.copy(source = StatusSource.CACHE) + is YieldBalance.Error -> yieldBalance } } else { - balance + it } } } } - override suspend fun store( - userWalletId: UserWalletId, - integrationId: String, - address: String, - item: YieldBalanceWrapperDTO, - ) { + override suspend fun store(userWalletId: UserWalletId, stakingID: StakingID, item: YieldBalanceWrapperDTO) { coroutineScope { launch { - storeInRuntimeStore(userWalletId, integrationId, address, item) - storeInPersistenceStore(userWalletId, integrationId, address, item) + storeInRuntimeStore( + userWalletId = userWalletId, + integrationId = stakingID.integrationId, + address = stakingID.address, + item = item, + ) + + storeInPersistenceStore( + userWalletId = userWalletId, + integrationId = stakingID.integrationId, + address = stakingID.address, + item = item, + ) + } + } + } + + override suspend fun storeSingleYieldBalance(userWalletId: UserWalletId, item: YieldBalance) { + runtimeStore.update(default = emptyMap()) { saved -> + saved.toMutableMap().apply { + this[userWalletId] = saved[userWalletId] + ?.addOrReplace(item) { it.integrationId == item.integrationId && it.address == item.address } + ?: setOf(item) } } } @@ -178,28 +234,22 @@ internal class DefaultStakingBalanceStore( private fun mergeYieldBalances( cachedBalances: Set, runtimeBalances: Set, + stakingIds: List, ): Set { - if (runtimeBalances.isEmpty()) { - return cachedBalances.mapNotNullTo(hashSetOf()) { - when (it) { - is YieldBalance.Data -> it.copy(source = StatusSource.ONLY_CACHE) - is YieldBalance.Empty -> it.copy(source = StatusSource.ONLY_CACHE) - is YieldBalance.Error -> null - } + return stakingIds.mapTo(hashSetOf()) { id -> + val runtime = runtimeBalances.getBalance(stakingID = id) + + if (runtime == null || runtime is YieldBalance.Error) { + getCachedBalanceIfPossible(cachedBalances = cachedBalances, stakingID = id) + } else { + runtime } } - - return runtimeBalances - .map { runtime -> - runtime.takeIf { runtime !is YieldBalance.Error } - ?: getCachedBalanceIfPossible(cachedBalances, runtime) - } - .toSet() } - private fun getCachedBalanceIfPossible(cachedBalances: Set, runtime: YieldBalance): YieldBalance { - val cached = cachedBalances.getBalance(address = runtime.address, integrationId = runtime.integrationId) - ?: return runtime + private fun getCachedBalanceIfPossible(cachedBalances: Set, stakingID: StakingID): YieldBalance { + val cached = cachedBalances.getBalance(stakingID) + ?: return YieldBalance.Error(integrationId = stakingID.address, address = stakingID.integrationId) val updatedCached = when (cached) { is YieldBalance.Data -> cached.copy(source = StatusSource.ONLY_CACHE) @@ -207,7 +257,11 @@ internal class DefaultStakingBalanceStore( is YieldBalance.Error -> null } - return updatedCached ?: runtime + return updatedCached ?: YieldBalance.Error(integrationId = stakingID.address, address = stakingID.integrationId) + } + + private fun Set.getBalance(stakingID: StakingID): YieldBalance? { + return getBalance(address = stakingID.address, integrationId = stakingID.integrationId) } private fun Set.getBalance(address: String?, integrationId: String?): YieldBalance? { diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/token/StakingBalanceStore.kt b/core/datasource/src/main/java/com/tangem/datasource/local/token/StakingBalanceStore.kt index 7722a21c10..779536d430 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/token/StakingBalanceStore.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/token/StakingBalanceStore.kt @@ -9,23 +9,32 @@ import kotlinx.coroutines.flow.Flow /** Staking balance store */ interface StakingBalanceStore { - /** Get flow of [YieldBalanceList] by [userWalletId] */ - fun get(userWalletId: UserWalletId): Flow> + /** Get flow of [YieldBalanceList] by [userWalletId] and [stakingIds] */ + fun get(userWalletId: UserWalletId, stakingIds: List): Flow> - /** Get flow of [YieldBalance] by [userWalletId], [address] and [integrationId] */ - fun get(userWalletId: UserWalletId, address: String, integrationId: String): Flow + /** Get flow of [YieldBalance] by [userWalletId] and [stakingID] */ + fun get(userWalletId: UserWalletId, stakingID: StakingID): Flow - /** Get [YieldBalanceList] synchronously or null by [userWalletId] */ + /** Get all [YieldBalance] synchronously or null by [userWalletId] */ suspend fun getSyncOrNull(userWalletId: UserWalletId): Set? - /** Get [YieldBalance] synchronously or null by [userWalletId], [address] and [integrationId] */ - suspend fun getSyncOrNull(userWalletId: UserWalletId, address: String, integrationId: String): YieldBalance? + /** Get [YieldBalanceList] synchronously or null by [userWalletId] and [stakingIds] */ + suspend fun getSyncOrNull(userWalletId: UserWalletId, stakingIds: List): Set? + + /** Get [YieldBalance] synchronously or null by [userWalletId] and [stakingID] */ + suspend fun getSyncOrNull(userWalletId: UserWalletId, stakingID: StakingID): YieldBalance? /** Store [items] by [userWalletId] */ suspend fun store(userWalletId: UserWalletId, items: Set) - /** Store [item] by [userWalletId], [integrationId] and [address] */ - suspend fun store(userWalletId: UserWalletId, integrationId: String, address: String, item: YieldBalanceWrapperDTO) + /** Store [item] by [userWalletId] and [stakingID] */ + suspend fun store(userWalletId: UserWalletId, stakingID: StakingID, item: YieldBalanceWrapperDTO) - suspend fun refresh(userWalletId: UserWalletId, addressWithIntegrationIdMap: Map) + /** Store [item] by [userWalletId] */ + suspend fun storeSingleYieldBalance(userWalletId: UserWalletId, item: YieldBalance) + + /** Refresh balances of [stakingIds] by [userWalletId] */ + suspend fun refresh(userWalletId: UserWalletId, stakingIds: List) + + data class StakingID(val integrationId: String, val address: String) } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/token/converter/YieldBalanceConverter.kt b/core/datasource/src/main/java/com/tangem/datasource/local/token/converter/YieldBalanceConverter.kt index 9df25f3294..6fc465801a 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/token/converter/YieldBalanceConverter.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/token/converter/YieldBalanceConverter.kt @@ -7,14 +7,18 @@ import com.tangem.domain.staking.model.stakekit.YieldBalance import com.tangem.domain.staking.model.stakekit.YieldBalanceItem import com.tangem.utils.converter.Converter -internal class YieldBalanceConverter(private val isCached: Boolean) : Converter { +internal class YieldBalanceConverter( + private val source: StatusSource, +) : Converter { + + constructor(isCached: Boolean) : this(source = if (isCached) StatusSource.CACHE else StatusSource.ACTUAL) override fun convert(value: YieldBalanceWrapperDTO): YieldBalance { return if (value.balances.isEmpty()) { YieldBalance.Empty( integrationId = value.integrationId, address = value.addresses.address, - source = if (isCached) StatusSource.CACHE else StatusSource.ACTUAL, + source = source, ) } else { YieldBalance.Data( @@ -40,7 +44,7 @@ internal class YieldBalanceConverter(private val isCached: Boolean) : Converter< .sortedWith(compareBy({ it.type }, { it.amount })), integrationId = value.integrationId, ), - source = if (isCached) StatusSource.CACHE else StatusSource.ACTUAL, + source = source, ) } } diff --git a/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt b/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt index 8482f9a190..876e516350 100644 --- a/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt +++ b/data/staking/src/main/java/com/tangem/data/staking/DefaultStakingRepository.kt @@ -372,20 +372,33 @@ internal class DefaultStakingRepository( } val requestBody = getBalanceRequestData(address, integrationId) - val result = stakeKitApi.getSingleYieldBalance( - integrationId = requestBody.integrationId, - body = requestBody, - ).getOrThrow() - stakingBalanceStore.store( - userWalletId = userWalletId, - integrationId = requestBody.integrationId, - address = address, - item = YieldBalanceWrapperDTO( - balances = result, - integrationId = requestBody.integrationId, - addresses = requestBody.addresses, - ), + safeApiCall( + call = { + val result = stakeKitApi.getSingleYieldBalance( + integrationId = requestBody.integrationId, + body = requestBody, + ).bind() + + stakingBalanceStore.store( + userWalletId = userWalletId, + stakingID = StakingBalanceStore.StakingID( + integrationId = requestBody.integrationId, + address = address, + ), + item = YieldBalanceWrapperDTO( + balances = result, + integrationId = requestBody.integrationId, + addresses = requestBody.addresses, + ), + ) + }, + onError = { + stakingBalanceStore.storeSingleYieldBalance( + userWalletId = userWalletId, + item = YieldBalance.Error(integrationId = requestBody.integrationId, address = address), + ) + }, ) }, ) @@ -399,7 +412,11 @@ internal class DefaultStakingRepository( val address = walletManagersFacade.getDefaultAddress(userWalletId, cryptoCurrency.network).orEmpty() val integrationId = integrationIdMap[getIntegrationKey(cryptoCurrency.id)] ?: error("Could not get integrationId") - stakingBalanceStore.get(userWalletId, address, integrationId) + + stakingBalanceStore.get( + userWalletId = userWalletId, + stakingID = StakingBalanceStore.StakingID(integrationId = integrationId, address = address), + ) .distinctUntilChanged() .collectLatest { if (it != null) { @@ -413,10 +430,7 @@ internal class DefaultStakingRepository( } withContext(dispatchers.io) { - fetchSingleYieldBalance( - userWalletId, - cryptoCurrency, - ) + fetchSingleYieldBalance(userWalletId = userWalletId, cryptoCurrency = cryptoCurrency) } }.cancellable() @@ -431,7 +445,10 @@ internal class DefaultStakingRepository( val integrationId = integrationIdMap[getIntegrationKey(cryptoCurrency.id)] ?: error("Could not get integrationId") - stakingBalanceStore.getSyncOrNull(userWalletId, address, integrationId) + stakingBalanceStore.getSyncOrNull( + userWalletId = userWalletId, + stakingID = StakingBalanceStore.StakingID(integrationId = integrationId, address = address), + ) ?: YieldBalance.Error(integrationId, address) } @@ -444,21 +461,7 @@ internal class DefaultStakingRepository( if (refresh) { stakingBalanceStore.refresh( userWalletId = userWalletId, - addressWithIntegrationIdMap = cryptoCurrencies - .mapNotNull { currency -> - val addresses = walletManagersFacade.getAddresses(userWalletId, currency.network) - val integrationId = integrationIdMap[getIntegrationKey(currency.id)] - - if (integrationId != null) { - addresses to integrationId - } else { - null - } - } - .flatMap { (addresses, integrationId) -> - addresses.map { address -> integrationId to address.value } - } - .toMap(), + stakingIds = cryptoCurrencies.mapStakingId(userWalletId), ) } @@ -523,20 +526,52 @@ internal class DefaultStakingRepository( ) } + private suspend fun List.mapStakingId( + userWalletId: UserWalletId, + ): List { + return this + .mapNotNull { currency -> + val addresses = walletManagersFacade.getAddresses(userWalletId, currency.network) + val integrationId = integrationIdMap[getIntegrationKey(currency.id)] + + if (integrationId != null) { + addresses to integrationId + } else { + null + } + } + .flatMap { (addresses, integrationId) -> + addresses.map { address -> + StakingBalanceStore.StakingID( + integrationId = integrationId, + address = address.value, + ) + } + } + } + override fun getMultiYieldBalanceUpdates( userWalletId: UserWalletId, cryptoCurrencies: List, ): Flow { - return stakingBalanceStore.get(userWalletId) - .map(YieldBalanceListConverter::convert) - .flowOn(dispatchers.io) + return flow { + stakingBalanceStore.get( + userWalletId = userWalletId, + stakingIds = cryptoCurrencies.mapStakingId(userWalletId), + ) + .map(YieldBalanceListConverter::convert) + .collect { emit(it) } + } } override fun getMultiYieldBalanceUpdatesLegacy( userWalletId: UserWalletId, cryptoCurrencies: List, ): Flow = channelFlow { - stakingBalanceStore.get(userWalletId) + stakingBalanceStore.get( + userWalletId = userWalletId, + stakingIds = cryptoCurrencies.mapStakingId(userWalletId), + ) .onEach { val balances = YieldBalanceListConverter.convert(it) send(balances) @@ -554,7 +589,8 @@ internal class DefaultStakingRepository( ): YieldBalanceList = withContext(dispatchers.io) { fetchMultiYieldBalance(userWalletId, cryptoCurrencies) - stakingBalanceStore.getSyncOrNull(userWalletId)?.let(YieldBalanceListConverter::convert) + stakingBalanceStore.getSyncOrNull(userWalletId, cryptoCurrencies.mapStakingId(userWalletId)) + ?.let(YieldBalanceListConverter::convert) ?: YieldBalanceList.Error } @@ -697,6 +733,7 @@ internal class DefaultStakingRepository( } } + @Suppress("unused") private companion object { const val YIELDS_STORE_KEY = "yields" diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CachedCurrenciesStatusesOperations.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CachedCurrenciesStatusesOperations.kt index be0fdb52a2..739ad63738 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CachedCurrenciesStatusesOperations.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CachedCurrenciesStatusesOperations.kt @@ -112,7 +112,13 @@ class CachedCurrenciesStatusesOperations( val rawCurrenciesIds = currenciesIds.mapNotNullTo(mutableSetOf()) { it.rawCurrencyId } quotesRepository.fetchQuotes(rawCurrenciesIds) }, - async { stakingRepository.fetchMultiYieldBalance(userWalletId, currencies) }, + async { + if (currencies.size == 1) { + stakingRepository.fetchSingleYieldBalance(userWalletId, currencies.first()) + } else { + stakingRepository.fetchMultiYieldBalance(userWalletId, currencies) + } + }, ) } .map { } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt index 01d1f570c7..3a4f7fe8ba 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt @@ -122,7 +122,7 @@ internal class StakingModel @Inject constructor( private val shareManager: ShareManager, @DelayedWork private val coroutineScope: CoroutineScope, private val innerRouter: InnerStakingRouter, - private val appRouter: AppRouter, + appRouter: AppRouter, ) : Model(), StakingClickIntents { val uiState: StateFlow = stateController.uiState @@ -207,6 +207,7 @@ internal class StakingModel @Inject constructor( private val transactionsInProgress: CopyOnWriteArrayList = CopyOnWriteArrayList() + private var actionsJobHolder: JobHolder = JobHolder() private var approvalJobHolder: JobHolder = JobHolder() private var feeJobHolder: JobHolder = JobHolder() private var sendTransactionJobHolder = JobHolder() @@ -274,6 +275,7 @@ internal class StakingModel @Inject constructor( appCurrencyProvider = Provider { appCurrency }, feeCryptoCurrencyStatus = feeCryptoCurrencyStatus, fee = gasEstimate, + cryptoCurrencyStatus = cryptoCurrencyStatus, ), ) updateNotifications() @@ -293,6 +295,7 @@ internal class StakingModel @Inject constructor( appCurrencyProvider = Provider { appCurrency }, feeCryptoCurrencyStatus = feeCryptoCurrencyStatus, fee = fee, + cryptoCurrencyStatus = cryptoCurrencyStatus, ), ) updateNotifications() @@ -312,25 +315,26 @@ internal class StakingModel @Inject constructor( }, onConstructError = { error -> stakingEventFactory.createStakingErrorAlert(error) - stateController.update(SetConfirmationStateResetAssentTransformer) + stateController.update(SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus)) }, onSendSuccess = { txUrl -> stakingAnalyticSender.sendTransactionStakingAnalytics(stateController.value) transactionsInProgress.clear() - stateController.update(SetConfirmationStateCompletedTransformer(txUrl)) + stateController.update(SetConfirmationStateCompletedTransformer(txUrl, cryptoCurrencyStatus)) }, onSendError = { error -> analyticsEventHandler.send(StakingAnalyticsEvent.TransactionError) stakingEventFactory.createSendTransactionErrorAlert(error) - stateController.update(SetConfirmationStateResetAssentTransformer) + stateController.update(SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus)) }, onFeeIncreased = { increasedFee -> stateController.updateAll( - SetConfirmationStateResetAssentTransformer, + SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus), SetConfirmationStateAssentTransformer( appCurrencyProvider = Provider { appCurrency }, feeCryptoCurrencyStatus = feeCryptoCurrencyStatus, fee = increasedFee, + cryptoCurrencyStatus = cryptoCurrencyStatus, ), ) stateController.updateEvent( @@ -355,7 +359,9 @@ internal class StakingModel @Inject constructor( } if (!isApprovalInProgress) { stakingStateRouter.onPrevClick() - stateController.update(SetConfirmationStateResetAssentTransformer) + stateController.update( + SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus = cryptoCurrencyStatus), + ) } } null, @@ -545,6 +551,7 @@ internal class StakingModel @Inject constructor( stateController.update(SetApprovalBottomSheetTypeChangeTransformer(approveType)) } + @Suppress("LongMethod") override fun onApprovalClick() { modelScope.launch { stateController.update( @@ -581,10 +588,13 @@ internal class StakingModel @Inject constructor( appCurrencyProvider = Provider { appCurrency }, feeCryptoCurrencyStatus = feeCryptoCurrencyStatus, fee = TransactionFee.Single(fee), + cryptoCurrencyStatus = cryptoCurrencyStatus, ), ) stakingEventFactory.createGenericErrorAlert(error.message ?: error.toString()) - stateController.update(SetConfirmationStateResetAssentTransformer) + stateController.update( + SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus = cryptoCurrencyStatus), + ) return@launch }, ifRight = { it }, @@ -603,10 +613,13 @@ internal class StakingModel @Inject constructor( appCurrencyProvider = Provider { appCurrency }, feeCryptoCurrencyStatus = feeCryptoCurrencyStatus, fee = TransactionFee.Single(fee), + cryptoCurrencyStatus = cryptoCurrencyStatus, ), ) stakingEventFactory.createSendTransactionErrorAlert(error) - stateController.update(SetConfirmationStateResetAssentTransformer) + stateController.update( + SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus = cryptoCurrencyStatus), + ) }, ifRight = { stakingAnalyticSender.sendTransactionApprovalAnalytics(tokenCryptoCurrency) @@ -851,10 +864,16 @@ internal class StakingModel @Inject constructor( }, ifLeft = { stakingEventFactory.createGenericErrorAlert(it.toString()) - stateController.update(SetConfirmationStateResetAssentTransformer) + stateController.update( + SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus = cryptoCurrencyStatus), + ) }, ) - getCurrencyStatusUpdatesUseCase(userWalletId, cryptoCurrencyId, false) + getCurrencyStatusUpdatesUseCase( + userWalletId = userWalletId, + currencyId = cryptoCurrencyId, + isSingleWalletWithTokens = false, + ) .conflate() .distinctUntilChangedBy { it.getOrNull()?.value?.yieldBalance } .filter { value.currentStep == StakingStep.InitialInfo } @@ -888,12 +907,14 @@ internal class StakingModel @Inject constructor( setupApprovalNeeded() setupIsAnyTokenStaked() checkIfSubtractAvailable() - subscribeOnActionsUpdates() - subscribeOnStepChanges() + subscribeOnActionsUpdates(status) + subscribeOnStepChanges(status) }, ifLeft = { error -> stakingEventFactory.createGenericErrorAlert(error.toString()) - stateController.update(SetConfirmationStateResetAssentTransformer) + stateController.update( + SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus = cryptoCurrencyStatus), + ) }, ) } @@ -923,13 +944,13 @@ internal class StakingModel @Inject constructor( .launchIn(modelScope) } - private fun subscribeOnStepChanges() { + private fun subscribeOnStepChanges(status: CryptoCurrencyStatus) { uiState .distinctUntilChangedBy { it.currentStep } .onEach { when { isInitState() -> { - updateInitialData() + updateInitialData(status) balanceUpdater.initialUpdate() } isAssentState() -> { @@ -950,32 +971,30 @@ internal class StakingModel @Inject constructor( .saveIn(stepChangesJobHolder) } - private fun subscribeOnActionsUpdates() { - getActionsUseCase( - userWalletId = userWalletId, - cryptoCurrencyId = cryptoCurrencyId, - ) + private fun subscribeOnActionsUpdates(status: CryptoCurrencyStatus) { + getActionsUseCase(userWalletId = userWalletId, cryptoCurrencyId = cryptoCurrencyId) .conflate() .distinctUntilChanged() .onEach { result -> result.getOrNull()?.let { actions -> processingActions = actions if (isInitState()) { - updateInitialData() + updateInitialData(status) } } } .flowOn(dispatchers.main) .launchIn(modelScope) + .saveIn(actionsJobHolder) } - private fun updateInitialData() { + private fun updateInitialData(status: CryptoCurrencyStatus) { stateController.updateAll( SetInitialDataStateTransformer( clickIntents = this@StakingModel, yield = yield, isAnyTokenStaked = isAnyTokenStaked, - cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus }, + cryptoCurrencyStatus = status, userWalletProvider = Provider { userWallet }, appCurrencyProvider = Provider { appCurrency }, balancesToShowProvider = Provider { balancesToShow }, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/BalanceItemConverter.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/BalanceItemConverter.kt index 8051fb9e54..1449a49895 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/BalanceItemConverter.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/BalanceItemConverter.kt @@ -21,13 +21,12 @@ import org.joda.time.DateTime import java.util.Calendar internal class BalanceItemConverter( - private val cryptoCurrencyStatusProvider: Provider, + private val cryptoCurrencyStatus: CryptoCurrencyStatus, private val appCurrencyProvider: Provider, private val yield: Yield, ) : Converter { override fun convert(value: BalanceItem): BalanceState? { - val cryptoCurrencyStatus = cryptoCurrencyStatusProvider() val appCurrency = appCurrencyProvider() val cryptoCurrency = cryptoCurrencyStatus.currency diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/RewardsValidatorStateConverter.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/RewardsValidatorStateConverter.kt index d9996e2ded..d7a73fa6f9 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/RewardsValidatorStateConverter.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/RewardsValidatorStateConverter.kt @@ -20,13 +20,11 @@ import org.joda.time.DateTime import java.math.BigDecimal internal class RewardsValidatorStateConverter( - private val cryptoCurrencyStatusProvider: Provider, + private val cryptoCurrencyStatus: CryptoCurrencyStatus, private val appCurrencyProvider: Provider, private val yield: Yield, ) : Converter { override fun convert(value: Unit): StakingStates.RewardsValidatorsState { - val cryptoCurrencyStatus = cryptoCurrencyStatusProvider() - val yieldBalance = cryptoCurrencyStatus.value.yieldBalance return if (yieldBalance is YieldBalance.Data) { val balances = yieldBalance.balance.items diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/YieldBalancesConverter.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/YieldBalancesConverter.kt index 41c9881df8..ed5cb2cdad 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/YieldBalancesConverter.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/converters/YieldBalancesConverter.kt @@ -15,18 +15,17 @@ import com.tangem.utils.converter.Converter import kotlinx.collections.immutable.toPersistentList internal class YieldBalancesConverter( - private val cryptoCurrencyStatusProvider: Provider, + private val cryptoCurrencyStatus: CryptoCurrencyStatus, private val appCurrencyProvider: Provider, private val balancesToShowProvider: Provider>, private val yield: Yield, ) : Converter { private val balanceItemConverter by lazy(LazyThreadSafetyMode.NONE) { - BalanceItemConverter(cryptoCurrencyStatusProvider, appCurrencyProvider, yield) + BalanceItemConverter(cryptoCurrencyStatus, appCurrencyProvider, yield) } override fun convert(value: Unit): InnerYieldBalanceState { - val cryptoCurrencyStatus = cryptoCurrencyStatusProvider() val appCurrency = appCurrencyProvider() val cryptoCurrency = cryptoCurrencyStatus.currency @@ -68,7 +67,6 @@ internal class YieldBalancesConverter( .toPersistentList() private fun getRewardBlockType(): Pair { - val cryptoCurrencyStatus = cryptoCurrencyStatusProvider() val blockchainId = cryptoCurrencyStatus.currency.network.id.value val yieldBalance = cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data val rewards = yieldBalance?.balance?.items diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingBalanceUpdater.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingBalanceUpdater.kt index c84db7f3ea..b1058db489 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingBalanceUpdater.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingBalanceUpdater.kt @@ -1,7 +1,7 @@ package com.tangem.features.staking.impl.presentation.state.helpers -import com.tangem.domain.staking.FetchStakingYieldBalanceUseCase import com.tangem.domain.staking.FetchActionsUseCase +import com.tangem.domain.staking.FetchStakingYieldBalanceUseCase import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.domain.staking.model.stakekit.action.StakingActionStatus import com.tangem.domain.tokens.FetchPendingTransactionsUseCase diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateAssentTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateAssentTransformer.kt index 85443b4096..56e01d3a83 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateAssentTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateAssentTransformer.kt @@ -13,6 +13,7 @@ internal class SetConfirmationStateAssentTransformer( private val appCurrencyProvider: Provider, private val feeCryptoCurrencyStatus: CryptoCurrencyStatus?, private val fee: Fee, + private val cryptoCurrencyStatus: CryptoCurrencyStatus, ) : Transformer { override fun transform(prevState: StakingUiState): StakingUiState { @@ -32,7 +33,9 @@ internal class SetConfirmationStateAssentTransformer( appCurrency = appCurrencyProvider(), isFeeApproximate = false, ), - isPrimaryButtonEnabled = true, + isPrimaryButtonEnabled = with(cryptoCurrencyStatus.value) { + sources.yieldBalanceSource.isActual() && sources.networkSource.isActual() + }, ) } else { return this diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateCompletedTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateCompletedTransformer.kt index 4ecbf95344..7190ad5ae1 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateCompletedTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateCompletedTransformer.kt @@ -1,12 +1,17 @@ package com.tangem.features.staking.impl.presentation.state.transformers import com.tangem.core.ui.extensions.TextReference -import com.tangem.features.staking.impl.presentation.state.* +import com.tangem.domain.tokens.model.CryptoCurrencyStatus +import com.tangem.features.staking.impl.presentation.state.InnerConfirmationStakingState +import com.tangem.features.staking.impl.presentation.state.StakingStates +import com.tangem.features.staking.impl.presentation.state.StakingUiState +import com.tangem.features.staking.impl.presentation.state.TransactionDoneState import com.tangem.utils.transformer.Transformer import kotlinx.collections.immutable.persistentListOf internal class SetConfirmationStateCompletedTransformer( private val txUrl: String, + private val cryptoCurrencyStatus: CryptoCurrencyStatus, ) : Transformer { override fun transform(prevState: StakingUiState): StakingUiState { @@ -18,7 +23,9 @@ internal class SetConfirmationStateCompletedTransformer( private fun StakingStates.ConfirmationState.copyWrapped(): StakingStates.ConfirmationState { return if (this is StakingStates.ConfirmationState.Data) { copy( - isPrimaryButtonEnabled = true, + isPrimaryButtonEnabled = with(cryptoCurrencyStatus.value) { + sources.yieldBalanceSource.isActual() && sources.networkSource.isActual() + }, innerState = InnerConfirmationStakingState.COMPLETED, footerText = TextReference.EMPTY, notifications = persistentListOf(), diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateInitTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateInitTransformer.kt index c55fb7a485..b3694b4fdf 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateInitTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateInitTransformer.kt @@ -63,7 +63,9 @@ internal class SetConfirmationStateInitTransformer( actionType = actionType, balanceState = balanceState, confirmationState = StakingStates.ConfirmationState.Data( - isPrimaryButtonEnabled = false, + isPrimaryButtonEnabled = with(cryptoCurrencyStatus.value) { + sources.yieldBalanceSource.isActual() && sources.networkSource.isActual() + }, innerState = InnerConfirmationStakingState.ASSENT, feeState = FeeState.Loading, notifications = persistentListOf(), diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateResetAssentTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateResetAssentTransformer.kt index 1c1c7103dc..327ec4ae8e 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateResetAssentTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateResetAssentTransformer.kt @@ -1,17 +1,22 @@ package com.tangem.features.staking.impl.presentation.state.transformers +import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.features.staking.impl.presentation.state.InnerConfirmationStakingState import com.tangem.features.staking.impl.presentation.state.StakingStates import com.tangem.features.staking.impl.presentation.state.StakingUiState import com.tangem.utils.transformer.Transformer -internal object SetConfirmationStateResetAssentTransformer : Transformer { +internal class SetConfirmationStateResetAssentTransformer( + private val cryptoCurrencyStatus: CryptoCurrencyStatus, +) : Transformer { override fun transform(prevState: StakingUiState): StakingUiState { val confirmationState = prevState.confirmationState return prevState.copy( confirmationState = if (confirmationState is StakingStates.ConfirmationState.Data) { confirmationState.copy( - isPrimaryButtonEnabled = true, + isPrimaryButtonEnabled = with(cryptoCurrencyStatus.value) { + sources.yieldBalanceSource.isActual() && sources.networkSource.isActual() + }, innerState = InnerConfirmationStakingState.ASSENT, ) } else { diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt index 873626c210..67eef70501 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt @@ -5,25 +5,28 @@ import com.tangem.common.ui.amountScreen.converters.AmountStateConverter import com.tangem.common.ui.amountScreen.models.AmountParameters import com.tangem.common.ui.amountScreen.models.AmountState import com.tangem.common.ui.amountScreen.models.EnterAmountBoundary +import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter import com.tangem.core.ui.components.list.RoundedListWithDividersItemData import com.tangem.core.ui.extensions.* import com.tangem.core.ui.format.bigdecimal.crypto import com.tangem.core.ui.format.bigdecimal.format import com.tangem.core.ui.format.bigdecimal.percent -import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig import com.tangem.domain.appcurrency.model.AppCurrency import com.tangem.domain.staking.model.stakekit.BalanceItem import com.tangem.domain.staking.model.stakekit.Yield import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.wallets.models.UserWallet import com.tangem.features.staking.impl.R -import com.tangem.features.staking.impl.presentation.state.* +import com.tangem.features.staking.impl.presentation.model.StakingClickIntents +import com.tangem.features.staking.impl.presentation.state.InnerYieldBalanceState +import com.tangem.features.staking.impl.presentation.state.StakingStates +import com.tangem.features.staking.impl.presentation.state.StakingStep +import com.tangem.features.staking.impl.presentation.state.StakingUiState import com.tangem.features.staking.impl.presentation.state.bottomsheet.InfoType import com.tangem.features.staking.impl.presentation.state.converters.RewardsValidatorStateConverter import com.tangem.features.staking.impl.presentation.state.converters.YieldBalancesConverter import com.tangem.features.staking.impl.presentation.state.utils.getRewardScheduleText -import com.tangem.features.staking.impl.presentation.model.StakingClickIntents import com.tangem.lib.crypto.BlockchainUtils.isPolkadot import com.tangem.utils.Provider import com.tangem.utils.isNullOrZero @@ -37,7 +40,7 @@ internal class SetInitialDataStateTransformer( private val clickIntents: StakingClickIntents, private val yield: Yield, private val isAnyTokenStaked: Boolean, - private val cryptoCurrencyStatusProvider: Provider, + private val cryptoCurrencyStatus: CryptoCurrencyStatus, private val userWalletProvider: Provider, private val appCurrencyProvider: Provider, private val balancesToShowProvider: Provider>, @@ -46,20 +49,20 @@ internal class SetInitialDataStateTransformer( private val iconStateConverter by lazy(::CryptoCurrencyToIconStateConverter) private val rewardsValidatorStateConverter by lazy(LazyThreadSafetyMode.NONE) { - RewardsValidatorStateConverter(cryptoCurrencyStatusProvider, appCurrencyProvider, yield) + RewardsValidatorStateConverter(cryptoCurrencyStatus, appCurrencyProvider, yield) } private val yieldBalancesConverter by lazy(LazyThreadSafetyMode.NONE) { YieldBalancesConverter( - cryptoCurrencyStatusProvider, - appCurrencyProvider, - balancesToShowProvider, - yield, + cryptoCurrencyStatus = cryptoCurrencyStatus, + appCurrencyProvider = appCurrencyProvider, + balancesToShowProvider = balancesToShowProvider, + yield = yield, ) } override fun transform(prevState: StakingUiState): StakingUiState { - val cryptoCurrency = cryptoCurrencyStatusProvider().currency + val cryptoCurrency = cryptoCurrencyStatus.currency return prevState.copy( title = TextReference.EMPTY, cryptoCurrencyName = cryptoCurrency.name, @@ -77,8 +80,12 @@ internal class SetInitialDataStateTransformer( private fun createInitialInfoState(): StakingStates.InitialInfoState.Data { val yieldBalance = yieldBalancesConverter.convert(Unit) + + val status = cryptoCurrencyStatus.value return StakingStates.InitialInfoState.Data( - isPrimaryButtonEnabled = !cryptoCurrencyStatusProvider().value.amount.isNullOrZero(), + isPrimaryButtonEnabled = with(status) { + !amount.isNullOrZero() && sources.yieldBalanceSource.isActual() && sources.networkSource.isActual() + }, showBanner = !isAnyTokenStaked && yieldBalance == InnerYieldBalanceState.Empty, aprRange = getAprRange(yield.preferredValidators), infoItems = getInfoItems(), @@ -92,8 +99,6 @@ internal class SetInitialDataStateTransformer( } private fun getInfoItems(): PersistentList { - val cryptoCurrencyStatus = cryptoCurrencyStatusProvider() - return listOfNotNull( createAnnualPercentageRateItem(), createAvailableItem(cryptoCurrencyStatus), @@ -187,7 +192,7 @@ internal class SetInitialDataStateTransformer( private fun createRewardScheduleItem(): RoundedListWithDividersItemData? { val endTextReference = getRewardScheduleText( rewardSchedule = yield.metadata.rewardSchedule, - networkId = cryptoCurrencyStatusProvider().currency.network.id.value, + networkId = cryptoCurrencyStatus.currency.network.id.value, decapitalize = false, ) ?: return null @@ -200,7 +205,7 @@ internal class SetInitialDataStateTransformer( } private fun createInitialAmountState(): AmountState { - val cryptoBalanceValue = cryptoCurrencyStatusProvider().value + val cryptoBalanceValue = cryptoCurrencyStatus.value val maxEnterAmount = EnterAmountBoundary( amount = cryptoBalanceValue.amount, fiatAmount = cryptoBalanceValue.fiatAmount, @@ -208,7 +213,7 @@ internal class SetInitialDataStateTransformer( ) return AmountStateConverter( clickIntents = clickIntents, - cryptoCurrencyStatusProvider = cryptoCurrencyStatusProvider, + cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus }, appCurrencyProvider = appCurrencyProvider, iconStateConverter = iconStateConverter, maxEnterAmount = maxEnterAmount, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/approval/SetConfirmationStateAssentApprovalTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/approval/SetConfirmationStateAssentApprovalTransformer.kt index 6f331795e4..0729792529 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/approval/SetConfirmationStateAssentApprovalTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/approval/SetConfirmationStateAssentApprovalTransformer.kt @@ -14,6 +14,7 @@ internal class SetConfirmationStateAssentApprovalTransformer( private val appCurrencyProvider: Provider, private val feeCryptoCurrencyStatus: CryptoCurrencyStatus?, private val fee: TransactionFee, + private val cryptoCurrencyStatus: CryptoCurrencyStatus, ) : Transformer { override fun transform(prevState: StakingUiState): StakingUiState { @@ -35,7 +36,9 @@ internal class SetConfirmationStateAssentApprovalTransformer( appCurrency = appCurrencyProvider(), isFeeApproximate = false, ), - isPrimaryButtonEnabled = true, + isPrimaryButtonEnabled = with(cryptoCurrencyStatus.value) { + sources.yieldBalanceSource.isActual() && sources.networkSource.isActual() + }, isApprovalNeeded = true, ) } else { diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt index 6aeb94cc74..40dbd696c0 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/notifications/AddStakingNotificationsTransformer.kt @@ -114,6 +114,10 @@ internal class AddStakingNotificationsTransformer( ) }.toImmutableList() + val isActualSources = with(cryptoCurrencyStatus.value) { + sources.yieldBalanceSource.isActual() && sources.networkSource.isActual() + } + return prevState.copy( confirmationState = confirmationState.copy( notifications = notifications.toImmutableList(), @@ -122,7 +126,7 @@ internal class AddStakingNotificationsTransformer( it is NotificationUM.Error || it is NotificationUM.Warning.NetworkFeeUnreachable || it is StakingNotification.Warning.TransactionInProgress - }, + } && isActualSources, ), ) } diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsBalanceSelectStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsBalanceSelectStateConverter.kt index 4a76d6f1c9..b08ab69246 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsBalanceSelectStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsBalanceSelectStateConverter.kt @@ -20,9 +20,14 @@ internal class TokenDetailsBalanceSelectStateConverter( override fun convert(value: TokenBalanceSegmentedButtonConfig): TokenDetailsState { return with(currentStateProvider()) { - if (stakingBlocksState !is StakingBlockUM.Staked) return this val cryptoCurrencyStatus = cryptoCurrencyStatusProvider() ?: return this + if (stakingBlocksState !is StakingBlockUM.Staked && + stakingBlocksState !is StakingBlockUM.TemporaryUnavailable + ) { + return this + } + val yieldBalance = cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data val stakingCryptoAmount = yieldBalance?.getTotalWithRewardsStakingBalance() val stakingFiatAmount = stakingCryptoAmount?.let { cryptoCurrencyStatus.value.fiatRate?.multiply(it) }