diff --git a/services/opencode/src/main/kotlin/com/getcode/opencode/internal/exchange/RealVerifiedFiatCalculator.kt b/services/opencode/src/main/kotlin/com/getcode/opencode/internal/exchange/RealVerifiedFiatCalculator.kt index 3227bef7d..2eda845e6 100644 --- a/services/opencode/src/main/kotlin/com/getcode/opencode/internal/exchange/RealVerifiedFiatCalculator.kt +++ b/services/opencode/src/main/kotlin/com/getcode/opencode/internal/exchange/RealVerifiedFiatCalculator.kt @@ -114,7 +114,6 @@ internal class RealVerifiedFiatCalculator @Inject constructor( val underlyingTokenAmount = Fiat(quarks = quarks.toLong(), currencyCode = CurrencyCode.USD) val sellEstimate = Fiat.tokenBalance(quarks.toLong(), token, supply).convertingTo(rate) - if (!sellEstimate.hasDisplayableValue) { return Result.failure(ComputeVerifiedFiatError.AmountBelowMinimum()) } diff --git a/services/opencode/src/main/kotlin/com/getcode/opencode/model/financial/Fiat.kt b/services/opencode/src/main/kotlin/com/getcode/opencode/model/financial/Fiat.kt index 482dd0b1a..184d288fc 100644 --- a/services/opencode/src/main/kotlin/com/getcode/opencode/model/financial/Fiat.kt +++ b/services/opencode/src/main/kotlin/com/getcode/opencode/model/financial/Fiat.kt @@ -163,7 +163,7 @@ data class Fiat( /** Whether this value would format as non-zero in its currency. */ val hasDisplayableValue: Boolean - get() = this >= smallestUnit + get() = rounded(currencyCode.fractionDigits) >= smallestUnit fun valueLessThan(other: Fiat): Boolean = toDouble() < other.toDouble() fun valueGreaterThan(other: Fiat): Boolean = toDouble() > other.toDouble() diff --git a/services/opencode/src/test/kotlin/com/getcode/opencode/internal/exchange/RealVerifiedFiatCalculatorTest.kt b/services/opencode/src/test/kotlin/com/getcode/opencode/internal/exchange/RealVerifiedFiatCalculatorTest.kt index 5abf381bf..88c4aff5a 100644 --- a/services/opencode/src/test/kotlin/com/getcode/opencode/internal/exchange/RealVerifiedFiatCalculatorTest.kt +++ b/services/opencode/src/test/kotlin/com/getcode/opencode/internal/exchange/RealVerifiedFiatCalculatorTest.kt @@ -420,6 +420,27 @@ class RealVerifiedFiatCalculatorTest { assertIs(result.exceptionOrNull()) } + @Test + fun `one cent USD succeeds for established token`() = runTest { + // Regression: $0.01 USD on a high-supply (established) bonding-curve token + // would fail with AmountBelowMinimum due to round-trip precision loss through + // the bonding curve. The sell estimate quarks (e.g. 9987) fell just below the + // smallestUnit (10000) before rounding, even though formatted() shows "$0.01". + val supply = 50_000_000_000_000L // established token with high supply + val token = bondingCurveToken(supply = supply) + stubVerifiedState(CurrencyCode.USD, testMint, supply) + + val result = calculator.compute( + amount = Fiat(fiat = 0.01, currencyCode = CurrencyCode.USD), + token = token, + rate = Rate.oneToOne, + trace = false, + ) + + assertTrue(result.isSuccess, "Expected success but got: ${result.exceptionOrNull()}") + assertTrue(result.getOrThrow().localFiat.underlyingTokenAmount.quarks > 0) + } + // endregion // region helpers