diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/ChatItemExportIterator.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/ChatItemExportIterator.kt index edf341a15c..07041f1f62 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/ChatItemExportIterator.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/ChatItemExportIterator.kt @@ -503,7 +503,7 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize: PaymentNotification( amountMob = payment.amount.serializeAmountString(), feeMob = payment.fee.serializeAmountString(), - note = payment.note, + note = payment.note.takeUnless { it.isEmpty() }, transactionDetails = payment.getTransactionDetails() ) } @@ -789,16 +789,18 @@ class ChatItemExportIterator(private val cursor: Cursor, private val batchSize: } private fun PaymentTable.PaymentTransaction.getTransactionDetails(): PaymentNotification.TransactionDetails? { - if (failureReason != null || state == State.FAILED) { - return PaymentNotification.TransactionDetails(failedTransaction = PaymentNotification.TransactionDetails.FailedTransaction(reason = failureReason.toBackupFailureReason())) + if (this.failureReason != null || this.state == State.FAILED) { + return PaymentNotification.TransactionDetails(failedTransaction = PaymentNotification.TransactionDetails.FailedTransaction(reason = this.failureReason.toBackupFailureReason())) } return PaymentNotification.TransactionDetails( transaction = PaymentNotification.TransactionDetails.Transaction( status = this.state.toBackupState(), - timestamp = timestamp, - blockIndex = blockIndex, - blockTimestamp = blockTimestamp, - mobileCoinIdentification = paymentMetaData.mobileCoinTxoIdentification?.toBackup() + timestamp = this.timestamp, + blockIndex = this.blockIndex, + blockTimestamp = this.blockTimestamp, + mobileCoinIdentification = this.paymentMetaData.mobileCoinTxoIdentification?.toBackup(), + transaction = this.transaction?.toByteString(), + receipt = this.receipt?.toByteString() ) ) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/ChatItemImportInserter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/ChatItemImportInserter.kt index 57c4e56913..e214dbfb72 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/ChatItemImportInserter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/database/ChatItemImportInserter.kt @@ -62,6 +62,7 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.ThreadMergeEvent import org.thoughtcrime.securesms.mms.QuoteModel import org.thoughtcrime.securesms.payments.CryptoValueUtil import org.thoughtcrime.securesms.payments.Direction +import org.thoughtcrime.securesms.payments.FailureReason import org.thoughtcrime.securesms.payments.State import org.thoughtcrime.securesms.payments.proto.PaymentMetaData import org.thoughtcrime.securesms.profiles.ProfileName @@ -494,6 +495,7 @@ class ChatItemImportInserter( chatRecipientId, transaction.timestamp ?: 0, transaction.blockIndex ?: 0, + transaction.blockTimestamp ?: 0, paymentNotification.note ?: "", if (chatItem.outgoing != null) Direction.SENT else Direction.RECEIVED, transaction.status.toLocalStatus(), @@ -502,7 +504,8 @@ class ChatItemImportInserter( transaction.transaction?.toByteArray(), transaction.receipt?.toByteArray(), mobileCoinIdentification, - chatItem.incoming?.read ?: true + chatItem.incoming?.read ?: true, + null ) } @@ -710,17 +713,17 @@ class ChatItemImportInserter( private fun ContentValues.addPaymentNotification(chatItem: ChatItem, chatRecipientId: RecipientId) { val paymentNotification = chatItem.paymentNotification!! if (chatItem.paymentNotification.amountMob.isNullOrEmpty()) { - addPaymentTombstoneNoAmount() + this.addPaymentTombstoneNoAmount() return } - val amount = paymentNotification.amountMob?.tryParseMoney() ?: return addPaymentTombstoneNoAmount() - val fee = paymentNotification.feeMob?.tryParseMoney() ?: return addPaymentTombstoneNoAmount() + val amount = paymentNotification.amountMob?.tryParseMoney() ?: return this.addPaymentTombstoneNoAmount() + val fee = paymentNotification.feeMob?.tryParseMoney() ?: return this.addPaymentTombstoneNoAmount() if (chatItem.paymentNotification.transactionDetails?.failedTransaction != null) { - addFailedPaymentNotification(chatItem, amount, fee, chatRecipientId) + this.addFailedPaymentNotification(chatItem, amount, fee, chatRecipientId) return } - addPaymentTombstoneNoMetadata(chatItem.paymentNotification) + this.addPaymentTombstoneNoMetadata(chatItem.paymentNotification) } private fun PaymentNotification.TransactionDetails.MobileCoinTxoIdentification.toLocal(): PaymentMetaData { @@ -737,6 +740,7 @@ class ChatItemImportInserter( chatRecipientId, 0, 0, + 0, chatItem.paymentNotification?.note ?: "", if (chatItem.outgoing != null) Direction.SENT else Direction.RECEIVED, State.FAILED, @@ -745,7 +749,8 @@ class ChatItemImportInserter( null, null, null, - chatItem.incoming?.read ?: true + chatItem.incoming?.read ?: true, + chatItem.paymentNotification?.transactionDetails?.failedTransaction?.reason?.toLocalPaymentFailureReason() ) if (uuid != null) { put(MessageTable.BODY, uuid.toString()) @@ -755,6 +760,14 @@ class ChatItemImportInserter( } } + private fun PaymentNotification.TransactionDetails.FailedTransaction.FailureReason.toLocalPaymentFailureReason(): FailureReason { + return when (this) { + PaymentNotification.TransactionDetails.FailedTransaction.FailureReason.GENERIC -> FailureReason.UNKNOWN + PaymentNotification.TransactionDetails.FailedTransaction.FailureReason.NETWORK -> FailureReason.NETWORK + PaymentNotification.TransactionDetails.FailedTransaction.FailureReason.INSUFFICIENT_FUNDS -> FailureReason.INSUFFICIENT_FUNDS + } + } + private fun ContentValues.addPaymentTombstoneNoAmount() { put(MessageTable.TYPE, getAsLong(MessageTable.TYPE) or MessageTypes.SPECIAL_TYPE_PAYMENTS_TOMBSTONE) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/PaymentTable.java b/app/src/main/java/org/thoughtcrime/securesms/database/PaymentTable.java index 2e4cb1ed89..9c11d1fed2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/PaymentTable.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/PaymentTable.java @@ -186,6 +186,7 @@ public final class PaymentTable extends DatabaseTable implements RecipientIdData public UUID restoreFromBackup(@NonNull RecipientId recipientId, long timestamp, long blockIndex, + long blockTimestamp, @NonNull String note, @NonNull Direction direction, @NonNull State state, @@ -194,10 +195,16 @@ public final class PaymentTable extends DatabaseTable implements RecipientIdData @Nullable byte[] transaction, @Nullable byte[] receipt, @Nullable PaymentMetaData metaData, - boolean seen) { + boolean seen, + @Nullable FailureReason failureReason) + { UUID uuid = UUID.randomUUID(); try { create(uuid, recipientId, null, timestamp, blockIndex, note, direction, state, amount, fee, transaction, receipt, metaData, seen); + updateBlockDetails(uuid, blockIndex, blockTimestamp); + if (failureReason != null) { + markPaymentFailed(uuid, failureReason); + } } catch (SerializationException | PublicKeyConflictException e) { return null; } @@ -619,13 +626,20 @@ public final class PaymentTable extends DatabaseTable implements RecipientIdData } private static @NonNull PaymentTransaction readPayment(@NonNull Cursor cursor) { + State state = State.deserialize(CursorUtil.requireInt(cursor, STATE)); + FailureReason failureReason = null; + + if (state == State.FAILED) { + failureReason = FailureReason.deserialize(CursorUtil.requireInt(cursor, FAILURE)); + } + return new PaymentTransaction(UUID.fromString(CursorUtil.requireString(cursor, PAYMENT_UUID)), getRecipientId(cursor), MobileCoinPublicAddress.fromBase58NullableOrThrow(CursorUtil.requireString(cursor, ADDRESS)), CursorUtil.requireLong(cursor, TIMESTAMP), Direction.deserialize(CursorUtil.requireInt(cursor, DIRECTION)), - State.deserialize(CursorUtil.requireInt(cursor, STATE)), - FailureReason.deserialize(CursorUtil.requireInt(cursor, FAILURE)), + state, + failureReason, CursorUtil.requireString(cursor, NOTE), getMoneyValue(CursorUtil.requireBlob(cursor, AMOUNT)), getMoneyValue(CursorUtil.requireBlob(cursor, FEE)),