diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingUiState.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingUiState.kt index cdc4967df2..0613d78e25 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingUiState.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/StakingUiState.kt @@ -118,6 +118,7 @@ internal sealed class StakingStates { val footerText: TextReference, val transactionDoneState: TransactionDoneState, val isApprovalNeeded: Boolean, + val allowance: BigDecimal, val reduceAmountBy: BigDecimal?, ) : ConfirmationState() diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingFeeTransactionLoader.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingFeeTransactionLoader.kt index a56aa88c94..207436cf09 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingFeeTransactionLoader.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/helpers/StakingFeeTransactionLoader.kt @@ -8,7 +8,6 @@ import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.common.extensions.isZero import com.tangem.common.ui.amountScreen.models.AmountState import com.tangem.domain.staking.EstimateGasUseCase -import com.tangem.domain.staking.model.StakingApproval import com.tangem.domain.staking.model.stakekit.PendingAction import com.tangem.domain.staking.model.stakekit.StakingError import com.tangem.domain.staking.model.stakekit.Yield @@ -17,7 +16,6 @@ import com.tangem.domain.staking.model.stakekit.transaction.ActionParams import com.tangem.domain.staking.model.stakekit.transaction.StakingGasEstimate import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.domain.transaction.error.GetFeeError -import com.tangem.domain.transaction.usecase.GetAllowanceUseCase import com.tangem.domain.transaction.usecase.GetFeeUseCase import com.tangem.domain.wallets.models.UserWallet import com.tangem.features.staking.impl.presentation.state.StakingStateController @@ -37,13 +35,11 @@ import java.math.BigDecimal @Suppress("LongParameterList") internal class StakingFeeTransactionLoader @AssistedInject constructor( private val stateController: StakingStateController, - private val getAllowanceUseCase: GetAllowanceUseCase, private val getFeeUseCase: GetFeeUseCase, private val estimateGasUseCase: EstimateGasUseCase, @Assisted private val cryptoCurrencyStatus: CryptoCurrencyStatus, @Assisted private val userWallet: UserWallet, @Assisted private val yield: Yield, - @Assisted private val stakingApproval: StakingApproval, ) { suspend fun getFee( @@ -66,31 +62,16 @@ internal class StakingFeeTransactionLoader @AssistedInject constructor( val validatorAddress = validatorState.chosenValidator.address - val approval = stakingApproval as? StakingApproval.Needed - if (approval != null && state.actionType == StakingActionCommonType.Enter) { - val allowance = getAllowanceUseCase( - userWalletId = userWallet.walletId, - cryptoCurrency = cryptoCurrencyStatus.currency, - spenderAddress = approval.spenderAddress, - ).getOrElse { BigDecimal.ZERO } - - if (allowance < amount) { - getApproveFee( - amount = amount, - validatorAddress = validatorAddress, - onApprovalFee = onApprovalFee, - onApprovalFeeError = onFeeError, - ) - } else { - estimateGas( - pendingAction = pendingAction, - pendingActions = pendingActions, - amount = amount, - validatorAddress = validatorAddress, - onStakingFeeError = onStakingFeeError, - onStakingFee = onStakingFee, - ) - } + val isEnter = state.actionType == StakingActionCommonType.Enter + val isApprovalNeeded = confirmationState.isApprovalNeeded + val isAllowanceNotEnough = confirmationState.allowance < amount + if (isEnter && isApprovalNeeded && isAllowanceNotEnough) { + getApproveFee( + amount = amount, + validatorAddress = validatorAddress, + onApprovalFee = onApprovalFee, + onApprovalFeeError = onFeeError, + ) } else { estimateGas( pendingAction = pendingAction, @@ -234,7 +215,6 @@ internal class StakingFeeTransactionLoader @AssistedInject constructor( cryptoCurrencyStatus: CryptoCurrencyStatus, userWallet: UserWallet, yield: Yield, - stakingApproval: StakingApproval, ): StakingFeeTransactionLoader } } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/previewdata/ConfirmationStatePreviewData.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/previewdata/ConfirmationStatePreviewData.kt index dbcf70f6bb..ac86e7084a 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/previewdata/ConfirmationStatePreviewData.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/previewdata/ConfirmationStatePreviewData.kt @@ -45,6 +45,7 @@ internal object ConfirmationStatePreviewData { transactionDoneState = TransactionDoneState.Empty, pendingAction = null, isApprovalNeeded = false, + allowance = BigDecimal.ZERO, reduceAmountBy = null, pendingActions = null, ) diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetButtonsStateTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetButtonsStateTransformer.kt index c2761a0713..c2fcce7f80 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetButtonsStateTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetButtonsStateTransformer.kt @@ -1,5 +1,6 @@ package com.tangem.features.staking.impl.presentation.state.transformers +import com.tangem.common.ui.amountScreen.models.AmountState import com.tangem.common.ui.navigationButtons.NavigationButton import com.tangem.common.ui.navigationButtons.NavigationButtonsState import com.tangem.core.navigation.url.UrlOpener @@ -9,6 +10,7 @@ import com.tangem.core.ui.extensions.resourceReference import com.tangem.domain.staking.model.stakekit.action.StakingActionCommonType import com.tangem.features.staking.impl.presentation.state.* import com.tangem.features.staking.impl.presentation.state.utils.getPendingActionTitle +import com.tangem.utils.extensions.orZero import com.tangem.utils.transformer.Transformer import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf @@ -116,13 +118,16 @@ internal class SetButtonsStateTransformer( } private fun StakingUiState.getConfirmationButtonText(): TextReference { - return if (confirmationState is StakingStates.ConfirmationState.Data) { + val confirmationState = confirmationState as? StakingStates.ConfirmationState.Data + val amountState = amountState as? AmountState.Data + return if (confirmationState != null && amountState != null) { if (confirmationState.innerState == InnerConfirmationStakingState.COMPLETED) { resourceReference(R.string.common_close) } else { when (actionType) { StakingActionCommonType.Enter -> { - if (confirmationState.isApprovalNeeded) { + val amount = amountState.amountTextField.cryptoAmount.value.orZero() + if (confirmationState.isApprovalNeeded && confirmationState.allowance < amount) { resourceReference(R.string.give_permission_title) } else { resourceReference(R.string.common_stake) diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateInitTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateInitTransformer.kt index 8387933908..e638ea2e20 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateInitTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateInitTransformer.kt @@ -12,10 +12,12 @@ import com.tangem.features.staking.impl.presentation.state.utils.isTronStakedBal import com.tangem.utils.transformer.Transformer import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf +import java.math.BigDecimal internal class SetConfirmationStateInitTransformer( private val isEnter: Boolean, private val stakingApproval: StakingApproval, + private val stakingAllowance: BigDecimal, private val cryptoCurrencyStatus: CryptoCurrencyStatus, private val pendingActions: ImmutableList? = null, private val pendingAction: PendingAction? = pendingActions?.firstOrNull(), @@ -60,6 +62,7 @@ internal class SetConfirmationStateInitTransformer( footerText = TextReference.EMPTY, transactionDoneState = TransactionDoneState.Empty, isApprovalNeeded = stakingApproval is StakingApproval.Needed, + allowance = stakingAllowance, reduceAmountBy = null, pendingAction = pendingAction, pendingActions = pendingActions.takeIf { isComposePendingActions }, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/confirmation/SetUpdatedAllowanceTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/confirmation/SetUpdatedAllowanceTransformer.kt new file mode 100644 index 0000000000..5d8677de4f --- /dev/null +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/confirmation/SetUpdatedAllowanceTransformer.kt @@ -0,0 +1,17 @@ +package com.tangem.features.staking.impl.presentation.state.transformers.confirmation + +import com.tangem.features.staking.impl.presentation.state.StakingStates +import com.tangem.features.staking.impl.presentation.state.StakingUiState +import com.tangem.utils.transformer.Transformer +import java.math.BigDecimal + +internal class SetUpdatedAllowanceTransformer( + private val allowance: BigDecimal, +) : Transformer { + override fun transform(prevState: StakingUiState): StakingUiState { + val confirmationState = prevState.confirmationState as? StakingStates.ConfirmationState.Data + return prevState.copy( + confirmationState = confirmationState?.copy(allowance = allowance) ?: prevState.confirmationState, + ) + } +} \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt index 159ba0ac57..998261a393 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/viewmodel/StakingViewModel.kt @@ -26,7 +26,10 @@ import com.tangem.domain.feedback.SaveBlockchainErrorUseCase import com.tangem.domain.feedback.SendFeedbackEmailUseCase import com.tangem.domain.feedback.models.BlockchainErrorInfo import com.tangem.domain.feedback.models.FeedbackEmailType -import com.tangem.domain.staking.* +import com.tangem.domain.staking.GetActionsUseCase +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 @@ -63,6 +66,7 @@ import com.tangem.features.staking.impl.presentation.state.helpers.StakingTransa import com.tangem.features.staking.impl.presentation.state.transformers.* import com.tangem.features.staking.impl.presentation.state.transformers.amount.* import com.tangem.features.staking.impl.presentation.state.transformers.approval.* +import com.tangem.features.staking.impl.presentation.state.transformers.confirmation.SetUpdatedAllowanceTransformer import com.tangem.features.staking.impl.presentation.state.transformers.notifications.AddStakingNotificationsTransformer import com.tangem.features.staking.impl.presentation.state.transformers.notifications.DismissStakingNotificationsStateTransformer import com.tangem.features.staking.impl.presentation.state.transformers.validator.ValidatorSelectChangeTransformer @@ -167,7 +171,6 @@ internal class StakingViewModel @Inject constructor( cryptoCurrencyStatus = cryptoCurrencyStatus, userWallet = userWallet, yield = yield, - stakingApproval = stakingApproval, ) } @@ -192,6 +195,7 @@ internal class StakingViewModel @Inject constructor( ) private var stakingApproval: StakingApproval = StakingApproval.Empty + private var stakingAllowance: BigDecimal = BigDecimal.ZERO private var isAmountSubtractAvailable: Boolean = false private var isAnyTokenStaked: Boolean = false private val allowanceTaskScheduler = SingleTaskScheduler() @@ -357,6 +361,7 @@ internal class StakingViewModel @Inject constructor( isEnter = true, cryptoCurrencyStatus = cryptoCurrencyStatus, stakingApproval = stakingApproval, + stakingAllowance = stakingAllowance, ), ValidatorSelectChangeTransformer( selectedValidator = null, @@ -651,9 +656,11 @@ internal class StakingViewModel @Inject constructor( } }, onSuccess = { allowance -> + stakingAllowance = allowance val amount = (value.amountState as? AmountState.Data)?.amountTextField?.cryptoAmount?.value ?: error("No amount provided") if (allowance >= amount) { + stateController.update(SetUpdatedAllowanceTransformer(allowance)) getFee() allowanceTaskScheduler.cancelTask() } @@ -730,8 +737,22 @@ internal class StakingViewModel @Inject constructor( this.stakingStateRouter = stateRouter } - private fun setupApprovalNeeded() { - stakingApproval = isApproveNeededUseCase(cryptoCurrencyStatus.currency).getOrElse { StakingApproval.Empty } + private suspend fun setupApprovalNeeded() { + stakingApproval = isApproveNeededUseCase(cryptoCurrencyStatus.currency).fold( + ifRight = { approval -> + if (approval is StakingApproval.Needed) { + stakingAllowance = getAllowanceUseCase( + userWalletId = userWalletId, + cryptoCurrency = cryptoCurrencyStatus.currency, + spenderAddress = approval.spenderAddress, + ).getOrElse { BigDecimal.ZERO } + } + approval + }, + ifLeft = { + StakingApproval.Empty + }, + ) } private suspend fun setupIsAnyTokenStaked() { @@ -886,6 +907,7 @@ internal class StakingViewModel @Inject constructor( stakingApproval = stakingApproval, pendingActions = pendingActions, pendingAction = pendingAction, + stakingAllowance = stakingAllowance, ), ValidatorSelectChangeTransformer( selectedValidator = validator,