diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml
index 7ed29ac733..45b3948014 100644
--- a/core/res/src/main/res/values-ru/strings.xml
+++ b/core/res/src/main/res/values-ru/strings.xml
@@ -92,7 +92,6 @@
Обозреватель
Комиссия
Сетевые комиссии – это плата пользователя за обработку и подтверждение транзакций. Размер комиссии зависит от нагрузки на сеть, объема транзакции и приоритета исполнения. %s
- Подробнее
Свое
Быстро
По рынку
@@ -111,6 +110,7 @@
OK
Основная карта
Вставить
+ Подробнее
Получить
Отклонить
Перезагрузить
@@ -457,6 +457,8 @@
Поддержка
Транзакция не выполнена
Причина: %1$s\nКод: %2$s
+ Недостаточно средств для покрытия комиссии сети. Вычесть комиссию из отправляемой сумму?
+ Вычесть
%1$s в %2$s
Адрес
Код назначения
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 6189bc5cbf..246e7b197e 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -90,7 +90,6 @@
Explorer
Fee
Network fees are charges users pay to process and confirm transactions. The fee amount can be affected by network congestion, transaction size, and execution priority. %s
- Read more
Custom
Fast
Market
@@ -110,6 +109,7 @@
OK
Primary Card
Paste
+ Read more
Receive
Reject
Reload
@@ -459,6 +459,8 @@
Support
The transaction is not completed
Reason: %1$s\nCode: %2$s
+ Недостаточно средств для покрытия комиссии сети. Вычесть комиссию из отправляемой сумму?
+ Вычесть
Confirm
%1$s at %2$s
Address
@@ -486,7 +488,7 @@
Maximum fee amount
Numbers only for Destination Tag
Network fee
- Sending amount will be reduced to cover the selected fee level
+ Sending amount will be reduced by %1$s to cover the selected commission level. The recipient will get %2$s.
Network fee coverage
Insufficient funds for the transfer, as the total of the fee and transfer amount exceeds the existing balance
Total exceeds balance
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/analytics/utils/SendOnNextScreenAnalyticSender.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/analytics/utils/SendOnNextScreenAnalyticSender.kt
index e3f5666a1c..4fc8d719af 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/analytics/utils/SendOnNextScreenAnalyticSender.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/analytics/utils/SendOnNextScreenAnalyticSender.kt
@@ -23,9 +23,6 @@ internal class SendOnNextScreenAnalyticSender(
}
analyticsEventHandler.send(SendAnalyticEvents.SelectedFee(selectedFee.name))
}
- if (feeState.isSubtract) {
- analyticsEventHandler.send(SendAnalyticEvents.SubtractFromAmount)
- }
}
SendUiStateType.Amount -> {
val isFiatSelected = state.amountState?.amountTextField?.isFiatValue ?: return
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendAlertState.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendAlertState.kt
index 672ceb39d5..ce176c7174 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendAlertState.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendAlertState.kt
@@ -45,11 +45,20 @@ internal sealed class SendAlertState {
override val message: TextReference = resourceReference(id = R.string.warning_demo_mode_message)
}
- object FeeIncreased : SendAlertState() {
+ data object FeeIncreased : SendAlertState() {
override val title: TextReference? = null
override val message: TextReference = resourceReference(id = R.string.send_notification_high_fee_title)
}
+ data class FeeCoverage(
+ override val onConfirmClick: (() -> Unit),
+ ) : SendAlertState() {
+ override val title: TextReference? = null
+ override val message: TextReference = resourceReference(id = R.string.send_alert_fee_coverage_title)
+ override val confirmButtonText: TextReference =
+ resourceReference(id = R.string.send_alert_fee_coverage_subract_text)
+ }
+
data class ReserveAmount(val amount: String) : SendAlertState() {
override val title: TextReference =
resourceReference(id = R.string.send_notification_invalid_reserve_amount_title, wrappedList(amount))
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendEventStateFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendEventStateFactory.kt
index 23c9aec225..1bfe20a62b 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendEventStateFactory.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendEventStateFactory.kt
@@ -43,6 +43,20 @@ internal class SendEventStateFactory(
)
}
+ fun getFeeCoverageAlert(onConsume: () -> Unit): SendUiState {
+ val state = currentStateProvider()
+ return state.copy(
+ event = triggeredEvent(
+ data = SendEvent.ShowAlert(
+ SendAlertState.FeeCoverage(
+ onConfirmClick = clickIntents::onSubtractSelect,
+ ),
+ ),
+ onConsume = onConsume,
+ ),
+ )
+ }
+
fun getFeeUpdatedAlert(fee: TransactionFee, onConsume: () -> Unit, onFeeNotIncreased: () -> Unit): SendUiState {
val state = currentStateProvider()
val feeSelector = state.feeState?.feeSelectorState as? FeeSelectorState.Content ?: return state
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendNotification.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendNotification.kt
index cdbd005127..4ab6952836 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendNotification.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendNotification.kt
@@ -85,5 +85,16 @@ internal sealed class SendNotification(val config: NotificationConfig) {
title = resourceReference(R.string.send_notification_existential_deposit_title),
subtitle = resourceReference(R.string.send_notification_existential_deposit_text, wrappedList(deposit)),
)
+
+ data class NetworkCoverage(
+ val amountReducedBy: String,
+ val amountReduced: String,
+ ) : Warning(
+ title = resourceReference(id = R.string.send_network_fee_warning_title),
+ subtitle = resourceReference(
+ id = R.string.send_network_fee_warning_content,
+ formatArgs = wrappedList(amountReducedBy, amountReduced),
+ ),
+ )
}
}
\ No newline at end of file
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendNotificationFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendNotificationFactory.kt
index cdfb8fc271..6f3021a2b5 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendNotificationFactory.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendNotificationFactory.kt
@@ -30,20 +30,22 @@ internal class SendNotificationFactory(
.filter { it.type == SendUiStateType.Send }
.map {
val state = currentStateProvider()
+ val sendState = state.sendState
val feeState = state.feeState ?: return@map persistentListOf()
val feeAmount = feeState.fee?.amount?.value ?: BigDecimal.ZERO
- val amountValue = state.amountState?.amountTextField?.value?.toBigDecimalOrNull() ?: BigDecimal.ZERO
- val sendAmount = if (feeState.isSubtract) feeState.receivedAmountValue else amountValue
+ val amountValue = state.amountState?.amountTextField?.cryptoAmount?.value ?: BigDecimal.ZERO
+ val sendAmount = if (sendState.isSubtract) amountValue.minus(feeAmount) else amountValue
buildList {
// errors
addExceedBalanceNotification(feeAmount, sendAmount)
- addInvalidAmountNotification(feeState.isSubtract, sendAmount)
+ addInvalidAmountNotification(sendState.isSubtract, sendAmount)
addMinimumAmountErrorNotification(feeAmount, sendAmount)
addDustWarningNotification(feeAmount, sendAmount)
addTransactionLimitErrorNotification(feeAmount, sendAmount)
// warnings
+ addFeeCoverageNotification(sendState.isSubtract, sendAmount)
addExistentialWarningNotification(feeAmount, sendAmount)
- addHighFeeWarningNotification(amountValue, state.sendState.ignoreAmountReduce)
+ addHighFeeWarningNotification(sendAmount, sendState.ignoreAmountReduce)
}.toImmutableList()
}
@@ -234,6 +236,29 @@ internal class SendNotificationFactory(
}
}
+ private fun MutableList.addFeeCoverageNotification(
+ isSubtract: Boolean,
+ amountValue: BigDecimal,
+ ) {
+ val state = currentStateProvider()
+ val cryptoCurrency = cryptoCurrencyStatusProvider().currency
+ val feeAmount = state.feeState?.fee?.amount?.value ?: BigDecimal.ZERO
+
+ val amountReducedValue = amountValue.minus(feeAmount)
+ val amountReducedByValue = amountValue.minus(amountReducedValue)
+ val amountReducedBy = BigDecimalFormatter.formatCryptoAmount(
+ cryptoAmount = amountReducedByValue,
+ cryptoCurrency = cryptoCurrency,
+ )
+ val amountReduced = BigDecimalFormatter.formatCryptoAmount(
+ cryptoAmount = amountReducedValue,
+ cryptoCurrency = cryptoCurrency,
+ )
+ if (isSubtract) {
+ add(SendNotification.Warning.NetworkCoverage(amountReducedBy, amountReduced))
+ }
+ }
+
companion object {
private const val CARDANO_MINIMUM = "1"
private const val DOGECOIN_MINIMUM = "0.01"
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendStateFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendStateFactory.kt
index bbace2d0ac..10b562c4c5 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendStateFactory.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendStateFactory.kt
@@ -223,6 +223,13 @@ internal class SendStateFactory(
//endregion
//region send
+ fun onSubtractSelect(isSubtract: Boolean): SendUiState {
+ val state = currentStateProvider()
+ return state.copy(
+ sendState = state.sendState.copy(isSubtract = isSubtract),
+ )
+ }
+
fun getSendingStateUpdate(isSending: Boolean): SendUiState {
val state = currentStateProvider()
return state.copy(sendState = state.sendState.copy(isSending = isSending))
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt
index 9f1c13016c..8611ded493 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/SendUiState.kt
@@ -75,12 +75,7 @@ internal sealed class SendStates {
override val type: SendUiStateType = SendUiStateType.Fee,
override val isPrimaryButtonEnabled: Boolean = false,
val feeSelectorState: FeeSelectorState,
- val isSubtractAvailable: Boolean,
- val isSubtract: Boolean,
- val isUserSubtracted: Boolean,
val fee: Fee?,
- val receivedAmountValue: BigDecimal,
- val receivedAmount: String,
val rate: BigDecimal?,
val appCurrency: AppCurrency,
val isFeeApproximate: Boolean,
@@ -94,6 +89,7 @@ internal sealed class SendStates {
override val isPrimaryButtonEnabled: Boolean = true,
val isSending: Boolean = false,
val isSuccess: Boolean = false,
+ val isSubtract: Boolean = false,
val transactionDate: Long = 0L,
val txUrl: String = "",
val ignoreAmountReduce: Boolean = false,
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/StateRouter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/StateRouter.kt
index 21a6c3e9db..a9c6451ab9 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/StateRouter.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/StateRouter.kt
@@ -119,12 +119,12 @@ internal class StateRouter(
mutableCurrentState.update { SendUiCurrentScreen(SendUiStateType.Fee, isFromConfirmation) }
}
- private fun continueToSend(show: () -> Unit) {
- if (currentState.value.isFromConfirmation) showSend() else show()
- }
-
- private fun showSend() {
+ fun showSend() {
analyticsEventsHandler.send(SendAnalyticEvents.ConfirmationScreenOpened)
mutableCurrentState.update { SendUiCurrentScreen(SendUiStateType.Send, isFromConfirmation = false) }
}
+
+ private fun continueToSend(show: () -> Unit) {
+ if (currentState.value.isFromConfirmation) showSend() else show()
+ }
}
\ No newline at end of file
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeCalculation.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeCalculation.kt
index 16d58d39a6..b9a182691f 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeCalculation.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeCalculation.kt
@@ -1,14 +1,14 @@
package com.tangem.features.send.impl.presentation.state.fee
-import com.tangem.blockchain.common.transaction.Fee
+import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.features.send.impl.presentation.state.SendUiState
-import java.math.BigDecimal
/**
- * Calculate receiving amount when fee is subtracted from sending amount
+ * Check if sending amount with fee is greater than balance
*/
-internal fun calculateReceiveAmount(state: SendUiState, feeAmount: Fee): BigDecimal {
- val amountValue = state.amountState?.amountTextField?.cryptoAmount?.value ?: BigDecimal.ZERO
- val fee = feeAmount.amount.value ?: return BigDecimal.ZERO
- return amountValue.minus(fee)
+internal fun checkFeeCoverage(state: SendUiState, cryptoCurrencyStatus: CryptoCurrencyStatus): Boolean {
+ val balance = cryptoCurrencyStatus.value.amount ?: return false
+ val fee = state.feeState?.fee?.amount?.value ?: return false
+ val amount = state.amountState?.amountTextField?.cryptoAmount?.value ?: return false
+ return balance <= amount + fee
}
\ No newline at end of file
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeNotificationFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeNotificationFactory.kt
index 3581ba0610..47b85049a3 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeNotificationFactory.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeNotificationFactory.kt
@@ -9,7 +9,6 @@ import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.features.send.impl.R
-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.fields.SendTextField
@@ -47,7 +46,6 @@ internal class FeeNotificationFactory(
val selectedFee = feeSelectorState.selectedFee
addTooLowNotification(feeSelectorState.fees, selectedFee, customFee)
addTooHighNotification(feeSelectorState.fees, selectedFee, customFee)
- addFeeCoverageNotification(feeState, state.amountState)
addExceedsBalanceNotification(feeState.fee)
}
}
@@ -89,20 +87,6 @@ internal class FeeNotificationFactory(
}
}
- private fun MutableList.addFeeCoverageNotification(
- feeState: SendStates.FeeState,
- amountState: SendStates.AmountState?,
- ) {
- if (!feeState.isSubtractAvailable) return
-
- val cryptoAmount = coinCryptoCurrencyStatusProvider().value.amount ?: return
- val feeValue = feeState.fee?.amount?.value ?: return
- val value = amountState?.amountTextField?.cryptoAmount?.value ?: return
- if (cryptoAmount <= value + feeValue && feeState.isSubtract && !feeState.isUserSubtracted) {
- add(SendFeeNotification.Warning.NetworkCoverage)
- }
- }
-
private suspend fun MutableList.addExceedsBalanceNotification(fee: Fee?) {
val feeValue = fee?.amount?.value ?: BigDecimal.ZERO
val userWalletId = userWalletProvider().walletId
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeStateFactory.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeStateFactory.kt
index b8f99a5511..d928d3c091 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeStateFactory.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/FeeStateFactory.kt
@@ -3,7 +3,6 @@ package com.tangem.features.send.impl.presentation.state.fee
import com.tangem.blockchain.common.transaction.Fee
import com.tangem.blockchain.common.transaction.TransactionFee
import com.tangem.common.extensions.isZero
-import com.tangem.core.ui.utils.BigDecimalFormatter
import com.tangem.core.ui.utils.parseToBigDecimal
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
@@ -14,7 +13,6 @@ import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents
import com.tangem.utils.Provider
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
-import java.math.BigDecimal
/**
* Factory to produce fee state for [SendUiState]
@@ -22,7 +20,6 @@ import java.math.BigDecimal
internal class FeeStateFactory(
private val clickIntents: SendClickIntents,
private val currentStateProvider: Provider,
- private val coinCryptoCurrencyStatusProvider: Provider,
private val cryptoCurrencyStatusProvider: Provider,
private val appCurrencyProvider: Provider,
private val isFeeApproximateUseCase: IsFeeApproximateUseCase,
@@ -55,9 +52,8 @@ internal class FeeStateFactory(
)
}
- fun onFeeOnLoadedState(fees: TransactionFee, isSubtractAvailable: Boolean): SendUiState {
+ fun onFeeOnLoadedState(fees: TransactionFee): SendUiState {
val state = currentStateProvider()
- val balance = coinCryptoCurrencyStatusProvider().value.amount ?: BigDecimal.ZERO
val feeState = state.feeState ?: return state
val feeSelectorState = (feeState.feeSelectorState as? FeeSelectorState.Content)?.copy(
fees = fees,
@@ -68,43 +64,15 @@ internal class FeeStateFactory(
)
val fee = feeConverter.convert(feeSelectorState)
- val receivedAmount = calculateReceiveAmount(state, fee)
return state.copy(
feeState = feeState.copy(
- isSubtractAvailable = isSubtractAvailable,
feeSelectorState = feeSelectorState,
fee = fee,
- receivedAmountValue = receivedAmount,
- receivedAmount = getFormattedValue(receivedAmount),
- isSubtract = isSubtractAvailable && checkAutoSubtract(state, fee, balance),
isFeeApproximate = isFeeApproximate(fee),
),
)
}
- fun onFeeOnLoadedState(fees: TransactionFee): SendUiState {
- val state = currentStateProvider()
- val balance = coinCryptoCurrencyStatusProvider().value.amount ?: BigDecimal.ZERO
- val feeState = state.feeState ?: return state
- val feeSelectorState = feeState.feeSelectorState as? FeeSelectorState.Content ?: return state
-
- val updatedFeeSelector = feeSelectorState.copy(
- fees = fees,
- customValues = customFeeFieldConverter.convert(fees.normal),
- )
- val fee = feeConverter.convert(updatedFeeSelector)
- val receivedAmount = calculateReceiveAmount(state, fee)
- return state.copy(
- feeState = feeState.copy(
- feeSelectorState = updatedFeeSelector,
- fee = fee,
- receivedAmountValue = receivedAmount,
- receivedAmount = getFormattedValue(receivedAmount),
- isSubtract = checkAutoSubtract(state, fee, balance),
- ),
- )
- }
-
fun onFeeOnErrorState(): SendUiState {
val state = currentStateProvider()
return state.copy(
@@ -118,18 +86,13 @@ internal class FeeStateFactory(
val state = currentStateProvider()
val feeState = state.feeState ?: return state
val feeSelectorState = feeState.feeSelectorState as? FeeSelectorState.Content ?: return state
- val balance = coinCryptoCurrencyStatusProvider().value.amount ?: BigDecimal.ZERO
val updatedFeeSelectorState = feeSelectorState.copy(selectedFee = feeType)
val fee = feeConverter.convert(updatedFeeSelectorState)
- val receivedAmount = calculateReceiveAmount(state, fee)
return state.copy(
feeState = feeState.copy(
fee = fee,
feeSelectorState = updatedFeeSelectorState,
- receivedAmountValue = receivedAmount,
- receivedAmount = getFormattedValue(receivedAmount),
- isSubtract = checkAutoSubtract(state, fee, balance),
),
)
}
@@ -139,34 +102,12 @@ internal class FeeStateFactory(
val feeState = state.feeState ?: return state
val feeSelectorState = feeState.feeSelectorState as? FeeSelectorState.Content ?: return state
val updatedFeeSelectorState = customFeeFieldConverter.onValueChange(feeSelectorState, index, value)
- val balance = coinCryptoCurrencyStatusProvider().value.amount ?: BigDecimal.ZERO
val fee = feeConverter.convert(updatedFeeSelectorState)
- val receivedAmount = calculateReceiveAmount(state, fee)
return state.copy(
feeState = feeState.copy(
feeSelectorState = updatedFeeSelectorState,
fee = fee,
- receivedAmountValue = receivedAmount,
- receivedAmount = getFormattedValue(receivedAmount),
- isSubtract = checkAutoSubtract(state, fee, balance),
- ),
- )
- }
-
- fun onSubtractSelect(value: Boolean): SendUiState {
- val state = currentStateProvider()
- val feeState = state.feeState ?: return state
- val feeSelectorState = feeState.feeSelectorState as? FeeSelectorState.Content ?: return state
- val fee = feeConverter.convert(feeSelectorState)
- val receivedAmount = calculateReceiveAmount(state, fee)
- return state.copy(
- feeState = feeState.copy(
- isSubtract = value,
- isUserSubtracted = true,
- receivedAmountValue = receivedAmount,
- receivedAmount = getFormattedValue(receivedAmount),
- fee = fee,
),
)
}
@@ -187,9 +128,6 @@ internal class FeeStateFactory(
): Boolean {
val feeSelectorState = feeState.feeSelectorState as? FeeSelectorState.Content ?: return false
val customValue = feeSelectorState.customValues.firstOrNull()
- val balance = coinCryptoCurrencyStatusProvider().value.amount ?: BigDecimal.ZERO
- val fee = feeConverter.convert(feeSelectorState)
- val feeValue = fee.amount.value ?: BigDecimal.ZERO
val isNotCustom = feeSelectorState.selectedFee != FeeType.Custom
val isNotEmptyCustom = if (customValue != null) {
@@ -198,24 +136,8 @@ internal class FeeStateFactory(
false
}
val noErrors = notifications.none { it is SendFeeNotification.Error }
- val isSubtractRequired = when {
- !feeState.isSubtractAvailable -> true // current currency is not fee currency
- feeValue + feeState.receivedAmountValue >= balance -> feeState.isSubtract
- else -> feeValue + feeState.receivedAmountValue <= balance
- }
- return noErrors && isSubtractRequired && (isNotEmptyCustom || isNotCustom)
- }
-
- private fun checkAutoSubtract(state: SendUiState, fee: Fee, balance: BigDecimal): Boolean {
- val feeState = state.feeState ?: return false
- val amountValue = state.amountState?.amountTextField?.cryptoAmount?.value ?: BigDecimal.ZERO
- val feeAmount = fee.amount.value ?: BigDecimal.ZERO
- return if (feeState.isUserSubtracted) {
- feeState.isSubtract
- } else {
- amountValue + feeAmount >= balance
- }
+ return noErrors && (isNotEmptyCustom || isNotCustom)
}
private fun isFeeApproximate(fee: Fee): Boolean {
@@ -225,13 +147,4 @@ internal class FeeStateFactory(
amountType = fee.amount.type,
)
}
-
- private fun getFormattedValue(value: BigDecimal): String {
- val cryptoCurrency = cryptoCurrencyStatusProvider().currency
- return BigDecimalFormatter.formatCryptoAmount(
- cryptoAmount = value,
- cryptoCurrency = cryptoCurrency.symbol,
- decimals = cryptoCurrency.decimals,
- )
- }
}
\ No newline at end of file
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeNotification.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeNotification.kt
index f895fb4921..56add5cfe5 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeNotification.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeNotification.kt
@@ -32,11 +32,6 @@ sealed class SendFeeNotification(val config: NotificationConfig) {
subtitle = resourceReference(id = R.string.send_notification_fee_too_high_text, wrappedList(value)),
)
- object NetworkCoverage : Warning(
- title = resourceReference(id = R.string.send_network_fee_warning_title),
- subtitle = resourceReference(id = R.string.send_network_fee_warning_content),
- )
-
data class NetworkFeeUnreachable(val onRefresh: () -> Unit) : Warning(
title = resourceReference(R.string.send_fee_unreachable_error_title),
subtitle = resourceReference(R.string.send_fee_unreachable_error_text),
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeStateConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeStateConverter.kt
index 1dbee6b3fd..2659080a08 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeStateConverter.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fee/SendFeeStateConverter.kt
@@ -6,7 +6,6 @@ import com.tangem.features.send.impl.presentation.state.SendStates
import com.tangem.utils.Provider
import com.tangem.utils.converter.Converter
import kotlinx.collections.immutable.persistentListOf
-import java.math.BigDecimal
internal class SendFeeStateConverter(
private val appCurrencyProvider: Provider,
@@ -17,12 +16,7 @@ internal class SendFeeStateConverter(
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
return SendStates.FeeState(
feeSelectorState = FeeSelectorState.Loading,
- isSubtractAvailable = false,
- isSubtract = false,
- isUserSubtracted = false,
fee = null,
- receivedAmountValue = BigDecimal.ZERO,
- receivedAmount = "",
notifications = persistentListOf(),
rate = cryptoCurrencyStatus.value.fiatRate,
appCurrency = appCurrencyProvider(),
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fields/SendAmountFieldChangeConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fields/SendAmountFieldChangeConverter.kt
index 630a026952..1b2a4d56f6 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fields/SendAmountFieldChangeConverter.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fields/SendAmountFieldChangeConverter.kt
@@ -6,7 +6,6 @@ import androidx.compose.ui.text.input.KeyboardType
import com.tangem.common.extensions.isZero
import com.tangem.core.ui.utils.parseBigDecimal
import com.tangem.core.ui.utils.parseToBigDecimal
-import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.features.send.impl.presentation.state.SendUiState
import com.tangem.utils.Provider
@@ -22,7 +21,6 @@ internal class SendAmountFieldChangeConverter(
val state = currentStateProvider()
val amountState = state.amountState ?: return state
val amountTextField = amountState.amountTextField
- val feeState = state.feeState ?: return state
if (value.isEmpty()) return state.emptyState()
val cryptoDecimals = amountTextField.cryptoAmount.decimals
@@ -36,7 +34,6 @@ internal class SendAmountFieldChangeConverter(
val checkValue = if (amountTextField.isFiatValue) fiatValue else cryptoValue
val isExceedBalance = checkValue.checkExceedBalance(amountTextField)
- val isMaxAmount = checkValue.checkMaxAmount(amountTextField)
return state.copy(
amountState = amountState.copy(
isPrimaryButtonEnabled = !isExceedBalance,
@@ -52,9 +49,6 @@ internal class SendAmountFieldChangeConverter(
),
),
),
- feeState = feeState.copy(
- isSubtract = isMaxAmount,
- ),
)
}
@@ -104,19 +98,4 @@ internal class SendAmountFieldChangeConverter(
cryptoDecimal > currencyCryptoAmount || cryptoDecimal.isZero()
}
}
-
- private fun String.checkMaxAmount(amountTextField: SendTextField.AmountField): Boolean {
- val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
-
- // If current currency is Token
- if (cryptoCurrencyStatus.currency is CryptoCurrency.Token) return false
-
- val currencyCryptoAmount = cryptoCurrencyStatus.value.amount ?: BigDecimal.ZERO
- val currencyFiatAmount = cryptoCurrencyStatus.value.fiatAmount ?: BigDecimal.ZERO
- return if (amountTextField.isFiatValue) {
- parseToBigDecimal(amountTextField.fiatAmount.decimals) == currencyFiatAmount
- } else {
- parseToBigDecimal(amountTextField.cryptoAmount.decimals) == currencyCryptoAmount
- }
- }
}
\ No newline at end of file
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fields/SendAmountFieldMaxAmountConverter.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fields/SendAmountFieldMaxAmountConverter.kt
index f6875731d7..b29459e757 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fields/SendAmountFieldMaxAmountConverter.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/state/fields/SendAmountFieldMaxAmountConverter.kt
@@ -20,7 +20,6 @@ internal class SendAmountFieldMaxAmountConverter(
val cryptoCurrencyStatus = cryptoCurrencyStatusProvider()
val amountState = state.amountState ?: return state
val amountTextField = amountState.amountTextField
- val feeState = state.feeState ?: return state
val cryptoDecimals = amountTextField.cryptoAmount.decimals
val fiatDecimals = amountTextField.fiatAmount.decimals
@@ -47,9 +46,6 @@ internal class SendAmountFieldMaxAmountConverter(
),
),
),
- feeState = feeState.copy(
- isSubtract = true,
- ),
)
}
}
\ No newline at end of file
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedAndFeeContent.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedAndFeeContent.kt
index 95a469975a..5acd6b57b1 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedAndFeeContent.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedAndFeeContent.kt
@@ -15,7 +15,6 @@ import com.tangem.core.ui.components.notifications.Notification
import com.tangem.core.ui.res.TangemTheme
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
import com.tangem.features.send.impl.presentation.state.fee.SendFeeNotification
import com.tangem.features.send.impl.presentation.viewmodel.SendClickIntents
import kotlinx.collections.immutable.ImmutableList
@@ -41,8 +40,6 @@ internal fun SendSpeedAndFeeContent(state: SendStates.FeeState?, clickIntents: S
topNotifications(notifications)
customFee(feeSendState)
middleNotifications(notifications)
- subtractButton(state, clickIntents)
- bottomNotifications(notifications)
}
}
@@ -85,17 +82,6 @@ private fun LazyListScope.middleNotifications(
)
}
-private fun LazyListScope.bottomNotifications(
- configs: ImmutableList,
- modifier: Modifier = Modifier,
-) {
- notifications(
- configs = configs.filterIsInstance().toImmutableList(),
- isLast = true,
- modifier = modifier,
- )
-}
-
@OptIn(ExperimentalFoundationApi::class)
private fun LazyListScope.notifications(
configs: ImmutableList,
@@ -159,36 +145,4 @@ internal fun LazyListScope.customFee(feeSendState: FeeSelectorState, modifier: M
}
}
}
-}
-
-@OptIn(ExperimentalFoundationApi::class)
-internal fun LazyListScope.subtractButton(
- state: SendStates.FeeState,
- clickIntents: SendClickIntents,
- modifier: Modifier = Modifier,
-) {
- val receivedAmount = state.receivedAmount
- val isSubtract = state.isSubtract
- val isSubtractAvailable = state.isSubtractAvailable
- val feeSendState = state.feeSelectorState
- if (isSubtractAvailable) {
- item {
- val feeStateContent = feeSendState as? FeeSelectorState.Content
- val isCustomAvailable = feeStateContent?.customValues.isNullOrEmpty().not()
- val isCustomSelected = feeStateContent?.selectedFee == FeeType.Custom
- val topPadding = if (isCustomSelected && isCustomAvailable) {
- TangemTheme.dimens.spacing12
- } else {
- TangemTheme.dimens.spacing20
- }
- SendSpeedSubtract(
- receivingAmount = receivedAmount,
- isSubtract = isSubtract,
- onSelectClick = clickIntents::onSubtractSelect,
- modifier = modifier
- .padding(top = topPadding)
- .animateItemPlacement(),
- )
- }
- }
}
\ No newline at end of file
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt
index 611c29dd70..4d13b7d7a5 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/fee/SendSpeedSelector.kt
@@ -154,7 +154,7 @@ internal fun SendSpeedSelector(
@Composable
private fun FooterText(onReadMoreClick: () -> Unit) {
- val linkText = stringResource(R.string.common_fee_selector_link_description)
+ val linkText = stringResource(R.string.common_read_more)
val fullString = stringResource(R.string.common_fee_selector_footer, linkText)
val linkTextPosition = fullString.length - linkText.length
val defaultStyle = TangemTheme.colors.text.tertiary
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendClickIntents.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendClickIntents.kt
index 8d409188fd..6c66189f98 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendClickIntents.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendClickIntents.kt
@@ -43,7 +43,7 @@ internal interface SendClickIntents {
fun onCustomFeeValueChange(index: Int, value: String)
- fun onSubtractSelect(value: Boolean)
+ fun onSubtractSelect()
fun onReadMoreClick()
// endregion
diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendViewModel.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendViewModel.kt
index 524d95dada..c9969641c5 100644
--- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendViewModel.kt
+++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/viewmodel/SendViewModel.kt
@@ -45,9 +45,9 @@ import com.tangem.features.send.impl.presentation.domain.AvailableWallet
import com.tangem.features.send.impl.presentation.state.*
import com.tangem.features.send.impl.presentation.state.amount.AmountStateFactory
import com.tangem.features.send.impl.presentation.state.fee.FeeNotificationFactory
-import com.tangem.features.send.impl.presentation.state.fee.FeeSelectorState
import com.tangem.features.send.impl.presentation.state.fee.FeeStateFactory
import com.tangem.features.send.impl.presentation.state.fee.FeeType
+import com.tangem.features.send.impl.presentation.state.fee.checkFeeCoverage
import com.tangem.lib.crypto.BlockchainUtils
import com.tangem.utils.Provider
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@@ -126,7 +126,6 @@ internal class SendViewModel @Inject constructor(
private val feeStateFactory = FeeStateFactory(
clickIntents = this,
currentStateProvider = Provider { uiState },
- coinCryptoCurrencyStatusProvider = Provider { coinCryptoCurrencyStatus },
cryptoCurrencyStatusProvider = Provider { cryptoCurrencyStatus },
appCurrencyProvider = Provider(selectedAppCurrencyFlow::value),
isFeeApproximateUseCase = isFeeApproximateUseCase,
@@ -411,6 +410,20 @@ internal class SendViewModel @Inject constructor(
override fun popBackStack() = stateRouter.popBackStack()
override fun onBackClick() = stateRouter.onBackClick(uiState.sendState.isSuccess)
override fun onNextClick() {
+ val currentState = stateRouter.currentState.value
+ val isCurrentFee = currentState.type == SendUiStateType.Fee
+ if (isCurrentFee) {
+ val isFeeCoverage = checkFeeCoverage(uiState, cryptoCurrencyStatus)
+ if (isAmountSubtractAvailable && isFeeCoverage) {
+ uiState = eventStateFactory.getFeeCoverageAlert(
+ onConsume = { uiState = eventStateFactory.onConsumeEventState() },
+ )
+ return
+ } else {
+ uiState = stateFactory.onSubtractSelect(false)
+ }
+ }
+
val prevScreen = stateRouter.onNextClick()
sendOnNextScreenAnalyticSender.send(prevScreen, uiState)
}
@@ -520,9 +533,9 @@ internal class SendViewModel @Inject constructor(
updateFeeNotifications()
}
- override fun onSubtractSelect(value: Boolean) {
- uiState = feeStateFactory.onSubtractSelect(value)
- updateFeeNotifications()
+ override fun onSubtractSelect() {
+ uiState = stateFactory.onSubtractSelect(true)
+ stateRouter.showSend()
}
override fun onReadMoreClick() {
@@ -539,12 +552,8 @@ internal class SendViewModel @Inject constructor(
viewModelScope.launch(dispatchers.main) {
uiState = feeStateFactory.onFeeOnLoadingState()
uiState = callFeeUseCase()?.fold(
- ifRight = { fees ->
- feeStateFactory.onFeeOnLoadedState(fees, isAmountSubtractAvailable)
- },
- ifLeft = {
- feeStateFactory.onFeeOnErrorState()
- },
+ ifRight = feeStateFactory::onFeeOnLoadedState,
+ ifLeft = { feeStateFactory.onFeeOnErrorState() },
) ?: feeStateFactory.onFeeOnErrorState()
updateFeeNotifications()
}.saveIn(feeJobHolder)
@@ -587,16 +596,19 @@ internal class SendViewModel @Inject constructor(
}
override fun showAmount() {
+ uiState = stateFactory.onSubtractSelect(false)
stateRouter.showAmount(isFromConfirmation = true)
analyticsEventHandler.send(SendAnalyticEvents.ScreenReopened(SendScreenSource.Amount))
}
override fun showRecipient() {
+ uiState = stateFactory.onSubtractSelect(false)
stateRouter.showRecipient(isFromConfirmation = true)
analyticsEventHandler.send(SendAnalyticEvents.ScreenReopened(SendScreenSource.Address))
}
override fun showFee() {
+ uiState = stateFactory.onSubtractSelect(false)
stateRouter.showFee(isFromConfirmation = true)
analyticsEventHandler.send(SendAnalyticEvents.ScreenReopened(SendScreenSource.Fee))
}
@@ -623,12 +635,12 @@ internal class SendViewModel @Inject constructor(
private fun verifyAndSendTransaction() {
val recipient = uiState.recipientState?.addressTextField?.value ?: return
val feeState = uiState.feeState ?: return
- val feeSelectorState = feeState.feeSelectorState as? FeeSelectorState.Content ?: return
+ val fee = feeState.fee ?: return
val memo = uiState.recipientState?.memoTextField?.value
- val fee = feeStateFactory.feeConverter.convert(feeSelectorState)
val amountValue = uiState.amountState?.amountTextField?.cryptoAmount?.value ?: return
- val amountToSend = if (feeState.isSubtract && isAmountSubtractAvailable) {
- feeState.receivedAmountValue
+ val amountToSend = if (uiState.sendState.isSubtract && isAmountSubtractAvailable) {
+ val feeValue = fee.amount.value ?: return
+ amountValue.minus(feeValue)
} else {
amountValue
}
diff --git a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt
index 49d98a51dd..0da7c077d1 100644
--- a/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt
+++ b/features/swap/presentation/src/main/java/com/tangem/feature/swap/ui/StateBuilder.kt
@@ -1119,7 +1119,7 @@ internal class StateBuilder(
},
readMoreUrl = buildReadMoreUrl(),
feeItems = txFeeState.toFeeItemState(),
- readMore = resourceReference(R.string.common_fee_selector_link_description),
+ readMore = resourceReference(R.string.common_read_more),
onReadMoreClick = actions.onFeeReadMoreClick,
)
return uiState.copy(