mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-04-19 23:36:00 -04:00
fixes when cloned offers are taken at the same time
This commit is contained in:
parent
13e13d945d
commit
c7a3a9740f
@ -2648,7 +2648,7 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
|
||||
}
|
||||
}
|
||||
setDepositTxs(txs);
|
||||
if (getMaker().getDepositTx() == null || (getTaker().getDepositTx() == null && !hasBuyerAsTakerWithoutDeposit())) return; // skip if either deposit tx not seen
|
||||
if (!isPublished(getMaker().getDepositTx()) || (!hasBuyerAsTakerWithoutDeposit() && !isPublished(getTaker().getDepositTx()))) return; // skip if deposit txs not published successfully
|
||||
setStateDepositsSeen();
|
||||
|
||||
// set actual security deposits
|
||||
@ -2750,6 +2750,13 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPublished(MoneroTx tx) {
|
||||
if (tx == null) return false;
|
||||
if (Boolean.TRUE.equals(tx.isFailed())) return false;
|
||||
if (!Boolean.TRUE.equals(tx.inTxPool()) && !Boolean.TRUE.equals(tx.isConfirmed())) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void syncWalletIfBehind() {
|
||||
synchronized (walletLock) {
|
||||
if (isWalletBehind()) {
|
||||
|
@ -460,9 +460,19 @@ public abstract class TradeProtocol implements DecryptedDirectMessageListener, D
|
||||
.using(new TradeTaskRunner(trade,
|
||||
() -> {
|
||||
stopTimeout();
|
||||
this.errorMessageHandler = null; // TODO: set this when trade state is >= DEPOSIT_PUBLISHED
|
||||
handleTaskRunnerSuccess(sender, response);
|
||||
if (tradeResultHandler != null) tradeResultHandler.handleResult(trade); // trade is initialized
|
||||
|
||||
// tasks may complete successfully but process an error
|
||||
if (trade.getInitError() == null) {
|
||||
this.errorMessageHandler = null; // TODO: set this when trade state is >= DEPOSIT_PUBLISHED
|
||||
handleTaskRunnerSuccess(sender, response);
|
||||
if (tradeResultHandler != null) tradeResultHandler.handleResult(trade); // trade is initialized
|
||||
} else {
|
||||
handleTaskRunnerSuccess(sender, response);
|
||||
if (errorMessageHandler != null) errorMessageHandler.handleErrorMessage(trade.getInitError().getMessage());
|
||||
}
|
||||
|
||||
this.tradeResultHandler = null;
|
||||
this.errorMessageHandler = null;
|
||||
},
|
||||
errorMessage -> {
|
||||
handleTaskRunnerFault(sender, response, errorMessage);
|
||||
|
@ -95,6 +95,18 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
|
||||
// set peer's signature
|
||||
sender.setContractSignature(signature);
|
||||
|
||||
// subscribe to trade state once to send responses with ack or nack
|
||||
if (!hasBothContractSignatures()) {
|
||||
trade.stateProperty().addListener((obs, oldState, newState) -> {
|
||||
if (oldState == newState) return;
|
||||
if (newState == Trade.State.PUBLISH_DEPOSIT_TX_REQUEST_FAILED) {
|
||||
sendDepositResponsesOnce(trade.getProcessModel().error == null ? "Arbitrator failed to publish deposit txs within timeout for trade " + trade.getId() : trade.getProcessModel().error.getMessage());
|
||||
} else if (newState.ordinal() >= Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TXS.ordinal()) {
|
||||
sendDepositResponsesOnce(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// collect expected values
|
||||
Offer offer = trade.getOffer();
|
||||
boolean isFromTaker = sender == trade.getTaker();
|
||||
@ -138,7 +150,7 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
|
||||
|
||||
// relay deposit txs when both requests received
|
||||
MoneroDaemon daemon = trade.getXmrWalletService().getDaemon();
|
||||
if (processModel.getMaker().getContractSignature() != null && processModel.getTaker().getContractSignature() != null) {
|
||||
if (hasBothContractSignatures()) {
|
||||
|
||||
// check timeout and extend just before relaying
|
||||
if (isTimedOut()) throw new RuntimeException("Trade protocol has timed out before relaying deposit txs for {} {}" + trade.getClass().getSimpleName() + " " + trade.getShortId());
|
||||
@ -182,22 +194,15 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
|
||||
// subscribe to trade state once to send responses with ack or nack
|
||||
trade.stateProperty().addListener((obs, oldState, newState) -> {
|
||||
if (oldState == newState) return;
|
||||
if (newState == Trade.State.PUBLISH_DEPOSIT_TX_REQUEST_FAILED) {
|
||||
sendDepositResponsesOnce(trade.getProcessModel().error == null ? "Arbitrator failed to publish deposit txs within timeout for trade " + trade.getId() : trade.getProcessModel().error.getMessage());
|
||||
} else if (newState.ordinal() >= Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TXS.ordinal()) {
|
||||
sendDepositResponsesOnce(null);
|
||||
}
|
||||
});
|
||||
|
||||
if (processModel.getMaker().getDepositTxHex() == null) log.info("Arbitrator waiting for deposit request from maker for trade " + trade.getId());
|
||||
if (processModel.getTaker().getDepositTxHex() == null && !trade.hasBuyerAsTakerWithoutDeposit()) log.info("Arbitrator waiting for deposit request from taker for trade " + trade.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasBothContractSignatures() {
|
||||
return processModel.getMaker().getContractSignature() != null && processModel.getTaker().getContractSignature() != null;
|
||||
}
|
||||
|
||||
private boolean isTimedOut() {
|
||||
return !processModel.getTradeManager().hasOpenTrade(trade);
|
||||
}
|
||||
@ -210,7 +215,7 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
|
||||
|
||||
// log error
|
||||
if (errorMessage != null) {
|
||||
log.warn("Sending deposit responses with error={}", errorMessage, new Throwable("Stack trace"));
|
||||
log.warn("Sending deposit responses for tradeId={}, error={}", trade.getId(), errorMessage);
|
||||
}
|
||||
|
||||
// create deposit response
|
||||
@ -229,7 +234,7 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
|
||||
}
|
||||
|
||||
private void sendDepositResponse(NodeAddress nodeAddress, PubKeyRing pubKeyRing, DepositResponse response) {
|
||||
log.info("Sending deposit response to trader={}; offerId={}, error={}", nodeAddress, trade.getId(), trade.getProcessModel().error);
|
||||
log.info("Sending deposit response to trader={}; offerId={}, error={}", nodeAddress, trade.getId(), response.getErrorMessage());
|
||||
processModel.getP2PService().sendEncryptedDirectMessage(nodeAddress, pubKeyRing, response, new SendDirectMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
|
@ -38,13 +38,14 @@ public class ProcessDepositResponse extends TradeTask {
|
||||
try {
|
||||
runInterceptHook();
|
||||
|
||||
// throw if error
|
||||
// handle error
|
||||
DepositResponse message = (DepositResponse) processModel.getTradeMessage();
|
||||
if (message.getErrorMessage() != null) {
|
||||
log.warn("Unregistering trade {} {} because deposit response has error message={}", trade.getClass().getSimpleName(), trade.getShortId(), message.getErrorMessage());
|
||||
log.warn("Deposit response for {} {} has error message={}", trade.getClass().getSimpleName(), trade.getShortId(), message.getErrorMessage());
|
||||
trade.setStateIfValidTransitionTo(Trade.State.PUBLISH_DEPOSIT_TX_REQUEST_FAILED);
|
||||
processModel.getTradeManager().unregisterTrade(trade);
|
||||
throw new RuntimeException(message.getErrorMessage());
|
||||
trade.setInitError(new RuntimeException(message.getErrorMessage()));
|
||||
complete();
|
||||
return;
|
||||
}
|
||||
|
||||
// record security deposits
|
||||
|
@ -105,7 +105,6 @@ public abstract class XmrWalletBase {
|
||||
// start polling wallet for progress
|
||||
syncProgressLatch = new CountDownLatch(1);
|
||||
syncProgressLooper = new TaskLooper(() -> {
|
||||
if (wallet == null) return;
|
||||
long height;
|
||||
try {
|
||||
height = wallet.getHeight(); // can get read timeout while syncing
|
||||
|
@ -346,7 +346,8 @@ public class DepositView extends ActivatableView<VBox, Void> {
|
||||
List<XmrAddressEntry> addressEntries = xmrWalletService.getAddressEntries();
|
||||
List<DepositListItem> items = new ArrayList<>();
|
||||
for (XmrAddressEntry addressEntry : addressEntries) {
|
||||
if (addressEntry.isTradePayout()) continue; // do not show trade payout addresses
|
||||
DepositListItem item = new DepositListItem(addressEntry, xmrWalletService, formatter);
|
||||
if (addressEntry.isTradePayout() && BigInteger.ZERO.equals(item.getBalanceAsBI())) continue; // do not show empty trade payout addresses
|
||||
items.add(new DepositListItem(addressEntry, xmrWalletService, formatter));
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user