Exclude withdrawn currencies from the picker, keep precious metals

Currency.getAvailableCurrencies() (JVM/Android) and NSLocale.ISOCurrencyCodes
(iOS/macOS) return every ISO 4217 code the platform has ever known about —
withdrawn currencies like the Deutsche Mark and French Franc, and test/
placeholder codes (XTS, XXX), included. Measured on the JVM: 232 total
codes, only 156 still assigned to a country.

Filters the list down to currencies actually assigned to an ISO country
today, which drops the withdrawn ones without needing a maintained
exclusion list. Precious metals (XAU, XAG, XPD, XPT) are added back in
since they're still actively traded despite not being tied to any country.
Web is left unfiltered — there's no reliable country-to-currency API there.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QpjMKWGoiT5aJBzhxvXkwp
This commit is contained in:
2026-09-08 17:20:09 +03:00
co-authored by Claude Sonnet 5
parent b0f3744851
commit 323ca43472
5 changed files with 89 additions and 0 deletions
@@ -5,9 +5,27 @@ import java.util.Locale
actual fun systemCurrencies(): List<CurrencyInfo> =
Currency.getAvailableCurrencies()
.filter { it.currencyCode in currentlyUsedCurrencyCodes() }
.map { CurrencyInfo(it.currencyCode, it.getDisplayName(Locale.getDefault())) }
.sortedBy { it.code }
/**
* `Currency.getAvailableCurrencies()` includes every ISO 4217 code the JDK has ever known about —
* historical currencies (Deutsche Mark, French Franc, ...) and test/placeholder codes (XTS, XXX)
* included. The currency currently assigned to each ISO country is a reliable proxy for "still in
* use" without needing a maintained exclusion list; precious metals are added back in since
* they're actively traded but aren't tied to any country.
*/
@Suppress("DEPRECATION") // Locale(language, country) still works fine; Locale.of() needs newer Android API levels.
private fun currentlyUsedCurrencyCodes(): Set<String> =
Locale.getISOCountries().mapNotNullTo(mutableSetOf()) { country ->
try {
Currency.getInstance(Locale("", country))?.currencyCode
} catch (e: IllegalArgumentException) {
null
}
} + PRECIOUS_METAL_CURRENCY_CODES
actual fun localeCurrencyCode(): String? = try {
Currency.getInstance(Locale.getDefault())?.currencyCode
} catch (e: IllegalArgumentException) {