mirror of
https://github.com/haveno-dex/haveno.git
synced 2024-12-23 03:59:36 +00:00
arbitrator sends original unsigned payout tx if published
synchronize on trade when processing dispute messages
This commit is contained in:
parent
17ac09fa4d
commit
6dca11f471
5 changed files with 135 additions and 123 deletions
|
@ -36,7 +36,6 @@ import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import monero.wallet.model.MoneroTxWallet;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static java.lang.String.format;
|
import static java.lang.String.format;
|
||||||
|
@ -171,25 +170,25 @@ public class CoreDisputesService {
|
||||||
applyPayoutAmountsToDisputeResult(payout, winningDispute, disputeResult, customWinnerAmount);
|
applyPayoutAmountsToDisputeResult(payout, winningDispute, disputeResult, customWinnerAmount);
|
||||||
|
|
||||||
// create dispute payout tx
|
// create dispute payout tx
|
||||||
MoneroTxWallet disputePayoutTx = arbitrationManager.createDisputePayoutTx(trade, winningDispute.getContract(), disputeResult, false);
|
trade.getProcessModel().setUnsignedPayoutTx(arbitrationManager.createDisputePayoutTx(trade, winningDispute.getContract(), disputeResult, false));
|
||||||
|
|
||||||
// close winning dispute ticket
|
// close winning dispute ticket
|
||||||
closeDisputeTicket(arbitrationManager, winningDispute, disputeResult, disputePayoutTx, () -> {
|
closeDisputeTicket(arbitrationManager, winningDispute, disputeResult, () -> {
|
||||||
arbitrationManager.requestPersistence();
|
arbitrationManager.requestPersistence();
|
||||||
}, (errMessage, err) -> {
|
}, (errMessage, err) -> {
|
||||||
throw new IllegalStateException(errMessage, err);
|
throw new IllegalStateException(errMessage, err);
|
||||||
});
|
});
|
||||||
|
|
||||||
// close loser's dispute ticket
|
// close loser's dispute ticket
|
||||||
var peersDisputeOptional = arbitrationManager.getDisputesAsObservableList().stream()
|
var loserDisputeOptional = arbitrationManager.getDisputesAsObservableList().stream()
|
||||||
.filter(d -> tradeId.equals(d.getTradeId()) && winningDispute.getTraderId() != d.getTraderId())
|
.filter(d -> tradeId.equals(d.getTradeId()) && winningDispute.getTraderId() != d.getTraderId())
|
||||||
.findFirst();
|
.findFirst();
|
||||||
if (!peersDisputeOptional.isPresent()) throw new IllegalStateException("could not find peer dispute");
|
if (!loserDisputeOptional.isPresent()) throw new IllegalStateException("could not find peer dispute");
|
||||||
var peerDispute = peersDisputeOptional.get();
|
var loserDispute = loserDisputeOptional.get();
|
||||||
var peerDisputeResult = createDisputeResult(peerDispute, winner, reason, summaryNotes, closeDate);
|
var loserDisputeResult = createDisputeResult(loserDispute, winner, reason, summaryNotes, closeDate);
|
||||||
peerDisputeResult.setBuyerPayoutAmount(disputeResult.getBuyerPayoutAmount());
|
loserDisputeResult.setBuyerPayoutAmount(disputeResult.getBuyerPayoutAmount());
|
||||||
peerDisputeResult.setSellerPayoutAmount(disputeResult.getSellerPayoutAmount());
|
loserDisputeResult.setSellerPayoutAmount(disputeResult.getSellerPayoutAmount());
|
||||||
closeDisputeTicket(arbitrationManager, peerDispute, peerDisputeResult, disputePayoutTx, () -> {
|
closeDisputeTicket(arbitrationManager, loserDispute, loserDisputeResult, () -> {
|
||||||
arbitrationManager.requestPersistence();
|
arbitrationManager.requestPersistence();
|
||||||
}, (errMessage, err) -> {
|
}, (errMessage, err) -> {
|
||||||
throw new IllegalStateException(errMessage, err);
|
throw new IllegalStateException(errMessage, err);
|
||||||
|
@ -248,7 +247,7 @@ public class CoreDisputesService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void closeDisputeTicket(DisputeManager disputeManager, Dispute dispute, DisputeResult disputeResult, MoneroTxWallet payoutTx, ResultHandler resultHandler, FaultHandler faultHandler) {
|
public void closeDisputeTicket(DisputeManager disputeManager, Dispute dispute, DisputeResult disputeResult, ResultHandler resultHandler, FaultHandler faultHandler) {
|
||||||
DisputeResult.Reason reason = disputeResult.getReason();
|
DisputeResult.Reason reason = disputeResult.getReason();
|
||||||
|
|
||||||
String role = Res.get("shared.arbitrator");
|
String role = Res.get("shared.arbitrator");
|
||||||
|
@ -279,7 +278,7 @@ public class CoreDisputesService {
|
||||||
String summaryText = DisputeSummaryVerification.signAndApply(disputeManager, disputeResult, textToSign);
|
String summaryText = DisputeSummaryVerification.signAndApply(disputeManager, disputeResult, textToSign);
|
||||||
summaryText += Res.get("disputeSummaryWindow.close.nextStepsForRefundAgentArbitration");
|
summaryText += Res.get("disputeSummaryWindow.close.nextStepsForRefundAgentArbitration");
|
||||||
|
|
||||||
disputeManager.closeDisputeTicket(disputeResult, dispute, summaryText, payoutTx, () -> {
|
disputeManager.closeDisputeTicket(disputeResult, dispute, summaryText, () -> {
|
||||||
dispute.setDisputeResult(disputeResult);
|
dispute.setDisputeResult(disputeResult);
|
||||||
dispute.setIsClosed();
|
dispute.setIsClosed();
|
||||||
resultHandler.handleResult();
|
resultHandler.handleResult();
|
||||||
|
|
|
@ -443,105 +443,106 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
|
||||||
Dispute dispute = message.getDispute();
|
Dispute dispute = message.getDispute();
|
||||||
log.info("{}.onDisputeOpenedMessage() with trade {}, dispute {}", getClass().getSimpleName(), dispute.getTradeId(), dispute.getId());
|
log.info("{}.onDisputeOpenedMessage() with trade {}, dispute {}", getClass().getSimpleName(), dispute.getTradeId(), dispute.getId());
|
||||||
|
|
||||||
Trade trade = null;
|
// get trade
|
||||||
String errorMessage = null;
|
Trade trade = tradeManager.getTrade(dispute.getTradeId());
|
||||||
PubKeyRing senderPubKeyRing = null;
|
if (trade == null) {
|
||||||
try {
|
log.warn("Dispute trade {} does not exist", dispute.getTradeId());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// initialize
|
synchronized (trade) {
|
||||||
T disputeList = getDisputeList();
|
String errorMessage = null;
|
||||||
if (disputeList == null) {
|
PubKeyRing senderPubKeyRing = null;
|
||||||
log.warn("disputes is null");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dispute.setSupportType(message.getSupportType());
|
|
||||||
dispute.setState(Dispute.State.NEW);
|
|
||||||
Contract contract = dispute.getContract();
|
|
||||||
|
|
||||||
// validate dispute
|
|
||||||
try {
|
try {
|
||||||
DisputeValidation.validateDisputeData(dispute);
|
|
||||||
DisputeValidation.validateNodeAddresses(dispute, config);
|
|
||||||
DisputeValidation.validateSenderNodeAddress(dispute, message.getSenderNodeAddress());
|
|
||||||
DisputeValidation.validatePaymentAccountPayload(dispute);
|
|
||||||
//DisputeValidation.testIfDisputeTriesReplay(dispute, disputeList.getList());
|
|
||||||
} catch (DisputeValidation.ValidationException e) {
|
|
||||||
validationExceptions.add(e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get trade
|
// initialize
|
||||||
trade = tradeManager.getTrade(dispute.getTradeId());
|
T disputeList = getDisputeList();
|
||||||
if (trade == null) {
|
if (disputeList == null) {
|
||||||
log.warn("Dispute trade {} does not exist", dispute.getTradeId());
|
log.warn("disputes is null");
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// get sender
|
|
||||||
senderPubKeyRing = trade.isArbitrator() ? (dispute.isDisputeOpenerIsBuyer() ? contract.getBuyerPubKeyRing() : contract.getSellerPubKeyRing()) : trade.getArbitrator().getPubKeyRing();
|
|
||||||
TradePeer sender = trade.getTradePeer(senderPubKeyRing);
|
|
||||||
if (sender == null) throw new RuntimeException("Pub key ring is not from arbitrator, buyer, or seller");
|
|
||||||
|
|
||||||
// message to trader is expected from arbitrator
|
|
||||||
if (!trade.isArbitrator() && sender != trade.getArbitrator()) {
|
|
||||||
throw new RuntimeException(message.getClass().getSimpleName() + " to trader is expected only from arbitrator");
|
|
||||||
}
|
|
||||||
|
|
||||||
// arbitrator verifies signature of payment sent message if given
|
|
||||||
if (trade.isArbitrator() && message.getPaymentSentMessage() != null) {
|
|
||||||
HavenoUtils.verifyPaymentSentMessage(trade, message.getPaymentSentMessage());
|
|
||||||
trade.getBuyer().setUpdatedMultisigHex(message.getPaymentSentMessage().getUpdatedMultisigHex());
|
|
||||||
trade.advanceState(sender == trade.getBuyer() ? Trade.State.BUYER_SENT_PAYMENT_SENT_MSG : Trade.State.SELLER_RECEIVED_PAYMENT_SENT_MSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update multisig hex
|
|
||||||
if (message.getUpdatedMultisigHex() != null) sender.setUpdatedMultisigHex(message.getUpdatedMultisigHex());
|
|
||||||
|
|
||||||
// update peer node address
|
|
||||||
// TODO: tests can reuse the same addresses so nullify equal peer
|
|
||||||
sender.setNodeAddress(message.getSenderNodeAddress());
|
|
||||||
|
|
||||||
// add chat message with price info
|
|
||||||
if (trade instanceof ArbitratorTrade) addPriceInfoMessage(dispute, 0);
|
|
||||||
|
|
||||||
// add dispute
|
|
||||||
synchronized (disputeList) {
|
|
||||||
if (!disputeList.contains(dispute)) {
|
|
||||||
Optional<Dispute> storedDisputeOptional = findDispute(dispute);
|
|
||||||
if (!storedDisputeOptional.isPresent()) {
|
|
||||||
disputeList.add(dispute);
|
|
||||||
trade.advanceDisputeState(Trade.DisputeState.DISPUTE_OPENED);
|
|
||||||
|
|
||||||
// send dispute opened message to peer if arbitrator
|
|
||||||
if (trade.isArbitrator()) sendDisputeOpenedMessageToPeer(dispute, contract, dispute.isDisputeOpenerIsBuyer() ? contract.getSellerPubKeyRing() : contract.getBuyerPubKeyRing(), trade.getSelf().getUpdatedMultisigHex());
|
|
||||||
tradeManager.requestPersistence();
|
|
||||||
errorMessage = null;
|
|
||||||
} else {
|
|
||||||
// valid case if both have opened a dispute and agent was not online
|
|
||||||
log.debug("We got a dispute already open for that trade and trading peer. TradeId = {}",
|
|
||||||
dispute.getTradeId());
|
|
||||||
}
|
|
||||||
|
|
||||||
// add chat message with mediation info if applicable
|
|
||||||
addMediationResultMessage(dispute);
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException("We got a dispute msg that we have already stored. TradeId = " + dispute.getTradeId());
|
|
||||||
}
|
}
|
||||||
|
dispute.setSupportType(message.getSupportType());
|
||||||
|
dispute.setState(Dispute.State.NEW);
|
||||||
|
Contract contract = dispute.getContract();
|
||||||
|
|
||||||
|
// validate dispute
|
||||||
|
try {
|
||||||
|
DisputeValidation.validateDisputeData(dispute);
|
||||||
|
DisputeValidation.validateNodeAddresses(dispute, config);
|
||||||
|
DisputeValidation.validateSenderNodeAddress(dispute, message.getSenderNodeAddress());
|
||||||
|
DisputeValidation.validatePaymentAccountPayload(dispute);
|
||||||
|
//DisputeValidation.testIfDisputeTriesReplay(dispute, disputeList.getList());
|
||||||
|
} catch (DisputeValidation.ValidationException e) {
|
||||||
|
validationExceptions.add(e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get sender
|
||||||
|
senderPubKeyRing = trade.isArbitrator() ? (dispute.isDisputeOpenerIsBuyer() ? contract.getBuyerPubKeyRing() : contract.getSellerPubKeyRing()) : trade.getArbitrator().getPubKeyRing();
|
||||||
|
TradePeer sender = trade.getTradePeer(senderPubKeyRing);
|
||||||
|
if (sender == null) throw new RuntimeException("Pub key ring is not from arbitrator, buyer, or seller");
|
||||||
|
|
||||||
|
// message to trader is expected from arbitrator
|
||||||
|
if (!trade.isArbitrator() && sender != trade.getArbitrator()) {
|
||||||
|
throw new RuntimeException(message.getClass().getSimpleName() + " to trader is expected only from arbitrator");
|
||||||
|
}
|
||||||
|
|
||||||
|
// arbitrator verifies signature of payment sent message if given
|
||||||
|
if (trade.isArbitrator() && message.getPaymentSentMessage() != null) {
|
||||||
|
HavenoUtils.verifyPaymentSentMessage(trade, message.getPaymentSentMessage());
|
||||||
|
trade.getBuyer().setUpdatedMultisigHex(message.getPaymentSentMessage().getUpdatedMultisigHex());
|
||||||
|
trade.advanceState(sender == trade.getBuyer() ? Trade.State.BUYER_SENT_PAYMENT_SENT_MSG : Trade.State.SELLER_RECEIVED_PAYMENT_SENT_MSG);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update multisig hex
|
||||||
|
if (message.getUpdatedMultisigHex() != null) sender.setUpdatedMultisigHex(message.getUpdatedMultisigHex());
|
||||||
|
|
||||||
|
// update peer node address
|
||||||
|
// TODO: tests can reuse the same addresses so nullify equal peer
|
||||||
|
sender.setNodeAddress(message.getSenderNodeAddress());
|
||||||
|
|
||||||
|
// add chat message with price info
|
||||||
|
if (trade instanceof ArbitratorTrade) addPriceInfoMessage(dispute, 0);
|
||||||
|
|
||||||
|
// add dispute
|
||||||
|
synchronized (disputeList) {
|
||||||
|
if (!disputeList.contains(dispute)) {
|
||||||
|
Optional<Dispute> storedDisputeOptional = findDispute(dispute);
|
||||||
|
if (!storedDisputeOptional.isPresent()) {
|
||||||
|
disputeList.add(dispute);
|
||||||
|
trade.advanceDisputeState(Trade.DisputeState.DISPUTE_OPENED);
|
||||||
|
|
||||||
|
// send dispute opened message to peer if arbitrator
|
||||||
|
if (trade.isArbitrator()) sendDisputeOpenedMessageToPeer(dispute, contract, dispute.isDisputeOpenerIsBuyer() ? contract.getSellerPubKeyRing() : contract.getBuyerPubKeyRing(), trade.getSelf().getUpdatedMultisigHex());
|
||||||
|
tradeManager.requestPersistence();
|
||||||
|
errorMessage = null;
|
||||||
|
} else {
|
||||||
|
// valid case if both have opened a dispute and agent was not online
|
||||||
|
log.debug("We got a dispute already open for that trade and trading peer. TradeId = {}",
|
||||||
|
dispute.getTradeId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// add chat message with mediation info if applicable
|
||||||
|
addMediationResultMessage(dispute);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("We got a dispute msg that we have already stored. TradeId = " + dispute.getTradeId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
errorMessage = e.getMessage();
|
||||||
|
log.warn(errorMessage);
|
||||||
|
if (trade != null) trade.setErrorMessage(errorMessage);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
errorMessage = e.getMessage();
|
|
||||||
log.warn(errorMessage);
|
|
||||||
if (trade != null) trade.setErrorMessage(errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// use chat message instead of open dispute message for the ack
|
// use chat message instead of open dispute message for the ack
|
||||||
ObservableList<ChatMessage> messages = message.getDispute().getChatMessages();
|
ObservableList<ChatMessage> messages = message.getDispute().getChatMessages();
|
||||||
if (!messages.isEmpty()) {
|
if (!messages.isEmpty()) {
|
||||||
ChatMessage msg = messages.get(0);
|
ChatMessage msg = messages.get(0);
|
||||||
sendAckMessage(msg, senderPubKeyRing, errorMessage == null, errorMessage);
|
sendAckMessage(msg, senderPubKeyRing, errorMessage == null, errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
requestPersistence();
|
requestPersistence();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// arbitrator sends dispute opened message to opener's peer
|
// arbitrator sends dispute opened message to opener's peer
|
||||||
|
@ -700,16 +701,13 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
|
||||||
}
|
}
|
||||||
|
|
||||||
// arbitrator sends result to trader when their dispute is closed
|
// arbitrator sends result to trader when their dispute is closed
|
||||||
public void closeDisputeTicket(DisputeResult disputeResult, Dispute dispute, String summaryText, MoneroTxWallet payoutTx, ResultHandler resultHandler, FaultHandler faultHandler) {
|
public void closeDisputeTicket(DisputeResult disputeResult, Dispute dispute, String summaryText, ResultHandler resultHandler, FaultHandler faultHandler) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// get trade
|
// get trade
|
||||||
Trade trade = tradeManager.getTrade(dispute.getTradeId());
|
Trade trade = tradeManager.getTrade(dispute.getTradeId());
|
||||||
if (trade == null) throw new RuntimeException("Dispute trade " + dispute.getTradeId() + " does not exist");
|
if (trade == null) throw new RuntimeException("Dispute trade " + dispute.getTradeId() + " does not exist");
|
||||||
|
|
||||||
// create dispute payout tx if not given
|
|
||||||
if (payoutTx == null) payoutTx = createDisputePayoutTx(trade, dispute.getContract(), disputeResult, false); // can be null if already published or we don't have receiver's multisig hex
|
|
||||||
|
|
||||||
// persist result in dispute's chat message once
|
// persist result in dispute's chat message once
|
||||||
boolean resending = disputeResult.getChatMessage() != null;
|
boolean resending = disputeResult.getChatMessage() != null;
|
||||||
if (!resending) {
|
if (!resending) {
|
||||||
|
@ -724,9 +722,15 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
|
||||||
dispute.addAndPersistChatMessage(chatMessage);
|
dispute.addAndPersistChatMessage(chatMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create dispute closed message
|
// create dispute payout tx if not published
|
||||||
TradePeer receiver = trade.getTradePeer(dispute.getTraderPubKeyRing());
|
TradePeer receiver = trade.getTradePeer(dispute.getTraderPubKeyRing());
|
||||||
String unsignedPayoutTxHex = payoutTx == null ? null : payoutTx.getTxSet().getMultisigTxHex();
|
if (!trade.isPayoutPublished() && receiver.getUpdatedMultisigHex() != null) {
|
||||||
|
trade.getProcessModel().setUnsignedPayoutTx(createDisputePayoutTx(trade, dispute.getContract(), disputeResult, false)); // can be null if we don't have receiver's multisig hex
|
||||||
|
}
|
||||||
|
|
||||||
|
// create dispute closed message
|
||||||
|
MoneroTxWallet unsignedPayoutTx = receiver.getUpdatedMultisigHex() == null ? null : trade.getProcessModel().getUnsignedPayoutTx();
|
||||||
|
String unsignedPayoutTxHex = unsignedPayoutTx == null ? null : unsignedPayoutTx.getTxSet().getMultisigTxHex();
|
||||||
TradePeer receiverPeer = receiver == trade.getBuyer() ? trade.getSeller() : trade.getBuyer();
|
TradePeer receiverPeer = receiver == trade.getBuyer() ? trade.getSeller() : trade.getBuyer();
|
||||||
boolean deferPublishPayout = !resending && unsignedPayoutTxHex != null && receiverPeer.getUpdatedMultisigHex() != null && trade.getDisputeState().ordinal() >= Trade.DisputeState.ARBITRATOR_SAW_ARRIVED_DISPUTE_CLOSED_MSG.ordinal() ;
|
boolean deferPublishPayout = !resending && unsignedPayoutTxHex != null && receiverPeer.getUpdatedMultisigHex() != null && trade.getDisputeState().ordinal() >= Trade.DisputeState.ARBITRATOR_SAW_ARRIVED_DISPUTE_CLOSED_MSG.ordinal() ;
|
||||||
DisputeClosedMessage disputeClosedMessage = new DisputeClosedMessage(disputeResult,
|
DisputeClosedMessage disputeClosedMessage = new DisputeClosedMessage(disputeResult,
|
||||||
|
@ -799,9 +803,9 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
|
||||||
);
|
);
|
||||||
|
|
||||||
// save state
|
// save state
|
||||||
if (payoutTx != null) {
|
if (unsignedPayoutTx != null) {
|
||||||
trade.setPayoutTx(payoutTx);
|
trade.setPayoutTx(unsignedPayoutTx);
|
||||||
trade.setPayoutTxHex(payoutTx.getTxSet().getMultisigTxHex());
|
trade.setPayoutTxHex(unsignedPayoutTx.getTxSet().getMultisigTxHex());
|
||||||
}
|
}
|
||||||
trade.advanceDisputeState(Trade.DisputeState.ARBITRATOR_SENT_DISPUTE_CLOSED_MSG);
|
trade.advanceDisputeState(Trade.DisputeState.ARBITRATOR_SENT_DISPUTE_CLOSED_MSG);
|
||||||
requestPersistence();
|
requestPersistence();
|
||||||
|
|
|
@ -169,6 +169,9 @@ public class ProcessModel implements Model, PersistablePayload {
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
transient private MoneroTxWallet depositTxXmr;
|
transient private MoneroTxWallet depositTxXmr;
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
transient private MoneroTxWallet unsignedPayoutTx;
|
||||||
@Nullable
|
@Nullable
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
|
|
|
@ -58,7 +58,8 @@ public class ResendDisputeClosedMessageWithPayout extends TradeTask {
|
||||||
for (Dispute dispute : disputes) {
|
for (Dispute dispute : disputes) {
|
||||||
if (!dispute.isClosed()) continue; // dispute must be closed
|
if (!dispute.isClosed()) continue; // dispute must be closed
|
||||||
if (sender.getPubKeyRing().equals(dispute.getTraderPubKeyRing())) {
|
if (sender.getPubKeyRing().equals(dispute.getTraderPubKeyRing())) {
|
||||||
HavenoUtils.arbitrationManager.closeDisputeTicket(dispute.getDisputeResultProperty().get(), dispute, dispute.getDisputeResultProperty().get().summaryNotesProperty().get(), null, () -> {
|
log.info("Arbitrator resending DisputeClosedMessage for trade {} after receiving updated multisig hex", trade.getId());
|
||||||
|
HavenoUtils.arbitrationManager.closeDisputeTicket(dispute.getDisputeResultProperty().get(), dispute, dispute.getDisputeResultProperty().get().summaryNotesProperty().get(), () -> {
|
||||||
completeAux();
|
completeAux();
|
||||||
}, (errMessage, err) -> {
|
}, (errMessage, err) -> {
|
||||||
err.printStackTrace();
|
err.printStackTrace();
|
||||||
|
|
|
@ -590,8 +590,13 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
|
|
||||||
closeTicketButton.setOnAction(e -> {
|
closeTicketButton.setOnAction(e -> {
|
||||||
|
|
||||||
// get or create payout tx
|
// get or create dispute payout tx
|
||||||
MoneroTxWallet payoutTx = trade.isPayoutPublished() ? trade.getPayoutTx() : arbitrationManager.createDisputePayoutTx(trade, dispute.getContract(), disputeResult, false);
|
MoneroTxWallet payoutTx = null;
|
||||||
|
if (trade.isPayoutPublished()) payoutTx = trade.getPayoutTx();
|
||||||
|
else {
|
||||||
|
payoutTx = arbitrationManager.createDisputePayoutTx(trade, dispute.getContract(), disputeResult, false);
|
||||||
|
trade.getProcessModel().setUnsignedPayoutTx(payoutTx);
|
||||||
|
}
|
||||||
|
|
||||||
// show confirmation
|
// show confirmation
|
||||||
if (dispute.getSupportType() == SupportType.ARBITRATION &&
|
if (dispute.getSupportType() == SupportType.ARBITRATION &&
|
||||||
|
@ -600,9 +605,9 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
showPayoutTxConfirmation(contract,
|
showPayoutTxConfirmation(contract,
|
||||||
disputeResult,
|
disputeResult,
|
||||||
payoutTx,
|
payoutTx,
|
||||||
() -> doClose(closeTicketButton, payoutTx));
|
() -> doClose(closeTicketButton));
|
||||||
} else {
|
} else {
|
||||||
doClose(closeTicketButton, payoutTx);
|
doClose(closeTicketButton);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -654,7 +659,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doClose(Button closeTicketButton, MoneroTxWallet payoutTx) {
|
private void doClose(Button closeTicketButton) {
|
||||||
DisputeManager<? extends DisputeList<Dispute>> disputeManager = getDisputeManager(dispute);
|
DisputeManager<? extends DisputeList<Dispute>> disputeManager = getDisputeManager(dispute);
|
||||||
if (disputeManager == null) {
|
if (disputeManager == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -663,7 +668,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||||
summaryNotesTextArea.textProperty().unbindBidirectional(disputeResult.summaryNotesProperty());
|
summaryNotesTextArea.textProperty().unbindBidirectional(disputeResult.summaryNotesProperty());
|
||||||
|
|
||||||
disputeResult.setCloseDate(new Date());
|
disputeResult.setCloseDate(new Date());
|
||||||
disputesService.closeDisputeTicket(disputeManager, dispute, disputeResult, payoutTx, () -> {
|
disputesService.closeDisputeTicket(disputeManager, dispute, disputeResult, () -> {
|
||||||
if (peersDisputeOptional.isPresent() && !peersDisputeOptional.get().isClosed() && !DevEnv.isDevMode()) {
|
if (peersDisputeOptional.isPresent() && !peersDisputeOptional.get().isClosed() && !DevEnv.isDevMode()) {
|
||||||
new Popup().attention(Res.get("disputeSummaryWindow.close.closePeer")).show();
|
new Popup().attention(Res.get("disputeSummaryWindow.close.closePeer")).show();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue