fix fee calculation taking offer within range

This commit is contained in:
woodser 2023-05-30 12:42:50 -04:00
parent 0251b49d61
commit b90163baa5
10 changed files with 32 additions and 15 deletions

View file

@ -512,10 +512,11 @@ public class CoreApi {
public void takeOffer(String offerId,
String paymentAccountId,
long amountAsLong,
Consumer<Trade> 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,

View file

@ -89,6 +89,7 @@ class CoreTradesService {
void takeOffer(Offer offer,
String paymentAccountId,
long amountAsLong,
Consumer<Trade> 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,

View file

@ -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;
}

View file

@ -69,9 +69,9 @@ public class SendOfferAvailabilityRequest extends Task<OfferAvailabilityModel> {
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,

View file

@ -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();

View file

@ -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);
}

View file

@ -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(),

View file

@ -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()

View file

@ -156,6 +156,7 @@ class TakeOfferDataModel extends OfferDataModel {
tradeManager.checkOfferAvailability(offer,
false,
paymentAccount.getId(),
this.amount.get(),
() -> {
},
errorMessage -> new Popup().warning(errorMessage).show());

View file

@ -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 {