diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/StakeKitApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/StakeKitApi.kt index b1f2170fea..cca877d764 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/StakeKitApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/stakekit/StakeKitApi.kt @@ -16,7 +16,7 @@ import retrofit2.http.* interface StakeKitApi { @GET("yields/enabled") - suspend fun getMultipleYields( + suspend fun getEnabledYields( @Query("preferredValidatorsOnly") preferredValidatorsOnly: Boolean? = null, @Query("ledgerWalletAPICompatible") ledgerWalletAPICompatible: Boolean? = null, @Query("type") type: YieldType? = null, 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 0e2ae15ec3..985a008daf 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 @@ -5,7 +5,7 @@ import com.tangem.datasource.local.datastore.core.StringKeyDataStore import com.tangem.domain.wallets.models.UserWalletId import com.tangem.utils.extensions.addOrReplace import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.flow.map import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock @@ -29,9 +29,13 @@ internal class DefaultStakingBalanceStore( } } - override fun get(userWalletId: UserWalletId, address: String, integrationId: String): Flow { + override fun get( + userWalletId: UserWalletId, + address: String, + integrationId: String, + ): Flow { return dataStore.get(userWalletId.stringValue) - .mapNotNull { balances -> + .map { balances -> balances.firstOrNull { it.integrationId == integrationId && it.addresses.address == address } } } 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 601b11ccb0..8e10d5f395 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 @@ -12,7 +12,7 @@ interface StakingBalanceStore { suspend fun store(userWalletId: UserWalletId, items: Set) - fun get(userWalletId: UserWalletId, address: String, integrationId: String): Flow + fun get(userWalletId: UserWalletId, address: String, integrationId: String): Flow suspend fun getSyncOrNull( userWalletId: UserWalletId, 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 2ccac4081b..5251158860 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 @@ -111,7 +111,7 @@ internal class DefaultStakingRepository( rawNetworkId.plus(rawCurrencyId) } - override fun isStakingSupported(integrationKey: String): Boolean { + override fun isStakingSupportedInMobileApp(integrationKey: String): Boolean { return integrationIdMap.containsKey(integrationKey) } @@ -121,7 +121,7 @@ internal class DefaultStakingRepository( key = YIELDS_STORE_KEY, skipCache = refresh, block = { - val stakingTokensWithYields = stakeKitApi.getMultipleYields(preferredValidatorsOnly = true) + val stakingTokensWithYields = stakeKitApi.getEnabledYields(preferredValidatorsOnly = true) .getOrThrow() stakingYieldsStore.store(stakingTokensWithYields.data) @@ -166,17 +166,22 @@ internal class DefaultStakingRepository( val rawCurrencyId = cryptoCurrency.id.rawCurrencyId ?: return StakingAvailability.Unavailable return withContext(dispatchers.io) { - val yields = getEnabledYields() ?: return@withContext StakingAvailability.Unavailable + val isSupportedInMobileApp = isStakingSupportedInMobileApp(getIntegrationKey(cryptoCurrency.id)) + + val yields = getEnabledYields() ?: return@withContext if (isSupportedInMobileApp) { + StakingAvailability.TemporaryUnavailable + } else { + StakingAvailability.Unavailable + } val prefetchedYield = findPrefetchedYield(yields, rawCurrencyId, cryptoCurrency.symbol) - val isSupported = isStakingSupported(getIntegrationKey(cryptoCurrency.id)) when { - prefetchedYield != null && isSupported -> { + prefetchedYield != null && isSupportedInMobileApp -> { StakingAvailability.Available(prefetchedYield.id) } - prefetchedYield == null && isSupported -> { - StakingAvailability.TemporaryDisabled + prefetchedYield == null && isSupportedInMobileApp -> { + StakingAvailability.TemporaryUnavailable } else -> StakingAvailability.Unavailable } @@ -336,8 +341,13 @@ internal class DefaultStakingRepository( val integrationId = integrationIdMap[getIntegrationKey(cryptoCurrency.id)] ?: error("Could not get integrationId") stakingBalanceStore.get(userWalletId, address, integrationId) + .distinctUntilChanged() .collectLatest { - send(yieldBalanceConverter.convert(it)) + if (it != null) { + send(yieldBalanceConverter.convert(it)) + } else { + error("No yield balance available for currency ${cryptoCurrency.id.value}") + } } } @@ -385,12 +395,13 @@ internal class DefaultStakingRepository( key = getYieldBalancesKey(userWalletId), skipCache = refresh, block = { + val yields = getEnabledYields() ?: error("No yields found") val availableCurrencies = cryptoCurrencies .mapNotNull { currency -> val addresses = walletManagersFacade.getAddresses(userWalletId, currency.network) val integrationId = integrationIdMap[getIntegrationKey(currency.id)] - if (integrationId != null) { + if (integrationId != null && yields.any { it.id == integrationId }) { addresses to integrationId } else { null diff --git a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/StakingAvailability.kt b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/StakingAvailability.kt index d7eaa306e0..182d5fbec6 100644 --- a/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/StakingAvailability.kt +++ b/domain/staking/models/src/main/kotlin/com/tangem/domain/staking/model/StakingAvailability.kt @@ -6,5 +6,5 @@ sealed class StakingAvailability { data object Unavailable : StakingAvailability() - data object TemporaryDisabled : StakingAvailability() + data object TemporaryUnavailable : StakingAvailability() } \ No newline at end of file diff --git a/domain/staking/src/main/java/com/tangem/domain/staking/repositories/StakingRepository.kt b/domain/staking/src/main/java/com/tangem/domain/staking/repositories/StakingRepository.kt index ba93d3e3cb..3484bc6151 100644 --- a/domain/staking/src/main/java/com/tangem/domain/staking/repositories/StakingRepository.kt +++ b/domain/staking/src/main/java/com/tangem/domain/staking/repositories/StakingRepository.kt @@ -23,7 +23,7 @@ interface StakingRepository { fun getIntegrationKey(cryptoCurrencyId: CryptoCurrency.ID): String - fun isStakingSupported(integrationKey: String): Boolean + fun isStakingSupportedInMobileApp(integrationKey: String): Boolean suspend fun fetchEnabledYields(refresh: Boolean) diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrenciesStatusesLceOperations.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrenciesStatusesLceOperations.kt index ff2271edbb..526962c0e1 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrenciesStatusesLceOperations.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrenciesStatusesLceOperations.kt @@ -146,7 +146,7 @@ internal class CurrenciesStatusesLceOperations( val quote = quotes?.firstOrNull { it.rawCurrencyId == currency.id.rawCurrencyId } val networkStatus = networksStatuses?.firstOrNull { it.network == currency.network } val address = extractAddress(networkStatus) - val isStakingSupported = stakingRepository.isStakingSupported( + val isStakingSupported = stakingRepository.isStakingSupportedInMobileApp( stakingRepository.getIntegrationKey(currency.id), ) val yieldBalance = if (isStakingSupported) { diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrenciesStatusesOperations.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrenciesStatusesOperations.kt index ac688c34ef..a7e0233a4b 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrenciesStatusesOperations.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrenciesStatusesOperations.kt @@ -271,7 +271,7 @@ internal class CurrenciesStatusesOperations( val networkStatus = networksStatuses?.firstOrNull { it.network == currency.network } val address = extractAddress(networkStatus) - val isStakingSupported = stakingRepository.isStakingSupported( + val isStakingSupported = stakingRepository.isStakingSupportedInMobileApp( stakingRepository.getIntegrationKey(currency.id), ) val yieldBalance = if (isStakingSupported) { diff --git a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/repository/MockStakingRepository.kt b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/repository/MockStakingRepository.kt index cc3fc8d8b2..36242e041b 100644 --- a/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/repository/MockStakingRepository.kt +++ b/domain/tokens/src/test/kotlin/com/tangem/domain/tokens/repository/MockStakingRepository.kt @@ -26,7 +26,7 @@ class MockStakingRepository : StakingRepository { override fun getIntegrationKey(cryptoCurrencyId: CryptoCurrency.ID): String = "" - override fun isStakingSupported(currencyId: String): Boolean = true + override fun isStakingSupportedInMobileApp(integrationKey: String): Boolean = true override suspend fun fetchEnabledYields(refresh: Boolean) { /* no-op */ diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/TokenDetailsPreviewData.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/TokenDetailsPreviewData.kt index c75f89ca04..747cf08519 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/TokenDetailsPreviewData.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/TokenDetailsPreviewData.kt @@ -139,8 +139,8 @@ internal object TokenDetailsPreviewData { private val marketPriceLoading = MarketPriceBlockState.Loading(currencySymbol = "USDT") + val stakingTemporaryUnavailableBlock = StakingBlockUM.TemporaryUnavailable val stakingLoadingBlock = StakingBlockUM.Loading(iconState) - val stakingErrorBlock = StakingBlockUM.Error(iconState) val stakingAvailableBlock = StakingBlockUM.StakeAvailable( titleText = resourceReference( @@ -312,7 +312,6 @@ internal object TokenDetailsPreviewData { bottomSheetConfig = null, isBalanceHidden = false, isMarketPriceAvailable = false, - isStakingBlockShown = false, event = consumedEvent(), ) @@ -343,7 +342,6 @@ internal object TokenDetailsPreviewData { bottomSheetConfig = null, isBalanceHidden = false, isMarketPriceAvailable = true, - isStakingBlockShown = true, event = consumedEvent(), ) diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/StakingBlockUM.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/StakingBlockUM.kt index b29d476a32..55ba3c6fcc 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/StakingBlockUM.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/StakingBlockUM.kt @@ -6,7 +6,8 @@ import java.math.BigDecimal @Stable internal sealed interface StakingBlockUM { - data class Error(val iconState: IconState) : StakingBlockUM + + data object TemporaryUnavailable : StakingBlockUM data class Loading(val iconState: IconState) : StakingBlockUM diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/TokenDetailsState.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/TokenDetailsState.kt index ffc5d6f5c1..a3fbf4d4fb 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/TokenDetailsState.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/TokenDetailsState.kt @@ -17,7 +17,7 @@ internal data class TokenDetailsState( val tokenInfoBlockState: TokenInfoBlockState, val tokenBalanceBlockState: TokenDetailsBalanceBlockState, val marketPriceBlockState: MarketPriceBlockState, - val stakingBlocksState: StakingBlockUM, + val stakingBlocksState: StakingBlockUM?, val notifications: ImmutableList, val pendingTxs: PersistentList, val swapTxs: PersistentList, @@ -27,6 +27,5 @@ internal data class TokenDetailsState( val bottomSheetConfig: TangemBottomSheetConfig?, val isBalanceHidden: Boolean, val isMarketPriceAvailable: Boolean, - val isStakingBlockShown: Boolean, val event: StateEvent, ) \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt index dafdd53e8c..24a7b170f3 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt @@ -12,6 +12,7 @@ import com.tangem.core.ui.extensions.stringReference import com.tangem.core.ui.extensions.wrappedList import com.tangem.core.ui.utils.BigDecimalFormatter import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.staking.model.StakingAvailability import com.tangem.domain.staking.model.StakingEntryInfo import com.tangem.domain.staking.model.stakekit.RewardBlockType import com.tangem.domain.staking.model.stakekit.YieldBalance @@ -37,6 +38,7 @@ internal class TokenDetailsLoadedBalanceConverter( private val currentStateProvider: Provider, private val appCurrencyProvider: Provider, private val stakingEntryInfoProvider: Provider, + private val stakingAvailabilityProvider: Provider, private val symbol: String, private val decimals: Int, private val clickIntents: TokenDetailsClickIntents, @@ -57,7 +59,6 @@ internal class TokenDetailsLoadedBalanceConverter( private fun convertError(): TokenDetailsState { val state = currentStateProvider() return state.copy( - isStakingBlockShown = false, tokenBalanceBlockState = TokenDetailsBalanceBlockState.Error( actionButtons = state.tokenBalanceBlockState.actionButtons, balanceSegmentedButtonConfig = state.tokenBalanceBlockState.balanceSegmentedButtonConfig, @@ -137,19 +138,26 @@ internal class TokenDetailsLoadedBalanceConverter( } } - private fun getYieldBalance(status: CryptoCurrencyStatus, state: TokenDetailsState): StakingBlockUM { + private fun getYieldBalance(status: CryptoCurrencyStatus, state: TokenDetailsState): StakingBlockUM? { val yieldBalance = status.value.yieldBalance as? YieldBalance.Data val stakingCryptoAmount = yieldBalance?.getTotalStakingBalance() val stakingEntryInfo = stakingEntryInfoProvider.invoke() + val stakingAvailability = stakingAvailabilityProvider.invoke() val iconState = state.tokenInfoBlockState.iconState return when { + stakingAvailability == StakingAvailability.TemporaryUnavailable -> { + StakingBlockUM.TemporaryUnavailable + } + stakingAvailability == StakingAvailability.Unavailable -> { + null + } stakingCryptoAmount.isNullOrZero() && stakingEntryInfo != null -> { getStakeAvailableState(stakingEntryInfo, iconState) } stakingCryptoAmount.isNullOrZero() && stakingEntryInfo == null -> { - StakingBlockUM.Error(iconState = iconState) + null } else -> { val fiatRate = status.value.fiatRate diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt index 582ddd5560..04de376869 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsSkeletonStateConverter.kt @@ -73,7 +73,6 @@ internal class TokenDetailsSkeletonStateConverter( bottomSheetConfig = null, isBalanceHidden = true, isMarketPriceAvailable = value.id.rawCurrencyId != null, - isStakingBlockShown = false, event = consumedEvent(), ) } diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt index 54b171bf7d..133ebb4f93 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsStateFactory.kt @@ -19,7 +19,6 @@ import com.tangem.domain.card.NetworkHasDerivationUseCase import com.tangem.domain.common.CardTypesResolver import com.tangem.domain.staking.model.StakingAvailability import com.tangem.domain.staking.model.StakingEntryInfo -import com.tangem.domain.staking.model.stakekit.StakingError import com.tangem.domain.tokens.error.CurrencyStatusError import com.tangem.domain.tokens.model.* import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning @@ -50,6 +49,7 @@ internal class TokenDetailsStateFactory( private val currentStateProvider: Provider, private val appCurrencyProvider: Provider, private val stakingEntryInfoProvider: Provider, + private val stakingAvailabilityProvider: Provider, private val cryptoCurrencyStatusProvider: Provider, private val clickIntents: TokenDetailsClickIntents, private val networkHasDerivationUseCase: NetworkHasDerivationUseCase, @@ -78,6 +78,7 @@ internal class TokenDetailsStateFactory( currentStateProvider = currentStateProvider, appCurrencyProvider = appCurrencyProvider, stakingEntryInfoProvider = stakingEntryInfoProvider, + stakingAvailabilityProvider = stakingAvailabilityProvider, symbol = symbol, decimals = decimals, clickIntents = clickIntents, @@ -114,13 +115,6 @@ internal class TokenDetailsStateFactory( ) } - private val stakingStateConverter by lazy { - TokenStakingStateConverter( - currentStateProvider = currentStateProvider, - clickIntents = clickIntents, - ) - } - private val balanceSelectStateConverter by lazy { TokenDetailsBalanceSelectStateConverter( currentStateProvider = currentStateProvider, @@ -233,18 +227,6 @@ internal class TokenDetailsStateFactory( ) } - fun getStateWithUpdatedStakingAvailability(stakingAvailability: StakingAvailability): TokenDetailsState { - return currentStateProvider().copy( - isStakingBlockShown = stakingAvailability != StakingAvailability.Unavailable, - ) - } - - fun getStateWithStaking(stakingEither: Either): TokenDetailsState { - return currentStateProvider().copy( - stakingBlocksState = stakingStateConverter.convert(stakingEither), - ) - } - fun getRefreshingState(): TokenDetailsState { return refreshStateConverter.convert(true) } diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenStakingStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenStakingStateConverter.kt deleted file mode 100644 index 14bd84bf23..0000000000 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenStakingStateConverter.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.tangem.feature.tokendetails.presentation.tokendetails.state.factory - -import arrow.core.Either -import com.tangem.core.ui.extensions.resourceReference -import com.tangem.core.ui.extensions.wrappedList -import com.tangem.core.ui.utils.BigDecimalFormatter -import com.tangem.domain.staking.model.StakingEntryInfo -import com.tangem.domain.staking.model.stakekit.StakingError -import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingBlockUM -import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState -import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents -import com.tangem.features.tokendetails.impl.R -import com.tangem.utils.Provider -import com.tangem.utils.converter.Converter - -internal class TokenStakingStateConverter( - private val clickIntents: TokenDetailsClickIntents, - private val currentStateProvider: Provider, -) : Converter, StakingBlockUM> { - - override fun convert(value: Either): StakingBlockUM { - val state = currentStateProvider() - if (state.stakingBlocksState is StakingBlockUM.Staked) return state.stakingBlocksState - - val iconState = state.tokenInfoBlockState.iconState - return value.fold( - ifLeft = { - StakingBlockUM.Error(iconState = iconState) - }, - ifRight = { stakingEntryInfo -> - val apr = BigDecimalFormatter.formatPercent( - percent = stakingEntryInfo.apr, - useAbsoluteValue = true, - ) - StakingBlockUM.StakeAvailable( - titleText = resourceReference( - id = R.string.token_details_staking_block_title, - formatArgs = wrappedList(apr), - ), - subtitleText = resourceReference( - id = R.string.staking_notification_earn_rewards_text, - formatArgs = wrappedList(stakingEntryInfo.tokenSymbol), - ), - iconState = iconState, - onStakeClicked = clickIntents::onStakeBannerClick, - ) - }, - ) - } -} \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/TokenDetailsScreen.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/TokenDetailsScreen.kt index 0cda424f1a..1c953617df 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/TokenDetailsScreen.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/TokenDetailsScreen.kt @@ -164,7 +164,7 @@ internal fun TokenDetailsScreen(state: TokenDetailsState, tokenMarketBlockCompon } } - if (state.isStakingBlockShown) { + if (state.stakingBlocksState != null) { item( key = StakingBlockUM::class.java, contentType = StakingBlockUM::class.java, diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/StakingUnavailableBlock.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/StakingUnavailableBlock.kt new file mode 100644 index 0000000000..2341b0cab8 --- /dev/null +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/StakingUnavailableBlock.kt @@ -0,0 +1,51 @@ +package com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.staking + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview +import com.tangem.features.tokendetails.impl.R + +@Composable +internal fun StakingTemporaryUnavailableBlock(modifier: Modifier = Modifier) { + Column( + verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing4), + modifier = modifier + .fillMaxWidth() + .clip(TangemTheme.shapes.roundedCornersXMedium) + .background(TangemTheme.colors.background.primary) + .padding(TangemTheme.dimens.spacing12), + ) { + Text( + text = stringResource(R.string.staking_native), + style = TangemTheme.typography.subtitle2, + color = TangemTheme.colors.text.tertiary, + ) + Text( + text = stringResource(R.string.staking_notification_network_error_text), + style = TangemTheme.typography.body2, + color = TangemTheme.colors.text.tertiary, + ) + } +} + +// region Preview +@Preview(showBackground = true, widthDp = 360) +@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun StakingTemporaryUnavailableBlock_Preview() { + TangemThemePreview { + StakingTemporaryUnavailableBlock( + modifier = Modifier.padding(TangemTheme.dimens.spacing16), + ) + } +} + +// endregion \ No newline at end of file diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/TokenStakingBlock.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/TokenStakingBlock.kt index 8abb138685..a4db00c78a 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/TokenStakingBlock.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/ui/components/staking/TokenStakingBlock.kt @@ -23,8 +23,8 @@ import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.utils.getGreyScaleColorFilter import com.tangem.feature.tokendetails.presentation.tokendetails.TokenDetailsPreviewData.stakingAvailableBlock -import com.tangem.feature.tokendetails.presentation.tokendetails.TokenDetailsPreviewData.stakingErrorBlock import com.tangem.feature.tokendetails.presentation.tokendetails.TokenDetailsPreviewData.stakingLoadingBlock +import com.tangem.feature.tokendetails.presentation.tokendetails.TokenDetailsPreviewData.stakingTemporaryUnavailableBlock import com.tangem.feature.tokendetails.presentation.tokendetails.state.IconState import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingBlockUM import com.tangem.feature.tokendetails.presentation.tokendetails.ui.components.CurrencyIcon @@ -45,7 +45,7 @@ internal fun TokenStakingBlock(state: StakingBlockUM, isBalanceHidden: Boolean, label = "Staking block animation", ) { when (it) { - is StakingBlockUM.Error -> Row {} // TODO staking error + is StakingBlockUM.TemporaryUnavailable -> StakingTemporaryUnavailableBlock(modifier) is StakingBlockUM.Loading -> StakingLoading( iconState = it.iconState, modifier = modifier, @@ -185,7 +185,7 @@ private class StakingBlockStateProvider : CollectionPreviewParameterProvider>() private val stateFactory = TokenDetailsStateFactory( currentStateProvider = Provider { uiState.value }, appCurrencyProvider = Provider(selectedAppCurrencyFlow::value), stakingEntryInfoProvider = Provider { stakingEntryInfo }, + stakingAvailabilityProvider = Provider { stakingAvailability }, cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus }, clickIntents = this, networkHasDerivationUseCase = networkHasDerivationUseCase, @@ -389,12 +391,13 @@ internal class TokenDetailsViewModel @Inject constructor( private fun updateStakingInfo() { viewModelScope.launch { - val stakingAvailability = getStakingAvailabilityUseCase( + val availability = getStakingAvailabilityUseCase( userWalletId = userWalletId, cryptoCurrency = cryptoCurrency, ).getOrElse { StakingAvailability.Unavailable } - internalUiState.value = stateFactory.getStateWithUpdatedStakingAvailability(stakingAvailability) + stakingAvailability = availability + if (stakingAvailability is StakingAvailability.Available) { val stakingInfo = getStakingEntryInfoUseCase( cryptoCurrencyId = cryptoCurrency.id,