recover from payment received message not processed

This commit is contained in:
woodser 2024-07-16 12:22:12 -04:00
parent 1c381de806
commit 33bf54bcac
4 changed files with 41 additions and 27 deletions

View file

@ -490,7 +490,6 @@ public abstract class Trade implements Tradable, Model {
private Long payoutHeight;
private IdlePayoutSyncer idlePayoutSyncer;
@Getter
@Setter
private boolean isCompleted;
///////////////////////////////////////////////////////////////////////////////////////////
@ -614,8 +613,8 @@ public abstract class Trade implements Tradable, Model {
public void initialize(ProcessModelServiceProvider serviceProvider) {
if (isInitialized) throw new IllegalStateException(getClass().getSimpleName() + " " + getId() + " is already initialized");
// done if payout unlocked
if (isPayoutUnlocked()) {
// done if payout unlocked and marked complete
if (isPayoutUnlocked() && isCompleted()) {
clearAndShutDown();
return;
}
@ -679,13 +678,12 @@ public abstract class Trade implements Tradable, Model {
log.info("Payout published for {} {}", getClass().getSimpleName(), getId());
// sync main wallet to update pending balance
if (!isPayoutConfirmed()) {
new Thread(() -> {
HavenoUtils.waitFor(1000);
if (isShutDownStarted) return;
if (xmrConnectionService.isConnected()) syncAndPollWallet();
}).start();
}
ThreadUtils.submitToPool(() -> {
HavenoUtils.waitFor(1000);
if (isPayoutConfirmed()) return;
if (isShutDownStarted) return;
if (xmrConnectionService.isConnected()) syncAndPollWallet();
});
// complete disputed trade
if (getDisputeState().isArbitrated() && !getDisputeState().isClosed()) {
@ -707,7 +705,8 @@ public abstract class Trade implements Tradable, Model {
if (newValue == Trade.PayoutState.PAYOUT_UNLOCKED) {
if (!isInitialized) return;
log.info("Payout unlocked for {} {}, deleting multisig wallet", getClass().getSimpleName(), getId());
clearAndShutDown();
if (isCompleted()) clearAndShutDown();
else deleteWallet();
}
});
});
@ -790,6 +789,11 @@ public abstract class Trade implements Tradable, Model {
return getArbitrator() == null ? null : getArbitrator().getNodeAddress();
}
public void setCompleted(boolean completed) {
this.isCompleted = completed;
if (isPayoutUnlocked()) clearAndShutDown();
}
///////////////////////////////////////////////////////////////////////////////////////////
// WALLET MANAGEMENT
///////////////////////////////////////////////////////////////////////////////////////////
@ -996,7 +1000,11 @@ public abstract class Trade implements Tradable, Model {
private void forceCloseWallet() {
if (wallet != null) {
xmrWalletService.forceCloseWallet(wallet, wallet.getPath());
try {
xmrWalletService.forceCloseWallet(wallet, wallet.getPath());
} catch (Exception e) {
log.warn("Error force closing wallet for {} {}: {}", getClass().getSimpleName(), getId(), e.getMessage());
}
stopPolling();
wallet = null;
}

View file

@ -296,7 +296,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
}
public void handleInitMultisigRequest(InitMultisigRequest request, NodeAddress sender) {
System.out.println(getClass().getSimpleName() + ".handleInitMultisigRequest()");
System.out.println(getClass().getSimpleName() + ".handleInitMultisigRequest() for " + trade.getClass().getSimpleName() + " " + trade.getShortId());
trade.addInitProgressStep();
ThreadUtils.execute(() -> {
synchronized (trade) {
@ -333,7 +333,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
}
public void handleSignContractRequest(SignContractRequest message, NodeAddress sender) {
System.out.println(getClass().getSimpleName() + ".handleSignContractRequest() " + trade.getId());
System.out.println(getClass().getSimpleName() + ".handleSignContractRequest() for " + trade.getClass().getSimpleName() + " " + trade.getShortId());
ThreadUtils.execute(() -> {
synchronized (trade) {
@ -376,7 +376,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
}
public void handleSignContractResponse(SignContractResponse message, NodeAddress sender) {
System.out.println(getClass().getSimpleName() + ".handleSignContractResponse() " + trade.getId());
System.out.println(getClass().getSimpleName() + ".handleSignContractResponse() for " + trade.getClass().getSimpleName() + " " + trade.getShortId());
trade.addInitProgressStep();
ThreadUtils.execute(() -> {
synchronized (trade) {
@ -422,7 +422,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
}
public void handleDepositResponse(DepositResponse response, NodeAddress sender) {
System.out.println(getClass().getSimpleName() + ".handleDepositResponse()");
System.out.println(getClass().getSimpleName() + ".handleDepositResponse() for " + trade.getClass().getSimpleName() + " " + trade.getShortId());
trade.addInitProgressStep();
ThreadUtils.execute(() -> {
synchronized (trade) {
@ -452,7 +452,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
}
public void handle(DepositsConfirmedMessage message, NodeAddress sender) {
System.out.println(getClass().getSimpleName() + ".handle(DepositsConfirmedMessage) from " + sender);
System.out.println(getClass().getSimpleName() + ".handle(DepositsConfirmedMessage) from " + sender + " for " + trade.getClass().getSimpleName() + " " + trade.getShortId());
if (!trade.isInitialized() || trade.isShutDown()) return;
ThreadUtils.execute(() -> {
synchronized (trade) {
@ -481,7 +481,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
// received by seller and arbitrator
protected void handle(PaymentSentMessage message, NodeAddress peer) {
System.out.println(getClass().getSimpleName() + ".handle(PaymentSentMessage)");
System.out.println(getClass().getSimpleName() + ".handle(PaymentSentMessage) for " + trade.getClass().getSimpleName() + " " + trade.getShortId());
if (!trade.isInitialized() || trade.isShutDown()) return;
if (!(trade instanceof SellerTrade || trade instanceof ArbitratorTrade)) {
log.warn("Ignoring PaymentSentMessage since not seller or arbitrator");
@ -535,7 +535,7 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
}
private void handle(PaymentReceivedMessage message, NodeAddress peer, boolean reprocessOnError) {
System.out.println(getClass().getSimpleName() + ".handle(PaymentReceivedMessage)");
System.out.println(getClass().getSimpleName() + ".handle(PaymentReceivedMessage) for " + trade.getClass().getSimpleName() + " " + trade.getShortId());
if (!trade.isInitialized() || trade.isShutDown()) return;
ThreadUtils.execute(() -> {
if (!(trade instanceof BuyerTrade || trade instanceof ArbitratorTrade)) {

View file

@ -61,16 +61,20 @@ public class ProcessDepositsConfirmedMessage extends TradeTask {
}
// update multisig hex
sender.setUpdatedMultisigHex(request.getUpdatedMultisigHex());
if (sender.getUpdatedMultisigHex() == null) {
sender.setUpdatedMultisigHex(request.getUpdatedMultisigHex());
// try to import multisig hex (retry later)
ThreadUtils.submitToPool(() -> {
try {
trade.importMultisigHex();
} catch (Exception e) {
e.printStackTrace();
// try to import multisig hex (retry later)
if (!trade.isPayoutPublished()) {
ThreadUtils.submitToPool(() -> {
try {
trade.importMultisigHex();
} catch (Exception e) {
e.printStackTrace();
}
});
}
});
}
// persist
processModel.getTradeManager().requestPersistence();

View file

@ -210,6 +210,8 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
sellerState.set(UNDEFINED);
buyerState.set(BuyerState.UNDEFINED);
onTradeStateChanged(trade.getState());
if (trade.isPayoutPublished()) onPayoutStateChanged(trade.getPayoutState()); // TODO: payout state takes precedence in case PaymentReceivedMessage not processed
else onTradeStateChanged(trade.getState());
});
}