Updated on 2026-08-14

This commit is contained in:
Tangem 2026-07-21 12:37:44 +04:00
parent 64b094c8e7
commit e6faa0a588
5 changed files with 123 additions and 1 deletions

View file

@ -842,7 +842,8 @@ internal class SwapModel @Inject constructor(
fromTokenAmount: String,
) {
val feePaidCryptoCurrency = dataState.feePaidCryptoCurrency
val selectedFee = getSelectedSwapFee()?.fee
val selectedSwapFee = getSelectedSwapFee()
val selectedFee = selectedSwapFee?.fee
val swapState = swapTransferInteractor.updateTransfer(
fromSwapCurrencyStatus = fromSwapCurrencyStatus,
toSwapCurrencyStatus = toSwapCurrencyStatus,
@ -864,6 +865,7 @@ internal class SwapModel @Inject constructor(
uiStateHolder = uiState,
feePaidCryptoCurrencyStatus = feePaidCryptoCurrency,
feeSelectorUM = feeSelectorRepository.state.value,
isHighNetworkFee = isHighNetworkFee(selectedSwapFee),
)
when {
uiState.successState != null -> Unit
@ -912,6 +914,7 @@ internal class SwapModel @Inject constructor(
fee = fee,
isTangemPayWithdrawal = isTangemPayWithdrawal(),
feeSelectorUM = feeSelectorRepository.state.value,
isHighNetworkFee = isHighNetworkFee(getSelectedSwapFee()),
)
}
}

View file

@ -40,6 +40,7 @@ internal class SwapTransferNotificationsFactory @Inject constructor() {
feeSelectorUM: FeeSelectorUM?,
feeCryptoCurrencyStatus: CryptoCurrencyStatus?,
actions: UiActions,
isHighNetworkFee: Boolean = false,
): 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.
@ -71,9 +72,16 @@ internal class SwapTransferNotificationsFactory @Inject constructor() {
feeError = getFeeError,
actions = actions,
)
maybeAddHighNetworkFeeWarning(isHighNetworkFee)
}.toPersistentList()
}
private fun MutableList<NotificationUM>.maybeAddHighNetworkFeeWarning(isHighNetworkFee: Boolean) {
if (isHighNetworkFee) {
add(NotificationUM.Warning.HighNetworkFee)
}
}
private fun MutableList<NotificationUM>.maybeAddDomainWarnings(
state: SwapState.Transfer,
feeCryptoCurrencyStatus: CryptoCurrencyStatus?,

View file

@ -60,6 +60,7 @@ internal class SwapTransferStateBuilder @Inject constructor(
uiStateHolder: SwapStateHolder,
feePaidCryptoCurrencyStatus: CryptoCurrencyStatus?,
feeSelectorUM: FeeSelectorUM?,
isHighNetworkFee: Boolean = false,
): SwapStateHolder {
val fromTokenSwapInfo = transferState.fromTokenInfo
val isInsufficientBalance = transferState.isInsufficientBalance
@ -70,6 +71,7 @@ internal class SwapTransferStateBuilder @Inject constructor(
feeSelectorUM = feeSelectorUM,
feeCryptoCurrencyStatus = feePaidCryptoCurrencyStatus,
actions = actions,
isHighNetworkFee = isHighNetworkFee,
)
return uiStateHolder.copy(
sendCardData = createSendSwapCardState(
@ -343,12 +345,14 @@ internal class SwapTransferStateBuilder @Inject constructor(
fee: Fee?,
isTangemPayWithdrawal: Boolean,
feeSelectorUM: FeeSelectorUM?,
isHighNetworkFee: Boolean = false,
): SwapStateHolder {
val notifications = notificationsFactory.getNotifications(
transferState = transferState,
feeCryptoCurrencyStatus = feePaidCryptoCurrencyStatus,
feeSelectorUM = feeSelectorUM,
actions = actions,
isHighNetworkFee = isHighNetworkFee,
)
return uiStateHolder.copy(
notifications = notifications,

View file

@ -56,6 +56,42 @@ internal class SwapTransferNotificationsFactoryTest {
assertThat(result).isEmpty()
}
@Test
fun `GIVEN isHighNetworkFee true WHEN getNotifications THEN HighNetworkFee warning is added`() = runTest {
// Arrange
val transferState = buildTransferState()
// Act
val result = sut.getNotifications(
transferState = transferState,
feeSelectorUM = null,
feeCryptoCurrencyStatus = null,
actions = actions,
isHighNetworkFee = true,
)
// Assert
assertThat(result).contains(NotificationUM.Warning.HighNetworkFee)
}
@Test
fun `GIVEN isHighNetworkFee false WHEN getNotifications THEN HighNetworkFee warning is absent`() = runTest {
// Arrange
val transferState = buildTransferState()
// Act
val result = sut.getNotifications(
transferState = transferState,
feeSelectorUM = null,
feeCryptoCurrencyStatus = null,
actions = actions,
isHighNetworkFee = false,
)
// Assert
assertThat(result).doesNotContain(NotificationUM.Warning.HighNetworkFee)
}
@Test
fun `GIVEN currencyCheck with rentWarning WHEN getNotifications THEN Solana RentInfo is added`() = runTest {
val rentWarning = CryptoCurrencyWarning.Rent(

View file

@ -13,6 +13,7 @@ import com.tangem.common.ui.account.toUM
import com.tangem.common.ui.amountScreen.models.AmountFieldModel
import com.tangem.common.ui.components.currency.icon.converter.CryptoCurrencyToIconStateConverter
import com.tangem.common.ui.navigationButtons.NavigationUM
import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.common.ui.userwallet.ext.walletInterationIcon
import com.tangem.core.ui.extensions.TextReference
import com.tangem.core.ui.extensions.resourceReference
@ -376,6 +377,76 @@ internal class SwapTransferStateBuilderTest {
}
}
@Test
fun `GIVEN high network fee WHEN createTransferState THEN flag is forwarded to notifications factory`() =
runTest {
// Arrange
val transferState = buildTransferState(
fromAmount = BigDecimal("1.5"),
toAmount = BigDecimal("1.5"),
isAccountsMode = false,
)
// Act
sut.createTransferState(
actions = actions,
transferState = transferState,
uiStateHolder = baseStateHolder(),
feePaidCryptoCurrencyStatus = null,
feeSelectorUM = null,
isHighNetworkFee = true,
)
// Assert
coVerify(exactly = 1) {
notificationsFactory.getNotifications(
transferState = transferState,
feeSelectorUM = any(),
feeCryptoCurrencyStatus = null,
actions = any(),
isHighNetworkFee = true,
)
}
}
@Test
fun `GIVEN high network fee warning WHEN updateTransferButtonEnableState THEN swap button stays enabled`() =
runTest {
// Arrange
val transferState = buildTransferState(
fromAmount = BigDecimal("1"),
toAmount = BigDecimal("1"),
isAccountsMode = false,
)
val fee: Fee = mockk(relaxed = true)
coEvery {
notificationsFactory.getNotifications(
transferState = transferState,
feeSelectorUM = any(),
feeCryptoCurrencyStatus = null,
actions = any(),
isHighNetworkFee = true,
)
} returns persistentListOf(NotificationUM.Warning.HighNetworkFee)
// Act
val result = sut.updateTransferButtonEnableState(
dataState = SwapProcessDataState(),
transferState = transferState,
actions = actions,
uiStateHolder = baseStateHolder(),
feePaidCryptoCurrencyStatus = null,
fee = fee,
isTangemPayWithdrawal = false,
feeSelectorUM = null,
isHighNetworkFee = true,
)
// Assert
assertThat(result.notifications).contains(NotificationUM.Warning.HighNetworkFee)
assertThat(result.swapButton.isEnabled).isTrue()
}
@Test
fun `GIVEN fee coverage reduces amount WHEN createTransferState THEN receive card shows reduced sendingAmount`() =
runTest {