Updated on 2026-08-14

This commit is contained in:
Tangem 2024-08-14 13:27:51 +05:00
parent 38f5c42a94
commit 4b32c119c4
9 changed files with 74 additions and 50 deletions

View file

@ -11,13 +11,13 @@ sealed class YieldBalance {
fun getTotalStakingBalance(): BigDecimal {
return balance.items
.filterNot { it.type == BalanceType.REWARDS }
.sumOf { it.amount * it.pricePerShare }
.sumOf { it.amount }
}
fun getRewardStakingBalance(): BigDecimal {
return balance.items
.filter { it.type == BalanceType.REWARDS }
.sumOf { it.amount * it.pricePerShare }
.sumOf { it.amount }
}
}

View file

@ -13,6 +13,7 @@ sealed class InnerYieldBalanceState {
val rewardsCrypto: String,
val rewardsFiat: String,
val isRewardsToClaim: Boolean,
val isRewardsClaimable: Boolean,
val balance: ImmutableList<BalanceGroupedState>,
) : InnerYieldBalanceState()

View file

@ -44,7 +44,7 @@ internal class RewardsValidatorStateConverter(
val validator = yield.validators.firstOrNull {
it.address.contains(balance.validatorAddress.orEmpty(), ignoreCase = true)
}
val cryptoValue = balance.amount.times(balance.pricePerShare)
val cryptoValue = balance.amount
val fiatValue = cryptoCurrencyStatus.value.fiatRate?.times(cryptoValue)
val unbondingPeriod = yield.metadata.cooldownPeriod.days
validator?.toBalanceState(

View file

@ -1,5 +1,6 @@
package com.tangem.features.staking.impl.presentation.state.converters
import com.tangem.common.extensions.isZero
import com.tangem.core.ui.extensions.pluralReference
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringReference
@ -34,7 +35,9 @@ internal class YieldBalancesConverter(
val cryptoRewardsValue = yieldBalance.getRewardStakingBalance()
val fiatRewardsValue = cryptoCurrencyStatus.value.fiatRate?.times(cryptoRewardsValue)
val groupedBalances = getGroupedBalance(yieldBalance.balance)
val isRewardsClaimable = yieldBalance.balance.items
.filter { it.type == BalanceType.REWARDS }
.any { it.pendingActions.isNotEmpty() }
InnerYieldBalanceState.Data(
rewardsCrypto = BigDecimalFormatter.formatCryptoAmount(
cryptoAmount = cryptoRewardsValue,
@ -46,6 +49,7 @@ internal class YieldBalancesConverter(
fiatCurrencySymbol = appCurrency.symbol,
),
isRewardsToClaim = !cryptoRewardsValue.isNullOrZero(),
isRewardsClaimable = isRewardsClaimable,
balance = groupedBalances,
)
} else {
@ -69,47 +73,50 @@ internal class YieldBalancesConverter(
)
}
}
.filterNot { it.items.isEmpty() }
.toPersistentList()
private fun List<BalanceItem>.mapBalances(): List<BalanceState> {
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
val appCurrency = appCurrencyProvider()
val cryptoCurrency = cryptoCurrencyStatus.currency
return this.mapNotNull { balance ->
val validator = yield.validators.firstOrNull {
balance.validatorAddress?.contains(it.address, ignoreCase = true) == true
}
val cryptoAmount = balance.amount * balance.pricePerShare
val fiatAmount = cryptoCurrencyStatus.value.fiatRate?.times(cryptoAmount)
val unbondingPeriod = yield.metadata.cooldownPeriod.days
validator?.let {
BalanceState(
validator = validator,
cryptoValue = cryptoAmount.parseBigDecimal(cryptoCurrency.decimals),
cryptoDecimal = cryptoAmount,
cryptoAmount = stringReference(
BigDecimalFormatter.formatCryptoAmount(
cryptoAmount = cryptoAmount,
cryptoCurrency = cryptoCurrency,
return this
.filterNot { it.amount.isZero() }
.mapNotNull { balance ->
val validator = yield.validators.firstOrNull {
balance.validatorAddress?.contains(it.address, ignoreCase = true) == true
}
val cryptoAmount = balance.amount
val fiatAmount = cryptoCurrencyStatus.value.fiatRate?.times(cryptoAmount)
val unbondingPeriod = yield.metadata.cooldownPeriod.days
validator?.let {
BalanceState(
validator = validator,
cryptoValue = cryptoAmount.parseBigDecimal(cryptoCurrency.decimals),
cryptoDecimal = cryptoAmount,
cryptoAmount = stringReference(
BigDecimalFormatter.formatCryptoAmount(
cryptoAmount = cryptoAmount,
cryptoCurrency = cryptoCurrency,
),
),
),
fiatAmount = stringReference(
BigDecimalFormatter.formatFiatAmount(
fiatAmount = fiatAmount,
fiatCurrencyCode = appCurrency.code,
fiatCurrencySymbol = appCurrency.symbol,
fiatAmount = stringReference(
BigDecimalFormatter.formatFiatAmount(
fiatAmount = fiatAmount,
fiatCurrencyCode = appCurrency.code,
fiatCurrencySymbol = appCurrency.symbol,
),
),
),
rawCurrencyId = balance.rawCurrencyId,
unbondingPeriod = pluralReference(
id = R.plurals.common_days,
count = unbondingPeriod,
formatArgs = wrappedList(unbondingPeriod),
),
pendingActions = balance.pendingActions.toPersistentList(),
)
rawCurrencyId = balance.rawCurrencyId,
unbondingPeriod = pluralReference(
id = R.plurals.common_days,
count = unbondingPeriod,
formatArgs = wrappedList(unbondingPeriod),
),
pendingActions = balance.pendingActions.toPersistentList(),
)
}
}
}
}
private fun BalanceType.toGroup() = when (this) {

View file

@ -60,6 +60,7 @@ internal object InitialStakingStatePreview {
rewardsFiat = "100 $",
rewardsCrypto = "100 SOL",
isRewardsToClaim = false,
isRewardsClaimable = false,
balance = persistentListOf(
BalanceGroupedState(
title = stringReference("Staked"),

View file

@ -13,24 +13,27 @@ 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.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.TransactionDoneState
import com.tangem.features.staking.impl.presentation.state.ValidatorState
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.previewdata.ConfirmationStatePreviewData
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
import com.tangem.utils.Provider
import com.tangem.utils.transformer.Transformer
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList
import java.math.BigDecimal
@Suppress("LongParameterList")
internal class SetInitialDataStateTransformer(
private val clickIntents: StakingClickIntents,
private val yield: Yield,
private val isStakeMoreAvailable: Boolean,
private val isApprovalNeeded: Boolean,
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
private val userWalletProvider: Provider<UserWallet>,
private val appCurrencyProvider: Provider<AppCurrency>,
@ -202,12 +205,17 @@ internal class SetInitialDataStateTransformer(
}
private fun createInitialConfirmationState(): StakingStates.ConfirmationState {
return ConfirmationStatePreviewData.assentStakingState.copy(
validatorState = ValidatorState.Content(
isClickable = true,
chosenValidator = yield.validators.first(),
availableValidators = yield.validators,
),
return StakingStates.ConfirmationState.Data(
isPrimaryButtonEnabled = false,
innerState = InnerConfirmationStakingState.ASSENT,
feeState = FeeState.Loading,
validatorState = ValidatorState.Loading,
notifications = persistentListOf(),
footerText = "",
transactionDoneState = TransactionDoneState.Empty,
pendingActions = persistentListOf(),
pendingActionInProgress = null,
isApprovalNeeded = isApprovalNeeded,
)
}

View file

@ -11,13 +11,17 @@ internal class ValidatorSelectChangeTransformer(
) : Transformer<StakingUiState> {
override fun transform(prevState: StakingUiState): StakingUiState {
val confirmationState = prevState.confirmationState as? StakingStates.ConfirmationState.Data ?: return prevState
val validatorState = confirmationState.validatorState as? ValidatorState.Content ?: return prevState
val validatorState = (confirmationState.validatorState as? ValidatorState.Content)?.copy(
chosenValidator = selectedValidator,
) ?: ValidatorState.Content(
isClickable = false,
availableValidators = emptyList(),
chosenValidator = selectedValidator,
)
return prevState.copy(
confirmationState = confirmationState.copy(
validatorState = validatorState.copy(
chosenValidator = selectedValidator,
),
validatorState = validatorState,
),
)
}

View file

@ -87,6 +87,7 @@ internal fun StakingInitialInfoContent(state: StakingStates.InitialInfoState, cl
rewardCrypto = state.yieldBalance.rewardsCrypto,
rewardFiat = state.yieldBalance.rewardsFiat,
isRewardsToClaim = state.yieldBalance.isRewardsToClaim,
isRewardsClaimable = state.yieldBalance.isRewardsClaimable,
onRewardsClick = clickIntents::openRewardsValidators,
)
SpacerH12()
@ -140,6 +141,7 @@ private fun StakingRewardBlock(
rewardCrypto: String,
rewardFiat: String,
isRewardsToClaim: Boolean,
isRewardsClaimable: Boolean,
onRewardsClick: () -> Unit,
) {
val (text, textColor) = if (isRewardsToClaim) {
@ -158,7 +160,7 @@ private fun StakingRewardBlock(
InputRowDefault(
title = resourceReference(R.string.staking_rewards),
text = text,
iconRes = R.drawable.ic_chevron_right_24.takeIf { isRewardsToClaim },
iconRes = R.drawable.ic_chevron_right_24.takeIf { isRewardsToClaim && isRewardsClaimable },
textColor = textColor,
modifier = Modifier
.clip(TangemTheme.shapes.roundedCornersXMedium)
@ -166,7 +168,7 @@ private fun StakingRewardBlock(
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(),
enabled = isRewardsToClaim,
enabled = isRewardsToClaim && isRewardsClaimable,
onClick = onRewardsClick,
),
)

View file

@ -480,6 +480,7 @@ internal class StakingViewModel @Inject constructor(
clickIntents = this@StakingViewModel,
yield = yield,
isStakeMoreAvailable = isStakeMoreAvailable.getOrElse { false },
isApprovalNeeded = stakingApproval is StakingApproval.Needed,
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
userWalletProvider = Provider { userWallet },
appCurrencyProvider = Provider { appCurrency },