diff --git a/cli/src/main/java/bisq/cli/GrpcClient.java b/cli/src/main/java/bisq/cli/GrpcClient.java index 8cb6808eb0..4d20a2d4b7 100644 --- a/cli/src/main/java/bisq/cli/GrpcClient.java +++ b/cli/src/main/java/bisq/cli/GrpcClient.java @@ -53,6 +53,7 @@ import bisq.proto.grpc.SendBtcRequest; import bisq.proto.grpc.SetTxFeeRatePreferenceRequest; import bisq.proto.grpc.SetWalletPasswordRequest; import bisq.proto.grpc.StopRequest; +import bisq.proto.grpc.TakeOfferReply; import bisq.proto.grpc.TakeOfferRequest; import bisq.proto.grpc.TradeInfo; import bisq.proto.grpc.TxFeeRateInfo; @@ -309,41 +310,21 @@ public final class GrpcClient { .collect(Collectors.toList()); } - public TradeInfo takeOffer(String offerId, String paymentAccountId, String takerFeeCurrencyCode) { + public TakeOfferReply getTakeOfferReply(String offerId, String paymentAccountId, String takerFeeCurrencyCode) { var request = TakeOfferRequest.newBuilder() .setOfferId(offerId) .setPaymentAccountId(paymentAccountId) .setTakerFeeCurrencyCode(takerFeeCurrencyCode) .build(); - var reply = grpcStubs.tradesService.takeOffer(request); - if (reply.hasTrade()) { + return grpcStubs.tradesService.takeOffer(request); + } + + public TradeInfo takeOffer(String offerId, String paymentAccountId, String takerFeeCurrencyCode) { + var reply = getTakeOfferReply(offerId, paymentAccountId, takerFeeCurrencyCode); + if (reply.hasTrade()) return reply.getTrade(); - } else { - // If there is no trade, there should be a reason in the AvailabilityResult. - // Convert the enum to a user error message before throwing the exception. - switch (reply.getAvailabilityResult()) { - case MARKET_PRICE_NOT_AVAILABLE: - throw new IllegalStateException("could not take offer because market price for calculating trade price is unavailable"); - case PRICE_OUT_OF_TOLERANCE: - throw new IllegalStateException("could not take offer because taker's price is outside tolerance"); - case PRICE_CHECK_FAILED: - throw new IllegalStateException("could not take offer because trade price check failed"); - case NO_ARBITRATORS: - throw new IllegalStateException("could not take offer because no arbitrators are available"); - case NO_MEDIATORS: - throw new IllegalStateException("could not take offer because no mediators are available"); - case NO_REFUND_AGENTS: - throw new IllegalStateException("could not take offer because no refund agents are available"); - case USER_IGNORED: - throw new IllegalStateException("could not take offer from ignored user"); - case MAKER_DENIED_API_USER: - throw new IllegalStateException("could not take offer because maker is api user"); - case UNCONF_TX_LIMIT_HIT: - throw new IllegalStateException("could not take offer because you have too many unconfirmed transactions at this moment"); - default: - throw new IllegalStateException("programmer error: could not take offer for unknown reason"); - } - } + else + throw new IllegalStateException(reply.getAvailabilityResultDescription()); } public TradeInfo getTrade(String tradeId) { diff --git a/core/src/main/java/bisq/core/offer/AvailabilityResult.java b/core/src/main/java/bisq/core/offer/AvailabilityResult.java index fb58ac111d..e4ad982163 100644 --- a/core/src/main/java/bisq/core/offer/AvailabilityResult.java +++ b/core/src/main/java/bisq/core/offer/AvailabilityResult.java @@ -18,17 +18,31 @@ package bisq.core.offer; public enum AvailabilityResult { - UNKNOWN_FAILURE, - AVAILABLE, - OFFER_TAKEN, - PRICE_OUT_OF_TOLERANCE, - MARKET_PRICE_NOT_AVAILABLE, - @SuppressWarnings("unused") NO_ARBITRATORS, - NO_MEDIATORS, - USER_IGNORED, - @SuppressWarnings("unused") MISSING_MANDATORY_CAPABILITY, - @SuppressWarnings("unused") NO_REFUND_AGENTS, - UNCONF_TX_LIMIT_HIT, - MAKER_DENIED_API_USER, - PRICE_CHECK_FAILED + UNKNOWN_FAILURE("cannot take offer for unknown reason"), + AVAILABLE("offer available"), + OFFER_TAKEN("offer taken"), + PRICE_OUT_OF_TOLERANCE("cannot take offer because taker's price is outside tolerance"), + MARKET_PRICE_NOT_AVAILABLE("cannot take offer because market price for calculating trade price is unavailable"), + @SuppressWarnings("unused") NO_ARBITRATORS("cannot take offer because no arbitrators are available"), + NO_MEDIATORS("cannot take offer because no mediators are available"), + USER_IGNORED("cannot take offer because user is ignored"), + @SuppressWarnings("unused") MISSING_MANDATORY_CAPABILITY("description not available"), + @SuppressWarnings("unused") NO_REFUND_AGENTS("cannot take offer because no refund agents are available"), + UNCONF_TX_LIMIT_HIT("cannot take offer because you have too many unconfirmed transactions at this moment"), + MAKER_DENIED_API_USER("cannot take offer because maker is api user"), + PRICE_CHECK_FAILED("cannot take offer because trade price check failed"); + + private final String description; + + AvailabilityResult(String description) { + this.description = description; + } + + public String description() { + return description; + } + + public static AvailabilityResult fromProto(protobuf.AvailabilityResult proto) { + return AvailabilityResult.valueOf(proto.name()); + } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcErrorMessageHandler.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcErrorMessageHandler.java index 5ca79bb785..435284252b 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcErrorMessageHandler.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcErrorMessageHandler.java @@ -92,9 +92,10 @@ public class GrpcErrorMessageHandler implements ErrorMessageHandler { // The client should look at the grpc reply object's AvailabilityResult // field if reply.hasTrade = false, and use it give the user a human readable msg. try { - AvailabilityResult availabilityResult = getAvailabilityResult(errorMessage); + AvailabilityResult availabilityResultProto = getAvailabilityResult(errorMessage); var reply = TakeOfferReply.newBuilder() - .setAvailabilityResult(availabilityResult) + .setAvailabilityResult(availabilityResultProto) + .setAvailabilityResultDescription(getAvailabilityResultDescription(availabilityResultProto)) .build(); @SuppressWarnings("unchecked") var takeOfferResponseObserver = (StreamObserver) responseObserver; @@ -116,6 +117,10 @@ public class GrpcErrorMessageHandler implements ErrorMessageHandler { format("Could not find an AvailabilityResult in error message:%n%s", errorMessage))); } + private String getAvailabilityResultDescription(AvailabilityResult proto) { + return bisq.core.offer.AvailabilityResult.fromProto(proto).description(); + } + private boolean isTakeOfferError() { return fullMethodName.equals(getTakeOfferMethod().getFullMethodName()); } diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index fcf92fcc27..d2eda23c93 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -278,6 +278,7 @@ message TakeOfferRequest { message TakeOfferReply { TradeInfo trade = 1; AvailabilityResult availabilityResult = 2; + string availabilityResultDescription = 3; } message ConfirmPaymentStartedRequest {