Updated on 2026-08-14
This commit is contained in:
parent
553078f9f6
commit
1fe12ed9d7
17 changed files with 53 additions and 43 deletions
|
|
@ -256,7 +256,7 @@ internal class DefaultStakingRepository(
|
|||
params,
|
||||
),
|
||||
)
|
||||
StakingActionCommonType.Exit -> stakeKitApi.createExitAction(
|
||||
is StakingActionCommonType.Exit -> stakeKitApi.createExitAction(
|
||||
createActionRequestBody(
|
||||
userWalletId,
|
||||
network,
|
||||
|
|
@ -286,7 +286,7 @@ internal class DefaultStakingRepository(
|
|||
params,
|
||||
),
|
||||
)
|
||||
StakingActionCommonType.Exit -> stakeKitApi.estimateGasOnExit(
|
||||
is StakingActionCommonType.Exit -> stakeKitApi.estimateGasOnExit(
|
||||
createActionRequestBody(
|
||||
userWalletId,
|
||||
network,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.tangem.domain.staking.model.stakekit.action
|
|||
sealed class StakingActionCommonType {
|
||||
|
||||
data object Enter : StakingActionCommonType()
|
||||
data object Exit : StakingActionCommonType()
|
||||
data class Exit(val partiallyUnstakeDisabled: Boolean) : StakingActionCommonType()
|
||||
sealed class Pending : StakingActionCommonType() {
|
||||
data object Restake : Pending()
|
||||
data object Rewards : Pending()
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ internal class StakingAnalyticSender(
|
|||
|
||||
return when (value.actionType) {
|
||||
StakingActionCommonType.Enter -> StakingActionType.STAKE
|
||||
StakingActionCommonType.Exit -> StakingActionType.UNSTAKE
|
||||
is StakingActionCommonType.Exit -> StakingActionType.UNSTAKE
|
||||
is StakingActionCommonType.Pending -> confirmationState?.pendingAction?.type ?: StakingActionType.UNKNOWN
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,10 +2,9 @@ package com.tangem.features.staking.impl.presentation.state
|
|||
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.core.analytics.api.AnalyticsEventHandler
|
||||
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
|
||||
import com.tangem.domain.staking.analytics.StakingAnalyticsEvent
|
||||
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
|
||||
import com.tangem.features.staking.impl.analytics.utils.StakingAnalyticSender
|
||||
import com.tangem.lib.crypto.BlockchainUtils.isSolana
|
||||
|
||||
internal class StakingStateRouter(
|
||||
private val appRouter: AppRouter,
|
||||
|
|
@ -23,10 +22,9 @@ internal class StakingStateRouter(
|
|||
|
||||
fun onNextClick() {
|
||||
when (stateController.value.currentStep) {
|
||||
StakingStep.InitialInfo -> when (stateController.value.actionType) {
|
||||
StakingStep.InitialInfo -> when (val actionType = stateController.value.actionType) {
|
||||
StakingActionCommonType.Enter -> showAmount()
|
||||
// TODO staking [REDACTED_TASK_KEY] support solana multisize hashes signing
|
||||
StakingActionCommonType.Exit -> if (isSolana(stateController.value.cryptoCurrencyBlockchainId)) {
|
||||
is StakingActionCommonType.Exit -> if (actionType.partiallyUnstakeDisabled) {
|
||||
showConfirmation()
|
||||
} else {
|
||||
showAmount()
|
||||
|
|
@ -54,15 +52,12 @@ internal class StakingStateRouter(
|
|||
StakingStep.Amount,
|
||||
-> showInitial()
|
||||
StakingStep.Confirmation -> {
|
||||
val isEnter = uiState.actionType == StakingActionCommonType.Enter
|
||||
val isExit = uiState.actionType == StakingActionCommonType.Exit
|
||||
|
||||
// TODO staking [REDACTED_TASK_KEY] support solana multisize hashes signing
|
||||
val isSolana = isSolana(uiState.cryptoCurrencyBlockchainId)
|
||||
if (isEnter || isExit && !isSolana) {
|
||||
showAmount()
|
||||
} else {
|
||||
showInitial()
|
||||
when (val actionType = uiState.actionType) {
|
||||
StakingActionCommonType.Enter -> showAmount()
|
||||
is StakingActionCommonType.Pending -> showInitial()
|
||||
is StakingActionCommonType.Exit -> {
|
||||
if (actionType.partiallyUnstakeDisabled) showInitial() else showAmount()
|
||||
}
|
||||
}
|
||||
}
|
||||
StakingStep.Validators -> showConfirmation()
|
||||
|
|
|
|||
|
|
@ -120,6 +120,7 @@ internal sealed class StakingStates {
|
|||
val footerText: TextReference,
|
||||
val transactionDoneState: TransactionDoneState,
|
||||
val isApprovalNeeded: Boolean,
|
||||
val isAmountEditable: Boolean,
|
||||
val allowance: BigDecimal,
|
||||
val reduceAmountBy: BigDecimal?,
|
||||
) : ConfirmationState()
|
||||
|
|
|
|||
|
|
@ -48,5 +48,6 @@ internal object ConfirmationStatePreviewData {
|
|||
allowance = BigDecimal.ZERO,
|
||||
reduceAmountBy = null,
|
||||
pendingActions = null,
|
||||
isAmountEditable = true,
|
||||
)
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ internal class SetAmountDataTransformer(
|
|||
private val iconStateConverter by lazy(::CryptoCurrencyToIconStateConverter)
|
||||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
val title = if (prevState.actionType == StakingActionCommonType.Exit) {
|
||||
val title = if (prevState.actionType is StakingActionCommonType.Exit) {
|
||||
resourceReference(R.string.staking_staked_amount)
|
||||
} else {
|
||||
stringReference(userWalletProvider().name)
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ internal class SetButtonsStateTransformer(
|
|||
resourceReference(R.string.common_stake)
|
||||
}
|
||||
}
|
||||
StakingActionCommonType.Exit -> resourceReference(R.string.common_unstake)
|
||||
is StakingActionCommonType.Exit -> resourceReference(R.string.common_unstake)
|
||||
is StakingActionCommonType.Pending -> confirmationState.pendingAction?.type.getPendingActionTitle()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,17 +3,21 @@ package com.tangem.features.staking.impl.presentation.state.transformers
|
|||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.staking.model.StakingApproval
|
||||
import com.tangem.domain.staking.model.stakekit.PendingAction
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
|
||||
import com.tangem.domain.staking.model.stakekit.action.StakingActionType
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.staking.impl.presentation.state.*
|
||||
import com.tangem.features.staking.impl.presentation.state.utils.isCompositePendingActions
|
||||
import com.tangem.features.staking.impl.presentation.state.utils.isTronStakedBalance
|
||||
import com.tangem.lib.crypto.BlockchainUtils
|
||||
import com.tangem.utils.extensions.isPositive
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import java.math.BigDecimal
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SetConfirmationStateInitTransformer(
|
||||
private val isEnter: Boolean,
|
||||
private val isExplicitExit: Boolean,
|
||||
|
|
@ -21,9 +25,9 @@ internal class SetConfirmationStateInitTransformer(
|
|||
private val stakingApproval: StakingApproval,
|
||||
private val stakingAllowance: BigDecimal,
|
||||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val yieldArgs: Yield.Args,
|
||||
private val pendingActions: ImmutableList<PendingAction>? = null,
|
||||
private val pendingAction: PendingAction? = pendingActions?.firstOrNull(),
|
||||
|
||||
) : Transformer<StakingUiState> {
|
||||
|
||||
private val networkId
|
||||
|
|
@ -41,10 +45,10 @@ internal class SetConfirmationStateInitTransformer(
|
|||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
val actionType = when {
|
||||
isEnter -> StakingActionCommonType.Enter
|
||||
isImplicitExit || isExplicitExit -> StakingActionCommonType.Exit
|
||||
isImplicitExit || isExplicitExit -> StakingActionCommonType.Exit(isPartiallyUnstakeDisabled(prevState))
|
||||
else -> when (pendingAction?.type) {
|
||||
StakingActionType.STAKE -> StakingActionCommonType.Enter
|
||||
StakingActionType.UNSTAKE -> StakingActionCommonType.Exit
|
||||
StakingActionType.UNSTAKE -> StakingActionCommonType.Exit(isPartiallyUnstakeDisabled(prevState))
|
||||
StakingActionType.CLAIM_REWARDS,
|
||||
StakingActionType.RESTAKE_REWARDS,
|
||||
-> StakingActionCommonType.Pending.Rewards
|
||||
|
|
@ -67,10 +71,26 @@ internal class SetConfirmationStateInitTransformer(
|
|||
transactionDoneState = TransactionDoneState.Empty,
|
||||
isApprovalNeeded = stakingApproval is StakingApproval.Needed,
|
||||
allowance = stakingAllowance,
|
||||
isAmountEditable = actionType == StakingActionCommonType.Enter ||
|
||||
actionType is StakingActionCommonType.Exit &&
|
||||
!actionType.partiallyUnstakeDisabled,
|
||||
reduceAmountBy = null,
|
||||
pendingAction = pendingAction,
|
||||
pendingActions = pendingActions.takeIf { isComposePendingActions },
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun isPartiallyUnstakeDisabled(state: StakingUiState): Boolean {
|
||||
// TODO staking [REDACTED_TASK_KEY] support solana multisize hashes signing
|
||||
if (BlockchainUtils.isSolana(state.cryptoCurrencyBlockchainId)) {
|
||||
return true
|
||||
}
|
||||
|
||||
val exitArgs = yieldArgs.exit ?: return false
|
||||
val exitAmount = exitArgs.args[Yield.Args.ArgType.AMOUNT] ?: return false
|
||||
val min = exitAmount.minimum ?: return false
|
||||
val max = exitAmount.maximum ?: return false
|
||||
return !min.isPositive() && !max.isPositive()
|
||||
}
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@ internal object SetTitleTransformer : Transformer<StakingUiState> {
|
|||
R.string.staking_title_stake,
|
||||
wrappedList(prevState.cryptoCurrencyName),
|
||||
)
|
||||
StakingActionCommonType.Exit -> resourceReference(
|
||||
is StakingActionCommonType.Exit -> resourceReference(
|
||||
R.string.staking_title_unstake,
|
||||
wrappedList(prevState.cryptoCurrencyName),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ internal class AmountChangeStateTransformer(
|
|||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
val actionType = prevState.actionType
|
||||
val maxEnterAmount = if (actionType == StakingActionCommonType.Exit) {
|
||||
val maxEnterAmount = if (actionType is StakingActionCommonType.Exit) {
|
||||
EnterAmountBoundary(
|
||||
amount = prevState.balanceState?.cryptoAmount,
|
||||
fiatAmount = prevState.balanceState?.fiatAmount,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ internal class AmountMaxValueStateTransformer(
|
|||
private val maxEnterAmountConverter = MaxEnterAmountConverter()
|
||||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
val maxEnterAmount = if (actionType == StakingActionCommonType.Exit) {
|
||||
val maxEnterAmount = if (actionType is StakingActionCommonType.Exit) {
|
||||
EnterAmountBoundary(
|
||||
amount = prevState.balanceState?.cryptoAmount,
|
||||
fiatAmount = prevState.balanceState?.fiatAmount,
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ internal class AmountRequirementStateTransformer(
|
|||
R.string.staking_amount_tron_integer_error,
|
||||
wrappedList(roundedDownCrypto),
|
||||
)
|
||||
StakingActionCommonType.Exit -> resourceReference(
|
||||
is StakingActionCommonType.Exit -> resourceReference(
|
||||
R.string.staking_amount_tron_integer_error_unstaking,
|
||||
wrappedList(roundedDownCrypto),
|
||||
)
|
||||
|
|
@ -96,7 +96,7 @@ internal class AmountRequirementStateTransformer(
|
|||
val enterRequirements = yield.args.enter.args[Yield.Args.ArgType.AMOUNT]
|
||||
enterRequirements?.getError(amountDecimal, R.string.staking_amount_requirement_error)
|
||||
}
|
||||
StakingActionCommonType.Exit -> {
|
||||
is StakingActionCommonType.Exit -> {
|
||||
val exitRequirements = yield.args.exit?.args?.get(Yield.Args.ArgType.AMOUNT)
|
||||
exitRequirements?.getError(amountDecimal, R.string.staking_unstake_amount_requirement_error)
|
||||
}
|
||||
|
|
@ -107,7 +107,7 @@ internal class AmountRequirementStateTransformer(
|
|||
private fun isIntegerOnlyError(amountState: AmountState.Data, actionType: StakingActionCommonType): Boolean {
|
||||
val cryptoAmountValue = amountState.amountTextField.cryptoAmount.value ?: return false
|
||||
|
||||
val isEnterOrExit = actionType == StakingActionCommonType.Enter || actionType == StakingActionCommonType.Exit
|
||||
val isEnterOrExit = actionType == StakingActionCommonType.Enter || actionType is StakingActionCommonType.Exit
|
||||
val isTron = isTron(cryptoCurrencyStatus.currency.network.id.value)
|
||||
|
||||
val isIntegerOnly = cryptoAmountValue.isZero() || cryptoAmountValue.remainder(BigDecimal.ONE).isZero()
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ internal class StakingInfoNotificationsFactory(
|
|||
|
||||
when (prevState.actionType) {
|
||||
StakingActionCommonType.Enter -> addEnterInfoNotifications(sendingAmount, feeValue)
|
||||
StakingActionCommonType.Exit -> addExitInfoNotifications()
|
||||
is StakingActionCommonType.Exit -> addExitInfoNotifications()
|
||||
is StakingActionCommonType.Pending -> addPendingInfoNotifications(prevState)
|
||||
}
|
||||
}
|
||||
|
|
@ -167,7 +167,7 @@ internal class StakingInfoNotificationsFactory(
|
|||
prevState: StakingUiState,
|
||||
actionAmount: BigDecimal,
|
||||
) {
|
||||
if (prevState.actionType != StakingActionCommonType.Exit) return
|
||||
if (prevState.actionType !is StakingActionCommonType.Exit) return
|
||||
|
||||
val maxAmount = prevState.balanceState?.cryptoAmount ?: return
|
||||
val exitRequirements = yield.args.exit?.args?.get(Yield.Args.ArgType.AMOUNT) ?: return
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import com.tangem.core.ui.components.transactions.TransactionDoneTitle
|
|||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
|
||||
import com.tangem.features.staking.impl.R
|
||||
import com.tangem.features.staking.impl.presentation.state.InnerConfirmationStakingState
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingNotification
|
||||
|
|
@ -39,11 +38,8 @@ internal fun StakingConfirmationContent(
|
|||
state: StakingStates.ConfirmationState,
|
||||
validatorState: StakingStates.ValidatorState,
|
||||
clickIntents: StakingClickIntents,
|
||||
type: StakingActionCommonType,
|
||||
isSolana: Boolean, // TODO staking [REDACTED_TASK_KEY] support solana multisize hashes signing
|
||||
) {
|
||||
if (state !is StakingStates.ConfirmationState.Data) return
|
||||
val isAmountEditable = type == StakingActionCommonType.Enter || type == StakingActionCommonType.Exit && !isSolana
|
||||
val isTransactionSent = state.innerState == InnerConfirmationStakingState.COMPLETED
|
||||
val isTransactionInProgress = state.notifications.any { it is StakingNotification.Warning.TransactionInProgress }
|
||||
Column(
|
||||
|
|
@ -65,8 +61,8 @@ internal fun StakingConfirmationContent(
|
|||
}
|
||||
AmountBlock(
|
||||
amountState = amountState,
|
||||
isClickDisabled = !isAmountEditable || isTransactionSent || isTransactionInProgress,
|
||||
isEditingDisabled = !isAmountEditable && state.innerState != InnerConfirmationStakingState.COMPLETED,
|
||||
isClickDisabled = !state.isAmountEditable || isTransactionSent || isTransactionInProgress,
|
||||
isEditingDisabled = !state.isAmountEditable && state.innerState != InnerConfirmationStakingState.COMPLETED,
|
||||
onClick = clickIntents::onPrevClick,
|
||||
)
|
||||
ValidatorBlock(
|
||||
|
|
@ -90,8 +86,6 @@ private fun Preview_StakingConfirmationContent() {
|
|||
state = ConfirmationStatePreviewData.assentStakingState,
|
||||
validatorState = ValidatorStatePreviewData.validatorState,
|
||||
clickIntents = StakingClickIntentsStub,
|
||||
type = StakingActionCommonType.Enter,
|
||||
isSolana = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ import com.tangem.features.staking.impl.presentation.state.bottomsheet.StakingAc
|
|||
import com.tangem.features.staking.impl.presentation.state.bottomsheet.StakingInfoBottomSheetConfig
|
||||
import com.tangem.features.staking.impl.presentation.ui.bottomsheet.StakingActionSelectorBottomSheet
|
||||
import com.tangem.features.staking.impl.presentation.ui.bottomsheet.StakingInfoBottomSheet
|
||||
import com.tangem.lib.crypto.BlockchainUtils.isSolana
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
|
@ -170,8 +169,6 @@ private fun StakingScreenContent(uiState: StakingUiState, modifier: Modifier = M
|
|||
state = uiState.confirmationState,
|
||||
validatorState = uiState.validatorState,
|
||||
clickIntents = uiState.clickIntents,
|
||||
type = uiState.actionType,
|
||||
isSolana = isSolana(uiState.cryptoCurrencyBlockchainId),
|
||||
)
|
||||
StakingStep.RestakeValidator,
|
||||
StakingStep.Validators,
|
||||
|
|
|
|||
|
|
@ -241,6 +241,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
stakingApproval = stakingApproval,
|
||||
stakingAllowance = stakingAllowance,
|
||||
yieldArgs = yield.args,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -711,7 +712,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
feeValue = fee.orZero(),
|
||||
reduceAmountBy = reduceAmountBy,
|
||||
)
|
||||
StakingActionCommonType.Exit,
|
||||
is StakingActionCommonType.Exit,
|
||||
is StakingActionCommonType.Pending,
|
||||
-> BigDecimal.ZERO
|
||||
}
|
||||
|
|
@ -996,6 +997,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
pendingActions = pendingActions,
|
||||
pendingAction = pendingAction,
|
||||
stakingAllowance = stakingAllowance,
|
||||
yieldArgs = yield.args,
|
||||
),
|
||||
ValidatorSelectChangeTransformer(
|
||||
selectedValidator = validator,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue