From 64f228d872ac9f042f82971b07ad3b55fa51249f Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Sat, 27 Nov 2021 14:01:14 -0300 Subject: [PATCH] Make rpc GetOfferCategory service work for my+avail offers There are some use cases where the CLI needs to know what kind of offer is being acted on before the request is made, For example: There are differences between a BsqSwap 'takeoffer'request, and a v1 'takeoffer' request. A BsqSwap offer cannot be edited by an 'editoffer' request, and an attempt should be blocked by the CLI. - Append isMyOffer GetOfferCategoryRequest rpc msg def. - Adjust daemon.grpc services for new boolean GetOfferCategoryRequest param. - Adjust core.api for new boolean GetOfferCategoryRequest param. - Add validation check in core.api EditOfferValidator to block attempt to edit a BsqSwap offer. - Refactor CoreOffersService get*offer(id) methods to optionally throw excpetions. --- core/src/main/java/bisq/core/api/CoreApi.java | 12 +-- .../java/bisq/core/api/CoreOffersService.java | 99 +++++++++++-------- .../bisq/core/api/EditOfferValidator.java | 10 +- .../bisq/daemon/grpc/GrpcOffersService.java | 11 ++- .../bisq/daemon/grpc/GrpcTradesService.java | 2 +- proto/src/main/proto/grpc.proto | 1 + 6 files changed, 82 insertions(+), 53 deletions(-) diff --git a/core/src/main/java/bisq/core/api/CoreApi.java b/core/src/main/java/bisq/core/api/CoreApi.java index 261993f08d..caa9e2650a 100644 --- a/core/src/main/java/bisq/core/api/CoreApi.java +++ b/core/src/main/java/bisq/core/api/CoreApi.java @@ -120,16 +120,16 @@ public class CoreApi { // Offers /////////////////////////////////////////////////////////////////////////////////////////// - public boolean isAvailableFiatOffer(String id) { - return coreOffersService.isAvailableFiatOffer(id); + public boolean isFiatOffer(String id, boolean isMyOffer) { + return coreOffersService.isFiatOffer(id, isMyOffer); } - public boolean isAvailableAltcoinOffer(String id) { - return coreOffersService.isAvailableAltcoinOffer(id); + public boolean isAltcoinOffer(String id, boolean isMyOffer) { + return coreOffersService.isAltcoinOffer(id, isMyOffer); } - public boolean isAvailableBsqSwapOffer(String id) { - return coreOffersService.isAvailableBsqSwapOffer(id); + public boolean isBsqSwapOffer(String id, boolean isMyOffer) { + return coreOffersService.isBsqSwapOffer(id, isMyOffer); } public Offer getBsqSwapOffer(String id) { diff --git a/core/src/main/java/bisq/core/api/CoreOffersService.java b/core/src/main/java/bisq/core/api/CoreOffersService.java index 74e8af6c30..fde91f273c 100644 --- a/core/src/main/java/bisq/core/api/CoreOffersService.java +++ b/core/src/main/java/bisq/core/api/CoreOffersService.java @@ -48,6 +48,8 @@ import java.math.BigDecimal; import java.util.Comparator; import java.util.List; import java.util.Objects; +import java.util.Optional; +import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -61,8 +63,6 @@ import static bisq.core.locale.CurrencyUtil.isCryptoCurrency; import static bisq.core.offer.Offer.State; import static bisq.core.offer.OfferDirection.BUY; import static bisq.core.offer.OfferUtil.getRandomOfferId; -import static bisq.core.offer.OfferUtil.isAltcoinOffer; -import static bisq.core.offer.OfferUtil.isFiatOffer; import static bisq.core.offer.OpenOffer.State.AVAILABLE; import static bisq.core.offer.OpenOffer.State.DEACTIVATED; import static bisq.core.payment.PaymentAccountUtil.isPaymentAccountValidForOffer; @@ -81,6 +81,9 @@ class CoreOffersService { private final Supplier> openOfferPriceComparator = () -> comparing(openOffer -> openOffer.getOffer().getPrice()); + private final BiFunction toOfferWithId = (id, isMyOffer) -> + isMyOffer ? getMyOffer(id).getOffer() : getOffer(id); + private final CoreContext coreContext; private final KeyRing keyRing; // Dependencies on core api services in this package must be kept to an absolute @@ -121,63 +124,48 @@ class CoreOffersService { this.user = user; } - boolean isAvailableFiatOffer(String id) { - return isFiatOffer(getOffer(id)); + boolean isFiatOffer(String id, boolean isMyOffer) { + var offer = toOfferWithId.apply(id, isMyOffer); + return OfferUtil.isFiatOffer(offer); } - boolean isAvailableAltcoinOffer(String id) { - return isAltcoinOffer(getOffer(id)); + boolean isAltcoinOffer(String id, boolean isMyOffer) { + var offer = toOfferWithId.apply(id, isMyOffer); + return OfferUtil.isAltcoinOffer(offer); } - boolean isAvailableBsqSwapOffer(String id) { - var offer = getOffer(id); + boolean isBsqSwapOffer(String id, boolean isMyOffer) { + var offer = toOfferWithId.apply(id, isMyOffer); return offer.isBsqSwapOffer(); } - Offer getBsqSwapOffer(String id) { - return offerBookService.getOffers().stream() - .filter(o -> o.getId().equals(id)) - .filter(o -> !o.isMyOffer(keyRing)) - .filter(o -> offerFilterService.canTakeOffer(o, coreContext.isApiUser()).isValid()) - .filter(o -> o.isBsqSwapOffer()) - .findAny().orElseThrow(() -> - new IllegalStateException(format("offer with id '%s' not found", id))); - } - Offer getOffer(String id) { - return offerBookService.getOffers().stream() - .filter(o -> o.getId().equals(id)) - .filter(o -> !o.isMyOffer(keyRing)) - .filter(o -> offerFilterService.canTakeOffer(o, coreContext.isApiUser()).isValid()) - .findAny().orElseThrow(() -> - new IllegalStateException(format("offer with id '%s' not found", id))); + return findAvailableOffer(id).orElseThrow(() -> + new IllegalStateException(format("offer with id '%s' not found", id))); } OpenOffer getMyOffer(String id) { - return openOfferManager.getObservableList().stream() - .filter(o -> o.getId().equals(id)) - .filter(o -> o.getOffer().isMyOffer(keyRing)) - .findAny().orElseThrow(() -> - new IllegalStateException(format("offer with id '%s' not found", id))); + return findMyOpenOffer(id).orElseThrow(() -> + new IllegalStateException(format("offer with id '%s' not found", id))); + } + + Offer getBsqSwapOffer(String id) { + return findAvailableBsqSwapOffer(id).orElseThrow(() -> + new IllegalStateException(format("offer with id '%s' not found", id))); } Offer getMyBsqSwapOffer(String id) { - return offerBookService.getOffers().stream() - .filter(o -> o.getId().equals(id)) - .filter(o -> o.isMyOffer(keyRing)) - .filter(o -> o.isBsqSwapOffer()) - .findAny().orElseThrow(() -> - new IllegalStateException(format("offer with id '%s' not found", id))); + return findMyBsqSwapOffer(id).orElseThrow(() -> + new IllegalStateException(format("offer with id '%s' not found", id))); } List getBsqSwapOffers(String direction) { - var offers = offerBookService.getOffers().stream() + return offerBookService.getOffers().stream() .filter(o -> !o.isMyOffer(keyRing)) .filter(o -> o.getDirection().name().equalsIgnoreCase(direction)) - .filter(o -> o.isBsqSwapOffer()) + .filter(Offer::isBsqSwapOffer) .sorted(priceComparator(direction)) .collect(Collectors.toList()); - return offers; } List getOffers(String direction, String currencyCode) { @@ -198,13 +186,12 @@ class CoreOffersService { } List getMyBsqSwapOffers(String direction) { - var offers = offerBookService.getOffers().stream() + return offerBookService.getOffers().stream() .filter(o -> o.isMyOffer(keyRing)) .filter(o -> o.getDirection().name().equalsIgnoreCase(direction)) .filter(Offer::isBsqSwapOffer) .sorted(priceComparator(direction)) .collect(Collectors.toList()); - return offers; } OpenOffer getMyOpenBsqSwapOffer(String id) { @@ -393,6 +380,38 @@ class CoreOffersService { throw new IllegalStateException(offer.getErrorMessage()); } + private Optional findAvailableBsqSwapOffer(String id) { + return offerBookService.getOffers().stream() + .filter(o -> o.getId().equals(id)) + .filter(o -> !o.isMyOffer(keyRing)) + .filter(o -> offerFilterService.canTakeOffer(o, coreContext.isApiUser()).isValid()) + .filter(Offer::isBsqSwapOffer) + .findAny(); + } + + private Optional findMyBsqSwapOffer(String id) { + return offerBookService.getOffers().stream() + .filter(o -> o.getId().equals(id)) + .filter(o -> o.isMyOffer(keyRing)) + .filter(Offer::isBsqSwapOffer) + .findAny(); + } + + private Optional findAvailableOffer(String id) { + return offerBookService.getOffers().stream() + .filter(o -> o.getId().equals(id)) + .filter(o -> !o.isMyOffer(keyRing)) + .filter(o -> offerFilterService.canTakeOffer(o, coreContext.isApiUser()).isValid()) + .findAny(); + } + + private Optional findMyOpenOffer(String id) { + return openOfferManager.getObservableList().stream() + .filter(o -> o.getId().equals(id)) + .filter(o -> o.getOffer().isMyOffer(keyRing)) + .findAny(); + } + private OfferPayload getMergedOfferPayload(OpenOffer openOffer, String editedPriceAsString, double editedMarketPriceMargin, diff --git a/core/src/main/java/bisq/core/api/EditOfferValidator.java b/core/src/main/java/bisq/core/api/EditOfferValidator.java index 7a9840c3cd..89c9366e1e 100644 --- a/core/src/main/java/bisq/core/api/EditOfferValidator.java +++ b/core/src/main/java/bisq/core/api/EditOfferValidator.java @@ -45,7 +45,8 @@ class EditOfferValidator { } void validate() { - log.info("Verifying 'editoffer' params OK for editType {}", editType); + log.info("Verifying 'editoffer' params for editType {}", editType); + checkNotBsqSwapOffer(); switch (editType) { case ACTIVATION_STATE_ONLY: { validateEditedActivationState(); @@ -138,4 +139,11 @@ class EditOfferValidator { currentlyOpenOffer.getId())); } } + + private void checkNotBsqSwapOffer() { + if (currentlyOpenOffer.getOffer().isBsqSwapOffer()) { + throw new IllegalStateException( + format("cannot edit bsq swap offer with id '%s'", currentlyOpenOffer.getId())); + } + } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java index 4f2fef1556..edfa09a3d6 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java @@ -92,7 +92,7 @@ class GrpcOffersService extends OffersImplBase { public void getOfferCategory(GetOfferCategoryRequest req, StreamObserver responseObserver) { try { - OfferCategory category = getAvailableOfferCategory(req.getId()); + OfferCategory category = getOfferCategory(req.getId(), req.getIsMyOffer()); var reply = newBuilder() .setOfferCategory(category) .build(); @@ -335,6 +335,7 @@ class GrpcOffersService extends OffersImplBase { return getCustomRateMeteringInterceptor(coreApi.getConfig().appDataDir, this.getClass()) .or(() -> Optional.of(CallRateMeteringInterceptor.valueOf( new HashMap<>() {{ + put(getGetOfferCategoryMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS)); put(getGetOfferMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS)); put(getGetMyOfferMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS)); put(getGetOffersMethod().getFullMethodName(), new GrpcCallRateMeter(1, SECONDS)); @@ -346,12 +347,12 @@ class GrpcOffersService extends OffersImplBase { ))); } - private OfferCategory getAvailableOfferCategory(String offerId) { - if (coreApi.isAvailableAltcoinOffer(offerId)) + private OfferCategory getOfferCategory(String offerId, boolean isMyOffer) { + if (coreApi.isAltcoinOffer(offerId, isMyOffer)) return ALTCOIN; - else if (coreApi.isAvailableFiatOffer(offerId)) + else if (coreApi.isFiatOffer(offerId, isMyOffer)) return FIAT; - else if (coreApi.isAvailableBsqSwapOffer(offerId)) + else if (coreApi.isBsqSwapOffer(offerId, isMyOffer)) return BSQ_SWAP; else return UNKNOWN; diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java index 22961043b1..6a9ce12a7c 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java @@ -79,7 +79,7 @@ class GrpcTradesService extends TradesImplBase { exceptionHandler, log); - if (coreApi.isAvailableBsqSwapOffer(req.getOfferId())) { + if (coreApi.isBsqSwapOffer(req.getOfferId(), false)) { coreApi.takeBsqSwapOffer(req.getOfferId(), bsqSwapTrade -> { var reply = buildTakeOfferReply(bsqSwapTrade); diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index ad0ca7f8b6..10a90940db 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -92,6 +92,7 @@ service Offers { message GetOfferCategoryRequest { string id = 1; + bool isMyOffer = 2; } message GetOfferCategoryReply {