diff --git a/core/src/main/java/haveno/core/api/CoreApi.java b/core/src/main/java/haveno/core/api/CoreApi.java index 5b200429..4b6ae129 100644 --- a/core/src/main/java/haveno/core/api/CoreApi.java +++ b/core/src/main/java/haveno/core/api/CoreApi.java @@ -380,20 +380,16 @@ public class CoreApi { return coreOffersService.getOffer(id); } - public Offer getMyOffer(String id) { - return coreOffersService.getMyOffer(id); - } - public List getOffers(String direction, String currencyCode) { return coreOffersService.getOffers(direction, currencyCode); } - public List getMyOffers(String direction, String currencyCode) { + public List getMyOffers(String direction, String currencyCode) { return coreOffersService.getMyOffers(direction, currencyCode); } - public OpenOffer getMyOpenOffer(String id) { - return coreOffersService.getMyOpenOffer(id); + public OpenOffer getMyOffer(String id) { + return coreOffersService.getMyOffer(id); } public void postOffer(String currencyCode, diff --git a/core/src/main/java/haveno/core/api/CoreOffersService.java b/core/src/main/java/haveno/core/api/CoreOffersService.java index e6e5aaf0..65e9e9f0 100644 --- a/core/src/main/java/haveno/core/api/CoreOffersService.java +++ b/core/src/main/java/haveno/core/api/CoreOffersService.java @@ -64,6 +64,7 @@ import static java.util.Comparator.comparing; public class CoreOffersService { private final Supplier> priceComparator = () -> comparing(Offer::getPrice); + private final Supplier> openOfferPriceComparator = () -> comparing(openOffer -> openOffer.getOffer().getPrice()); private final Supplier> reversePriceComparator = () -> comparing(Offer::getPrice).reversed(); private final CoreContext coreContext; @@ -125,31 +126,23 @@ public class CoreOffersService { new IllegalStateException(format("offer with id '%s' not found", id))); } - List getMyOffers() { - List offers = openOfferManager.getOpenOffers().stream() - .map(OpenOffer::getOffer) - .filter(o -> o.isMyOffer(keyRing)) + List getMyOffers() { + List offers = openOfferManager.getOpenOffers().stream() + .filter(o -> o.getOffer().isMyOffer(keyRing)) .collect(Collectors.toList()); - offers.removeAll(getOffersWithDuplicateKeyImages(offers)); - return offers; + Set offersWithDuplicateKeyImages = getOffersWithDuplicateKeyImages(offers.stream().map(OpenOffer::getOffer).collect(Collectors.toList())); // TODO: this is hacky way of filtering offers with duplicate key images + Set offerIdsWithDuplicateKeyImages = offersWithDuplicateKeyImages.stream().map(Offer::getId).collect(Collectors.toSet()); + return offers.stream().filter(o -> !offerIdsWithDuplicateKeyImages.contains(o.getId())).collect(Collectors.toList()); }; - List getMyOffers(String direction, String currencyCode) { + List getMyOffers(String direction, String currencyCode) { return getMyOffers().stream() - .filter(o -> offerMatchesDirectionAndCurrency(o, direction, currencyCode)) - .sorted(priceComparator(direction)) + .filter(o -> offerMatchesDirectionAndCurrency(o.getOffer(), direction, currencyCode)) + .sorted(openOfferPriceComparator(direction, CurrencyUtil.isTraditionalCurrency(currencyCode))) .collect(Collectors.toList()); } - Offer getMyOffer(String id) { - return getMyOffers().stream() - .filter(o -> o.getId().equals(id)) - .findAny().orElseThrow(() -> - new IllegalStateException(format("offer with id '%s' not found", id))); - } - - OpenOffer getMyOpenOffer(String id) { - getMyOffer(id); // ensure offer is valid + OpenOffer getMyOffer(String id) { return openOfferManager.getOpenOfferById(id) .filter(open -> open.getOffer().isMyOffer(keyRing)) .orElseThrow(() -> @@ -229,7 +222,7 @@ public class CoreOffersService { } void cancelOffer(String id) { - Offer offer = getMyOffer(id); + Offer offer = getMyOffer(id).getOffer(); openOfferManager.removeOffer(offer, () -> { }, @@ -303,6 +296,19 @@ public class CoreOffersService { : priceComparator.get(); } + private Comparator openOfferPriceComparator(String direction, boolean isTraditional) { + // A buyer probably wants to see sell orders in price ascending order. + // A seller probably wants to see buy orders in price descending order. + if (isTraditional) + return direction.equalsIgnoreCase(OfferDirection.BUY.name()) + ? openOfferPriceComparator.get().reversed() + : openOfferPriceComparator.get(); + else + return direction.equalsIgnoreCase(OfferDirection.SELL.name()) + ? openOfferPriceComparator.get().reversed() + : openOfferPriceComparator.get(); + } + private long priceStringToLong(String priceAsString, String currencyCode) { int precision = CurrencyUtil.isTraditionalCurrency(currencyCode) ? TraditionalMoney.SMALLEST_UNIT_EXPONENT : CryptoMoney.SMALLEST_UNIT_EXPONENT; double priceAsDouble = new BigDecimal(priceAsString).doubleValue(); diff --git a/core/src/main/java/haveno/core/locale/CurrencyUtil.java b/core/src/main/java/haveno/core/locale/CurrencyUtil.java index 99c65812..bd9db3b2 100644 --- a/core/src/main/java/haveno/core/locale/CurrencyUtil.java +++ b/core/src/main/java/haveno/core/locale/CurrencyUtil.java @@ -209,11 +209,13 @@ public class CurrencyUtil { public static boolean isFiatCurrency(String currencyCode) { if (!isTraditionalCurrency(currencyCode)) return false; - if ("xag".equalsIgnoreCase(currencyCode) || "xau".equalsIgnoreCase(currencyCode)) return false; + if ("XAG".equalsIgnoreCase(currencyCode) || "XAU".equalsIgnoreCase(currencyCode)) return false; return true; } public static boolean isTraditionalCurrency(String currencyCode) { + if (currencyCode != null) currencyCode = currencyCode.toUpperCase(); + if (currencyCode != null && isTraditionalCurrencyMap.containsKey(currencyCode)) { return isTraditionalCurrencyMap.get(currencyCode); } @@ -473,18 +475,6 @@ public class CurrencyUtil { return Res.get("shared.offerVolumeCode", currencyCode); } - public static boolean apiSupportsCryptoCurrency(String currencyCode) { - // Although this method is only used by the core.api package, its - // presence here avoids creating a new util class just for this method. - if (isCryptoCurrency(currencyCode)) - return currencyCode.equals("BTC") - || currencyCode.equals("XMR"); - else - throw new IllegalArgumentException( - format("Method requires a crypto currency code, but was given '%s'.", - currencyCode)); - } - public static List getAllTransferwiseUSDCurrencies() { return List.of(new TraditionalCurrency("USD")); } diff --git a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java index d5fd337d..4183013c 100644 --- a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java +++ b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java @@ -1032,7 +1032,6 @@ public class XmrWalletService { boolean exists = xmrAddressEntryList.getAddressEntriesAsListImmutable().stream().filter(addressEntry -> addressEntry.getAddressString().equals(subaddress.getAddress())).findAny().isPresent(); if (!exists) { XmrAddressEntry entry = new XmrAddressEntry(subaddress.getIndex(), subaddress.getAddress(), subaddress.getIndex() == 0 ? XmrAddressEntry.Context.BASE_ADDRESS : XmrAddressEntry.Context.AVAILABLE, null, null); - log.info("Add XmrAddressEntry from existing subaddress: {}", entry); xmrAddressEntryList.addAddressEntry(entry); } } diff --git a/daemon/src/main/java/haveno/daemon/grpc/GrpcOffersService.java b/daemon/src/main/java/haveno/daemon/grpc/GrpcOffersService.java index 1b11d73f..10abf516 100644 --- a/daemon/src/main/java/haveno/daemon/grpc/GrpcOffersService.java +++ b/daemon/src/main/java/haveno/daemon/grpc/GrpcOffersService.java @@ -83,12 +83,11 @@ class GrpcOffersService extends OffersImplBase { } } - // TODO: merge with getOffer()? @Override public void getMyOffer(GetMyOfferRequest req, StreamObserver responseObserver) { try { - OpenOffer openOffer = coreApi.getMyOpenOffer(req.getId()); + OpenOffer openOffer = coreApi.getMyOffer(req.getId()); var reply = GetMyOfferReply.newBuilder() .setOffer(OfferInfo.toMyOfferInfo(openOffer).toProtoMessage()) .build(); @@ -123,9 +122,8 @@ class GrpcOffersService extends OffersImplBase { StreamObserver responseObserver) { try { List result = new ArrayList(); - for (Offer offer : coreApi.getMyOffers(req.getDirection(), req.getCurrencyCode())) { - OpenOffer openOffer = coreApi.getMyOpenOffer(offer.getId()); - result.add(OfferInfo.toMyOfferInfo(openOffer)); + for (OpenOffer offer : coreApi.getMyOffers(req.getDirection(), req.getCurrencyCode())) { + result.add(OfferInfo.toMyOfferInfo(offer)); } var reply = GetMyOffersReply.newBuilder() .addAllOffers(result.stream() @@ -163,7 +161,7 @@ class GrpcOffersService extends OffersImplBase { offer -> { // This result handling consumer's accept operation will return // the new offer to the gRPC client after async placement is done. - OpenOffer openOffer = coreApi.getMyOpenOffer(offer.getId()); + OpenOffer openOffer = coreApi.getMyOffer(offer.getId()); OfferInfo offerInfo = OfferInfo.toMyOfferInfo(openOffer); PostOfferReply reply = PostOfferReply.newBuilder() .setOffer(offerInfo.toProtoMessage())