From b90163baa5991be6afbe440afa32499632ba4050 Mon Sep 17 00:00:00 2001 From: woodser Date: Tue, 30 May 2023 12:42:50 -0400 Subject: [PATCH] fix fee calculation taking offer within range --- .../src/main/java/haveno/core/api/CoreApi.java | 3 ++- .../haveno/core/api/CoreTradesService.java | 8 ++++++-- .../availability/OfferAvailabilityModel.java | 6 ++++++ .../tasks/SendOfferAvailabilityRequest.java | 4 ++-- .../core/offer/takeoffer/TakeOfferModel.java | 3 ++- .../java/haveno/core/trade/TradeManager.java | 18 ++++++++++-------- .../tasks/MakerSendInitTradeRequest.java | 2 +- .../haveno/daemon/grpc/GrpcTradesService.java | 1 + .../offer/takeoffer/TakeOfferDataModel.java | 1 + proto/src/main/proto/grpc.proto | 1 + 10 files changed, 32 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/haveno/core/api/CoreApi.java b/core/src/main/java/haveno/core/api/CoreApi.java index 052e54747c..1662e3fca4 100644 --- a/core/src/main/java/haveno/core/api/CoreApi.java +++ b/core/src/main/java/haveno/core/api/CoreApi.java @@ -512,10 +512,11 @@ public class CoreApi { public void takeOffer(String offerId, String paymentAccountId, + long amountAsLong, Consumer resultHandler, ErrorMessageHandler errorMessageHandler) { Offer offer = coreOffersService.getOffer(offerId); - coreTradesService.takeOffer(offer, paymentAccountId, resultHandler, errorMessageHandler); + coreTradesService.takeOffer(offer, paymentAccountId, amountAsLong, resultHandler, errorMessageHandler); } public void confirmPaymentSent(String tradeId, diff --git a/core/src/main/java/haveno/core/api/CoreTradesService.java b/core/src/main/java/haveno/core/api/CoreTradesService.java index d533c2bec0..db9f066641 100644 --- a/core/src/main/java/haveno/core/api/CoreTradesService.java +++ b/core/src/main/java/haveno/core/api/CoreTradesService.java @@ -89,6 +89,7 @@ class CoreTradesService { void takeOffer(Offer offer, String paymentAccountId, + long amountAsLong, Consumer resultHandler, ErrorMessageHandler errorMessageHandler) { try { @@ -101,18 +102,21 @@ class CoreTradesService { var useSavingsWallet = true; + // default to offer amount + BigInteger amount = amountAsLong == 0 ? offer.getAmount() : BigInteger.valueOf(amountAsLong); + // synchronize access to take offer model // TODO (woodser): to avoid synchronizing, don't use stateful model BigInteger takerFee; BigInteger fundsNeededForTrade; synchronized (takeOfferModel) { - takeOfferModel.initModel(offer, paymentAccount, useSavingsWallet); + takeOfferModel.initModel(offer, paymentAccount, amount, useSavingsWallet); takerFee = takeOfferModel.getTakerFee(); fundsNeededForTrade = takeOfferModel.getFundsNeededForTrade(); log.info("Initiating take {} offer, {}", offer.isBuyOffer() ? "buy" : "sell", takeOfferModel); } // take offer - tradeManager.onTakeOffer(offer.getAmount(), + tradeManager.onTakeOffer(amount, takerFee, fundsNeededForTrade, offer, diff --git a/core/src/main/java/haveno/core/offer/availability/OfferAvailabilityModel.java b/core/src/main/java/haveno/core/offer/availability/OfferAvailabilityModel.java index 7b98e39d62..c4fa1caecf 100644 --- a/core/src/main/java/haveno/core/offer/availability/OfferAvailabilityModel.java +++ b/core/src/main/java/haveno/core/offer/availability/OfferAvailabilityModel.java @@ -32,6 +32,8 @@ import haveno.network.p2p.P2PService; import lombok.Getter; import lombok.Setter; +import java.math.BigInteger; + import javax.annotation.Nullable; public class OfferAvailabilityModel implements Model { @@ -54,6 +56,8 @@ public class OfferAvailabilityModel implements Model { @Getter private String paymentAccountId; @Getter + private BigInteger tradeAmount; + @Getter private OfferUtil offerUtil; @Getter @Setter @@ -76,6 +80,7 @@ public class OfferAvailabilityModel implements Model { TradeStatisticsManager tradeStatisticsManager, boolean isTakerApiUser, String paymentAccountId, + BigInteger tradeAmount, OfferUtil offerUtil) { this.offer = offer; this.pubKeyRing = pubKeyRing; @@ -86,6 +91,7 @@ public class OfferAvailabilityModel implements Model { this.tradeStatisticsManager = tradeStatisticsManager; this.isTakerApiUser = isTakerApiUser; this.paymentAccountId = paymentAccountId; + this.tradeAmount = tradeAmount; this.offerUtil = offerUtil; } diff --git a/core/src/main/java/haveno/core/offer/availability/tasks/SendOfferAvailabilityRequest.java b/core/src/main/java/haveno/core/offer/availability/tasks/SendOfferAvailabilityRequest.java index 38a1b9e6dc..9429649d97 100644 --- a/core/src/main/java/haveno/core/offer/availability/tasks/SendOfferAvailabilityRequest.java +++ b/core/src/main/java/haveno/core/offer/availability/tasks/SendOfferAvailabilityRequest.java @@ -69,9 +69,9 @@ public class SendOfferAvailabilityRequest extends Task { offer.getId(), P2PService.getMyNodeAddress(), p2PService.getKeyRing().getPubKeyRing(), - offer.getAmount().longValueExact(), + model.getTradeAmount().longValueExact(), price.getValue(), - HavenoUtils.getTakerFee(offer.getAmount()).longValueExact(), + HavenoUtils.getTakerFee(model.getTradeAmount()).longValueExact(), user.getAccountId(), paymentAccountId, paymentMethodId, diff --git a/core/src/main/java/haveno/core/offer/takeoffer/TakeOfferModel.java b/core/src/main/java/haveno/core/offer/takeoffer/TakeOfferModel.java index c4065f6507..15f8b11e21 100644 --- a/core/src/main/java/haveno/core/offer/takeoffer/TakeOfferModel.java +++ b/core/src/main/java/haveno/core/offer/takeoffer/TakeOfferModel.java @@ -92,6 +92,7 @@ public class TakeOfferModel implements Model { public void initModel(Offer offer, PaymentAccount paymentAccount, + BigInteger tradeAmount, boolean useSavingsWallet) { this.clearModel(); this.offer = offer; @@ -100,7 +101,7 @@ public class TakeOfferModel implements Model { validateModelInputs(); this.useSavingsWallet = useSavingsWallet; - this.amount = offer.getAmount().min(BigInteger.valueOf(getMaxTradeLimit())); + this.amount = tradeAmount.min(BigInteger.valueOf(getMaxTradeLimit())); this.securityDeposit = offer.getDirection() == SELL ? offer.getBuyerSecurityDeposit() : offer.getSellerSecurityDeposit(); diff --git a/core/src/main/java/haveno/core/trade/TradeManager.java b/core/src/main/java/haveno/core/trade/TradeManager.java index 44651244a3..2c029c1747 100644 --- a/core/src/main/java/haveno/core/trade/TradeManager.java +++ b/core/src/main/java/haveno/core/trade/TradeManager.java @@ -561,11 +561,11 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi } // get expected taker fee - BigInteger takerFee = HavenoUtils.getTakerFee(BigInteger.valueOf(offer.getOfferPayload().getAmount())); + BigInteger takerFee = HavenoUtils.getTakerFee(BigInteger.valueOf(request.getTradeAmount())); // create arbitrator trade trade = new ArbitratorTrade(offer, - BigInteger.valueOf(offer.getOfferPayload().getAmount()), + BigInteger.valueOf(request.getTradeAmount()), takerFee, offer.getOfferPayload().getPrice(), xmrWalletService, @@ -630,12 +630,12 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi openOfferManager.reserveOpenOffer(openOffer); // get expected taker fee - BigInteger takerFee = HavenoUtils.getTakerFee(BigInteger.valueOf(offer.getOfferPayload().getAmount())); + BigInteger takerFee = HavenoUtils.getTakerFee(BigInteger.valueOf(request.getTradeAmount())); Trade trade; if (offer.isBuyOffer()) trade = new BuyerAsMakerTrade(offer, - BigInteger.valueOf(offer.getOfferPayload().getAmount()), + BigInteger.valueOf(request.getTradeAmount()), takerFee, offer.getOfferPayload().getPrice(), xmrWalletService, @@ -646,7 +646,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi request.getArbitratorNodeAddress()); else trade = new SellerAsMakerTrade(offer, - BigInteger.valueOf(offer.getOfferPayload().getAmount()), + BigInteger.valueOf(request.getTradeAmount()), takerFee, offer.getOfferPayload().getPrice(), xmrWalletService, @@ -788,9 +788,10 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi public void checkOfferAvailability(Offer offer, boolean isTakerApiUser, String paymentAccountId, + BigInteger tradeAmount, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { - offer.checkOfferAvailability(getOfferAvailabilityModel(offer, isTakerApiUser, paymentAccountId), resultHandler, errorMessageHandler); + offer.checkOfferAvailability(getOfferAvailabilityModel(offer, isTakerApiUser, paymentAccountId, tradeAmount), resultHandler, errorMessageHandler); } // First we check if offer is still available then we create the trade with the protocol @@ -806,7 +807,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi checkArgument(!wasOfferAlreadyUsedInTrade(offer.getId())); - OfferAvailabilityModel model = getOfferAvailabilityModel(offer, isTakerApiUser, paymentAccountId); + OfferAvailabilityModel model = getOfferAvailabilityModel(offer, isTakerApiUser, paymentAccountId, amount); offer.checkOfferAvailability(model, () -> { if (offer.getState() == Offer.State.AVAILABLE) { @@ -886,7 +887,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi processModelServiceProvider.getKeyRing().getPubKeyRing()); } - private OfferAvailabilityModel getOfferAvailabilityModel(Offer offer, boolean isTakerApiUser, String paymentAccountId) { + private OfferAvailabilityModel getOfferAvailabilityModel(Offer offer, boolean isTakerApiUser, String paymentAccountId, BigInteger tradeAmount) { return new OfferAvailabilityModel( offer, keyRing.getPubKeyRing(), @@ -897,6 +898,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi tradeStatisticsManager, isTakerApiUser, paymentAccountId, + tradeAmount, offerUtil); } diff --git a/core/src/main/java/haveno/core/trade/protocol/tasks/MakerSendInitTradeRequest.java b/core/src/main/java/haveno/core/trade/protocol/tasks/MakerSendInitTradeRequest.java index 05e65cfaeb..e29c204a10 100644 --- a/core/src/main/java/haveno/core/trade/protocol/tasks/MakerSendInitTradeRequest.java +++ b/core/src/main/java/haveno/core/trade/protocol/tasks/MakerSendInitTradeRequest.java @@ -54,7 +54,7 @@ public class MakerSendInitTradeRequest extends TradeTask { offer.getId(), processModel.getMyNodeAddress(), processModel.getPubKeyRing(), - offer.getAmount().longValueExact(), + trade.getAmount().longValueExact(), trade.getPrice().getValue(), offer.getMakerFee().longValueExact(), trade.getProcessModel().getAccountId(), diff --git a/daemon/src/main/java/haveno/daemon/grpc/GrpcTradesService.java b/daemon/src/main/java/haveno/daemon/grpc/GrpcTradesService.java index 5b83e5c04d..7e8c1e4198 100644 --- a/daemon/src/main/java/haveno/daemon/grpc/GrpcTradesService.java +++ b/daemon/src/main/java/haveno/daemon/grpc/GrpcTradesService.java @@ -122,6 +122,7 @@ class GrpcTradesService extends TradesImplBase { try { coreApi.takeOffer(req.getOfferId(), req.getPaymentAccountId(), + req.getAmount(), trade -> { TradeInfo tradeInfo = toTradeInfo(trade); var reply = TakeOfferReply.newBuilder() diff --git a/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferDataModel.java b/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferDataModel.java index 3971bd8332..30fa04b6cc 100644 --- a/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferDataModel.java +++ b/desktop/src/main/java/haveno/desktop/main/offer/takeoffer/TakeOfferDataModel.java @@ -156,6 +156,7 @@ class TakeOfferDataModel extends OfferDataModel { tradeManager.checkOfferAvailability(offer, false, paymentAccount.getId(), + this.amount.get(), () -> { }, errorMessage -> new Popup().warning(errorMessage).show()); diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index ff42b98ba7..801798763e 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -746,6 +746,7 @@ service Trades { message TakeOfferRequest { string offer_id = 1; string payment_account_id = 2; + uint64 amount = 3 [jstype = JS_STRING]; } message TakeOfferReply {