Updated on 2026-08-14
This commit is contained in:
parent
3a9bdb16ad
commit
aa621dd48f
10 changed files with 78 additions and 36 deletions
|
|
@ -294,9 +294,8 @@ internal object TokensDomainModule {
|
|||
@Singleton
|
||||
fun provideIsAmountSubtractAvailableUseCase(
|
||||
currenciesRepository: CurrenciesRepository,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): IsAmountSubtractAvailableUseCase {
|
||||
return IsAmountSubtractAvailableUseCase(currenciesRepository, dispatchers)
|
||||
return IsAmountSubtractAvailableUseCase(currenciesRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
|
|||
|
|
@ -2,11 +2,9 @@ package com.tangem.domain.tokens
|
|||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.domain.tokens.model.FeePaidCurrency
|
||||
import com.tangem.domain.tokens.repository.CurrenciesRepository
|
||||
import com.tangem.domain.models.wallet.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/**
|
||||
* Use case for checking if currency amount can be subtracted.
|
||||
|
|
@ -14,17 +12,18 @@ import kotlinx.coroutines.withContext
|
|||
*/
|
||||
class IsAmountSubtractAvailableUseCase(
|
||||
private val currenciesRepository: CurrenciesRepository,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) {
|
||||
suspend operator fun invoke(userWalletId: UserWalletId, currency: CryptoCurrency): Either<Throwable, Boolean> =
|
||||
Either.catch {
|
||||
withContext(dispatchers.io) {
|
||||
when (val feeCurrency = currenciesRepository.getFeePaidCurrency(userWalletId, currency.network)) {
|
||||
is FeePaidCurrency.Coin -> currency is CryptoCurrency.Coin
|
||||
is FeePaidCurrency.SameCurrency -> true
|
||||
is FeePaidCurrency.Token -> currency.id == feeCurrency.tokenId
|
||||
is FeePaidCurrency.FeeResource -> false
|
||||
}
|
||||
}
|
||||
suspend operator fun invoke(
|
||||
userWalletId: UserWalletId,
|
||||
currency: CryptoCurrency,
|
||||
isGaslessEthTx: Boolean = false,
|
||||
): Either<Throwable, Boolean> = Either.catch {
|
||||
if (isGaslessEthTx) return@catch true
|
||||
when (val feeCurrency = currenciesRepository.getFeePaidCurrency(userWalletId, currency.network)) {
|
||||
is FeePaidCurrency.Coin -> currency is CryptoCurrency.Coin
|
||||
is FeePaidCurrency.SameCurrency -> true
|
||||
is FeePaidCurrency.Token -> currency.id == feeCurrency.tokenId
|
||||
is FeePaidCurrency.FeeResource -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,7 +28,6 @@ interface SendNotificationsComponent {
|
|||
val analyticsCategoryName: String,
|
||||
val userWalletId: UserWalletId,
|
||||
val cryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
val feeCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
val appCurrency: AppCurrency,
|
||||
val notificationData: NotificationData,
|
||||
val callback: ModelCallback,
|
||||
|
|
@ -41,6 +40,7 @@ interface SendNotificationsComponent {
|
|||
val isIgnoreReduce: Boolean,
|
||||
val fee: Fee?,
|
||||
val feeError: GetFeeError?,
|
||||
val feeCryptoCurrencyStatus: CryptoCurrencyStatus,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -105,7 +105,6 @@ internal class SendConfirmComponent(
|
|||
analyticsCategoryName = params.analyticsCategoryName,
|
||||
userWalletId = params.userWallet.walletId,
|
||||
cryptoCurrencyStatus = params.cryptoCurrencyStatus,
|
||||
feeCryptoCurrencyStatus = params.feeCryptoCurrencyStatus,
|
||||
appCurrency = params.appCurrency,
|
||||
callback = model,
|
||||
notificationData = NotificationData(
|
||||
|
|
@ -116,6 +115,7 @@ internal class SendConfirmComponent(
|
|||
isIgnoreReduce = model.confirmData.isIgnoreReduce,
|
||||
fee = model.confirmData.fee,
|
||||
feeError = model.confirmData.feeError,
|
||||
feeCryptoCurrencyStatus = params.feeCryptoCurrencyStatus,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import androidx.compose.runtime.Stable
|
|||
import arrow.core.getOrElse
|
||||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.blockchain.common.TransactionData
|
||||
import com.tangem.blockchain.common.transaction.Fee
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.common.ui.amountScreen.converters.AmountReduceByTransformer
|
||||
import com.tangem.common.ui.amountScreen.models.AmountState
|
||||
|
|
@ -29,6 +30,7 @@ import com.tangem.domain.feedback.SendFeedbackEmailUseCase
|
|||
import com.tangem.domain.feedback.models.BlockchainErrorInfo
|
||||
import com.tangem.domain.feedback.models.FeedbackEmailType
|
||||
import com.tangem.domain.models.currency.CryptoCurrency
|
||||
import com.tangem.domain.models.currency.CryptoCurrencyStatus
|
||||
import com.tangem.domain.settings.IsSendTapHelpEnabledUseCase
|
||||
import com.tangem.domain.settings.NeverShowTapHelpUseCase
|
||||
import com.tangem.domain.tokens.AddCryptoCurrenciesUseCase
|
||||
|
|
@ -155,10 +157,7 @@ internal class SendConfirmModel @Inject constructor(
|
|||
internal var feeStateConfiguration: FeeStateConfiguration = FeeStateConfiguration.None
|
||||
|
||||
init {
|
||||
modelScope.launch {
|
||||
isAmountSubtractAvailable =
|
||||
isAmountSubtractAvailableUseCase(userWallet.walletId, cryptoCurrency).getOrElse { false }
|
||||
}
|
||||
updateAmountSubtractAvailability()
|
||||
configConfirmNavigation()
|
||||
subscribeOnNotificationsUpdateTrigger()
|
||||
subscribeOnCheckFeeResultUpdates()
|
||||
|
|
@ -357,7 +356,7 @@ internal class SendConfirmModel @Inject constructor(
|
|||
|
||||
val receivingAmount = checkAndCalculateSubtractedAmount(
|
||||
isAmountSubtractAvailable = isAmountSubtractAvailable,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
cryptoCurrencyStatus = getCurrencyStatusForFeePayment(),
|
||||
amountValue = amountValue,
|
||||
feeValue = feeValue,
|
||||
reduceAmountBy = confirmData.reduceAmountBy.orZero(),
|
||||
|
|
@ -392,7 +391,9 @@ internal class SendConfirmModel @Inject constructor(
|
|||
private suspend fun sendTransaction(txData: TransactionData.Uncompiled) {
|
||||
val feeExtended = feeUMV2?.feeExtraInfo?.transactionFeeExtended
|
||||
|
||||
val result = if (feeExtended != null) {
|
||||
val isFeeInTokenCurrency = feeExtended?.transactionFee?.normal is Fee.Ethereum.TokenCurrency
|
||||
|
||||
val result = if (isFeeInTokenCurrency) {
|
||||
createAndSendGaslessTransactionUseCase(
|
||||
userWallet = userWallet,
|
||||
transactionData = txData,
|
||||
|
|
@ -439,6 +440,16 @@ internal class SendConfirmModel @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun getCurrencyStatusForFeePayment(): CryptoCurrencyStatus {
|
||||
val feeExtended = feeUMV2?.feeExtraInfo?.transactionFeeExtended
|
||||
val isFeeInTokenCurrency = feeExtended?.transactionFee?.normal is Fee.Ethereum.TokenCurrency
|
||||
return if (isFeeInTokenCurrency) {
|
||||
feeUMV2?.feeExtraInfo?.feeCryptoCurrencyStatus ?: cryptoCurrencyStatus
|
||||
} else {
|
||||
params.feeCryptoCurrencyStatus
|
||||
}
|
||||
}
|
||||
|
||||
private fun addTokenToWalletIfNeeded() {
|
||||
if (cryptoCurrency !is CryptoCurrency.Token) return
|
||||
val wallets = destinationUM?.wallets ?: return
|
||||
|
|
@ -509,6 +520,7 @@ internal class SendConfirmModel @Inject constructor(
|
|||
isIgnoreReduce = confirmData.isIgnoreReduce,
|
||||
fee = confirmData.fee,
|
||||
feeError = confirmData.feeError,
|
||||
feeCryptoCurrencyStatus = getCurrencyStatusForFeePayment(),
|
||||
),
|
||||
)
|
||||
_uiState.update { state ->
|
||||
|
|
@ -610,9 +622,23 @@ internal class SendConfirmModel @Inject constructor(
|
|||
override fun onFeeResult(feeSelectorUM: FeeSelectorUMRedesigned) {
|
||||
sendIdleTimer = SystemClock.elapsedRealtime()
|
||||
_uiState.update { it.copy(feeSelectorUM = feeSelectorUM) }
|
||||
updateAmountSubtractAvailability()
|
||||
updateConfirmNotifications()
|
||||
}
|
||||
|
||||
private fun updateAmountSubtractAvailability() {
|
||||
modelScope.launch {
|
||||
val isGaslessEthTx =
|
||||
feeUMV2?.feeExtraInfo?.transactionFeeExtended?.transactionFee?.normal is Fee.Ethereum.TokenCurrency
|
||||
isAmountSubtractAvailable =
|
||||
isAmountSubtractAvailableUseCase(
|
||||
userWalletId = userWallet.walletId,
|
||||
currency = cryptoCurrency,
|
||||
isGaslessEthTx = isGaslessEthTx,
|
||||
).getOrElse { false }
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val CHECK_FEE_UPDATE_DELAY = 10_000L
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,6 @@ internal class NFTSendConfirmComponent @AssistedInject constructor(
|
|||
analyticsCategoryName = params.analyticsCategoryName,
|
||||
userWalletId = params.userWallet.walletId,
|
||||
cryptoCurrencyStatus = params.cryptoCurrencyStatus,
|
||||
feeCryptoCurrencyStatus = params.feeCryptoCurrencyStatus,
|
||||
appCurrency = params.appCurrency,
|
||||
callback = model,
|
||||
notificationData = SendNotificationsComponent.Params.NotificationData(
|
||||
|
|
@ -113,6 +112,7 @@ internal class NFTSendConfirmComponent @AssistedInject constructor(
|
|||
isIgnoreReduce = false,
|
||||
fee = model.confirmData.fee,
|
||||
feeError = model.confirmData.feeError,
|
||||
feeCryptoCurrencyStatus = params.feeCryptoCurrencyStatus,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -350,6 +350,7 @@ internal class NFTSendConfirmModel @Inject constructor(
|
|||
isIgnoreReduce = false,
|
||||
fee = confirmData.fee,
|
||||
feeError = confirmData.feeError,
|
||||
feeCryptoCurrencyStatus = params.feeCryptoCurrencyStatus, // TODO change when gasless implement
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ internal class NotificationsModel @Inject constructor(
|
|||
private val analyticsCategoryName = params.analyticsCategoryName
|
||||
private val userWalletId = params.userWalletId
|
||||
private val cryptoCurrencyStatus = params.cryptoCurrencyStatus
|
||||
private val feeCryptoCurrencyStatus = params.feeCryptoCurrencyStatus
|
||||
private val feeCryptoCurrencyStatus = params.notificationData.feeCryptoCurrencyStatus
|
||||
private val currency = cryptoCurrencyStatus.currency
|
||||
private val appCurrency = params.appCurrency
|
||||
|
||||
|
|
@ -92,7 +92,10 @@ internal class NotificationsModel @Inject constructor(
|
|||
|
||||
init {
|
||||
subscribeToNotificationUpdateTrigger()
|
||||
checkIfSubtractAvailable()
|
||||
modelScope.launch {
|
||||
checkIfSubtractAvailable()
|
||||
buildNotifications()
|
||||
}
|
||||
incrementNotificationsShowCount()
|
||||
}
|
||||
|
||||
|
|
@ -102,11 +105,12 @@ internal class NotificationsModel @Inject constructor(
|
|||
.launchIn(modelScope)
|
||||
}
|
||||
|
||||
private fun checkIfSubtractAvailable() {
|
||||
modelScope.launch {
|
||||
isAmountSubtractAvailable = isAmountSubtractAvailableUseCase(userWalletId, currency).getOrElse { false }
|
||||
buildNotifications()
|
||||
}
|
||||
private suspend fun checkIfSubtractAvailable() {
|
||||
isAmountSubtractAvailable = isAmountSubtractAvailableUseCase(
|
||||
userWalletId = userWalletId,
|
||||
currency = currency,
|
||||
isGaslessEthTx = notificationData.fee is Fee.Ethereum.TokenCurrency,
|
||||
).getOrElse { false }
|
||||
}
|
||||
|
||||
private fun incrementNotificationsShowCount() {
|
||||
|
|
@ -115,16 +119,19 @@ internal class NotificationsModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun updateState(data: NotificationData) {
|
||||
private fun updateState(data: NotificationData) {
|
||||
notificationData = data
|
||||
buildNotifications()
|
||||
modelScope.launch {
|
||||
checkIfSubtractAvailable()
|
||||
buildNotifications()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun buildNotifications() = with(notificationData) {
|
||||
val feeValue = fee?.amount?.value
|
||||
val sendingAmount = checkAndCalculateSubtractedAmount(
|
||||
isAmountSubtractAvailable = isAmountSubtractAvailable,
|
||||
cryptoCurrencyStatus = cryptoCurrencyStatus,
|
||||
cryptoCurrencyStatus = getCurrencyStatusForFeePayment(),
|
||||
amountValue = amountValue,
|
||||
feeValue = feeValue,
|
||||
reduceAmountBy = reduceAmountBy,
|
||||
|
|
@ -369,6 +376,15 @@ internal class NotificationsModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getCurrencyStatusForFeePayment(): CryptoCurrencyStatus {
|
||||
val isFeeInTokenCurrency = notificationData.fee is Fee.Ethereum.TokenCurrency
|
||||
return if (isFeeInTokenCurrency) {
|
||||
notificationData.feeCryptoCurrencyStatus
|
||||
} else {
|
||||
cryptoCurrencyStatus
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TRON_FEE_NOTIFICATION_MAX_SHOW_COUNT = 3
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,7 +107,6 @@ internal class SendWithSwapConfirmComponent @AssistedInject constructor(
|
|||
analyticsCategoryName = params.analyticsCategoryName,
|
||||
userWalletId = params.userWallet.walletId,
|
||||
cryptoCurrencyStatus = model.primaryCurrencyStatus,
|
||||
feeCryptoCurrencyStatus = model.primaryFeePaidCurrencyStatus,
|
||||
appCurrency = params.appCurrency,
|
||||
callback = model,
|
||||
notificationData = SendNotificationsComponent.Params.NotificationData(
|
||||
|
|
@ -121,6 +120,7 @@ internal class SendWithSwapConfirmComponent @AssistedInject constructor(
|
|||
isIgnoreReduce = model.confirmData.isIgnoreReduce,
|
||||
fee = model.confirmData.fee,
|
||||
feeError = model.confirmData.feeError,
|
||||
feeCryptoCurrencyStatus = model.primaryFeePaidCurrencyStatus,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -357,6 +357,7 @@ internal class SendWithSwapConfirmModel @Inject constructor(
|
|||
isIgnoreReduce = confirmData.isIgnoreReduce,
|
||||
fee = confirmData.fee,
|
||||
feeError = confirmData.feeError,
|
||||
feeCryptoCurrencyStatus = params.primaryFeePaidCurrencyStatusFlow.value,
|
||||
),
|
||||
)
|
||||
swapNotificationsUpdateTrigger.triggerUpdate(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue