Keep "currency to Sats" empty when the BTC rate is, and whole-Sats only
Clearing the Manual rate cleared pricedCurrencyCodes but left rateDisplays stale, so "currency to Sats" kept showing a value computed from the old rate even after "BTC to currency" went empty. refresh()'s early-return path now clears rateDisplays too. oneCurrencyToSats() also now derives from defaultCurrencyRate() directly instead of re-reading rateDisplays independently, so the two rates structurally can't disagree about whether a rate is known, and formats to a whole number of Sats (0 decimals) instead of 2 — fractional Sats aren't a meaningful unit to show. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FXcrACM5sok3M1KQJ8kByy
This commit is contained in:
@@ -26,10 +26,14 @@ fun ConverterUiState.exceedsMaxSupply(): Boolean {
|
||||
fun ConverterUiState.defaultCurrencyRate(): String =
|
||||
rateDisplays[defaultCurrencyCode]?.takeIf { it.isNotEmpty() } ?: ""
|
||||
|
||||
/** The current "1 [ConverterUiState.defaultCurrencyCode] = ? Sats" rate, as a plain number. */
|
||||
/**
|
||||
* The current "1 [ConverterUiState.defaultCurrencyCode] = ? Sats" rate, as a whole (never
|
||||
* fractional) number of Sats — empty whenever [defaultCurrencyRate] is, so the two rates never
|
||||
* disagree about whether a rate is currently known.
|
||||
*/
|
||||
fun ConverterUiState.oneCurrencyToSats(): String {
|
||||
val rate = rateDisplays[defaultCurrencyCode]?.toBigDecimalOrNull() ?: return ""
|
||||
return CurrencyConverter.satsPerCurrencyUnit(rate)?.let { formatAmount(it, 2) } ?: ""
|
||||
val rate = defaultCurrencyRate().toBigDecimalOrNull() ?: return ""
|
||||
return CurrencyConverter.satsPerCurrencyUnit(rate)?.let { formatAmount(it, 0) } ?: ""
|
||||
}
|
||||
|
||||
/** The pinned, non-removable "Current Currency" shown in the currency picker's own section. */
|
||||
|
||||
@@ -143,10 +143,16 @@ class PriceViewModel(
|
||||
fun refresh() {
|
||||
if (currentSource === manualSource && manualSource.rate == null) {
|
||||
// No rate typed in (yet): nothing to price fiat currencies with, so clear any stale
|
||||
// rate this might otherwise still compute fiat amounts from.
|
||||
// rate this might otherwise still compute fiat amounts (or the derived "currency to
|
||||
// Sats" rate) from.
|
||||
rates = null
|
||||
_uiState.update {
|
||||
it.copy(isLoading = false, errorMessage = null, pricedCurrencyCodes = emptySet())
|
||||
it.copy(
|
||||
isLoading = false,
|
||||
errorMessage = null,
|
||||
pricedCurrencyCodes = emptySet(),
|
||||
rateDisplays = emptyMap(),
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package xyz.tyiu.satsprice.ui
|
||||
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class ConverterUiStateDisplayTest {
|
||||
|
||||
@Test
|
||||
fun oneCurrencyToSats_isInverseOfTheBtcRate() {
|
||||
val state = ConverterUiState(defaultCurrencyCode = "USD", rateDisplays = mapOf("USD" to "50000.00"))
|
||||
|
||||
// 1 BTC = 50,000 USD, so 1 USD is worth 100,000,000 / 50,000 = 2,000 Sats.
|
||||
assertEquals("2000", state.oneCurrencyToSats())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun oneCurrencyToSats_roundsToAWholeNumberOfSats() {
|
||||
// 1 BTC = 78,293.19 USD, so 1 USD is worth ~1,277.24 Sats — never shown fractionally.
|
||||
val state = ConverterUiState(defaultCurrencyCode = "USD", rateDisplays = mapOf("USD" to "78293.19"))
|
||||
|
||||
assertEquals("1277", state.oneCurrencyToSats())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun oneCurrencyToSats_isEmptyWheneverDefaultCurrencyRateIs() {
|
||||
// No rate for the default currency at all (e.g. Manual with nothing typed in yet).
|
||||
val noRate = ConverterUiState(defaultCurrencyCode = "USD", rateDisplays = emptyMap())
|
||||
assertEquals("", noRate.defaultCurrencyRate())
|
||||
assertEquals("", noRate.oneCurrencyToSats())
|
||||
|
||||
// A rate is known, just not for the default currency.
|
||||
val otherCurrencyOnly = ConverterUiState(defaultCurrencyCode = "USD", rateDisplays = mapOf("EUR" to "45000"))
|
||||
assertEquals("", otherCurrencyOnly.defaultCurrencyRate())
|
||||
assertEquals("", otherCurrencyOnly.oneCurrencyToSats())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user