mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-22 06:41:41 +01:00
Merge branch 'mrosseel-api-pr1' into Development
This commit is contained in:
commit
92434c4851
5 changed files with 168 additions and 59 deletions
|
@ -97,17 +97,17 @@
|
|||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>2.8.9</version>
|
||||
<version>2.8.10</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>2.8.9</version>
|
||||
<version>2.8.10</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.8.9</version>
|
||||
<version>2.8.10</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
|
|
132
core/src/main/java/io/bisq/core/offer/OfferUtil.java
Normal file
132
core/src/main/java/io/bisq/core/offer/OfferUtil.java
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bisq.core.offer;
|
||||
|
||||
import io.bisq.common.util.MathUtils;
|
||||
import io.bisq.core.app.BisqEnvironment;
|
||||
import io.bisq.core.btc.wallet.BsqWalletService;
|
||||
import io.bisq.core.provider.fee.FeeService;
|
||||
import io.bisq.core.user.Preferences;
|
||||
import io.bisq.core.util.CoinUtil;
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This class holds utility methods for the creation of an Offer.
|
||||
* Most of these are extracted here because they are used both in the GUI and in the API.
|
||||
*
|
||||
* Long-term there could be a GUI-agnostic OfferService which provides these and other functionalities to both the
|
||||
* GUI and the API.
|
||||
*/
|
||||
public class OfferUtil {
|
||||
|
||||
/**
|
||||
* Given the direction, is this a BUY?
|
||||
*
|
||||
* @param direction
|
||||
* @return
|
||||
*/
|
||||
public static boolean isBuyOffer(OfferPayload.Direction direction) {
|
||||
return direction == OfferPayload.Direction.BUY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the makerFee as Coin, this can be priced in BTC or BSQ.
|
||||
*
|
||||
* @param bsqWalletService
|
||||
* @param preferences preferences are used to see if the user indicated a preference for paying fees in BTC
|
||||
* @param amount
|
||||
* @param marketPriceAvailable
|
||||
* @param marketPriceMargin
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
public static Coin getMakerFee(BsqWalletService bsqWalletService, Preferences preferences, Coin amount, boolean marketPriceAvailable, double marketPriceMargin) {
|
||||
final boolean isCurrencyForMakerFeeBtc = isCurrencyForMakerFeeBtc(preferences, bsqWalletService, amount, marketPriceAvailable, marketPriceMargin);
|
||||
return getMakerFee(isCurrencyForMakerFeeBtc,
|
||||
amount,
|
||||
marketPriceAvailable,
|
||||
marketPriceMargin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the maker fee for the given amount, marketPrice and marketPriceMargin.
|
||||
*
|
||||
* @param isCurrencyForMakerFeeBtc
|
||||
* @param amount
|
||||
* @param marketPriceAvailable
|
||||
* @param marketPriceMargin
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
public static Coin getMakerFee(boolean isCurrencyForMakerFeeBtc, @Nullable Coin amount, boolean marketPriceAvailable, double marketPriceMargin) {
|
||||
if (amount != null) {
|
||||
final Coin feePerBtc = CoinUtil.getFeePerBtc(FeeService.getMakerFeePerBtc(isCurrencyForMakerFeeBtc), amount);
|
||||
double makerFeeAsDouble = (double) feePerBtc.value;
|
||||
if (marketPriceAvailable) {
|
||||
if (marketPriceMargin > 0)
|
||||
makerFeeAsDouble = makerFeeAsDouble * Math.sqrt(marketPriceMargin * 100);
|
||||
else
|
||||
makerFeeAsDouble = 0;
|
||||
// For BTC we round so min value change is 100 satoshi
|
||||
if (isCurrencyForMakerFeeBtc)
|
||||
makerFeeAsDouble = MathUtils.roundDouble(makerFeeAsDouble / 100, 0) * 100;
|
||||
}
|
||||
|
||||
return CoinUtil.maxCoin(Coin.valueOf(MathUtils.doubleToLong(makerFeeAsDouble)), FeeService.getMinMakerFee(isCurrencyForMakerFeeBtc));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the maker fee should be paid in BTC, this can be the case due to user preference or because the user
|
||||
* doesn't have enough BSQ.
|
||||
*
|
||||
* @param preferences
|
||||
* @param bsqWalletService
|
||||
* @param amount
|
||||
* @param marketPriceAvailable
|
||||
* @param marketPriceMargin
|
||||
* @return
|
||||
*/
|
||||
public static boolean isCurrencyForMakerFeeBtc(Preferences preferences, BsqWalletService bsqWalletService, Coin amount, boolean marketPriceAvailable, double marketPriceMargin) {
|
||||
return preferences.getPayFeeInBtc() ||
|
||||
!isBsqForFeeAvailable(bsqWalletService, amount, marketPriceAvailable, marketPriceMargin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the available BSQ balance is sufficient to pay for the offer's maker fee.
|
||||
*
|
||||
* @param bsqWalletService
|
||||
* @param amount
|
||||
* @param marketPriceAvailable
|
||||
* @param marketPriceMargin
|
||||
* @return
|
||||
*/
|
||||
public static boolean isBsqForFeeAvailable(BsqWalletService bsqWalletService, @Nullable Coin amount, boolean marketPriceAvailable, double marketPriceMargin) {
|
||||
final Coin makerFee = getMakerFee(false, amount, marketPriceAvailable, marketPriceMargin);
|
||||
final Coin availableBalance = bsqWalletService.getAvailableBalance();
|
||||
return makerFee != null &&
|
||||
BisqEnvironment.isBaseCurrencySupportingBsq() &&
|
||||
availableBalance != null &&
|
||||
!availableBalance.subtract(makerFee).isNegative();
|
||||
}
|
||||
}
|
|
@ -285,7 +285,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
public void placeOffer(Offer offer,
|
||||
Coin reservedFundsForOffer,
|
||||
boolean useSavingsWallet,
|
||||
TransactionResultHandler resultHandler) {
|
||||
TransactionResultHandler resultHandler,
|
||||
ErrorMessageHandler errorMessageHandler) {
|
||||
PlaceOfferModel model = new PlaceOfferModel(offer,
|
||||
reservedFundsForOffer,
|
||||
useSavingsWallet,
|
||||
|
@ -307,6 +308,9 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
} else {
|
||||
log.debug("We have stopped already. We ignore that placeOfferProtocol.placeOffer.onResult call.");
|
||||
}
|
||||
},
|
||||
error -> {
|
||||
errorMessageHandler.handleErrorMessage(error);
|
||||
}
|
||||
);
|
||||
placeOfferProtocol.placeOffer();
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package io.bisq.core.offer.placeoffer;
|
||||
|
||||
import io.bisq.common.handlers.ErrorMessageHandler;
|
||||
import io.bisq.common.taskrunner.TaskRunner;
|
||||
import io.bisq.core.offer.placeoffer.tasks.AddOfferToRemoteOfferBook;
|
||||
import io.bisq.core.offer.placeoffer.tasks.BroadcastMakerFeeTx;
|
||||
|
@ -31,6 +32,7 @@ public class PlaceOfferProtocol {
|
|||
|
||||
private final PlaceOfferModel model;
|
||||
private final TransactionResultHandler resultHandler;
|
||||
private final ErrorMessageHandler errorMessageHandler;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -38,9 +40,11 @@ public class PlaceOfferProtocol {
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public PlaceOfferProtocol(PlaceOfferModel model,
|
||||
TransactionResultHandler resultHandler) {
|
||||
TransactionResultHandler resultHandler,
|
||||
ErrorMessageHandler errorMessageHandler) {
|
||||
this.model = model;
|
||||
this.resultHandler = resultHandler;
|
||||
this.errorMessageHandler = errorMessageHandler;
|
||||
}
|
||||
|
||||
|
||||
|
@ -66,7 +70,7 @@ public class PlaceOfferProtocol {
|
|||
},
|
||||
log::error);
|
||||
}
|
||||
log.error(errorMessage);
|
||||
errorMessageHandler.handleErrorMessage(errorMessage);
|
||||
}
|
||||
);
|
||||
taskRunner.addTasks(
|
||||
|
|
|
@ -27,7 +27,6 @@ import io.bisq.common.locale.Res;
|
|||
import io.bisq.common.locale.TradeCurrency;
|
||||
import io.bisq.common.monetary.Price;
|
||||
import io.bisq.common.monetary.Volume;
|
||||
import io.bisq.common.util.MathUtils;
|
||||
import io.bisq.common.util.Utilities;
|
||||
import io.bisq.core.app.BisqEnvironment;
|
||||
import io.bisq.core.btc.AddressEntry;
|
||||
|
@ -39,6 +38,7 @@ import io.bisq.core.btc.wallet.BtcWalletService;
|
|||
import io.bisq.core.filter.FilterManager;
|
||||
import io.bisq.core.offer.Offer;
|
||||
import io.bisq.core.offer.OfferPayload;
|
||||
import io.bisq.core.offer.OfferUtil;
|
||||
import io.bisq.core.offer.OpenOfferManager;
|
||||
import io.bisq.core.payment.*;
|
||||
import io.bisq.core.payment.payload.BankAccountPayload;
|
||||
|
@ -47,7 +47,6 @@ import io.bisq.core.provider.price.PriceFeedService;
|
|||
import io.bisq.core.trade.handlers.TransactionResultHandler;
|
||||
import io.bisq.core.user.Preferences;
|
||||
import io.bisq.core.user.User;
|
||||
import io.bisq.core.util.CoinUtil;
|
||||
import io.bisq.gui.common.model.ActivatableDataModel;
|
||||
import io.bisq.gui.main.overlays.notifications.Notification;
|
||||
import io.bisq.gui.util.BSFormatter;
|
||||
|
@ -59,7 +58,6 @@ import javafx.collections.SetChangeListener;
|
|||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -411,7 +409,8 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
|||
openOfferManager.placeOffer(offer,
|
||||
reservedFundsForOffer,
|
||||
useSavingsWallet,
|
||||
resultHandler);
|
||||
resultHandler,
|
||||
log::error);
|
||||
}
|
||||
|
||||
void onPaymentAccountSelected(PaymentAccount paymentAccount) {
|
||||
|
@ -507,10 +506,6 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
|||
return direction;
|
||||
}
|
||||
|
||||
String getOfferId() {
|
||||
return offerId;
|
||||
}
|
||||
|
||||
AddressEntry getAddressEntry() {
|
||||
return addressEntry;
|
||||
}
|
||||
|
@ -544,22 +539,10 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
|||
return marketPriceMargin;
|
||||
}
|
||||
|
||||
boolean isCurrencyForMakerFeeBtc() {
|
||||
return preferences.getPayFeeInBtc() || !isBsqForFeeAvailable();
|
||||
}
|
||||
|
||||
boolean isMakerFeeValid() {
|
||||
return preferences.getPayFeeInBtc() || isBsqForFeeAvailable();
|
||||
}
|
||||
|
||||
boolean isBsqForFeeAvailable() {
|
||||
return BisqEnvironment.isBaseCurrencySupportingBsq() &&
|
||||
getMakerFee(false) != null &&
|
||||
bsqWalletService.getAvailableBalance() != null &&
|
||||
getMakerFee(false) != null &&
|
||||
!bsqWalletService.getAvailableBalance().subtract(getMakerFee(false)).isNegative();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
|
@ -613,8 +596,8 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
|||
return isBuyOffer() ? buyerSecurityDeposit.get() : sellerSecurityDeposit;
|
||||
}
|
||||
|
||||
boolean isBuyOffer() {
|
||||
return direction == OfferPayload.Direction.BUY;
|
||||
public boolean isBuyOffer() {
|
||||
return OfferUtil.isBuyOffer(getDirection());
|
||||
}
|
||||
|
||||
private void updateBalance() {
|
||||
|
@ -668,7 +651,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
|||
}
|
||||
|
||||
public void swapTradeToSavings() {
|
||||
log.error("swapTradeToSavings, offerid={}", offerId);
|
||||
log.error("swapTradeToSavings, offerId={}", offerId);
|
||||
btcWalletService.resetAddressEntriesForOpenOffer(offerId);
|
||||
}
|
||||
|
||||
|
@ -706,32 +689,6 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
|||
preferences.setBuyerSecurityDepositAsLong(buyerSecurityDeposit.value);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Coin getMakerFee() {
|
||||
return getMakerFee(isCurrencyForMakerFeeBtc());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Coin getMakerFee(boolean isCurrencyForMakerFeeBtc) {
|
||||
Coin amount = this.amount.get();
|
||||
if (amount != null) {
|
||||
final Coin feePerBtc = CoinUtil.getFeePerBtc(FeeService.getMakerFeePerBtc(isCurrencyForMakerFeeBtc), amount);
|
||||
double makerFeeAsDouble = (double) feePerBtc.value;
|
||||
if (marketPriceAvailable) {
|
||||
if (marketPriceMargin > 0)
|
||||
makerFeeAsDouble = makerFeeAsDouble * Math.sqrt(marketPriceMargin * 100);
|
||||
else
|
||||
makerFeeAsDouble = 0;
|
||||
// For BTC we round so min value change is 100 satoshi
|
||||
if (isCurrencyForMakerFeeBtc)
|
||||
makerFeeAsDouble = MathUtils.roundDouble(makerFeeAsDouble / 100, 0) * 100;
|
||||
}
|
||||
|
||||
return CoinUtil.maxCoin(Coin.valueOf(MathUtils.doubleToLong(makerFeeAsDouble)), FeeService.getMinMakerFee(isCurrencyForMakerFeeBtc));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
|
@ -757,10 +714,6 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
|||
this.minAmount.set(minAmount);
|
||||
}
|
||||
|
||||
void setDirection(OfferPayload.Direction direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
ReadOnlyStringProperty getTradeCurrencyCode() {
|
||||
return tradeCurrencyCode;
|
||||
}
|
||||
|
@ -800,4 +753,20 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
|||
public void setMarketPriceAvailable(boolean marketPriceAvailable) {
|
||||
this.marketPriceAvailable = marketPriceAvailable;
|
||||
}
|
||||
|
||||
public Coin getMakerFee(boolean isCurrencyForMakerFeeBtc) {
|
||||
return OfferUtil.getMakerFee(isCurrencyForMakerFeeBtc, amount.get(), marketPriceAvailable, marketPriceMargin);
|
||||
}
|
||||
|
||||
public Coin getMakerFee() {
|
||||
return OfferUtil.getMakerFee(bsqWalletService, preferences, amount.get(), marketPriceAvailable, marketPriceMargin);
|
||||
}
|
||||
|
||||
public boolean isCurrencyForMakerFeeBtc() {
|
||||
return OfferUtil.isCurrencyForMakerFeeBtc(preferences, bsqWalletService, amount.get(), marketPriceAvailable, marketPriceMargin);
|
||||
}
|
||||
|
||||
public boolean isBsqForFeeAvailable() {
|
||||
return OfferUtil.isBsqForFeeAvailable(bsqWalletService, amount.get(), marketPriceAvailable, marketPriceMargin);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue