Updated on 2026-08-14
This commit is contained in:
parent
a80542d5da
commit
3d832ddd3e
13 changed files with 88 additions and 24 deletions
|
|
@ -9,6 +9,7 @@ import com.tangem.core.ui.extensions.wrappedList
|
|||
import com.tangem.core.ui.format.bigdecimal.crypto
|
||||
import com.tangem.core.ui.format.bigdecimal.format
|
||||
import com.tangem.core.ui.format.bigdecimal.shorted
|
||||
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
|
||||
import java.math.BigDecimal
|
||||
|
||||
sealed class NotificationUM(val config: NotificationConfig) {
|
||||
|
|
@ -307,4 +308,17 @@ sealed class NotificationUM(val config: NotificationConfig) {
|
|||
),
|
||||
)
|
||||
}
|
||||
|
||||
sealed interface Solana {
|
||||
|
||||
data class RentInfo(
|
||||
private val rentInfo: CryptoCurrencyWarning.Rent,
|
||||
) : Info(
|
||||
title = TextReference.Res(R.string.warning_rent_fee_title),
|
||||
subtitle = TextReference.Res(
|
||||
id = R.string.warning_solana_rent_fee_message,
|
||||
formatArgs = wrappedList(rentInfo.rent, rentInfo.exemptionAmount),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ dependencies {
|
|||
implementation(projects.domain.tokens.models)
|
||||
implementation(projects.domain.txhistory.models)
|
||||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.staking.models)
|
||||
|
||||
/** Project - Data */
|
||||
implementation(projects.core.datasource)
|
||||
|
|
|
|||
|
|
@ -6,13 +6,17 @@ import com.tangem.blockchain.common.MinimumSendAmountProvider
|
|||
import com.tangem.blockchain.common.ReserveAmountProvider
|
||||
import com.tangem.blockchain.common.UtxoAmountLimitProvider
|
||||
import com.tangem.data.tokens.converters.UtxoConverter
|
||||
import com.tangem.domain.staking.model.stakekit.YieldBalance
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.CurrencyAmount
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.model.blockchains.UtxoAmountLimit
|
||||
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
|
||||
import com.tangem.domain.tokens.repository.CurrencyChecksRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import com.tangem.utils.extensions.isZero
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.math.BigDecimal
|
||||
|
||||
|
|
@ -118,4 +122,23 @@ internal class DefaultCurrencyChecksRepository(
|
|||
}
|
||||
return utxoAmount?.let(UtxoConverter()::convert)
|
||||
}
|
||||
|
||||
override suspend fun getRentInfoWarning(
|
||||
userWalletId: UserWalletId,
|
||||
currencyStatus: CryptoCurrencyStatus,
|
||||
balanceAfterTransaction: BigDecimal?,
|
||||
): CryptoCurrencyWarning.Rent? {
|
||||
val rentData = walletManagersFacade.getRentInfo(userWalletId, currencyStatus.currency.network) ?: return null
|
||||
val balanceValue = currencyStatus.value as? CryptoCurrencyStatus.Loaded ?: return null
|
||||
val stakingTotalBalance =
|
||||
(balanceValue.yieldBalance as? YieldBalance.Data)?.getTotalStakingBalance() ?: BigDecimal.ZERO
|
||||
val amount = balanceAfterTransaction ?: balanceValue.amount
|
||||
return when {
|
||||
amount.isZero() && stakingTotalBalance.isZero() -> null
|
||||
amount < rentData.exemptionAmount && stakingTotalBalance.isZero() -> {
|
||||
CryptoCurrencyWarning.Rent(rentData.rent, rentData.exemptionAmount)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -25,11 +25,11 @@ import com.tangem.domain.common.util.hasDerivation
|
|||
import com.tangem.domain.demo.DemoConfig
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
|
||||
import com.tangem.domain.transaction.models.AssetRequirementsCondition
|
||||
import com.tangem.domain.txhistory.models.PaginationWrapper
|
||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||
import com.tangem.domain.txhistory.models.TxHistoryState
|
||||
import com.tangem.domain.walletmanager.model.RentData
|
||||
import com.tangem.domain.walletmanager.model.SmartContractMethod
|
||||
import com.tangem.domain.walletmanager.model.TokenInfo
|
||||
import com.tangem.domain.walletmanager.model.UpdateWalletManagerResult
|
||||
|
|
@ -413,7 +413,7 @@ class DefaultWalletManagersFacade(
|
|||
return manager?.wallet?.addresses.orEmpty()
|
||||
}
|
||||
|
||||
override suspend fun getRentInfo(userWalletId: UserWalletId, network: Network): CryptoCurrencyWarning.Rent? {
|
||||
override suspend fun getRentInfo(userWalletId: UserWalletId, network: Network): RentData? {
|
||||
val manager = getOrCreateWalletManager(
|
||||
userWalletId = userWalletId,
|
||||
network = network,
|
||||
|
|
@ -422,24 +422,7 @@ class DefaultWalletManagersFacade(
|
|||
|
||||
return when (val result = manager.minimalBalanceForRentExemption()) {
|
||||
is Result.Success -> {
|
||||
val balance = manager.wallet.fundsAvailable(AmountType.Coin)
|
||||
val outgoingTxs = manager.wallet.recentTransactions
|
||||
.filter {
|
||||
it.sourceAddress == manager.wallet.address &&
|
||||
it.amount.type == AmountType.Coin &&
|
||||
it.status != TransactionStatus.Confirmed
|
||||
}
|
||||
|
||||
val rentExempt = result.data
|
||||
val setRent = if (outgoingTxs.isEmpty()) {
|
||||
balance < rentExempt
|
||||
} else {
|
||||
val outgoingAmount = outgoingTxs.sumOf { it.amount.value ?: BigDecimal.ZERO }
|
||||
val rest = balance.minus(outgoingAmount)
|
||||
balance < rest
|
||||
}
|
||||
|
||||
if (setRent) CryptoCurrencyWarning.Rent(manager.rentAmount(), rentExempt) else null
|
||||
RentData(manager.rentAmount(), result.data)
|
||||
}
|
||||
is Result.Failure -> null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ import com.tangem.blockchain.extensions.Result
|
|||
import com.tangem.blockchain.extensions.SimpleResult
|
||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
|
||||
import com.tangem.domain.transaction.models.AssetRequirementsCondition
|
||||
import com.tangem.domain.txhistory.models.PaginationWrapper
|
||||
import com.tangem.domain.txhistory.models.TxHistoryItem
|
||||
import com.tangem.domain.txhistory.models.TxHistoryState
|
||||
import com.tangem.domain.walletmanager.model.RentData
|
||||
import com.tangem.domain.walletmanager.model.TokenInfo
|
||||
import com.tangem.domain.walletmanager.model.UpdateWalletManagerResult
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
|
@ -140,7 +140,7 @@ interface WalletManagersFacade {
|
|||
* @param userWalletId selected wallet id
|
||||
* @param network network of currency
|
||||
*/
|
||||
suspend fun getRentInfo(userWalletId: UserWalletId, network: Network): CryptoCurrencyWarning.Rent?
|
||||
suspend fun getRentInfo(userWalletId: UserWalletId, network: Network): RentData?
|
||||
|
||||
@Deprecated("Will be removed in future")
|
||||
fun getAll(userWalletId: UserWalletId): Flow<List<WalletManager>>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
package com.tangem.domain.walletmanager.model
|
||||
|
||||
import java.math.BigDecimal
|
||||
|
||||
/**
|
||||
* Represents wallet blockchain rent
|
||||
* @param rent Amount that will be charged in overtime if the blockchain does not have an amount greater than
|
||||
* the [exemptionAmount]
|
||||
* @param exemptionAmount Amount that should be on the blockchain balance not to pay rent
|
||||
*/
|
||||
data class RentData(val rent: BigDecimal, val exemptionAmount: BigDecimal)
|
||||
|
|
@ -10,4 +10,5 @@ data class CryptoCurrencyCheck(
|
|||
val existentialDeposit: BigDecimal?,
|
||||
val utxoAmountLimit: UtxoAmountLimit?,
|
||||
val isAccountFunded: Boolean,
|
||||
val rentWarning: CryptoCurrencyWarning.Rent?,
|
||||
)
|
||||
|
|
@ -18,6 +18,7 @@ class GetCurrencyCheckUseCase(
|
|||
currencyStatus: CryptoCurrencyStatus,
|
||||
amount: BigDecimal?,
|
||||
fee: BigDecimal?,
|
||||
balanceAfterTransaction: BigDecimal?,
|
||||
recipientAddress: String? = null,
|
||||
): CryptoCurrencyCheck {
|
||||
return withContext(dispatchers.io) {
|
||||
|
|
@ -26,6 +27,8 @@ class GetCurrencyCheckUseCase(
|
|||
val reserveAmount = currencyChecksRepository.getReserveAmount(userWalletId, network)
|
||||
val minimumSendAmount = currencyChecksRepository.getMinimumSendAmount(userWalletId, network)
|
||||
val existentialDeposit = currencyChecksRepository.getExistentialDeposit(userWalletId, network)
|
||||
val rentWarning =
|
||||
currencyChecksRepository.getRentInfoWarning(userWalletId, currencyStatus, balanceAfterTransaction)
|
||||
val isAccountFunded = recipientAddress?.let {
|
||||
currencyChecksRepository.checkIfAccountFunded(
|
||||
userWalletId,
|
||||
|
|
@ -51,6 +54,7 @@ class GetCurrencyCheckUseCase(
|
|||
existentialDeposit = existentialDeposit,
|
||||
utxoAmountLimit = utxoAmountLimit,
|
||||
isAccountFunded = isAccountFunded,
|
||||
rentWarning = rentWarning,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ class GetCurrencyWarningsUseCase(
|
|||
derivationPath = derivationPath,
|
||||
isSingleWalletWithTokens = isSingleWalletWithTokens,
|
||||
),
|
||||
flowOf(walletManagersFacade.getRentInfo(userWalletId, currency.network)),
|
||||
flowOf(currencyChecksRepository.getRentInfoWarning(userWalletId, currencyStatus, null)),
|
||||
flowOf(currencyChecksRepository.getExistentialDeposit(userWalletId, currency.network)),
|
||||
flowOf(currencyChecksRepository.getFeeResourceAmount(userWalletId, currency.network)),
|
||||
getSwapPromoNotificationWarning(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
package com.tangem.domain.tokens.repository
|
||||
|
||||
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
|
||||
import com.tangem.domain.tokens.model.CurrencyAmount
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.model.blockchains.UtxoAmountLimit
|
||||
import com.tangem.domain.tokens.model.warnings.CryptoCurrencyWarning
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import java.math.BigDecimal
|
||||
|
||||
|
|
@ -39,4 +41,14 @@ interface CurrencyChecksRepository {
|
|||
amount: BigDecimal,
|
||||
fee: BigDecimal,
|
||||
): UtxoAmountLimit?
|
||||
|
||||
/**
|
||||
* Checks if need warning for Solana rent
|
||||
* @param balanceAfterTransaction if non null, checks with balance remains after transaction
|
||||
*/
|
||||
suspend fun getRentInfoWarning(
|
||||
userWalletId: UserWalletId,
|
||||
currencyStatus: CryptoCurrencyStatus,
|
||||
balanceAfterTransaction: BigDecimal?,
|
||||
): CryptoCurrencyWarning.Rent?
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ import com.tangem.domain.tokens.GetBalanceNotEnoughForFeeWarningUseCase
|
|||
import com.tangem.domain.tokens.GetCurrencyCheckUseCase
|
||||
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.domain.transaction.usecase.ValidateTransactionUseCase
|
||||
import com.tangem.domain.utils.convertToSdkAmount
|
||||
|
|
@ -93,12 +94,15 @@ internal class SendNotificationFactory(
|
|||
val feeError = (feeState.feeSelectorState as? FeeSelectorState.Error)?.error
|
||||
|
||||
val recipientAddress = state.recipientState?.addressTextField?.value
|
||||
val statusValue = cryptoCurrencyStatus.value as? CryptoCurrencyStatus.Loaded
|
||||
val balanceAfterTransaction = statusValue?.let { it.amount - sendingAmount - feeValue }
|
||||
val currencyCheck = getCurrencyCheckUseCase(
|
||||
userWalletId = userWalletId,
|
||||
currencyStatus = cryptoCurrencyStatus,
|
||||
amount = sendingAmount,
|
||||
fee = feeValue,
|
||||
recipientAddress = recipientAddress,
|
||||
balanceAfterTransaction = balanceAfterTransaction,
|
||||
)
|
||||
buildList {
|
||||
addErrorNotifications(
|
||||
|
|
@ -221,6 +225,11 @@ internal class SendNotificationFactory(
|
|||
network = cryptoCurrencyStatus.currency.network,
|
||||
).leftOrNull()
|
||||
}
|
||||
|
||||
addRentExemptionNotification(
|
||||
rentWarning = currencyCheck.rentWarning,
|
||||
)
|
||||
|
||||
addExistentialWarningNotification(
|
||||
existentialDeposit = currencyCheck.existentialDeposit,
|
||||
feeAmount = feeState.fee?.amount?.value.orZero(),
|
||||
|
|
@ -303,4 +312,9 @@ internal class SendNotificationFactory(
|
|||
add(NotificationUM.Warning.TooHigh(diff))
|
||||
}
|
||||
}
|
||||
|
||||
private fun MutableList<NotificationUM>.addRentExemptionNotification(rentWarning: CryptoCurrencyWarning.Rent?) {
|
||||
if (rentWarning == null) return
|
||||
add(NotificationUM.Solana.RentInfo(rentWarning))
|
||||
}
|
||||
}
|
||||
|
|
@ -44,7 +44,7 @@ internal fun LazyListScope.notifications(
|
|||
is NotificationUM.Warning,
|
||||
-> null
|
||||
is NotificationUM.Error -> TangemTheme.colors.icon.warning
|
||||
is NotificationUM.Info -> null
|
||||
is NotificationUM.Info -> TangemTheme.colors.icon.accent
|
||||
},
|
||||
isEnabled = !isClickDisabled,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -638,6 +638,7 @@ internal class StakingViewModel @Inject constructor(
|
|||
currencyStatus = cryptoCurrencyStatus,
|
||||
amount = amount,
|
||||
fee = fee,
|
||||
balanceAfterTransaction = null, // ignore this in staking
|
||||
)
|
||||
stateController.update(
|
||||
AddStakingNotificationsTransformer(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue