Updated on 2026-08-14

This commit is contained in:
Tangem 2026-06-26 17:52:48 +01:00
parent 28bc842e91
commit 535f2ce1b3
8 changed files with 201 additions and 95 deletions

View file

@ -822,8 +822,7 @@ internal class SwapModel @Inject constructor(
transferState = swapState,
uiStateHolder = uiState,
feePaidCryptoCurrencyStatus = feePaidCryptoCurrency,
fee = selectedFee,
feeError = feeSelectorRepository.state.value as? FeeSelectorUM.Error,
feeSelectorUM = feeSelectorRepository.state.value,
)
when {
uiState.successState != null -> Unit
@ -871,7 +870,7 @@ internal class SwapModel @Inject constructor(
feePaidCryptoCurrencyStatus = feePaidCryptoCurrencyStatus ?: dataState.feePaidCryptoCurrency,
fee = fee,
isTangemPayWithdrawal = isTangemPayWithdrawal(),
feeError = feeSelectorRepository.state.value as? FeeSelectorUM.Error,
feeSelectorUM = feeSelectorRepository.state.value,
)
}
}

View file

@ -1,8 +1,8 @@
package com.tangem.feature.swap.ui.transfer
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.common.ui.notifications.NotificationsFactory.addDustWarningNotification
import com.tangem.common.ui.notifications.NotificationsFactory.addExceedBalanceNotification
import com.tangem.common.ui.notifications.NotificationsFactory.addExceedsBalanceNotification
import com.tangem.common.ui.notifications.NotificationsFactory.addExistentialWarningNotification
import com.tangem.common.ui.notifications.NotificationsFactory.addFeeCoverageNotification
@ -18,6 +18,8 @@ import com.tangem.feature.swap.domain.models.SwapAmount
import com.tangem.feature.swap.domain.models.ui.SwapState
import com.tangem.feature.swap.models.UiActions
import com.tangem.feature.swap.models.states.SwapNotificationUM
import com.tangem.features.send.api.entity.FeeSelectorUM
import com.tangem.features.send.api.subcomponents.feeSelector.utils.FeeCalculationUtils
import com.tangem.lib.crypto.BlockchainUtils
import com.tangem.lib.crypto.BlockchainUtils.getTezosThreshold
import com.tangem.lib.crypto.BlockchainUtils.isTezos
@ -33,22 +35,30 @@ internal class SwapTransferNotificationsFactory @Inject constructor() {
@Suppress("LongParameterList")
fun getNotifications(
transferState: SwapState.Transfer,
feeSelectorUM: FeeSelectorUM?,
feeCryptoCurrencyStatus: CryptoCurrencyStatus?,
fee: Fee?,
actions: UiActions,
getFeeError: GetFeeError?,
): ImmutableList<NotificationUM> {
// The fee selector exposes a single sealed state; narrow it here so call sites pass the raw
// FeeSelectorUM and this factory owns the Content/Error/Loading discrimination.
val feeContent = feeSelectorUM
val getFeeError = (feeSelectorUM as? FeeSelectorUM.Error)?.error
return buildList {
maybeAddRentExemptionError(transferState)
maybeAddDomainWarnings(
state = transferState,
feeCryptoCurrencyStatus = feeCryptoCurrencyStatus,
fee = fee,
feeSelectorUM = feeContent,
onReduceByAmount = actions.onReduceByAmount,
onReduceToAmount = actions.onReduceToAmount,
)
maybeAddNeedReserveToCreateAccountWarning(transferState)
maybeAddExceedsBalanceNotification(transferState, onBuyClick = actions.openTokenDetailsScreen)
maybeAddExceedsBalanceNotifications(
transferState = transferState,
feeSelectorUM = feeContent,
onBuyClick = actions.openTokenDetailsScreen,
)
maybeAddTooHighOrTooLowNotification(feeContent)
addTronNetworkFeesNotification(
cryptoCurrencyStatus = transferState.fromTokenInfo.swapCurrencyStatus.status,
transferState = transferState,
@ -71,13 +81,14 @@ internal class SwapTransferNotificationsFactory @Inject constructor() {
private fun MutableList<NotificationUM>.maybeAddDomainWarnings(
state: SwapState.Transfer,
feeCryptoCurrencyStatus: CryptoCurrencyStatus?,
fee: Fee?,
feeSelectorUM: FeeSelectorUM?,
onReduceByAmount: (SwapAmount, BigDecimal) -> Unit,
onReduceToAmount: (SwapAmount) -> Unit,
) {
val swapCurrencyStatus = state.fromTokenInfo.swapCurrencyStatus
val amount = state.fromTokenInfo.tokenAmount
val balance = swapCurrencyStatus.status.value.amount ?: BigDecimal.ZERO
val fee = (feeSelectorUM as? FeeSelectorUM.Content)?.selectedFeeItem?.fee
val feeValue = fee?.amount?.value.orZero()
val isCardano = BlockchainUtils.isCardano(swapCurrencyStatus.currency.network.rawId)
addExistentialWarningNotification(
@ -191,8 +202,9 @@ internal class SwapTransferNotificationsFactory @Inject constructor() {
}
}
private fun MutableList<NotificationUM>.maybeAddExceedsBalanceNotification(
private fun MutableList<NotificationUM>.maybeAddExceedsBalanceNotifications(
transferState: SwapState.Transfer,
feeSelectorUM: FeeSelectorUM?,
onBuyClick: (CryptoCurrency) -> Unit,
) {
val cryptoCurrencyStatus = transferState.fromTokenInfo.swapCurrencyStatus.status
@ -206,6 +218,27 @@ internal class SwapTransferNotificationsFactory @Inject constructor() {
onAnalyticsEvent = {},
onResetAnalyticsEvent = {},
)
val feeAmount = (feeSelectorUM as? FeeSelectorUM.Content)?.selectedFeeItem?.fee?.amount?.value
if (feeAmount != null) {
addExceedBalanceNotification(
feeAmount = feeAmount,
sendingAmount = transferState.sendingAmount,
isSubtractionAvailable = transferState.isAmountSubtractAvailable,
cryptoCurrencyStatus = transferState.fromTokenInfo.swapCurrencyStatus.status,
)
}
}
@Suppress("CanBeNonNullable")
private fun MutableList<NotificationUM>.maybeAddTooHighOrTooLowNotification(feeSelectorUM: FeeSelectorUM?) {
val content = feeSelectorUM as? FeeSelectorUM.Content ?: return
val (isFeeTooHigh, diff) = FeeCalculationUtils.checkIfCustomFeeTooHigh(feeSelectorUM = content)
if (isFeeTooHigh) {
add(NotificationUM.Warning.TooHigh(diff))
}
if (FeeCalculationUtils.checkIfCustomFeeTooLow(feeSelectorUM = content)) {
add(NotificationUM.Warning.FeeTooLow)
}
}
private fun MutableList<NotificationUM>.addTronNetworkFeesNotification(

View file

@ -59,8 +59,7 @@ internal class SwapTransferStateBuilder @Inject constructor(
transferState: SwapState.Transfer,
uiStateHolder: SwapStateHolder,
feePaidCryptoCurrencyStatus: CryptoCurrencyStatus?,
fee: Fee?,
feeError: FeeSelectorUM.Error?,
feeSelectorUM: FeeSelectorUM?,
): SwapStateHolder {
val fromTokenSwapInfo = transferState.fromTokenInfo
val isInsufficientBalance = transferState.isInsufficientBalance
@ -68,10 +67,9 @@ internal class SwapTransferStateBuilder @Inject constructor(
val prevAmountField = prevSendCard?.amountField
val notifications = notificationsFactory.getNotifications(
transferState = transferState,
feeSelectorUM = feeSelectorUM,
feeCryptoCurrencyStatus = feePaidCryptoCurrencyStatus,
fee = fee,
actions = actions,
getFeeError = feeError?.error,
)
return uiStateHolder.copy(
sendCardData = createSendSwapCardState(
@ -344,14 +342,13 @@ internal class SwapTransferStateBuilder @Inject constructor(
feePaidCryptoCurrencyStatus: CryptoCurrencyStatus?,
fee: Fee?,
isTangemPayWithdrawal: Boolean,
feeError: FeeSelectorUM.Error?,
feeSelectorUM: FeeSelectorUM?,
): SwapStateHolder {
val notifications = notificationsFactory.getNotifications(
transferState = transferState,
feeCryptoCurrencyStatus = feePaidCryptoCurrencyStatus,
fee = fee,
feeSelectorUM = feeSelectorUM,
actions = actions,
getFeeError = feeError?.error,
)
return uiStateHolder.copy(
notifications = notifications,