Updated on 2026-08-14
This commit is contained in:
commit
5223d4b417
784 changed files with 24026 additions and 3170 deletions
|
|
@ -16,6 +16,8 @@ import com.tangem.core.decompose.di.ModelScoped
|
|||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.core.navigation.share.ShareManager
|
||||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.haptic.TangemHapticEffect
|
||||
import com.tangem.core.ui.haptic.VibratorHapticManager
|
||||
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||
|
|
@ -34,6 +36,7 @@ import com.tangem.domain.staking.model.stakekit.*
|
|||
import com.tangem.domain.staking.model.stakekit.action.StakingAction
|
||||
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
|
||||
import com.tangem.domain.staking.model.stakekit.transaction.StakingTransaction
|
||||
import com.tangem.domain.staking.utils.getValidatorsCount
|
||||
import com.tangem.domain.tokens.*
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
|
|
@ -114,6 +117,7 @@ internal class StakingModel @Inject constructor(
|
|||
private val sendFeedbackEmailUseCase: SendFeedbackEmailUseCase,
|
||||
private val getActionsUseCase: GetActionsUseCase,
|
||||
private val getYieldUseCase: GetYieldUseCase,
|
||||
private val checkAccountInitializedUseCase: CheckAccountInitializedUseCase,
|
||||
private val paramsInterceptorHolder: ParamsInterceptorHolder,
|
||||
private val shareManager: ShareManager,
|
||||
@DelayedWork private val coroutineScope: CoroutineScope,
|
||||
|
|
@ -229,49 +233,62 @@ internal class StakingModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onNextClick(balanceState: BalanceState?) {
|
||||
val isInitialInfoStep = value.currentStep == StakingStep.InitialInfo
|
||||
val noBalanceState = balanceState == null
|
||||
val noYieldBalanceData = cryptoCurrencyStatus.value.yieldBalance !is YieldBalance.Data
|
||||
modelScope.launch {
|
||||
val isInitialInfoStep = value.currentStep == StakingStep.InitialInfo
|
||||
val noBalanceState = balanceState == null
|
||||
val noYieldBalanceData = cryptoCurrencyStatus.value.yieldBalance !is YieldBalance.Data
|
||||
val isAccountInitialized = checkAccountInitializedUseCase.invoke(
|
||||
userWalletId = userWalletId,
|
||||
network = cryptoCurrencyStatus.currency.network,
|
||||
).getOrElse {
|
||||
Timber.e(it)
|
||||
false
|
||||
}
|
||||
|
||||
when {
|
||||
isInitialInfoStep && noBalanceState && yield.allValidatorsFull && noYieldBalanceData -> {
|
||||
stakingEventFactory.createStakingValidatorsUnavailableAlert()
|
||||
return
|
||||
}
|
||||
isInitialInfoStep && noBalanceState -> {
|
||||
val list = buildList {
|
||||
SetConfirmationStateInitTransformer(
|
||||
isEnter = true,
|
||||
isExplicitExit = false,
|
||||
balanceState = null,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
stakingApproval = stakingApproval,
|
||||
stakingAllowance = stakingAllowance,
|
||||
yieldArgs = yield.args,
|
||||
).let(::add)
|
||||
if (yield.args.enter.isPartialAmountDisabled) {
|
||||
ValidatorSelectChangeTransformer(
|
||||
selectedValidator = yield.preferredValidators.firstOrNull(),
|
||||
yield = yield,
|
||||
).let(::add)
|
||||
SetAmountDataTransformer(
|
||||
clickIntents = this@StakingModel,
|
||||
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
|
||||
userWalletProvider = Provider { userWallet },
|
||||
appCurrencyProvider = Provider { appCurrency },
|
||||
).let(::add)
|
||||
AmountMaxValueStateTransformer(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
minimumTransactionAmount = minimumTransactionAmount,
|
||||
actionType = uiState.value.actionType,
|
||||
yield = yield,
|
||||
).let(::add)
|
||||
}
|
||||
when {
|
||||
isInitialInfoStep && noBalanceState && yield.allValidatorsFull && noYieldBalanceData -> {
|
||||
stakingEventFactory.createStakingValidatorsUnavailableAlert()
|
||||
return@launch
|
||||
}
|
||||
isInitialInfoStep && noBalanceState && !isAccountInitialized -> {
|
||||
stakingEventFactory.createInitializeAccountAlert()
|
||||
return@launch
|
||||
}
|
||||
isInitialInfoStep && noBalanceState -> {
|
||||
val list = buildList {
|
||||
SetConfirmationStateInitTransformer(
|
||||
isEnter = true,
|
||||
isExplicitExit = false,
|
||||
balanceState = null,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
stakingApproval = stakingApproval,
|
||||
stakingAllowance = stakingAllowance,
|
||||
yieldArgs = yield.args,
|
||||
).let(::add)
|
||||
if (yield.args.enter.isPartialAmountDisabled) {
|
||||
ValidatorSelectChangeTransformer(
|
||||
selectedValidator = yield.preferredValidators.firstOrNull(),
|
||||
yield = yield,
|
||||
).let(::add)
|
||||
SetAmountDataTransformer(
|
||||
clickIntents = this@StakingModel,
|
||||
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
|
||||
userWalletProvider = Provider { userWallet },
|
||||
appCurrencyProvider = Provider { appCurrency },
|
||||
).let(::add)
|
||||
AmountMaxValueStateTransformer(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
minimumTransactionAmount = minimumTransactionAmount,
|
||||
actionType = uiState.value.actionType,
|
||||
yield = yield,
|
||||
).let(::add)
|
||||
}
|
||||
}
|
||||
stateController.updateAll(*list.toTypedArray())
|
||||
}
|
||||
stateController.updateAll(*list.toTypedArray())
|
||||
}
|
||||
stakingStateRouter.onNextClick()
|
||||
}
|
||||
stakingStateRouter.onNextClick()
|
||||
}
|
||||
|
||||
override fun getFee() {
|
||||
|
|
@ -497,19 +514,34 @@ internal class StakingModel @Inject constructor(
|
|||
analyticsEventHandler.send(StakingAnalyticsEvent.ButtonRewards)
|
||||
val rewardsValidators =
|
||||
stateController.value.rewardsValidatorsState as? StakingStates.RewardsValidatorsState.Data
|
||||
val rewards = rewardsValidators?.rewards
|
||||
if (rewards != null && rewards.isSingleItem()) {
|
||||
onActiveStake(rewards.first())
|
||||
} else {
|
||||
analyticsEventHandler.send(
|
||||
StakingAnalyticsEvent.ButtonValidator(
|
||||
source = StakeScreenSource.Info,
|
||||
),
|
||||
|
||||
val initialInfoState = stateController.value.initialInfoState as? StakingStates.InitialInfoState.Data
|
||||
val yieldBalance = initialInfoState?.yieldBalance as? InnerYieldBalanceState.Data
|
||||
val rewardBlockType = yieldBalance?.reward?.rewardBlockType
|
||||
val rewardPendingActionConstraints = yieldBalance?.reward?.rewardConstraints
|
||||
|
||||
if (rewardBlockType == RewardBlockType.RewardsRequirementsError) {
|
||||
stakingEventFactory.createStakingRewardsMinimumRequirementsErrorAlert(
|
||||
cryptoCurrencyName = cryptoCurrencyStatus.currency.name,
|
||||
cryptoAmountValue = rewardPendingActionConstraints?.amountArg?.minimum?.format {
|
||||
crypto(cryptoCurrencyStatus.currency)
|
||||
}.orEmpty(),
|
||||
)
|
||||
stateController.update {
|
||||
value.copy(actionType = StakingActionCommonType.Pending.Rewards)
|
||||
} else {
|
||||
val rewards = rewardsValidators?.rewards
|
||||
if (rewards != null && rewards.isSingleItem()) {
|
||||
onActiveStake(rewards.first())
|
||||
} else {
|
||||
analyticsEventHandler.send(
|
||||
StakingAnalyticsEvent.ButtonValidator(
|
||||
source = StakeScreenSource.Info,
|
||||
),
|
||||
)
|
||||
stateController.update {
|
||||
value.copy(actionType = StakingActionCommonType.Pending.Rewards)
|
||||
}
|
||||
stakingStateRouter.showRewardsValidators()
|
||||
}
|
||||
stakingStateRouter.showRewardsValidators()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,18 +2,14 @@ package com.tangem.features.staking.impl.presentation.state
|
|||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.staking.model.stakekit.BalanceType
|
||||
import com.tangem.domain.staking.model.stakekit.PendingAction
|
||||
import com.tangem.domain.staking.model.stakekit.RewardBlockType
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.staking.model.stakekit.*
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import java.math.BigDecimal
|
||||
|
||||
@Immutable
|
||||
internal sealed class InnerYieldBalanceState {
|
||||
data class Data(
|
||||
val rewardsCrypto: String,
|
||||
val rewardsFiat: String,
|
||||
val rewardBlockType: RewardBlockType,
|
||||
val reward: YieldReward,
|
||||
val isActionable: Boolean,
|
||||
val balances: ImmutableList<BalanceState>,
|
||||
) : InnerYieldBalanceState()
|
||||
|
|
@ -37,4 +33,12 @@ internal data class BalanceState(
|
|||
val validator: Yield.Validator?,
|
||||
val pendingActions: ImmutableList<PendingAction>,
|
||||
val isPending: Boolean,
|
||||
)
|
||||
|
||||
@Immutable
|
||||
internal data class YieldReward(
|
||||
val rewardsCrypto: String,
|
||||
val rewardsFiat: String,
|
||||
val rewardBlockType: RewardBlockType,
|
||||
val rewardConstraints: PendingActionConstraints?,
|
||||
)
|
||||
|
|
@ -6,8 +6,11 @@ import com.tangem.core.ui.format.bigdecimal.fiat
|
|||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.staking.model.stakekit.*
|
||||
import com.tangem.domain.staking.model.stakekit.action.StakingActionType
|
||||
import com.tangem.domain.staking.utils.getRewardStakingBalance
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.staking.impl.presentation.state.InnerYieldBalanceState
|
||||
import com.tangem.features.staking.impl.presentation.state.YieldReward
|
||||
import com.tangem.lib.crypto.BlockchainUtils.isBSC
|
||||
import com.tangem.lib.crypto.BlockchainUtils.isSolana
|
||||
import com.tangem.utils.Provider
|
||||
|
|
@ -29,11 +32,11 @@ internal class YieldBalancesConverter(
|
|||
val appCurrency = appCurrencyProvider()
|
||||
|
||||
val cryptoCurrency = cryptoCurrencyStatus.currency
|
||||
val yieldBalance = cryptoCurrencyStatus.value.yieldBalance
|
||||
val yieldBalance = cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data
|
||||
val balanceToShowItems = balancesToShowProvider()
|
||||
|
||||
return if (yieldBalance is YieldBalance.Data || balanceToShowItems.any { it.isPending }) {
|
||||
val cryptoRewardsValue = (yieldBalance as? YieldBalance.Data)?.getRewardStakingBalance()
|
||||
return if (yieldBalance != null || balanceToShowItems.any { it.isPending }) {
|
||||
val cryptoRewardsValue = yieldBalance?.getRewardStakingBalance()
|
||||
|
||||
val fiatRate = cryptoCurrencyStatus.value.fiatRate
|
||||
val fiatRewardsValue = if (fiatRate != null && cryptoRewardsValue != null) {
|
||||
|
|
@ -41,17 +44,25 @@ internal class YieldBalancesConverter(
|
|||
} else {
|
||||
null
|
||||
}
|
||||
val (type, isActionable) = getRewardBlockType()
|
||||
val type = getRewardBlockType()
|
||||
val pendingRewardsConstraints = yieldBalance?.balance?.items
|
||||
?.firstOrNull { it.type == BalanceType.REWARDS }
|
||||
?.pendingActionsConstraints
|
||||
?.firstOrNull { it.type == StakingActionType.CLAIM_REWARDS }
|
||||
|
||||
InnerYieldBalanceState.Data(
|
||||
rewardsCrypto = cryptoRewardsValue.format { crypto(cryptoCurrency) },
|
||||
rewardsFiat = fiatRewardsValue.format {
|
||||
fiat(
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
)
|
||||
},
|
||||
rewardBlockType = type,
|
||||
isActionable = isActionable,
|
||||
reward = YieldReward(
|
||||
rewardsCrypto = cryptoRewardsValue.format { crypto(cryptoCurrency) },
|
||||
rewardsFiat = fiatRewardsValue.format {
|
||||
fiat(
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
fiatCurrencySymbol = appCurrency.symbol,
|
||||
)
|
||||
},
|
||||
rewardBlockType = type,
|
||||
rewardConstraints = pendingRewardsConstraints,
|
||||
),
|
||||
isActionable = type.isActionable,
|
||||
balances = balanceToShowItems.mapBalances(),
|
||||
)
|
||||
} else {
|
||||
|
|
@ -66,7 +77,7 @@ internal class YieldBalancesConverter(
|
|||
.sortedBy { it.type.order }
|
||||
.toPersistentList()
|
||||
|
||||
private fun getRewardBlockType(): Pair<RewardBlockType, Boolean> {
|
||||
private fun getRewardBlockType(): RewardBlockType {
|
||||
val blockchainId = cryptoCurrencyStatus.currency.network.id.value
|
||||
val yieldBalance = cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data
|
||||
val rewards = yieldBalance?.balance?.items
|
||||
|
|
@ -76,9 +87,10 @@ internal class YieldBalancesConverter(
|
|||
val isRewardsClaimable = rewards?.isNotEmpty() == true
|
||||
|
||||
return when {
|
||||
isSolana(blockchainId) || isBSC(blockchainId) -> RewardBlockType.RewardUnavailable to false
|
||||
isRewardsClaimable -> RewardBlockType.Rewards to isActionable
|
||||
else -> RewardBlockType.NoRewards to false
|
||||
isSolana(blockchainId) || isBSC(blockchainId) -> RewardBlockType.RewardUnavailable
|
||||
isRewardsClaimable && isActionable -> RewardBlockType.Rewards
|
||||
isRewardsClaimable && !isActionable -> RewardBlockType.RewardsRequirementsError
|
||||
else -> RewardBlockType.NoRewards
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -61,4 +61,24 @@ internal sealed class StakingAlertUM : AlertUM {
|
|||
)
|
||||
override val confirmButtonText: TextReference = resourceReference(id = R.string.common_ok)
|
||||
}
|
||||
|
||||
data object InitializeAccount : StakingAlertUM() {
|
||||
override val onConfirmClick: (() -> Unit)? = null
|
||||
override val title: TextReference = resourceReference(id = R.string.staking_error_no_validators_title)
|
||||
override val message: TextReference = resourceReference(id = R.string.staking_notification_ton_activate_account)
|
||||
override val confirmButtonText: TextReference = resourceReference(id = R.string.common_ok)
|
||||
}
|
||||
|
||||
data class RewardsMinimumRequirementsError(
|
||||
val cryptoCurrencyName: String,
|
||||
val cryptoAmountValue: String,
|
||||
) : StakingAlertUM() {
|
||||
override val onConfirmClick: (() -> Unit)? = null
|
||||
override val title: TextReference? = null
|
||||
override val message: TextReference = resourceReference(
|
||||
id = R.string.staking_details_min_rewards_notification,
|
||||
formatArgs = wrappedList(cryptoCurrencyName, cryptoAmountValue),
|
||||
)
|
||||
override val confirmButtonText: TextReference = resourceReference(id = R.string.common_ok)
|
||||
}
|
||||
}
|
||||
|
|
@ -46,4 +46,20 @@ internal class StakingEventFactory(
|
|||
val alert = StakingEvent.ShowAlert(alert = StakingAlertUM.ValidatorsUnavailable)
|
||||
stateController.updateEvent(alert)
|
||||
}
|
||||
|
||||
fun createInitializeAccountAlert() {
|
||||
val alert = StakingEvent.ShowAlert(alert = StakingAlertUM.InitializeAccount)
|
||||
stateController.updateEvent(alert)
|
||||
}
|
||||
|
||||
fun createStakingRewardsMinimumRequirementsErrorAlert(cryptoCurrencyName: String, cryptoAmountValue: String) {
|
||||
stateController.updateEvent(
|
||||
StakingEvent.ShowAlert(
|
||||
alert = StakingAlertUM.RewardsMinimumRequirementsError(
|
||||
cryptoCurrencyName = cryptoCurrencyName,
|
||||
cryptoAmountValue = cryptoAmountValue,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.previewdata
|
||||
|
||||
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.core.ui.components.list.RoundedListWithDividersItemData
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.components.containers.pullToRefresh.PullToRefreshConfig
|
||||
import com.tangem.domain.staking.model.stakekit.BalanceType
|
||||
import com.tangem.domain.staking.model.stakekit.RewardBlockType
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
|
|
@ -11,6 +11,7 @@ import com.tangem.features.staking.impl.R
|
|||
import com.tangem.features.staking.impl.presentation.state.BalanceState
|
||||
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.YieldReward
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
internal object InitialStakingStatePreview {
|
||||
|
|
@ -63,9 +64,12 @@ internal object InitialStakingStatePreview {
|
|||
|
||||
val stateWithYield = defaultState.copy(
|
||||
yieldBalance = InnerYieldBalanceState.Data(
|
||||
rewardsFiat = "100 $",
|
||||
rewardsCrypto = "100 SOL",
|
||||
rewardBlockType = RewardBlockType.RewardUnavailable,
|
||||
reward = YieldReward(
|
||||
rewardsFiat = "100 $",
|
||||
rewardsCrypto = "100 SOL",
|
||||
rewardBlockType = RewardBlockType.RewardUnavailable,
|
||||
rewardConstraints = null,
|
||||
),
|
||||
isActionable = true,
|
||||
balances = persistentListOf(
|
||||
BalanceState(
|
||||
|
|
|
|||
|
|
@ -43,28 +43,7 @@ internal class SetConfirmationStateInitTransformer(
|
|||
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
val actionType = when {
|
||||
isEnter -> StakingActionCommonType.Enter(
|
||||
skipEnterAmount = yieldArgs.enter.isPartialAmountDisabled,
|
||||
)
|
||||
isImplicitExit || isExplicitExit -> StakingActionCommonType.Exit(isPartiallyUnstakeDisabled(prevState))
|
||||
else -> when (pendingAction?.type) {
|
||||
StakingActionType.STAKE -> StakingActionCommonType.Pending.Stake(
|
||||
skipEnterAmount = yieldArgs.enter.isPartialAmountDisabled,
|
||||
)
|
||||
StakingActionType.UNSTAKE -> StakingActionCommonType.Exit(
|
||||
partiallyUnstakeDisabled = isPartiallyUnstakeDisabled(prevState),
|
||||
)
|
||||
StakingActionType.CLAIM_REWARDS,
|
||||
StakingActionType.RESTAKE_REWARDS,
|
||||
-> StakingActionCommonType.Pending.Rewards
|
||||
StakingActionType.VOTE_LOCKED,
|
||||
StakingActionType.RESTAKE,
|
||||
-> StakingActionCommonType.Pending.Restake
|
||||
else -> StakingActionCommonType.Pending.Other
|
||||
}
|
||||
}
|
||||
|
||||
val actionType = getActionType(prevState)
|
||||
return prevState.copy(
|
||||
actionType = actionType,
|
||||
balanceState = balanceState,
|
||||
|
|
@ -86,6 +65,26 @@ internal class SetConfirmationStateInitTransformer(
|
|||
)
|
||||
}
|
||||
|
||||
private fun getActionType(prevState: StakingUiState): StakingActionCommonType {
|
||||
val isPartialEnterAmountDisabled = yieldArgs.enter.isPartialAmountDisabled
|
||||
val isPartialExitAmountDisabled = isPartiallyUnstakeDisabled(prevState)
|
||||
return when {
|
||||
isEnter -> StakingActionCommonType.Enter(isPartialEnterAmountDisabled)
|
||||
isImplicitExit || isExplicitExit -> StakingActionCommonType.Exit(isPartialExitAmountDisabled)
|
||||
else -> when (pendingAction?.type) {
|
||||
StakingActionType.STAKE -> StakingActionCommonType.Pending.Stake(isPartialEnterAmountDisabled)
|
||||
StakingActionType.UNSTAKE -> StakingActionCommonType.Exit(isPartialExitAmountDisabled)
|
||||
StakingActionType.CLAIM_REWARDS,
|
||||
StakingActionType.RESTAKE_REWARDS,
|
||||
-> StakingActionCommonType.Pending.Rewards
|
||||
StakingActionType.VOTE_LOCKED,
|
||||
StakingActionType.RESTAKE,
|
||||
-> StakingActionCommonType.Pending.Restake
|
||||
else -> StakingActionCommonType.Pending.Other
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isPartiallyUnstakeDisabled(state: StakingUiState): Boolean {
|
||||
val isSolana = BlockchainUtils.isSolana(state.cryptoCurrencyBlockchainId)
|
||||
val isValidatorPreferred = balanceState?.validator?.preferred == true
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ internal class AmountPasteDismissStateTransformer : Transformer<StakingUiState>
|
|||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
return prevState.copy(
|
||||
amountState = AmountPastedTriggerDismissTransformer().transform(prevState.amountState),
|
||||
amountState = AmountPastedTriggerDismissTransformer.transform(prevState.amountState),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -98,9 +98,7 @@ internal class AddStakingNotificationsTransformer(
|
|||
onReload = prevState.clickIntents::getFee,
|
||||
feeValue = feeValue,
|
||||
)
|
||||
addStakingErrorNotifications(
|
||||
stakingError = stakingError,
|
||||
)
|
||||
addStakingErrorNotifications(stakingError = stakingError, onReload = prevState.clickIntents::getFee)
|
||||
// warnings
|
||||
addWarningNotifications(
|
||||
prevState = prevState,
|
||||
|
|
@ -136,7 +134,10 @@ internal class AddStakingNotificationsTransformer(
|
|||
)
|
||||
}
|
||||
|
||||
private fun MutableList<NotificationUM>.addStakingErrorNotifications(stakingError: StakingError?) {
|
||||
private fun MutableList<NotificationUM>.addStakingErrorNotifications(
|
||||
stakingError: StakingError?,
|
||||
onReload: () -> Unit,
|
||||
) {
|
||||
when (stakingError) {
|
||||
is StakingError.StakeKitApiError -> {
|
||||
if (stakingError.message != StakingErrors.MinimumAmountNotReachedError.message) {
|
||||
|
|
@ -146,9 +147,7 @@ internal class AddStakingNotificationsTransformer(
|
|||
}
|
||||
}
|
||||
null -> Unit
|
||||
else -> add(
|
||||
StakingNotification.Error.Common(subtitle = stringReference(stakingError.toString())),
|
||||
)
|
||||
else -> add(NotificationUM.Warning.NetworkFeeUnreachable(onReload))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ internal class ValidatorSelectChangeTransformer(
|
|||
chosenValidator = selectedValidator ?: yield.preferredValidators.first(),
|
||||
availableValidators = filteredValidators,
|
||||
isPrimaryButtonEnabled = true,
|
||||
isClickable = true,
|
||||
isClickable = yield.preferredValidators.size > 1,
|
||||
activeValidator = activeValidator,
|
||||
isVisibleOnConfirmation = isEnter || isRestake || isVoteLocked,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import androidx.compose.ui.unit.Density
|
|||
import com.tangem.common.ui.navigationButtons.NavigationButtonsState
|
||||
import com.tangem.common.ui.navigationButtons.NavigationPrimaryButton
|
||||
import com.tangem.core.ui.components.SpacerH12
|
||||
import com.tangem.core.ui.components.containers.pullToRefresh.TangemPullToRefreshContainer
|
||||
import com.tangem.core.ui.components.inputrow.InputRowDefault
|
||||
import com.tangem.core.ui.components.inputrow.InputRowImageInfo
|
||||
import com.tangem.core.ui.components.list.roundedListWithDividersItems
|
||||
|
|
@ -38,19 +39,18 @@ import com.tangem.core.ui.decorations.roundedShapeItemDecoration
|
|||
import com.tangem.core.ui.extensions.*
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.format.bigdecimal.percent
|
||||
import com.tangem.core.ui.components.containers.pullToRefresh.TangemPullToRefreshContainer
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.domain.staking.model.stakekit.BalanceType
|
||||
import com.tangem.domain.staking.model.stakekit.RewardBlockType
|
||||
import com.tangem.features.staking.impl.R
|
||||
import com.tangem.features.staking.impl.presentation.model.StakingClickIntents
|
||||
import com.tangem.features.staking.impl.presentation.state.BalanceState
|
||||
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.previewdata.InitialStakingStatePreview
|
||||
import com.tangem.features.staking.impl.presentation.state.stub.StakingClickIntentsStub
|
||||
import com.tangem.features.staking.impl.presentation.model.StakingClickIntents
|
||||
import com.tangem.utils.StringsSigns.DOT
|
||||
import com.tangem.utils.extensions.orZero
|
||||
|
||||
|
|
@ -214,14 +214,17 @@ private fun StakingRewardBlock(
|
|||
onRewardsClick: () -> Unit,
|
||||
isBalanceHidden: Boolean,
|
||||
) {
|
||||
val (text, textColor) = when (yieldBalanceState.rewardBlockType) {
|
||||
RewardBlockType.Rewards -> {
|
||||
val reward = yieldBalanceState.reward
|
||||
val (text, textColor) = when (yieldBalanceState.reward.rewardBlockType) {
|
||||
RewardBlockType.RewardsRequirementsError,
|
||||
RewardBlockType.Rewards,
|
||||
-> {
|
||||
annotatedReference {
|
||||
append(yieldBalanceState.rewardsFiat.orMaskWithStars(isBalanceHidden))
|
||||
append(reward.rewardsFiat.orMaskWithStars(isBalanceHidden))
|
||||
appendSpace()
|
||||
append(DOT)
|
||||
appendSpace()
|
||||
append(yieldBalanceState.rewardsCrypto.orMaskWithStars(isBalanceHidden))
|
||||
append(reward.rewardsCrypto.orMaskWithStars(isBalanceHidden))
|
||||
} to TangemTheme.colors.text.primary1
|
||||
}
|
||||
RewardBlockType.RewardUnavailable -> {
|
||||
|
|
@ -232,7 +235,7 @@ private fun StakingRewardBlock(
|
|||
resourceReference(R.string.staking_details_no_rewards_to_claim) to TangemTheme.colors.text.tertiary
|
||||
}
|
||||
}
|
||||
val isShowIcon = yieldBalanceState.rewardBlockType == RewardBlockType.Rewards && yieldBalanceState.isActionable
|
||||
val isShowIcon = reward.rewardBlockType == RewardBlockType.Rewards && yieldBalanceState.isActionable
|
||||
InputRowDefault(
|
||||
title = resourceReference(R.string.staking_rewards),
|
||||
text = text,
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetTitle
|
||||
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheetTitle
|
||||
import com.tangem.core.ui.components.inputrow.InputRowDefault
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ import androidx.compose.material3.Text
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetTitle
|
||||
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheetTitle
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue