Skip to content

Commit

Permalink
Merge pull request #2991 from axpoems/imp-trade-details-popup
Browse files Browse the repository at this point in the history
Improve trade details popup
  • Loading branch information
HenrikJannsen authored Nov 10, 2024
2 parents 7a1e9f7 + dfa679c commit d19341f
Show file tree
Hide file tree
Showing 8 changed files with 348 additions and 431 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,24 @@ public static String createOfferBookMessageFromPeerPerspective(String messageOwn
}

public static String getFormattedPriceSpec(PriceSpec priceSpec) {
return getFormattedPriceSpec(priceSpec, false);
}

public static String getFormattedPriceSpec(PriceSpec priceSpec, boolean abbreviated) {
String priceInfo;
if (priceSpec instanceof FixPriceSpec fixPriceSpec) {
String price = PriceFormatter.formatWithCode(fixPriceSpec.getPriceQuote());
priceInfo = Res.get("bisqEasy.tradeWizard.review.chatMessage.fixPrice", price);
} else if (priceSpec instanceof FloatPriceSpec floatPriceSpec) {
String percent = PercentageFormatter.formatToPercentWithSymbol(Math.abs(floatPriceSpec.getPercentage()));
priceInfo = Res.get(floatPriceSpec.getPercentage() >= 0
? "bisqEasy.tradeWizard.review.chatMessage.floatPrice.above"
: "bisqEasy.tradeWizard.review.chatMessage.floatPrice.below", percent);
? abbreviated
? "bisqEasy.tradeWizard.review.chatMessage.floatPrice.plus"
: "bisqEasy.tradeWizard.review.chatMessage.floatPrice.above"
: abbreviated
? "bisqEasy.tradeWizard.review.chatMessage.floatPrice.minus"
: "bisqEasy.tradeWizard.review.chatMessage.floatPrice.below"
, percent);
} else {
priceInfo = Res.get("bisqEasy.tradeWizard.review.chatMessage.marketPrice");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,158 +17,101 @@

package bisq.desktop.main.content.bisq_easy.open_trades.trade_details;

import bisq.account.payment_method.BitcoinPaymentRail;
import bisq.bisq_easy.NavigationTarget;
import bisq.chat.bisqeasy.open_trades.BisqEasyOpenTradeChannel;
import bisq.common.monetary.Coin;
import bisq.common.monetary.Fiat;
import bisq.common.monetary.Monetary;
import bisq.common.monetary.PriceQuote;
import bisq.common.network.AddressByTransportTypeMap;
import bisq.common.util.StringUtils;
import bisq.contract.bisq_easy.BisqEasyContract;
import bisq.desktop.ServiceProvider;
import bisq.desktop.common.view.Controller;
import bisq.desktop.common.view.InitWithDataController;
import bisq.desktop.common.view.NavigationController;
import bisq.desktop.main.content.bisq_easy.BisqEasyServiceUtil;
import bisq.desktop.overlay.OverlayController;
import bisq.i18n.Res;
import bisq.network.identity.NetworkId;
import bisq.offer.Direction;
import bisq.offer.price.spec.FixPriceSpec;
import bisq.offer.price.spec.FloatPriceSpec;
import bisq.offer.price.spec.MarketPriceSpec;
import bisq.offer.price.spec.PriceSpec;
import bisq.presentation.formatters.AmountFormatter;
import bisq.presentation.formatters.DateFormatter;
import bisq.presentation.formatters.PercentageFormatter;
import bisq.presentation.formatters.PriceFormatter;
import bisq.trade.bisq_easy.BisqEasyTrade;
import bisq.trade.bisq_easy.BisqEasyTradeFormatter;
import bisq.trade.bisq_easy.BisqEasyTradeUtils;
import bisq.user.identity.UserIdentityService;
import bisq.user.profile.UserProfile;
import com.google.common.base.Joiner;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
public class TradeDetailsController extends NavigationController
implements InitWithDataController<TradeDetailsController.InitData> {
protected final UserIdentityService userIdentityService;
public class TradeDetailsController extends NavigationController implements InitWithDataController<TradeDetailsController.InitData> {
@Getter
private final TradeDetailsView view;
@EqualsAndHashCode
@ToString
public static class InitData {
private final BisqEasyTrade bisqEasyTrade;
private final BisqEasyOpenTradeChannel channel;

public InitData(BisqEasyTrade bisqEasyTrade, BisqEasyOpenTradeChannel channel) {
this.bisqEasyTrade = bisqEasyTrade;
this.channel = channel;
}
}

@Getter
private final TradeDetailsModel model;
@Getter
private final TradeDetailsView view;
private BisqEasyTrade trade;
private BisqEasyOpenTradeChannel channel;
BisqEasyContract contract;

public TradeDetailsController(ServiceProvider serviceProvider) {
super(NavigationTarget.BISQ_EASY_TRADE_DETAILS);

userIdentityService = serviceProvider.getUserService().getUserIdentityService();
model = new TradeDetailsModel();
view = new TradeDetailsView(model, this);
}

private static String getPriceSpec(BisqEasyContract contract) {
PriceSpec priceSpec = contract.getAgreedPriceSpec();
String priceSpecStr = "";
switch (priceSpec) {
case MarketPriceSpec marketPriceSpec ->
priceSpecStr = Res.get("bisqEasy.openTrades.tradeDetails.marketPrice");
case FloatPriceSpec floatPriceSpec -> {
String absPercent = PercentageFormatter.formatToPercentWithSymbol(Math.abs(floatPriceSpec.getPercentage()));
priceSpecStr = Res.get(floatPriceSpec.getPercentage() >= 0
? "bisqEasy.openTrades.tradeDetails.aboveMarketPrice"
: "bisqEasy.openTrades.tradeDetails.belowMarketPrice", absPercent);
}
case FixPriceSpec fixPriceSpec -> priceSpecStr = Res.get("bisqEasy.openTrades.tradeDetails.fixedPrice");
case null, default -> {
// this should not happen unless a new PriceSpec is added
}
}
return priceSpecStr;
}

private static String formatNetworkAddresses(AddressByTransportTypeMap addressMap) {
return Joiner.on(", ").join(addressMap.entrySet().stream()
.map(e -> e.getValue().getFullAddress())
.collect(Collectors.toList()));
}

@Override
public void initWithData(InitData initData) {
BisqEasyTrade trade = initData.bisqEasyTrade;
BisqEasyOpenTradeChannel channel = initData.channel;
model.getTradeId().set(trade.getId());
model.getPeerUsername().set(channel.getPeer().getUserName());

String bitcoinPaymentAddress = trade.getBitcoinPaymentData().get();
if (StringUtils.isNotEmpty(bitcoinPaymentAddress)) {
model.getBitcoinPaymentAddress().set(bitcoinPaymentAddress);
} else {
model.getBitcoinPaymentAddress().set("");
}

BisqEasyContract contract = trade.getContract();
long date = contract.getTakeOfferDate();
model.getOfferTakenDateTime().set(DateFormatter.formatDateTime(date));

long quoteSideAmount = contract.getQuoteSideAmount();
Monetary quoteAmount = Fiat.from(quoteSideAmount, trade.getOffer().getMarket().getQuoteCurrencyCode());

NetworkId peerNetworkId = trade.getPeer().getNetworkId();
String peerAddress = formatNetworkAddresses(peerNetworkId.getAddressByTransportTypeMap());
model.getPeerNetworkAddress().set(peerAddress);

String amountInFiat = AmountFormatter.formatAmount(quoteAmount);
model.getAmountInFiat().set(amountInFiat);
String currencyAbbreviation = quoteAmount.getCode();
model.getCurrency().set(currencyAbbreviation);

long baseSideAmount = contract.getBaseSideAmount();
Coin amountInBTC = Coin.asBtcFromValue(baseSideAmount);
String baseAmountString = AmountFormatter.formatAmount(amountInBTC, false);
model.getAmountInBTC().set(baseAmountString);

String btcPaymentMethod = contract.getBaseSidePaymentMethodSpec().getDisplayString();
model.getBitcoinPaymentMethod().set(btcPaymentMethod);
String fiatPaymentMethod = contract.getQuoteSidePaymentMethodSpec().getDisplayString();
model.getFiatPaymentMethod().set(fiatPaymentMethod);

String paymentAccountData = trade.getPaymentAccountData().get();
if (StringUtils.isNotEmpty(paymentAccountData)) {
model.getPaymentAccountData().set(paymentAccountData);
} else {
model.getPaymentAccountData().set("");
}

String myMakerTakerRole = BisqEasyTradeFormatter.getMakerTakerRole(trade);
model.getMyMakerTakerRole().set(myMakerTakerRole);
Direction direction = BisqEasyTradeFormatter.getDirectionObject(trade);
String buyerSellerRole = (direction == Direction.BUY) ? Res.get("bisqEasy.openTrades.tradeDetails.buyBtc") : Res.get("bisqEasy.openTrades.tradeDetails.sellBtc");
model.getMySellBuyRole().set(buyerSellerRole);

Optional<UserProfile> mediator = channel.getMediator();
if (mediator.isPresent()) {
model.getMediator().set(mediator.get().getUserName());
} else {
model.getMediator().set("");
}

PriceQuote priceQuote = BisqEasyTradeUtils.getPriceQuote(trade);
String codes = priceQuote.getMarket().getMarketCodes();
model.getPriceSpec().set(codes + " @ " + getPriceSpec(contract));
String price = PriceFormatter.format(BisqEasyTradeUtils.getPriceQuote(trade));
model.getTradePrice().set(price);
trade = initData.bisqEasyTrade;
channel = initData.channel;
contract = trade.getContract();
}

@Override
public void onActivate() {
model.setTradeDate(DateFormatter.formatDateTime(contract.getTakeOfferDate()));
model.setMe(String.format("%s (%s)", channel.getMyUserIdentity().getNickName(), BisqEasyTradeFormatter.getMakerTakerRole(trade).toLowerCase()));
model.setPeer(channel.getPeer().getUserName());
model.setOfferType(trade.getOffer().getDirection().isBuy()
? Res.get("bisqEasy.openTrades.tradeDetails.offerTypeAndMarket.buyOffer")
: Res.get("bisqEasy.openTrades.tradeDetails.offerTypeAndMarket.sellOffer"));
model.setMarket(Res.get("bisqEasy.openTrades.tradeDetails.offerTypeAndMarket.fiatMarket",
trade.getOffer().getMarket().getQuoteCurrencyCode()));
model.setFiatAmount(BisqEasyTradeFormatter.formatQuoteSideAmount(trade));
model.setFiatCurrency(trade.getOffer().getMarket().getQuoteCurrencyCode());
model.setBtcAmount(BisqEasyTradeFormatter.formatBaseSideAmount(trade));
model.setPrice(PriceFormatter.format(BisqEasyTradeUtils.getPriceQuote(contract)));
model.setPriceCodes(trade.getOffer().getMarket().getMarketCodes());
model.setPriceSpec(trade.getOffer().getPriceSpec() instanceof FixPriceSpec
? ""
: String.format("(%s)", BisqEasyServiceUtil.getFormattedPriceSpec(trade.getOffer().getPriceSpec(), true)));
model.setPaymentMethod(contract.getQuoteSidePaymentMethodSpec().getShortDisplayString());
model.setSettlementMethod(contract.getBaseSidePaymentMethodSpec().getShortDisplayString());
model.setTradeId(trade.getId());
model.setPeerNetworkAddress(channel.getPeer().getAddressByTransportDisplayString(50));
model.setOnChainSettlement(contract.getBaseSidePaymentMethodSpec().getPaymentMethod().getPaymentRail() == BitcoinPaymentRail.MAIN_CHAIN);
model.setBtcPaymentAddress(trade.getBitcoinPaymentData().get() == null
? Res.get("bisqEasy.openTrades.tradeDetails.dataNotYetProvided")
: trade.getBitcoinPaymentData().get());
model.setBtcPaymentDataEmpty(trade.getBitcoinPaymentData().get() == null);
model.setPaymentAccountData(trade.getPaymentAccountData().get() == null
? Res.get("bisqEasy.openTrades.tradeDetails.dataNotYetProvided")
: trade.getPaymentAccountData().get());
model.setPaymentAccountDataEmpty(trade.getPaymentAccountData().get() == null);
model.setAssignedMediator(channel.getMediator().map(UserProfile::getUserName).orElse(""));
model.setHasMediatorBeenAssigned(channel.getMediator().isPresent());
}

@Override
Expand All @@ -183,17 +126,4 @@ protected Optional<? extends Controller> createController(NavigationTarget navig
void onClose() {
OverlayController.hide();
}

@Getter
@EqualsAndHashCode
@ToString
public static class InitData {
private final BisqEasyTrade bisqEasyTrade;
private final BisqEasyOpenTradeChannel channel;

public InitData(BisqEasyTrade bisqEasyTrade, BisqEasyOpenTradeChannel channel) {
this.bisqEasyTrade = bisqEasyTrade;
this.channel = channel;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,36 @@

import bisq.bisq_easy.NavigationTarget;
import bisq.desktop.common.view.NavigationModel;
import javafx.beans.property.SimpleStringProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Getter
@Setter
public class TradeDetailsModel extends NavigationModel {
private final SimpleStringProperty peerUsername = new SimpleStringProperty();
private final SimpleStringProperty tradeId = new SimpleStringProperty();
private final SimpleStringProperty amountInFiat = new SimpleStringProperty();
private final SimpleStringProperty currency = new SimpleStringProperty();
private final SimpleStringProperty bitcoinPaymentAddress = new SimpleStringProperty();
private final SimpleStringProperty amountInBTC = new SimpleStringProperty();
private final SimpleStringProperty tradePrice = new SimpleStringProperty();
private final SimpleStringProperty priceSpec = new SimpleStringProperty();
private final SimpleStringProperty mySellBuyRole = new SimpleStringProperty();
private final SimpleStringProperty myMakerTakerRole = new SimpleStringProperty();
private final SimpleStringProperty offerTakenDateTime = new SimpleStringProperty();
private final SimpleStringProperty fiatPaymentMethod = new SimpleStringProperty();
private final SimpleStringProperty bitcoinPaymentMethod = new SimpleStringProperty();
private final SimpleStringProperty peerNetworkAddress = new SimpleStringProperty();
private final SimpleStringProperty paymentAccountData = new SimpleStringProperty();
private final SimpleStringProperty mediator = new SimpleStringProperty();
private String tradeDate;
private String me;
private String peer;
private String offerType;
private String market;
private String fiatAmount;
private String fiatCurrency;
private String btcAmount;
private String price;
private String priceCodes;
private String priceSpec;
private String paymentMethod;
private String settlementMethod;
private String tradeId;
private String peerNetworkAddress;
private boolean isOnChainSettlement;
private String btcPaymentAddress;
private boolean isBtcPaymentDataEmpty;
private String paymentAccountData;
private boolean isPaymentAccountDataEmpty;
private String assignedMediator;
private boolean hasMediatorBeenAssigned;

@Override
public NavigationTarget getDefaultNavigationTarget() {
Expand Down
Loading

0 comments on commit d19341f

Please sign in to comment.