diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt index 494dcdd997..88e9a090ad 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/model/StakingModel.kt @@ -3,6 +3,7 @@ package com.tangem.features.staking.impl.presentation.model import androidx.compose.runtime.Stable import arrow.core.getOrElse import com.tangem.blockchain.common.TransactionData +import com.tangem.blockchain.common.transaction.Fee import com.tangem.blockchain.common.transaction.TransactionFee import com.tangem.common.routing.AppRouter import com.tangem.common.ui.amountScreen.converters.AmountReduceByTransformer @@ -397,62 +398,122 @@ internal class StakingModel @Inject constructor( modelScope.launch { stakingAnalyticSender.sendTransactionStakingClickedAnalytics(value) stateController.update(SetConfirmationStateInProgressTransformer()) - transactionSender.send( - StakingTransactionSender.Callbacks( - onConstructSuccess = { constructedTransactions -> - transactionsInProgress.addAll(constructedTransactions) - }, - onConstructError = { error -> - stakingEventFactory.createStakingErrorAlert(error) - stateController.update(SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus)) - }, - onSendSuccess = { txUrl -> - stakingAnalyticSender.sendTransactionStakingAnalytics( - stateController.value, - cryptoCurrencyStatus, - ) - transactionsInProgress.clear() - stateController.update( - SetConfirmationStateCompletedTransformer(txUrl, cryptoCurrencyStatus), - ) - }, - onSendError = { error -> - analyticsEventHandler.send( - StakingAnalyticsEvent.TransactionError( - errorCode = error.getAnalyticsDescription(), - ), - ) - stakingEventFactory.createSendTransactionErrorAlert(error) - stateController.update(SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus)) - }, - onFeeIncreased = { increasedFee, isFeeApproximate -> - stateController.updateAll( - SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus), - SetConfirmationStateAssentTransformer( - appCurrencyProvider = Provider { appCurrency }, - feeCryptoCurrencyStatus = feeCryptoCurrencyStatus, - fee = increasedFee, - isFeeApproximate = isFeeApproximate, - cryptoCurrencyStatus = cryptoCurrencyStatus, - ), - ) - stateController.updateEvent( - StakingEvent.ShowAlert( - StakingAlertUM.FeeIncreased(stateController::dismissAlert), - ), - ) - updateNotifications() - }, - onTransactionExpired = { - stateController.update(SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus)) - getFee() - }, - ), - ) + + if (integration is P2PEthPoolIntegration) { + checkFeeAndSendP2PTransaction() + } else { + sendTransaction() + } }.saveIn(sendTransactionJobHolder) } } + private suspend fun checkFeeAndSendP2PTransaction() { + val confirmationState = value.confirmationState as? StakingStates.ConfirmationState.Data + val currentFeeState = confirmationState?.feeState as? FeeState.Content + val currentFee = currentFeeState?.fee + + var actualFee: Fee? = null + feeLoader.getFee( + onStakingFee = { fee, _ -> + actualFee = fee + }, + onStakingFeeError = { error -> + stakingEventFactory.createStakingErrorAlert(error) + stateController.update(SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus)) + }, + onApprovalFee = { }, + onFeeError = { error -> + stateController.update(SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus)) + updateNotifications(error) + }, + ) + + val newFee = actualFee ?: return + + val currentFeeAmount = when (currentFee) { + is Fee.Common -> currentFee.amount.value ?: BigDecimal.ZERO + is Fee.Ethereum -> currentFee.amount.value ?: BigDecimal.ZERO + else -> BigDecimal.ZERO + } + + val newFeeAmount = when (newFee) { + is Fee.Common -> newFee.amount.value ?: BigDecimal.ZERO + is Fee.Ethereum -> newFee.amount.value ?: BigDecimal.ZERO + else -> BigDecimal.ZERO + } + + if (newFeeAmount > currentFeeAmount) { + stateController.update(SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus)) + stakingEventFactory.createNetworkFeeUpdatedAlert( + onConfirm = { + modelScope.launch { + stateController.update(UpdateConfirmationFeeTransformer(newFee)) + stateController.update(SetConfirmationStateInProgressTransformer()) + sendTransaction() + } + }, + ) + } else { + sendTransaction() + } + } + + private suspend fun sendTransaction() { + transactionSender.send( + StakingTransactionSender.Callbacks( + onConstructSuccess = { constructedTransactions -> + transactionsInProgress.addAll(constructedTransactions) + }, + onConstructError = { error -> + stakingEventFactory.createStakingErrorAlert(error) + stateController.update(SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus)) + }, + onSendSuccess = { txUrl -> + stakingAnalyticSender.sendTransactionStakingAnalytics( + stateController.value, + cryptoCurrencyStatus, + ) + transactionsInProgress.clear() + stateController.update( + SetConfirmationStateCompletedTransformer(txUrl, cryptoCurrencyStatus), + ) + }, + onSendError = { error -> + analyticsEventHandler.send( + StakingAnalyticsEvent.TransactionError( + errorCode = error.getAnalyticsDescription(), + ), + ) + stakingEventFactory.createSendTransactionErrorAlert(error) + stateController.update(SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus)) + }, + onFeeIncreased = { increasedFee, isFeeApproximate -> + stateController.updateAll( + SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus), + SetConfirmationStateAssentTransformer( + appCurrencyProvider = Provider { appCurrency }, + feeCryptoCurrencyStatus = feeCryptoCurrencyStatus, + fee = increasedFee, + isFeeApproximate = isFeeApproximate, + cryptoCurrencyStatus = cryptoCurrencyStatus, + ), + ) + stateController.updateEvent( + StakingEvent.ShowAlert( + StakingAlertUM.FeeIncreased(stateController::dismissAlert), + ), + ) + updateNotifications() + }, + onTransactionExpired = { + stateController.update(SetConfirmationStateResetAssentTransformer(cryptoCurrencyStatus)) + getFee() + }, + ), + ) + } + override fun onPrevClick() { if (value.currentStep == StakingStep.Confirmation) { val confirmationState = value.confirmationState as? StakingStates.ConfirmationState.Data diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingAlertUM.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingAlertUM.kt index af6931c29f..3e757a6adc 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingAlertUM.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingAlertUM.kt @@ -74,4 +74,12 @@ internal sealed class StakingAlertUM : AlertUM { ) override val confirmButtonText: TextReference = resourceReference(id = R.string.common_ok) } + + data class NetworkFeeUpdated( + override val onConfirmClick: () -> Unit, + ) : StakingAlertUM() { + override val title: TextReference = resourceReference(R.string.staking_alert_network_fee_updated_title) + override val message: TextReference = resourceReference(R.string.staking_alert_network_fee_updated_message) + override val confirmButtonText: TextReference = resourceReference(id = R.string.common_ok) + } } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingEventFactory.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingEventFactory.kt index 465bd1c024..4ba7fb1dd9 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingEventFactory.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/events/StakingEventFactory.kt @@ -57,4 +57,13 @@ internal class StakingEventFactory( ), ) } + + fun createNetworkFeeUpdatedAlert(onConfirm: () -> Unit) { + val alert = StakingEvent.ShowAlert( + alert = StakingAlertUM.NetworkFeeUpdated( + onConfirmClick = onConfirm, + ), + ) + stateController.updateEvent(alert) + } } \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/UpdateConfirmationFeeTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/UpdateConfirmationFeeTransformer.kt new file mode 100644 index 0000000000..9c00ba3234 --- /dev/null +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/UpdateConfirmationFeeTransformer.kt @@ -0,0 +1,28 @@ +package com.tangem.features.staking.impl.presentation.state.transformers + +import com.tangem.blockchain.common.transaction.Fee +import com.tangem.features.staking.impl.presentation.state.FeeState +import com.tangem.features.staking.impl.presentation.state.StakingStates +import com.tangem.features.staking.impl.presentation.state.StakingUiState +import com.tangem.utils.transformer.Transformer + +internal class UpdateConfirmationFeeTransformer( + private val newFee: Fee, +) : Transformer { + + override fun transform(prevState: StakingUiState): StakingUiState { + val confirmationState = prevState.confirmationState as? StakingStates.ConfirmationState.Data + ?: return prevState + + val currentFeeState = confirmationState.feeState as? FeeState.Content + ?: return prevState + + val updatedFeeState = currentFeeState.copy(fee = newFee) + + return prevState.copy( + confirmationState = confirmationState.copy( + feeState = updatedFeeState, + ), + ) + } +} \ No newline at end of file