From ce27818f437963b441c9d15706e61217c38b08e2 Mon Sep 17 00:00:00 2001
From: woodser <13068859+woodser@users.noreply.github.com>
Date: Thu, 20 Mar 2025 08:02:01 -0400
Subject: [PATCH] recover payment sent message state on startup if undefined

---
 .../main/java/haveno/core/trade/Trade.java    | 29 +++++++++++++++++++
 .../pendingtrades/PendingTradesViewModel.java |  2 +-
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/core/src/main/java/haveno/core/trade/Trade.java b/core/src/main/java/haveno/core/trade/Trade.java
index eaec78a6b0..114edcabe5 100644
--- a/core/src/main/java/haveno/core/trade/Trade.java
+++ b/core/src/main/java/haveno/core/trade/Trade.java
@@ -46,6 +46,7 @@ import haveno.common.taskrunner.Model;
 import haveno.common.util.Utilities;
 import haveno.core.monetary.Price;
 import haveno.core.monetary.Volume;
+import haveno.core.network.MessageState;
 import haveno.core.offer.Offer;
 import haveno.core.offer.OfferDirection;
 import haveno.core.offer.OpenOffer;
@@ -738,6 +739,15 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
             xmrWalletService.addWalletListener(idlePayoutSyncer);
         }
 
+        // TODO: buyer's payment sent message state property became unsynced if shut down while awaiting ack from seller. fixed mismatch in v1.0.19, but can this check can be removed?
+        if (isBuyer()) {
+            MessageState expectedState = getPaymentSentMessageState();
+            if (expectedState != null && expectedState != getSeller().getPaymentSentMessageStateProperty().get()) {
+                log.warn("Updating unexpected payment sent message state for {} {}, expected={}, actual={}", getClass().getSimpleName(), getId(), expectedState, processModel.getPaymentSentMessageStatePropertySeller().get());
+                getSeller().getPaymentSentMessageStateProperty().set(expectedState);
+            }
+        }
+
         // handle confirmations
         walletHeight.addListener((observable, oldValue, newValue) -> {
             importMultisigHexIfScheduled();
@@ -2074,6 +2084,25 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
         throw new IllegalArgumentException("Trade is not buyer, seller, or arbitrator");
     }
 
+    private MessageState getPaymentSentMessageState() {
+        if (isPaymentReceived()) return MessageState.ACKNOWLEDGED;
+        if (getSeller().getPaymentSentMessageStateProperty().get() == MessageState.ACKNOWLEDGED) return MessageState.ACKNOWLEDGED;
+        switch (state) {
+            case BUYER_SENT_PAYMENT_SENT_MSG:
+                return MessageState.SENT;
+            case BUYER_SAW_ARRIVED_PAYMENT_SENT_MSG:
+                return MessageState.ARRIVED;
+            case BUYER_STORED_IN_MAILBOX_PAYMENT_SENT_MSG:
+                return MessageState.STORED_IN_MAILBOX;
+            case SELLER_RECEIVED_PAYMENT_SENT_MSG:
+                return MessageState.ACKNOWLEDGED;
+            case BUYER_SEND_FAILED_PAYMENT_SENT_MSG:
+                return MessageState.FAILED;
+            default:
+                return null;
+        }
+    }
+
     public String getPeerRole(TradePeer peer) {
         if (peer == getBuyer()) return "Buyer";
         if (peer == getSeller()) return "Seller";
diff --git a/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java b/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java
index 1db4d944c0..6a34504dad 100644
--- a/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java
+++ b/desktop/src/main/java/haveno/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java
@@ -424,7 +424,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
                 }
                 break;
 
-            // seller step 3
+            // seller step 3 or 4 if published
             case SELLER_CONFIRMED_PAYMENT_RECEIPT:
             case SELLER_SEND_FAILED_PAYMENT_RECEIVED_MSG:
             case SELLER_STORED_IN_MAILBOX_PAYMENT_RECEIVED_MSG: