Updated on 2026-08-14

This commit is contained in:
Tangem 2024-04-16 23:08:32 +05:00
parent f8b66b9637
commit 626e2764d3
2 changed files with 36 additions and 2 deletions

View file

@ -11,6 +11,8 @@ import java.util.Locale
private const val TEXT_CHUNK_THOUSAND = 3
private const val POINT_SEPARATOR = '.'
private const val COMMA_SEPARATOR = ','
const val DECIMAL_SEPARATOR_LIMIT = 1
@Composable
fun rememberDecimalFormat(): DecimalFormat {
@ -152,6 +154,37 @@ fun BigDecimal.parseBigDecimal(decimals: Int, roundingMode: RoundingMode = Round
}
}
/**
* Universal amount string parser to [BigDecimal]
* Able to parse values with only ONE separator, assuming separator is COMMA.
* Otherwise returns null.
*/
fun String.parseBigDecimalOrNull() = runCatching {
// Filtering value containing more than one either grouping or decimal separator.
// We assume there will be only decimal separator, otherwise parsing will fail.
if (count { !it.isDigit() } > DECIMAL_SEPARATOR_LIMIT) return null
// An attempt to parse value with POINT decimal separator
val parsed = this.toBigDecimalOrNull()
if (parsed == null) {
// If parsing with POINT separator fails trying to parse with COMMA separator
val decimalFormatSymbol = DecimalFormatSymbols().apply {
decimalSeparator = COMMA_SEPARATOR
}
val decimalFormat = DecimalFormat().apply {
decimalFormatSymbols = decimalFormatSymbol
isParseBigDecimal = true
}
// Return either number or null if fails
decimalFormat.parse(this) as? BigDecimal
} else {
// If parsing with POINT separator succeeds return number
parsed
}
}.getOrNull()
private fun Int.getWithIntegerDecimals(before: String, separator: Char, after: String): String = if (this == 0) {
before
} else {

View file

@ -1,6 +1,7 @@
package com.tangem.data.qrscanning.repository
import com.tangem.blockchain.common.Blockchain
import com.tangem.core.ui.utils.parseBigDecimalOrNull
import com.tangem.domain.qrscanning.models.QrResult
import com.tangem.domain.qrscanning.models.SourceType
import com.tangem.domain.qrscanning.repository.QrScanningEventsRepository
@ -44,7 +45,7 @@ internal class DefaultQrScanningEventsRepository : QrScanningEventsRepository {
when (it.key) {
Parameter.Amount -> {
// According to BIP-0021, the value is specified in decimals. No conversion needed
result.amount = it.value.toBigDecimalOrNull()
result.amount = it.value.parseBigDecimalOrNull()
}
Parameter.Message,
Parameter.Memo,
@ -69,7 +70,7 @@ internal class DefaultQrScanningEventsRepository : QrScanningEventsRepository {
-> {
// Extra convert parses scientific notation to decimal
// This is necessary to be able comparing BigDecimal values
result.amount = it.value.toBigDecimalOrNull()
result.amount = it.value.parseBigDecimalOrNull()
?.toPlainString()?.toBigDecimalOrNull()
?.divide(BigDecimal.TEN.pow(cryptoCurrency.decimals))
}