Updated on 2026-08-14
This commit is contained in:
commit
aedc3b5375
9 changed files with 74 additions and 50 deletions
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ sealed class InnerYieldBalanceState {
|
|||
val rewardsCrypto: String,
|
||||
val rewardsFiat: String,
|
||||
val isRewardsToClaim: Boolean,
|
||||
val isRewardsClaimable: Boolean,
|
||||
val balance: ImmutableList<BalanceGroupedState>,
|
||||
) : InnerYieldBalanceState()
|
||||
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ internal object InitialStakingStatePreview {
|
|||
rewardsFiat = "100 $",
|
||||
rewardsCrypto = "100 SOL",
|
||||
isRewardsToClaim = false,
|
||||
isRewardsClaimable = false,
|
||||
balance = persistentListOf(
|
||||
BalanceGroupedState(
|
||||
title = stringReference("Staked"),
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,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()
|
||||
|
|
@ -143,6 +144,7 @@ private fun StakingRewardBlock(
|
|||
rewardCrypto: String,
|
||||
rewardFiat: String,
|
||||
isRewardsToClaim: Boolean,
|
||||
isRewardsClaimable: Boolean,
|
||||
onRewardsClick: () -> Unit,
|
||||
) {
|
||||
val (text, textColor) = if (isRewardsToClaim) {
|
||||
|
|
@ -161,7 +163,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)
|
||||
|
|
@ -169,7 +171,7 @@ private fun StakingRewardBlock(
|
|||
.clickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = rememberRipple(),
|
||||
enabled = isRewardsToClaim,
|
||||
enabled = isRewardsToClaim && isRewardsClaimable,
|
||||
onClick = onRewardsClick,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue