Updated on 2026-08-14
This commit is contained in:
parent
ef36fbf13e
commit
5e597758b9
13 changed files with 121 additions and 65 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
package com.tangem.features.staking.impl.presentation.state
|
package com.tangem.features.staking.impl.presentation.state
|
||||||
|
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
|
import com.tangem.domain.staking.model.stakekit.PendingAction
|
||||||
import com.tangem.domain.staking.model.stakekit.Yield
|
import com.tangem.domain.staking.model.stakekit.Yield
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
@ -31,6 +32,7 @@ data class BalanceState(
|
||||||
val fiatAmount: TextReference,
|
val fiatAmount: TextReference,
|
||||||
val rawCurrencyId: String?,
|
val rawCurrencyId: String?,
|
||||||
val unbondingPeriod: TextReference,
|
val unbondingPeriod: TextReference,
|
||||||
|
val pendingActions: ImmutableList<PendingAction>,
|
||||||
)
|
)
|
||||||
|
|
||||||
enum class BalanceGroupType {
|
enum class BalanceGroupType {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,9 @@ internal class StakingStateRouter(
|
||||||
when (stateController.value.currentStep) {
|
when (stateController.value.currentStep) {
|
||||||
StakingStep.InitialInfo -> when (stateController.value.routeType) {
|
StakingStep.InitialInfo -> when (stateController.value.routeType) {
|
||||||
RouteType.STAKE -> showAmount()
|
RouteType.STAKE -> showAmount()
|
||||||
RouteType.UNSTAKE -> showConfirmation()
|
RouteType.OTHER,
|
||||||
|
RouteType.UNSTAKE,
|
||||||
|
-> showConfirmation()
|
||||||
RouteType.CLAIM -> showRewardsValidators()
|
RouteType.CLAIM -> showRewardsValidators()
|
||||||
}
|
}
|
||||||
StakingStep.RewardsValidators,
|
StakingStep.RewardsValidators,
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import com.tangem.common.ui.amountScreen.models.AmountState
|
||||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||||
import com.tangem.core.ui.event.StateEvent
|
import com.tangem.core.ui.event.StateEvent
|
||||||
import com.tangem.core.ui.extensions.TextReference
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
|
import com.tangem.domain.staking.model.stakekit.PendingAction
|
||||||
import com.tangem.features.staking.impl.presentation.state.transformers.InfoType
|
import com.tangem.features.staking.impl.presentation.state.transformers.InfoType
|
||||||
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
|
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
@ -83,6 +84,7 @@ internal sealed class StakingStates {
|
||||||
val innerState: InnerConfirmationStakingState,
|
val innerState: InnerConfirmationStakingState,
|
||||||
val feeState: FeeState,
|
val feeState: FeeState,
|
||||||
val validatorState: ValidatorState,
|
val validatorState: ValidatorState,
|
||||||
|
val pendingActions: ImmutableList<PendingAction>,
|
||||||
val notifications: ImmutableList<StakingNotification>,
|
val notifications: ImmutableList<StakingNotification>,
|
||||||
val footerText: String,
|
val footerText: String,
|
||||||
val transactionDoneState: TransactionDoneState,
|
val transactionDoneState: TransactionDoneState,
|
||||||
|
|
@ -106,4 +108,5 @@ enum class RouteType {
|
||||||
STAKE,
|
STAKE,
|
||||||
UNSTAKE,
|
UNSTAKE,
|
||||||
CLAIM,
|
CLAIM,
|
||||||
|
OTHER,
|
||||||
}
|
}
|
||||||
|
|
@ -4,10 +4,7 @@ import com.tangem.core.ui.extensions.*
|
||||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||||
import com.tangem.core.ui.utils.parseBigDecimal
|
import com.tangem.core.ui.utils.parseBigDecimal
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
import com.tangem.domain.staking.model.stakekit.BalanceItem
|
import com.tangem.domain.staking.model.stakekit.*
|
||||||
import com.tangem.domain.staking.model.stakekit.BalanceType
|
|
||||||
import com.tangem.domain.staking.model.stakekit.Yield
|
|
||||||
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
|
||||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||||
import com.tangem.features.staking.impl.R
|
import com.tangem.features.staking.impl.R
|
||||||
import com.tangem.features.staking.impl.presentation.state.BalanceState
|
import com.tangem.features.staking.impl.presentation.state.BalanceState
|
||||||
|
|
@ -15,6 +12,7 @@ import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||||
import com.tangem.utils.Provider
|
import com.tangem.utils.Provider
|
||||||
import com.tangem.utils.StringsSigns.PLUS
|
import com.tangem.utils.StringsSigns.PLUS
|
||||||
import com.tangem.utils.converter.Converter
|
import com.tangem.utils.converter.Converter
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.toPersistentList
|
import kotlinx.collections.immutable.toPersistentList
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
|
@ -58,6 +56,7 @@ internal class RewardsValidatorStateConverter(
|
||||||
count = unbondingPeriod,
|
count = unbondingPeriod,
|
||||||
formatArgs = wrappedList(unbondingPeriod),
|
formatArgs = wrappedList(unbondingPeriod),
|
||||||
),
|
),
|
||||||
|
pendingActions = balance.pendingActions.toPersistentList(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,6 +65,7 @@ internal class RewardsValidatorStateConverter(
|
||||||
cryptoValue: BigDecimal,
|
cryptoValue: BigDecimal,
|
||||||
fiatValue: BigDecimal?,
|
fiatValue: BigDecimal?,
|
||||||
unbondingPeriod: TextReference,
|
unbondingPeriod: TextReference,
|
||||||
|
pendingActions: ImmutableList<PendingAction>,
|
||||||
): BalanceState {
|
): BalanceState {
|
||||||
val appCurrency = appCurrencyProvider()
|
val appCurrency = appCurrencyProvider()
|
||||||
val cryptoCurrency = cryptoCurrencyStatus.currency
|
val cryptoCurrency = cryptoCurrencyStatus.currency
|
||||||
|
|
@ -95,6 +95,7 @@ internal class RewardsValidatorStateConverter(
|
||||||
fiatAmount = fiatAmount,
|
fiatAmount = fiatAmount,
|
||||||
rawCurrencyId = cryptoCurrency.id.rawCurrencyId,
|
rawCurrencyId = cryptoCurrency.id.rawCurrencyId,
|
||||||
unbondingPeriod = unbondingPeriod,
|
unbondingPeriod = unbondingPeriod,
|
||||||
|
pendingActions = pendingActions,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -104,6 +104,7 @@ internal class YieldBalancesConverter(
|
||||||
count = unbondingPeriod,
|
count = unbondingPeriod,
|
||||||
formatArgs = wrappedList(unbondingPeriod),
|
formatArgs = wrappedList(unbondingPeriod),
|
||||||
),
|
),
|
||||||
|
pendingActions = balance.pendingActions.toPersistentList(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,5 +85,6 @@ internal object ConfirmationStatePreviewData {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
transactionDoneState = TransactionDoneState.Empty,
|
transactionDoneState = TransactionDoneState.Empty,
|
||||||
|
pendingActions = persistentListOf(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -51,6 +51,7 @@ internal object InitialStakingStatePreview {
|
||||||
preferred = false,
|
preferred = false,
|
||||||
),
|
),
|
||||||
unbondingPeriod = stringReference("3 days"),
|
unbondingPeriod = stringReference("3 days"),
|
||||||
|
pendingActions = persistentListOf(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,17 @@
|
||||||
package com.tangem.features.staking.impl.presentation.state.stub
|
package com.tangem.features.staking.impl.presentation.state.stub
|
||||||
|
|
||||||
|
import com.tangem.domain.staking.model.stakekit.PendingAction
|
||||||
import com.tangem.domain.staking.model.stakekit.Yield
|
import com.tangem.domain.staking.model.stakekit.Yield
|
||||||
import com.tangem.features.staking.impl.presentation.state.BalanceState
|
import com.tangem.features.staking.impl.presentation.state.BalanceState
|
||||||
import com.tangem.features.staking.impl.presentation.state.transformers.InfoType
|
import com.tangem.features.staking.impl.presentation.state.transformers.InfoType
|
||||||
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
|
import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
object StakingClickIntentsStub : StakingClickIntents {
|
object StakingClickIntentsStub : StakingClickIntents {
|
||||||
|
|
||||||
override fun onBackClick() {}
|
override fun onBackClick() {}
|
||||||
|
|
||||||
override fun onNextClick() {}
|
override fun onNextClick(pendingActions: ImmutableList<PendingAction>) {}
|
||||||
|
|
||||||
override fun onPrevClick() {}
|
override fun onPrevClick() {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,25 @@
|
||||||
package com.tangem.features.staking.impl.presentation.state.transformers
|
package com.tangem.features.staking.impl.presentation.state.transformers
|
||||||
|
|
||||||
|
import com.tangem.blockchain.common.Amount
|
||||||
import com.tangem.blockchain.common.transaction.Fee
|
import com.tangem.blockchain.common.transaction.Fee
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
|
import com.tangem.domain.staking.model.stakekit.PendingAction
|
||||||
import com.tangem.domain.staking.model.stakekit.transaction.StakingGasEstimate
|
import com.tangem.domain.staking.model.stakekit.transaction.StakingGasEstimate
|
||||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||||
import com.tangem.features.staking.impl.presentation.state.FeeState
|
import com.tangem.features.staking.impl.presentation.state.FeeState
|
||||||
|
import com.tangem.features.staking.impl.presentation.state.InnerConfirmationStakingState
|
||||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||||
import com.tangem.utils.Provider
|
import com.tangem.utils.Provider
|
||||||
import com.tangem.utils.transformer.Transformer
|
import com.tangem.utils.transformer.Transformer
|
||||||
import com.tangem.blockchain.common.Amount
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import com.tangem.features.staking.impl.presentation.state.InnerConfirmationStakingState
|
|
||||||
|
|
||||||
@Suppress("UnusedPrivateMember")
|
@Suppress("UnusedPrivateMember")
|
||||||
internal class SetConfirmationStateAssentTransformer(
|
internal class SetConfirmationStateAssentTransformer(
|
||||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||||
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
|
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
|
||||||
private val stakingGasEstimate: StakingGasEstimate,
|
private val stakingGasEstimate: StakingGasEstimate,
|
||||||
|
private val pendingActionList: ImmutableList<PendingAction>,
|
||||||
) : Transformer<StakingUiState> {
|
) : Transformer<StakingUiState> {
|
||||||
|
|
||||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||||
|
|
@ -45,6 +48,7 @@ internal class SetConfirmationStateAssentTransformer(
|
||||||
isFeeApproximate = false,
|
isFeeApproximate = false,
|
||||||
),
|
),
|
||||||
validatorState = validatorState.copySealed(isClickable = true),
|
validatorState = validatorState.copySealed(isClickable = true),
|
||||||
|
pendingActions = pendingActionList,
|
||||||
isPrimaryButtonEnabled = true,
|
isPrimaryButtonEnabled = true,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,6 @@ package com.tangem.features.staking.impl.presentation.state.transformers
|
||||||
|
|
||||||
import com.tangem.domain.staking.model.stakekit.Yield
|
import com.tangem.domain.staking.model.stakekit.Yield
|
||||||
import com.tangem.features.staking.impl.presentation.state.*
|
import com.tangem.features.staking.impl.presentation.state.*
|
||||||
import com.tangem.features.staking.impl.presentation.state.StakingNotification
|
|
||||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
|
||||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
|
||||||
import com.tangem.features.staking.impl.presentation.state.ValidatorState
|
|
||||||
import com.tangem.utils.transformer.Transformer
|
import com.tangem.utils.transformer.Transformer
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
|
|
@ -37,6 +33,7 @@ internal class SetConfirmationStateLoadingTransformer(
|
||||||
),
|
),
|
||||||
footerText = "",
|
footerText = "",
|
||||||
transactionDoneState = TransactionDoneState.Empty,
|
transactionDoneState = TransactionDoneState.Empty,
|
||||||
|
pendingActions = persistentListOf(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,6 @@ import com.tangem.core.ui.components.buttons.common.TangemButtonIconPosition
|
||||||
import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults
|
import com.tangem.core.ui.components.buttons.common.TangemButtonsDefaults
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.features.staking.impl.presentation.state.*
|
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.StakingUiState
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun StakingNavigationButtons(uiState: StakingUiState, modifier: Modifier = Modifier) {
|
internal fun StakingNavigationButtons(uiState: StakingUiState, modifier: Modifier = Modifier) {
|
||||||
|
|
@ -70,10 +68,8 @@ private fun StakingNavigationButton(uiState: StakingUiState, modifier: Modifier
|
||||||
val showTangemIcon = uiState.currentStep == StakingStep.Confirmation &&
|
val showTangemIcon = uiState.currentStep == StakingStep.Confirmation &&
|
||||||
(isInProgressInnerState || isInAssentInnerState)
|
(isInProgressInnerState || isInAssentInnerState)
|
||||||
|
|
||||||
val (buttonTextId, buttonClick) = getButtonData(
|
val buttonTextId = getButtonData(currentState = uiState)
|
||||||
currentState = uiState,
|
val (isButtonEnabled, isButtonDisplayed) = isButtonEnabled(uiState)
|
||||||
)
|
|
||||||
val isButtonEnabled = isButtonEnabled(uiState)
|
|
||||||
val buttonIcon = if (showTangemIcon) {
|
val buttonIcon = if (showTangemIcon) {
|
||||||
TangemButtonIconPosition.End(R.drawable.ic_tangem_24)
|
TangemButtonIconPosition.End(R.drawable.ic_tangem_24)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -101,17 +97,17 @@ private fun StakingNavigationButton(uiState: StakingUiState, modifier: Modifier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = buttonClick != null,
|
visible = isButtonDisplayed,
|
||||||
enter = fadeIn(),
|
enter = fadeIn(),
|
||||||
exit = fadeOut(),
|
exit = fadeOut(),
|
||||||
) {
|
) {
|
||||||
TangemButton(
|
TangemButton(
|
||||||
text = stringResource(buttonTextId),
|
text = stringResource(buttonTextId),
|
||||||
icon = buttonIcon,
|
icon = buttonIcon,
|
||||||
enabled = isButtonEnabled && buttonClick != null,
|
enabled = isButtonEnabled && isButtonDisplayed,
|
||||||
onClick = {
|
onClick = {
|
||||||
if (showTangemIcon) hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
if (showTangemIcon) hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||||
if (buttonClick != null) buttonClick()
|
onPrimaryClick(uiState)
|
||||||
},
|
},
|
||||||
showProgress = isInProgressInnerState,
|
showProgress = isInProgressInnerState,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
|
@ -121,37 +117,62 @@ private fun StakingNavigationButton(uiState: StakingUiState, modifier: Modifier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getButtonData(currentState: StakingUiState): Pair<Int, (() -> Unit)?> {
|
private fun getButtonData(currentState: StakingUiState): Int {
|
||||||
return when (currentState.currentStep) {
|
return when (currentState.currentStep) {
|
||||||
StakingStep.InitialInfo -> {
|
StakingStep.InitialInfo -> {
|
||||||
val initialState = currentState.initialInfoState as? StakingStates.InitialInfoState.Data
|
val initialState = currentState.initialInfoState as? StakingStates.InitialInfoState.Data
|
||||||
if (initialState?.yieldBalance is InnerYieldBalanceState.Data) {
|
if (initialState?.yieldBalance is InnerYieldBalanceState.Data) {
|
||||||
val click = if (initialState.isStakeMoreAvailable) {
|
R.string.staking_stake_more
|
||||||
currentState.clickIntents::onNextClick
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
R.string.staking_stake_more to click
|
|
||||||
} else {
|
} else {
|
||||||
R.string.common_next to currentState.clickIntents::onNextClick
|
R.string.common_next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StakingStep.Amount,
|
|
||||||
-> R.string.common_next to currentState.clickIntents::onNextClick
|
|
||||||
StakingStep.Confirmation -> {
|
StakingStep.Confirmation -> {
|
||||||
val confirmationState = currentState.confirmationState
|
val confirmationState = currentState.confirmationState
|
||||||
if (confirmationState is StakingStates.ConfirmationState.Data) {
|
if (confirmationState is StakingStates.ConfirmationState.Data) {
|
||||||
if (confirmationState.innerState == InnerConfirmationStakingState.COMPLETED) {
|
if (confirmationState.innerState == InnerConfirmationStakingState.COMPLETED) {
|
||||||
R.string.common_close to currentState.clickIntents::onBackClick
|
R.string.common_close
|
||||||
} else {
|
} else {
|
||||||
R.string.common_stake to currentState.clickIntents::onNextClick
|
R.string.common_stake
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
R.string.common_close to currentState.clickIntents::onBackClick
|
R.string.common_close
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StakingStep.Validators -> R.string.common_continue to currentState.clickIntents::onNextClick
|
StakingStep.Validators -> R.string.common_continue
|
||||||
StakingStep.RewardsValidators -> R.string.common_next to null
|
StakingStep.Amount,
|
||||||
|
StakingStep.RewardsValidators,
|
||||||
|
-> R.string.common_next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onPrimaryClick(currentState: StakingUiState) {
|
||||||
|
when (currentState.currentStep) {
|
||||||
|
StakingStep.InitialInfo -> {
|
||||||
|
val initialState = currentState.initialInfoState as? StakingStates.InitialInfoState.Data
|
||||||
|
if (initialState?.yieldBalance is InnerYieldBalanceState.Data) {
|
||||||
|
if (initialState.isStakeMoreAvailable) {
|
||||||
|
currentState.clickIntents.onNextClick()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentState.clickIntents.onNextClick()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StakingStep.Amount -> currentState.clickIntents.onNextClick()
|
||||||
|
StakingStep.Confirmation -> {
|
||||||
|
val confirmationState = currentState.confirmationState
|
||||||
|
if (confirmationState is StakingStates.ConfirmationState.Data) {
|
||||||
|
if (confirmationState.innerState == InnerConfirmationStakingState.COMPLETED) {
|
||||||
|
currentState.clickIntents.onBackClick()
|
||||||
|
} else {
|
||||||
|
currentState.clickIntents.onNextClick()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentState.clickIntents.onBackClick()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StakingStep.Validators -> currentState.clickIntents.onNextClick()
|
||||||
|
StakingStep.RewardsValidators -> Unit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,12 +186,16 @@ private fun isPrevButtonVisible(step: StakingStep): Boolean = when (step) {
|
||||||
-> true
|
-> true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isButtonEnabled(uiState: StakingUiState): Boolean {
|
private fun isButtonEnabled(uiState: StakingUiState): Pair<Boolean, Boolean> {
|
||||||
return when (uiState.currentStep) {
|
return when (uiState.currentStep) {
|
||||||
StakingStep.InitialInfo -> uiState.initialInfoState.isPrimaryButtonEnabled
|
StakingStep.InitialInfo -> {
|
||||||
StakingStep.Amount -> uiState.amountState.isPrimaryButtonEnabled
|
val initialState = uiState.initialInfoState as? StakingStates.InitialInfoState.Data
|
||||||
StakingStep.Confirmation -> uiState.confirmationState.isPrimaryButtonEnabled
|
val isDisplayed = initialState?.isStakeMoreAvailable == true
|
||||||
StakingStep.RewardsValidators -> uiState.rewardsValidatorsState.isPrimaryButtonEnabled
|
uiState.initialInfoState.isPrimaryButtonEnabled to isDisplayed
|
||||||
StakingStep.Validators -> true
|
}
|
||||||
|
StakingStep.Amount -> uiState.amountState.isPrimaryButtonEnabled to true
|
||||||
|
StakingStep.Confirmation -> uiState.confirmationState.isPrimaryButtonEnabled to true
|
||||||
|
StakingStep.RewardsValidators -> uiState.rewardsValidatorsState.isPrimaryButtonEnabled to false
|
||||||
|
StakingStep.Validators -> true to true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,15 +1,18 @@
|
||||||
package com.tangem.features.staking.impl.presentation.viewmodel
|
package com.tangem.features.staking.impl.presentation.viewmodel
|
||||||
|
|
||||||
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
|
import com.tangem.common.ui.amountScreen.AmountScreenClickIntents
|
||||||
|
import com.tangem.domain.staking.model.stakekit.PendingAction
|
||||||
import com.tangem.domain.staking.model.stakekit.Yield
|
import com.tangem.domain.staking.model.stakekit.Yield
|
||||||
import com.tangem.features.staking.impl.presentation.state.BalanceState
|
import com.tangem.features.staking.impl.presentation.state.BalanceState
|
||||||
import com.tangem.features.staking.impl.presentation.state.transformers.InfoType
|
import com.tangem.features.staking.impl.presentation.state.transformers.InfoType
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
internal interface StakingClickIntents : AmountScreenClickIntents {
|
internal interface StakingClickIntents : AmountScreenClickIntents {
|
||||||
|
|
||||||
fun onBackClick()
|
fun onBackClick()
|
||||||
|
|
||||||
fun onNextClick()
|
fun onNextClick(pendingActions: ImmutableList<PendingAction> = persistentListOf())
|
||||||
|
|
||||||
fun onPrevClick()
|
fun onPrevClick()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||||
import com.tangem.domain.staking.*
|
import com.tangem.domain.staking.*
|
||||||
|
import com.tangem.domain.staking.model.stakekit.PendingAction
|
||||||
import com.tangem.domain.staking.model.stakekit.Yield
|
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.StakingActionCommonType
|
||||||
import com.tangem.domain.staking.model.stakekit.transaction.ActionParams
|
import com.tangem.domain.staking.model.stakekit.transaction.ActionParams
|
||||||
|
|
@ -38,13 +39,14 @@ import com.tangem.features.staking.impl.presentation.state.transformers.validato
|
||||||
import com.tangem.utils.Provider
|
import com.tangem.utils.Provider
|
||||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LargeClass", "LongParameterList")
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
internal class StakingViewModel @Inject constructor(
|
internal class StakingViewModel @Inject constructor(
|
||||||
private val stateController: StakingStateController,
|
private val stateController: StakingStateController,
|
||||||
|
|
@ -98,11 +100,11 @@ internal class StakingViewModel @Inject constructor(
|
||||||
stakingStateRouter.onBackClick()
|
stakingStateRouter.onBackClick()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNextClick() {
|
override fun onNextClick(pendingActions: ImmutableList<PendingAction>) {
|
||||||
handleOnNextConfirmationClick()
|
handleOnNextConfirmationClick()
|
||||||
stakingStateRouter.onNextClick()
|
stakingStateRouter.onNextClick()
|
||||||
if (isAssentState()) {
|
if (isAssentState()) {
|
||||||
initStaking()
|
estimateGas(pendingActions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -115,16 +117,11 @@ internal class StakingViewModel @Inject constructor(
|
||||||
value.confirmationState as? StakingStates.ConfirmationState.Data ?: error("No confirmation state")
|
value.confirmationState as? StakingStates.ConfirmationState.Data ?: error("No confirmation state")
|
||||||
val validatorState = confirmationState.validatorState as? ValidatorState.Content
|
val validatorState = confirmationState.validatorState as? ValidatorState.Content
|
||||||
?: error("No validator provided")
|
?: error("No validator provided")
|
||||||
|
val pendingActions = confirmationState.pendingActions
|
||||||
val actionType = when (value.routeType) {
|
|
||||||
RouteType.STAKE -> StakingActionCommonType.ENTER
|
|
||||||
RouteType.UNSTAKE -> StakingActionCommonType.EXIT
|
|
||||||
RouteType.CLAIM -> TODO()
|
|
||||||
}
|
|
||||||
|
|
||||||
val stakingTransaction = getStakingTransactionUseCase(
|
val stakingTransaction = getStakingTransactionUseCase(
|
||||||
params = ActionParams(
|
params = ActionParams(
|
||||||
actionCommonType = actionType,
|
actionCommonType = getStakingCommonType(),
|
||||||
integrationId = yield.id,
|
integrationId = yield.id,
|
||||||
amount = (value.amountState as? AmountState.Data)?.amountTextField?.cryptoAmount?.value
|
amount = (value.amountState as? AmountState.Data)?.amountTextField?.cryptoAmount?.value
|
||||||
?: error("No amount provided"),
|
?: error("No amount provided"),
|
||||||
|
|
@ -132,6 +129,8 @@ internal class StakingViewModel @Inject constructor(
|
||||||
?: error("No available address"),
|
?: error("No available address"),
|
||||||
validatorAddress = validatorState.chosenValidator.address,
|
validatorAddress = validatorState.chosenValidator.address,
|
||||||
token = yield.token,
|
token = yield.token,
|
||||||
|
passthrough = pendingActions.firstOrNull()?.passthrough,
|
||||||
|
type = pendingActions.firstOrNull()?.type,
|
||||||
),
|
),
|
||||||
).getOrElse {
|
).getOrElse {
|
||||||
error(it)
|
error(it)
|
||||||
|
|
@ -141,37 +140,35 @@ internal class StakingViewModel @Inject constructor(
|
||||||
sendStakingTransaction(
|
sendStakingTransaction(
|
||||||
transactionId = stakingTransaction.id,
|
transactionId = stakingTransaction.id,
|
||||||
gasEstimate = stakingTransaction.gasEstimate ?: error("No gas estimate available"),
|
gasEstimate = stakingTransaction.gasEstimate ?: error("No gas estimate available"),
|
||||||
TransactionData.Compiled(value = it.hexToBytes()),
|
txData = TransactionData.Compiled(value = it.hexToBytes()),
|
||||||
|
pendingActions = pendingActions,
|
||||||
)
|
)
|
||||||
} ?: error("No unsigned transaction available")
|
} ?: error("No unsigned transaction available")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initStaking() {
|
private fun estimateGas(pendingActions: ImmutableList<PendingAction>) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
stateController.update(
|
stateController.update(
|
||||||
SetConfirmationStateLoadingTransformer(
|
SetConfirmationStateLoadingTransformer(
|
||||||
yield = yield,
|
yield = yield,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
val cryptoCurrencyValue = cryptoCurrencyStatus.value
|
||||||
val actionType = when (value.routeType) {
|
|
||||||
RouteType.STAKE -> StakingActionCommonType.ENTER
|
|
||||||
RouteType.UNSTAKE -> StakingActionCommonType.EXIT
|
|
||||||
RouteType.CLAIM -> TODO()
|
|
||||||
}
|
|
||||||
|
|
||||||
val stakingGasEstimate = estimateGasUseCase(
|
val stakingGasEstimate = estimateGasUseCase(
|
||||||
params = ActionParams(
|
params = ActionParams(
|
||||||
actionCommonType = actionType,
|
actionCommonType = getStakingCommonType(),
|
||||||
integrationId = yield.id,
|
integrationId = yield.id,
|
||||||
amount = (value.amountState as? AmountState.Data)?.amountTextField?.cryptoAmount?.value
|
amount = (value.amountState as? AmountState.Data)?.amountTextField?.cryptoAmount?.value
|
||||||
?: error("No amount provided"),
|
?: error("No amount provided"),
|
||||||
address = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value
|
address = cryptoCurrencyValue.networkAddress?.defaultAddress?.value
|
||||||
?: error("No available address"),
|
?: error("No available address"),
|
||||||
validatorAddress = yield.validators.getOrNull(0)?.address ?: error("No available validator"),
|
validatorAddress = yield.validators.getOrNull(0)?.address ?: error("No available validator"),
|
||||||
token = yield.token,
|
token = yield.token,
|
||||||
|
passthrough = pendingActions.firstOrNull()?.passthrough,
|
||||||
|
type = pendingActions.firstOrNull()?.type,
|
||||||
),
|
),
|
||||||
).getOrElse { error("Can't get fee info") }
|
).getOrElse { error("Can't get fee info") }
|
||||||
|
|
||||||
|
|
@ -180,6 +177,7 @@ internal class StakingViewModel @Inject constructor(
|
||||||
appCurrencyProvider = Provider { appCurrency },
|
appCurrencyProvider = Provider { appCurrency },
|
||||||
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
|
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
|
||||||
stakingGasEstimate = stakingGasEstimate,
|
stakingGasEstimate = stakingGasEstimate,
|
||||||
|
pendingActionList = pendingActions,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -230,9 +228,14 @@ internal class StakingViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActiveStake(activeStake: BalanceState) {
|
override fun onActiveStake(activeStake: BalanceState) {
|
||||||
stateController.update { it.copy(routeType = RouteType.UNSTAKE) }
|
val routeType = if (activeStake.pendingActions.isEmpty()) {
|
||||||
|
RouteType.UNSTAKE
|
||||||
|
} else {
|
||||||
|
RouteType.OTHER
|
||||||
|
}
|
||||||
|
stateController.update { it.copy(routeType = routeType) }
|
||||||
stateController.update(AmountChangeStateTransformer(cryptoCurrencyStatus, activeStake.cryptoValue))
|
stateController.update(AmountChangeStateTransformer(cryptoCurrencyStatus, activeStake.cryptoValue))
|
||||||
onNextClick()
|
onNextClick(activeStake.pendingActions)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onExploreClick() {
|
override fun onExploreClick() {
|
||||||
|
|
@ -314,6 +317,7 @@ internal class StakingViewModel @Inject constructor(
|
||||||
transactionId: String,
|
transactionId: String,
|
||||||
gasEstimate: StakingGasEstimate,
|
gasEstimate: StakingGasEstimate,
|
||||||
txData: TransactionData,
|
txData: TransactionData,
|
||||||
|
pendingActions: ImmutableList<PendingAction>,
|
||||||
) {
|
) {
|
||||||
sendTransactionUseCase(
|
sendTransactionUseCase(
|
||||||
txData = txData,
|
txData = txData,
|
||||||
|
|
@ -327,8 +331,10 @@ internal class StakingViewModel @Inject constructor(
|
||||||
appCurrencyProvider = Provider { appCurrency },
|
appCurrencyProvider = Provider { appCurrency },
|
||||||
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
|
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
|
||||||
stakingGasEstimate = gasEstimate,
|
stakingGasEstimate = gasEstimate,
|
||||||
|
pendingActionList = pendingActions,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
// todo add error dialog
|
||||||
},
|
},
|
||||||
ifRight = { txHash ->
|
ifRight = { txHash ->
|
||||||
submitHash(transactionId, txHash)
|
submitHash(transactionId, txHash)
|
||||||
|
|
@ -370,4 +376,12 @@ internal class StakingViewModel @Inject constructor(
|
||||||
(value.confirmationState as? StakingStates.ConfirmationState.Data)?.innerState ==
|
(value.confirmationState as? StakingStates.ConfirmationState.Data)?.innerState ==
|
||||||
InnerConfirmationStakingState.ASSENT
|
InnerConfirmationStakingState.ASSENT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getStakingCommonType() = when (value.routeType) {
|
||||||
|
RouteType.STAKE -> StakingActionCommonType.ENTER
|
||||||
|
RouteType.UNSTAKE -> StakingActionCommonType.EXIT
|
||||||
|
RouteType.CLAIM,
|
||||||
|
RouteType.OTHER,
|
||||||
|
-> StakingActionCommonType.PENDING
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue