Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make sign age column sortable #4929

Merged
merged 3 commits into from
Dec 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,12 @@ public enum SignState {
PEER_SIGNER(Res.get("offerbook.timeSinceSigning.info.signer")),
BANNED(Res.get("offerbook.timeSinceSigning.info.banned"));

private String presentation;
private String displayString;
private String hash = "";
private long daysUntilLimitLifted = 0;

SignState(String presentation) {
this.presentation = presentation;
SignState(String displayString) {
this.displayString = displayString;
}

public SignState addHash(String hash) {
Expand All @@ -120,11 +120,11 @@ public SignState setDaysUntilLimitLifted(long days) {
return this;
}

public String getPresentation() {
public String getDisplayString() {
if (!hash.isEmpty()) { // Only showing in DEBUG mode
return presentation + " " + hash;
return displayString + " " + hash;
}
return String.format(presentation, daysUntilLimitLifted);
return String.format(displayString, daysUntilLimitLifted);
}

}
Expand Down Expand Up @@ -265,7 +265,7 @@ Optional<AccountAgeWitness> findWitness(PaymentAccountPayload paymentAccountPayl
return getWitnessByHash(hash);
}

private Optional<AccountAgeWitness> findWitness(Offer offer) {
public Optional<AccountAgeWitness> findWitness(Offer offer) {
final Optional<String> accountAgeWitnessHash = offer.getAccountAgeWitnessHashAsHex();
return accountAgeWitnessHash.isPresent() ?
getWitnessByHashAsHex(accountAgeWitnessHash.get()) :
Expand Down Expand Up @@ -613,7 +613,10 @@ private boolean verifyPeersTradeLimit(Offer offer,
if (!result) {
String msg = "The peers trade limit is less than the traded amount.\n" +
"tradeAmount=" + tradeAmount.toFriendlyString() +
"\nPeers trade limit=" + Coin.valueOf(peersCurrentTradeLimit).toFriendlyString();
"\nPeers trade limit=" + Coin.valueOf(peersCurrentTradeLimit).toFriendlyString() +
"\nOffer ID=" + offer.getShortId() +
"\nPaymentMethod=" + offer.getPaymentMethod().getId() +
"\nCurrencyCode=" + offer.getCurrencyCode();
log.warn(msg);
errorMessageHandler.handleErrorMessage(msg);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ private String getWitnessDebugLog(PaymentAccountPayload paymentAccountPayload,

AccountAgeWitnessService.SignState signState =
accountAgeWitnessService.getSignState(accountAgeWitness.get());
return signState.name() + " " + signState.getPresentation() +
return signState.name() + " " + signState.getDisplayString() +
"\n" + accountAgeWitness.toString();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ private Tuple5<Long, Long, String, String, String> getPeersAccountAge(@Nullable

if (hasChargebackRisk(trade, offer)) {
String signAgeInfo = Res.get("peerInfo.age.chargeBackRisk");
String accountSigningState = StringUtils.capitalize(signState.getPresentation());
String accountSigningState = StringUtils.capitalize(signState.getDisplayString());
if (signState.equals(AccountAgeWitnessService.SignState.UNSIGNED))
signAgeInfo = null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ protected void addLimitations(boolean isDisplayForm) {
AccountAgeWitnessService.SignState signState =
accountAgeWitnessService.getSignState(myWitness);

accountSigningStateText = StringUtils.capitalize(signState.getPresentation());
accountSigningStateText = StringUtils.capitalize(signState.getDisplayString());

long daysSinceSigning = TimeUnit.MILLISECONDS.toDays(
accountAgeWitnessService.getWitnessSignAge(myWitness, new Date()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@
import bisq.desktop.util.GUIUtil;
import bisq.desktop.util.ImageUtil;

import bisq.core.account.sign.SignedWitnessService;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.locale.Res;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.payload.PaymentMethod;

import bisq.common.UserThread;
import bisq.common.app.DevEnv;
import bisq.common.util.Utilities;

import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -144,7 +142,7 @@ public void updateItem(final PaymentAccount item, boolean empty) {
accountAgeWitnessService.getSignState(accountAgeWitnessService.getMyWitness(
item.paymentAccountPayload));

String info = StringUtils.capitalize(signState.getPresentation());
String info = StringUtils.capitalize(signState.getDisplayString());
label.setIcon(GUIUtil.getIconForSignState(signState), info);
} else {
label.hideIcon();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,140 @@

package bisq.desktop.main.offer.offerbook;

import bisq.desktop.util.GUIUtil;

import bisq.core.account.sign.SignedWitnessService;
import bisq.core.account.witness.AccountAgeWitness;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.locale.CurrencyUtil;
import bisq.core.locale.Res;
import bisq.core.offer.Offer;
import bisq.core.payment.payload.PaymentMethod;

import de.jensd.fx.glyphs.GlyphIcons;
import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon;

import java.util.Date;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import lombok.Getter;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;

@Slf4j

@Value
public class OfferBookListItem {
@Getter
private final Offer offer;

// We cache the data once created for performance reasons. AccountAgeWitnessService calls can
// be a bit expensive.
private WitnessAgeData witnessAgeData;

public OfferBookListItem(Offer offer) {
this.offer = offer;
}

public WitnessAgeData getWitnessAgeData(AccountAgeWitnessService accountAgeWitnessService,
SignedWitnessService signedWitnessService) {
if (witnessAgeData == null) {
long ageInMs;
long daysSinceSignedAsLong = -1;
long accountAgeDaysAsLong = -1;
long accountAgeDaysNotYetSignedAsLong = -1;
String displayString;
String info;
GlyphIcons icon;

if (CurrencyUtil.isCryptoCurrency(offer.getCurrencyCode())) {
// Altcoins
displayString = Res.get("offerbook.timeSinceSigning.notSigned.noNeed");
info = Res.get("shared.notSigned.noNeedAlts");
icon = MaterialDesignIcon.INFORMATION_OUTLINE;
} else if (PaymentMethod.hasChargebackRisk(offer.getPaymentMethod(), offer.getCurrencyCode())) {
// Fiat and signed witness required
Optional<AccountAgeWitness> optionalWitness = accountAgeWitnessService.findWitness(offer);
AccountAgeWitnessService.SignState signState = optionalWitness.map(accountAgeWitnessService::getSignState)
.orElse(AccountAgeWitnessService.SignState.UNSIGNED);
boolean isSignedAccountAgeWitness = optionalWitness.map(signedWitnessService::isSignedAccountAgeWitness)
.orElse(false);
if (isSignedAccountAgeWitness || !signState.equals(AccountAgeWitnessService.SignState.UNSIGNED)) {
// either signed & limits lifted, or waiting for limits to be lifted
// Or banned
daysSinceSignedAsLong = TimeUnit.MILLISECONDS.toDays(optionalWitness.map(witness ->
accountAgeWitnessService.getWitnessSignAge(witness, new Date()))
.orElse(0L));
displayString = Res.get("offerbook.timeSinceSigning.daysSinceSigning", daysSinceSignedAsLong);
info = Res.get("offerbook.timeSinceSigning.info", signState.getDisplayString());
} else {
// Unsigned case
ageInMs = optionalWitness.map(e -> accountAgeWitnessService.getAccountAge(e, new Date()))
.orElse(-1L);
accountAgeDaysNotYetSignedAsLong = ageInMs > -1 ? TimeUnit.MILLISECONDS.toDays(ageInMs) : 0;
displayString = Res.get("offerbook.timeSinceSigning.notSigned");
info = Res.get("shared.notSigned", accountAgeDaysNotYetSignedAsLong);
}

icon = GUIUtil.getIconForSignState(signState);
} else {
// Fiat, no signed witness required, we show account age
ageInMs = accountAgeWitnessService.getAccountAge(offer);
accountAgeDaysAsLong = ageInMs > -1 ? TimeUnit.MILLISECONDS.toDays(ageInMs) : 0;
displayString = Res.get("offerbook.timeSinceSigning.notSigned.ageDays", accountAgeDaysAsLong);
info = Res.get("shared.notSigned.noNeedDays", accountAgeDaysAsLong);
icon = MaterialDesignIcon.CHECKBOX_MARKED_OUTLINE;
}

witnessAgeData = new WitnessAgeData(displayString, info, icon, daysSinceSignedAsLong, accountAgeDaysNotYetSignedAsLong, accountAgeDaysAsLong);
}
return witnessAgeData;
}

@Value
public static class WitnessAgeData {
private final String displayString;
private final String info;
private final GlyphIcons icon;
private final Long daysSinceSignedAsLong;
private final long accountAgeDaysNotYetSignedAsLong;
private final Long accountAgeDaysAsLong;
// Used for sorting
private final Long type;
// Used for sorting
private final Long days;

public WitnessAgeData(String displayString,
String info,
GlyphIcons icon,
long daysSinceSignedAsLong,
long accountAgeDaysNotYetSignedAsLong,
long accountAgeDaysAsLong) {
this.displayString = displayString;
this.info = info;
this.icon = icon;
this.daysSinceSignedAsLong = daysSinceSignedAsLong;
this.accountAgeDaysNotYetSignedAsLong = accountAgeDaysNotYetSignedAsLong;
this.accountAgeDaysAsLong = accountAgeDaysAsLong;

if (daysSinceSignedAsLong > -1) {
// First we show signed accounts sorted by days
this.type = 3L;
this.days = daysSinceSignedAsLong;
} else if (accountAgeDaysNotYetSignedAsLong > -1) {
// Next group is not yet signed accounts sorted by account age
this.type = 2L;
this.days = accountAgeDaysNotYetSignedAsLong;
} else if (accountAgeDaysAsLong > -1) {
// Next group is not signing required accounts sorted by account age
this.type = 1L;
this.days = accountAgeDaysAsLong;
} else {
// No signing and age required (altcoins)
this.type = 0L;
this.days = 0L;
}
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@
import javax.inject.Named;

import de.jensd.fx.fontawesome.AwesomeIcon;
import de.jensd.fx.glyphs.GlyphIcons;
import de.jensd.fx.glyphs.materialdesignicons.MaterialDesignIcon;

import javafx.scene.canvas.Canvas;
Expand Down Expand Up @@ -107,9 +106,7 @@
import javafx.util.StringConverter;

import java.util.Comparator;
import java.util.Date;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import org.jetbrains.annotations.NotNull;

Expand All @@ -124,6 +121,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
private final PrivateNotificationManager privateNotificationManager;
private final boolean useDevPrivilegeKeys;
private final AccountAgeWitnessService accountAgeWitnessService;
private final SignedWitnessService signedWitnessService;

private AutocompleteComboBox<TradeCurrency> currencyComboBox;
private AutocompleteComboBox<PaymentMethod> paymentMethodComboBox;
Expand Down Expand Up @@ -151,7 +149,8 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
@Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter,
PrivateNotificationManager privateNotificationManager,
@Named(Config.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys,
AccountAgeWitnessService accountAgeWitnessService) {
AccountAgeWitnessService accountAgeWitnessService,
SignedWitnessService signedWitnessService) {
super(model);

this.navigation = navigation;
Expand All @@ -160,6 +159,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
this.privateNotificationManager = privateNotificationManager;
this.useDevPrivilegeKeys = useDevPrivilegeKeys;
this.accountAgeWitnessService = accountAgeWitnessService;
this.signedWitnessService = signedWitnessService;
}

@Override
Expand Down Expand Up @@ -261,6 +261,11 @@ public void initialize() {

}, Comparator.nullsFirst(Comparator.naturalOrder())));

Comparator<OfferBookListItem> comparator = Comparator.comparing(e -> e.getWitnessAgeData(accountAgeWitnessService, signedWitnessService).getType(), Comparator.nullsFirst(Comparator.naturalOrder()));
signingStateColumn.setComparator(comparator.
thenComparing(e -> e.getWitnessAgeData(accountAgeWitnessService, signedWitnessService).getDays(),
Comparator.nullsFirst(Comparator.naturalOrder())));

nrOfOffersLabel = new AutoTooltipLabel("");
nrOfOffersLabel.setId("num-offers");
GridPane.setHalignment(nrOfOffersLabel, HPos.LEFT);
Expand Down Expand Up @@ -1108,55 +1113,11 @@ public void updateItem(final OfferBookListItem item, boolean empty) {
super.updateItem(item, empty);

if (item != null && !empty) {

GlyphIcons icon;
String info;
String timeSinceSigning;

boolean needsSigning = PaymentMethod.hasChargebackRisk(
item.getOffer().getPaymentMethod(), item.getOffer().getCurrencyCode());

if (needsSigning) {
if (accountAgeWitnessService.hasSignedWitness(item.getOffer())) {
// either signed & limits lifted, or waiting for limits to be lifted
AccountAgeWitnessService.SignState signState = accountAgeWitnessService.getSignState(item.getOffer());
icon = GUIUtil.getIconForSignState(signState);
info = Res.get("offerbook.timeSinceSigning.info",
signState.getPresentation());
long daysSinceSigning = TimeUnit.MILLISECONDS.toDays(
accountAgeWitnessService.getWitnessSignAge(item.getOffer(), new Date()));
timeSinceSigning = Res.get("offerbook.timeSinceSigning.daysSinceSigning",
daysSinceSigning);
} else {
// either banned, unsigned
AccountAgeWitnessService.SignState signState = accountAgeWitnessService.getSignState(item.getOffer());
icon = GUIUtil.getIconForSignState(signState);
if (!signState.equals(AccountAgeWitnessService.SignState.UNSIGNED)) {
info = Res.get("offerbook.timeSinceSigning.info", signState.getPresentation());
long daysSinceSigning = TimeUnit.MILLISECONDS.toDays(
accountAgeWitnessService.getWitnessSignAge(item.getOffer(), new Date()));
timeSinceSigning = Res.get("offerbook.timeSinceSigning.daysSinceSigning",
daysSinceSigning);
} else {
long accountAge = TimeUnit.MILLISECONDS.toDays(accountAgeWitnessService.getAccountAge(item.getOffer()));
info = Res.get("shared.notSigned", accountAge);
timeSinceSigning = Res.get("offerbook.timeSinceSigning.notSigned", accountAge);
}
}
} else {
if (CurrencyUtil.isFiatCurrency(item.getOffer().getCurrencyCode())) {
icon = MaterialDesignIcon.CHECKBOX_MARKED_OUTLINE;
long days = TimeUnit.MILLISECONDS.toDays(accountAgeWitnessService.getAccountAge(item.getOffer()));
info = Res.get("shared.notSigned.noNeedDays", days);
timeSinceSigning = Res.get("offerbook.timeSinceSigning.notSigned.ageDays", days);
} else { // altcoins
icon = MaterialDesignIcon.INFORMATION_OUTLINE;
info = Res.get("shared.notSigned.noNeedAlts");
timeSinceSigning = Res.get("offerbook.timeSinceSigning.notSigned.noNeed");
}
}

InfoAutoTooltipLabel label = new InfoAutoTooltipLabel(timeSinceSigning, icon, ContentDisplay.RIGHT, info);
var witnessAgeData = item.getWitnessAgeData(accountAgeWitnessService, signedWitnessService);
InfoAutoTooltipLabel label = new InfoAutoTooltipLabel(witnessAgeData.getDisplayString(),
witnessAgeData.getIcon(),
ContentDisplay.RIGHT,
witnessAgeData.getInfo());
setGraphic(label);
} else {
setGraphic(null);
Expand Down
2 changes: 1 addition & 1 deletion desktop/src/main/java/bisq/desktop/util/GUIUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@ protected void updateItem(PaymentAccount item, boolean empty) {
item.paymentAccountPayload);
AccountAgeWitnessService.SignState signState =
accountAgeWitnessService.getSignState(myWitness);
String info = StringUtils.capitalize(signState.getPresentation());
String info = StringUtils.capitalize(signState.getDisplayString());

MaterialDesignIcon icon;

Expand Down