Updated on 2026-08-14
This commit is contained in:
parent
1264ada90d
commit
08ddee9acc
9 changed files with 73 additions and 76 deletions
|
|
@ -58,6 +58,16 @@ internal sealed class SendAlertState {
|
|||
override val confirmButtonText: TextReference = resourceReference(R.string.common_continue)
|
||||
}
|
||||
|
||||
data class FeeTooHigh(
|
||||
val times: String,
|
||||
override val onConfirmClick: () -> Unit,
|
||||
) : SendAlertState() {
|
||||
override val title: TextReference? = null
|
||||
override val message: TextReference =
|
||||
resourceReference(id = R.string.send_alert_fee_too_high_text, wrappedList(times))
|
||||
override val confirmButtonText: TextReference = resourceReference(R.string.common_continue)
|
||||
}
|
||||
|
||||
data class FeeCoverage(
|
||||
val amount: String,
|
||||
override val onConfirmClick: (() -> Unit),
|
||||
|
|
|
|||
|
|
@ -115,6 +115,20 @@ internal class SendEventStateFactory(
|
|||
)
|
||||
}
|
||||
|
||||
fun getFeeTooHighAlert(diff: String, onConsume: () -> Unit): SendUiState {
|
||||
return currentStateProvider().copy(
|
||||
event = triggeredEvent(
|
||||
data = SendEvent.ShowAlert(
|
||||
SendAlertState.FeeTooHigh(
|
||||
onConfirmClick = clickIntents::showSend,
|
||||
times = diff,
|
||||
),
|
||||
),
|
||||
onConsume = onConsume,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fun getGenericErrorState(error: Throwable? = null, onConsume: () -> Unit): SendUiState {
|
||||
val state = currentStateProvider()
|
||||
return state.copy(
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import kotlinx.coroutines.flow.Flow
|
|||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class SendNotificationFactory(
|
||||
|
|
@ -64,6 +65,7 @@ internal class SendNotificationFactory(
|
|||
// warnings
|
||||
addExistentialWarningNotification(feeAmount, amountValue)
|
||||
addHighFeeWarningNotification(feeAmount, amountValue, sendState.ignoreAmountReduce)
|
||||
addTooHighNotification(feeState.feeSelectorState)
|
||||
addTooLowNotification(feeState)
|
||||
}.toImmutableList()
|
||||
}
|
||||
|
|
@ -279,6 +281,18 @@ internal class SendNotificationFactory(
|
|||
}
|
||||
}
|
||||
|
||||
private fun MutableList<SendNotification>.addTooHighNotification(feeSelectorState: FeeSelectorState) {
|
||||
if (feeSelectorState !is FeeSelectorState.Content) return
|
||||
val multipleFees = feeSelectorState.fees as? TransactionFee.Choosable ?: return
|
||||
val highValue = multipleFees.priority.amount.value ?: return
|
||||
val customAmount = feeSelectorState.customValues.firstOrNull() ?: return
|
||||
val customValue = customAmount.value.parseToBigDecimal(customAmount.decimals)
|
||||
val diff = (customValue / highValue).toBigInteger()
|
||||
if (feeSelectorState.selectedFee == FeeType.Custom && diff > FEE_MAX_DIFF) {
|
||||
add(SendNotification.Warning.TooHigh(diff.toString()))
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun MutableList<SendNotification>.addExceedsBalanceNotification(fee: Fee?) {
|
||||
val feeValue = fee?.amount?.value ?: BigDecimal.ZERO
|
||||
val userWalletId = userWalletProvider().walletId
|
||||
|
|
@ -359,5 +373,6 @@ internal class SendNotificationFactory(
|
|||
companion object {
|
||||
private const val DOGECOIN_MINIMUM = "0.01"
|
||||
private val TEZOS_FEE_THRESHOLD = BigDecimal("0.01")
|
||||
internal val FEE_MAX_DIFF = BigInteger("5")
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import com.tangem.blockchain.common.transaction.TransactionFee
|
|||
import com.tangem.core.ui.utils.parseToBigDecimal
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.features.send.impl.presentation.state.SendUiState
|
||||
import com.tangem.features.send.impl.presentation.state.confirm.SendNotificationFactory
|
||||
|
||||
/**
|
||||
* Check if sending amount with fee is greater than balance
|
||||
|
|
@ -26,4 +27,19 @@ internal fun checkIfFeeTooLow(state: SendUiState): Boolean {
|
|||
val customValue = customAmount.value.parseToBigDecimal(customAmount.decimals)
|
||||
|
||||
return feeSelectorState.selectedFee == FeeType.Custom && minimumValue > customValue
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if custom fee is too high
|
||||
*/
|
||||
internal fun checkIfFeeTooHigh(state: SendUiState, onShow: (String) -> Unit): Boolean {
|
||||
val feeSelectorState = state.feeState?.feeSelectorState as? FeeSelectorState.Content ?: return false
|
||||
val multipleFees = feeSelectorState.fees as? TransactionFee.Choosable ?: return false
|
||||
val highValue = multipleFees.priority.amount.value ?: return false
|
||||
val customAmount = feeSelectorState.customValues.firstOrNull() ?: return false
|
||||
val customValue = customAmount.value.parseToBigDecimal(customAmount.decimals)
|
||||
val diff = (customValue / highValue).toBigInteger()
|
||||
val isShow = feeSelectorState.selectedFee == FeeType.Custom && diff > SendNotificationFactory.FEE_MAX_DIFF
|
||||
if (isShow) onShow(diff.toString())
|
||||
return isShow
|
||||
}
|
||||
|
|
@ -1,20 +1,15 @@
|
|||
package com.tangem.features.send.impl.presentation.state.fee
|
||||
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.core.ui.utils.parseToBigDecimal
|
||||
import com.tangem.features.send.impl.presentation.state.SendNotification
|
||||
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.fields.SendTextField
|
||||
import com.tangem.features.send.impl.presentation.state.SendNotification
|
||||
import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents
|
||||
import com.tangem.utils.Provider
|
||||
import com.tangem.utils.toFormattedString
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
import java.math.BigDecimal
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
internal class FeeNotificationFactory(
|
||||
|
|
@ -29,16 +24,7 @@ internal class FeeNotificationFactory(
|
|||
val state = currentStateProvider()
|
||||
val feeState = state.feeState ?: return@map persistentListOf()
|
||||
buildList {
|
||||
when (val feeSelectorState = feeState.feeSelectorState) {
|
||||
FeeSelectorState.Error -> {
|
||||
addFeeUnreachableNotification(feeSelectorState)
|
||||
}
|
||||
is FeeSelectorState.Content -> {
|
||||
val customFee = feeSelectorState.customValues
|
||||
val selectedFee = feeSelectorState.selectedFee
|
||||
addTooHighNotification(feeSelectorState.fees, selectedFee, customFee)
|
||||
}
|
||||
}
|
||||
addFeeUnreachableNotification(feeState.feeSelectorState)
|
||||
}.toImmutableList()
|
||||
}
|
||||
|
||||
|
|
@ -47,24 +33,4 @@ internal class FeeNotificationFactory(
|
|||
add(SendNotification.Warning.NetworkFeeUnreachable(clickIntents::feeReload))
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<SendNotification>.addTooHighNotification(
|
||||
transactionFee: TransactionFee,
|
||||
selectedFee: FeeType,
|
||||
customFee: List<SendTextField.CustomFee>,
|
||||
) {
|
||||
val multipleFees = transactionFee as? TransactionFee.Choosable ?: return
|
||||
val highValue = multipleFees.priority.amount.value ?: return
|
||||
val customAmount = customFee.firstOrNull() ?: return
|
||||
val customValue = customAmount.value.parseToBigDecimal(customAmount.decimals)
|
||||
val diff = customValue / highValue
|
||||
if (selectedFee == FeeType.Custom && diff > FEE_MAX_DIFF) {
|
||||
add(SendNotification.Warning.TooHigh(diff.toFormattedString(HIGH_FEE_DIFF_DECIMALS)))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val FEE_MAX_DIFF = BigDecimal(5)
|
||||
private const val HIGH_FEE_DIFF_DECIMALS = 0
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ package com.tangem.features.send.impl.presentation.ui.fee
|
|||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.animation.*
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Row
|
||||
|
|
@ -12,15 +11,12 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.core.ui.components.SpacerWMax
|
||||
import com.tangem.core.ui.components.rows.SelectorRowItem
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.BigDecimalFormatter
|
||||
import com.tangem.features.send.impl.R
|
||||
import com.tangem.features.send.impl.presentation.state.SendNotification
|
||||
import com.tangem.features.send.impl.presentation.state.SendStates
|
||||
import com.tangem.features.send.impl.presentation.state.fee.FeeSelectorState
|
||||
import com.tangem.features.send.impl.presentation.state.fee.FeeType
|
||||
|
|
@ -64,11 +60,6 @@ internal fun SendSpeedSelectorItem(
|
|||
showDivider = showDivider,
|
||||
)
|
||||
SendSpeedSelectorItemError(isError = feeSelectorState is FeeSelectorState.Error)
|
||||
|
||||
if (feeType == FeeType.Custom) {
|
||||
val showWarning = state.notifications.any { it is SendNotification.Warning.TooHigh }
|
||||
WarningIcon(showWarning = showWarning)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -97,29 +88,6 @@ private fun SendSpeedSelectorItemError(isError: Boolean) {
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WarningIcon(showWarning: Boolean = false) {
|
||||
Row {
|
||||
SpacerWMax()
|
||||
AnimatedVisibility(
|
||||
visible = showWarning,
|
||||
label = "Custom fee warning indicator",
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut(),
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.drawable.ic_alert_triangle_20),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
vertical = TangemTheme.dimens.spacing12,
|
||||
horizontal = TangemTheme.dimens.spacing14,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun FeeSelectorState.Content.getAmount(feeType: FeeType): Amount? {
|
||||
val choosableFees = fees as? TransactionFee.Choosable
|
||||
return when (feeType) {
|
||||
|
|
|
|||
|
|
@ -525,7 +525,15 @@ internal class SendViewModel @Inject constructor(
|
|||
)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return checkIfFeeTooHigh(
|
||||
state = uiState,
|
||||
onShow = { diff ->
|
||||
uiState = eventStateFactory.getFeeTooHighAlert(
|
||||
diff = diff,
|
||||
onConsume = { uiState = eventStateFactory.onConsumeEventState() },
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun onFeeCoverageAlert(): Boolean {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue