Merge pull request #35 from haveno-dex/master

v1.0.14
This commit is contained in:
retoaccess1 2024-11-15 16:37:45 +00:00 committed by GitHub
commit c8a91de1b2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 126 additions and 127 deletions

View file

@ -610,7 +610,7 @@ configure(project(':desktop')) {
apply plugin: 'com.github.johnrengelman.shadow'
apply from: 'package/package.gradle'
version = '1.0.13-SNAPSHOT'
version = '1.0.14-SNAPSHOT'
jar.manifest.attributes(
"Implementation-Title": project.name,

View file

@ -28,7 +28,7 @@ import static com.google.common.base.Preconditions.checkArgument;
public class Version {
// The application versions
// We use semantic versioning with major, minor and patch
public static final String VERSION = "1.0.13";
public static final String VERSION = "1.0.14";
/**
* Holds a list of the tagged resource files for optimizing the getData requests.

View file

@ -32,6 +32,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
@ -76,11 +77,11 @@ public class FileUtil {
public static List<File> getBackupFiles(File dir, String fileName) {
File backupDir = new File(Paths.get(dir.getAbsolutePath(), BACKUP_DIR).toString());
if (!backupDir.exists()) return null;
if (!backupDir.exists()) return new ArrayList<File>();
String dirName = "backups_" + fileName;
if (dirName.contains(".")) dirName = dirName.replace(".", "_");
File backupFileDir = new File(Paths.get(backupDir.getAbsolutePath(), dirName).toString());
if (!backupFileDir.exists()) return null;
if (!backupFileDir.exists()) return new ArrayList<File>();
File[] files = backupFileDir.listFiles();
return Arrays.asList(files);
}

View file

@ -467,7 +467,7 @@ public final class Dispute implements NetworkPayload, PersistablePayload {
}
public boolean isOpen() {
return this.disputeState == State.OPEN || this.disputeState == State.REOPENED;
return isNew() || this.disputeState == State.OPEN || this.disputeState == State.REOPENED;
}
public boolean isClosed() {

View file

@ -359,6 +359,13 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
return;
}
// skip if payout is confirmed
if (trade.isPayoutConfirmed()) {
String errorMsg = "Cannot open dispute because payout is already confirmed for " + trade.getClass().getSimpleName() + " " + trade.getId();
faultHandler.handleFault(errorMsg, new IllegalStateException(errorMsg));
return;
}
synchronized (disputeList.getObservableList()) {
if (disputeList.contains(dispute)) {
String msg = "We got a dispute msg that we have already stored. TradeId = " + dispute.getTradeId() + ", DisputeId = " + dispute.getId();
@ -368,116 +375,109 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
}
Optional<Dispute> storedDisputeOptional = findDispute(dispute);
boolean reOpen = storedDisputeOptional.isPresent() && storedDisputeOptional.get().isClosed();
if (!storedDisputeOptional.isPresent() || reOpen) {
boolean reOpen = storedDisputeOptional.isPresent();
// add or re-open dispute
if (reOpen) {
dispute = storedDisputeOptional.get();
} else {
disputeList.add(dispute);
}
String disputeInfo = getDisputeInfo(dispute);
String sysMsg = dispute.isSupportTicket() ?
Res.get("support.youOpenedTicket", disputeInfo, Version.VERSION) :
Res.get("support.youOpenedDispute", disputeInfo, Version.VERSION);
ChatMessage chatMessage = new ChatMessage(
getSupportType(),
dispute.getTradeId(),
keyRing.getPubKeyRing().hashCode(),
false,
Res.get("support.systemMsg", sysMsg),
p2PService.getAddress());
chatMessage.setSystemMessage(true);
dispute.addAndPersistChatMessage(chatMessage);
// export latest multisig hex
try {
trade.exportMultisigHex();
} catch (Exception e) {
log.error("Failed to export multisig hex", e);
}
// create dispute opened message
NodeAddress agentNodeAddress = getAgentNodeAddress(dispute);
DisputeOpenedMessage disputeOpenedMessage = new DisputeOpenedMessage(dispute,
p2PService.getAddress(),
UUID.randomUUID().toString(),
getSupportType(),
trade.getSelf().getUpdatedMultisigHex(),
trade.getArbitrator().getPaymentSentMessage());
log.info("Send {} to peer {}. tradeId={}, openNewDisputeMessage.uid={}, " +
"chatMessage.uid={}",
disputeOpenedMessage.getClass().getSimpleName(), agentNodeAddress,
disputeOpenedMessage.getTradeId(), disputeOpenedMessage.getUid(),
chatMessage.getUid());
recordPendingMessage(disputeOpenedMessage.getClass().getSimpleName());
// send dispute opened message
trade.setDisputeState(Trade.DisputeState.DISPUTE_REQUESTED);
mailboxMessageService.sendEncryptedMailboxMessage(agentNodeAddress,
dispute.getAgentPubKeyRing(),
disputeOpenedMessage,
new SendMailboxMessageListener() {
@Override
public void onArrived() {
log.info("{} arrived at peer {}. tradeId={}, openNewDisputeMessage.uid={}, " +
"chatMessage.uid={}",
disputeOpenedMessage.getClass().getSimpleName(), agentNodeAddress,
disputeOpenedMessage.getTradeId(), disputeOpenedMessage.getUid(),
chatMessage.getUid());
clearPendingMessage();
// We use the chatMessage wrapped inside the openNewDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg
chatMessage.setArrived(true);
trade.advanceDisputeState(Trade.DisputeState.DISPUTE_REQUESTED);
requestPersistence();
resultHandler.handleResult();
}
@Override
public void onStoredInMailbox() {
log.info("{} stored in mailbox for peer {}. tradeId={}, openNewDisputeMessage.uid={}, " +
"chatMessage.uid={}",
disputeOpenedMessage.getClass().getSimpleName(), agentNodeAddress,
disputeOpenedMessage.getTradeId(), disputeOpenedMessage.getUid(),
chatMessage.getUid());
clearPendingMessage();
// We use the chatMessage wrapped inside the openNewDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg
chatMessage.setStoredInMailbox(true);
requestPersistence();
resultHandler.handleResult();
}
@Override
public void onFault(String errorMessage) {
log.error("{} failed: Peer {}. tradeId={}, openNewDisputeMessage.uid={}, " +
"chatMessage.uid={}, errorMessage={}",
disputeOpenedMessage.getClass().getSimpleName(), agentNodeAddress,
disputeOpenedMessage.getTradeId(), disputeOpenedMessage.getUid(),
chatMessage.getUid(), errorMessage);
clearPendingMessage();
// We use the chatMessage wrapped inside the openNewDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg
chatMessage.setSendMessageError(errorMessage);
trade.setDisputeState(Trade.DisputeState.NO_DISPUTE);
requestPersistence();
faultHandler.handleFault("Sending dispute message failed: " +
errorMessage, new DisputeMessageDeliveryFailedException());
}
});
// add or re-open dispute
if (reOpen) {
dispute = storedDisputeOptional.get();
} else {
String msg = "We got a dispute already open for that trade and trading peer.\n" +
"TradeId = " + dispute.getTradeId();
log.warn(msg);
faultHandler.handleFault(msg, new DisputeAlreadyOpenException());
disputeList.add(dispute);
}
String disputeInfo = getDisputeInfo(dispute);
String sysMsg = dispute.isSupportTicket() ?
Res.get("support.youOpenedTicket", disputeInfo, Version.VERSION) :
Res.get("support.youOpenedDispute", disputeInfo, Version.VERSION);
ChatMessage chatMessage = new ChatMessage(
getSupportType(),
dispute.getTradeId(),
keyRing.getPubKeyRing().hashCode(),
false,
Res.get("support.systemMsg", sysMsg),
p2PService.getAddress());
chatMessage.setSystemMessage(true);
dispute.addAndPersistChatMessage(chatMessage);
// export latest multisig hex
try {
trade.exportMultisigHex();
} catch (Exception e) {
log.error("Failed to export multisig hex", e);
}
// create dispute opened message
NodeAddress agentNodeAddress = getAgentNodeAddress(dispute);
DisputeOpenedMessage disputeOpenedMessage = new DisputeOpenedMessage(dispute,
p2PService.getAddress(),
UUID.randomUUID().toString(),
getSupportType(),
trade.getSelf().getUpdatedMultisigHex(),
trade.getArbitrator().getPaymentSentMessage());
log.info("Send {} to peer {}. tradeId={}, openNewDisputeMessage.uid={}, " +
"chatMessage.uid={}",
disputeOpenedMessage.getClass().getSimpleName(), agentNodeAddress,
disputeOpenedMessage.getTradeId(), disputeOpenedMessage.getUid(),
chatMessage.getUid());
recordPendingMessage(disputeOpenedMessage.getClass().getSimpleName());
// send dispute opened message
trade.setDisputeState(Trade.DisputeState.DISPUTE_REQUESTED);
mailboxMessageService.sendEncryptedMailboxMessage(agentNodeAddress,
dispute.getAgentPubKeyRing(),
disputeOpenedMessage,
new SendMailboxMessageListener() {
@Override
public void onArrived() {
log.info("{} arrived at peer {}. tradeId={}, openNewDisputeMessage.uid={}, " +
"chatMessage.uid={}",
disputeOpenedMessage.getClass().getSimpleName(), agentNodeAddress,
disputeOpenedMessage.getTradeId(), disputeOpenedMessage.getUid(),
chatMessage.getUid());
clearPendingMessage();
// We use the chatMessage wrapped inside the openNewDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg
chatMessage.setArrived(true);
trade.advanceDisputeState(Trade.DisputeState.DISPUTE_REQUESTED);
requestPersistence();
resultHandler.handleResult();
}
@Override
public void onStoredInMailbox() {
log.info("{} stored in mailbox for peer {}. tradeId={}, openNewDisputeMessage.uid={}, " +
"chatMessage.uid={}",
disputeOpenedMessage.getClass().getSimpleName(), agentNodeAddress,
disputeOpenedMessage.getTradeId(), disputeOpenedMessage.getUid(),
chatMessage.getUid());
clearPendingMessage();
// We use the chatMessage wrapped inside the openNewDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg
chatMessage.setStoredInMailbox(true);
requestPersistence();
resultHandler.handleResult();
}
@Override
public void onFault(String errorMessage) {
log.error("{} failed: Peer {}. tradeId={}, openNewDisputeMessage.uid={}, " +
"chatMessage.uid={}, errorMessage={}",
disputeOpenedMessage.getClass().getSimpleName(), agentNodeAddress,
disputeOpenedMessage.getTradeId(), disputeOpenedMessage.getUid(),
chatMessage.getUid(), errorMessage);
clearPendingMessage();
// We use the chatMessage wrapped inside the openNewDisputeMessage for
// the state, as that is displayed to the user and we only persist that msg
chatMessage.setSendMessageError(errorMessage);
trade.setDisputeState(Trade.DisputeState.NO_DISPUTE);
requestPersistence();
faultHandler.handleFault("Sending dispute message failed: " +
errorMessage, new DisputeMessageDeliveryFailedException());
}
});
}
requestPersistence();

View file

@ -5,10 +5,10 @@
<!-- See: https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -->
<key>CFBundleVersion</key>
<string>1.0.13</string>
<string>1.0.14</string>
<key>CFBundleShortVersionString</key>
<string>1.0.13</string>
<string>1.0.14</string>
<key>CFBundleExecutable</key>
<string>Haveno</string>

View file

@ -308,7 +308,7 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel<?>> exten
if (CurrencyUtil.isTraditionalCurrency(tradeCurrency.getCode())) {
placeOfferButtonLabel = Res.get("createOffer.placeOfferButton", Res.get("shared.buy"));
} else {
placeOfferButtonLabel = Res.get("createOffer.placeOfferButtonCrypto", Res.get("shared.buy"), tradeCurrency.getCode());
placeOfferButtonLabel = Res.get("createOffer.placeOfferButtonCrypto", Res.get("shared.sell"), tradeCurrency.getCode());
}
nextButton.setId("buy-button");
fundFromSavingsWalletButton.setId("buy-button");
@ -317,7 +317,7 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel<?>> exten
if (CurrencyUtil.isTraditionalCurrency(tradeCurrency.getCode())) {
placeOfferButtonLabel = Res.get("createOffer.placeOfferButton", Res.get("shared.sell"));
} else {
placeOfferButtonLabel = Res.get("createOffer.placeOfferButtonCrypto", Res.get("shared.sell"), tradeCurrency.getCode());
placeOfferButtonLabel = Res.get("createOffer.placeOfferButtonCrypto", Res.get("shared.buy"), tradeCurrency.getCode());
}
nextButton.setId("sell-button");
fundFromSavingsWalletButton.setId("sell-button");
@ -707,10 +707,10 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel<?>> exten
triggerPriceInputTextField.clear();
if (!CurrencyUtil.isTraditionalCurrency(newValue)) {
if (model.isShownAsBuyOffer()) {
placeOfferButton.updateText(Res.get("createOffer.placeOfferButtonCrypto", Res.get("shared.buy"),
placeOfferButton.updateText(Res.get("createOffer.placeOfferButtonCrypto", Res.get("shared.sell"),
model.getTradeCurrency().getCode()));
} else {
placeOfferButton.updateText(Res.get("createOffer.placeOfferButtonCrypto", Res.get("shared.sell"),
placeOfferButton.updateText(Res.get("createOffer.placeOfferButtonCrypto", Res.get("shared.buy"),
model.getTradeCurrency().getCode()));
}
}

View file

@ -402,9 +402,7 @@ abstract class OfferBookViewModel extends ActivatableViewModel {
}
public Optional<Double> getMarketBasedPrice(Offer offer) {
OfferDirection displayDirection = offer.isTraditionalOffer() ? direction :
direction.equals(OfferDirection.BUY) ? OfferDirection.SELL : OfferDirection.BUY;
return priceUtil.getMarketBasedPrice(offer, displayDirection);
return priceUtil.getMarketBasedPrice(offer, direction);
}
String formatMarketPriceMarginPct(Offer offer) {

View file

@ -306,12 +306,12 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
takeOfferButton.setId("buy-button-big");
nextButton.setId("buy-button");
fundFromSavingsWalletButton.setId("buy-button");
takeOfferButton.updateText(getTakeOfferLabel(offer, Res.get("shared.buy")));
takeOfferButton.updateText(getTakeOfferLabel(offer, false));
} else {
takeOfferButton.setId("sell-button-big");
nextButton.setId("sell-button");
fundFromSavingsWalletButton.setId("sell-button");
takeOfferButton.updateText(getTakeOfferLabel(offer, Res.get("shared.sell")));
takeOfferButton.updateText(getTakeOfferLabel(offer, true));
}
priceAsPercentageDescription.setText(model.getPercentagePriceDescription());
@ -1232,11 +1232,11 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
}
@NotNull
private String getTakeOfferLabel(Offer offer, String direction) {
private String getTakeOfferLabel(Offer offer, boolean isBuyOffer) {
return offer.isTraditionalOffer() ?
Res.get("takeOffer.takeOfferButton", direction) :
Res.get("takeOffer.takeOfferButton", isBuyOffer ? Res.get("shared.sell") : Res.get("shared.buy")) :
Res.get("takeOffer.takeOfferButtonCrypto",
direction,
isBuyOffer ? Res.get("shared.buy") : Res.get("shared.sell"),
offer.getCurrencyCode());
}

View file

@ -41,7 +41,7 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class SeedNodeMain extends ExecutableForAppWithP2p {
private static final long CHECK_CONNECTION_LOSS_SEC = 30;
private static final String VERSION = "1.0.13";
private static final String VERSION = "1.0.14";
private SeedNode seedNode;
private Timer checkConnectionLossTime;