diff --git a/core/src/main/java/bisq/core/api/CoreApi.java b/core/src/main/java/bisq/core/api/CoreApi.java index 58d4ac87f7..e8e6e4832f 100644 --- a/core/src/main/java/bisq/core/api/CoreApi.java +++ b/core/src/main/java/bisq/core/api/CoreApi.java @@ -293,10 +293,12 @@ public class CoreApi { /////////////////////////////////////////////////////////////////////////////////////////// public void takeBsqSwapOffer(String offerId, + long intendedTradeAmount, TradeResultHandler tradeResultHandler, ErrorMessageHandler errorMessageHandler) { Offer bsqSwapOffer = coreOffersService.getBsqSwapOffer(offerId); coreTradesService.takeBsqSwapOffer(bsqSwapOffer, + intendedTradeAmount, tradeResultHandler, errorMessageHandler); } @@ -304,12 +306,14 @@ public class CoreApi { public void takeOffer(String offerId, String paymentAccountId, String takerFeeCurrencyCode, + long intendedTradeAmount, Consumer resultHandler, ErrorMessageHandler errorMessageHandler) { Offer offer = coreOffersService.getOffer(offerId); coreTradesService.takeOffer(offer, paymentAccountId, takerFeeCurrencyCode, + intendedTradeAmount, resultHandler, errorMessageHandler); } diff --git a/core/src/main/java/bisq/core/api/CoreTradesService.java b/core/src/main/java/bisq/core/api/CoreTradesService.java index 7c47207454..17f1080356 100644 --- a/core/src/main/java/bisq/core/api/CoreTradesService.java +++ b/core/src/main/java/bisq/core/api/CoreTradesService.java @@ -114,15 +114,17 @@ class CoreTradesService { this.user = user; } - // TODO We need to pass the intended trade amount, not default to the maximum. void takeBsqSwapOffer(Offer offer, + long intendedTradeAmount, TradeResultHandler tradeResultHandler, ErrorMessageHandler errorMessageHandler) { coreWalletsService.verifyWalletsAreAvailable(); coreWalletsService.verifyEncryptedWalletIsUnlocked(); + verifyIntendedTradeAmountIsInRange(intendedTradeAmount, offer); + bsqSwapTakeOfferModel.initWithData(offer); - bsqSwapTakeOfferModel.applyAmount(offer.getAmount()); + bsqSwapTakeOfferModel.applyAmount(Coin.valueOf(intendedTradeAmount)); // Block attempt to take swap offer if there are insufficient funds for the trade. var missingCoin = bsqSwapTakeOfferModel.getMissingFundsAsCoin(); @@ -139,10 +141,10 @@ class CoreTradesService { coreContext.isApiUser()); } - // TODO We need to pass the intended trade amount, not default to the maximum. void takeOffer(Offer offer, String paymentAccountId, String takerFeeCurrencyCode, + long intendedTradeAmount, Consumer resultHandler, ErrorMessageHandler errorMessageHandler) { coreWalletsService.verifyWalletsAreAvailable(); @@ -154,9 +156,11 @@ class CoreTradesService { if (paymentAccount == null) throw new IllegalArgumentException(format("payment account with id '%s' not found", paymentAccountId)); + verifyIntendedTradeAmountIsInRange(intendedTradeAmount, offer); + var useSavingsWallet = true; - takeOfferModel.initModel(offer, paymentAccount, useSavingsWallet); + takeOfferModel.initModel(offer, paymentAccount, intendedTradeAmount, useSavingsWallet); log.info("Initiating take {} offer, {}", offer.isBuyOffer() ? "buy" : "sell", takeOfferModel); @@ -167,7 +171,7 @@ class CoreTradesService { format("wallet has insufficient btc to take offer with id '%s'", offer.getId())); //noinspection ConstantConditions - tradeManager.onTakeOffer(offer.getAmount(), + tradeManager.onTakeOffer(Coin.valueOf(intendedTradeAmount), takeOfferModel.getTxFeeFromFeeService(), takeOfferModel.getTakerFee(), takeOfferModel.isCurrencyForTakerFeeBtc(), @@ -457,4 +461,14 @@ class CoreTradesService { String.join(", ", tradeIds))); }); } + + // Throws a RuntimeException if the takeoffer's amount parameter is out of range. + void verifyIntendedTradeAmountIsInRange(long intendedTradeAmount, Offer offer) { + if (intendedTradeAmount < offer.getMinAmount().value || intendedTradeAmount > offer.getAmount().value) + throw new IllegalArgumentException( + format("intended trade amount %s is outside offer's min - max amount range of %s - %s", + Coin.valueOf(intendedTradeAmount).toPlainString().toLowerCase(), + offer.getMinAmount().toPlainString().toLowerCase(), + offer.getAmount().toPlainString().toLowerCase())); + } } diff --git a/core/src/main/java/bisq/core/offer/bisq_v1/TakeOfferModel.java b/core/src/main/java/bisq/core/offer/bisq_v1/TakeOfferModel.java index c6d69a47a1..3c5b935a53 100644 --- a/core/src/main/java/bisq/core/offer/bisq_v1/TakeOfferModel.java +++ b/core/src/main/java/bisq/core/offer/bisq_v1/TakeOfferModel.java @@ -111,6 +111,7 @@ public class TakeOfferModel implements Model { public void initModel(Offer offer, PaymentAccount paymentAccount, + long intendedTradeAmount, boolean useSavingsWallet) { this.clearModel(); this.offer = offer; @@ -119,12 +120,12 @@ public class TakeOfferModel implements Model { validateModelInputs(); this.useSavingsWallet = useSavingsWallet; - this.amount = valueOf(Math.min(offer.getAmount().value, getMaxTradeLimit())); + this.amount = valueOf(Math.min(intendedTradeAmount, getMaxTradeLimit())); this.securityDeposit = offer.getDirection() == SELL ? offer.getBuyerSecurityDeposit() : offer.getSellerSecurityDeposit(); - this.isCurrencyForTakerFeeBtc = offerUtil.isCurrencyForTakerFeeBtc(amount); - this.takerFee = offerUtil.getTakerFee(isCurrencyForTakerFeeBtc, amount); + this.isCurrencyForTakerFeeBtc = offerUtil.isCurrencyForTakerFeeBtc(this.amount); + this.takerFee = offerUtil.getTakerFee(isCurrencyForTakerFeeBtc, this.amount); calculateTxFees(); calculateVolume(); diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java index 904d406e04..0f8e1c8a49 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java @@ -97,9 +97,13 @@ class GrpcTradesService extends TradesImplBase { try { // Make sure the offer exists before trying to take it. Offer offer = coreApi.getOffer(req.getOfferId()); + var intendedTradeAmount = req.getAmount() == 0 + ? offer.getAmount().value + : req.getAmount(); if (offer.isBsqSwapOffer()) { coreApi.takeBsqSwapOffer(offer.getId(), + intendedTradeAmount, bsqSwapTrade -> { var reply = buildTakeOfferReply(bsqSwapTrade); responseObserver.onNext(reply); @@ -113,6 +117,7 @@ class GrpcTradesService extends TradesImplBase { coreApi.takeOffer(offer.getId(), req.getPaymentAccountId(), req.getTakerFeeCurrencyCode(), + intendedTradeAmount, trade -> { var reply = buildTakeOfferReply(trade); responseObserver.onNext(reply);