From c3850e7991119e0aea51d552ddf06d92fe7d383d Mon Sep 17 00:00:00 2001 From: Tangem Date: Fri, 19 Dec 2025 18:09:53 +0400 Subject: [PATCH] Updated on 2026-08-14 --- .../YieldSupplyGetDustMinAmountUseCase.kt | 9 ++- .../usecase/YieldSupplyMinAmountUseCase.kt | 8 ++ .../YieldSupplyGetDustMinAmountUseCaseTest.kt | 74 +++++++++++++++++-- .../active/model/YieldSupplyActiveModel.kt | 6 +- .../impl/main/model/YieldSupplyModel.kt | 3 +- 5 files changed, 91 insertions(+), 9 deletions(-) diff --git a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetDustMinAmountUseCase.kt b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetDustMinAmountUseCase.kt index 941311c2fa..54ee458d9d 100644 --- a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetDustMinAmountUseCase.kt +++ b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetDustMinAmountUseCase.kt @@ -1,6 +1,7 @@ package com.tangem.domain.yield.supply.usecase import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.models.currency.CryptoCurrencyStatus import java.math.BigDecimal /** @@ -12,11 +13,15 @@ import java.math.BigDecimal */ class YieldSupplyGetDustMinAmountUseCase { - operator fun invoke(minAmount: BigDecimal, appCurrency: AppCurrency): BigDecimal { + operator fun invoke( + minAmountTokenCurrency: BigDecimal, + appCurrency: AppCurrency, + tokenCryptoCurrencyStatus: CryptoCurrencyStatus, + ): BigDecimal { return if (appCurrency.code in SUPPORTED_DUST_CURRENCIES) { DUST_MIN_AMOUNT } else { - minAmount.stripTrailingZeros() + minAmountTokenCurrency.multiply(tokenCryptoCurrencyStatus.value.fiatRate) } } diff --git a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyMinAmountUseCase.kt b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyMinAmountUseCase.kt index 501e6c74f5..ccb1f53f0d 100644 --- a/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyMinAmountUseCase.kt +++ b/domain/yield-supply/src/main/java/com/tangem/domain/yield/supply/usecase/YieldSupplyMinAmountUseCase.kt @@ -13,6 +13,14 @@ import com.tangem.domain.yield.supply.fixFee import java.math.BigDecimal import java.math.RoundingMode +/** + * Use case that calculates the minimum amount required for yield supply operations. + * + * The calculation is based on the estimated transaction fee converted to the token currency, + * with a buffer multiplier applied to account for fee fluctuations. + * + * @return [BigDecimal] minimum amount in token currency (not native/network currency) + */ class YieldSupplyMinAmountUseCase( private val feeRepository: FeeRepository, private val quotesRepository: QuotesRepository, diff --git a/domain/yield-supply/src/test/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetDustMinAmountUseCaseTest.kt b/domain/yield-supply/src/test/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetDustMinAmountUseCaseTest.kt index 50a00ac69c..39017ac168 100644 --- a/domain/yield-supply/src/test/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetDustMinAmountUseCaseTest.kt +++ b/domain/yield-supply/src/test/java/com/tangem/domain/yield/supply/usecase/YieldSupplyGetDustMinAmountUseCaseTest.kt @@ -2,6 +2,10 @@ package com.tangem.domain.yield.supply.usecase import com.google.common.truth.Truth.assertThat import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.models.currency.CryptoCurrency +import com.tangem.domain.models.currency.CryptoCurrencyStatus +import com.tangem.domain.models.network.Network +import com.tangem.domain.models.network.NetworkAddress import org.junit.jupiter.api.Test import java.math.BigDecimal @@ -13,19 +17,79 @@ class YieldSupplyGetDustMinAmountUseCaseTest { fun `GIVEN supported currency WHEN invoke THEN return dust min amount`() { val minAmount = BigDecimal("123.456") val appCurrency = AppCurrency(code = "EUR", name = "Euro", symbol = "€") + val tokenStatus = createTokenStatus(fiatRate = BigDecimal("2.0")) - val result = useCase(minAmount, appCurrency) + val result = useCase(minAmount, appCurrency, tokenStatus) assertThat(result).isEqualTo(BigDecimal("0.1")) } @Test - fun `GIVEN unsupported currency WHEN invoke THEN return min amount stripped`() { - val minAmount = BigDecimal("1.2300") + fun `GIVEN unsupported currency WHEN invoke THEN return min amount multiplied by fiat rate`() { + val minAmount = BigDecimal("1.23") + val fiatRate = BigDecimal("150.0") val appCurrency = AppCurrency(code = "JPY", name = "Japanese Yen", symbol = "¥") + val tokenStatus = createTokenStatus(fiatRate = fiatRate) - val result = useCase(minAmount, appCurrency) + val result = useCase(minAmount, appCurrency, tokenStatus) - assertThat(result).isEqualTo(BigDecimal("1.23")) + assertThat(result).isEqualTo(minAmount.multiply(fiatRate)) + } + + private fun createTokenStatus(fiatRate: BigDecimal): CryptoCurrencyStatus { + val network = createNetwork() + val token = createToken(network) + return CryptoCurrencyStatus( + currency = token, + value = CryptoCurrencyStatus.Loaded( + amount = BigDecimal.ZERO, + fiatAmount = BigDecimal.ZERO, + fiatRate = fiatRate, + priceChange = BigDecimal.ZERO, + yieldBalance = null, + yieldSupplyStatus = null, + hasCurrentNetworkTransactions = false, + pendingTransactions = emptySet(), + networkAddress = NetworkAddress.Single( + NetworkAddress.Address(value = "0xabc", type = NetworkAddress.Address.Type.Primary), + ), + sources = CryptoCurrencyStatus.Sources(), + ), + ) + } + + private fun createNetwork(): Network { + val derivationPath = Network.DerivationPath.None + return Network( + id = Network.ID(Network.RawID("polygon"), derivationPath), + backendId = "polygon", + name = "Polygon", + currencySymbol = "MATIC", + derivationPath = derivationPath, + isTestnet = false, + standardType = Network.StandardType.ERC20, + hasFiatFeeRate = false, + canHandleTokens = true, + transactionExtrasType = Network.TransactionExtrasType.NONE, + nameResolvingType = Network.NameResolvingType.ENS, + ) + } + + private fun createToken(network: Network): CryptoCurrency.Token { + val tokenId = CryptoCurrency.ID( + prefix = CryptoCurrency.ID.Prefix.TOKEN_PREFIX, + body = CryptoCurrency.ID.Body.NetworkId(network.rawId), + suffix = CryptoCurrency.ID.Suffix.RawID("test-token", "0xContract"), + ) + return CryptoCurrency.Token( + id = tokenId, + network = network, + name = "Test Token", + symbol = "TT", + decimals = 18, + iconUrl = null, + isCustom = false, + contractAddress = "0xContract", + ) } } \ No newline at end of file diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/active/model/YieldSupplyActiveModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/active/model/YieldSupplyActiveModel.kt index e18a49c84a..3c65576a24 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/active/model/YieldSupplyActiveModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/active/model/YieldSupplyActiveModel.kt @@ -242,7 +242,11 @@ internal class YieldSupplyActiveModel @Inject constructor( userWalletId, cryptoCurrencyStatusFlow.value, ).onRight { minAmount -> - val dustAmount = yieldSupplyGetDustMinAmountUseCase(minAmount = minAmount, appCurrency = appCurrency) + val dustAmount = yieldSupplyGetDustMinAmountUseCase( + minAmountTokenCurrency = minAmount, + appCurrency = appCurrency, + tokenCryptoCurrencyStatus = cryptoCurrencyStatusFlow.value, + ) uiState.update( YieldSupplyActiveMinAmountTransformer( cryptoCurrencyStatus = cryptoCurrencyStatusFlow.value, diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt index 9cd65e6cb7..c9e5d75c69 100644 --- a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt +++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/main/model/YieldSupplyModel.kt @@ -348,8 +348,9 @@ internal class YieldSupplyModel @Inject constructor( .getOrNull() if (minAmount != null) { val dustAmount = yieldSupplyGetDustMinAmountUseCase( - minAmount = minAmount, + minAmountTokenCurrency = minAmount, appCurrency = appCurrency, + tokenCryptoCurrencyStatus = cryptoCurrencyStatus, ) cryptoCurrencyStatus.shouldShowNotSuppliedNotification(dustAmount) } else {