Updated on 2026-08-14
This commit is contained in:
parent
8202b6bf2a
commit
ab85772d10
47 changed files with 356 additions and 116 deletions
|
|
@ -30,9 +30,10 @@ internal data class BalanceState(
|
|||
val subtitle: TextReference?,
|
||||
val isClickable: Boolean,
|
||||
val cryptoValue: String,
|
||||
val cryptoDecimal: BigDecimal,
|
||||
val cryptoAmount: TextReference,
|
||||
val fiatAmount: TextReference,
|
||||
val cryptoAmount: BigDecimal,
|
||||
val formattedCryptoAmount: TextReference,
|
||||
val fiatAmount: BigDecimal?,
|
||||
val formattedFiatAmount: TextReference,
|
||||
val rawCurrencyId: String?,
|
||||
val validator: Yield.Validator?,
|
||||
val pendingActions: ImmutableList<PendingAction>,
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ internal class StakingStateController @Inject constructor(
|
|||
walletName = "",
|
||||
cryptoCurrencyName = "",
|
||||
cryptoCurrencySymbol = "",
|
||||
cryptoCurrencyNetworkId = "",
|
||||
currentStep = StakingStep.InitialInfo,
|
||||
initialInfoState = StakingStates.InitialInfoState.Empty(),
|
||||
amountState = AmountState.Empty(),
|
||||
|
|
@ -86,6 +87,7 @@ internal class StakingStateController @Inject constructor(
|
|||
bottomSheetConfig = null,
|
||||
actionType = StakingActionCommonType.Enter,
|
||||
buttonsState = NavigationButtonsState.Empty,
|
||||
balanceState = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ 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.features.staking.impl.analytics.utils.StakingAnalyticSender
|
||||
import com.tangem.lib.crypto.BlockchainUtils.isSolana
|
||||
|
||||
internal class StakingStateRouter(
|
||||
private val appRouter: AppRouter,
|
||||
|
|
@ -24,8 +25,13 @@ internal class StakingStateRouter(
|
|||
when (stateController.value.currentStep) {
|
||||
StakingStep.InitialInfo -> when (stateController.value.actionType) {
|
||||
StakingActionCommonType.Enter -> showAmount()
|
||||
// TODO staking [REDACTED_TASK_KEY] support solana multisize hashes signing
|
||||
StakingActionCommonType.Exit -> if (isSolana(stateController.value.cryptoCurrencyNetworkId)) {
|
||||
showConfirmation()
|
||||
} else {
|
||||
showAmount()
|
||||
}
|
||||
StakingActionCommonType.Pending.Other,
|
||||
StakingActionCommonType.Exit,
|
||||
StakingActionCommonType.Pending.Rewards,
|
||||
-> showConfirmation()
|
||||
StakingActionCommonType.Pending.Restake -> showRestakeValidators()
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ internal data class StakingUiState(
|
|||
val walletName: String,
|
||||
val cryptoCurrencyName: String,
|
||||
val cryptoCurrencySymbol: String,
|
||||
val cryptoCurrencyNetworkId: String,
|
||||
val currentStep: StakingStep,
|
||||
val initialInfoState: StakingStates.InitialInfoState,
|
||||
val amountState: AmountState,
|
||||
|
|
@ -40,6 +41,7 @@ internal data class StakingUiState(
|
|||
val actionType: StakingActionCommonType,
|
||||
val buttonsState: NavigationButtonsState,
|
||||
val event: StateEvent<StakingEvent>,
|
||||
val balanceState: BalanceState?,
|
||||
) {
|
||||
|
||||
fun copyWrapped(
|
||||
|
|
|
|||
|
|
@ -47,11 +47,12 @@ internal class BalanceItemConverter(
|
|||
subtitle = getSubtitle(value),
|
||||
type = value.type,
|
||||
cryptoValue = cryptoAmount.parseBigDecimal(cryptoCurrency.decimals),
|
||||
cryptoDecimal = cryptoAmount,
|
||||
cryptoAmount = stringReference(
|
||||
cryptoAmount = cryptoAmount,
|
||||
formattedCryptoAmount = stringReference(
|
||||
cryptoAmount.format { crypto(cryptoCurrency) },
|
||||
),
|
||||
fiatAmount = stringReference(
|
||||
fiatAmount = fiatAmount,
|
||||
formattedFiatAmount = stringReference(
|
||||
BigDecimalFormatter.formatFiatAmount(
|
||||
fiatAmount = fiatAmount,
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ internal class RewardsValidatorStateConverter(
|
|||
crypto(cryptoCurrency)
|
||||
},
|
||||
)
|
||||
val fiatAmount = stringReference(
|
||||
val formattedFiatAmount = stringReference(
|
||||
BigDecimalFormatter.formatFiatAmount(
|
||||
fiatAmount = fiatValue,
|
||||
fiatCurrencyCode = appCurrency.code,
|
||||
|
|
@ -85,9 +85,10 @@ internal class RewardsValidatorStateConverter(
|
|||
title = stringReference(this.name),
|
||||
subtitle = null,
|
||||
cryptoValue = cryptoValue.parseBigDecimal(cryptoCurrency.decimals),
|
||||
cryptoDecimal = cryptoValue,
|
||||
cryptoAmount = cryptoAmount,
|
||||
fiatAmount = fiatAmount,
|
||||
cryptoAmount = cryptoValue,
|
||||
formattedCryptoAmount = cryptoAmount,
|
||||
fiatAmount = fiatValue,
|
||||
formattedFiatAmount = formattedFiatAmount,
|
||||
rawCurrencyId = cryptoCurrency.id.rawCurrencyId,
|
||||
pendingActions = balance.pendingActions.toPersistentList(),
|
||||
isClickable = true,
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ internal class YieldBalancesConverter(
|
|||
private fun List<BalanceItem>.mapBalances() = asSequence()
|
||||
.filterNot { it.amount.isZero() || it.type == BalanceType.REWARDS }
|
||||
.mapNotNull(balanceItemConverter::convert)
|
||||
.sortedByDescending { it.cryptoDecimal }
|
||||
.sortedByDescending { it.cryptoAmount }
|
||||
.sortedBy { it.type.order }
|
||||
.toPersistentList()
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import com.tangem.domain.transaction.usecase.GetFeeUseCase
|
|||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStateController
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingStates
|
||||
import com.tangem.features.staking.impl.presentation.state.utils.isComposePendingActions
|
||||
import com.tangem.features.staking.impl.presentation.state.utils.isCompositePendingActions
|
||||
import com.tangem.utils.extensions.orZero
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
|
|
@ -95,7 +95,11 @@ internal class StakingFeeTransactionLoader @AssistedInject constructor(
|
|||
val sourceAddress = cryptoCurrencyStatus.value.networkAddress?.defaultAddress?.value
|
||||
?: error("No available address")
|
||||
|
||||
val gasEstimate = if (isComposePendingActions(cryptoCurrencyStatus.currency.network.id.value, pendingActions)) {
|
||||
val gasEstimate = if (isCompositePendingActions(
|
||||
networkId = cryptoCurrencyStatus.currency.network.id.value,
|
||||
pendingActions = pendingActions,
|
||||
)
|
||||
) {
|
||||
val result = coroutineScope {
|
||||
pendingActions?.map { action ->
|
||||
async {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import com.tangem.domain.utils.convertToSdkAmount
|
|||
import com.tangem.domain.wallets.models.UserWallet
|
||||
import com.tangem.features.staking.impl.presentation.state.*
|
||||
import com.tangem.features.staking.impl.presentation.state.utils.checkAndCalculateSubtractedAmount
|
||||
import com.tangem.features.staking.impl.presentation.state.utils.isComposePendingActions
|
||||
import com.tangem.features.staking.impl.presentation.state.utils.isCompositePendingActions
|
||||
import com.tangem.utils.extensions.orZero
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
|
|
@ -96,7 +96,7 @@ internal class StakingTransactionSender @AssistedInject constructor(
|
|||
confirmationState: StakingStates.ConfirmationState.Data,
|
||||
onConstructError: (StakingError) -> Unit,
|
||||
) = coroutineScope {
|
||||
val isComposePendingActions = isComposePendingActions(
|
||||
val isComposePendingActions = isCompositePendingActions(
|
||||
cryptoCurrencyStatus.currency.network.id.value,
|
||||
confirmationState.pendingActions,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -73,9 +73,10 @@ internal object InitialStakingStatePreview {
|
|||
groupId = "groupId",
|
||||
title = stringReference("Binance"),
|
||||
cryptoValue = "100",
|
||||
cryptoAmount = stringReference("100 SOL"),
|
||||
cryptoDecimal = "100".toBigDecimal(),
|
||||
fiatAmount = stringReference("100 $"),
|
||||
formattedCryptoAmount = stringReference("100 SOL"),
|
||||
cryptoAmount = "100".toBigDecimal(),
|
||||
fiatAmount = null,
|
||||
formattedFiatAmount = stringReference("100 $"),
|
||||
rawCurrencyId = null,
|
||||
validator = Yield.Validator(
|
||||
address = "address",
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ internal object StakingClickIntentsStub : StakingClickIntents {
|
|||
|
||||
override fun onInfoClick(infoType: InfoType) {}
|
||||
|
||||
override fun onEnterClick() {}
|
||||
override fun onAmountEnterClick() {}
|
||||
|
||||
override fun onAmountValueChange(value: String) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers
|
||||
|
||||
import com.tangem.common.ui.amountScreen.converters.AmountStateConverter
|
||||
import com.tangem.common.ui.amountScreen.models.AmountParameters
|
||||
import com.tangem.common.ui.amountScreen.models.MaxEnterAmount
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
|
||||
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.viewmodel.StakingClickIntents
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
internal class SetAmountDataTransformer(
|
||||
private val clickIntents: StakingClickIntents,
|
||||
private val cryptoCurrencyStatusProvider: Provider<CryptoCurrencyStatus>,
|
||||
private val userWalletProvider: Provider<UserWallet>,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val maxEnterAmountProvider: Provider<MaxEnterAmount>,
|
||||
) : Transformer<StakingUiState> {
|
||||
|
||||
private val iconStateConverter by lazy(::CryptoCurrencyToIconStateConverter)
|
||||
|
||||
private val amountStateConverter by lazy(LazyThreadSafetyMode.NONE) {
|
||||
AmountStateConverter(
|
||||
clickIntents = clickIntents,
|
||||
cryptoCurrencyStatusProvider = cryptoCurrencyStatusProvider,
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
iconStateConverter = iconStateConverter,
|
||||
maxEnterAmountProvider = maxEnterAmountProvider,
|
||||
)
|
||||
}
|
||||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
val title = if (prevState.actionType == StakingActionCommonType.Exit) {
|
||||
resourceReference(R.string.staking_staked_amount)
|
||||
} else {
|
||||
stringReference(userWalletProvider().name)
|
||||
}
|
||||
|
||||
return prevState.copy(
|
||||
amountState = amountStateConverter.convert(
|
||||
AmountParameters(
|
||||
title = title,
|
||||
value = "",
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -148,7 +148,7 @@ internal class SetButtonsStateTransformer(
|
|||
StakingStep.Validators,
|
||||
StakingStep.RestakeValidator,
|
||||
-> clickIntents.onNextClick()
|
||||
StakingStep.Amount -> clickIntents.onEnterClick()
|
||||
StakingStep.Amount -> clickIntents.onAmountEnterClick()
|
||||
StakingStep.Confirmation -> onConfirmationClick()
|
||||
StakingStep.RewardsValidators -> Unit
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ internal object SetConfirmationStateEmptyTransformer : Transformer<StakingUiStat
|
|||
actionType = StakingActionCommonType.Enter,
|
||||
validatorState = StakingStates.ValidatorState.Empty(),
|
||||
confirmationState = StakingStates.ConfirmationState.Empty(),
|
||||
balanceState = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ 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.isComposePendingActions
|
||||
import com.tangem.features.staking.impl.presentation.state.utils.isCompositePendingActions
|
||||
import com.tangem.features.staking.impl.presentation.state.utils.isTronStakedBalance
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
@ -16,29 +16,32 @@ import java.math.BigDecimal
|
|||
|
||||
internal class SetConfirmationStateInitTransformer(
|
||||
private val isEnter: Boolean,
|
||||
private val isExplicitExit: Boolean,
|
||||
private val balanceState: BalanceState?,
|
||||
private val stakingApproval: StakingApproval,
|
||||
private val stakingAllowance: BigDecimal,
|
||||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val pendingActions: ImmutableList<PendingAction>? = null,
|
||||
private val pendingAction: PendingAction? = pendingActions?.firstOrNull(),
|
||||
|
||||
) : Transformer<StakingUiState> {
|
||||
|
||||
private val networkId
|
||||
get() = cryptoCurrencyStatus.currency.network.id.value
|
||||
|
||||
private val isComposePendingActions
|
||||
get() = isComposePendingActions(networkId, pendingActions)
|
||||
get() = isCompositePendingActions(networkId, pendingActions)
|
||||
|
||||
private val isTronStakedBalance
|
||||
get() = isTronStakedBalance(networkId, pendingAction)
|
||||
|
||||
private val isExit: Boolean
|
||||
private val isImplicitExit: Boolean
|
||||
get() = pendingAction == null && pendingActions?.isEmpty() == true || isTronStakedBalance
|
||||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
val actionType = when {
|
||||
isEnter -> StakingActionCommonType.Enter
|
||||
isExit -> StakingActionCommonType.Exit
|
||||
isImplicitExit || isExplicitExit -> StakingActionCommonType.Exit
|
||||
else -> when (pendingAction?.type) {
|
||||
StakingActionType.STAKE -> StakingActionCommonType.Enter
|
||||
StakingActionType.UNSTAKE -> StakingActionCommonType.Exit
|
||||
|
|
@ -54,6 +57,7 @@ internal class SetConfirmationStateInitTransformer(
|
|||
|
||||
return prevState.copy(
|
||||
actionType = actionType,
|
||||
balanceState = balanceState,
|
||||
confirmationState = StakingStates.ConfirmationState.Data(
|
||||
isPrimaryButtonEnabled = false,
|
||||
innerState = InnerConfirmationStakingState.ASSENT,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@ package com.tangem.features.staking.impl.presentation.state.transformers
|
|||
|
||||
import com.tangem.common.extensions.remove
|
||||
import com.tangem.common.ui.amountScreen.converters.AmountStateConverter
|
||||
import com.tangem.common.ui.amountScreen.models.AmountParameters
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.models.MaxEnterAmount
|
||||
import com.tangem.core.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
|
||||
import com.tangem.core.ui.components.list.RoundedListWithDividersItemData
|
||||
import com.tangem.core.ui.extensions.*
|
||||
|
|
@ -39,6 +41,7 @@ internal class SetInitialDataStateTransformer(
|
|||
private val userWalletProvider: Provider<UserWallet>,
|
||||
private val appCurrencyProvider: Provider<AppCurrency>,
|
||||
private val balancesToShowProvider: Provider<List<BalanceItem>>,
|
||||
private val maxEnterAmountProvider: Provider<MaxEnterAmount>,
|
||||
) : Transformer<StakingUiState> {
|
||||
|
||||
private val iconStateConverter by lazy(::CryptoCurrencyToIconStateConverter)
|
||||
|
|
@ -48,8 +51,8 @@ internal class SetInitialDataStateTransformer(
|
|||
clickIntents = clickIntents,
|
||||
cryptoCurrencyStatusProvider = cryptoCurrencyStatusProvider,
|
||||
appCurrencyProvider = appCurrencyProvider,
|
||||
userWalletProvider = userWalletProvider,
|
||||
iconStateConverter = iconStateConverter,
|
||||
maxEnterAmountProvider = maxEnterAmountProvider,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -72,6 +75,7 @@ internal class SetInitialDataStateTransformer(
|
|||
title = TextReference.EMPTY,
|
||||
cryptoCurrencyName = cryptoCurrency.name,
|
||||
cryptoCurrencySymbol = cryptoCurrency.symbol,
|
||||
cryptoCurrencyNetworkId = cryptoCurrency.network.id.value,
|
||||
clickIntents = clickIntents,
|
||||
currentStep = StakingStep.InitialInfo,
|
||||
initialInfoState = createInitialInfoState(),
|
||||
|
|
@ -207,7 +211,12 @@ internal class SetInitialDataStateTransformer(
|
|||
}
|
||||
|
||||
private fun createInitialAmountState(): AmountState {
|
||||
return amountStateConverter.convert("")
|
||||
return amountStateConverter.convert(
|
||||
AmountParameters(
|
||||
title = stringReference(userWalletProvider().name),
|
||||
value = "",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun getAprRange(validators: List<Yield.Validator>): TextReference {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers.amount
|
||||
|
||||
import com.tangem.common.ui.amountScreen.converters.MaxEnterAmountConverter
|
||||
import com.tangem.common.ui.amountScreen.converters.field.AmountFieldChangeTransformer
|
||||
import com.tangem.common.ui.amountScreen.models.MaxEnterAmount
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
|
@ -12,11 +15,21 @@ internal class AmountChangeStateTransformer(
|
|||
private val yield: Yield,
|
||||
) : Transformer<StakingUiState> {
|
||||
|
||||
private val maxEnterAmountConverter = MaxEnterAmountConverter()
|
||||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
val updatedAmountState = AmountFieldChangeTransformer(
|
||||
cryptoCurrencyStatus,
|
||||
value,
|
||||
).transform(prevState.amountState)
|
||||
val actionType = prevState.actionType
|
||||
val maxEnterAmount = if (actionType == StakingActionCommonType.Exit) {
|
||||
MaxEnterAmount(
|
||||
amount = prevState.balanceState?.cryptoAmount,
|
||||
fiatAmount = prevState.balanceState?.fiatAmount,
|
||||
fiatRate = cryptoCurrencyStatus.value.fiatRate,
|
||||
)
|
||||
} else {
|
||||
maxEnterAmountConverter.convert(cryptoCurrencyStatus)
|
||||
}
|
||||
|
||||
val updatedAmountState = AmountFieldChangeTransformer(maxEnterAmount, value).transform(prevState.amountState)
|
||||
|
||||
return prevState.copy(
|
||||
amountState = AmountRequirementStateTransformer(
|
||||
|
|
|
|||
|
|
@ -1,18 +1,35 @@
|
|||
package com.tangem.features.staking.impl.presentation.state.transformers.amount
|
||||
|
||||
import com.tangem.common.ui.amountScreen.converters.field.AmountFieldMaxAmountTransformer
|
||||
import com.tangem.common.ui.amountScreen.converters.MaxEnterAmountConverter
|
||||
import com.tangem.common.ui.amountScreen.converters.field.AmountFieldSetMaxAmountTransformer
|
||||
import com.tangem.common.ui.amountScreen.models.MaxEnterAmount
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.staking.impl.presentation.state.StakingUiState
|
||||
import com.tangem.utils.transformer.Transformer
|
||||
|
||||
internal class AmountMaxValueStateTransformer(
|
||||
private val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
private val actionType: StakingActionCommonType,
|
||||
private val yield: Yield,
|
||||
) : Transformer<StakingUiState> {
|
||||
|
||||
private val maxEnterAmountConverter = MaxEnterAmountConverter()
|
||||
|
||||
override fun transform(prevState: StakingUiState): StakingUiState {
|
||||
val updatedAmountState = AmountFieldMaxAmountTransformer(cryptoCurrencyStatus).transform(prevState.amountState)
|
||||
val maxEnterAmount = if (actionType == StakingActionCommonType.Exit) {
|
||||
MaxEnterAmount(
|
||||
amount = prevState.balanceState?.cryptoAmount,
|
||||
fiatAmount = prevState.balanceState?.fiatAmount,
|
||||
fiatRate = cryptoCurrencyStatus.value.fiatRate,
|
||||
)
|
||||
} else {
|
||||
maxEnterAmountConverter.convert(cryptoCurrencyStatus)
|
||||
}
|
||||
|
||||
val updatedAmountState = AmountFieldSetMaxAmountTransformer(maxEnterAmount)
|
||||
.transform(prevState.amountState)
|
||||
return prevState.copy(
|
||||
amountState = AmountRequirementStateTransformer(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
|
|
|
|||
|
|
@ -61,10 +61,17 @@ internal class AmountRequirementStateTransformer(
|
|||
},
|
||||
),
|
||||
)
|
||||
isIntegerOnlyError -> resourceReference(
|
||||
R.string.staking_amount_tron_integer_error,
|
||||
wrappedList(value),
|
||||
)
|
||||
isIntegerOnlyError -> when (actionType) {
|
||||
StakingActionCommonType.Enter -> resourceReference(
|
||||
R.string.staking_amount_tron_integer_error,
|
||||
wrappedList(value),
|
||||
)
|
||||
StakingActionCommonType.Exit -> resourceReference(
|
||||
R.string.staking_amount_tron_integer_error_unstaking,
|
||||
wrappedList(value),
|
||||
)
|
||||
else -> TODO()
|
||||
}
|
||||
else -> TextReference.EMPTY
|
||||
}
|
||||
val isError = amountState.amountTextField.isError || isRequirementError
|
||||
|
|
@ -101,12 +108,12 @@ internal class AmountRequirementStateTransformer(
|
|||
private fun isIntegerOnlyError(amountState: AmountState.Data, actionType: StakingActionCommonType): Boolean {
|
||||
val cryptoAmountValue = amountState.amountTextField.cryptoAmount.value ?: return false
|
||||
|
||||
val isEnter = actionType == StakingActionCommonType.Enter
|
||||
val isEnterOrExit = actionType == StakingActionCommonType.Enter || actionType == StakingActionCommonType.Exit
|
||||
val isTron = isTron(cryptoCurrencyStatus.currency.network.id.value)
|
||||
|
||||
val isIntegerOnly = cryptoAmountValue.isZero() || cryptoAmountValue.remainder(BigDecimal.ONE).isZero()
|
||||
|
||||
return isEnter && isTron && !isIntegerOnly
|
||||
return isEnterOrExit && isTron && !isIntegerOnly
|
||||
}
|
||||
|
||||
data class Data(
|
||||
|
|
|
|||
|
|
@ -35,12 +35,12 @@ internal fun StakingActionType?.getPendingActionTitle(): TextReference = when (t
|
|||
|
||||
internal fun isSingleAction(networkId: String, activeStake: BalanceState): Boolean {
|
||||
val isSingleAction = activeStake.pendingActions.size <= 1 // Either single or none pending actions
|
||||
val isComposePendingActions = isComposePendingActions(networkId, activeStake.pendingActions)
|
||||
val isCompositePendingActions = isCompositePendingActions(networkId, activeStake.pendingActions)
|
||||
val isBscRestake = isBSC(networkId) && activeStake.pendingActions.any {
|
||||
it.type == StakingActionType.RESTAKE
|
||||
}
|
||||
|
||||
return isSingleAction && !isBscRestake || isComposePendingActions
|
||||
return isSingleAction && !isBscRestake || isCompositePendingActions
|
||||
}
|
||||
|
||||
internal fun withStubUnstakeAction(networkId: String, activeStake: BalanceState) = if (isBSC(networkId)) {
|
||||
|
|
@ -59,7 +59,7 @@ internal fun isTronStakedBalance(networkId: String, pendingAction: PendingAction
|
|||
return isTron(networkId) && pendingAction?.type == StakingActionType.REVOTE
|
||||
}
|
||||
|
||||
internal fun isComposePendingActions(networkId: String, pendingActions: ImmutableList<PendingAction>?): Boolean {
|
||||
internal fun isCompositePendingActions(networkId: String, pendingActions: ImmutableList<PendingAction>?): Boolean {
|
||||
return when {
|
||||
isSolana(networkId) -> pendingActions?.any { it.type == StakingActionType.WITHDRAW } == true
|
||||
else -> false
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ internal fun StakingClaimRewardsValidatorContent(
|
|||
)
|
||||
},
|
||||
),
|
||||
infoTitle = item.fiatAmount,
|
||||
infoSubtitle = item.cryptoAmount,
|
||||
infoTitle = item.formattedFiatAmount,
|
||||
infoSubtitle = item.formattedCryptoAmount,
|
||||
imageUrl = item.validator?.image.orEmpty(),
|
||||
onImageError = { ValidatorImagePlaceholder() },
|
||||
modifier = modifier
|
||||
|
|
|
|||
|
|
@ -270,8 +270,8 @@ private fun ActiveStakingBlock(
|
|||
InputRowImageInfo(
|
||||
subtitle = balance.title,
|
||||
caption = balance.subtitle ?: balance.getAprText(),
|
||||
infoTitle = balance.fiatAmount.orMaskWithStars(isBalanceHidden),
|
||||
infoSubtitle = balance.cryptoAmount.orMaskWithStars(isBalanceHidden),
|
||||
infoTitle = balance.formattedFiatAmount.orMaskWithStars(isBalanceHidden),
|
||||
infoSubtitle = balance.formattedCryptoAmount.orMaskWithStars(isBalanceHidden),
|
||||
imageUrl = balance.getImage(),
|
||||
iconRes = icon,
|
||||
iconTint = iconTint,
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ internal interface StakingClickIntents : AmountScreenClickIntents {
|
|||
|
||||
fun onInfoClick(infoType: InfoType)
|
||||
|
||||
fun onEnterClick()
|
||||
fun onAmountEnterClick()
|
||||
|
||||
fun getFee()
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import com.tangem.common.routing.AppRoute
|
|||
import com.tangem.common.routing.bundle.unbundle
|
||||
import com.tangem.common.ui.amountScreen.converters.AmountReduceByTransformer
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
import com.tangem.common.ui.amountScreen.models.MaxEnterAmount
|
||||
import com.tangem.common.ui.bottomsheet.permission.state.ApproveType
|
||||
import com.tangem.common.ui.bottomsheet.permission.state.GiveTxPermissionBottomSheetConfig
|
||||
import com.tangem.common.ui.notifications.NotificationUM
|
||||
|
|
@ -31,10 +32,6 @@ import com.tangem.domain.staking.InvalidatePendingTransactionsUseCase
|
|||
import com.tangem.domain.staking.IsAnyTokenStakedUseCase
|
||||
import com.tangem.domain.staking.IsApproveNeededUseCase
|
||||
import com.tangem.domain.staking.model.StakingApproval
|
||||
import com.tangem.domain.staking.model.stakekit.BalanceItem
|
||||
import com.tangem.domain.staking.model.stakekit.PendingAction
|
||||
import com.tangem.domain.staking.model.stakekit.Yield
|
||||
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
||||
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
|
||||
|
|
@ -52,6 +49,7 @@ import com.tangem.domain.wallets.models.UserWalletId
|
|||
import com.tangem.domain.wallets.usecase.GetUserWalletUseCase
|
||||
import com.tangem.domain.staking.analytics.StakeScreenSource
|
||||
import com.tangem.domain.staking.analytics.StakingAnalyticsEvent
|
||||
import com.tangem.domain.staking.model.stakekit.*
|
||||
import com.tangem.features.staking.impl.analytics.StakingParamsInterceptor
|
||||
import com.tangem.features.staking.impl.analytics.utils.StakingAnalyticSender
|
||||
import com.tangem.features.staking.impl.navigation.InnerStakingRouter
|
||||
|
|
@ -156,6 +154,14 @@ internal class StakingViewModel @Inject constructor(
|
|||
).getOrElse { emptyList() }
|
||||
}
|
||||
|
||||
private val maxEnterAmount: MaxEnterAmount
|
||||
get() =
|
||||
MaxEnterAmount(
|
||||
amount = uiState.value.balanceState?.cryptoAmount,
|
||||
fiatAmount = uiState.value.balanceState?.fiatAmount,
|
||||
fiatRate = cryptoCurrencyStatus.value.fiatRate,
|
||||
)
|
||||
|
||||
private var isInitialInfoAnalyticSent: Boolean = false
|
||||
|
||||
private val balanceUpdater by lazy(LazyThreadSafetyMode.NONE) {
|
||||
|
|
@ -227,6 +233,18 @@ internal class StakingViewModel @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onNextClick(balanceState: BalanceState?) {
|
||||
if (value.currentStep == StakingStep.InitialInfo && balanceState == null) {
|
||||
stateController.update(
|
||||
SetConfirmationStateInitTransformer(
|
||||
isEnter = true,
|
||||
isExplicitExit = false,
|
||||
balanceState = null,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
stakingApproval = stakingApproval,
|
||||
stakingAllowance = stakingAllowance,
|
||||
),
|
||||
)
|
||||
}
|
||||
stakingStateRouter.onNextClick()
|
||||
}
|
||||
|
||||
|
|
@ -350,24 +368,20 @@ internal class StakingViewModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
override fun onEnterClick() {
|
||||
override fun onAmountEnterClick() {
|
||||
if (yield.preferredValidators.isEmpty()) {
|
||||
stateController.updateEvent(
|
||||
StakingEvent.ShowAlert(StakingAlertUM.NoAvailableValidators),
|
||||
)
|
||||
} else {
|
||||
stateController.updateAll(
|
||||
SetConfirmationStateInitTransformer(
|
||||
isEnter = true,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
stakingApproval = stakingApproval,
|
||||
stakingAllowance = stakingAllowance,
|
||||
),
|
||||
ValidatorSelectChangeTransformer(
|
||||
selectedValidator = null,
|
||||
yield = yield,
|
||||
),
|
||||
)
|
||||
if (uiState.value.actionType == StakingActionCommonType.Enter) {
|
||||
stateController.updateAll(
|
||||
ValidatorSelectChangeTransformer(
|
||||
selectedValidator = null,
|
||||
yield = yield,
|
||||
),
|
||||
)
|
||||
}
|
||||
onNextClick()
|
||||
}
|
||||
}
|
||||
|
|
@ -382,7 +396,13 @@ internal class StakingViewModel @Inject constructor(
|
|||
|
||||
override fun onMaxValueClick() {
|
||||
analyticsEventHandler.send(StakingAnalyticsEvent.ButtonMax)
|
||||
stateController.update(AmountMaxValueStateTransformer(cryptoCurrencyStatus, yield))
|
||||
stateController.update(
|
||||
AmountMaxValueStateTransformer(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
actionType = uiState.value.actionType,
|
||||
yield = yield,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCurrencyChangeClick(isFiat: Boolean) {
|
||||
|
|
@ -439,23 +459,27 @@ internal class StakingViewModel @Inject constructor(
|
|||
val networkId = cryptoCurrencyStatus.currency.network.id.value
|
||||
if (isSingleAction(networkId, activeStake)) {
|
||||
prepareForConfirmation(
|
||||
balanceType = activeStake.type,
|
||||
pendingActions = activeStake.pendingActions,
|
||||
balanceState = activeStake,
|
||||
validator = activeStake.validator,
|
||||
amountValue = activeStake.cryptoValue,
|
||||
)
|
||||
onNextClick(balanceState = activeStake)
|
||||
onNextClick(activeStake)
|
||||
} else {
|
||||
stateController.update(
|
||||
ShowActionSelectorBottomSheetTransformer(
|
||||
pendingActions = withStubUnstakeAction(networkId, activeStake),
|
||||
onActionSelect = { action ->
|
||||
prepareForConfirmation(
|
||||
balanceType = activeStake.type,
|
||||
pendingAction = action,
|
||||
balanceState = activeStake,
|
||||
validator = activeStake.validator,
|
||||
amountValue = activeStake.cryptoValue,
|
||||
)
|
||||
stateController.update(DismissBottomSheetStateTransformer)
|
||||
onNextClick(balanceState = activeStake)
|
||||
onNextClick(activeStake)
|
||||
},
|
||||
onDismiss = { stateController.update(DismissBottomSheetStateTransformer) },
|
||||
),
|
||||
|
|
@ -889,12 +913,15 @@ internal class StakingViewModel @Inject constructor(
|
|||
userWalletProvider = Provider { userWallet },
|
||||
appCurrencyProvider = Provider { appCurrency },
|
||||
balancesToShowProvider = Provider { balancesToShow },
|
||||
maxEnterAmountProvider = Provider { maxEnterAmount },
|
||||
),
|
||||
SetConfirmationStateEmptyTransformer,
|
||||
)
|
||||
}
|
||||
|
||||
private fun prepareForConfirmation(
|
||||
balanceType: BalanceType,
|
||||
balanceState: BalanceState,
|
||||
pendingActions: ImmutableList<PendingAction> = persistentListOf(),
|
||||
pendingAction: PendingAction? = pendingActions.firstOrNull(),
|
||||
validator: Yield.Validator?,
|
||||
|
|
@ -903,6 +930,8 @@ internal class StakingViewModel @Inject constructor(
|
|||
stateController.updateAll(
|
||||
SetConfirmationStateInitTransformer(
|
||||
isEnter = false,
|
||||
isExplicitExit = balanceType == BalanceType.STAKED,
|
||||
balanceState = balanceState,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
stakingApproval = stakingApproval,
|
||||
pendingActions = pendingActions,
|
||||
|
|
@ -913,6 +942,13 @@ internal class StakingViewModel @Inject constructor(
|
|||
selectedValidator = validator,
|
||||
yield = yield,
|
||||
),
|
||||
SetAmountDataTransformer(
|
||||
clickIntents = this,
|
||||
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
|
||||
userWalletProvider = Provider { userWallet },
|
||||
appCurrencyProvider = Provider { appCurrency },
|
||||
maxEnterAmountProvider = Provider { maxEnterAmount },
|
||||
),
|
||||
AmountChangeStateTransformer(
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
value = amountValue,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue