recover from error closing dispute, show payout confirmation w/ tx fee

This commit is contained in:
woodser 2022-12-30 06:39:54 +00:00
parent 48baa1e602
commit 2c3dabfbf7
18 changed files with 273 additions and 358 deletions

View file

@ -35,6 +35,7 @@ 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;
@ -170,7 +171,7 @@ public class CoreDisputesService {
applyPayoutAmountsToDisputeResult(payout, winningDispute, disputeResult, customWinnerAmount); applyPayoutAmountsToDisputeResult(payout, winningDispute, disputeResult, customWinnerAmount);
// close dispute ticket // close dispute ticket
closeDisputeTicket(arbitrationManager, winningDispute, disputeResult, () -> { closeDisputeTicket(arbitrationManager, winningDispute, disputeResult, null, () -> {
arbitrationManager.requestPersistence(); arbitrationManager.requestPersistence();
// close peer's dispute ticket // close peer's dispute ticket
@ -182,12 +183,16 @@ public class CoreDisputesService {
var peerDisputeResult = createDisputeResult(peerDispute, winner, reason, summaryNotes, closeDate); var peerDisputeResult = createDisputeResult(peerDispute, winner, reason, summaryNotes, closeDate);
peerDisputeResult.setBuyerPayoutAmount(disputeResult.getBuyerPayoutAmount()); peerDisputeResult.setBuyerPayoutAmount(disputeResult.getBuyerPayoutAmount());
peerDisputeResult.setSellerPayoutAmount(disputeResult.getSellerPayoutAmount()); peerDisputeResult.setSellerPayoutAmount(disputeResult.getSellerPayoutAmount());
closeDisputeTicket(arbitrationManager, peerDispute, peerDisputeResult, () -> { closeDisputeTicket(arbitrationManager, peerDispute, peerDisputeResult, null, () -> {
arbitrationManager.requestPersistence(); arbitrationManager.requestPersistence();
}, (errMessage, err) -> {
throw new IllegalStateException(errMessage, err);
}); });
} else { } else {
throw new IllegalStateException("could not find peer dispute"); throw new IllegalStateException("could not find peer dispute");
} }
}, (errMessage, err) -> {
throw new IllegalStateException(errMessage, err);
}); });
} }
} catch (Exception e) { } catch (Exception e) {
@ -239,10 +244,7 @@ public class CoreDisputesService {
} }
} }
// From DisputeSummaryWindow.java 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) {
dispute.setDisputeResult(disputeResult);
dispute.setIsClosed();
DisputeResult.Reason reason = disputeResult.getReason(); DisputeResult.Reason reason = disputeResult.getReason();
String role = Res.get("shared.arbitrator"); String role = Res.get("shared.arbitrator");
@ -272,7 +274,12 @@ 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, resultHandler);
disputeManager.closeDisputeTicket(disputeResult, dispute, summaryText, payoutTx, () -> {
dispute.setDisputeResult(disputeResult);
dispute.setIsClosed();
resultHandler.handleResult();
}, faultHandler);
} }
public void sendDisputeChatMessage(String disputeId, String message, ArrayList<Attachment> attachments) { public void sendDisputeChatMessage(String disputeId, String message, ArrayList<Attachment> attachments) {

View file

@ -689,13 +689,17 @@ 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, ResultHandler resultHandler) { public void closeDisputeTicket(DisputeResult disputeResult, Dispute dispute, String summaryText, MoneroTxWallet payoutTx, ResultHandler resultHandler, FaultHandler faultHandler) {
T disputeList = getDisputeList(); try {
if (disputeList == null) {
log.warn("disputes is null");
return;
}
// get trade
Trade trade = tradeManager.getTrade(dispute.getTradeId());
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, disputeResult); // can be null if already published or we don't have receiver's multisig hex
// persist result in dispute's chat message
ChatMessage chatMessage = new ChatMessage( ChatMessage chatMessage = new ChatMessage(
getSupportType(), getSupportType(),
dispute.getTradeId(), dispute.getTradeId(),
@ -703,53 +707,12 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
false, false,
summaryText, summaryText,
p2PService.getAddress()); p2PService.getAddress());
disputeResult.setChatMessage(chatMessage); disputeResult.setChatMessage(chatMessage);
dispute.addAndPersistChatMessage(chatMessage); dispute.addAndPersistChatMessage(chatMessage);
// get trade
Trade trade = tradeManager.getTrade(dispute.getTradeId());
if (trade == null) {
log.warn("Dispute trade {} does not exist", dispute.getTradeId());
return;
}
// sync and save wallet
trade.syncWallet();
trade.saveWallet();
// create unsigned dispute payout tx if not already published and arbitrator has trader's updated multisig info
TradingPeer receiver = trade.getTradingPeer(dispute.getTraderPubKeyRing());
if (!trade.isPayoutPublished() && receiver.getUpdatedMultisigHex() != null) {
// import multisig hex
MoneroWallet multisigWallet = trade.getWallet();
List<String> updatedMultisigHexes = new ArrayList<String>();
if (trade.getBuyer().getUpdatedMultisigHex() != null) updatedMultisigHexes.add(trade.getBuyer().getUpdatedMultisigHex());
if (trade.getSeller().getUpdatedMultisigHex() != null) updatedMultisigHexes.add(trade.getSeller().getUpdatedMultisigHex());
if (!updatedMultisigHexes.isEmpty()) {
multisigWallet.importMultisigHex(updatedMultisigHexes.toArray(new String[0])); // TODO (monero-project): fails if multisig hex imported individually
}
// sync and save wallet
trade.syncWallet();
trade.saveWallet();
// create unsigned dispute payout tx
if (!trade.isPayoutPublished()) {
log.info("Arbitrator creating unsigned dispute payout tx for trade {}", trade.getId());
try {
MoneroTxWallet payoutTx = createDisputePayoutTx(trade, dispute, disputeResult);
trade.setPayoutTx(payoutTx);
trade.setPayoutTxHex(payoutTx.getTxSet().getMultisigTxHex());
} catch (Exception e) {
if (!trade.isPayoutPublished()) throw e;
}
}
}
// create dispute closed message // create dispute closed message
String unsignedPayoutTxHex = receiver.getUpdatedMultisigHex() == null ? null : trade.getPayoutTxHex(); TradingPeer receiver = trade.getTradingPeer(dispute.getTraderPubKeyRing());
String unsignedPayoutTxHex = payoutTx == null ? null : payoutTx.getTxSet().getMultisigTxHex();
TradingPeer receiverPeer = receiver == trade.getBuyer() ? trade.getSeller() : trade.getBuyer(); TradingPeer receiverPeer = receiver == trade.getBuyer() ? trade.getSeller() : trade.getBuyer();
boolean deferPublishPayout = unsignedPayoutTxHex != null && receiverPeer.getUpdatedMultisigHex() != null && trade.getDisputeState().ordinal() >= Trade.DisputeState.ARBITRATOR_SAW_ARRIVED_DISPUTE_CLOSED_MSG.ordinal() ; boolean deferPublishPayout = 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,
@ -816,19 +779,54 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
chatMessage.setSendMessageError(errorMessage); chatMessage.setSendMessageError(errorMessage);
trade.setDisputeStateIfProgress(Trade.DisputeState.ARBITRATOR_SEND_FAILED_DISPUTE_CLOSED_MSG); trade.setDisputeStateIfProgress(Trade.DisputeState.ARBITRATOR_SEND_FAILED_DISPUTE_CLOSED_MSG);
requestPersistence(); requestPersistence();
resultHandler.handleResult(); faultHandler.handleFault(errorMessage, new RuntimeException(errorMessage));
} }
} }
); );
// save state
if (payoutTx != null) {
trade.setPayoutTx(payoutTx);
trade.setPayoutTxHex(payoutTx.getTxSet().getMultisigTxHex());
}
trade.setDisputeStateIfProgress(Trade.DisputeState.ARBITRATOR_SENT_DISPUTE_CLOSED_MSG); trade.setDisputeStateIfProgress(Trade.DisputeState.ARBITRATOR_SENT_DISPUTE_CLOSED_MSG);
requestPersistence(); requestPersistence();
} catch (Exception e) {
faultHandler.handleFault(e.getMessage(), e);
}
} }
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Utils // Utils
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
private MoneroTxWallet createDisputePayoutTx(Trade trade, Dispute dispute, DisputeResult disputeResult) { public MoneroTxWallet createDisputePayoutTx(Trade trade, Dispute dispute, DisputeResult disputeResult) {
// sync and save wallet
trade.syncWallet();
trade.saveWallet();
// create unsigned dispute payout tx if not already published and arbitrator has trader's updated multisig info
TradingPeer receiver = trade.getTradingPeer(dispute.getTraderPubKeyRing());
if (!trade.isPayoutPublished() && receiver.getUpdatedMultisigHex() != null) {
// import multisig hex
MoneroWallet multisigWallet = trade.getWallet();
List<String> updatedMultisigHexes = new ArrayList<String>();
if (trade.getBuyer().getUpdatedMultisigHex() != null) updatedMultisigHexes.add(trade.getBuyer().getUpdatedMultisigHex());
if (trade.getSeller().getUpdatedMultisigHex() != null) updatedMultisigHexes.add(trade.getSeller().getUpdatedMultisigHex());
if (!updatedMultisigHexes.isEmpty()) {
multisigWallet.importMultisigHex(updatedMultisigHexes.toArray(new String[0])); // TODO (monero-project): fails if multisig hex imported individually
}
// sync and save wallet
trade.syncWallet();
trade.saveWallet();
// create unsigned dispute payout tx
if (!trade.isPayoutPublished()) {
log.info("Arbitrator creating unsigned dispute payout tx for trade {}", trade.getId());
try {
// trade wallet must be synced // trade wallet must be synced
if (trade.getWallet().isMultisigImportNeeded()) throw new RuntimeException("Arbitrator's wallet needs updated multisig hex to create payout tx which means a trader must have already broadcast the payout tx for trade " + dispute.getTradeId()); if (trade.getWallet().isMultisigImportNeeded()) throw new RuntimeException("Arbitrator's wallet needs updated multisig hex to create payout tx which means a trader must have already broadcast the payout tx for trade " + dispute.getTradeId());
@ -872,6 +870,12 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
// save updated multisig hex // save updated multisig hex
trade.getSelf().setUpdatedMultisigHex(trade.getWallet().exportMultisigHex()); trade.getSelf().setUpdatedMultisigHex(trade.getWallet().exportMultisigHex());
return payoutTx; return payoutTx;
} catch (Exception e) {
if (!trade.isPayoutPublished()) throw e;
}
}
}
return null; // can be null if already published or we don't have receiver's multisig hex
} }
private Tuple2<NodeAddress, PubKeyRing> getNodeAddressPubKeyRingTuple(Dispute dispute) { private Tuple2<NodeAddress, PubKeyRing> getNodeAddressPubKeyRingTuple(Dispute dispute) {

View file

@ -1849,8 +1849,7 @@ disputeSummaryWindow.close.txDetails.buyer=Buyer receives {0} on address: {1}\n
disputeSummaryWindow.close.txDetails.seller=Seller receives {0} on address: {1}\n disputeSummaryWindow.close.txDetails.seller=Seller receives {0} on address: {1}\n
disputeSummaryWindow.close.txDetails=Spending: {0}\n\ disputeSummaryWindow.close.txDetails=Spending: {0}\n\
{1}{2}\ {1}{2}\
Transaction fee: {3} ({4} satoshis/vbyte)\n\ Transaction fee: {3}\n\n\
Transaction vsize: {5} vKb\n\n\
Are you sure you want to publish this transaction? Are you sure you want to publish this transaction?
disputeSummaryWindow.close.noPayout.headline=Close without any payout disputeSummaryWindow.close.noPayout.headline=Close without any payout

View file

@ -1395,7 +1395,7 @@ disputeSummaryWindow.close.txDetails.headline=Zveřejněte transakci vrácení p
disputeSummaryWindow.close.txDetails.buyer=Kupující obdrží {0} na adresu: {1}\n disputeSummaryWindow.close.txDetails.buyer=Kupující obdrží {0} na adresu: {1}\n
# suppress inspection "TrailingSpacesInProperty" # suppress inspection "TrailingSpacesInProperty"
disputeSummaryWindow.close.txDetails.seller=Prodejce obdrží {0} na adresu: {1}\n disputeSummaryWindow.close.txDetails.seller=Prodejce obdrží {0} na adresu: {1}\n
disputeSummaryWindow.close.txDetails=Výdaje: {0}\n{1} {2} Transakční poplatek: {3} ({4} satoshi/vbyte)\nTransakční vsize: {5} vKb\n\nOpravdu chcete tuto transakci zveřejnit? disputeSummaryWindow.close.txDetails=Výdaje: {0}\n{1} {2} Transakční poplatek: {3}\n\nOpravdu chcete tuto transakci zveřejnit?
disputeSummaryWindow.close.noPayout.headline=Uzavřít bez jakékoli výplaty disputeSummaryWindow.close.noPayout.headline=Uzavřít bez jakékoli výplaty
disputeSummaryWindow.close.noPayout.text=Chcete zavřít bez výplaty? disputeSummaryWindow.close.noPayout.text=Chcete zavřít bez výplaty?

View file

@ -1395,7 +1395,7 @@ disputeSummaryWindow.close.txDetails.headline=Rückerstattungstransaktion veröf
disputeSummaryWindow.close.txDetails.buyer=Käufer erhält {0} an Adresse: {1}\n disputeSummaryWindow.close.txDetails.buyer=Käufer erhält {0} an Adresse: {1}\n
# suppress inspection "TrailingSpacesInProperty" # suppress inspection "TrailingSpacesInProperty"
disputeSummaryWindow.close.txDetails.seller=Verkäufer erhält {0} an Adresse: {1}\n disputeSummaryWindow.close.txDetails.seller=Verkäufer erhält {0} an Adresse: {1}\n
disputeSummaryWindow.close.txDetails=Ausgaben: {0}\n{1}{2}Transaktionsgebühr: {3} ({4} Satoshis/Byte)\nTransaktionsgröße: {5} Kb\n\nSind Sie sicher, dass Sie diese Transaktion veröffentlichen möchten? disputeSummaryWindow.close.txDetails=Ausgaben: {0}\n{1}{2}Transaktionsgebühr: {3}\n\nSind Sie sicher, dass Sie diese Transaktion veröffentlichen möchten?
disputeSummaryWindow.close.noPayout.headline=Ohne Auszahlung schließen disputeSummaryWindow.close.noPayout.headline=Ohne Auszahlung schließen
disputeSummaryWindow.close.noPayout.text=Wollen Sie schließen ohne eine Auszahlung zu tätigen? disputeSummaryWindow.close.noPayout.text=Wollen Sie schließen ohne eine Auszahlung zu tätigen?

View file

@ -1395,7 +1395,7 @@ disputeSummaryWindow.close.txDetails.headline=Publicar transacción de devoluci
disputeSummaryWindow.close.txDetails.buyer=El comprador recibe {0} en la dirección: {1}\n disputeSummaryWindow.close.txDetails.buyer=El comprador recibe {0} en la dirección: {1}\n
# suppress inspection "TrailingSpacesInProperty" # suppress inspection "TrailingSpacesInProperty"
disputeSummaryWindow.close.txDetails.seller=El vendedor recibe {0} en la dirección: {1}\n disputeSummaryWindow.close.txDetails.seller=El vendedor recibe {0} en la dirección: {1}\n
disputeSummaryWindow.close.txDetails=Gastando: {0}\n{1}{2}Tasa de transacción: {3} ({4} satoshis/vbyte)\nTamaño virtual de transacción: {5} vKb\n\n¿Está seguro de que quiere publicar esta transacción?\n disputeSummaryWindow.close.txDetails=Gastando: {0}\n{1}{2}Tasa de transacción: {3}\n\n¿Está seguro de que quiere publicar esta transacción?\n
disputeSummaryWindow.close.noPayout.headline=Cerrar sin realizar algún pago disputeSummaryWindow.close.noPayout.headline=Cerrar sin realizar algún pago
disputeSummaryWindow.close.noPayout.text=¿Quiere cerrar sin realizar algún pago? disputeSummaryWindow.close.noPayout.text=¿Quiere cerrar sin realizar algún pago?

View file

@ -1395,7 +1395,7 @@ disputeSummaryWindow.close.txDetails.headline=Publish refund transaction
disputeSummaryWindow.close.txDetails.buyer=Buyer receives {0} on address: {1}\n disputeSummaryWindow.close.txDetails.buyer=Buyer receives {0} on address: {1}\n
# suppress inspection "TrailingSpacesInProperty" # suppress inspection "TrailingSpacesInProperty"
disputeSummaryWindow.close.txDetails.seller=Seller receives {0} on address: {1}\n disputeSummaryWindow.close.txDetails.seller=Seller receives {0} on address: {1}\n
disputeSummaryWindow.close.txDetails=Spending: {0}\n{1}{2}Transaction fee: {3} ({4} satoshis/vbyte)\nTransaction vsize: {5} vKb\n\nAre you sure you want to publish this transaction? disputeSummaryWindow.close.txDetails=Spending: {0}\n{1}{2}Transaction fee: {3}\n\nAre you sure you want to publish this transaction?
disputeSummaryWindow.close.noPayout.headline=Close without any payout disputeSummaryWindow.close.noPayout.headline=Close without any payout
disputeSummaryWindow.close.noPayout.text=Do you want to close without doing any payout? disputeSummaryWindow.close.noPayout.text=Do you want to close without doing any payout?

View file

@ -1396,7 +1396,7 @@ disputeSummaryWindow.close.txDetails.headline=Publier la transaction de rembours
disputeSummaryWindow.close.txDetails.buyer=L''acheteur reçoit {0} à l''adresse: {1}\n disputeSummaryWindow.close.txDetails.buyer=L''acheteur reçoit {0} à l''adresse: {1}\n
# suppress inspection "TrailingSpacesInProperty" # suppress inspection "TrailingSpacesInProperty"
disputeSummaryWindow.close.txDetails.seller=Le vendeur reçoit {0} à l''adresse: {1}\n disputeSummaryWindow.close.txDetails.seller=Le vendeur reçoit {0} à l''adresse: {1}\n
disputeSummaryWindow.close.txDetails=Dépenser: {0}\n{1}{2}Frais de transaction: {3} ({4} satoshis/vbyte)\nTaille virtuelle de la transaction: {5} vKb\n\nÊtes-vous sûr de vouloir publier cette transaction ? disputeSummaryWindow.close.txDetails=Dépenser: {0}\n{1}{2}Frais de transaction: {3}\n\nÊtes-vous sûr de vouloir publier cette transaction ?
disputeSummaryWindow.close.noPayout.headline=Fermé sans paiement disputeSummaryWindow.close.noPayout.headline=Fermé sans paiement
disputeSummaryWindow.close.noPayout.text=Voulez-vous fermer sans paiement ? disputeSummaryWindow.close.noPayout.text=Voulez-vous fermer sans paiement ?

View file

@ -1395,7 +1395,7 @@ disputeSummaryWindow.close.txDetails.headline=Pubblica transazione di rimborso
disputeSummaryWindow.close.txDetails.buyer=L'acquirente riceve {0} all'indirizzo: {1}\n disputeSummaryWindow.close.txDetails.buyer=L'acquirente riceve {0} all'indirizzo: {1}\n
# suppress inspection "TrailingSpacesInProperty" # suppress inspection "TrailingSpacesInProperty"
disputeSummaryWindow.close.txDetails.seller=Il venditore riceve {0} all'indirizzo: {1}\n disputeSummaryWindow.close.txDetails.seller=Il venditore riceve {0} all'indirizzo: {1}\n
disputeSummaryWindow.close.txDetails=Spending: {0}\n{1}{2}Transaction fee: {3} ({4} satoshis/vbyte)\nTransaction vsize: {5} vKb\n\nAre you sure you want to publish this transaction? disputeSummaryWindow.close.txDetails=Spending: {0}\n{1}{2}Transaction fee: {3}\n\nAre you sure you want to publish this transaction?
disputeSummaryWindow.close.noPayout.headline=Close without any payout disputeSummaryWindow.close.noPayout.headline=Close without any payout
disputeSummaryWindow.close.noPayout.text=Do you want to close without doing any payout? disputeSummaryWindow.close.noPayout.text=Do you want to close without doing any payout?

View file

@ -1395,7 +1395,7 @@ disputeSummaryWindow.close.txDetails.headline=払い戻しトランザクショ
disputeSummaryWindow.close.txDetails.buyer=買い手が {0} を受けます、入金先アドレス: {1}\n disputeSummaryWindow.close.txDetails.buyer=買い手が {0} を受けます、入金先アドレス: {1}\n
# suppress inspection "TrailingSpacesInProperty" # suppress inspection "TrailingSpacesInProperty"
disputeSummaryWindow.close.txDetails.seller=売り手が {0} を受けます、入金先アドレス: {1}\n disputeSummaryWindow.close.txDetails.seller=売り手が {0} を受けます、入金先アドレス: {1}\n
disputeSummaryWindow.close.txDetails=支払う金額: {0}\n{1}{2}トランザクション手数料: {3}({4}サトシ/vバイト)\nトランザクションvサイズ: {5} vKb\n\nこのトランザクションを発行してもよろしいですか disputeSummaryWindow.close.txDetails=支払う金額: {0}\n{1}{2}トランザクション手数料: {3}\n\nこのトランザクションを発行してもよろしいですか
disputeSummaryWindow.close.noPayout.headline=支払いなしで閉じる disputeSummaryWindow.close.noPayout.headline=支払いなしで閉じる
disputeSummaryWindow.close.noPayout.text=支払いなしで閉じてもよろしいですか? disputeSummaryWindow.close.noPayout.text=支払いなしで閉じてもよろしいですか?

View file

@ -1399,7 +1399,7 @@ disputeSummaryWindow.close.txDetails.headline=Publicar transação de reembolso
disputeSummaryWindow.close.txDetails.buyer=Comprador recebe {0} no endereço: {1}\n disputeSummaryWindow.close.txDetails.buyer=Comprador recebe {0} no endereço: {1}\n
# suppress inspection "TrailingSpacesInProperty" # suppress inspection "TrailingSpacesInProperty"
disputeSummaryWindow.close.txDetails.seller=Vendedor recebe {0} no endereço: {1}\n disputeSummaryWindow.close.txDetails.seller=Vendedor recebe {0} no endereço: {1}\n
disputeSummaryWindow.close.txDetails=Spending: {0}\n{1}{2}Transaction fee: {3} ({4} satoshis/vbyte)\nTransaction vsize: {5} vKb\n\nAre you sure you want to publish this transaction? disputeSummaryWindow.close.txDetails=Spending: {0}\n{1}{2}Transaction fee: {3}\n\nAre you sure you want to publish this transaction?
disputeSummaryWindow.close.noPayout.headline=Close without any payout disputeSummaryWindow.close.noPayout.headline=Close without any payout
disputeSummaryWindow.close.noPayout.text=Do you want to close without doing any payout? disputeSummaryWindow.close.noPayout.text=Do you want to close without doing any payout?

View file

@ -1395,7 +1395,7 @@ disputeSummaryWindow.close.txDetails.headline=Publicar transação de reembolso
disputeSummaryWindow.close.txDetails.buyer=O comprador recebe {0} no endereço: {1}\n disputeSummaryWindow.close.txDetails.buyer=O comprador recebe {0} no endereço: {1}\n
# suppress inspection "TrailingSpacesInProperty" # suppress inspection "TrailingSpacesInProperty"
disputeSummaryWindow.close.txDetails.seller=O vendedor recebe {0} no endereço: {1}\n disputeSummaryWindow.close.txDetails.seller=O vendedor recebe {0} no endereço: {1}\n
disputeSummaryWindow.close.txDetails=Spending: {0}\n{1}{2}Transaction fee: {3} ({4} satoshis/vbyte)\nTransaction vsize: {5} vKb\n\nAre you sure you want to publish this transaction? disputeSummaryWindow.close.txDetails=Spending: {0}\n{1}{2}Transaction fee: {3}\n\nAre you sure you want to publish this transaction?
disputeSummaryWindow.close.noPayout.headline=Close without any payout disputeSummaryWindow.close.noPayout.headline=Close without any payout
disputeSummaryWindow.close.noPayout.text=Do you want to close without doing any payout? disputeSummaryWindow.close.noPayout.text=Do you want to close without doing any payout?

View file

@ -1395,7 +1395,7 @@ disputeSummaryWindow.close.txDetails.headline=Publish refund transaction
disputeSummaryWindow.close.txDetails.buyer=Buyer receives {0} on address: {1}\n disputeSummaryWindow.close.txDetails.buyer=Buyer receives {0} on address: {1}\n
# suppress inspection "TrailingSpacesInProperty" # suppress inspection "TrailingSpacesInProperty"
disputeSummaryWindow.close.txDetails.seller=Seller receives {0} on address: {1}\n disputeSummaryWindow.close.txDetails.seller=Seller receives {0} on address: {1}\n
disputeSummaryWindow.close.txDetails=Spending: {0}\n{1}{2}Transaction fee: {3} ({4} satoshis/vbyte)\nTransaction vsize: {5} vKb\n\nAre you sure you want to publish this transaction? disputeSummaryWindow.close.txDetails=Spending: {0}\n{1}{2}Transaction fee: {3}\n\nAre you sure you want to publish this transaction?
disputeSummaryWindow.close.noPayout.headline=Close without any payout disputeSummaryWindow.close.noPayout.headline=Close without any payout
disputeSummaryWindow.close.noPayout.text=Do you want to close without doing any payout? disputeSummaryWindow.close.noPayout.text=Do you want to close without doing any payout?

View file

@ -1395,7 +1395,7 @@ disputeSummaryWindow.close.txDetails.headline=Publish refund transaction
disputeSummaryWindow.close.txDetails.buyer=Buyer receives {0} on address: {1}\n disputeSummaryWindow.close.txDetails.buyer=Buyer receives {0} on address: {1}\n
# suppress inspection "TrailingSpacesInProperty" # suppress inspection "TrailingSpacesInProperty"
disputeSummaryWindow.close.txDetails.seller=Seller receives {0} on address: {1}\n disputeSummaryWindow.close.txDetails.seller=Seller receives {0} on address: {1}\n
disputeSummaryWindow.close.txDetails=Spending: {0}\n{1}{2}Transaction fee: {3} ({4} satoshis/vbyte)\nTransaction vsize: {5} vKb\n\nAre you sure you want to publish this transaction? disputeSummaryWindow.close.txDetails=Spending: {0}\n{1}{2}Transaction fee: {3}\n\nAre you sure you want to publish this transaction?
disputeSummaryWindow.close.noPayout.headline=Close without any payout disputeSummaryWindow.close.noPayout.headline=Close without any payout
disputeSummaryWindow.close.noPayout.text=Do you want to close without doing any payout? disputeSummaryWindow.close.noPayout.text=Do you want to close without doing any payout?

View file

@ -1397,7 +1397,7 @@ disputeSummaryWindow.close.txDetails.headline=Publish refund transaction
disputeSummaryWindow.close.txDetails.buyer=Buyer receives {0} on address: {1}\n disputeSummaryWindow.close.txDetails.buyer=Buyer receives {0} on address: {1}\n
# suppress inspection "TrailingSpacesInProperty" # suppress inspection "TrailingSpacesInProperty"
disputeSummaryWindow.close.txDetails.seller=Seller receives {0} on address: {1}\n disputeSummaryWindow.close.txDetails.seller=Seller receives {0} on address: {1}\n
disputeSummaryWindow.close.txDetails=Spending: {0}\n{1}{2}Transaction fee: {3} ({4} satoshis/vbyte)\nTransaction vsize: {5} vKb\n\nAre you sure you want to publish this transaction? disputeSummaryWindow.close.txDetails=Spending: {0}\n{1}{2}Transaction fee: {3}\n\nAre you sure you want to publish this transaction?
disputeSummaryWindow.close.noPayout.headline=Close without any payout disputeSummaryWindow.close.noPayout.headline=Close without any payout
disputeSummaryWindow.close.noPayout.text=Do you want to close without doing any payout? disputeSummaryWindow.close.noPayout.text=Do you want to close without doing any payout?

View file

@ -1395,7 +1395,7 @@ disputeSummaryWindow.close.txDetails.headline=发布交易退款
disputeSummaryWindow.close.txDetails.buyer=买方收到{0}在地址:{1} disputeSummaryWindow.close.txDetails.buyer=买方收到{0}在地址:{1}
# suppress inspection "TrailingSpacesInProperty" # suppress inspection "TrailingSpacesInProperty"
disputeSummaryWindow.close.txDetails.seller=卖方收到{0}在地址:{1} disputeSummaryWindow.close.txDetails.seller=卖方收到{0}在地址:{1}
disputeSummaryWindow.close.txDetails=费用:{0}\n{1}{2}交易费:{3}({4}satoshis/byte)\n事务大小{5} Kb\n\n您确定要发布此交易吗 disputeSummaryWindow.close.txDetails=费用:{0}\n{1}{2}交易费:{3}\n\n您确定要发布此交易吗
disputeSummaryWindow.close.noPayout.headline=未支付关闭 disputeSummaryWindow.close.noPayout.headline=未支付关闭
disputeSummaryWindow.close.noPayout.text=你想要在未作支付的情况下关闭吗? disputeSummaryWindow.close.noPayout.text=你想要在未作支付的情况下关闭吗?

View file

@ -1395,7 +1395,7 @@ disputeSummaryWindow.close.txDetails.headline=發佈交易退款
disputeSummaryWindow.close.txDetails.buyer=買方收到{0}在地址:{1} disputeSummaryWindow.close.txDetails.buyer=買方收到{0}在地址:{1}
# suppress inspection "TrailingSpacesInProperty" # suppress inspection "TrailingSpacesInProperty"
disputeSummaryWindow.close.txDetails.seller=賣方收到{0}在地址:{1} disputeSummaryWindow.close.txDetails.seller=賣方收到{0}在地址:{1}
disputeSummaryWindow.close.txDetails=費用:{0}\n{1}{2}交易費:{3}({4}satoshis/byte)\n事務大小{5} Kb\n\n您確定要發佈此交易嗎 disputeSummaryWindow.close.txDetails=費用:{0}\n{1}{2}交易費:{3}\n\n您確定要發佈此交易嗎
disputeSummaryWindow.close.noPayout.headline=未支付關閉 disputeSummaryWindow.close.noPayout.headline=未支付關閉
disputeSummaryWindow.close.noPayout.text=你想要在未作支付的情況下關閉嗎? disputeSummaryWindow.close.noPayout.text=你想要在未作支付的情況下關閉嗎?

View file

@ -30,6 +30,7 @@ import bisq.desktop.util.Layout;
import bisq.core.btc.wallet.TradeWalletService; import bisq.core.btc.wallet.TradeWalletService;
import bisq.core.btc.wallet.XmrWalletService; import bisq.core.btc.wallet.XmrWalletService;
import bisq.core.locale.Res; import bisq.core.locale.Res;
import bisq.core.support.SupportType;
import bisq.core.support.dispute.Dispute; import bisq.core.support.dispute.Dispute;
import bisq.core.support.dispute.DisputeList; import bisq.core.support.dispute.DisputeList;
import bisq.core.support.dispute.DisputeManager; import bisq.core.support.dispute.DisputeManager;
@ -38,6 +39,7 @@ import bisq.core.support.dispute.arbitration.ArbitrationManager;
import bisq.core.support.dispute.mediation.MediationManager; import bisq.core.support.dispute.mediation.MediationManager;
import bisq.core.support.dispute.refund.RefundManager; import bisq.core.support.dispute.refund.RefundManager;
import bisq.core.trade.Contract; import bisq.core.trade.Contract;
import bisq.core.trade.HavenoUtils;
import bisq.core.trade.Trade; import bisq.core.trade.Trade;
import bisq.core.trade.TradeManager; import bisq.core.trade.TradeManager;
import bisq.core.util.FormattingUtils; import bisq.core.util.FormattingUtils;
@ -78,6 +80,7 @@ import java.util.Date;
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 bisq.desktop.util.FormBuilder.add2ButtonsWithBox; import static bisq.desktop.util.FormBuilder.add2ButtonsWithBox;
import static bisq.desktop.util.FormBuilder.addConfirmationLabelLabel; import static bisq.desktop.util.FormBuilder.addConfirmationLabelLabel;
@ -113,7 +116,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
private ChangeListener<Boolean> customRadioButtonSelectedListener; private ChangeListener<Boolean> customRadioButtonSelectedListener;
private ChangeListener<Toggle> reasonToggleSelectionListener; private ChangeListener<Toggle> reasonToggleSelectionListener;
private InputTextField buyerPayoutAmountInputTextField, sellerPayoutAmountInputTextField; private InputTextField buyerPayoutAmountInputTextField, sellerPayoutAmountInputTextField;
private ChangeListener<String> buyerPayoutAmountListener, sellerPayoutAmountListener; private ChangeListener<Boolean> buyerPayoutAmountListener, sellerPayoutAmountListener;
private ChangeListener<Toggle> tradeAmountToggleGroupListener; private ChangeListener<Toggle> tradeAmountToggleGroupListener;
@ -319,16 +322,16 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
tradeAmountToggleGroupListener = (observable, oldValue, newValue) -> applyPayoutAmounts(newValue); tradeAmountToggleGroupListener = (observable, oldValue, newValue) -> applyPayoutAmounts(newValue);
tradeAmountToggleGroup.selectedToggleProperty().addListener(tradeAmountToggleGroupListener); tradeAmountToggleGroup.selectedToggleProperty().addListener(tradeAmountToggleGroupListener);
buyerPayoutAmountListener = (observable1, oldValue1, newValue1) -> applyCustomAmounts(buyerPayoutAmountInputTextField); buyerPayoutAmountListener = (observable, oldValue, newValue) -> applyCustomAmounts(buyerPayoutAmountInputTextField, oldValue, newValue);
sellerPayoutAmountListener = (observable1, oldValue1, newValue1) -> applyCustomAmounts(sellerPayoutAmountInputTextField); sellerPayoutAmountListener = (observable, oldValue, newValue) -> applyCustomAmounts(sellerPayoutAmountInputTextField, oldValue, newValue);
customRadioButtonSelectedListener = (observable, oldValue, newValue) -> { customRadioButtonSelectedListener = (observable, oldValue, newValue) -> {
buyerPayoutAmountInputTextField.setEditable(newValue); buyerPayoutAmountInputTextField.setEditable(newValue);
sellerPayoutAmountInputTextField.setEditable(newValue); sellerPayoutAmountInputTextField.setEditable(newValue);
if (newValue) { if (newValue) {
buyerPayoutAmountInputTextField.textProperty().addListener(buyerPayoutAmountListener); buyerPayoutAmountInputTextField.focusedProperty().addListener(buyerPayoutAmountListener);
sellerPayoutAmountInputTextField.textProperty().addListener(sellerPayoutAmountListener); sellerPayoutAmountInputTextField.focusedProperty().addListener(sellerPayoutAmountListener);
} else { } else {
removePayoutAmountListeners(); removePayoutAmountListeners();
} }
@ -338,11 +341,10 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
private void removePayoutAmountListeners() { private void removePayoutAmountListeners() {
if (buyerPayoutAmountInputTextField != null && buyerPayoutAmountListener != null) if (buyerPayoutAmountInputTextField != null && buyerPayoutAmountListener != null)
buyerPayoutAmountInputTextField.textProperty().removeListener(buyerPayoutAmountListener); buyerPayoutAmountInputTextField.focusedProperty().removeListener(buyerPayoutAmountListener);
if (sellerPayoutAmountInputTextField != null && sellerPayoutAmountListener != null) if (sellerPayoutAmountInputTextField != null && sellerPayoutAmountListener != null)
sellerPayoutAmountInputTextField.textProperty().removeListener(sellerPayoutAmountListener); sellerPayoutAmountInputTextField.focusedProperty().removeListener(sellerPayoutAmountListener);
} }
private boolean isPayoutAmountValid() { private boolean isPayoutAmountValid() {
@ -368,12 +370,12 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
} }
} }
private void applyCustomAmounts(InputTextField inputTextField) { private void applyCustomAmounts(InputTextField inputTextField, boolean oldFocusValue, boolean newFocusValue) {
// // We only apply adjustments at focus out, otherwise we cannot enter certain values if we update at each // We only apply adjustments at focus out, otherwise we cannot enter certain values if we update at each
// // keystroke. // keystroke.
// if (!oldFocusValue || newFocusValue) { if (!oldFocusValue || newFocusValue) {
// return; return;
// } }
Contract contract = dispute.getContract(); Contract contract = dispute.getContract();
Coin available = contract.getTradeAmount() Coin available = contract.getTradeAmount()
@ -579,22 +581,21 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
Button cancelButton = tuple.second; Button cancelButton = tuple.second;
closeTicketButton.setOnAction(e -> { closeTicketButton.setOnAction(e -> {
doClose(closeTicketButton);
// if (dispute.getDepositTxSerialized() == null) { // create payout tx
// log.warn("dispute.getDepositTxSerialized is null"); MoneroTxWallet payoutTx = arbitrationManager.createDisputePayoutTx(trade, dispute, disputeResult);
// return;
// } // show confirmation
// if (dispute.getSupportType() == SupportType.ARBITRATION &&
// if (dispute.getSupportType() == SupportType.REFUND && peersDisputeOptional.isPresent() &&
// peersDisputeOptional.isPresent() && !peersDisputeOptional.get().isClosed()) {
// !peersDisputeOptional.get().isClosed()) { showPayoutTxConfirmation(contract,
// showPayoutTxConfirmation(contract, disputeResult,
// disputeResult, payoutTx,
// () -> doCloseIfValid(closeTicketButton)); () -> doClose(closeTicketButton, payoutTx));
// } else { } else {
// doCloseIfValid(closeTicketButton); doClose(closeTicketButton, payoutTx);
// } }
}); });
cancelButton.setOnAction(e -> { cancelButton.setOnAction(e -> {
@ -604,146 +605,48 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
}); });
} }
private void showPayoutTxConfirmation(Contract contract, DisputeResult disputeResult, ResultHandler resultHandler) { private void showPayoutTxConfirmation(Contract contract, DisputeResult disputeResult, MoneroTxWallet payoutTx, ResultHandler resultHandler) {
throw new RuntimeException("DisputeSummaryWindow.showPayoutTxConfimration() needs updated for XMR"); Coin buyerPayoutAmount = disputeResult.getBuyerPayoutAmount();
// Coin buyerPayoutAmount = disputeResult.getBuyerPayoutAmount(); String buyerPayoutAddressString = contract.getBuyerPayoutAddressString();
// String buyerPayoutAddressString = contract.getBuyerPayoutAddressString(); Coin sellerPayoutAmount = disputeResult.getSellerPayoutAmount();
// Coin sellerPayoutAmount = disputeResult.getSellerPayoutAmount(); String sellerPayoutAddressString = contract.getSellerPayoutAddressString();
// String sellerPayoutAddressString = contract.getSellerPayoutAddressString(); Coin outputAmount = buyerPayoutAmount.add(sellerPayoutAmount);
// Coin outputAmount = buyerPayoutAmount.add(sellerPayoutAmount); String buyerDetails = "";
// Tuple2<Coin, Integer> feeTuple = txFeeEstimationService.getEstimatedFeeAndTxSize(outputAmount, feeService, btcWalletService); if (buyerPayoutAmount.isPositive()) {
// Coin fee = feeTuple.first; buyerDetails = Res.get("disputeSummaryWindow.close.txDetails.buyer",
// Integer txSize = feeTuple.second; formatter.formatCoinWithCode(buyerPayoutAmount),
// double feePerByte = CoinUtil.getFeePerByte(fee, txSize); buyerPayoutAddressString);
// double kb = txSize / 1000d; }
// Coin inputAmount = outputAmount.add(fee); String sellerDetails = "";
// String buyerDetails = ""; if (sellerPayoutAmount.isPositive()) {
// if (buyerPayoutAmount.isPositive()) { sellerDetails = Res.get("disputeSummaryWindow.close.txDetails.seller",
// buyerDetails = Res.get("disputeSummaryWindow.close.txDetails.buyer", formatter.formatCoinWithCode(sellerPayoutAmount),
// formatter.formatCoinWithCode(buyerPayoutAmount), sellerPayoutAddressString);
// buyerPayoutAddressString); }
// } if (outputAmount.isPositive()) {
// String sellerDetails = ""; new Popup().width(900)
// if (sellerPayoutAmount.isPositive()) { .headLine(Res.get("disputeSummaryWindow.close.txDetails.headline"))
// sellerDetails = Res.get("disputeSummaryWindow.close.txDetails.seller", .confirmation(Res.get("disputeSummaryWindow.close.txDetails",
// formatter.formatCoinWithCode(sellerPayoutAmount), formatter.formatCoinWithCode(outputAmount),
// sellerPayoutAddressString); buyerDetails,
// } sellerDetails,
// if (outputAmount.isPositive()) { formatter.formatCoinWithCode(HavenoUtils.atomicUnitsToCoin(payoutTx.getFee()))))
// new Popup().width(900) .actionButtonText(Res.get("shared.yes"))
// .headLine(Res.get("disputeSummaryWindow.close.txDetails.headline")) .onAction(() -> resultHandler.handleResult())
// .confirmation(Res.get("disputeSummaryWindow.close.txDetails", .closeButtonText(Res.get("shared.cancel"))
// formatter.formatCoinWithCode(inputAmount), .show();
// buyerDetails, } else {
// sellerDetails, // No payout will be made
// formatter.formatCoinWithCode(fee), new Popup().headLine(Res.get("disputeSummaryWindow.close.noPayout.headline"))
// feePerByte, .confirmation(Res.get("disputeSummaryWindow.close.noPayout.text"))
// kb)) .actionButtonText(Res.get("shared.yes"))
// .actionButtonText(Res.get("shared.yes")) .onAction(resultHandler::handleResult)
// .onAction(() -> { .closeButtonText(Res.get("shared.cancel"))
// doPayout(buyerPayoutAmount, .show();
// sellerPayoutAmount, }
// fee,
// buyerPayoutAddressString,
// sellerPayoutAddressString,
// resultHandler);
// })
// .closeButtonText(Res.get("shared.cancel"))
// .show();
// } else {
// // No payout will be made
// new Popup().headLine(Res.get("disputeSummaryWindow.close.noPayout.headline"))
// .confirmation(Res.get("disputeSummaryWindow.close.noPayout.text"))
// .actionButtonText(Res.get("shared.yes"))
// .onAction(resultHandler::handleResult)
// .closeButtonText(Res.get("shared.cancel"))
// .show();
// }
} }
private void doPayout(Coin buyerPayoutAmount, private void doClose(Button closeTicketButton, MoneroTxWallet payoutTx) {
Coin sellerPayoutAmount,
Coin fee,
String buyerPayoutAddressString,
String sellerPayoutAddressString,
ResultHandler resultHandler) {
throw new RuntimeException("DisputeSummaryWindow.doPayout() needs updated for XMR");
// try {
// Transaction tx = btcWalletService.createRefundPayoutTx(buyerPayoutAmount,
// sellerPayoutAmount,
// fee,
// buyerPayoutAddressString,
// sellerPayoutAddressString);
// tradeWalletService.broadcastTx(tx, new TxBroadcaster.Callback() {
// @Override
// public void onSuccess(Transaction transaction) {
// resultHandler.handleResult();
// }
//
// @Override
// public void onFailure(TxBroadcastException exception) {
// log.error("TxBroadcastException at doPayout", exception);
// new Popup().error(exception.toString()).show();
// }
// });
// } catch (InsufficientMoneyException | WalletException | TransactionVerificationException e) {
// log.error("Exception at doPayout", e);
// new Popup().error(e.toString()).show();
// }
}
private void doCloseIfValid(Button closeTicketButton) {
throw new RuntimeException("DisputeSummaryWindow.doCloseIfValid() needs updated for XMR");
// var disputeManager = checkNotNull(getDisputeManager(dispute));
// try {
// TradeDataValidation.validateDonationAddress(dispute.getDonationAddressOfDelayedPayoutTx());
// TradeDataValidation.testIfDisputeTriesReplay(dispute, disputeManager.getDisputesAsObservableList());
// doClose(closeTicketButton);
// } catch (TradeDataValidation.AddressException exception) {
// String addressAsString = dispute.getDonationAddressOfDelayedPayoutTx();
// String tradeId = dispute.getTradeId();
//
// // For mediators we do not enforce that the case cannot be closed to stay flexible,
// // but for refund agents we do.
// if (disputeManager instanceof MediationManager) {
// new Popup().width(900)
// .warning(Res.get("support.warning.disputesWithInvalidDonationAddress",
// addressAsString,
// tradeId,
// Res.get("support.warning.disputesWithInvalidDonationAddress.mediator")))
// .onAction(() -> {
// doClose(closeTicketButton);
// })
// .actionButtonText(Res.get("shared.yes"))
// .closeButtonText(Res.get("shared.no"))
// .show();
// } else {
// new Popup().width(900)
// .warning(Res.get("support.warning.disputesWithInvalidDonationAddress",
// addressAsString,
// tradeId,
// Res.get("support.warning.disputesWithInvalidDonationAddress.refundAgent")))
// .show();
// }
// } catch (TradeDataValidation.DisputeReplayException exception) {
// if (disputeManager instanceof MediationManager) {
// new Popup().width(900)
// .warning(exception.getMessage())
// .onAction(() -> {
// doClose(closeTicketButton);
// })
// .actionButtonText(Res.get("shared.yes"))
// .closeButtonText(Res.get("shared.no"))
// .show();
// } else {
// new Popup().width(900)
// .warning(exception.getMessage())
// .show();
// }
// }
}
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;
@ -752,15 +655,17 @@ 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, () -> { disputesService.closeDisputeTicket(disputeManager, dispute, disputeResult, payoutTx, () -> {
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();
} }
disputeManager.requestPersistence(); disputeManager.requestPersistence();
});
closeTicketButton.disableProperty().unbind(); closeTicketButton.disableProperty().unbind();
hide(); hide();
}, (errMessage, err) -> {
log.error(errMessage);
new Popup().error(err.toString()).show();
});
} }
private DisputeManager<? extends DisputeList<Dispute>> getDisputeManager(Dispute dispute) { private DisputeManager<? extends DisputeList<Dispute>> getDisputeManager(Dispute dispute) {
@ -818,7 +723,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
sellerPayoutAmount.equals(sellerSecurityDeposit)) { sellerPayoutAmount.equals(sellerSecurityDeposit)) {
buyerGetsTradeAmountRadioButton.setSelected(true); buyerGetsTradeAmountRadioButton.setSelected(true);
} else if (buyerPayoutAmount.equals(tradeAmount.add(buyerSecurityDeposit).add(sellerSecurityDeposit)) && } else if (buyerPayoutAmount.equals(tradeAmount.add(buyerSecurityDeposit).add(sellerSecurityDeposit)) &&
sellerPayoutAmount.equals(Coin.ZERO)) { // TODO (woodser): apply min payout to incentivize loser (see post v1.1.7) sellerPayoutAmount.equals(Coin.ZERO)) {
buyerGetsAllRadioButton.setSelected(true); buyerGetsAllRadioButton.setSelected(true);
} else if (sellerPayoutAmount.equals(tradeAmount.add(sellerSecurityDeposit)) } else if (sellerPayoutAmount.equals(tradeAmount.add(sellerSecurityDeposit))
&& buyerPayoutAmount.equals(buyerSecurityDeposit)) { && buyerPayoutAmount.equals(buyerSecurityDeposit)) {