Updated on 2026-08-14

This commit is contained in:
Tangem 2025-12-29 14:59:20 +04:00
parent e2ebacba76
commit 3b556e261d
2 changed files with 73 additions and 3 deletions

View file

@ -102,14 +102,16 @@ class YieldSupplyGetRewardsBalanceUseCase(
}.flowOn(dispatcherProvider.default)
private fun calculateMinVisibleDecimals(perTickDeltaAbs: BigDecimal, maxDecimals: Int): Int {
if (perTickDeltaAbs <= BigDecimal.ZERO) return MIN_DECIMALS
val effectiveMin = MIN_DECIMALS.coerceAtMost(maxDecimals)
if (perTickDeltaAbs <= BigDecimal.ZERO) return effectiveMin
val perTickAsDouble = perTickDeltaAbs.toDouble()
if (perTickAsDouble.isNaN() || perTickAsDouble.isInfinite()) return MIN_DECIMALS
if (perTickAsDouble.isNaN() || perTickAsDouble.isInfinite()) return effectiveMin
val safe = if (perTickAsDouble <= 0.0) EPSILON else perTickAsDouble
val raw = ceil(-ln(safe) / LN_10)
return raw.toInt().coerceIn(MIN_DECIMALS, maxDecimals)
return raw.toInt().coerceIn(effectiveMin, maxDecimals)
}
private fun perTickDelta(amount: BigDecimal, apyFraction: BigDecimal): BigDecimal {

View file

@ -459,4 +459,72 @@ class YieldSupplyGetRewardsBalanceUseCaseTest {
YieldSupplyGetRewardsBalanceUseCase.FIAT_MAX_DECIMALS,
)
}
@Test
fun `GIVEN token with decimals less than MIN_DECIMALS WHEN invoke THEN does not crash`() = runTest {
val network = createNetwork()
val tokenId = CryptoCurrency.ID(
prefix = CryptoCurrency.ID.Prefix.TOKEN_PREFIX,
body = CryptoCurrency.ID.Body.NetworkId(network.rawId),
suffix = CryptoCurrency.ID.Suffix.RawID("low-decimals-token", "0xLowDecimals"),
)
val tokenWithLowDecimals = CryptoCurrency.Token(
id = tokenId,
network = network,
name = "Low Decimals Token",
symbol = "LDT",
decimals = 0,
iconUrl = null,
isCustom = false,
contractAddress = "0xLowDecimals",
)
val amount = BigDecimal("100.00")
val apy = BigDecimal("10.0")
val status = CryptoCurrencyStatus(
currency = tokenWithLowDecimals,
value = CryptoCurrencyStatus.Custom(
amount = amount,
fiatAmount = null,
fiatRate = BigDecimal.ONE,
priceChange = null,
yieldBalance = null,
yieldSupplyStatus = null,
hasCurrentNetworkTransactions = false,
pendingTransactions = emptySet(),
networkAddress = NetworkAddress.Single(
NetworkAddress.Address(value = "0xabc", type = NetworkAddress.Address.Type.Primary),
),
sources = CryptoCurrencyStatus.Sources(),
),
)
coEvery { repository.getCachedMarkets() } returns listOf(
YieldMarketToken(
tokenAddress = tokenWithLowDecimals.contractAddress,
chainId = 1,
apy = apy,
isActive = true,
maxFeeNative = BigDecimal.ZERO,
maxFeeUSD = BigDecimal.ZERO,
backendId = "id",
),
)
val dispatcherProvider = testDispatcherProvider(this)
val useCase = YieldSupplyGetRewardsBalanceUseCase(repository, dispatcherProvider)
val appCurrency = AppCurrency.Default
val deferred = async { useCase(status, appCurrency).take(2).toList() }
testScheduler.advanceUntilIdle()
advanceTimeBy(TICK_MILLIS)
testScheduler.advanceUntilIdle()
val emissions = deferred.await()
assertThat(emissions).hasSize(2)
assertThat(emissions[0].cryptoBalance).isNotNull()
assertThat(emissions[1].cryptoBalance).isNotNull()
}
}