Updated on 2026-08-14
This commit is contained in:
parent
67be280129
commit
deb6d570b0
20 changed files with 111 additions and 105 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<YieldBalanceWrapperDTO> {
|
||||
override fun get(
|
||||
userWalletId: UserWalletId,
|
||||
address: String,
|
||||
integrationId: String,
|
||||
): Flow<YieldBalanceWrapperDTO?> {
|
||||
return dataStore.get(userWalletId.stringValue)
|
||||
.mapNotNull { balances ->
|
||||
.map { balances ->
|
||||
balances.firstOrNull { it.integrationId == integrationId && it.addresses.address == address }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ interface StakingBalanceStore {
|
|||
|
||||
suspend fun store(userWalletId: UserWalletId, items: Set<YieldBalanceWrapperDTO>)
|
||||
|
||||
fun get(userWalletId: UserWalletId, address: String, integrationId: String): Flow<YieldBalanceWrapperDTO>
|
||||
fun get(userWalletId: UserWalletId, address: String, integrationId: String): Flow<YieldBalanceWrapperDTO?>
|
||||
|
||||
suspend fun getSyncOrNull(
|
||||
userWalletId: UserWalletId,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -6,5 +6,5 @@ sealed class StakingAvailability {
|
|||
|
||||
data object Unavailable : StakingAvailability()
|
||||
|
||||
data object TemporaryDisabled : StakingAvailability()
|
||||
data object TemporaryUnavailable : StakingAvailability()
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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<TokenDetailsNotification>,
|
||||
val pendingTxs: PersistentList<TransactionState>,
|
||||
val swapTxs: PersistentList<SwapTransactionsState>,
|
||||
|
|
@ -27,6 +27,5 @@ internal data class TokenDetailsState(
|
|||
val bottomSheetConfig: TangemBottomSheetConfig?,
|
||||
val isBalanceHidden: Boolean,
|
||||
val isMarketPriceAvailable: Boolean,
|
||||
val isStakingBlockShown: Boolean,
|
||||
val event: StateEvent<TextReference>,
|
||||
)
|
||||
|
|
@ -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<TokenDetailsState>,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val stakingEntryInfoProvider: Provider<StakingEntryInfo?>,
|
||||
private val stakingAvailabilityProvider: Provider<StakingAvailability>,
|
||||
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
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@ internal class TokenDetailsSkeletonStateConverter(
|
|||
bottomSheetConfig = null,
|
||||
isBalanceHidden = true,
|
||||
isMarketPriceAvailable = value.id.rawCurrencyId != null,
|
||||
isStakingBlockShown = false,
|
||||
event = consumedEvent(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<TokenDetailsState>,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val stakingEntryInfoProvider: Provider<StakingEntryInfo?>,
|
||||
private val stakingAvailabilityProvider: Provider<StakingAvailability>,
|
||||
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus?>,
|
||||
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<StakingError, StakingEntryInfo>): TokenDetailsState {
|
||||
return currentStateProvider().copy(
|
||||
stakingBlocksState = stakingStateConverter.convert(stakingEither),
|
||||
)
|
||||
}
|
||||
|
||||
fun getRefreshingState(): TokenDetailsState {
|
||||
return refreshStateConverter.convert(true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<TokenDetailsState>,
|
||||
) : Converter<Either<StakingError, StakingEntryInfo>, StakingBlockUM> {
|
||||
|
||||
override fun convert(value: Either<StakingError, StakingEntryInfo>): 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,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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<Sta
|
|||
collection = listOf(
|
||||
stakingLoadingBlock,
|
||||
stakingAvailableBlock,
|
||||
stakingErrorBlock,
|
||||
stakingTemporaryUnavailableBlock,
|
||||
),
|
||||
)
|
||||
// endregion Preview
|
||||
|
|
@ -149,12 +149,14 @@ internal class TokenDetailsViewModel @Inject constructor(
|
|||
|
||||
private var cryptoCurrencyStatus: CryptoCurrencyStatus? = null
|
||||
private var stakingEntryInfo: StakingEntryInfo? = null
|
||||
private var stakingAvailability: StakingAvailability = StakingAvailability.Unavailable
|
||||
private var swapTxStatusTaskScheduler = SingleTaskScheduler<PersistentList<SwapTransactionsState>>()
|
||||
|
||||
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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue