Updated on 2026-08-14

This commit is contained in:
Tangem 2025-03-28 18:17:56 +05:00
parent 1f9aa7aca8
commit 039fbb5868
11 changed files with 641 additions and 10 deletions

View file

@ -16,6 +16,8 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyCheck
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
import com.tangem.domain.transaction.error.GetFeeError
import com.tangem.lib.crypto.BlockchainUtils.getTezosThreshold
import com.tangem.lib.crypto.BlockchainUtils.isTezos
import com.tangem.utils.extensions.isZero
import com.tangem.utils.extensions.orZero
import java.math.BigDecimal
@ -240,6 +242,31 @@ object NotificationsFactory {
}
}
fun MutableList<NotificationUM>.addFeeCoverageNotification(
isFeeCoverage: Boolean,
enteredAmountValue: BigDecimal,
sendingValue: BigDecimal,
appCurrency: AppCurrency,
cryptoCurrencyStatus: CryptoCurrencyStatus,
) {
val cryptoCurrency = cryptoCurrencyStatus.currency
val fiatRate = cryptoCurrencyStatus.value.fiatRate
val cryptoDiff = enteredAmountValue.minus(sendingValue)
if (isFeeCoverage) {
add(
NotificationUM.Warning.FeeCoverageNotification(
cryptoAmount = cryptoDiff.format { crypto(cryptoCurrency).uncapped() },
fiatAmount = getFiatString(
value = cryptoDiff,
rate = fiatRate,
appCurrency = appCurrency,
),
),
)
}
}
fun MutableList<NotificationUM>.addDustWarningNotification(
dustValue: BigDecimal?,
feeValue: BigDecimal,
@ -425,6 +452,41 @@ object NotificationsFactory {
add(NotificationUM.Solana.RentInfo(rentWarning))
}
fun MutableList<NotificationUM>.addHighFeeWarningNotification(
enteredAmountValue: BigDecimal,
cryptoCurrencyStatus: CryptoCurrencyStatus,
ignoreAmountReduce: Boolean,
onReduceClick: (
reduceAmountBy: BigDecimal,
reduceAmountByDiff: BigDecimal,
notification: Class<out NotificationUM>,
) -> Unit,
onCloseClick: (Class<out NotificationUM>) -> Unit,
) {
val balance = cryptoCurrencyStatus.value.amount ?: BigDecimal.ZERO
val isTezos = isTezos(cryptoCurrencyStatus.currency.network.id.value)
val threshold = getTezosThreshold()
val isTotalBalance = enteredAmountValue >= balance && balance > threshold
if (!ignoreAmountReduce && isTotalBalance && isTezos) {
add(
NotificationUM.Warning.HighFeeError(
currencyName = cryptoCurrencyStatus.currency.name,
amount = threshold.toPlainString(),
onConfirmClick = {
onReduceClick(
threshold,
threshold,
NotificationUM.Warning.HighFeeError::class.java,
)
},
onCloseClick = {
onCloseClick(NotificationUM.Warning.HighFeeError::class.java)
},
),
)
}
}
private fun checkDustLimits(
feeAmount: BigDecimal,
sendingAmount: BigDecimal,

View file

@ -0,0 +1,55 @@
package com.tangem.features.send.v2.subcomponents.notifications
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.ui.Modifier
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.transaction.error.GetFeeError
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.features.send.v2.subcomponents.notifications
import com.tangem.features.send.v2.subcomponents.notifications.model.NotificationsModel
import kotlinx.collections.immutable.ImmutableList
import kotlinx.coroutines.flow.StateFlow
import java.math.BigDecimal
internal class NotificationsComponent(
appComponentContext: AppComponentContext,
params: Params,
) : AppComponentContext by appComponentContext {
private val model: NotificationsModel = getOrCreateModel(params)
val state: StateFlow<ImmutableList<NotificationUM>> = model.uiState
fun LazyListScope.content(
state: ImmutableList<NotificationUM>,
modifier: Modifier = Modifier,
hasPaddingAbove: Boolean = false,
isClickDisabled: Boolean = false,
) {
notifications(
notifications = state,
modifier = modifier,
hasPaddingAbove = hasPaddingAbove,
isClickDisabled = isClickDisabled,
)
}
data class Params(
val analyticsCategoryName: String,
val userWalletId: UserWalletId,
val cryptoCurrencyStatus: CryptoCurrencyStatus,
val feeCryptoCurrencyStatus: CryptoCurrencyStatus,
val appCurrency: AppCurrency,
val destinationAddress: String,
val amountValue: BigDecimal,
val reduceAmountBy: BigDecimal,
val isIgnoreReduce: Boolean,
val fee: Fee?,
val feeError: GetFeeError?,
)
}

View file

@ -0,0 +1,40 @@
package com.tangem.features.send.v2.subcomponents.notifications
import com.tangem.features.send.v2.subcomponents.notifications.model.NotificationData
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import javax.inject.Inject
import javax.inject.Singleton
interface NotificationsUpdateTrigger {
/** Flow triggers notifications update */
val updateTriggerFlow: Flow<NotificationData>
/** Flow returns whether there is error notifications */
val hasErrorFlow: Flow<Boolean>
/** Trigger return callback with check result */
suspend fun callbackHasError(hasError: Boolean)
/** Trigger fee check reload */
suspend fun triggerUpdate(data: NotificationData)
}
@Singleton
internal class DefaultNotificationsUpdateTrigger @Inject constructor() : NotificationsUpdateTrigger {
private val _updateTriggerFlow = MutableSharedFlow<NotificationData>()
override val updateTriggerFlow = _updateTriggerFlow.asSharedFlow()
private val _hasErrorFlow = MutableSharedFlow<Boolean>()
override val hasErrorFlow = _hasErrorFlow.asSharedFlow()
override suspend fun callbackHasError(hasError: Boolean) {
_hasErrorFlow.emit(hasError)
}
override suspend fun triggerUpdate(data: NotificationData) {
_updateTriggerFlow.emit(data)
}
}

View file

@ -0,0 +1,32 @@
package com.tangem.features.send.v2.subcomponents.notifications.analytics
import com.tangem.core.analytics.models.AnalyticsEvent
import com.tangem.core.analytics.models.AnalyticsParam.Key.BLOCKCHAIN
import com.tangem.core.analytics.models.AnalyticsParam.Key.TOKEN_PARAM
internal sealed class NotificationsAnalyticEvents(
category: String,
event: String,
params: Map<String, String> = mapOf(),
) : AnalyticsEvent(category = category, event = event, params = params) {
abstract val categoryName: String
/** If not enough fee notification is present */
data class NoticeNotEnoughFee(
override val categoryName: String,
val token: String,
val blockchain: String,
) : NotificationsAnalyticEvents(
category = categoryName,
event = "Notice - Not Enough Fee",
params = mapOf(TOKEN_PARAM to token, BLOCKCHAIN to blockchain),
)
data class NoticeFeeCoverage(
override val categoryName: String,
) : NotificationsAnalyticEvents(
category = categoryName,
event = "Notice - Network Fee Coverage",
)
}

View file

@ -0,0 +1,20 @@
package com.tangem.features.send.v2.subcomponents.notifications.di
import com.tangem.features.send.v2.subcomponents.notifications.DefaultNotificationsUpdateTrigger
import com.tangem.features.send.v2.subcomponents.notifications.NotificationsUpdateTrigger
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
@Module
internal object NotificationsModule {
@Provides
@Singleton
fun providesNotificationsUpdateTrigger(): NotificationsUpdateTrigger {
return DefaultNotificationsUpdateTrigger()
}
}

View file

@ -0,0 +1,14 @@
package com.tangem.features.send.v2.subcomponents.notifications.model
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.domain.transaction.error.GetFeeError
import java.math.BigDecimal
data class NotificationData(
val destinationAddress: String,
val amountValue: BigDecimal,
val reduceAmountBy: BigDecimal,
val isIgnoreReduce: Boolean,
val fee: Fee?,
val feeError: GetFeeError?,
)

View file

@ -0,0 +1,366 @@
package com.tangem.features.send.v2.subcomponents.notifications.model
import androidx.compose.runtime.Stable
import arrow.core.getOrElse
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.common.routing.AppRoute
import com.tangem.common.routing.AppRouter
import com.tangem.common.ui.amountScreen.converters.AmountReduceByTransformer.ReduceByData
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
import com.tangem.common.ui.notifications.NotificationsFactory.addFeeUnreachableNotification
import com.tangem.common.ui.notifications.NotificationsFactory.addHighFeeWarningNotification
import com.tangem.common.ui.notifications.NotificationsFactory.addMinimumAmountErrorNotification
import com.tangem.common.ui.notifications.NotificationsFactory.addRentExemptionNotification
import com.tangem.common.ui.notifications.NotificationsFactory.addReserveAmountErrorNotification
import com.tangem.common.ui.notifications.NotificationsFactory.addTransactionLimitErrorNotification
import com.tangem.common.ui.notifications.NotificationsFactory.addValidateTransactionNotifications
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.domain.tokens.GetBalanceNotEnoughForFeeWarningUseCase
import com.tangem.domain.tokens.GetCurrencyCheckUseCase
import com.tangem.domain.tokens.IsAmountSubtractAvailableUseCase
import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyCheck
import com.tangem.domain.transaction.usecase.ValidateTransactionUseCase
import com.tangem.domain.utils.convertToSdkAmount
import com.tangem.features.send.v2.subcomponents.amount.SendAmountReduceTrigger
import com.tangem.features.send.v2.subcomponents.fee.SendFeeReloadTrigger
import com.tangem.features.send.v2.subcomponents.fee.model.checkAndCalculateSubtractedAmount
import com.tangem.features.send.v2.subcomponents.fee.model.checkFeeCoverage
import com.tangem.features.send.v2.subcomponents.notifications.NotificationsComponent
import com.tangem.features.send.v2.subcomponents.notifications.NotificationsUpdateTrigger
import com.tangem.features.send.v2.subcomponents.notifications.analytics.NotificationsAnalyticEvents
import com.tangem.lib.crypto.BlockchainUtils
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.extensions.orZero
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import java.math.BigDecimal
import javax.inject.Inject
@Suppress("LongParameterList")
@Stable
@ModelScoped
class NotificationsModel @Inject constructor(
paramsContainer: ParamsContainer,
override val dispatchers: CoroutineDispatcherProvider,
private val appRouter: AppRouter,
private val isAmountSubtractAvailableUseCase: IsAmountSubtractAvailableUseCase,
private val getCurrencyCheckUseCase: GetCurrencyCheckUseCase,
private val getBalanceNotEnoughForFeeWarningUseCase: GetBalanceNotEnoughForFeeWarningUseCase,
private val validateTransactionUseCase: ValidateTransactionUseCase,
private val sendFeeReloadTrigger: SendFeeReloadTrigger,
private val sendAmountReduceTrigger: SendAmountReduceTrigger,
private val notificationsUpdateTrigger: NotificationsUpdateTrigger,
private val analyticsEventHandler: AnalyticsEventHandler,
) : Model() {
private val params: NotificationsComponent.Params = paramsContainer.require()
private val analyticsCategoryName = params.analyticsCategoryName
private val userWalletId = params.userWalletId
private val cryptoCurrencyStatus = params.cryptoCurrencyStatus
private val feeCryptoCurrencyStatus = params.feeCryptoCurrencyStatus
private val currency = cryptoCurrencyStatus.currency
private val appCurrency = params.appCurrency
private var destinationAddress = params.destinationAddress
private var amountValue = params.amountValue
private var reduceAmountBy = params.reduceAmountBy
private var isIgnoreReduce = params.isIgnoreReduce
private var fee = params.fee
private var feeError = params.feeError
private val _uiState = MutableStateFlow<ImmutableList<NotificationUM>>(persistentListOf())
val uiState = _uiState.asStateFlow()
private var isAmountSubtractAvailable = false
init {
subscribeToNotificationUpdateTrigger()
checkIfSubtractAvailable()
}
private fun subscribeToNotificationUpdateTrigger() {
notificationsUpdateTrigger.updateTriggerFlow
.onEach { updateState(it) }
.launchIn(modelScope)
}
private fun checkIfSubtractAvailable() {
modelScope.launch {
isAmountSubtractAvailable = isAmountSubtractAvailableUseCase(userWalletId, currency).getOrElse { false }
buildNotifications()
}
}
private suspend fun updateState(data: NotificationData) {
destinationAddress = data.destinationAddress
amountValue = data.amountValue
reduceAmountBy = data.reduceAmountBy
isIgnoreReduce = data.isIgnoreReduce
fee = data.fee
feeError = data.feeError
buildNotifications()
}
private suspend fun buildNotifications() {
val notifications = buildList {
addFeeUnreachableNotification(
tokenStatus = cryptoCurrencyStatus,
coinStatus = feeCryptoCurrencyStatus,
feeError = feeError,
onReload = {
modelScope.launch {
sendFeeReloadTrigger.triggerUpdate()
}
},
onClick = ::showTokenDetails,
)
addDomainNotifications(
destinationAddress = destinationAddress,
amountValue = amountValue,
reduceAmountBy = reduceAmountBy,
fee = fee,
)
}
notificationsUpdateTrigger.callbackHasError(notifications.any { it is NotificationUM.Error })
_uiState.value = notifications.toImmutableList()
}
private fun showTokenDetails(currency: CryptoCurrency) {
appRouter.pop { isSuccess ->
if (isSuccess) {
appRouter.push(
AppRoute.CurrencyDetails(
userWalletId = userWalletId,
currency = currency,
),
)
}
}
}
private suspend fun MutableList<NotificationUM>.addDomainNotifications(
destinationAddress: String,
amountValue: BigDecimal,
reduceAmountBy: BigDecimal,
fee: Fee?,
) {
val balance = cryptoCurrencyStatus.value.amount ?: return
val feeValue = fee?.amount?.value ?: return
val isFeeCoverage = checkFeeCoverage(
isSubtractAvailable = isAmountSubtractAvailable,
balance = balance,
amountValue = amountValue,
feeValue = feeValue,
reduceAmountBy = reduceAmountBy,
)
val sendingAmount = checkAndCalculateSubtractedAmount(
isAmountSubtractAvailable = isAmountSubtractAvailable,
cryptoCurrencyStatus = cryptoCurrencyStatus,
amountValue = amountValue,
feeValue = feeValue,
reduceAmountBy = reduceAmountBy,
)
val feeCurrencyBalanceAfterTransaction = getFeeCurrencyBalanceAfterTx(
sendingAmount = sendingAmount,
feeValue = feeValue,
)
val currencyCheck = getCurrencyCheckUseCase(
userWalletId = userWalletId,
currencyStatus = cryptoCurrencyStatus,
amount = sendingAmount,
fee = feeValue,
recipientAddress = destinationAddress,
feeCurrencyBalanceAfterTransaction = feeCurrencyBalanceAfterTransaction,
)
addErrorNotifications(
sendingAmount = sendingAmount,
feeValue = feeValue,
currencyCheck = currencyCheck,
)
addWarningNotifications(
enteredAmount = amountValue,
fee = fee,
feeValue = feeValue,
sendingAmount = sendingAmount,
isFeeCoverage = isFeeCoverage,
currencyCheck = currencyCheck,
)
}
private fun getFeeCurrencyBalanceAfterTx(sendingAmount: BigDecimal, feeValue: BigDecimal): BigDecimal? {
val sendingCurrencyBalance = cryptoCurrencyStatus.value as? CryptoCurrencyStatus.Loaded
val feeCurrencyBalance = feeCryptoCurrencyStatus.value as? CryptoCurrencyStatus.Loaded
if (feeCryptoCurrencyStatus.value !is CryptoCurrencyStatus.Loaded) return null
return when {
feeCryptoCurrencyStatus == cryptoCurrencyStatus -> sendingCurrencyBalance?.let {
it.amount - sendingAmount - feeValue
}
else -> feeCurrencyBalance?.let { it.amount - feeValue }
}
}
private suspend fun MutableList<NotificationUM>.addErrorNotifications(
sendingAmount: BigDecimal,
feeValue: BigDecimal,
currencyCheck: CryptoCurrencyCheck,
) {
val currencyWarning = getBalanceNotEnoughForFeeWarningUseCase(
fee = feeValue,
userWalletId = userWalletId,
tokenStatus = cryptoCurrencyStatus,
coinStatus = feeCryptoCurrencyStatus,
).getOrNull()
addExceedBalanceNotification(
feeAmount = feeValue,
sendingAmount = sendingAmount,
isSubtractionAvailable = isAmountSubtractAvailable,
cryptoCurrencyStatus = cryptoCurrencyStatus,
)
addExceedsBalanceNotification(
cryptoCurrencyWarning = currencyWarning,
cryptoCurrencyStatus = cryptoCurrencyStatus,
shouldMergeFeeNetworkName = BlockchainUtils.isArbitrum(currency.network.backendId),
onClick = ::showTokenDetails,
onAnalyticsEvent = {
analyticsEventHandler.send(
NotificationsAnalyticEvents.NoticeNotEnoughFee(
categoryName = analyticsCategoryName,
token = cryptoCurrencyStatus.currency.symbol,
blockchain = cryptoCurrencyStatus.currency.network.name,
),
)
},
)
if (!BlockchainUtils.isCardano(currency.network.id.value)) {
addDustWarningNotification(
dustValue = currencyCheck.dustValue,
feeValue = feeValue,
sendingAmount = sendingAmount,
cryptoCurrencyStatus = cryptoCurrencyStatus,
feeCurrencyStatus = feeCryptoCurrencyStatus,
)
}
addTransactionLimitErrorNotification(
currencyCheck = currencyCheck,
sendingAmount = sendingAmount,
cryptoCurrencyStatus = cryptoCurrencyStatus,
feeCurrencyStatus = feeCryptoCurrencyStatus,
feeValue = feeValue,
onReduceClick = { reduceTo, _ ->
modelScope.launch {
sendAmountReduceTrigger.triggerReduceTo(reduceTo)
}
},
)
addReserveAmountErrorNotification(
reserveAmount = currencyCheck.reserveAmount,
sendingAmount = sendingAmount,
cryptoCurrency = currency,
isAccountFunded = currencyCheck.isAccountFunded,
)
addMinimumAmountErrorNotification(
minimumSendAmount = currencyCheck.minimumSendAmount,
sendingAmount = sendingAmount,
cryptoCurrency = currency,
)
}
private suspend fun MutableList<NotificationUM>.addWarningNotifications(
enteredAmount: BigDecimal,
sendingAmount: BigDecimal,
fee: Fee?,
feeValue: BigDecimal,
isFeeCoverage: Boolean,
currencyCheck: CryptoCurrencyCheck,
) {
val validationError = validateTransactionUseCase(
userWalletId = userWalletId,
amount = enteredAmount.convertToSdkAmount(currency),
fee = fee,
memo = null,
destination = "",
network = currency.network,
).leftOrNull()
addRentExemptionNotification(
rentWarning = currencyCheck.rentWarning,
)
addExistentialWarningNotification(
existentialDeposit = currencyCheck.existentialDeposit,
feeAmount = feeValue,
sendingAmount = sendingAmount,
cryptoCurrencyStatus = cryptoCurrencyStatus,
onReduceClick = { reduceBy, reduceByDiff, _ ->
modelScope.launch {
sendAmountReduceTrigger.triggerReduceBy(
ReduceByData(
reduceAmountBy = reduceBy,
reduceAmountByDiff = reduceByDiff,
),
)
}
},
)
addFeeCoverageNotification(
isFeeCoverage = isFeeCoverage,
enteredAmountValue = enteredAmount,
sendingValue = sendingAmount,
appCurrency = appCurrency,
cryptoCurrencyStatus = cryptoCurrencyStatus,
)
addValidateTransactionNotifications(
dustValue = currencyCheck.dustValue.orZero(),
minAdaValue = (fee as? Fee.CardanoToken)?.minAdaValue,
validationError = validationError,
cryptoCurrency = currency,
onReduceClick = { reduceTo, _ ->
modelScope.launch {
sendAmountReduceTrigger.triggerReduceTo(reduceTo)
}
},
)
addHighFeeWarningNotification(
enteredAmountValue = enteredAmount,
cryptoCurrencyStatus = cryptoCurrencyStatus,
ignoreAmountReduce = isIgnoreReduce,
onReduceClick = { reduceBy, reduceByDiff, _ ->
modelScope.launch {
sendAmountReduceTrigger.triggerReduceBy(
ReduceByData(
reduceAmountBy = reduceBy,
reduceAmountByDiff = reduceByDiff,
),
)
}
},
onCloseClick = {
modelScope.launch {
buildNotifications()
}
},
)
}
}

View file

@ -0,0 +1,48 @@
package com.tangem.features.send.v2.subcomponents.notifications.ui
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.core.ui.components.notifications.Notification
import com.tangem.core.ui.res.TangemTheme
import kotlinx.collections.immutable.ImmutableList
internal fun LazyListScope.notifications(
notifications: ImmutableList<NotificationUM>,
modifier: Modifier = Modifier,
hasPaddingAbove: Boolean = false,
isClickDisabled: Boolean = false,
) {
itemsIndexed(
items = notifications,
key = { _, item -> item::class.java },
contentType = { _, item -> item::class.java },
itemContent = { i, item ->
val topPadding = if (i == 0 && hasPaddingAbove) 0.dp else 12.dp
Notification(
config = item.config,
modifier = modifier
.padding(top = topPadding)
.animateItem(),
containerColor = when (item) {
is NotificationUM.Error.TokenExceedsBalance,
is NotificationUM.Warning.NetworkFeeUnreachable,
is NotificationUM.Warning.HighFeeError,
-> TangemTheme.colors.background.action
else -> TangemTheme.colors.button.disabled
},
iconTint = when (item) {
is NotificationUM.Error.TokenExceedsBalance,
is NotificationUM.Warning,
-> null
is NotificationUM.Error -> TangemTheme.colors.icon.warning
is NotificationUM.Info -> TangemTheme.colors.icon.accent
},
isEnabled = !isClickDisabled,
)
},
)
}

View file

@ -1,9 +1,7 @@
package com.tangem.features.send.impl.presentation.state.confirm
import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.blockchain.common.transaction.TransactionFee
import com.tangem.blockchainsdk.utils.minimalAmount
import com.tangem.common.ui.amountScreen.models.AmountState
import com.tangem.common.ui.notifications.NotificationUM
import com.tangem.common.ui.notifications.NotificationsFactory.addDustWarningNotification
@ -29,13 +27,14 @@ import com.tangem.domain.transaction.usecase.ValidateTransactionUseCase
import com.tangem.domain.utils.convertToSdkAmount
import com.tangem.domain.wallets.models.UserWalletId
import com.tangem.features.send.impl.presentation.analytics.SendAnalyticEvents
import com.tangem.features.send.impl.presentation.model.SendClickIntents
import com.tangem.features.send.impl.presentation.state.SendStates
import com.tangem.features.send.impl.presentation.state.SendUiState
import com.tangem.features.send.impl.presentation.state.SendUiStateType
import com.tangem.features.send.impl.presentation.state.StateRouter
import com.tangem.features.send.impl.presentation.state.fee.*
import com.tangem.features.send.impl.presentation.model.SendClickIntents
import com.tangem.lib.crypto.BlockchainUtils
import com.tangem.lib.crypto.BlockchainUtils.getTezosThreshold
import com.tangem.lib.crypto.BlockchainUtils.isTezos
import com.tangem.utils.Provider
import com.tangem.utils.extensions.orZero
@ -297,7 +296,7 @@ internal class SendNotificationFactory(
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
val balance = cryptoCurrencyStatus.value.amount ?: BigDecimal.ZERO
val isTezos = isTezos(cryptoCurrencyStatus.currency.network.id.value)
val threshold = Blockchain.Tezos.minimalAmount()
val threshold = getTezosThreshold()
val isTotalBalance = sendAmount >= balance && balance > threshold
if (!ignoreAmountReduce && isTotalBalance && isTezos) {
add(

View file

@ -463,10 +463,6 @@ fun Blockchain.amountToCreateAccount(walletManager: WalletManager, token: Token?
}
}
fun Blockchain.minimalAmount(): BigDecimal {
return BigDecimal.ONE.movePointLeft(decimals())
}
const val OLD_POLYGON_NAME = "matic-network"
const val NEW_POLYGON_NAME = "polygon-ecosystem-token"

View file

@ -5,7 +5,6 @@ import com.tangem.blockchain.common.Blockchain
import com.tangem.blockchainsdk.compatibility.l2BlockchainsList
import com.tangem.blockchainsdk.utils.ExcludedBlockchains
import com.tangem.blockchainsdk.utils.fromNetworkId
import com.tangem.blockchainsdk.utils.minimalAmount
import com.tangem.lib.crypto.converter.XrpTaggedAddressConverter
import com.tangem.lib.crypto.models.XrpTaggedAddress
import java.math.BigDecimal
@ -125,7 +124,7 @@ object BlockchainUtils {
return l2BlockchainsList.contains(blockchain)
}
fun getTezosThreshold(): BigDecimal = Blockchain.Tezos.minimalAmount()
fun getTezosThreshold(): BigDecimal = BigDecimal.ONE.movePointLeft(Blockchain.Tezos.decimals())
/**
* Blockchains not affecting total balance counting on errors