Fix mob stringification in backups.
Co-authored-by: Greyson Parrelli <greyson@signal.org>
This commit is contained in:
parent
335fcd72f3
commit
38f31528ff
@ -852,8 +852,8 @@ private fun BackupMessageRecord.toRemotePaymentNotificationUpdate(db: SignalData
|
||||
PaymentNotification()
|
||||
} else {
|
||||
PaymentNotification(
|
||||
amountMob = payment.amount.serializeAmountString(),
|
||||
feeMob = payment.fee.serializeAmountString(),
|
||||
amountMob = payment.amount.requireMobileCoin().amountDecimalString,
|
||||
feeMob = payment.fee.requireMobileCoin().amountDecimalString,
|
||||
note = payment.note.takeUnless { it.isEmpty() },
|
||||
transactionDetails = payment.toRemoteTransactionDetails()
|
||||
)
|
||||
|
||||
@ -60,7 +60,6 @@ import org.thoughtcrime.securesms.database.documents.NetworkFailureSet
|
||||
import org.thoughtcrime.securesms.database.model.GroupCallUpdateDetailsUtil
|
||||
import org.thoughtcrime.securesms.database.model.Mention
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.CryptoValue
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GV2UpdateDescription
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.MessageExtras
|
||||
@ -85,7 +84,7 @@ import org.thoughtcrime.securesms.util.Environment
|
||||
import org.thoughtcrime.securesms.util.MessageUtil
|
||||
import org.whispersystems.signalservice.api.payments.Money
|
||||
import org.whispersystems.signalservice.internal.push.DataMessage
|
||||
import java.math.BigInteger
|
||||
import java.math.BigDecimal
|
||||
import java.sql.SQLException
|
||||
import java.util.Optional
|
||||
import java.util.UUID
|
||||
@ -1064,8 +1063,8 @@ class ChatItemArchiveImporter(
|
||||
|
||||
private fun ContentValues.addPaymentTombstoneNoMetadata(paymentNotification: PaymentNotification) {
|
||||
put(MessageTable.TYPE, getAsLong(MessageTable.TYPE) or MessageTypes.SPECIAL_TYPE_PAYMENTS_TOMBSTONE)
|
||||
val amount = tryParseCryptoValue(paymentNotification.amountMob)
|
||||
val fee = tryParseCryptoValue(paymentNotification.feeMob)
|
||||
val amount = paymentNotification.amountMob?.tryParseMoney()?.let { CryptoValueUtil.moneyToCryptoValue(it) }
|
||||
val fee = paymentNotification.feeMob?.tryParseMoney()?.let { CryptoValueUtil.moneyToCryptoValue(it) }
|
||||
put(
|
||||
MessageTable.MESSAGE_EXTRAS,
|
||||
MessageExtras(
|
||||
@ -1119,26 +1118,15 @@ class ChatItemArchiveImporter(
|
||||
return null
|
||||
}
|
||||
|
||||
val amountCryptoValue = tryParseCryptoValue(this)
|
||||
return if (amountCryptoValue != null) {
|
||||
CryptoValueUtil.cryptoValueToMoney(amountCryptoValue)
|
||||
} else {
|
||||
return try {
|
||||
Money.mobileCoin(BigDecimal(this))
|
||||
} catch (e: NumberFormatException) {
|
||||
null
|
||||
} catch (e: ArithmeticException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryParseCryptoValue(bigIntegerString: String?): CryptoValue? {
|
||||
if (bigIntegerString == null) {
|
||||
return null
|
||||
}
|
||||
val amount = try {
|
||||
BigInteger(bigIntegerString).toString()
|
||||
} catch (e: NumberFormatException) {
|
||||
return null
|
||||
}
|
||||
return CryptoValue(mobileCoinValue = CryptoValue.MobileCoinValue(picoMobileCoin = amount))
|
||||
}
|
||||
|
||||
private fun ContentValues.addQuote(quote: Quote) {
|
||||
this.put(MessageTable.QUOTE_ID, quote.targetSentTimestamp ?: MessageTable.QUOTE_TARGET_MISSING_ID)
|
||||
this.put(MessageTable.QUOTE_AUTHOR, importState.requireLocalRecipientId(quote.authorId).serialize())
|
||||
|
||||
@ -208,10 +208,10 @@ public abstract class Money {
|
||||
}
|
||||
|
||||
/**
|
||||
* The value expressed in Mobile coin.
|
||||
* The value expressed in Mobile coin as a plain decimal string (never scientific notation).
|
||||
*/
|
||||
public String getAmountDecimalString() {
|
||||
return amountDecimal.toString();
|
||||
return amountDecimal.toPlainString();
|
||||
}
|
||||
|
||||
public boolean greaterThan(MobileCoin other) {
|
||||
|
||||
@ -52,6 +52,29 @@ public final class MoneyTest_MobileCoin {
|
||||
assertEquals("-1000.32456", mobileCoin.getAmountDecimalString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toAmountString_format_roundValuesUsePlainDecimalNotScientificNotation() {
|
||||
assertEquals("1", Money.mobileCoin(new BigDecimal("1")).getAmountDecimalString());
|
||||
assertEquals("10", Money.mobileCoin(new BigDecimal("10")).getAmountDecimalString());
|
||||
assertEquals("1000", Money.mobileCoin(new BigDecimal("1000")).getAmountDecimalString());
|
||||
assertEquals("0.001", Money.mobileCoin(new BigDecimal("0.001")).getAmountDecimalString());
|
||||
assertEquals("1234.5", Money.mobileCoin(new BigDecimal("1234.50")).getAmountDecimalString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void backupSerialization_decimalStringRoundTrips() {
|
||||
// Mirrors how backup v2 encodes (getAmountDecimalString) and decodes (Money.mobileCoin(BigDecimal)) payment amounts.
|
||||
String[] amounts = { "1", "10", "1000", "0.001", "1.00001", "1234.5", "1234567.890987654321" };
|
||||
for (String amount : amounts) {
|
||||
Money.MobileCoin original = Money.mobileCoin(new BigDecimal(amount));
|
||||
String encoded = original.getAmountDecimalString();
|
||||
Money.MobileCoin decoded = Money.mobileCoin(new BigDecimal(encoded));
|
||||
|
||||
assertEquals(original, decoded);
|
||||
assertEquals(encoded, decoded.getAmountDecimalString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void currency() {
|
||||
Money mobileCoin = Money.mobileCoin(BigDecimal.valueOf(-1000.32456));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user