diff --git a/apitest/src/test/java/bisq/apitest/method/MethodTest.java b/apitest/src/test/java/bisq/apitest/method/MethodTest.java index 5ca04409449..8ac98eee751 100644 --- a/apitest/src/test/java/bisq/apitest/method/MethodTest.java +++ b/apitest/src/test/java/bisq/apitest/method/MethodTest.java @@ -26,6 +26,9 @@ import bisq.proto.grpc.BalancesInfo; +import io.grpc.Status; +import io.grpc.StatusRuntimeException; + import java.io.File; import java.io.IOException; import java.io.PrintWriter; @@ -190,6 +193,15 @@ protected static String encodeToHex(String s) { return Utilities.bytesAsHexString(s.getBytes(UTF_8)); } + protected static Status.Code getStatusRuntimeExceptionStatusCode(Exception grpcException) { + if (grpcException instanceof StatusRuntimeException) + return ((StatusRuntimeException) grpcException).getStatus().getCode(); + else + throw new IllegalArgumentException( + format("Expected a io.grpc.StatusRuntimeException argument, but got a %s", + grpcException.getClass().getName())); + } + protected void verifyNoLoggedNodeExceptions() { var loggedExceptions = getNodeExceptionMessages(); if (loggedExceptions != null) { diff --git a/apitest/src/test/java/bisq/apitest/method/RegisterDisputeAgentsTest.java b/apitest/src/test/java/bisq/apitest/method/RegisterDisputeAgentsTest.java index b5011ffced8..a219f65c040 100644 --- a/apitest/src/test/java/bisq/apitest/method/RegisterDisputeAgentsTest.java +++ b/apitest/src/test/java/bisq/apitest/method/RegisterDisputeAgentsTest.java @@ -61,7 +61,7 @@ public static void setUp() { public void testRegisterArbitratorShouldThrowException() { Throwable exception = assertThrows(StatusRuntimeException.class, () -> arbClient.registerDisputeAgent(ARBITRATOR, DEV_PRIVILEGE_PRIV_KEY)); - assertEquals("INVALID_ARGUMENT: arbitrators must be registered in a Bisq UI", + assertEquals("UNIMPLEMENTED: arbitrators must be registered in a Bisq UI", exception.getMessage()); } diff --git a/apitest/src/test/java/bisq/apitest/method/offer/BsqSwapOfferTest.java b/apitest/src/test/java/bisq/apitest/method/offer/BsqSwapOfferTest.java index 7c2ff5e6f92..e1824f8c91a 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/BsqSwapOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/BsqSwapOfferTest.java @@ -31,9 +31,11 @@ import static bisq.apitest.config.ApiTestConfig.BSQ; import static bisq.apitest.config.ApiTestConfig.BTC; +import static io.grpc.Status.Code.NOT_FOUND; import static java.lang.String.format; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static protobuf.OfferDirection.BUY; @@ -44,7 +46,7 @@ public class BsqSwapOfferTest extends AbstractOfferTest { @BeforeAll public static void setUp() { - AbstractOfferTest.setUp(); + AbstractOfferTest.setUp(false); } @BeforeEach @@ -136,10 +138,13 @@ private void testGetMyBsqSwapOffer(OfferInfo bsqSwapOffer) { numFetchAttempts++; var fetchedBsqSwapOffer = aliceClient.getOffer(bsqSwapOffer.getId()); assertEquals(bsqSwapOffer.getId(), fetchedBsqSwapOffer.getId()); + assertTrue(fetchedBsqSwapOffer.getIsActivated()); log.debug("Alice found her (my) new bsq swap offer on attempt # {}.", numFetchAttempts); break; } catch (Exception ex) { log.warn(ex.getMessage()); + var statusCode = getStatusRuntimeExceptionStatusCode(ex); + assertEquals(NOT_FOUND, statusCode, "Expected a NOT_FOUND status code from server"); if (numFetchAttempts >= 9) fail(format("Alice giving up on fetching her (my) bsq swap offer after %d attempts.", numFetchAttempts), ex); @@ -156,10 +161,13 @@ private void testGetBsqSwapOffer(OfferInfo bsqSwapOffer) { numFetchAttempts++; var fetchedBsqSwapOffer = bobClient.getOffer(bsqSwapOffer.getId()); assertEquals(bsqSwapOffer.getId(), fetchedBsqSwapOffer.getId()); + assertTrue(fetchedBsqSwapOffer.getIsActivated()); log.debug("Bob found new available bsq swap offer on attempt # {}.", numFetchAttempts); break; } catch (Exception ex) { log.warn(ex.getMessage()); + var statusCode = getStatusRuntimeExceptionStatusCode(ex); + assertEquals(NOT_FOUND, statusCode, "Expected a NOT_FOUND status code from server"); if (numFetchAttempts > 9) fail(format("Bob gave up on fetching available bsq swap offer after %d attempts.", numFetchAttempts), ex); diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateBSQOffersTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateBSQOffersTest.java index 1807d1000b5..66819852bff 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateBSQOffersTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateBSQOffersTest.java @@ -68,6 +68,7 @@ public void testCreateBuy1BTCFor20KBSQOffer() { log.debug("Sell BSQ (Buy BTC) Offer:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); + assertFalse(newOffer.getIsActivated()); String newOfferId = newOffer.getId(); assertNotEquals("", newOfferId); @@ -89,6 +90,7 @@ public void testCreateBuy1BTCFor20KBSQOffer() { newOffer = aliceClient.getOffer(newOfferId); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); + assertTrue(newOffer.getIsActivated()); assertEquals(newOfferId, newOffer.getId()); assertEquals(BUY.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); @@ -119,6 +121,7 @@ public void testCreateSell1BTCFor20KBSQOffer() { log.debug("SELL 20K BSQ Offer:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); + assertFalse(newOffer.getIsActivated()); String newOfferId = newOffer.getId(); assertNotEquals("", newOfferId); @@ -140,6 +143,7 @@ public void testCreateSell1BTCFor20KBSQOffer() { newOffer = aliceClient.getOffer(newOfferId); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); + assertTrue(newOffer.getIsActivated()); assertEquals(newOfferId, newOffer.getId()); assertEquals(SELL.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); @@ -170,6 +174,7 @@ public void testCreateBuyBTCWith1To2KBSQOffer() { log.debug("BUY 1-2K BSQ Offer:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); + assertFalse(newOffer.getIsActivated()); String newOfferId = newOffer.getId(); assertNotEquals("", newOfferId); @@ -191,6 +196,7 @@ public void testCreateBuyBTCWith1To2KBSQOffer() { newOffer = aliceClient.getOffer(newOfferId); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); + assertTrue(newOffer.getIsActivated()); assertEquals(newOfferId, newOffer.getId()); assertEquals(BUY.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); @@ -221,6 +227,7 @@ public void testCreateSellBTCFor5To10KBSQOffer() { log.debug("SELL 5-10K BSQ Offer:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); + assertFalse(newOffer.getIsActivated()); String newOfferId = newOffer.getId(); assertNotEquals("", newOfferId); @@ -242,6 +249,7 @@ public void testCreateSellBTCFor5To10KBSQOffer() { newOffer = aliceClient.getOffer(newOfferId); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); + assertTrue(newOffer.getIsActivated()); assertEquals(newOfferId, newOffer.getId()); assertEquals(SELL.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); @@ -260,7 +268,7 @@ public void testCreateSellBTCFor5To10KBSQOffer() { @Test @Order(5) public void testGetAllMyBsqOffers() { - List offers = aliceClient.getMyCryptoCurrencyOffersSortedByDate(BSQ); + List offers = aliceClient.getMyOffersSortedByDate(BSQ); log.debug("All Alice's BSQ Offers:\n{}", toOffersTable.apply(offers)); assertEquals(4, offers.size()); log.debug("ALICE'S BALANCES\n{}", formatBalancesTbls(aliceClient.getBalances())); @@ -269,7 +277,7 @@ public void testGetAllMyBsqOffers() { @Test @Order(6) public void testGetAvailableBsqOffers() { - List offers = bobClient.getCryptoCurrencyOffersSortedByDate(BSQ); + List offers = bobClient.getOffersSortedByDate(BSQ); log.debug("All Bob's Available BSQ Offers:\n{}", toOffersTable.apply(offers)); assertEquals(4, offers.size()); log.debug("BOB'S BALANCES\n{}", formatBalancesTbls(bobClient.getBalances())); diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java index 7691a5e26d4..913d5fc1697 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java @@ -60,6 +60,7 @@ public void testCreateAUDBTCBuyOfferUsingFixedPrice16000() { log.debug("Offer #1:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); + assertFalse(newOffer.getIsActivated()); String newOfferId = newOffer.getId(); assertNotEquals("", newOfferId); @@ -79,6 +80,7 @@ public void testCreateAUDBTCBuyOfferUsingFixedPrice16000() { newOffer = aliceClient.getOffer(newOfferId); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); + assertTrue(newOffer.getIsActivated()); assertEquals(newOfferId, newOffer.getId()); assertEquals(BUY.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); @@ -109,6 +111,7 @@ public void testCreateUSDBTCBuyOfferUsingFixedPrice100001234() { log.debug("Offer #2:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); + assertFalse(newOffer.getIsActivated()); String newOfferId = newOffer.getId(); assertNotEquals("", newOfferId); @@ -128,6 +131,7 @@ public void testCreateUSDBTCBuyOfferUsingFixedPrice100001234() { newOffer = aliceClient.getOffer(newOfferId); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); + assertTrue(newOffer.getIsActivated()); assertEquals(newOfferId, newOffer.getId()); assertEquals(BUY.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); @@ -158,6 +162,7 @@ public void testCreateEURBTCSellOfferUsingFixedPrice95001234() { log.debug("Offer #3:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); + assertFalse(newOffer.getIsActivated()); String newOfferId = newOffer.getId(); assertNotEquals("", newOfferId); @@ -177,6 +182,7 @@ public void testCreateEURBTCSellOfferUsingFixedPrice95001234() { newOffer = aliceClient.getOffer(newOfferId); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); + assertTrue(newOffer.getIsActivated()); assertEquals(newOfferId, newOffer.getId()); assertEquals(SELL.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java index fc61b5699dc..8f58e845eaf 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java @@ -77,6 +77,7 @@ public void testCreateUSDBTCBuyOffer5PctPriceMargin() { log.debug("Offer #1:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); + assertFalse(newOffer.getIsActivated()); String newOfferId = newOffer.getId(); assertNotEquals("", newOfferId); @@ -94,6 +95,7 @@ public void testCreateUSDBTCBuyOffer5PctPriceMargin() { newOffer = aliceClient.getOffer(newOfferId); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); + assertTrue(newOffer.getIsActivated()); assertEquals(newOfferId, newOffer.getId()); assertEquals(BUY.name(), newOffer.getDirection()); assertTrue(newOffer.getUseMarketBasedPrice()); @@ -126,6 +128,7 @@ public void testCreateNZDBTCBuyOfferMinus2PctPriceMargin() { log.debug("Offer #2:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); + assertFalse(newOffer.getIsActivated()); String newOfferId = newOffer.getId(); assertNotEquals("", newOfferId); @@ -143,6 +146,7 @@ public void testCreateNZDBTCBuyOfferMinus2PctPriceMargin() { newOffer = aliceClient.getOffer(newOfferId); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); + assertTrue(newOffer.getIsActivated()); assertEquals(newOfferId, newOffer.getId()); assertEquals(BUY.name(), newOffer.getDirection()); assertTrue(newOffer.getUseMarketBasedPrice()); @@ -175,6 +179,7 @@ public void testCreateGBPBTCSellOfferMinus1Point5PctPriceMargin() { log.debug("Offer #3:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); + assertFalse(newOffer.getIsActivated()); String newOfferId = newOffer.getId(); assertNotEquals("", newOfferId); @@ -192,6 +197,7 @@ public void testCreateGBPBTCSellOfferMinus1Point5PctPriceMargin() { newOffer = aliceClient.getOffer(newOfferId); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); + assertTrue(newOffer.getIsActivated()); assertEquals(newOfferId, newOffer.getId()); assertEquals(SELL.name(), newOffer.getDirection()); assertTrue(newOffer.getUseMarketBasedPrice()); @@ -224,6 +230,7 @@ public void testCreateBRLBTCSellOffer6Point55PctPriceMargin() { log.debug("Offer #4:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); + assertFalse(newOffer.getIsActivated()); String newOfferId = newOffer.getId(); assertNotEquals("", newOfferId); @@ -241,6 +248,7 @@ public void testCreateBRLBTCSellOffer6Point55PctPriceMargin() { newOffer = aliceClient.getOffer(newOfferId); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); + assertTrue(newOffer.getIsActivated()); assertEquals(newOfferId, newOffer.getId()); assertEquals(SELL.name(), newOffer.getDirection()); assertTrue(newOffer.getUseMarketBasedPrice()); @@ -273,12 +281,14 @@ public void testCreateUSDBTCBuyOfferWithTriggerPrice() { triggerPrice); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); + assertFalse(newOffer.getIsActivated()); genBtcBlocksThenWait(1, 4000); // give time to add to offer book newOffer = aliceClient.getOffer(newOffer.getId()); log.debug("Offer #5:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); + assertTrue(newOffer.getIsActivated()); assertEquals(triggerPrice, newOffer.getTriggerPrice()); } diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateXMROffersTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateXMROffersTest.java index cb9db33a145..b9337051535 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateXMROffersTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateXMROffersTest.java @@ -71,6 +71,7 @@ public void testCreateFixedPriceBuy1BTCFor200KXMROffer() { log.debug("Sell XMR (Buy BTC) offer:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); + assertFalse(newOffer.getIsActivated()); String newOfferId = newOffer.getId(); assertNotEquals("", newOfferId); @@ -90,6 +91,7 @@ public void testCreateFixedPriceBuy1BTCFor200KXMROffer() { newOffer = aliceClient.getOffer(newOfferId); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); + assertTrue(newOffer.getIsActivated()); assertEquals(newOfferId, newOffer.getId()); assertEquals(BUY.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); @@ -118,6 +120,7 @@ public void testCreateFixedPriceSell1BTCFor200KXMROffer() { log.debug("Buy XMR (Sell BTC) offer:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); + assertFalse(newOffer.getIsActivated()); String newOfferId = newOffer.getId(); assertNotEquals("", newOfferId); @@ -137,6 +140,7 @@ public void testCreateFixedPriceSell1BTCFor200KXMROffer() { newOffer = aliceClient.getOffer(newOfferId); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); + assertTrue(newOffer.getIsActivated()); assertEquals(newOfferId, newOffer.getId()); assertEquals(SELL.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); @@ -168,6 +172,7 @@ public void testCreatePriceMarginBasedBuy1BTCOfferWithTriggerPrice() { log.debug("Pending Sell XMR (Buy BTC) offer:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); + assertFalse(newOffer.getIsActivated()); String newOfferId = newOffer.getId(); assertNotEquals("", newOfferId); @@ -191,6 +196,7 @@ public void testCreatePriceMarginBasedBuy1BTCOfferWithTriggerPrice() { log.debug("Available Sell XMR (Buy BTC) offer:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); + assertTrue(newOffer.getIsActivated()); assertEquals(newOfferId, newOffer.getId()); assertEquals(BUY.name(), newOffer.getDirection()); assertTrue(newOffer.getUseMarketBasedPrice()); @@ -224,6 +230,7 @@ public void testCreatePriceMarginBasedSell1BTCOffer() { log.debug("Buy XMR (Sell BTC) offer:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); + assertFalse(newOffer.getIsActivated()); String newOfferId = newOffer.getId(); assertNotEquals("", newOfferId); @@ -242,6 +249,7 @@ public void testCreatePriceMarginBasedSell1BTCOffer() { newOffer = aliceClient.getOffer(newOfferId); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); + assertTrue(newOffer.getIsActivated()); assertEquals(newOfferId, newOffer.getId()); assertEquals(SELL.name(), newOffer.getDirection()); assertTrue(newOffer.getUseMarketBasedPrice()); @@ -257,7 +265,7 @@ public void testCreatePriceMarginBasedSell1BTCOffer() { @Test @Order(5) public void testGetAllMyXMROffers() { - List offers = aliceClient.getMyCryptoCurrencyOffersSortedByDate(XMR); + List offers = aliceClient.getMyOffersSortedByDate(XMR); log.debug("All of Alice's XMR offers:\n{}", toOffersTable.apply(offers)); assertEquals(4, offers.size()); log.debug("Alice's balances\n{}", formatBalancesTbls(aliceClient.getBalances())); @@ -266,7 +274,7 @@ public void testGetAllMyXMROffers() { @Test @Order(6) public void testGetAvailableXMROffers() { - List offers = bobClient.getCryptoCurrencyOffersSortedByDate(XMR); + List offers = bobClient.getOffersSortedByDate(XMR); log.debug("All of Bob's available XMR offers:\n{}", toOffersTable.apply(offers)); assertEquals(4, offers.size()); log.debug("Bob's balances\n{}", formatBalancesTbls(bobClient.getBalances())); diff --git a/apitest/src/test/java/bisq/apitest/method/offer/EditOfferTest.java b/apitest/src/test/java/bisq/apitest/method/offer/EditOfferTest.java index 4e839924019..5536342218c 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/EditOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/EditOfferTest.java @@ -437,7 +437,7 @@ public void testChangeFixedPricedBsqOfferToPriceMarginBasedOfferShouldThrowExcep NO_TRIGGER_PRICE, ACTIVATE_OFFER, MKT_PRICE_MARGIN_ONLY)); - String expectedExceptionMessage = format("UNKNOWN: cannot set mkt price margin or" + String expectedExceptionMessage = format("INVALID_ARGUMENT: cannot set mkt price margin or" + " trigger price on fixed price bsq offer with id '%s'", originalOffer.getId()); assertEquals(expectedExceptionMessage, exception.getMessage()); @@ -465,7 +465,7 @@ public void testEditTriggerPriceOnFixedPriceBsqOfferShouldThrowException() { newTriggerPriceAsLong, ACTIVATE_OFFER, TRIGGER_PRICE_ONLY)); - String expectedExceptionMessage = format("UNKNOWN: cannot set mkt price margin or" + String expectedExceptionMessage = format("INVALID_ARGUMENT: cannot set mkt price margin or" + " trigger price on fixed price bsq offer with id '%s'", originalOffer.getId()); assertEquals(expectedExceptionMessage, exception.getMessage()); @@ -850,8 +850,10 @@ public void testEditBsqSwapOfferShouldThrowException() { NO_TRIGGER_PRICE, ACTIVATE_OFFER, TRIGGER_PRICE_ONLY)); - String expectedExceptionMessage = format("UNKNOWN: cannot edit bsq swap offer with id '%s'", - originalOffer.getId()); + String expectedExceptionMessage = + format("INVALID_ARGUMENT: cannot edit bsq swap offer with id '%s'," + + " replace it with a new swap offer instead", + originalOffer.getId()); assertEquals(expectedExceptionMessage, exception.getMessage()); } diff --git a/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java b/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java index 71e9ac72285..52ed72056f2 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java @@ -207,10 +207,7 @@ protected final void sendBsqPayment(Logger log, String receiverAddress = contract.getIsBuyerMakerAndSellerTaker() ? contract.getTakerPaymentAccountPayload().getAddress() : contract.getMakerPaymentAccountPayload().getAddress(); - // TODO Fix trade vol src bug for subclasses. - // This bug was fixed for production CLI with https://github.com/bisq-network/bisq/pull/5704 on Sep 27, 2021 - String sendBsqAmount = trade.getOffer().getVolume(); - // String sendBsqAmount = trade.getTradeVolume(); + String sendBsqAmount = trade.getTradeVolume(); log.debug("Sending {} BSQ to address {}", sendBsqAmount, receiverAddress); grpcClient.sendBsq(receiverAddress, sendBsqAmount, ""); } @@ -219,10 +216,7 @@ protected final void verifyBsqPaymentHasBeenReceived(Logger log, GrpcClient grpcClient, TradeInfo trade) { var contract = trade.getContract(); - // TODO Fix trade vol src bug for subclasses. - // This bug was fixed for production with https://github.com/bisq-network/bisq/pull/5704 on Sep 27, 2021 - var receiveAmountAsString = trade.getOffer().getVolume(); - // String receiveAmountAsString = trade.getTradeVolume(); + String receiveAmountAsString = trade.getTradeVolume(); var address = contract.getIsBuyerMakerAndSellerTaker() ? contract.getTakerPaymentAccountPayload().getAddress() : contract.getMakerPaymentAccountPayload().getAddress(); diff --git a/apitest/src/test/java/bisq/apitest/method/trade/BsqSwapBuyBtcTradeTest.java b/apitest/src/test/java/bisq/apitest/method/trade/BsqSwapBuyBtcTradeTest.java index 8dc20b54170..172f4b2c449 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/BsqSwapBuyBtcTradeTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/BsqSwapBuyBtcTradeTest.java @@ -36,6 +36,7 @@ import static bisq.apitest.config.ApiTestConfig.BTC; import static bisq.core.offer.OfferDirection.BUY; import static bisq.proto.grpc.GetOfferCategoryReply.OfferCategory.BSQ_SWAP; +import static io.grpc.Status.Code.NOT_FOUND; import static java.lang.String.format; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; @@ -171,6 +172,9 @@ private TradeInfo getBsqSwapTrade(GrpcClient client, String tradeId) { return client.getTrade(tradeId); } catch (Exception ex) { log.warn(ex.getMessage()); + var statusCode = getStatusRuntimeExceptionStatusCode(ex); + assertEquals(NOT_FOUND, statusCode, "Expected a NOT_FOUND status code from server"); + if (numFetchAttempts > 9) { if (checkForLoggedExceptions) { printNodeExceptionMessages(log); diff --git a/apitest/src/test/java/bisq/apitest/method/trade/BsqSwapSellBtcTradeTest.java b/apitest/src/test/java/bisq/apitest/method/trade/BsqSwapSellBtcTradeTest.java index 50f78a4970d..9c97695c2d6 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/BsqSwapSellBtcTradeTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/BsqSwapSellBtcTradeTest.java @@ -34,6 +34,7 @@ import static bisq.apitest.config.ApiTestConfig.BTC; import static bisq.core.offer.OfferDirection.SELL; import static bisq.proto.grpc.GetOfferCategoryReply.OfferCategory.BSQ_SWAP; +import static io.grpc.Status.Code.NOT_FOUND; import static java.lang.String.format; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; @@ -169,6 +170,9 @@ private TradeInfo getBsqSwapTrade(GrpcClient client, String tradeId) { return client.getTrade(tradeId); } catch (Exception ex) { log.warn(ex.getMessage()); + var statusCode = getStatusRuntimeExceptionStatusCode(ex); + assertEquals(NOT_FOUND, statusCode, "Expected a NOT_FOUND status code from server"); + if (numFetchAttempts > 9) { if (checkForLoggedExceptions) { printNodeExceptionMessages(log); diff --git a/apitest/src/test/java/bisq/apitest/method/trade/FailUnfailTradeTest.java b/apitest/src/test/java/bisq/apitest/method/trade/FailUnfailTradeTest.java index 5985ea81285..b87c9dcf603 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/FailUnfailTradeTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/FailUnfailTradeTest.java @@ -61,11 +61,11 @@ public void testFailAndUnFailBuyBTCTrade(final TestInfo testInfo) { TakeBuyBTCOfferTest test = new TakeBuyBTCOfferTest(); test.testTakeAlicesBuyOffer(testInfo); - var tradeId = test.getTradeId(); + var tradeId = AbstractTradeTest.getTradeId(); aliceClient.failTrade(tradeId); Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.getTrade(tradeId)); - String expectedExceptionMessage = format("INVALID_ARGUMENT: trade with id '%s' not found", tradeId); + String expectedExceptionMessage = format("NOT_FOUND: trade with id '%s' not found", tradeId); assertEquals(expectedExceptionMessage, exception.getMessage()); try { @@ -82,11 +82,11 @@ public void testFailAndUnFailSellBTCTrade(final TestInfo testInfo) { TakeSellBTCOfferTest test = new TakeSellBTCOfferTest(); test.testTakeAlicesSellOffer(testInfo); - var tradeId = test.getTradeId(); + var tradeId = AbstractTradeTest.getTradeId(); aliceClient.failTrade(tradeId); Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.getTrade(tradeId)); - String expectedExceptionMessage = format("INVALID_ARGUMENT: trade with id '%s' not found", tradeId); + String expectedExceptionMessage = format("NOT_FOUND: trade with id '%s' not found", tradeId); assertEquals(expectedExceptionMessage, exception.getMessage()); try { @@ -101,14 +101,14 @@ public void testFailAndUnFailSellBTCTrade(final TestInfo testInfo) { @Order(3) public void testFailAndUnFailBuyXmrTrade(final TestInfo testInfo) { TakeBuyXMROfferTest test = new TakeBuyXMROfferTest(); - test.createXmrPaymentAccounts(); + createXmrPaymentAccounts(); test.testTakeAlicesSellBTCForXMROffer(testInfo); - var tradeId = test.getTradeId(); + var tradeId = AbstractTradeTest.getTradeId(); aliceClient.failTrade(tradeId); Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.getTrade(tradeId)); - String expectedExceptionMessage = format("INVALID_ARGUMENT: trade with id '%s' not found", tradeId); + String expectedExceptionMessage = format("NOT_FOUND: trade with id '%s' not found", tradeId); assertEquals(expectedExceptionMessage, exception.getMessage()); try { @@ -123,14 +123,14 @@ public void testFailAndUnFailBuyXmrTrade(final TestInfo testInfo) { @Order(4) public void testFailAndUnFailTakeSellXMRTrade(final TestInfo testInfo) { TakeSellXMROfferTest test = new TakeSellXMROfferTest(); - test.createXmrPaymentAccounts(); + createXmrPaymentAccounts(); test.testTakeAlicesBuyBTCForXMROffer(testInfo); - var tradeId = test.getTradeId(); + var tradeId = AbstractTradeTest.getTradeId(); aliceClient.failTrade(tradeId); Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.getTrade(tradeId)); - String expectedExceptionMessage = format("INVALID_ARGUMENT: trade with id '%s' not found", tradeId); + String expectedExceptionMessage = format("NOT_FOUND: trade with id '%s' not found", tradeId); assertEquals(expectedExceptionMessage, exception.getMessage()); try { diff --git a/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBSQOfferTest.java b/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBSQOfferTest.java index a2ae7eda575..1425e7182cd 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBSQOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBSQOfferTest.java @@ -83,7 +83,7 @@ public void testTakeAlicesSellBTCForBSQOffer(final TestInfo testInfo) { var offerId = alicesOffer.getId(); assertFalse(alicesOffer.getIsCurrencyForMakerFeeBtc()); - var alicesBsqOffers = aliceClient.getMyCryptoCurrencyOffers(btcTradeDirection, BSQ); + var alicesBsqOffers = aliceClient.getMyOffers(btcTradeDirection, BSQ); assertEquals(1, alicesBsqOffers.size()); var trade = takeAlicesOffer(offerId, @@ -97,7 +97,7 @@ public void testTakeAlicesSellBTCForBSQOffer(final TestInfo testInfo) { tradeId = trade.getTradeId(); genBtcBlocksThenWait(1, 2_500); - alicesBsqOffers = aliceClient.getMyCryptoCurrencyOffersSortedByDate(BSQ); + alicesBsqOffers = aliceClient.getMyOffersSortedByDate(BSQ); assertEquals(0, alicesBsqOffers.size()); waitForDepositConfirmation(log, testInfo, bobClient, trade.getTradeId()); diff --git a/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyXMROfferTest.java b/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyXMROfferTest.java index 65bb62be7fc..da7d448c773 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyXMROfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyXMROfferTest.java @@ -84,10 +84,10 @@ public void testTakeAlicesSellBTCForXMROffer(final TestInfo testInfo) { var offerId = alicesOffer.getId(); assertFalse(alicesOffer.getIsCurrencyForMakerFeeBtc()); - var alicesXmrOffers = aliceClient.getMyCryptoCurrencyOffers(btcTradeDirection, XMR); + var alicesXmrOffers = aliceClient.getMyOffers(btcTradeDirection, XMR); assertEquals(1, alicesXmrOffers.size()); var trade = takeAlicesOffer(offerId, bobsXmrAcct.getId(), TRADE_FEE_CURRENCY_CODE); - alicesXmrOffers = aliceClient.getMyCryptoCurrencyOffersSortedByDate(XMR); + alicesXmrOffers = aliceClient.getMyOffersSortedByDate(XMR); assertEquals(0, alicesXmrOffers.size()); genBtcBlocksThenWait(1, 2_500); waitForDepositConfirmation(log, testInfo, bobClient, trade.getTradeId()); diff --git a/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBSQOfferTest.java b/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBSQOfferTest.java index 71e89e36402..f7cf59cc899 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBSQOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBSQOfferTest.java @@ -84,14 +84,14 @@ public void testTakeAlicesBuyBTCForBSQOffer(final TestInfo testInfo) { genBtcBlocksThenWait(1, 4_000); var offerId = alicesOffer.getId(); assertTrue(alicesOffer.getIsCurrencyForMakerFeeBtc()); - var alicesBsqOffers = aliceClient.getMyCryptoCurrencyOffers(btcTradeDirection, BSQ); + var alicesBsqOffers = aliceClient.getMyOffers(btcTradeDirection, BSQ); assertEquals(1, alicesBsqOffers.size()); var trade = takeAlicesOffer(offerId, bobsLegacyBsqAcct.getId(), TRADE_FEE_CURRENCY_CODE, false); sleep(2_500); // Allow available offer to be removed from offer book. - alicesBsqOffers = aliceClient.getMyCryptoCurrencyOffersSortedByDate(BSQ); + alicesBsqOffers = aliceClient.getMyOffersSortedByDate(BSQ); assertEquals(0, alicesBsqOffers.size()); genBtcBlocksThenWait(1, 2_500); waitForDepositConfirmation(log, testInfo, bobClient, trade.getTradeId()); diff --git a/apitest/src/test/java/bisq/apitest/method/trade/TakeSellXMROfferTest.java b/apitest/src/test/java/bisq/apitest/method/trade/TakeSellXMROfferTest.java index 49b03395eb1..6b884f5bff4 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/TakeSellXMROfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/TakeSellXMROfferTest.java @@ -88,10 +88,10 @@ public void testTakeAlicesBuyBTCForXMROffer(final TestInfo testInfo) { var offerId = alicesOffer.getId(); assertTrue(alicesOffer.getIsCurrencyForMakerFeeBtc()); - var alicesXmrOffers = aliceClient.getMyCryptoCurrencyOffers(btcTradeDirection, XMR); + var alicesXmrOffers = aliceClient.getMyOffers(btcTradeDirection, XMR); assertEquals(1, alicesXmrOffers.size()); var trade = takeAlicesOffer(offerId, bobsXmrAcct.getId(), TRADE_FEE_CURRENCY_CODE); - alicesXmrOffers = aliceClient.getMyCryptoCurrencyOffersSortedByDate(XMR); + alicesXmrOffers = aliceClient.getMyOffersSortedByDate(XMR); assertEquals(0, alicesXmrOffers.size()); genBtcBlocksThenWait(1, 2_500); diff --git a/apitest/src/test/java/bisq/apitest/method/wallet/BtcTxFeeRateTest.java b/apitest/src/test/java/bisq/apitest/method/wallet/BtcTxFeeRateTest.java index 493491439fe..1925b4452c5 100644 --- a/apitest/src/test/java/bisq/apitest/method/wallet/BtcTxFeeRateTest.java +++ b/apitest/src/test/java/bisq/apitest/method/wallet/BtcTxFeeRateTest.java @@ -58,7 +58,7 @@ public void testSetInvalidTxFeeRateShouldThrowException(final TestInfo testInfo) var currentTxFeeRateInfo = TxFeeRateInfo.fromProto(aliceClient.getTxFeeRate()); Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.setTxFeeRate(1)); String expectedExceptionMessage = - format("UNKNOWN: tx fee rate preference must be >= %d sats/byte", + format("INVALID_ARGUMENT: tx fee rate preference must be >= %d sats/byte", currentTxFeeRateInfo.getMinFeeServiceRate()); assertEquals(expectedExceptionMessage, exception.getMessage()); } diff --git a/apitest/src/test/java/bisq/apitest/method/wallet/WalletProtectionTest.java b/apitest/src/test/java/bisq/apitest/method/wallet/WalletProtectionTest.java index 30de7f585b8..9799c38dfc8 100644 --- a/apitest/src/test/java/bisq/apitest/method/wallet/WalletProtectionTest.java +++ b/apitest/src/test/java/bisq/apitest/method/wallet/WalletProtectionTest.java @@ -48,7 +48,7 @@ public void testSetWalletPassword() { @Order(2) public void testGetBalanceOnEncryptedWalletShouldThrowException() { Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.getBtcBalances()); - assertEquals("UNKNOWN: wallet is locked", exception.getMessage()); + assertEquals("FAILED_PRECONDITION: wallet is locked", exception.getMessage()); } @Test @@ -58,7 +58,7 @@ public void testUnlockWalletFor4Seconds() { aliceClient.getBtcBalances(); // should not throw 'wallet locked' exception sleep(4500); // let unlock timeout expire Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.getBtcBalances()); - assertEquals("UNKNOWN: wallet is locked", exception.getMessage()); + assertEquals("FAILED_PRECONDITION: wallet is locked", exception.getMessage()); } @Test @@ -67,7 +67,7 @@ public void testGetBalanceAfterUnlockTimeExpiryShouldThrowException() { aliceClient.unlockWallet("first-password", 3); sleep(4000); // let unlock timeout expire Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.getBtcBalances()); - assertEquals("UNKNOWN: wallet is locked", exception.getMessage()); + assertEquals("FAILED_PRECONDITION: wallet is locked", exception.getMessage()); } @Test @@ -76,14 +76,14 @@ public void testLockWalletBeforeUnlockTimeoutExpiry() { aliceClient.unlockWallet("first-password", 60); aliceClient.lockWallet(); Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.getBtcBalances()); - assertEquals("UNKNOWN: wallet is locked", exception.getMessage()); + assertEquals("FAILED_PRECONDITION: wallet is locked", exception.getMessage()); } @Test @Order(6) public void testLockWalletWhenWalletAlreadyLockedShouldThrowException() { Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.lockWallet()); - assertEquals("UNKNOWN: wallet is already locked", exception.getMessage()); + assertEquals("ALREADY_EXISTS: wallet is already locked", exception.getMessage()); } @Test @@ -110,7 +110,7 @@ public void testSetNewWalletPassword() { public void testSetNewWalletPasswordWithIncorrectNewPasswordShouldThrowException() { Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.setWalletPassword("bad old password", "irrelevant")); - assertEquals("UNKNOWN: incorrect old password", exception.getMessage()); + assertEquals("INVALID_ARGUMENT: incorrect old password", exception.getMessage()); } @Test diff --git a/cli/src/main/java/bisq/cli/CliMain.java b/cli/src/main/java/bisq/cli/CliMain.java index 361fb1daa34..f1282101feb 100644 --- a/cli/src/main/java/bisq/cli/CliMain.java +++ b/cli/src/main/java/bisq/cli/CliMain.java @@ -740,7 +740,8 @@ public static void run(String[] args) { } } } catch (StatusRuntimeException ex) { - // Remove the leading gRPC status code (e.g. "UNKNOWN: ") from the message + // Remove the leading gRPC status code, e.g., INVALID_ARGUMENT, + // NOT_FOUND, ..., UNKNOWN from the exception message. String message = ex.getMessage().replaceFirst("^[A-Z_]+: ", ""); if (message.equals("io exception")) throw new RuntimeException(message + ", server may not be running", ex); diff --git a/cli/src/main/java/bisq/cli/GrpcClient.java b/cli/src/main/java/bisq/cli/GrpcClient.java index bf9b20888da..ab9484f350a 100644 --- a/cli/src/main/java/bisq/cli/GrpcClient.java +++ b/cli/src/main/java/bisq/cli/GrpcClient.java @@ -27,7 +27,6 @@ import bisq.proto.grpc.OfferInfo; import bisq.proto.grpc.RegisterDisputeAgentRequest; import bisq.proto.grpc.StopRequest; -import bisq.proto.grpc.TakeOfferReply; import bisq.proto.grpc.TradeInfo; import bisq.proto.grpc.TxFeeRateInfo; import bisq.proto.grpc.TxInfo; @@ -271,10 +270,6 @@ public OfferInfo getOffer(String offerId) { return offersServiceRequest.getOffer(offerId); } - public OfferInfo getMyBsqSwapOffer(String offerId) { - return offersServiceRequest.getMyBsqSwapOffer(offerId); - } - @Deprecated // Since 5-Dec-2021. // Endpoint to be removed from future version. Use getOffer service method instead. public OfferInfo getMyOffer(String offerId) { @@ -289,10 +284,6 @@ public List getOffers(String direction, String currencyCode) { return offersServiceRequest.getOffers(direction, currencyCode); } - public List getCryptoCurrencyOffers(String direction, String currencyCode) { - return offersServiceRequest.getCryptoCurrencyOffers(direction, currencyCode); - } - public List getOffersSortedByDate(String currencyCode) { return offersServiceRequest.getOffersSortedByDate(currencyCode); } @@ -301,58 +292,26 @@ public List getOffersSortedByDate(String direction, String currencyCo return offersServiceRequest.getOffersSortedByDate(direction, currencyCode); } - public List getCryptoCurrencyOffersSortedByDate(String currencyCode) { - return offersServiceRequest.getCryptoCurrencyOffersSortedByDate(currencyCode); - } - public List getBsqSwapOffersSortedByDate() { return offersServiceRequest.getBsqSwapOffersSortedByDate(); } - public List getMyBsqSwapOffers(String direction) { - return offersServiceRequest.getMyBsqSwapOffers(direction); - } - public List getMyOffers(String direction, String currencyCode) { return offersServiceRequest.getMyOffers(direction, currencyCode); } - public List getMyCryptoCurrencyOffers(String direction, String currencyCode) { - return offersServiceRequest.getMyCryptoCurrencyOffers(direction, currencyCode); - } - - public List getMyOffersSortedByDate(String direction, String currencyCode) { - return offersServiceRequest.getMyOffersSortedByDate(direction, currencyCode); - } - public List getMyOffersSortedByDate(String currencyCode) { return offersServiceRequest.getMyOffersSortedByDate(currencyCode); } - public List getMyCryptoCurrencyOffersSortedByDate(String currencyCode) { - return offersServiceRequest.getMyCryptoCurrencyOffersSortedByDate(currencyCode); + public List getMyOffersSortedByDate(String direction, String currencyCode) { + return offersServiceRequest.getMyOffersSortedByDate(direction, currencyCode); } public List getMyBsqSwapBsqOffersSortedByDate() { return offersServiceRequest.getMyBsqSwapOffersSortedByDate(); } - public OfferInfo getMostRecentOffer(String direction, String currencyCode) { - return offersServiceRequest.getMostRecentOffer(direction, currencyCode); - } - - public List sortBsqSwapOffersByDate(List offers) { - return offersServiceRequest.sortOffersByDate(offers); - } - - public List sortOffersByDate(List offers) { - return offersServiceRequest.sortOffersByDate(offers); - } - - public TakeOfferReply getTakeOfferReply(String offerId, String paymentAccountId, String takerFeeCurrencyCode) { - return tradesServiceRequest.getTakeOfferReply(offerId, paymentAccountId, takerFeeCurrencyCode); - } - public TradeInfo takeBsqSwapOffer(String offerId) { return tradesServiceRequest.takeBsqSwapOffer(offerId); } diff --git a/cli/src/main/java/bisq/cli/request/OffersServiceRequest.java b/cli/src/main/java/bisq/cli/request/OffersServiceRequest.java index 65b62f05838..20f6158f2b6 100644 --- a/cli/src/main/java/bisq/cli/request/OffersServiceRequest.java +++ b/cli/src/main/java/bisq/cli/request/OffersServiceRequest.java @@ -32,7 +32,6 @@ import java.util.ArrayList; import java.util.List; -import static bisq.cli.CryptoCurrencyUtil.apiDoesSupportCryptoCurrency; import static bisq.proto.grpc.EditOfferRequest.EditType.ACTIVATION_STATE_ONLY; import static bisq.proto.grpc.EditOfferRequest.EditType.FIXED_PRICE_ONLY; import static bisq.proto.grpc.EditOfferRequest.EditType.MKT_PRICE_MARGIN_ONLY; @@ -217,13 +216,6 @@ public OfferInfo getOffer(String offerId) { return grpcStubs.offersService.getOffer(request).getOffer(); } - public OfferInfo getMyBsqSwapOffer(String offerId) { - var request = GetMyOfferRequest.newBuilder() - .setId(offerId) - .build(); - return grpcStubs.offersService.getMyBsqSwapOffer(request).getBsqSwapOffer(); - } - public OfferInfo getMyOffer(String offerId) { var request = GetMyOfferRequest.newBuilder() .setId(offerId) @@ -240,28 +232,18 @@ public List getBsqSwapOffers(String direction) { } public List getOffers(String direction, String currencyCode) { - if (apiDoesSupportCryptoCurrency(currencyCode)) { - return getCryptoCurrencyOffers(direction, currencyCode); - } else { - var request = GetOffersRequest.newBuilder() - .setDirection(direction) - .setCurrencyCode(currencyCode) - .build(); - return grpcStubs.offersService.getOffers(request).getOffersList(); - } - } - - public List getCryptoCurrencyOffers(String direction, String currencyCode) { - return getOffers(direction, "BTC").stream() - .filter(o -> o.getBaseCurrencyCode().equalsIgnoreCase(currencyCode)) - .collect(toList()); + var request = GetOffersRequest.newBuilder() + .setDirection(direction) + .setCurrencyCode(currencyCode) + .build(); + return grpcStubs.offersService.getOffers(request).getOffersList(); } public List getOffersSortedByDate(String currencyCode) { ArrayList offers = new ArrayList<>(); offers.addAll(getOffers(BUY.name(), currencyCode)); offers.addAll(getOffers(SELL.name(), currencyCode)); - return sortOffersByDate(offers); + return offers.isEmpty() ? offers : sortOffersByDate(offers); } public List getOffersSortedByDate(String direction, String currencyCode) { @@ -269,13 +251,6 @@ public List getOffersSortedByDate(String direction, String currencyCo return offers.isEmpty() ? offers : sortOffersByDate(offers); } - public List getCryptoCurrencyOffersSortedByDate(String currencyCode) { - ArrayList offers = new ArrayList<>(); - offers.addAll(getCryptoCurrencyOffers(BUY.name(), currencyCode)); - offers.addAll(getCryptoCurrencyOffers(SELL.name(), currencyCode)); - return sortOffersByDate(offers); - } - public List getBsqSwapOffersSortedByDate() { ArrayList offers = new ArrayList<>(); offers.addAll(getBsqSwapOffers(BUY.name())); @@ -291,40 +266,23 @@ public List getMyBsqSwapOffers(String direction) { } public List getMyOffers(String direction, String currencyCode) { - if (apiDoesSupportCryptoCurrency(currencyCode)) { - return getMyCryptoCurrencyOffers(direction, currencyCode); - } else { - var request = GetMyOffersRequest.newBuilder() - .setDirection(direction) - .setCurrencyCode(currencyCode) - .build(); - return grpcStubs.offersService.getMyOffers(request).getOffersList(); - } - } - - public List getMyCryptoCurrencyOffers(String direction, String currencyCode) { - return getMyOffers(direction, "BTC").stream() - .filter(o -> o.getBaseCurrencyCode().equalsIgnoreCase(currencyCode)) - .collect(toList()); - } - - public List getMyOffersSortedByDate(String direction, String currencyCode) { - var offers = getMyOffers(direction, currencyCode); - return offers.isEmpty() ? offers : sortOffersByDate(offers); + var request = GetMyOffersRequest.newBuilder() + .setDirection(direction) + .setCurrencyCode(currencyCode) + .build(); + return grpcStubs.offersService.getMyOffers(request).getOffersList(); } public List getMyOffersSortedByDate(String currencyCode) { ArrayList offers = new ArrayList<>(); offers.addAll(getMyOffers(BUY.name(), currencyCode)); offers.addAll(getMyOffers(SELL.name(), currencyCode)); - return sortOffersByDate(offers); + return offers.isEmpty() ? offers : sortOffersByDate(offers); } - public List getMyCryptoCurrencyOffersSortedByDate(String currencyCode) { - ArrayList offers = new ArrayList<>(); - offers.addAll(getMyCryptoCurrencyOffers(BUY.name(), currencyCode)); - offers.addAll(getMyCryptoCurrencyOffers(SELL.name(), currencyCode)); - return sortOffersByDate(offers); + public List getMyOffersSortedByDate(String direction, String currencyCode) { + var offers = getMyOffers(direction, currencyCode); + return offers.isEmpty() ? offers : sortOffersByDate(offers); } public List getMyBsqSwapOffersSortedByDate() { diff --git a/cli/src/test/java/bisq/cli/AbstractCliTest.java b/cli/src/test/java/bisq/cli/AbstractCliTest.java index a0367ed2602..8fc279295fb 100644 --- a/cli/src/test/java/bisq/cli/AbstractCliTest.java +++ b/cli/src/test/java/bisq/cli/AbstractCliTest.java @@ -135,7 +135,7 @@ protected List getMyAltcoinOffers(String currencyCode) { CliMain.main(args); out.println("<<<<<"); - return aliceClient.getMyCryptoCurrencyOffersSortedByDate(currencyCode); + return aliceClient.getMyOffersSortedByDate(currencyCode); } protected String[] getMyOffersCommand(String direction, String currencyCode) { diff --git a/core/src/main/java/bisq/core/api/CoreDisputeAgentsService.java b/core/src/main/java/bisq/core/api/CoreDisputeAgentsService.java index 7b060834a93..e22275fb054 100644 --- a/core/src/main/java/bisq/core/api/CoreDisputeAgentsService.java +++ b/core/src/main/java/bisq/core/api/CoreDisputeAgentsService.java @@ -17,6 +17,7 @@ package bisq.core.api; +import bisq.core.api.exception.NotAvailableException; import bisq.core.support.SupportType; import bisq.core.support.dispute.mediation.mediator.Mediator; import bisq.core.support.dispute.mediation.mediator.MediatorManager; @@ -79,12 +80,12 @@ public CoreDisputeAgentsService(Config config, void registerDisputeAgent(String disputeAgentType, String registrationKey) { if (!p2PService.isBootstrapped()) - throw new IllegalStateException("p2p service is not bootstrapped yet"); + throw new NotAvailableException("p2p service is not bootstrapped yet"); if (config.baseCurrencyNetwork.isMainnet() || config.baseCurrencyNetwork.isDaoBetaNet() || !config.useLocalhostForP2P) - throw new IllegalStateException("dispute agents must be registered in a Bisq UI"); + throw new UnsupportedOperationException("dispute agents must be registered in a Bisq UI"); if (!registrationKey.equals(DEV_PRIVILEGE_PRIV_KEY)) throw new IllegalArgumentException("invalid registration key"); @@ -95,7 +96,7 @@ void registerDisputeAgent(String disputeAgentType, String registrationKey) { String signature; switch (supportType.get()) { case ARBITRATION: - throw new IllegalArgumentException("arbitrators must be registered in a Bisq UI"); + throw new UnsupportedOperationException("arbitrators must be registered in a Bisq UI"); case MEDIATION: ecKey = mediatorManager.getRegistrationKey(registrationKey); signature = mediatorManager.signStorageSignaturePubKey(Objects.requireNonNull(ecKey)); @@ -107,7 +108,7 @@ void registerDisputeAgent(String disputeAgentType, String registrationKey) { registerRefundAgent(nodeAddress, languageCodes, ecKey, signature); return; case TRADE: - throw new IllegalArgumentException("trade agent registration not supported"); + throw new UnsupportedOperationException("trade agent registration not supported"); } } else { throw new IllegalArgumentException(format("unknown dispute agent type '%s'", disputeAgentType)); diff --git a/core/src/main/java/bisq/core/api/CoreHelpService.java b/core/src/main/java/bisq/core/api/CoreHelpService.java index 6a4605f7484..1ee33abf3b9 100644 --- a/core/src/main/java/bisq/core/api/CoreHelpService.java +++ b/core/src/main/java/bisq/core/api/CoreHelpService.java @@ -17,6 +17,8 @@ package bisq.core.api; +import bisq.core.api.exception.NotFoundException; + import javax.inject.Inject; import javax.inject.Singleton; @@ -45,7 +47,7 @@ public String getMethodHelp(String methodName) { return readHelpFile(resourceFile); } catch (NullPointerException ex) { log.error("", ex); - throw new IllegalStateException(format("no help found for api method %s", methodName)); + throw new NotFoundException(format("no help found for api method %s", methodName)); } catch (IOException ex) { log.error("", ex); throw new IllegalStateException(format("could not read %s help doc", methodName)); diff --git a/core/src/main/java/bisq/core/api/CoreOffersService.java b/core/src/main/java/bisq/core/api/CoreOffersService.java index 4fdd8495738..c02b7cf1dee 100644 --- a/core/src/main/java/bisq/core/api/CoreOffersService.java +++ b/core/src/main/java/bisq/core/api/CoreOffersService.java @@ -17,6 +17,7 @@ package bisq.core.api; +import bisq.core.api.exception.NotFoundException; import bisq.core.monetary.Altcoin; import bisq.core.monetary.Price; import bisq.core.offer.Offer; @@ -59,7 +60,9 @@ import static bisq.common.util.MathUtils.exactMultiply; import static bisq.common.util.MathUtils.roundDoubleToLong; import static bisq.common.util.MathUtils.scaleUpByPowerOf10; +import static bisq.core.locale.CurrencyUtil.apiSupportsCryptoCurrency; import static bisq.core.locale.CurrencyUtil.isCryptoCurrency; +import static bisq.core.locale.CurrencyUtil.isFiatCurrency; import static bisq.core.offer.Offer.State; import static bisq.core.offer.OfferDirection.BUY; import static bisq.core.offer.OfferUtil.getRandomOfferId; @@ -143,7 +146,7 @@ boolean isBsqSwapOffer(String id, boolean isMyOffer) { Offer getOffer(String id) { return findAvailableOffer(id).orElseThrow(() -> - new IllegalStateException(format("offer with id '%s' not found", id))); + new NotFoundException(format("offer with id '%s' not found", id))); } Optional findAvailableOffer(String id) { @@ -156,7 +159,7 @@ Optional findAvailableOffer(String id) { OpenOffer getMyOffer(String id) { return findMyOpenOffer(id).orElseThrow(() -> - new IllegalStateException(format("offer with id '%s' not found", id))); + new NotFoundException(format("offer with id '%s' not found", id))); } Optional findMyOpenOffer(String id) { @@ -168,7 +171,7 @@ Optional findMyOpenOffer(String id) { Offer getBsqSwapOffer(String id) { return findAvailableBsqSwapOffer(id).orElseThrow(() -> - new IllegalStateException(format("offer with id '%s' not found", id))); + new NotFoundException(format("offer with id '%s' not found", id))); } Optional findAvailableBsqSwapOffer(String id) { @@ -182,7 +185,7 @@ Optional findAvailableBsqSwapOffer(String id) { Offer getMyBsqSwapOffer(String id) { return findMyBsqSwapOffer(id).orElseThrow(() -> - new IllegalStateException(format("offer with id '%s' not found", id))); + new NotFoundException(format("offer with id '%s' not found", id))); } Optional findMyBsqSwapOffer(String id) { @@ -203,20 +206,57 @@ List getBsqSwapOffers(String direction) { } List getOffers(String direction, String currencyCode) { - return offerBookService.getOffers().stream() - .filter(o -> !o.isMyOffer(keyRing)) - .filter(o -> offerMatchesDirectionAndCurrency(o, direction, currencyCode)) - .filter(o -> offerFilterService.canTakeOffer(o, coreContext.isApiUser()).isValid()) - .sorted(priceComparator(direction)) - .collect(Collectors.toList()); + var upperCaseCurrencyCode = currencyCode.toUpperCase(); + if (isFiatCurrency(upperCaseCurrencyCode)) { + return offerBookService.getOffers().stream() + .filter(o -> !o.isMyOffer(keyRing)) + .filter(o -> offerMatchesDirectionAndCurrency(o, direction, upperCaseCurrencyCode)) + .filter(o -> offerFilterService.canTakeOffer(o, coreContext.isApiUser()).isValid()) + .sorted(priceComparator(direction)) + .collect(Collectors.toList()); + } else { + // In fiat offers, the baseCurrencyCode=BTC, counterCurrencyCode=FiatCode. + // In altcoin offers, baseCurrencyCode=AltcoinCode, counterCurrencyCode=BTC. + // This forces an extra filtering step below: get all BTC offers, + // then filter on the currencyCode param (the altcoin code). + if (apiSupportsCryptoCurrency(upperCaseCurrencyCode)) + return offerBookService.getOffers().stream() + .filter(o -> !o.isMyOffer(keyRing)) + .filter(o -> offerMatchesDirectionAndCurrency(o, direction, "BTC")) + .filter(o -> o.getBaseCurrencyCode().equalsIgnoreCase(upperCaseCurrencyCode)) + .filter(o -> offerFilterService.canTakeOffer(o, coreContext.isApiUser()).isValid()) + .sorted(priceComparator(direction)) + .collect(Collectors.toList()); + else + throw new IllegalArgumentException( + format("api does not support the '%s' crypto currency", upperCaseCurrencyCode)); + } } List getMyOffers(String direction, String currencyCode) { - return openOfferManager.getObservableList().stream() - .filter(o -> o.getOffer().isMyOffer(keyRing)) - .filter(o -> offerMatchesDirectionAndCurrency(o.getOffer(), direction, currencyCode)) - .sorted(openOfferPriceComparator(direction)) - .collect(Collectors.toList()); + var upperCaseCurrencyCode = currencyCode.toUpperCase(); + if (isFiatCurrency(upperCaseCurrencyCode)) { + return openOfferManager.getObservableList().stream() + .filter(o -> o.getOffer().isMyOffer(keyRing)) + .filter(o -> offerMatchesDirectionAndCurrency(o.getOffer(), direction, upperCaseCurrencyCode)) + .sorted(openOfferPriceComparator(direction)) + .collect(Collectors.toList()); + } else { + // In fiat offers, the baseCurrencyCode=BTC, counterCurrencyCode=FiatCode. + // In altcoin offers, baseCurrencyCode=AltcoinCode, counterCurrencyCode=BTC. + // This forces an extra filtering step below: get all BTC offers, + // then filter on the currencyCode param (the altcoin code). + if (apiSupportsCryptoCurrency(upperCaseCurrencyCode)) + return openOfferManager.getObservableList().stream() + .filter(o -> o.getOffer().isMyOffer(keyRing)) + .filter(o -> offerMatchesDirectionAndCurrency(o.getOffer(), direction, "BTC")) + .filter(o -> o.getOffer().getBaseCurrencyCode().equalsIgnoreCase(upperCaseCurrencyCode)) + .sorted(openOfferPriceComparator(direction)) + .collect(Collectors.toList()); + else + throw new IllegalArgumentException( + format("api does not support the '%s' crypto currency", upperCaseCurrencyCode)); + } } List getMyBsqSwapOffers(String direction) { @@ -233,14 +273,14 @@ OpenOffer getMyOpenBsqSwapOffer(String id) { .filter(open -> open.getOffer().isMyOffer(keyRing)) .filter(open -> open.getOffer().isBsqSwapOffer()) .orElseThrow(() -> - new IllegalStateException(format("openoffer with id '%s' not found", id))); + new NotFoundException(format("openoffer with id '%s' not found", id))); } OpenOffer getMyOpenOffer(String id) { return openOfferManager.getOpenOfferById(id) .filter(open -> open.getOffer().isMyOffer(keyRing)) .orElseThrow(() -> - new IllegalStateException(format("offer with id '%s' not found", id))); + new NotFoundException(format("offer with id '%s' not found", id))); } boolean isMyOffer(Offer offer) { diff --git a/core/src/main/java/bisq/core/api/CorePaymentAccountsService.java b/core/src/main/java/bisq/core/api/CorePaymentAccountsService.java index de053847384..05e34852d3e 100644 --- a/core/src/main/java/bisq/core/api/CorePaymentAccountsService.java +++ b/core/src/main/java/bisq/core/api/CorePaymentAccountsService.java @@ -40,13 +40,13 @@ import java.util.List; import java.util.Optional; import java.util.Set; -import java.util.function.Predicate; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import static bisq.common.app.DevEnv.isDaoTradingActivated; import static bisq.common.config.Config.baseCurrencyNetwork; +import static bisq.core.locale.CurrencyUtil.apiSupportsCryptoCurrency; import static bisq.core.locale.CurrencyUtil.findAsset; import static bisq.core.locale.CurrencyUtil.getCryptoCurrency; import static java.lang.String.format; @@ -55,9 +55,6 @@ @Slf4j class CorePaymentAccountsService { - private final Predicate apiDoesSupportCryptoCurrencyAccount = (c) -> - c.equals("BSQ") || c.equals("XMR"); - private final CoreWalletsService coreWalletsService; private final AccountAgeWitnessService accountAgeWitnessService; private final PaymentAccountForm paymentAccountForm; @@ -159,7 +156,7 @@ private void verifyCryptoCurrencyAddress(String cryptoCurrencyCode, String addre } private void verifyApiDoesSupportCryptoCurrencyAccount(String cryptoCurrencyCode) { - if (!apiDoesSupportCryptoCurrencyAccount.test(cryptoCurrencyCode)) + if (!apiSupportsCryptoCurrency(cryptoCurrencyCode)) throw new IllegalArgumentException( format("api does not currently support %s accounts", cryptoCurrencyCode.toLowerCase())); diff --git a/core/src/main/java/bisq/core/api/CoreTradesService.java b/core/src/main/java/bisq/core/api/CoreTradesService.java index db206e2b4b4..2456a28e8c0 100644 --- a/core/src/main/java/bisq/core/api/CoreTradesService.java +++ b/core/src/main/java/bisq/core/api/CoreTradesService.java @@ -17,6 +17,7 @@ package bisq.core.api; +import bisq.core.api.exception.NotFoundException; import bisq.core.btc.model.AddressEntry; import bisq.core.btc.wallet.BtcWalletService; import bisq.core.offer.Offer; @@ -204,7 +205,7 @@ void closeTrade(String tradeId) { verifyTradeIsNotClosed(tradeId); var trade = getOpenTrade(tradeId).orElseThrow(() -> - new IllegalArgumentException(format("trade with id '%s' not found", tradeId))); + new NotFoundException(format("trade with id '%s' not found", tradeId))); log.info("Closing trade {}", tradeId); tradeManager.onTradeCompleted(trade); } @@ -215,7 +216,7 @@ void withdrawFunds(String tradeId, String toAddress, String memo) { verifyTradeIsNotClosed(tradeId); var trade = getOpenTrade(tradeId).orElseThrow(() -> - new IllegalArgumentException(format("trade with id '%s' not found", tradeId))); + new NotFoundException(format("trade with id '%s' not found", tradeId))); verifyIsValidBTCAddress(toAddress); @@ -263,7 +264,7 @@ TradeModel getTradeModel(String tradeId) { return closedTrade.get(); return tradeManager.findBsqSwapTradeById(tradeId).orElseThrow(() -> - new IllegalArgumentException(format("trade with id '%s' not found", tradeId))); + new NotFoundException(format("trade with id '%s' not found", tradeId))); } String getTradeRole(TradeModel tradeModel) { @@ -285,7 +286,7 @@ Trade getTrade(String tradeId) { coreWalletsService.verifyEncryptedWalletIsUnlocked(); return getOpenTrade(tradeId).orElseGet(() -> getClosedTrade(tradeId).orElseThrow(() -> - new IllegalArgumentException(format("trade with id '%s' not found", tradeId)) + new NotFoundException(format("trade with id '%s' not found", tradeId)) )); } @@ -333,7 +334,7 @@ void unFailTrade(String tradeId) { tradeManager.addFailedTradeToPendingTrades(failedTrade); log.info("Failed trade {} changed to open trade.", tradeId); }, () -> { - throw new IllegalArgumentException(format("failed trade '%s' not found", tradeId)); + throw new NotFoundException(format("failed trade '%s' not found", tradeId)); }); } diff --git a/core/src/main/java/bisq/core/api/CoreWalletsService.java b/core/src/main/java/bisq/core/api/CoreWalletsService.java index 6579786e147..4b01bfc79ba 100644 --- a/core/src/main/java/bisq/core/api/CoreWalletsService.java +++ b/core/src/main/java/bisq/core/api/CoreWalletsService.java @@ -17,6 +17,10 @@ package bisq.core.api; +import bisq.core.api.exception.AlreadyExistsException; +import bisq.core.api.exception.FailedPreconditionException; +import bisq.core.api.exception.NotAvailableException; +import bisq.core.api.exception.NotFoundException; import bisq.core.api.model.AddressBalanceInfo; import bisq.core.api.model.BalancesInfo; import bisq.core.api.model.BsqBalanceInfo; @@ -152,7 +156,7 @@ BalancesInfo getBalances(String currencyCode) { verifyWalletsAreAvailable(); verifyEncryptedWalletIsUnlocked(); if (balances.getAvailableBalance().get() == null) - throw new IllegalStateException("balance is not yet available"); + throw new NotAvailableException("balance is not yet available"); switch (currencyCode.trim().toUpperCase()) { case "BSQ": @@ -241,13 +245,13 @@ void sendBsq(String addressStr, txFeePerVbyte.value); bsqTransferService.sendFunds(model, callback); } catch (InsufficientMoneyException ex) { - log.error("", ex); - throw new IllegalStateException("cannot send bsq due to insufficient funds", ex); + log.error(ex.toString()); + throw new NotAvailableException("cannot send bsq due to insufficient funds", ex); } catch (NumberFormatException | BsqChangeBelowDustException | TransactionVerificationException | WalletException ex) { - log.error("", ex); + log.error(ex.toString()); throw new IllegalStateException(ex); } } @@ -299,11 +303,11 @@ void sendBtc(String address, memo.isEmpty() ? null : memo, callback); } catch (AddressEntryException ex) { - log.error("", ex); + log.error(ex.toString()); throw new IllegalStateException("cannot send btc from any addresses in wallet", ex); } catch (InsufficientFundsException | InsufficientMoneyException ex) { - log.error("", ex); - throw new IllegalStateException("cannot send btc due to insufficient funds", ex); + log.error(ex.toString()); + throw new NotAvailableException("cannot send btc due to insufficient funds", ex); } } @@ -362,7 +366,7 @@ public void onFailure(Throwable t) { }, MoreExecutors.directExecutor()); } catch (Exception ex) { - log.error("", ex); + log.error(ex.toString()); throw new IllegalStateException("could not request fees from fee service", ex); } } @@ -371,7 +375,7 @@ void setTxFeeRatePreference(long txFeeRate, ResultHandler resultHandler) { long minFeePerVbyte = feeService.getMinFeePerVByte(); if (txFeeRate < minFeePerVbyte) - throw new IllegalStateException( + throw new IllegalArgumentException( format("tx fee rate preference must be >= %d sats/byte", minFeePerVbyte)); preferences.setUseCustomWithdrawalTxFee(true); @@ -416,11 +420,11 @@ void setWalletPassword(String password, String newPassword) { if (newPassword != null && !newPassword.isEmpty()) { // TODO Validate new password before replacing old password. if (!walletsManager.areWalletsEncrypted()) - throw new IllegalStateException("wallet is not encrypted with a password"); + throw new FailedPreconditionException("wallet is not encrypted with a password"); KeyParameter aesKey = keyCrypterScrypt.deriveKey(password); if (!walletsManager.checkAESKey(aesKey)) - throw new IllegalStateException("incorrect old password"); + throw new IllegalArgumentException("incorrect old password"); walletsManager.decryptWallets(aesKey); aesKey = keyCrypterScrypt.deriveKey(newPassword); @@ -430,7 +434,7 @@ void setWalletPassword(String password, String newPassword) { } if (walletsManager.areWalletsEncrypted()) - throw new IllegalStateException("wallet is encrypted with a password"); + throw new AlreadyExistsException("wallet is already encrypted with a password"); // TODO Validate new password. KeyParameter aesKey = keyCrypterScrypt.deriveKey(password); @@ -440,10 +444,10 @@ void setWalletPassword(String password, String newPassword) { void lockWallet() { if (!walletsManager.areWalletsEncrypted()) - throw new IllegalStateException("wallet is not encrypted with a password"); + throw new FailedPreconditionException("wallet is not encrypted with a password"); if (tempAesKey == null) - throw new IllegalStateException("wallet is already locked"); + throw new AlreadyExistsException("wallet is already locked"); tempAesKey = null; } @@ -457,7 +461,7 @@ void unlockWallet(String password, long timeout) { tempAesKey = keyCrypterScrypt.deriveKey(password); if (!walletsManager.checkAESKey(tempAesKey)) - throw new IllegalStateException("incorrect password"); + throw new IllegalArgumentException("incorrect password"); if (lockTimer != null) { // The user has called unlockwallet again, before the prior unlockwallet @@ -488,7 +492,7 @@ void removeWalletPassword(String password) { KeyParameter aesKey = keyCrypterScrypt.deriveKey(password); if (!walletsManager.checkAESKey(aesKey)) - throw new IllegalStateException("incorrect password"); + throw new IllegalArgumentException("incorrect password"); walletsManager.decryptWallets(aesKey); walletsManager.backupWallets(); @@ -503,7 +507,7 @@ void verifyWalletsAreAvailable() { // to leave this check in place until certain AppStartupState will always work // as expected. if (!walletsManager.areWalletsAvailable()) - throw new IllegalStateException("wallet is not yet available"); + throw new NotAvailableException("wallet is not yet available"); } // Throws a RuntimeException if wallets are not available or not encrypted. @@ -511,28 +515,28 @@ void verifyWalletIsAvailableAndEncrypted() { verifyWalletAndNetworkIsReady(); if (!walletsManager.areWalletsAvailable()) - throw new IllegalStateException("wallet is not yet available"); + throw new NotAvailableException("wallet is not yet available"); if (!walletsManager.areWalletsEncrypted()) - throw new IllegalStateException("wallet is not encrypted with a password"); + throw new FailedPreconditionException("wallet is not encrypted with a password"); } // Throws a RuntimeException if wallets are encrypted and locked. void verifyEncryptedWalletIsUnlocked() { if (walletsManager.areWalletsEncrypted() && tempAesKey == null) - throw new IllegalStateException("wallet is locked"); + throw new FailedPreconditionException("wallet is locked"); } // Throws a RuntimeException if wallets and network are not ready. void verifyWalletAndNetworkIsReady() { if (!appStartupState.isWalletAndNetworkReady()) - throw new IllegalStateException("wallet and network is not yet initialized"); + throw new NotAvailableException("wallet and network are not yet initialized"); } // Throws a RuntimeException if application is not fully initialized. void verifyApplicationIsFullyInitialized() { if (!appStartupState.isApplicationFullyInitialized()) - throw new IllegalStateException("server is not fully initialized"); + throw new NotAvailableException("server is not fully initialized"); } // Returns an Address for the string, or a RuntimeException if invalid. @@ -541,7 +545,7 @@ Address getValidBsqAddress(String address) { return bsqFormatter.getAddressFromBsqAddress(address); } catch (RuntimeException e) { log.error("", e); - throw new IllegalStateException(format("%s is not a valid bsq address", address)); + throw new IllegalArgumentException(format("%s is not a valid bsq address", address)); } } @@ -552,7 +556,7 @@ private void verifyWalletCurrencyCodeIsValid(String currencyCode) { if (!currencyCode.equalsIgnoreCase("BSQ") && !currencyCode.equalsIgnoreCase("BTC")) - throw new IllegalStateException(format("wallet does not support %s", currencyCode)); + throw new UnsupportedOperationException(format("wallet does not support %s", currencyCode)); } private void maybeSetWalletsManagerKey() { @@ -593,15 +597,15 @@ private BtcBalanceInfo getBtcBalances() { var availableBalance = balances.getAvailableBalance().get(); if (availableBalance == null) - throw new IllegalStateException("balance is not yet available"); + throw new NotAvailableException("balance is not yet available"); var reservedBalance = balances.getReservedBalance().get(); if (reservedBalance == null) - throw new IllegalStateException("reserved balance is not yet available"); + throw new NotAvailableException("reserved balance is not yet available"); var lockedBalance = balances.getLockedBalance().get(); if (lockedBalance == null) - throw new IllegalStateException("locked balance is not yet available"); + throw new NotAvailableException("locked balance is not yet available"); return new BtcBalanceInfo(availableBalance.value, reservedBalance.value, @@ -613,7 +617,7 @@ private BtcBalanceInfo getBtcBalances() { private Coin getValidTransferAmount(String amount, CoinFormatter coinFormatter) { Coin amountAsCoin = parseToCoin(amount, coinFormatter); if (amountAsCoin.isLessThan(getMinNonDustOutput())) - throw new IllegalStateException(format("%s is an invalid transfer amount", amount)); + throw new IllegalArgumentException(format("%s is an invalid transfer amount", amount)); return amountAsCoin; } @@ -639,7 +643,7 @@ private AddressEntry getAddressEntry(String addressString) { .findFirst(); if (!addressEntry.isPresent()) - throw new IllegalStateException(format("address %s not found in wallet", addressString)); + throw new NotFoundException(format("address %s not found in wallet", addressString)); return addressEntry.get(); } @@ -651,13 +655,13 @@ private Transaction getTransactionWithId(String txId) { try { Transaction tx = btcWalletService.getTransaction(txId); if (tx == null) - throw new IllegalArgumentException(format("tx with id %s not found", txId)); + throw new NotFoundException(format("tx with id %s not found", txId)); else return tx; } catch (IllegalArgumentException ex) { - log.error("", ex); - throw new IllegalArgumentException( + log.error(ex.toString()); + throw new IllegalStateException( format("could not get transaction with id %s%ncause: %s", txId, ex.getMessage().toLowerCase())); diff --git a/core/src/main/java/bisq/core/api/EditOfferValidator.java b/core/src/main/java/bisq/core/api/EditOfferValidator.java index e6123e14bd8..e54398cd8c0 100644 --- a/core/src/main/java/bisq/core/api/EditOfferValidator.java +++ b/core/src/main/java/bisq/core/api/EditOfferValidator.java @@ -205,7 +205,8 @@ private void validateEditedTriggerPrice() { private void checkNotBsqOffer() { if ("BSQ".equals(currentlyOpenOffer.getOffer().getCurrencyCode())) { - throw new IllegalStateException( + // An illegal argument is a user error. + throw new IllegalArgumentException( format("cannot set mkt price margin or trigger price on fixed price bsq offer with id '%s'", currentlyOpenOffer.getId())); } @@ -213,8 +214,10 @@ private void checkNotBsqOffer() { private void checkNotBsqSwapOffer() { if (currentlyOpenOffer.getOffer().isBsqSwapOffer()) { - throw new IllegalStateException( - format("cannot edit bsq swap offer with id '%s'", currentlyOpenOffer.getId())); + // An illegal argument is a user error. + throw new IllegalArgumentException( + format("cannot edit bsq swap offer with id '%s', replace it with a new swap offer instead", + currentlyOpenOffer.getId())); } } } diff --git a/core/src/main/java/bisq/core/api/exception/AlreadyExistsException.java b/core/src/main/java/bisq/core/api/exception/AlreadyExistsException.java new file mode 100644 index 00000000000..c445717f796 --- /dev/null +++ b/core/src/main/java/bisq/core/api/exception/AlreadyExistsException.java @@ -0,0 +1,31 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.api.exception; + +import bisq.common.BisqException; + +/** + * To be thrown in cases when some value or state already exists, e.g., trying to lock + * an encrypted wallet that is already locked. + */ +public class AlreadyExistsException extends BisqException { + + public AlreadyExistsException(String format, Object... args) { + super(format, args); + } +} diff --git a/core/src/main/java/bisq/core/api/exception/FailedPreconditionException.java b/core/src/main/java/bisq/core/api/exception/FailedPreconditionException.java new file mode 100644 index 00000000000..e17b307a32d --- /dev/null +++ b/core/src/main/java/bisq/core/api/exception/FailedPreconditionException.java @@ -0,0 +1,32 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.api.exception; + +import bisq.common.BisqException; + +/** + * To be thrown in cases when client is attempting to change some state requiring a + * pre-conditional state to exist, e.g., when attempting to lock or unlock a wallet that + * is not encrypted. + */ +public class FailedPreconditionException extends BisqException { + + public FailedPreconditionException(String format, Object... args) { + super(format, args); + } +} diff --git a/core/src/main/java/bisq/core/api/exception/NotAvailableException.java b/core/src/main/java/bisq/core/api/exception/NotAvailableException.java new file mode 100644 index 00000000000..1ff6a357d26 --- /dev/null +++ b/core/src/main/java/bisq/core/api/exception/NotAvailableException.java @@ -0,0 +1,31 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.api.exception; + +import bisq.common.BisqException; + +/** + * To be thrown in cases where some service or value, e.g., + * a wallet balance, or sufficient funds are unavailable. + */ +public class NotAvailableException extends BisqException { + + public NotAvailableException(String format, Object... args) { + super(format, args); + } +} diff --git a/core/src/main/java/bisq/core/api/exception/NotFoundException.java b/core/src/main/java/bisq/core/api/exception/NotFoundException.java new file mode 100644 index 00000000000..cbfb0d43590 --- /dev/null +++ b/core/src/main/java/bisq/core/api/exception/NotFoundException.java @@ -0,0 +1,33 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.core.api.exception; + +import bisq.common.BisqException; + +/** + * To be thrown when a file or entity such as an Offer, PaymentAccount, or Trade + * is not found by RPC methods such as GetOffer(id), PaymentAccount(id), or GetTrade(id). + * + * May also be used if a resource such as a File is not found. + */ +public class NotFoundException extends BisqException { + + public NotFoundException(String format, Object... args) { + super(format, args); + } +} diff --git a/core/src/main/java/bisq/core/api/exception/package-info.java b/core/src/main/java/bisq/core/api/exception/package-info.java new file mode 100644 index 00000000000..e045f86c129 --- /dev/null +++ b/core/src/main/java/bisq/core/api/exception/package-info.java @@ -0,0 +1,29 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +/** + * This package contains exceptions thrown only from services in the bisq.core.api + * package. They are needed by the gRPC daemon service classes in the + * bisq.daemon.grpc package, for the purpose of mapping these custom exceptions to + * meaningful io.grpc.Status.Code values sent to gRPC clients. + * + * If / when a Bisq webapp module is created on top of the core API, these exceptions + * will serve the same purpose, to be mapped to meaningful HTTP status codes sent to + * REST clients. + */ + +package bisq.core.api.exception; diff --git a/core/src/main/java/bisq/core/api/model/CanceledTradeInfo.java b/core/src/main/java/bisq/core/api/model/CanceledTradeInfo.java index d1bb85ff80d..14bffe34c12 100644 --- a/core/src/main/java/bisq/core/api/model/CanceledTradeInfo.java +++ b/core/src/main/java/bisq/core/api/model/CanceledTradeInfo.java @@ -22,7 +22,7 @@ import bisq.core.offer.OpenOffer; import static bisq.core.api.model.ContractInfo.emptyContract; -import static bisq.core.api.model.OfferInfo.toMyOfferInfo; +import static bisq.core.api.model.OfferInfo.toMyInactiveOfferInfo; import static bisq.core.offer.OpenOffer.State.CANCELED; import static java.lang.String.format; import static org.apache.commons.lang3.StringUtils.capitalize; @@ -37,7 +37,7 @@ public static TradeInfo toCanceledTradeInfo(OpenOffer myCanceledOpenOffer) { throw new IllegalArgumentException(format("offer '%s' is not canceled", myCanceledOpenOffer.getId())); Offer offer = myCanceledOpenOffer.getOffer(); - OfferInfo offerInfo = toMyOfferInfo(offer); + OfferInfo offerInfo = toMyInactiveOfferInfo(offer); return new TradeInfoV1Builder() .withOffer(offerInfo) diff --git a/core/src/main/java/bisq/core/api/model/OfferInfo.java b/core/src/main/java/bisq/core/api/model/OfferInfo.java index de155b86291..444d0fe1aa1 100644 --- a/core/src/main/java/bisq/core/api/model/OfferInfo.java +++ b/core/src/main/java/bisq/core/api/model/OfferInfo.java @@ -113,14 +113,18 @@ public OfferInfo(OfferInfoBuilder builder) { this.protocolVersion = builder.getProtocolVersion(); } - public static OfferInfo toMyOfferInfo(Offer offer) { - return getBuilder(offer, true).build(); + public static OfferInfo toMyInactiveOfferInfo(Offer offer) { + return getBuilder(offer, true) + .withIsActivated(false) + .build(); } public static OfferInfo toOfferInfo(Offer offer) { // Assume the offer is not mine, but isMyOffer can be reset to true, i.e., when // calling TradeInfo toTradeInfo(Trade trade, String role, boolean isMyOffer); - return getBuilder(offer, false).build(); + return getBuilder(offer, false) + .withIsActivated(true) + .build(); } public static OfferInfo toMyPendingOfferInfo(Offer myNewOffer) { @@ -130,21 +134,24 @@ public static OfferInfo toMyPendingOfferInfo(Offer myNewOffer) { // column that will show a PENDING value when this.isMyPendingOffer = true. return getBuilder(myNewOffer, true) .withIsMyPendingOffer(true) + .withIsActivated(false) .build(); } public static OfferInfo toMyOfferInfo(OpenOffer openOffer) { // An OpenOffer is always my offer. - var currencyCode = openOffer.getOffer().getCurrencyCode(); - Optional optionalTriggerPrice = openOffer.getTriggerPrice() > 0 + var offer = openOffer.getOffer(); + var currencyCode = offer.getCurrencyCode(); + var isActivated = !openOffer.isDeactivated(); + Optional optionalTriggerPrice = (!offer.isBsqSwapOffer() && openOffer.getTriggerPrice() > 0) ? Optional.of(Price.valueOf(currencyCode, openOffer.getTriggerPrice())) : Optional.empty(); var preciseTriggerPrice = optionalTriggerPrice .map(value -> reformatMarketPrice(value.toPlainString(), currencyCode)) .orElse("0"); - return getBuilder(openOffer.getOffer(), true) + return getBuilder(offer, true) .withTriggerPrice(preciseTriggerPrice) - .withIsActivated(!openOffer.isDeactivated()) + .withIsActivated(isActivated) .build(); } diff --git a/core/src/main/java/bisq/core/api/model/TradeInfo.java b/core/src/main/java/bisq/core/api/model/TradeInfo.java index f150bcaac2c..cf65cf77999 100644 --- a/core/src/main/java/bisq/core/api/model/TradeInfo.java +++ b/core/src/main/java/bisq/core/api/model/TradeInfo.java @@ -32,7 +32,7 @@ import lombok.Getter; import static bisq.core.api.model.BsqSwapTradeInfo.toBsqSwapTradeInfo; -import static bisq.core.api.model.OfferInfo.toMyOfferInfo; +import static bisq.core.api.model.OfferInfo.toMyInactiveOfferInfo; import static bisq.core.api.model.OfferInfo.toOfferInfo; import static bisq.core.api.model.PaymentAccountPayloadInfo.toPaymentAccountPayloadInfo; import static bisq.core.offer.OfferDirection.BUY; @@ -50,7 +50,7 @@ public class TradeInfo implements Payload { // view and interact with trades. private static final BiFunction toOfferInfo = (tradeModel, isMyOffer) -> - isMyOffer ? toMyOfferInfo(tradeModel.getOffer()) : toOfferInfo(tradeModel.getOffer()); + isMyOffer ? toMyInactiveOfferInfo(tradeModel.getOffer()) : toOfferInfo(tradeModel.getOffer()); private static final Function toPeerNodeAddress = (tradeModel) -> tradeModel.getTradingPeerNodeAddress() == null diff --git a/core/src/main/java/bisq/core/locale/CurrencyUtil.java b/core/src/main/java/bisq/core/locale/CurrencyUtil.java index 7a572fc79f8..47b7afaa1fb 100644 --- a/core/src/main/java/bisq/core/locale/CurrencyUtil.java +++ b/core/src/main/java/bisq/core/locale/CurrencyUtil.java @@ -793,4 +793,17 @@ public static String getPriceWithCurrencyCode(String currencyCode, String transl public static String getOfferVolumeCode(String currencyCode) { 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("BSQ") + || currencyCode.equals("XMR"); + else + throw new IllegalArgumentException( + format("Method requires a crypto currency code, but was given '%s'.", + currencyCode)); + } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcExceptionHandler.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcExceptionHandler.java index bfa950978fb..4dbecf7ec95 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcExceptionHandler.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcExceptionHandler.java @@ -17,6 +17,11 @@ package bisq.daemon.grpc; +import bisq.core.api.exception.AlreadyExistsException; +import bisq.core.api.exception.FailedPreconditionException; +import bisq.core.api.exception.NotAvailableException; +import bisq.core.api.exception.NotFoundException; + import io.grpc.Status; import io.grpc.StatusRuntimeException; import io.grpc.stub.StreamObserver; @@ -29,8 +34,7 @@ import org.slf4j.Logger; -import static io.grpc.Status.INVALID_ARGUMENT; -import static io.grpc.Status.UNKNOWN; +import static io.grpc.Status.*; /** * The singleton instance of this class handles any expected core api Throwable by @@ -40,9 +44,26 @@ @Singleton class GrpcExceptionHandler { + private static final String CORE_API_EXCEPTION_PKG_NAME = NotFoundException.class.getPackage().getName(); + + /** + * Returns true if Throwable is a custom core api exception instance, + * or one of the following native Java exception instances: + *

+ *

+     * IllegalArgumentException
+     * IllegalStateException
+     * UnsupportedOperationException
+     * 
+ *

+ */ private final Predicate isExpectedException = (t) -> - t instanceof IllegalStateException || t instanceof IllegalArgumentException; + t.getClass().getPackage().getName().equals(CORE_API_EXCEPTION_PKG_NAME) + || t instanceof IllegalArgumentException + || t instanceof IllegalStateException + || t instanceof UnsupportedOperationException; + @SuppressWarnings("unused") @Inject public GrpcExceptionHandler() { } @@ -107,18 +128,27 @@ private StatusRuntimeException wrapException(Throwable t) { }; private Status mapGrpcErrorStatus(Throwable t, String description) { - // We default to the UNKNOWN status, except were the mapping of a core api - // exception to a gRPC Status is obvious. If we ever use a gRPC reverse-proxy - // to support RESTful clients, we will need to have more specific mappings - // to support correct HTTP 1.1. status codes. - //noinspection SwitchStatementWithTooFewBranches - switch (t.getClass().getSimpleName()) { - // We go ahead and use a switch statement instead of if, in anticipation - // of more, specific exception mappings. - case "IllegalArgumentException": - return INVALID_ARGUMENT.withDescription(description); - default: - return UNKNOWN.withDescription(description); - } + // Check if a custom core.api.exception was thrown, so we can map it to a more + // meaningful io.grpc.Status, something more useful to gRPC clients than UNKNOWN. + if (t instanceof AlreadyExistsException) + return ALREADY_EXISTS.withDescription(description); + else if (t instanceof FailedPreconditionException) + return FAILED_PRECONDITION.withDescription(description); + else if (t instanceof NotFoundException) + return NOT_FOUND.withDescription(description); + else if (t instanceof NotAvailableException) + return UNAVAILABLE.withDescription(description); + + // If the above checks did not return an io.grpc.Status.Code, we map + // the native Java exception to an io.grpc.Status. + if (t instanceof IllegalArgumentException) + return INVALID_ARGUMENT.withDescription(description); + else if (t instanceof IllegalStateException) + return UNKNOWN.withDescription(description); + else if (t instanceof UnsupportedOperationException) + return UNIMPLEMENTED.withDescription(description); + else + return UNKNOWN.withDescription(description); } } + diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java index 18bb17bf048..cfb6cc34973 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java @@ -125,8 +125,10 @@ public void getOffer(GetOfferRequest req, try { String offerId = req.getId(); Optional myOpenOffer = coreApi.findMyOpenOffer(offerId); + Offer offer = myOpenOffer.map(OpenOffer::getOffer) + .orElseGet(() -> coreApi.getOffer(offerId)); OfferInfo offerInfo = myOpenOffer.map(OfferInfo::toMyOfferInfo) - .orElseGet(() -> toOfferInfo(coreApi.getOffer(offerId))); + .orElseGet(() -> toOfferInfo(offer)); var reply = GetOfferReply.newBuilder() .setOffer(offerInfo.toProtoMessage()) .build(); @@ -174,7 +176,8 @@ public void getBsqSwapOffers(GetBsqSwapOffersRequest req, StreamObserver responseObserver) { try { List result = coreApi.getBsqSwapOffers(req.getDirection()) - .stream().map(OfferInfo::toOfferInfo) + .stream() + .map(OfferInfo::toOfferInfo) .collect(Collectors.toList()); var reply = GetBsqSwapOffersReply.newBuilder() .addAllBsqSwapOffers(result.stream() @@ -193,7 +196,8 @@ public void getOffers(GetOffersRequest req, StreamObserver responseObserver) { try { List result = coreApi.getOffers(req.getDirection(), req.getCurrencyCode()) - .stream().map(OfferInfo::toOfferInfo) + .stream() + .map(OfferInfo::toOfferInfo) .collect(Collectors.toList()); var reply = GetOffersReply.newBuilder() .addAllOffers(result.stream() @@ -212,7 +216,9 @@ public void getMyBsqSwapOffers(GetBsqSwapOffersRequest req, StreamObserver responseObserver) { try { List result = coreApi.getMyBsqSwapOffers(req.getDirection()) - .stream().map(OfferInfo::toOfferInfo) + .stream() + .map(o -> coreApi.getMyOpenBsqSwapOffer(o.getId())) + .map(OfferInfo::toMyOfferInfo) .collect(Collectors.toList()); var reply = GetMyBsqSwapOffersReply.newBuilder() .addAllBsqSwapOffers(result.stream() diff --git a/daemon/src/main/java/bisq/daemon/grpc/interceptor/GrpcServiceRateMeteringConfig.java b/daemon/src/main/java/bisq/daemon/grpc/interceptor/GrpcServiceRateMeteringConfig.java index b01ac176552..633399611b2 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/interceptor/GrpcServiceRateMeteringConfig.java +++ b/daemon/src/main/java/bisq/daemon/grpc/interceptor/GrpcServiceRateMeteringConfig.java @@ -243,9 +243,9 @@ public void addCallRateMeter(String grpcServiceClassName, timeUnit.toMillis(1) * numTimeUnits); rateMeterConfigs.stream().filter(c -> c.isConfigForGrpcService(grpcServiceClassName)) .findFirst().ifPresentOrElse( - (config) -> config.addMethodCallRateMeter(methodName, maxCalls, timeUnit, numTimeUnits), - () -> rateMeterConfigs.add(new GrpcServiceRateMeteringConfig(grpcServiceClassName) - .addMethodCallRateMeter(methodName, maxCalls, timeUnit, numTimeUnits))); + (config) -> config.addMethodCallRateMeter(methodName, maxCalls, timeUnit, numTimeUnits), + () -> rateMeterConfigs.add(new GrpcServiceRateMeteringConfig(grpcServiceClassName) + .addMethodCallRateMeter(methodName, maxCalls, timeUnit, numTimeUnits))); } public File build() {