switch to xmr atomic units as native units

This commit is contained in:
woodser 2023-03-05 14:09:14 -05:00
parent ab94b2d6fa
commit 9b4f8046b7
124 changed files with 1155 additions and 1283 deletions

View file

@ -25,7 +25,7 @@ import bisq.desktop.util.GUIUtil;
import bisq.core.account.sign.SignedWitnessService;
import bisq.core.locale.Res;
import bisq.core.offer.OfferRestrictions;
import bisq.core.util.coin.CoinFormatter;
import bisq.core.trade.HavenoUtils;
import bisq.common.UserThread;
@ -54,14 +54,13 @@ public class AccountStatusTooltipLabel extends AutoTooltipLabel {
private PopOver popOver;
private boolean keepPopOverVisible = false;
public AccountStatusTooltipLabel(OfferBookListItem.WitnessAgeData witnessAgeData,
CoinFormatter formatter) {
public AccountStatusTooltipLabel(OfferBookListItem.WitnessAgeData witnessAgeData) {
super(witnessAgeData.getDisplayString());
this.witnessAgeData = witnessAgeData;
this.textIcon = FormBuilder.getIcon(witnessAgeData.getIcon());
this.popupTitle = witnessAgeData.isLimitLifted()
? Res.get("offerbook.timeSinceSigning.tooltip.accountLimitLifted")
: Res.get("offerbook.timeSinceSigning.tooltip.accountLimit", formatter.formatCoinWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT));
: Res.get("offerbook.timeSinceSigning.tooltip.accountLimit", HavenoUtils.formatToXmrWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT));
positionAndActivateIcon();
}

View file

@ -21,11 +21,9 @@ import bisq.desktop.main.overlays.popups.Popup;
import bisq.desktop.util.GUIUtil;
import bisq.core.locale.Res;
import bisq.core.trade.HavenoUtils;
import bisq.common.util.Utilities;
import org.bitcoinj.core.Coin;
import de.jensd.fx.fontawesome.AwesomeDude;
import de.jensd.fx.fontawesome.AwesomeIcon;
@ -40,6 +38,7 @@ import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import java.math.BigInteger;
import java.net.URI;
import org.slf4j.Logger;
@ -50,7 +49,7 @@ public class AddressTextField extends AnchorPane {
private final StringProperty address = new SimpleStringProperty();
private final StringProperty paymentLabel = new SimpleStringProperty();
private final ObjectProperty<Coin> amountAsCoin = new SimpleObjectProperty<>(Coin.ZERO);
private final ObjectProperty<BigInteger> amount = new SimpleObjectProperty<>(BigInteger.ZERO);
private boolean wasPrimaryButtonDown;
@ -128,16 +127,16 @@ public class AddressTextField extends AnchorPane {
return address;
}
public Coin getAmountAsCoin() {
return amountAsCoin.get();
public BigInteger getAmount() {
return amount.get();
}
public ObjectProperty<Coin> amountAsCoinProperty() {
return amountAsCoin;
public ObjectProperty<BigInteger> amountAsProperty() {
return amount;
}
public void setAmountAsCoin(Coin amountAsCoin) {
this.amountAsCoin.set(amountAsCoin);
public void setAmount(BigInteger amount) {
this.amount.set(amount);
}
public String getPaymentLabel() {
@ -158,11 +157,11 @@ public class AddressTextField extends AnchorPane {
///////////////////////////////////////////////////////////////////////////////////////////
private String getBitcoinURI() {
if (amountAsCoin.get().isNegative()) {
if (amount.get().compareTo(BigInteger.valueOf(0)) < 0) {
log.warn("Amount must not be negative");
setAmountAsCoin(Coin.ZERO);
setAmount(BigInteger.valueOf(0));
}
return GUIUtil.getBitcoinURI(address.get(), amountAsCoin.get(),
return GUIUtil.getBitcoinURI(address.get(), HavenoUtils.atomicUnitsToCoin(amount.get()),
paymentLabel.get());
}
}

View file

@ -17,10 +17,9 @@
package bisq.desktop.components;
import bisq.core.trade.HavenoUtils;
import bisq.core.util.coin.CoinFormatter;
import org.bitcoinj.core.Coin;
import com.jfoenix.controls.JFXTextField;
import javafx.scene.effect.BlurType;
@ -29,17 +28,19 @@ import javafx.scene.effect.Effect;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import java.math.BigInteger;
import javax.annotation.Nullable;
public class BalanceTextField extends AnchorPane {
private Coin targetAmount;
private BigInteger targetAmount;
private final JFXTextField textField;
private final Effect fundedEffect = new DropShadow(BlurType.THREE_PASS_BOX, Color.GREEN, 4, 0.0, 0, 0);
private final Effect notFundedEffect = new DropShadow(BlurType.THREE_PASS_BOX, Color.ORANGERED, 4, 0.0, 0, 0);
private CoinFormatter formatter;
@Nullable
private Coin balance;
private BigInteger balance;
///////////////////////////////////////////////////////////////////////////////////////////
@ -64,13 +65,13 @@ public class BalanceTextField extends AnchorPane {
this.formatter = formatter;
}
public void setBalance(Coin balance) {
public void setBalance(BigInteger balance) {
this.balance = balance;
updateBalance(balance);
}
public void setTargetAmount(Coin targetAmount) {
public void setTargetAmount(BigInteger targetAmount) {
this.targetAmount = targetAmount;
if (this.balance != null)
@ -81,9 +82,9 @@ public class BalanceTextField extends AnchorPane {
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void updateBalance(Coin balance) {
private void updateBalance(BigInteger balance) {
if (formatter != null)
textField.setText(formatter.formatCoinWithCode(balance));
textField.setText(HavenoUtils.formatToXmrWithCode(balance));
//TODO: replace with new validation logic
// if (targetAmount != null) {

View file

@ -238,7 +238,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
Tuple2<Label, VBox> availableBalanceBox = getBalanceBox(Res.get("mainView.balance.available"));
availableBalanceBox.first.textProperty().bind(model.getAvailableBalance());
availableBalanceBox.first.setPrefWidth(100);
availableBalanceBox.first.setPrefWidth(105);
availableBalanceBox.first.tooltipProperty().bind(new ObjectBinding<>() {
{
bind(model.getAvailableBalance());

View file

@ -115,6 +115,7 @@ import bisq.core.payment.validation.TransferwiseValidator;
import bisq.core.payment.validation.USPostalMoneyOrderValidator;
import bisq.core.payment.validation.UpholdValidator;
import bisq.core.payment.validation.WeChatPayValidator;
import bisq.core.trade.HavenoUtils;
import bisq.core.util.FormattingUtils;
import bisq.core.util.coin.CoinFormatter;
@ -123,8 +124,6 @@ import bisq.common.util.Tuple2;
import bisq.common.util.Tuple3;
import bisq.common.util.Utilities;
import org.bitcoinj.core.Coin;
import javax.inject.Inject;
import javax.inject.Named;
@ -142,6 +141,7 @@ import javafx.collections.ObservableList;
import javafx.util.StringConverter;
import java.math.BigInteger;
import java.util.List;
import java.util.stream.Collectors;
@ -257,9 +257,9 @@ public class FiatAccountsView extends PaymentAccountsView<GridPane, FiatAccounts
///////////////////////////////////////////////////////////////////////////////////////////
private void onSaveNewAccount(PaymentAccount paymentAccount) {
Coin maxTradeLimitAsCoin = paymentAccount.getPaymentMethod().getMaxTradeLimitAsCoin("USD");
Coin maxTradeLimitSecondMonth = maxTradeLimitAsCoin.divide(2L);
Coin maxTradeLimitFirstMonth = maxTradeLimitAsCoin.divide(4L);
BigInteger maxTradeLimit = paymentAccount.getPaymentMethod().getMaxTradeLimit("USD");
BigInteger maxTradeLimitSecondMonth = maxTradeLimit.divide(BigInteger.valueOf(2L));
BigInteger maxTradeLimitFirstMonth = maxTradeLimit.divide(BigInteger.valueOf(4L));
if (paymentAccount instanceof F2FAccount) {
new Popup().information(Res.get("payment.f2f.info"))
.width(700)
@ -287,17 +287,17 @@ public class FiatAccountsView extends PaymentAccountsView<GridPane, FiatAccounts
} else {
String limitsInfoKey = "payment.limits.info";
String initialLimit = formatter.formatCoinWithCode(maxTradeLimitFirstMonth);
String initialLimit = HavenoUtils.formatToXmrWithCode(maxTradeLimitFirstMonth);
if (PaymentMethod.hasChargebackRisk(paymentAccount.getPaymentMethod(), paymentAccount.getTradeCurrencies())) {
limitsInfoKey = "payment.limits.info.withSigning";
initialLimit = formatter.formatCoinWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT);
initialLimit = HavenoUtils.formatToXmrWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT);
}
new Popup().information(Res.get(limitsInfoKey,
initialLimit,
formatter.formatCoinWithCode(maxTradeLimitSecondMonth),
formatter.formatCoinWithCode(maxTradeLimitAsCoin)))
HavenoUtils.formatToXmrWithCode(maxTradeLimitSecondMonth),
HavenoUtils.formatToXmrWithCode(maxTradeLimit)))
.width(700)
.closeButtonText(Res.get("shared.cancel"))
.actionButtonText(Res.get("shared.iUnderstand"))

View file

@ -37,14 +37,13 @@ import monero.daemon.model.MoneroTx;
import monero.wallet.model.MoneroTransferQuery;
import monero.wallet.model.MoneroTxQuery;
import monero.wallet.model.MoneroTxWallet;
import org.bitcoinj.core.Coin;
@Slf4j
class DepositListItem {
private final StringProperty balance = new SimpleStringProperty();
private final XmrAddressEntry addressEntry;
private final XmrWalletService xmrWalletService;
private Coin balanceAsCoin;
private BigInteger balanceAsBI;
private String usage = "-";
private XmrBalanceListener balanceListener;
private int numTxOutputs = 0;
@ -66,15 +65,15 @@ class DepositListItem {
balanceListener = new XmrBalanceListener(addressEntry.getSubaddressIndex()) {
@Override
public void onBalanceChanged(BigInteger balance) {
DepositListItem.this.balanceAsCoin = HavenoUtils.atomicUnitsToCoin(balance);
DepositListItem.this.balance.set(formatter.formatCoin(balanceAsCoin));
DepositListItem.this.balanceAsBI = balance;
DepositListItem.this.balance.set(HavenoUtils.formatToXmr(balanceAsBI));
updateUsage(addressEntry.getSubaddressIndex(), null);
}
};
xmrWalletService.addBalanceListener(balanceListener);
balanceAsCoin = xmrWalletService.getBalanceForSubaddress(addressEntry.getSubaddressIndex());
balance.set(formatter.formatCoin(balanceAsCoin));
balanceAsBI = xmrWalletService.getBalanceForSubaddress(addressEntry.getSubaddressIndex());
balance.set(HavenoUtils.formatToXmr(balanceAsBI));
updateUsage(addressEntry.getSubaddressIndex(), cachedTxs);
@ -124,8 +123,8 @@ class DepositListItem {
return balance.get();
}
public Coin getBalanceAsCoin() {
return balanceAsCoin;
public BigInteger getBalanceAsBI() {
return balanceAsBI;
}
public int getNumTxOutputs() {

View file

@ -157,7 +157,7 @@ public class DepositView extends ActivatableView<VBox, Void> {
setConfidenceColumnCellFactory();
addressColumn.setComparator(Comparator.comparing(DepositListItem::getAddressString));
balanceColumn.setComparator(Comparator.comparing(DepositListItem::getBalanceAsCoin));
balanceColumn.setComparator(Comparator.comparing(DepositListItem::getBalanceAsBI));
confirmationsColumn.setComparator(Comparator.comparingLong(o -> o.getNumConfirmationsSinceFirstUsed()));
usageColumn.setComparator(Comparator.comparingInt(DepositListItem::getNumTxOutputs));
tableView.getSortOrder().add(usageColumn);
@ -237,7 +237,7 @@ public class DepositView extends ActivatableView<VBox, Void> {
xmrWalletService.addBalanceListener(balanceListener);
amountTextFieldSubscription = EasyBind.subscribe(amountTextField.textProperty(), t -> {
addressTextField.setAmountAsCoin(ParsingUtils.parseToCoin(t, formatter));
addressTextField.setAmount(HavenoUtils.parseXmr(t));
updateQRCode();
});
@ -306,7 +306,7 @@ public class DepositView extends ActivatableView<VBox, Void> {
.forEach(e -> observableList.add(new DepositListItem(e, xmrWalletService, formatter, incomingTxs)));
}
private Coin getAmountAsCoin() {
private Coin getAmount() {
return ParsingUtils.parseToCoin(amountTextField.getText(), formatter);
}
@ -314,7 +314,7 @@ public class DepositView extends ActivatableView<VBox, Void> {
private String getPaymentUri() {
return xmrWalletService.getWallet().getPaymentUri(new MoneroTxConfig()
.setAddress(addressTextField.getAddress())
.setAmount(HavenoUtils.coinToAtomicUnits(getAmountAsCoin()))
.setAmount(HavenoUtils.coinToAtomicUnits(getAmount()))
.setNote(paymentLabelString));
}

View file

@ -51,8 +51,6 @@ public class TransactionListItemFactory {
TransactionsListItem create(MoneroTxWallet transaction, @Nullable TransactionAwareTradable tradable) {
return new TransactionsListItem(transaction,
xmrWalletService,
tradable,
formatter,
preferences.getIgnoreDustThreshold());
tradable);
}
}

View file

@ -24,7 +24,6 @@ import bisq.core.offer.OpenOffer;
import bisq.core.trade.HavenoUtils;
import bisq.core.trade.Tradable;
import bisq.core.trade.Trade;
import bisq.core.util.coin.CoinFormatter;
import bisq.desktop.components.indicator.TxConfidenceIndicator;
import bisq.desktop.util.DisplayUtils;
import bisq.desktop.util.GUIUtil;
@ -41,11 +40,9 @@ import monero.wallet.model.MoneroIncomingTransfer;
import monero.wallet.model.MoneroOutgoingTransfer;
import monero.wallet.model.MoneroTxWallet;
import monero.wallet.model.MoneroWalletListener;
import org.bitcoinj.core.Coin;
@Slf4j
class TransactionsListItem {
private final CoinFormatter formatter;
private String dateString;
private final Date date;
private final String txId;
@ -56,11 +53,10 @@ class TransactionsListItem {
private String direction = "";
private boolean received;
private boolean detailsAvailable;
private Coin amountAsCoin = Coin.ZERO;
private BigInteger amount = BigInteger.valueOf(0);
private String memo = "";
private long confirmations = 0;
@Getter
private final boolean isDustAttackTx;
private boolean initialTxConfidenceVisibility = true;
private final Supplier<LazyFields> lazyFieldsSupplier;
@ -77,25 +73,20 @@ class TransactionsListItem {
TransactionsListItem() {
date = null;
txId = null;
formatter = null;
isDustAttackTx = false;
lazyFieldsSupplier = null;
}
TransactionsListItem(MoneroTxWallet tx,
XmrWalletService xmrWalletService,
TransactionAwareTradable transactionAwareTradable,
CoinFormatter formatter,
long ignoreDustThreshold) {
this.formatter = formatter;
TransactionAwareTradable transactionAwareTradable) {
this.memo = tx.getNote();
this.txId = tx.getHash();
Optional<Tradable> optionalTradable = Optional.ofNullable(transactionAwareTradable)
.map(TransactionAwareTradable::asTradable);
Coin valueSentToMe = HavenoUtils.atomicUnitsToCoin(tx.getIncomingAmount() == null ? new BigInteger("0") : tx.getIncomingAmount());
Coin valueSentFromMe = HavenoUtils.atomicUnitsToCoin(tx.getOutgoingAmount() == null ? new BigInteger("0") : tx.getOutgoingAmount());
BigInteger valueSentToMe = tx.getIncomingAmount() == null ? new BigInteger("0") : tx.getIncomingAmount();
BigInteger valueSentFromMe = tx.getOutgoingAmount() == null ? new BigInteger("0") : tx.getOutgoingAmount();
if (tx.getTransfers().get(0).isIncoming()) {
addressString = ((MoneroIncomingTransfer) tx.getTransfers().get(0)).getAddress();
@ -105,12 +96,12 @@ class TransactionsListItem {
else addressString = "unavailable";
}
if (valueSentFromMe.isZero()) {
amountAsCoin = valueSentToMe;
if (valueSentFromMe.compareTo(BigInteger.valueOf(0)) == 0) {
amount = valueSentToMe;
direction = Res.get("funds.tx.direction.receivedWith");
received = true;
} else {
amountAsCoin = valueSentFromMe.multiply(-1);
amount = valueSentFromMe.multiply(BigInteger.valueOf(-1));
received = false;
direction = Res.get("funds.tx.direction.sentTo");
}
@ -134,13 +125,13 @@ class TransactionsListItem {
} else if (trade.getPayoutTxId() != null &&
trade.getPayoutTxId().equals(txId)) {
details = Res.get("funds.tx.multiSigPayout", tradeId);
if (amountAsCoin.isZero()) {
if (amount.compareTo(BigInteger.valueOf(0)) == 0) {
initialTxConfidenceVisibility = false;
}
} else {
Trade.DisputeState disputeState = trade.getDisputeState();
if (disputeState == Trade.DisputeState.DISPUTE_CLOSED) {
if (valueSentToMe.isPositive()) {
if (valueSentToMe.compareTo(BigInteger.valueOf(0)) > 0) {
details = Res.get("funds.tx.disputePayout", tradeId);
} else {
details = Res.get("funds.tx.disputeLost", tradeId);
@ -148,7 +139,7 @@ class TransactionsListItem {
} else if (disputeState == Trade.DisputeState.REFUND_REQUEST_CLOSED ||
disputeState == Trade.DisputeState.REFUND_REQUESTED ||
disputeState == Trade.DisputeState.REFUND_REQUEST_STARTED_BY_PEER) {
if (valueSentToMe.isPositive()) {
if (valueSentToMe.compareTo(BigInteger.valueOf(0)) > 0) {
details = Res.get("funds.tx.refund", tradeId);
} else {
// We have spent the deposit tx outputs to the Bisq donation address to enable
@ -156,7 +147,7 @@ class TransactionsListItem {
// already when funding the deposit tx we show 0 BTC as amount.
// Confirmation is not known from the BitcoinJ side (not 100% clear why) as no funds
// left our wallet nor we received funds. So we set indicator invisible.
amountAsCoin = Coin.ZERO;
amount = BigInteger.valueOf(0);
details = Res.get("funds.tx.collateralForRefund", tradeId);
initialTxConfidenceVisibility = false;
}
@ -166,7 +157,7 @@ class TransactionsListItem {
}
}
} else {
if (amountAsCoin.isZero()) {
if (amount.compareTo(BigInteger.valueOf(0)) == 0) {
details = Res.get("funds.tx.noFundsFromDispute");
}
}
@ -176,11 +167,6 @@ class TransactionsListItem {
this.date = new Date(timestamp);
dateString = DisplayUtils.formatDateTime(date);
isDustAttackTx = received && valueSentToMe.value < ignoreDustThreshold;
if (isDustAttackTx) {
details = Res.get("funds.tx.dustAttackTx");
}
// confidence
lazyFieldsSupplier = Suppliers.memoize(() -> new LazyFields() {{
txConfidenceIndicator = new TxConfidenceIndicator();
@ -217,16 +203,14 @@ class TransactionsListItem {
return dateString;
}
public String getAmount() {
return formatter.formatCoin(amountAsCoin);
public String getAmountStr() {
return HavenoUtils.formatToXmr(amount);
}
public Coin getAmountAsCoin() {
return amountAsCoin;
public BigInteger getAmount() {
return amount;
}
public String getAddressString() {
return addressString;
}

View file

@ -24,7 +24,6 @@ import bisq.desktop.components.AutoTooltipButton;
import bisq.desktop.components.AutoTooltipLabel;
import bisq.desktop.components.ExternalHyperlink;
import bisq.desktop.components.HyperlinkWithIcon;
import bisq.desktop.main.overlays.popups.Popup;
import bisq.desktop.main.overlays.windows.OfferDetailsWindow;
import bisq.desktop.main.overlays.windows.TradeDetailsWindow;
import bisq.desktop.util.GUIUtil;
@ -168,7 +167,7 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
});
addressColumn.setComparator(Comparator.comparing(item -> item.getDirection() + item.getAddressString()));
transactionColumn.setComparator(Comparator.comparing(TransactionsListItem::getTxId));
amountColumn.setComparator(Comparator.comparing(TransactionsListItem::getAmountAsCoin));
amountColumn.setComparator(Comparator.comparing(TransactionsListItem::getAmount));
confidenceColumn.setComparator(Comparator.comparingLong(item -> item.getNumConfirmations()));
memoColumn.setComparator(Comparator.comparing(TransactionsListItem::getMemo));
@ -221,7 +220,7 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
columns[1] = item.getDetails();
columns[2] = item.getDirection() + " " + item.getAddressString();
columns[3] = item.getTxId();
columns[4] = item.getAmount();
columns[4] = item.getAmountStr();
columns[5] = item.getMemo() == null ? "" : item.getMemo();
columns[6] = String.valueOf(item.getNumConfirmations());
return columns;
@ -320,13 +319,7 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
setGraphic(hyperlinkWithIcon);
// If details are available its a trade tx and we don't expect any dust attack tx
} else {
if (item.isDustAttackTx()) {
hyperlinkWithIcon = new HyperlinkWithIcon(item.getDetails(), AwesomeIcon.WARNING_SIGN);
hyperlinkWithIcon.setOnAction(event -> new Popup().warning(Res.get("funds.tx.dustAttackTx.popup")).show());
setGraphic(hyperlinkWithIcon);
} else {
setGraphic(new AutoTooltipLabel(item.getDetails()));
}
setGraphic(new AutoTooltipLabel(item.getDetails()));
}
} else {
setGraphic(null);
@ -423,7 +416,7 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
super.updateItem(item, empty);
if (item != null && !empty) {
setGraphic(new AutoTooltipLabel(item.getAmount()));
setGraphic(new AutoTooltipLabel(item.getAmountStr()));
} else {
setGraphic(null);
}

View file

@ -23,11 +23,9 @@ import bisq.core.btc.listeners.XmrBalanceListener;
import bisq.core.btc.model.XmrAddressEntry;
import bisq.core.btc.wallet.XmrWalletService;
import bisq.core.locale.Res;
import bisq.core.util.ParsingUtils;
import bisq.core.trade.HavenoUtils;
import bisq.core.util.coin.CoinFormatter;
import org.bitcoinj.core.Coin;
import javafx.scene.control.Label;
import java.math.BigInteger;
@ -41,7 +39,7 @@ class WithdrawalListItem {
private final XmrAddressEntry addressEntry;
private final XmrWalletService walletService;
private final CoinFormatter formatter;
private Coin balance;
private BigInteger balance;
private final String addressString;
@Setter
@Getter
@ -74,7 +72,7 @@ class WithdrawalListItem {
private void updateBalance() {
balance = walletService.getBalanceForSubaddress(addressEntry.getSubaddressIndex());
if (balance != null)
balanceLabel.setText(formatter.formatCoin(this.balance));
balanceLabel.setText(HavenoUtils.formatToXmr(this.balance));
}
public final String getLabel() {
@ -111,7 +109,7 @@ class WithdrawalListItem {
return balanceLabel;
}
public Coin getBalance() {
public BigInteger getBalance() {
return balance;
}

View file

@ -35,18 +35,12 @@ import bisq.core.trade.HavenoUtils;
import bisq.core.trade.Trade;
import bisq.core.trade.TradeManager;
import bisq.core.user.DontShowAgainLookup;
import bisq.core.util.FormattingUtils;
import bisq.core.util.ParsingUtils;
import bisq.core.util.coin.CoinFormatter;
import bisq.core.util.validation.BtcAddressValidator;
import bisq.network.p2p.P2PService;
import bisq.common.util.Tuple2;
import org.bitcoinj.core.Coin;
import javax.inject.Inject;
import javax.inject.Named;
import monero.wallet.model.MoneroTxConfig;
import monero.wallet.model.MoneroTxWallet;
@ -78,9 +72,8 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
private final XmrWalletService xmrWalletService;
private final TradeManager tradeManager;
private final P2PService p2PService;
private final CoinFormatter formatter;
private XmrBalanceListener balanceListener;
private Coin amountAsCoin = Coin.ZERO;
private BigInteger amount = BigInteger.valueOf(0);
private ChangeListener<String> amountListener;
private ChangeListener<Boolean> amountFocusListener;
private int rowIndex = 0;
@ -94,13 +87,11 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
TradeManager tradeManager,
P2PService p2PService,
WalletsSetup walletsSetup,
@Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter,
BtcAddressValidator btcAddressValidator,
WalletPasswordWindow walletPasswordWindow) {
this.xmrWalletService = xmrWalletService;
this.tradeManager = tradeManager;
this.p2PService = p2PService;
this.formatter = formatter;
}
@Override
@ -136,7 +127,7 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
amountListener = (observable, oldValue, newValue) -> {
if (amountTextField.focusedProperty().get()) {
try {
amountAsCoin = ParsingUtils.parseToCoin(amountTextField.getText(), formatter);
amount = HavenoUtils.parseXmr(amountTextField.getText());
} catch (Throwable t) {
log.error("Error at amountTextField input. " + t.toString());
}
@ -144,8 +135,8 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
};
amountFocusListener = (observable, oldValue, newValue) -> {
if (oldValue && !newValue) {
if (amountAsCoin.isPositive())
amountTextField.setText(formatter.formatCoin(amountAsCoin));
if (amount.compareTo(BigInteger.valueOf(0)) > 0)
amountTextField.setText(HavenoUtils.formatToXmr(amount));
else
amountTextField.setText("");
}
@ -184,23 +175,23 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
final String withdrawToAddress = withdrawToTextField.getText();
// get receiver amount
Coin receiverAmount = amountAsCoin;
if (!receiverAmount.isPositive()) throw new RuntimeException(Res.get("portfolio.pending.step5_buyer.amountTooLow"));
BigInteger receiverAmount = amount;
if (receiverAmount.compareTo(BigInteger.valueOf(0)) <= 0) throw new RuntimeException(Res.get("portfolio.pending.step5_buyer.amountTooLow"));
// create tx
MoneroTxWallet tx = xmrWalletService.getWallet().createTx(new MoneroTxConfig()
.setAccountIndex(0)
.setAmount(HavenoUtils.coinToAtomicUnits(receiverAmount)) // TODO: rename to centinerosToAtomicUnits()?
.setAmount(receiverAmount)
.setAddress(withdrawToAddress));
// create confirmation message
Coin sendersAmount = receiverAmount;
Coin fee = HavenoUtils.atomicUnitsToCoin(tx.getFee());
BigInteger sendersAmount = receiverAmount;
BigInteger fee = tx.getFee();
String messageText = Res.get("shared.sendFundsDetailsWithFee",
formatter.formatCoinWithCode(sendersAmount),
HavenoUtils.formatToXmrWithCode(sendersAmount),
withdrawToAddress,
formatter.formatCoinWithCode(fee),
formatter.formatCoinWithCode(receiverAmount));
HavenoUtils.formatToXmrWithCode(fee),
HavenoUtils.formatToXmrWithCode(receiverAmount));
// popup confirmation message
new Popup().headLine(Res.get("funds.withdrawal.confirmWithdrawalRequest"))
@ -214,7 +205,7 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
xmrWalletService.getWallet().setTxNote(tx.getHash(), withdrawMemoTextField.getText()); // TODO (monero-java): tx note does not persist when tx created then relayed
String key = "showTransactionSent";
if (DontShowAgainLookup.showAgain(key)) {
new TxDetails(tx.getHash(), withdrawToAddress, formatter.formatCoinWithCode(sendersAmount), formatter.formatCoinWithCode(fee), xmrWalletService.getWallet().getTxNote(tx.getHash()))
new TxDetails(tx.getHash(), withdrawToAddress, HavenoUtils.formatToXmrWithCode(sendersAmount), HavenoUtils.formatToXmrWithCode(fee), xmrWalletService.getWallet().getTxNote(tx.getHash()))
.dontShowAgainId(key)
.show();
}
@ -225,7 +216,7 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
.filter(Trade::isPayoutPublished)
.forEach(trade -> xmrWalletService.getAddressEntry(trade.getId(), XmrAddressEntry.Context.TRADE_PAYOUT)
.ifPresent(addressEntry -> {
if (xmrWalletService.getBalanceForAddress(addressEntry.getAddressString()).isZero())
if (xmrWalletService.getBalanceForAddress(addressEntry.getAddressString()).compareTo(BigInteger.valueOf(0)) == 0)
tradeManager.onTradeCompleted(trade);
}));
} catch (Exception e) {
@ -251,7 +242,7 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
///////////////////////////////////////////////////////////////////////////////////////////
private void reset() {
amountAsCoin = Coin.ZERO;
amount = BigInteger.valueOf(0);
amountTextField.setText("");
amountTextField.setPromptText(Res.get("funds.withdrawal.setAmount"));

View file

@ -32,7 +32,6 @@ import bisq.desktop.util.CurrencyList;
import bisq.desktop.util.CurrencyListItem;
import bisq.desktop.util.DisplayUtils;
import bisq.desktop.util.GUIUtil;
import bisq.common.UserThread;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.locale.CurrencyUtil;
import bisq.core.locale.GlobalSettings;
@ -67,7 +66,6 @@ import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;
class OfferBookChartViewModel extends ActivatableViewModel {
@ -402,7 +400,7 @@ class OfferBookChartViewModel extends ActivatableViewModel {
for (Offer offer : sortedList) {
Price price = offer.getPrice();
if (price != null) {
double amount = (double) offer.getAmount().value / LongMath.pow(10, offer.getAmount().smallestUnitExponent());
double amount = (double) offer.getAmount().longValueExact() / LongMath.pow(10, HavenoUtils.XMR_SMALLEST_UNIT_EXPONENT);
accumulatedAmount += amount;
offerTableListTemp.add(new OfferListItem(offer, accumulatedAmount));

View file

@ -19,11 +19,11 @@ package bisq.desktop.main.market.spread;
import bisq.core.monetary.Price;
import org.bitcoinj.core.Coin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import javax.annotation.Nullable;
public class SpreadItem {
@ -36,10 +36,10 @@ public class SpreadItem {
public final Price priceSpread;
public final String percentage;
public final double percentageValue;
public final Coin totalAmount;
public final BigInteger totalAmount;
public SpreadItem(String currencyCode, int numberOfBuyOffers, int numberOfSellOffers, int numberOfOffers,
@Nullable Price priceSpread, String percentage, double percentageValue, Coin totalAmount) {
@Nullable Price priceSpread, String percentage, double percentageValue, BigInteger totalAmount) {
this.currencyCode = currencyCode;
this.numberOfBuyOffers = numberOfBuyOffers;
this.numberOfSellOffers = numberOfSellOffers;

View file

@ -26,11 +26,10 @@ import bisq.desktop.util.GUIUtil;
import bisq.common.UserThread;
import bisq.core.locale.CurrencyUtil;
import bisq.core.locale.Res;
import bisq.core.trade.HavenoUtils;
import bisq.core.util.FormattingUtils;
import bisq.core.util.coin.CoinFormatter;
import org.bitcoinj.core.Coin;
import javax.inject.Inject;
import javax.inject.Named;
@ -48,6 +47,7 @@ import javafx.collections.transformation.SortedList;
import javafx.util.Callback;
import java.math.BigInteger;
import java.util.Comparator;
@FxmlView
@ -127,7 +127,10 @@ public class SpreadView extends ActivatableViewAndModel<GridPane, SpreadViewMode
int numberOfOffers = sortedList.stream().mapToInt(item -> item.numberOfOffers).sum();
int numberOfBuyOffers = sortedList.stream().mapToInt(item -> item.numberOfBuyOffers).sum();
int numberOfSellOffers = sortedList.stream().mapToInt(item -> item.numberOfSellOffers).sum();
String total = formatter.formatCoin(Coin.valueOf(sortedList.stream().mapToLong(item -> item.totalAmount.value).sum()));
BigInteger totalAmount = BigInteger.valueOf(0);
for (SpreadItem item : sortedList) totalAmount = totalAmount.add(item.totalAmount);
String total = HavenoUtils.formatToXmr(totalAmount);
UserThread.execute(() -> {
numberOfOffersColumn.setGraphic(new AutoTooltipLabel(Res.get("market.spread.numberOfOffersColumn", numberOfOffers)));

View file

@ -30,10 +30,10 @@ import bisq.core.offer.Offer;
import bisq.core.offer.OfferDirection;
import bisq.core.provider.price.MarketPrice;
import bisq.core.provider.price.PriceFeedService;
import bisq.core.trade.HavenoUtils;
import bisq.core.util.FormattingUtils;
import bisq.core.util.coin.CoinFormatter;
import org.bitcoinj.core.Coin;
import org.bitcoinj.utils.Fiat;
import com.google.inject.Inject;
@ -48,6 +48,7 @@ import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.ArrayList;
@ -135,7 +136,7 @@ class SpreadViewModel extends ActivatableViewModel {
}
spreadItems.clear();
Coin totalAmount = null;
BigInteger totalAmount = BigInteger.valueOf(0);
for (String key : offersByCurrencyMap.keySet()) {
List<Offer> offers = offersByCurrencyMap.get(key);
@ -235,7 +236,7 @@ class SpreadViewModel extends ActivatableViewModel {
}
}
totalAmount = Coin.valueOf(offers.stream().mapToLong(offer -> offer.getAmount().getValue()).sum());
for (Offer offer : offers) totalAmount = totalAmount.add(offer.getAmount());
spreadItems.add(new SpreadItem(key, buyOffers.size(), sellOffers.size(),
uniqueOffers.size(), spread, percentage, percentageValue, totalAmount));
}
@ -243,11 +244,11 @@ class SpreadViewModel extends ActivatableViewModel {
maxPlacesForAmount.set(formatAmount(totalAmount, false).length());
}
public String getAmount(Coin amount) {
public String getAmount(BigInteger amount) {
return formatAmount(amount, true);
}
private String formatAmount(Coin amount, boolean decimalAligned) {
return formatter.formatCoin(amount, GUIUtil.AMOUNT_DECIMALS, decimalAligned, maxPlacesForAmount.get());
private String formatAmount(BigInteger amount, boolean decimalAligned) {
return formatter.formatCoin(HavenoUtils.atomicUnitsToCoin(amount), GUIUtil.AMOUNT_DECIMALS, decimalAligned, maxPlacesForAmount.get());
}
}

View file

@ -113,27 +113,26 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
protected TradeCurrency tradeCurrency;
protected final StringProperty tradeCurrencyCode = new SimpleStringProperty();
protected final BooleanProperty useMarketBasedPrice = new SimpleBooleanProperty();
protected final ObjectProperty<Coin> amount = new SimpleObjectProperty<>();
protected final ObjectProperty<Coin> minAmount = new SimpleObjectProperty<>();
protected final ObjectProperty<BigInteger> amount = new SimpleObjectProperty<>();
protected final ObjectProperty<BigInteger> minAmount = new SimpleObjectProperty<>();
protected final ObjectProperty<Price> price = new SimpleObjectProperty<>();
protected final ObjectProperty<Volume> volume = new SimpleObjectProperty<>();
protected final ObjectProperty<Volume> minVolume = new SimpleObjectProperty<>();
// Percentage value of buyer security deposit. E.g. 0.01 means 1% of trade amount
protected final DoubleProperty buyerSecurityDeposit = new SimpleDoubleProperty();
protected final DoubleProperty buyerSecurityDepositPct = new SimpleDoubleProperty();
protected final ObservableList<PaymentAccount> paymentAccounts = FXCollections.observableArrayList();
protected PaymentAccount paymentAccount;
boolean isTabSelected;
protected double marketPriceMargin = 0;
private Coin txFeeFromFeeService = Coin.ZERO;
@Getter
private boolean marketPriceAvailable;
protected boolean allowAmountUpdate = true;
private final TradeStatisticsManager tradeStatisticsManager;
private final Predicate<ObjectProperty<Coin>> isNonZeroAmount = (c) -> c.get() != null && !c.get().isZero();
private final Predicate<ObjectProperty<BigInteger>> isNonZeroAmount = (c) -> c.get() != null && c.get().compareTo(BigInteger.valueOf(0)) != 0;
private final Predicate<ObjectProperty<Price>> isNonZeroPrice = (p) -> p.get() != null && !p.get().isZero();
private final Predicate<ObjectProperty<Volume>> isNonZeroVolume = (v) -> v.get() != null && !v.get().isZero();
@Getter
@ -176,7 +175,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
addressEntry = xmrWalletService.getOrCreateAddressEntry(offerId, XmrAddressEntry.Context.OFFER_FUNDING);
useMarketBasedPrice.set(preferences.isUsePercentageBasedPrice());
buyerSecurityDeposit.set(Restrictions.getMinBuyerSecurityDepositAsPercent());
buyerSecurityDepositPct.set(Restrictions.getMinBuyerSecurityDepositAsPercent());
xmrBalanceListener = new XmrBalanceListener(getAddressEntry().getSubaddressIndex()) {
@Override
@ -295,10 +294,10 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
amount.get(),
minAmount.get(),
price.get(),
txFeeFromFeeService,
Coin.ZERO,
useMarketBasedPrice.get(),
marketPriceMargin,
buyerSecurityDeposit.get(),
buyerSecurityDepositPct.get(),
paymentAccount);
}
@ -319,7 +318,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
setSuggestedSecurityDeposit(getPaymentAccount());
if (amount.get() != null && this.allowAmountUpdate)
this.amount.set(Coin.valueOf(Math.min(amount.get().value, getMaxTradeLimit())));
this.amount.set(amount.get().min(BigInteger.valueOf(getMaxTradeLimit())));
}
}
@ -356,10 +355,10 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
// Suggested deposit is double the trade range over the previous lock time period, bounded by min/max deposit
var suggestedSecurityDeposit =
Math.min(2 * (max - min) / max, Restrictions.getMaxBuyerSecurityDepositAsPercent());
buyerSecurityDeposit.set(Math.max(suggestedSecurityDeposit, minSecurityDeposit));
buyerSecurityDepositPct.set(Math.max(suggestedSecurityDeposit, minSecurityDeposit));
} catch (Throwable t) {
log.error(t.toString());
buyerSecurityDeposit.set(minSecurityDeposit);
buyerSecurityDepositPct.set(minSecurityDeposit);
}
}
@ -421,7 +420,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
boolean isMinAmountLessOrEqualAmount() {
//noinspection SimplifiableIfStatement
if (minAmount.get() != null && amount.get() != null)
return !minAmount.get().isGreaterThan(amount.get());
return minAmount.get().compareTo(amount.get()) <= 0;
return true;
}
@ -512,7 +511,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
}
}
private Volume calculateVolumeForAmount(ObjectProperty<Coin> minAmount) {
private Volume calculateVolumeForAmount(ObjectProperty<BigInteger> minAmount) {
Volume volumeByAmount = price.get().getVolumeByAmount(minAmount.get());
// For HalCash we want multiple of 10 EUR
@ -526,7 +525,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
void calculateAmount() {
if (isNonZeroPrice.test(price) && isNonZeroVolume.test(volume) && allowAmountUpdate) {
try {
Coin value = DisplayUtils.reduceTo4Decimals(price.get().getAmountByVolume(volume.get()), btcFormatter);
BigInteger value = HavenoUtils.coinToAtomicUnits(DisplayUtils.reduceTo4Decimals(HavenoUtils.atomicUnitsToCoin(price.get().getAmountByVolume(volume.get())), btcFormatter));
if (isUsingHalCashAccount())
value = CoinUtil.getAdjustedAmountForHalCash(value, price.get(), getMaxTradeLimit());
else if (CurrencyUtil.isFiatCurrency(tradeCurrencyCode.get()))
@ -546,17 +545,17 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
// Maker does not pay the mining fee for the trade txs because the mining fee might be different when maker
// created the offer and reserved his funds, so that would not work well with dynamic fees.
// The mining fee for the createOfferFee tx is deducted from the createOfferFee and not visible to the trader
final Coin makerFee = getMakerFee();
final BigInteger makerFee = getMakerFee();
if (direction != null && amount.get() != null && makerFee != null) {
Coin feeAndSecDeposit = getSecurityDeposit().add(makerFee);
Coin total = isBuyOffer() ? feeAndSecDeposit : feeAndSecDeposit.add(amount.get());
totalToPayAsCoin.set(total);
BigInteger feeAndSecDeposit = getSecurityDeposit().add(makerFee);
BigInteger total = isBuyOffer() ? feeAndSecDeposit : feeAndSecDeposit.add(amount.get());
totalToPay.set(total);
updateBalance();
}
}
Coin getSecurityDeposit() {
return isBuyOffer() ? getBuyerSecurityDepositAsCoin() : getSellerSecurityDepositAsCoin();
BigInteger getSecurityDeposit() {
return isBuyOffer() ? getBuyerSecurityDeposit() : getSellerSecurityDeposit();
}
void swapTradeToSavings() {
@ -571,7 +570,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
protected abstract Set<PaymentAccount> getUserPaymentAccounts();
protected void setAmount(Coin amount) {
protected void setAmount(BigInteger amount) {
this.amount.set(amount);
}
@ -584,18 +583,18 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
}
protected void setBuyerSecurityDeposit(double value) {
this.buyerSecurityDeposit.set(value);
this.buyerSecurityDepositPct.set(value);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Getters
///////////////////////////////////////////////////////////////////////////////////////////
protected ReadOnlyObjectProperty<Coin> getAmount() {
protected ReadOnlyObjectProperty<BigInteger> getAmount() {
return amount;
}
protected ReadOnlyObjectProperty<Coin> getMinAmount() {
protected ReadOnlyObjectProperty<BigInteger> getMinAmount() {
return minAmount;
}
@ -611,7 +610,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
return minVolume;
}
protected void setMinAmount(Coin minAmount) {
protected void setMinAmount(BigInteger minAmount) {
this.minAmount.set(minAmount);
}
@ -635,46 +634,46 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
return useMarketBasedPrice;
}
ReadOnlyDoubleProperty getBuyerSecurityDeposit() {
return buyerSecurityDeposit;
ReadOnlyDoubleProperty getBuyerSecurityDepositPct() {
return buyerSecurityDepositPct;
}
protected Coin getBuyerSecurityDepositAsCoin() {
Coin percentOfAmountAsCoin = CoinUtil.getPercentOfAmountAsCoin(buyerSecurityDeposit.get(), amount.get());
return getBoundedBuyerSecurityDepositAsCoin(percentOfAmountAsCoin);
protected BigInteger getBuyerSecurityDeposit() {
BigInteger percentOfAmount = CoinUtil.getPercentOfAmount(buyerSecurityDepositPct.get(), amount.get());
return getBoundedBuyerSecurityDeposit(percentOfAmount);
}
private Coin getSellerSecurityDepositAsCoin() {
Coin amountAsCoin = this.amount.get();
if (amountAsCoin == null)
amountAsCoin = Coin.ZERO;
private BigInteger getSellerSecurityDeposit() {
BigInteger amount = this.amount.get();
if (amount == null)
amount = BigInteger.valueOf(0);
Coin percentOfAmountAsCoin = CoinUtil.getPercentOfAmountAsCoin(
createOfferService.getSellerSecurityDepositAsDouble(buyerSecurityDeposit.get()), amountAsCoin);
return getBoundedSellerSecurityDepositAsCoin(percentOfAmountAsCoin);
BigInteger percentOfAmount = CoinUtil.getPercentOfAmount(
createOfferService.getSellerSecurityDepositAsDouble(buyerSecurityDepositPct.get()), amount);
return getBoundedSellerSecurityDeposit(percentOfAmount);
}
protected Coin getBoundedBuyerSecurityDepositAsCoin(Coin value) {
protected BigInteger getBoundedBuyerSecurityDeposit(BigInteger value) {
// We need to ensure that for small amount values we don't get a too low BTC amount. We limit it with using the
// MinBuyerSecurityDepositAsCoin from Restrictions.
return Coin.valueOf(Math.max(Restrictions.getMinBuyerSecurityDepositAsCoin().value, value.value));
// MinBuyerSecurityDeposit from Restrictions.
return Restrictions.getMinBuyerSecurityDeposit().max(value);
}
private Coin getBoundedSellerSecurityDepositAsCoin(Coin value) {
private BigInteger getBoundedSellerSecurityDeposit(BigInteger value) {
// We need to ensure that for small amount values we don't get a too low BTC amount. We limit it with using the
// MinSellerSecurityDepositAsCoin from Restrictions.
return Coin.valueOf(Math.max(Restrictions.getMinSellerSecurityDepositAsCoin().value, value.value));
// MinSellerSecurityDeposit from Restrictions.
return Restrictions.getMinSellerSecurityDeposit().max(value);
}
ReadOnlyObjectProperty<Coin> totalToPayAsCoinProperty() {
return totalToPayAsCoin;
ReadOnlyObjectProperty<BigInteger> totalToPayAsProperty() {
return totalToPay;
}
public void setMarketPriceAvailable(boolean marketPriceAvailable) {
this.marketPriceAvailable = marketPriceAvailable;
}
public Coin getMakerFee() {
public BigInteger getMakerFee() {
return HavenoUtils.getMakerFee(amount.get());
}
@ -684,7 +683,7 @@ public abstract class MutableOfferDataModel extends OfferDataModel {
}
public boolean isMinBuyerSecurityDeposit() {
return !getBuyerSecurityDepositAsCoin().isGreaterThan(Restrictions.getMinBuyerSecurityDepositAsCoin());
return getBuyerSecurityDeposit().compareTo(Restrictions.getMinBuyerSecurityDeposit()) <= 0;
}
public void setTriggerPrice(long triggerPrice) {

View file

@ -48,6 +48,7 @@ import bisq.core.offer.OfferDirection;
import bisq.core.payment.FasterPaymentsAccount;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.trade.HavenoUtils;
import bisq.core.user.DontShowAgainLookup;
import bisq.core.user.Preferences;
import bisq.core.util.coin.CoinFormatter;
@ -58,8 +59,6 @@ import bisq.common.util.Tuple2;
import bisq.common.util.Tuple3;
import bisq.common.util.Utilities;
import org.bitcoinj.core.Coin;
import net.glxn.qrgen.QRCode;
import net.glxn.qrgen.image.ImageType;
@ -105,7 +104,7 @@ import javafx.util.StringConverter;
import java.net.URI;
import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -157,7 +156,7 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel<?>> exten
buyerSecurityDepositFocusedListener, priceFocusedListener, placeOfferCompletedListener,
priceAsPercentageFocusedListener, getShowWalletFundedNotificationListener,
isMinBuyerSecurityDepositListener, triggerPriceFocusedListener;
private ChangeListener<Coin> missingCoinListener;
private ChangeListener<BigInteger> missingCoinListener;
private ChangeListener<String> tradeCurrencyCodeListener, errorMessageListener,
marketPriceMarginListener, volumeListener, buyerSecurityDepositInBTCListener;
private ChangeListener<Number> marketPriceAvailableListener;
@ -248,7 +247,7 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel<?>> exten
onPaymentAccountsComboBoxSelected();
balanceTextField.setTargetAmount(model.getDataModel().totalToPayAsCoinProperty().get());
balanceTextField.setTargetAmount(model.getDataModel().totalToPayAsProperty().get());
updatePriceToggle();
Label popOverLabel = OfferViewUtil.createPopOverLabel(Res.get("createOffer.triggerPrice.tooltip"));
@ -331,7 +330,7 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel<?>> exten
// called from parent as the view does not get notified when the tab is closed
public void onClose() {
// we use model.placeOfferCompleted to not react on close which was triggered by a successful placeOffer
if (model.getDataModel().getBalance().get().isPositive() && !model.placeOfferCompleted.get()) {
if (model.getDataModel().getBalance().get().compareTo(BigInteger.valueOf(0)) > 0 && !model.placeOfferCompleted.get()) {
model.getDataModel().swapTradeToSavings();
}
}
@ -411,7 +410,7 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel<?>> exten
triggerPriceVBox.setVisible(false);
}
balanceTextField.setTargetAmount(model.getDataModel().totalToPayAsCoinProperty().get());
balanceTextField.setTargetAmount(model.getDataModel().totalToPayAsProperty().get());
// temporarily disabled due to high CPU usage (per issue #4649)
// waitingForFundsSpinner.play();
@ -550,7 +549,7 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel<?>> exten
volumeTextField.textProperty().bindBidirectional(model.volume);
volumeTextField.promptTextProperty().bind(model.volumePromptLabel);
totalToPayTextField.textProperty().bind(model.totalToPay);
addressTextField.amountAsCoinProperty().bind(model.getDataModel().getMissingCoin());
addressTextField.amountAsProperty().bind(model.getDataModel().getMissingCoin());
buyerSecurityDepositInputTextField.textProperty().bindBidirectional(model.buyerSecurityDeposit);
buyerSecurityDepositLabel.textProperty().bind(model.buyerSecurityDepositLabel);
tradeFeeInBtcLabel.textProperty().bind(model.tradeFeeInBtcWithFiat);
@ -598,7 +597,7 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel<?>> exten
volumeTextField.textProperty().unbindBidirectional(model.volume);
volumeTextField.promptTextProperty().unbindBidirectional(model.volume);
totalToPayTextField.textProperty().unbind();
addressTextField.amountAsCoinProperty().unbind();
addressTextField.amountAsProperty().unbind();
buyerSecurityDepositInputTextField.textProperty().unbindBidirectional(model.buyerSecurityDeposit);
buyerSecurityDepositLabel.textProperty().unbind();
tradeFeeInBtcLabel.textProperty().unbind();
@ -736,7 +735,7 @@ public abstract class MutableOfferView<M extends MutableOfferViewModel<?>> exten
if (newValue) {
Notification walletFundedNotification = new Notification()
.headLine(Res.get("notification.walletUpdate.headline"))
.notification(Res.get("notification.walletUpdate.msg", xmrFormatter.formatCoinWithCode(model.getDataModel().getTotalToPayAsCoin().get())))
.notification(Res.get("notification.walletUpdate.msg", HavenoUtils.formatToXmrWithCode(model.getDataModel().getTotalToPay().get())))
.autoClose();
walletFundedNotification.show();

View file

@ -41,7 +41,7 @@ import bisq.core.offer.OfferRestrictions;
import bisq.core.offer.OfferUtil;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.payment.validation.BtcValidator;
import bisq.core.payment.validation.XmrValidator;
import bisq.core.payment.validation.FiatVolumeValidator;
import bisq.core.payment.validation.SecurityDepositValidator;
import bisq.core.provider.price.MarketPrice;
@ -84,6 +84,7 @@ import javafx.beans.value.ChangeListener;
import javafx.util.Callback;
import java.math.BigInteger;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
@ -92,7 +93,7 @@ import static javafx.beans.binding.Bindings.createStringBinding;
@Slf4j
public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> extends ActivatableWithDataModel<M> {
private final BtcValidator btcValidator;
private final XmrValidator xmrValidator;
protected final SecurityDepositValidator securityDepositValidator;
protected final PriceFeedService priceFeedService;
private final AccountAgeWitnessService accountAgeWitnessService;
@ -163,8 +164,8 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
private ChangeListener<String> volumeStringListener;
private ChangeListener<String> securityDepositStringListener;
private ChangeListener<Coin> amountAsCoinListener;
private ChangeListener<Coin> minAmountAsCoinListener;
private ChangeListener<BigInteger> amountListener;
private ChangeListener<BigInteger> minAmountListener;
private ChangeListener<Price> priceListener;
private ChangeListener<Volume> volumeListener;
private ChangeListener<Number> securityDepositAsDoubleListener;
@ -190,7 +191,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
FiatVolumeValidator fiatVolumeValidator,
FiatPriceValidator fiatPriceValidator,
AltcoinValidator altcoinValidator,
BtcValidator btcValidator,
XmrValidator btcValidator,
SecurityDepositValidator securityDepositValidator,
PriceFeedService priceFeedService,
AccountAgeWitnessService accountAgeWitnessService,
@ -203,7 +204,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
this.fiatVolumeValidator = fiatVolumeValidator;
this.fiatPriceValidator = fiatPriceValidator;
this.altcoinValidator = altcoinValidator;
this.btcValidator = btcValidator;
this.xmrValidator = btcValidator;
this.securityDepositValidator = securityDepositValidator;
this.priceFeedService = priceFeedService;
this.accountAgeWitnessService = accountAgeWitnessService;
@ -271,10 +272,10 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
() -> Res.get("createOffer.volume.prompt", dataModel.getTradeCurrencyCode().get()),
dataModel.getTradeCurrencyCode()));
totalToPay.bind(createStringBinding(() -> btcFormatter.formatCoinWithCode(dataModel.totalToPayAsCoinProperty().get()),
dataModel.totalToPayAsCoinProperty()));
totalToPay.bind(createStringBinding(() -> HavenoUtils.formatToXmrWithCode(dataModel.totalToPayAsProperty().get()),
dataModel.totalToPayAsProperty()));
tradeAmount.bind(createStringBinding(() -> btcFormatter.formatCoinWithCode(dataModel.getAmount().get()),
tradeAmount.bind(createStringBinding(() -> HavenoUtils.formatToXmrWithCode(dataModel.getAmount().get()),
dataModel.getAmount()));
tradeCurrencyCode.bind(dataModel.getTradeCurrencyCode());
@ -298,7 +299,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
private void createListeners() {
amountStringListener = (ov, oldValue, newValue) -> {
if (!ignoreAmountStringListener) {
if (isBtcInputValid(newValue).isValid) {
if (isXmrInputValid(newValue).isValid) {
setAmountToModel();
dataModel.calculateVolume();
dataModel.calculateTotalToPay();
@ -308,7 +309,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
}
};
minAmountStringListener = (ov, oldValue, newValue) -> {
if (isBtcInputValid(newValue).isValid)
if (isXmrInputValid(newValue).isValid)
setMinAmountToModel();
updateButtonDisableState();
};
@ -431,10 +432,10 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
};
amountAsCoinListener = (ov, oldValue, newValue) -> {
amountListener = (ov, oldValue, newValue) -> {
if (newValue != null) {
amount.set(btcFormatter.formatCoin(newValue));
buyerSecurityDepositInBTC.set(btcFormatter.formatCoinWithCode(dataModel.getBuyerSecurityDepositAsCoin()));
amount.set(HavenoUtils.formatToXmr(newValue));
buyerSecurityDepositInBTC.set(HavenoUtils.formatToXmrWithCode(dataModel.getBuyerSecurityDeposit()));
} else {
amount.set("");
buyerSecurityDepositInBTC.set("");
@ -442,9 +443,9 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
applyMakerFee();
};
minAmountAsCoinListener = (ov, oldValue, newValue) -> {
minAmountListener = (ov, oldValue, newValue) -> {
if (newValue != null)
minAmount.set(btcFormatter.formatCoin(newValue));
minAmount.set(HavenoUtils.formatToXmr(newValue));
else
minAmount.set("");
};
@ -473,7 +474,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
if (newValue != null) {
buyerSecurityDeposit.set(FormattingUtils.formatToPercent((double) newValue));
if (dataModel.getAmount().get() != null) {
buyerSecurityDepositInBTC.set(btcFormatter.formatCoinWithCode(dataModel.getBuyerSecurityDepositAsCoin()));
buyerSecurityDepositInBTC.set(HavenoUtils.formatToXmrWithCode(dataModel.getBuyerSecurityDeposit()));
}
updateBuyerSecurityDeposit();
} else {
@ -498,13 +499,13 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
tradeFeeCurrencyCode.set(Res.getBaseCurrencyCode());
tradeFeeDescription.set(Res.get("createOffer.tradeFee.descriptionBTCOnly"));
Coin makerFeeAsCoin = dataModel.getMakerFee();
if (makerFeeAsCoin == null) {
BigInteger makerFee = dataModel.getMakerFee();
if (makerFee == null) {
return;
}
isTradeFeeVisible.setValue(true);
tradeFee.set(getFormatterForMakerFee().formatCoin(makerFeeAsCoin));
tradeFee.set(HavenoUtils.formatToXmr(makerFee));
tradeFeeInBtcWithFiat.set(OfferViewModelUtil.getTradeFeeWithFiatEquivalent(offerUtil,
dataModel.getMakerFee(),
btcFormatter));
@ -529,11 +530,11 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
buyerSecurityDeposit.addListener(securityDepositStringListener);
// Binding with Bindings.createObjectBinding does not work because of bi-directional binding
dataModel.getAmount().addListener(amountAsCoinListener);
dataModel.getMinAmount().addListener(minAmountAsCoinListener);
dataModel.getAmount().addListener(amountListener);
dataModel.getMinAmount().addListener(minAmountListener);
dataModel.getPrice().addListener(priceListener);
dataModel.getVolume().addListener(volumeListener);
dataModel.getBuyerSecurityDeposit().addListener(securityDepositAsDoubleListener);
dataModel.getBuyerSecurityDepositPct().addListener(securityDepositAsDoubleListener);
// dataModel.feeFromFundingTxProperty.addListener(feeFromFundingTxListener);
dataModel.getIsXmrWalletFunded().addListener(isWalletFundedListener);
@ -551,11 +552,11 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
buyerSecurityDeposit.removeListener(securityDepositStringListener);
// Binding with Bindings.createObjectBinding does not work because of bi-directional binding
dataModel.getAmount().removeListener(amountAsCoinListener);
dataModel.getMinAmount().removeListener(minAmountAsCoinListener);
dataModel.getAmount().removeListener(amountListener);
dataModel.getMinAmount().removeListener(minAmountListener);
dataModel.getPrice().removeListener(priceListener);
dataModel.getVolume().removeListener(volumeListener);
dataModel.getBuyerSecurityDeposit().removeListener(securityDepositAsDoubleListener);
dataModel.getBuyerSecurityDepositPct().removeListener(securityDepositAsDoubleListener);
//dataModel.feeFromFundingTxProperty.removeListener(feeFromFundingTxListener);
dataModel.getIsXmrWalletFunded().removeListener(isWalletFundedListener);
@ -574,9 +575,9 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
boolean initWithData(OfferDirection direction, TradeCurrency tradeCurrency) {
boolean result = dataModel.initWithData(direction, tradeCurrency);
if (dataModel.paymentAccount != null)
btcValidator.setMaxValue(dataModel.paymentAccount.getPaymentMethod().getMaxTradeLimitAsCoin(dataModel.getTradeCurrencyCode().get()));
btcValidator.setMaxTradeLimit(Coin.valueOf(dataModel.getMaxTradeLimit()));
btcValidator.setMinValue(Restrictions.getMinTradeAmount());
xmrValidator.setMaxValue(dataModel.paymentAccount.getPaymentMethod().getMaxTradeLimit(dataModel.getTradeCurrencyCode().get()));
xmrValidator.setMaxTradeLimit(BigInteger.valueOf(dataModel.getMaxTradeLimit()));
xmrValidator.setMinValue(Restrictions.getMinTradeAmount());
final boolean isBuy = dataModel.getDirection() == OfferDirection.BUY;
@ -592,7 +593,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
securityDepositValidator.setPaymentAccount(dataModel.paymentAccount);
validateAndSetBuyerSecurityDepositToModel();
buyerSecurityDeposit.set(FormattingUtils.formatToPercent(dataModel.getBuyerSecurityDeposit().get()));
buyerSecurityDeposit.set(FormattingUtils.formatToPercent(dataModel.getBuyerSecurityDepositPct().get()));
buyerSecurityDepositLabel.set(getSecurityDepositLabel());
applyMakerFee();
@ -630,10 +631,10 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
public void onPaymentAccountSelected(PaymentAccount paymentAccount) {
dataModel.onPaymentAccountSelected(paymentAccount);
if (amount.get() != null)
amountValidationResult.set(isBtcInputValid(amount.get()));
amountValidationResult.set(isXmrInputValid(amount.get()));
btcValidator.setMaxValue(dataModel.paymentAccount.getPaymentMethod().getMaxTradeLimitAsCoin(dataModel.getTradeCurrencyCode().get()));
btcValidator.setMaxTradeLimit(Coin.valueOf(dataModel.getMaxTradeLimit()));
xmrValidator.setMaxValue(dataModel.paymentAccount.getPaymentMethod().getMaxTradeLimit(dataModel.getTradeCurrencyCode().get()));
xmrValidator.setMaxTradeLimit(BigInteger.valueOf(dataModel.getMaxTradeLimit()));
maybeShowMakeOfferToUnsignedAccountWarning();
securityDepositValidator.setPaymentAccount(paymentAccount);
@ -659,8 +660,8 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
updateButtonDisableState();
} else {
new Popup().warning(Res.get("shared.notEnoughFunds",
btcFormatter.formatCoinWithCode(dataModel.totalToPayAsCoinProperty().get()),
btcFormatter.formatCoinWithCode(dataModel.getTotalBalance())))
HavenoUtils.formatToXmrWithCode(dataModel.totalToPayAsProperty().get()),
HavenoUtils.formatToXmrWithCode(dataModel.getTotalBalance())))
.actionButtonTextWithGoTo("navigation.funds.depositFunds")
.onAction(() -> navigation.navigateTo(MainView.class, FundsView.class, DepositView.class))
.show();
@ -675,12 +676,15 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
// On focus out we do validation and apply the data to the model
void onFocusOutAmountTextField(boolean oldValue, boolean newValue) {
if (oldValue && !newValue) {
InputValidator.ValidationResult result = isBtcInputValid(amount.get());
System.out.println("Checking if input valid: " + amount.get());
InputValidator.ValidationResult result = isXmrInputValid(amount.get());
amountValidationResult.set(result);
System.out.println("Result is valid: " + result.isValid);
System.out.println("Result error: " + result.errorMessage);
if (result.isValid) {
setAmountToModel();
ignoreAmountStringListener = true;
amount.set(btcFormatter.formatCoin(dataModel.getAmount().get()));
amount.set(HavenoUtils.formatToXmr(dataModel.getAmount().get()));
ignoreAmountStringListener = false;
dataModel.calculateVolume();
@ -690,12 +694,12 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
amountValidationResult.set(result);
if (minAmount.get() != null)
minAmountValidationResult.set(isBtcInputValid(minAmount.get()));
} else if (amount.get() != null && btcValidator.getMaxTradeLimit() != null && btcValidator.getMaxTradeLimit().value == OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.value) {
amount.set(btcFormatter.formatCoin(btcValidator.getMaxTradeLimit()));
minAmountValidationResult.set(isXmrInputValid(minAmount.get()));
} else if (amount.get() != null && xmrValidator.getMaxTradeLimit() != null && xmrValidator.getMaxTradeLimit().longValueExact() == OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.longValueExact()) {
amount.set(HavenoUtils.formatToXmr(xmrValidator.getMaxTradeLimit()));
boolean isBuy = dataModel.getDirection() == OfferDirection.BUY;
new Popup().information(Res.get(isBuy ? "popup.warning.tradeLimitDueAccountAgeRestriction.buyer" : "popup.warning.tradeLimitDueAccountAgeRestriction.seller",
btcFormatter.formatCoinWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT),
HavenoUtils.formatToXmrWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT),
Res.get("offerbook.warning.newVersionAnnouncement")))
.width(900)
.show();
@ -714,11 +718,11 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
public void onFocusOutMinAmountTextField(boolean oldValue, boolean newValue) {
if (oldValue && !newValue) {
InputValidator.ValidationResult result = isBtcInputValid(minAmount.get());
InputValidator.ValidationResult result = isXmrInputValid(minAmount.get());
minAmountValidationResult.set(result);
if (result.isValid) {
Coin minAmountAsCoin = dataModel.getMinAmount().get();
syncMinAmountWithAmount = minAmountAsCoin != null && minAmountAsCoin.equals(dataModel.getAmount().get());
BigInteger minAmount = dataModel.getMinAmount().get();
syncMinAmountWithAmount = minAmount != null && minAmount.equals(dataModel.getAmount().get());
setMinAmountToModel();
dataModel.calculateMinVolume();
@ -732,14 +736,14 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
updateButtonDisableState();
}
this.minAmount.set(btcFormatter.formatCoin(minAmountAsCoin));
this.minAmount.set(HavenoUtils.formatToXmr(minAmount));
if (!dataModel.isMinAmountLessOrEqualAmount()) {
this.amount.set(this.minAmount.get());
} else {
minAmountValidationResult.set(result);
if (this.amount.get() != null)
amountValidationResult.set(isBtcInputValid(this.amount.get()));
amountValidationResult.set(isXmrInputValid(this.amount.get()));
}
} else {
syncMinAmountWithAmount = true;
@ -864,12 +868,12 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
minAmount.set(amount.getValue());
} else {
if (amount.get() != null)
amountValidationResult.set(isBtcInputValid(amount.get()));
amountValidationResult.set(isXmrInputValid(amount.get()));
// We only check minAmountValidationResult if amountValidationResult is valid, otherwise we would get
// triggered a close of the popup when the minAmountValidationResult is applied
if (amountValidationResult.getValue() != null && amountValidationResult.getValue().isValid && minAmount.get() != null)
minAmountValidationResult.set(isBtcInputValid(minAmount.get()));
minAmountValidationResult.set(isXmrInputValid(minAmount.get()));
}
}
@ -899,7 +903,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
.onAction(() -> {
dataModel.setBuyerSecurityDeposit(defaultSecurityDeposit);
ignoreSecurityDepositStringListener = true;
buyerSecurityDeposit.set(FormattingUtils.formatToPercent(dataModel.getBuyerSecurityDeposit().get()));
buyerSecurityDeposit.set(FormattingUtils.formatToPercent(dataModel.getBuyerSecurityDepositPct().get()));
ignoreSecurityDepositStringListener = false;
})
.closeButtonText(Res.get("createOffer.useLowerValue"))
@ -916,7 +920,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
private void applyBuyerSecurityDepositOnFocusOut() {
setBuyerSecurityDepositToModel();
ignoreSecurityDepositStringListener = true;
buyerSecurityDeposit.set(FormattingUtils.formatToPercent(dataModel.getBuyerSecurityDeposit().get()));
buyerSecurityDeposit.set(FormattingUtils.formatToPercent(dataModel.getBuyerSecurityDepositPct().get()));
ignoreSecurityDepositStringListener = false;
}
@ -985,12 +989,12 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
dataModel.getSecurityDeposit(),
dataModel.getAmount().get(),
btcFormatter,
Restrictions.getMinBuyerSecurityDepositAsCoin()
Restrictions.getMinBuyerSecurityDeposit()
);
}
public String getSecurityDepositWithCode() {
return btcFormatter.formatCoinWithCode(dataModel.getSecurityDeposit());
return HavenoUtils.formatToXmrWithCode(dataModel.getSecurityDeposit());
}
@ -1003,13 +1007,13 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
}
public String getMakerFeePercentage() {
final Coin makerFeeAsCoin = dataModel.getMakerFee();
return GUIUtil.getPercentage(makerFeeAsCoin, dataModel.getAmount().get());
final BigInteger makerFee = dataModel.getMakerFee();
return GUIUtil.getPercentage(makerFee, dataModel.getAmount().get());
}
public String getTotalToPayInfo() {
return OfferViewModelUtil.getTradeFeeWithFiatEquivalent(offerUtil,
dataModel.totalToPayAsCoin.get(),
dataModel.totalToPay.get(),
btcFormatter);
}
@ -1083,7 +1087,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
private void setAmountToModel() {
if (amount.get() != null && !amount.get().isEmpty()) {
Coin amount = DisplayUtils.parseToCoinWith4Decimals(this.amount.get(), btcFormatter);
BigInteger amount = HavenoUtils.coinToAtomicUnits(DisplayUtils.parseToCoinWith4Decimals(this.amount.get(), btcFormatter));
long maxTradeLimit = dataModel.getMaxTradeLimit();
Price price = dataModel.getPrice().get();
@ -1107,7 +1111,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
private void setMinAmountToModel() {
if (minAmount.get() != null && !minAmount.get().isEmpty()) {
Coin minAmount = DisplayUtils.parseToCoinWith4Decimals(this.minAmount.get(), btcFormatter);
BigInteger minAmount = HavenoUtils.coinToAtomicUnits(DisplayUtils.parseToCoinWith4Decimals(this.minAmount.get(), btcFormatter));
Price price = dataModel.getPrice().get();
long maxTradeLimit = dataModel.getMaxTradeLimit();
@ -1158,7 +1162,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
private void validateAndSetBuyerSecurityDepositToModel() {
// If the security deposit in the model is not valid percent
String value = FormattingUtils.formatToPercent(dataModel.getBuyerSecurityDeposit().get());
String value = FormattingUtils.formatToPercent(dataModel.getBuyerSecurityDepositPct().get());
if (!securityDepositValidator.validate(value).isValid) {
dataModel.setBuyerSecurityDeposit(Restrictions.getDefaultBuyerSecurityDepositAsPercent());
}
@ -1168,15 +1172,15 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
if (!makeOfferFromUnsignedAccountWarningDisplayed &&
dataModel.getDirection() == OfferDirection.SELL &&
PaymentMethod.hasChargebackRisk(dataModel.getPaymentAccount().getPaymentMethod(), dataModel.getTradeCurrency().getCode())) {
Coin checkAmount = dataModel.getMinAmount().get() == null ? dataModel.getAmount().get() : dataModel.getMinAmount().get();
if (checkAmount != null && !checkAmount.isGreaterThan(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT)) {
BigInteger checkAmount = dataModel.getMinAmount().get() == null ? dataModel.getAmount().get() : dataModel.getMinAmount().get();
if (checkAmount != null && checkAmount.compareTo(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT) <= 0) {
makeOfferFromUnsignedAccountWarningDisplayed = true;
}
}
}
private InputValidator.ValidationResult isBtcInputValid(String input) {
return btcValidator.validate(input);
private InputValidator.ValidationResult isXmrInputValid(String input) {
return xmrValidator.validate("" + HavenoUtils.atomicUnitsToXmr(HavenoUtils.parseXmr(input)));
}
private InputValidator.ValidationResult isPriceInputValid(String input) {
@ -1219,16 +1223,16 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
if (dataModel.isMinBuyerSecurityDeposit()) {
buyerSecurityDepositLabel.set(Res.get("createOffer.minSecurityDepositUsed"));
buyerSecurityDeposit.set(btcFormatter.formatCoin(Restrictions.getMinBuyerSecurityDepositAsCoin()));
buyerSecurityDeposit.set(HavenoUtils.formatToXmr(Restrictions.getMinBuyerSecurityDeposit()));
} else {
buyerSecurityDepositLabel.set(getSecurityDepositLabel());
buyerSecurityDeposit.set(FormattingUtils.formatToPercent(dataModel.getBuyerSecurityDeposit().get()));
buyerSecurityDeposit.set(FormattingUtils.formatToPercent(dataModel.getBuyerSecurityDepositPct().get()));
}
}
void updateButtonDisableState() {
boolean inputDataValid = isBtcInputValid(amount.get()).isValid &&
isBtcInputValid(minAmount.get()).isValid &&
boolean inputDataValid = isXmrInputValid(amount.get()).isValid &&
isXmrInputValid(minAmount.get()).isValid &&
isPriceInputValid(price.get()).isValid &&
dataModel.getPrice().get() != null &&
dataModel.getPrice().get().getValue() != 0 &&
@ -1249,10 +1253,6 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
isPlaceOfferButtonDisabled.set(createOfferRequested || !inputDataValid || !dataModel.getIsXmrWalletFunded().get());
}
private CoinFormatter getFormatterForMakerFee() {
return btcFormatter;
}
private void updateMarketPriceToManual() {
final String currencyCode = dataModel.getTradeCurrencyCode().get();
MarketPrice marketPrice = priceFeedService.getMarketPrice(currencyCode);

View file

@ -23,8 +23,6 @@ import bisq.core.btc.model.XmrAddressEntry;
import bisq.core.btc.wallet.XmrWalletService;
import bisq.core.offer.OfferUtil;
import org.bitcoinj.core.Coin;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
@ -32,7 +30,7 @@ import javafx.beans.property.SimpleObjectProperty;
import lombok.Getter;
import static bisq.core.util.coin.CoinUtil.minCoin;
import java.math.BigInteger;
/**
* Domain for that UI element.
@ -48,19 +46,19 @@ public abstract class OfferDataModel extends ActivatableDataModel {
@Getter
protected final BooleanProperty isXmrWalletFunded = new SimpleBooleanProperty();
@Getter
protected final ObjectProperty<Coin> totalToPayAsCoin = new SimpleObjectProperty<>();
protected final ObjectProperty<BigInteger> totalToPay = new SimpleObjectProperty<>();
@Getter
protected final ObjectProperty<Coin> balance = new SimpleObjectProperty<>();
protected final ObjectProperty<BigInteger> balance = new SimpleObjectProperty<>();
@Getter
protected final ObjectProperty<Coin> availableBalance = new SimpleObjectProperty<>();
protected final ObjectProperty<BigInteger> availableBalance = new SimpleObjectProperty<>();
@Getter
protected final ObjectProperty<Coin> missingCoin = new SimpleObjectProperty<>(Coin.ZERO);
protected final ObjectProperty<BigInteger> missingCoin = new SimpleObjectProperty<>(BigInteger.valueOf(0));
@Getter
protected final BooleanProperty showWalletFundedNotification = new SimpleBooleanProperty();
@Getter
protected Coin totalBalance;
protected BigInteger totalBalance;
@Getter
protected Coin totalAvailableBalance;
protected BigInteger totalAvailableBalance;
protected XmrAddressEntry addressEntry;
protected boolean useSavingsWallet;
@ -70,37 +68,37 @@ public abstract class OfferDataModel extends ActivatableDataModel {
}
protected void updateBalance() {
Coin tradeWalletBalance = xmrWalletService.getBalanceForSubaddress(addressEntry.getSubaddressIndex());
BigInteger tradeWalletBalance = xmrWalletService.getBalanceForSubaddress(addressEntry.getSubaddressIndex());
if (useSavingsWallet) {
Coin walletBalance = xmrWalletService.getBalance();
BigInteger walletBalance = xmrWalletService.getBalance();
totalBalance = walletBalance.add(tradeWalletBalance);
if (totalToPayAsCoin.get() != null) {
balance.set(minCoin(totalToPayAsCoin.get(), totalBalance));
if (totalToPay.get() != null) {
balance.set(totalToPay.get().min(totalBalance));
}
} else {
balance.set(tradeWalletBalance);
}
missingCoin.set(offerUtil.getBalanceShortage(totalToPayAsCoin.get(), balance.get()));
isXmrWalletFunded.set(offerUtil.isBalanceSufficient(totalToPayAsCoin.get(), balance.get()));
if (totalToPayAsCoin.get() != null && isXmrWalletFunded.get() && !showWalletFundedNotification.get()) {
missingCoin.set(offerUtil.getBalanceShortage(totalToPay.get(), balance.get()));
isXmrWalletFunded.set(offerUtil.isBalanceSufficient(totalToPay.get(), balance.get()));
if (totalToPay.get() != null && isXmrWalletFunded.get() && !showWalletFundedNotification.get()) {
showWalletFundedNotification.set(true);
}
}
protected void updateAvailableBalance() {
Coin tradeWalletBalance = xmrWalletService.getAvailableBalanceForSubaddress(addressEntry.getSubaddressIndex());
BigInteger tradeWalletBalance = xmrWalletService.getAvailableBalanceForSubaddress(addressEntry.getSubaddressIndex());
if (useSavingsWallet) {
Coin walletAvailableBalance = xmrWalletService.getAvailableBalance();
BigInteger walletAvailableBalance = xmrWalletService.getAvailableBalance();
totalAvailableBalance = walletAvailableBalance.add(tradeWalletBalance);
if (totalToPayAsCoin.get() != null) {
availableBalance.set(minCoin(totalToPayAsCoin.get(), totalAvailableBalance));
if (totalToPay.get() != null) {
availableBalance.set(totalToPay.get().min(totalAvailableBalance));
}
} else {
availableBalance.set(tradeWalletBalance);
}
missingCoin.set(offerUtil.getBalanceShortage(totalToPayAsCoin.get(), availableBalance.get()));
isXmrWalletFunded.set(offerUtil.isBalanceSufficient(totalToPayAsCoin.get(), availableBalance.get()));
if (totalToPayAsCoin.get() != null && isXmrWalletFunded.get() && !showWalletFundedNotification.get()) {
missingCoin.set(offerUtil.getBalanceShortage(totalToPay.get(), availableBalance.get()));
isXmrWalletFunded.set(offerUtil.isBalanceSufficient(totalToPay.get(), availableBalance.get()));
if (totalToPay.get() != null && isXmrWalletFunded.get() && !showWalletFundedNotification.get()) {
showWalletFundedNotification.set(true);
}
}

View file

@ -23,19 +23,17 @@ import bisq.desktop.util.GUIUtil;
import bisq.core.locale.Res;
import bisq.core.monetary.Volume;
import bisq.core.offer.OfferUtil;
import bisq.core.trade.HavenoUtils;
import bisq.core.util.VolumeUtil;
import bisq.core.util.coin.CoinFormatter;
import bisq.common.app.DevEnv;
import org.bitcoinj.core.Coin;
import java.math.BigInteger;
import java.util.Optional;
// Shared utils for ViewModels
public class OfferViewModelUtil {
public static String getTradeFeeWithFiatEquivalent(OfferUtil offerUtil,
Coin tradeFee,
BigInteger tradeFee,
CoinFormatter formatter) {
Optional<Volume> optionalBtcFeeInFiat = offerUtil.getFeeInUserFiatCurrency(tradeFee,
@ -45,13 +43,13 @@ public class OfferViewModelUtil {
}
public static String getTradeFeeWithFiatEquivalentAndPercentage(OfferUtil offerUtil,
Coin tradeFee,
Coin tradeAmount,
BigInteger tradeFee,
BigInteger tradeAmount,
CoinFormatter formatter,
Coin minTradeFee) {
String feeAsBtc = formatter.formatCoinWithCode(tradeFee);
BigInteger minTradeFee) {
String feeAsBtc = HavenoUtils.formatToXmrWithCode(tradeFee);
String percentage;
if (!tradeFee.isGreaterThan(minTradeFee)) {
if (tradeFee.compareTo(minTradeFee) <= 0) {
percentage = Res.get("guiUtil.requiredMinimum")
.replace("(", "")
.replace(")", "");

View file

@ -22,7 +22,7 @@ import bisq.desktop.common.model.ViewModel;
import bisq.desktop.main.offer.MutableOfferViewModel;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.offer.OfferUtil;
import bisq.core.payment.validation.BtcValidator;
import bisq.core.payment.validation.XmrValidator;
import bisq.core.payment.validation.FiatVolumeValidator;
import bisq.core.payment.validation.SecurityDepositValidator;
import bisq.core.provider.price.PriceFeedService;
@ -42,7 +42,7 @@ class CreateOfferViewModel extends MutableOfferViewModel<CreateOfferDataModel> i
FiatVolumeValidator fiatVolumeValidator,
FiatPriceValidator fiatPriceValidator,
AltcoinValidator altcoinValidator,
BtcValidator btcValidator,
XmrValidator btcValidator,
SecurityDepositValidator securityDepositValidator,
PriceFeedService priceFeedService,
AccountAgeWitnessService accountAgeWitnessService,

View file

@ -61,6 +61,7 @@ import bisq.core.offer.OfferRestrictions;
import bisq.core.offer.OpenOffer;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.trade.HavenoUtils;
import bisq.core.user.DontShowAgainLookup;
import bisq.core.util.coin.CoinFormatter;
@ -110,6 +111,8 @@ import javafx.collections.ListChangeListener;
import javafx.util.Callback;
import javafx.util.StringConverter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Comparator;
import java.util.Map;
import java.util.Optional;
@ -299,15 +302,15 @@ abstract public class OfferBookView<R extends GridPane, M extends OfferBookViewM
avatarColumn.setComparator(Comparator.comparing(o -> model.getNumTrades(o.getOffer())));
depositColumn.setComparator(Comparator.comparing(item -> {
boolean isSellOffer = item.getOffer().getDirection() == OfferDirection.SELL;
Coin deposit = isSellOffer ?
BigInteger deposit = isSellOffer ?
item.getOffer().getBuyerSecurityDeposit() :
item.getOffer().getSellerSecurityDeposit();
double amountValue = item.getOffer().getAmount().getValue();
long amountValue = item.getOffer().getAmount().longValueExact();
if ((deposit == null || amountValue == 0)) {
return 0d;
} else {
return deposit.getValue() / amountValue;
return BigDecimal.valueOf(deposit.longValueExact()).divide(BigDecimal.valueOf(amountValue)).doubleValue();
}
}, Comparator.nullsFirst(Comparator.naturalOrder())));
@ -715,7 +718,7 @@ abstract public class OfferBookView<R extends GridPane, M extends OfferBookViewM
if (model.isBootstrappedOrShowPopup()) {
String key = "RemoveOfferWarning";
if (DontShowAgainLookup.showAgain(key)) {
String message = offer.getMakerFee().isPositive() ?
String message = offer.getMakerFee().compareTo(BigInteger.valueOf(0)) > 0 ?
Res.get("popup.warning.removeOffer", model.getMakerFeeAsString(offer)) :
Res.get("popup.warning.removeNoFeeOffer");
new Popup().warning(message)
@ -1034,7 +1037,7 @@ abstract public class OfferBookView<R extends GridPane, M extends OfferBookViewM
} else {
setText("");
setGraphic(new ColoredDecimalPlacesWithZerosText(model.formatDepositString(
deposit, item.getOffer().getAmount().getValue()),
deposit, item.getOffer().getAmount().longValueExact()),
GUIUtil.AMOUNT_DECIMALS_WITH_ZEROS));
}
} else {
@ -1186,7 +1189,7 @@ abstract public class OfferBookView<R extends GridPane, M extends OfferBookViewM
Res.get("offerbook.timeSinceSigning"),
Res.get("offerbook.timeSinceSigning.help",
SignedWitnessService.SIGNER_AGE_DAYS,
formatter.formatCoinWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT))) {
HavenoUtils.formatToXmrWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT))) {
{
setMinWidth(60);
setSortable(true);
@ -1206,7 +1209,7 @@ abstract public class OfferBookView<R extends GridPane, M extends OfferBookViewM
if (item != null && !empty) {
var witnessAgeData = item.getWitnessAgeData(accountAgeWitnessService, signedWitnessService);
var label = witnessAgeData.isSigningRequired()
? new AccountStatusTooltipLabel(witnessAgeData, formatter)
? new AccountStatusTooltipLabel(witnessAgeData)
: new InfoAutoTooltipLabel(witnessAgeData.getDisplayString(), witnessAgeData.getIcon(), ContentDisplay.RIGHT, witnessAgeData.getInfo());
setGraphic(label);
} else {

View file

@ -47,6 +47,7 @@ import bisq.core.payment.PaymentAccountUtil;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.provider.price.PriceFeedService;
import bisq.core.trade.ClosedTradableManager;
import bisq.core.trade.HavenoUtils;
import bisq.core.trade.Trade;
import bisq.core.user.Preferences;
import bisq.core.user.User;
@ -61,8 +62,6 @@ import bisq.network.p2p.P2PService;
import bisq.common.handlers.ErrorMessageHandler;
import bisq.common.handlers.ResultHandler;
import org.bitcoinj.core.Coin;
import com.google.common.base.Joiner;
import javafx.beans.property.BooleanProperty;
@ -78,6 +77,8 @@ import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.util.Comparator;
@ -181,7 +182,7 @@ abstract class OfferBookViewModel extends ActivatableViewModel {
filterItemsListener = c -> {
final Optional<OfferBookListItem> highestAmountOffer = filteredItems.stream()
.max(Comparator.comparingLong(o -> o.getOffer().getAmount().getValue()));
.max(Comparator.comparingLong(o -> o.getOffer().getAmount().longValueExact()));
final boolean containsRangeAmount = filteredItems.stream().anyMatch(o -> o.getOffer().isRange());
@ -196,7 +197,6 @@ abstract class OfferBookViewModel extends ActivatableViewModel {
maxPlacesForAmount.set(formatAmount(item.getOffer(), false).length());
maxPlacesForVolume.set(formatVolume(item.getOffer(), false).length());
}
}
final Optional<OfferBookListItem> highestPriceOffer = filteredItems.stream()
@ -627,7 +627,7 @@ abstract class OfferBookViewModel extends ActivatableViewModel {
}
public String getMakerFeeAsString(Offer offer) {
return btcFormatter.formatCoinWithCode(offer.getMakerFee());
return HavenoUtils.formatToXmrWithCode(offer.getMakerFee());
}
private static String getDirectionWithCodeDetailed(OfferDirection direction, String currencyCode) {
@ -637,9 +637,9 @@ abstract class OfferBookViewModel extends ActivatableViewModel {
return (direction == OfferDirection.SELL) ? Res.get("shared.buyingCurrency", currencyCode) : Res.get("shared.sellingCurrency", currencyCode);
}
public String formatDepositString(Coin deposit, long amount) {
var percentage = FormattingUtils.formatToRoundedPercentWithSymbol(deposit.getValue() / (double) amount);
return btcFormatter.formatCoin(deposit) + " (" + percentage + ")";
public String formatDepositString(BigInteger deposit, long amount) {
var percentage = FormattingUtils.formatToRoundedPercentWithSymbol(BigDecimal.valueOf(deposit.longValueExact()).divide(BigDecimal.valueOf(amount)).doubleValue());
return HavenoUtils.formatToXmr(deposit) + " (" + percentage + ")";
}
PaymentMethod getShowAllEntryForPaymentMethod() {

View file

@ -26,7 +26,6 @@ import bisq.common.handlers.ErrorMessageHandler;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.btc.listeners.XmrBalanceListener;
import bisq.core.btc.model.XmrAddressEntry;
import bisq.core.btc.wallet.Restrictions;
import bisq.core.btc.wallet.XmrWalletService;
import bisq.core.filter.FilterManager;
import bisq.core.locale.CurrencyUtil;
@ -47,12 +46,9 @@ import bisq.core.trade.handlers.TradeResultHandler;
import bisq.core.user.Preferences;
import bisq.core.user.User;
import bisq.core.util.VolumeUtil;
import bisq.core.util.coin.CoinUtil;
import bisq.network.p2p.P2PService;
import org.bitcoinj.core.Coin;
import com.google.inject.Inject;
import javafx.beans.property.IntegerProperty;
@ -94,13 +90,13 @@ class TakeOfferDataModel extends OfferDataModel {
private final Navigation navigation;
private final P2PService p2PService;
private Coin securityDeposit;
private BigInteger securityDeposit;
private Offer offer;
// final BooleanProperty isFeeFromFundingTxSufficient = new SimpleBooleanProperty();
// final BooleanProperty isMainNet = new SimpleBooleanProperty();
private final ObjectProperty<Coin> amount = new SimpleObjectProperty<>();
private final ObjectProperty<BigInteger> amount = new SimpleObjectProperty<>();
final ObjectProperty<Volume> volume = new SimpleObjectProperty<>();
private XmrBalanceListener balanceListener;
@ -198,7 +194,7 @@ class TakeOfferDataModel extends OfferDataModel {
checkArgument(!possiblePaymentAccounts.isEmpty(), "possiblePaymentAccounts.isEmpty()");
paymentAccount = getLastSelectedPaymentAccount();
this.amount.set(Coin.valueOf(Math.min(offer.getAmount().value, getMaxTradeLimit())));
this.amount.set(offer.getAmount().min(BigInteger.valueOf(getMaxTradeLimit())));
securityDeposit = offer.getDirection() == OfferDirection.SELL ?
getBuyerSecurityDeposit() :
@ -263,7 +259,7 @@ class TakeOfferDataModel extends OfferDataModel {
void onTakeOffer(TradeResultHandler tradeResultHandler, ErrorMessageHandler errorMessageHandler) {
checkNotNull(getTakerFee(), "takerFee must not be null");
Coin fundsNeededForTrade = getFundsNeededForTrade();
BigInteger fundsNeededForTrade = getFundsNeededForTrade();
if (isBuyOffer())
fundsNeededForTrade = fundsNeededForTrade.add(amount.get());
@ -301,7 +297,7 @@ class TakeOfferDataModel extends OfferDataModel {
this.paymentAccount = paymentAccount;
long myLimit = getMaxTradeLimit();
this.amount.set(Coin.valueOf(Math.max(offer.getMinAmount().value, Math.min(amount.get().value, myLimit))));
this.amount.set(offer.getMinAmount().max(amount.get().min(BigInteger.valueOf(myLimit))));
preferences.setTakeOfferSelectedPaymentAccountId(paymentAccount.getId());
}
@ -385,7 +381,7 @@ class TakeOfferDataModel extends OfferDataModel {
void calculateVolume() {
if (tradePrice != null && offer != null &&
amount.get() != null &&
!amount.get().isZero()) {
amount.get().compareTo(BigInteger.valueOf(0)) != 0) {
Volume volumeByAmount = tradePrice.getVolumeByAmount(amount.get());
if (offer.getPaymentMethod().getId().equals(PaymentMethod.HAL_CASH_ID))
volumeByAmount = VolumeUtil.getAdjustedVolumeForHalCash(volumeByAmount);
@ -398,8 +394,8 @@ class TakeOfferDataModel extends OfferDataModel {
}
}
void applyAmount(Coin amount) {
this.amount.set(Coin.valueOf(Math.min(amount.value, getMaxTradeLimit())));
void applyAmount(BigInteger amount) {
this.amount.set(amount.min(BigInteger.valueOf(getMaxTradeLimit())));
calculateTotalToPay();
}
@ -408,15 +404,15 @@ class TakeOfferDataModel extends OfferDataModel {
// Taker pays 2 times the tx fee because the mining fee might be different when maker created the offer
// and reserved his funds, so that would not work well with dynamic fees.
// The mining fee for the takeOfferFee tx is deducted from the createOfferFee and not visible to the trader
final Coin takerFee = getTakerFee();
final BigInteger takerFee = getTakerFee();
if (offer != null && amount.get() != null && takerFee != null) {
Coin feeAndSecDeposit = securityDeposit.add(takerFee);
BigInteger feeAndSecDeposit = securityDeposit.add(takerFee);
if (isBuyOffer())
totalToPayAsCoin.set(feeAndSecDeposit.add(amount.get()));
totalToPay.set(feeAndSecDeposit.add(amount.get()));
else
totalToPayAsCoin.set(feeAndSecDeposit);
totalToPay.set(feeAndSecDeposit);
updateAvailableBalance();
log.debug("totalToPayAsCoin {}", totalToPayAsCoin.get().toFriendlyString());
log.debug("totalToPay {}", totalToPay.get());
}
}
@ -433,7 +429,7 @@ class TakeOfferDataModel extends OfferDataModel {
}
@Nullable
Coin getTakerFee() {
BigInteger getTakerFee() {
return HavenoUtils.getTakerFee(this.amount.get());
}
@ -450,33 +446,22 @@ class TakeOfferDataModel extends OfferDataModel {
boolean isMinAmountLessOrEqualAmount() {
//noinspection SimplifiableIfStatement
if (offer != null && amount.get() != null)
return !offer.getMinAmount().isGreaterThan(amount.get());
return offer.getMinAmount().compareTo(amount.get()) <= 0;
return true;
}
boolean isAmountLargerThanOfferAmount() {
//noinspection SimplifiableIfStatement
if (amount.get() != null && offer != null)
return amount.get().isGreaterThan(offer.getAmount());
return amount.get().compareTo(offer.getAmount()) > 0;
return true;
}
boolean wouldCreateDustForMaker() {
//noinspection SimplifiableIfStatement
boolean result;
if (amount.get() != null && offer != null) {
Coin customAmount = offer.getAmount().subtract(amount.get());
result = customAmount.isPositive() && customAmount.isLessThan(Restrictions.getMinNonDustOutput());
if (result)
log.info("would create dust for maker, customAmount={}, Restrictions.getMinNonDustOutput()={}", customAmount, Restrictions.getMinNonDustOutput());
} else {
result = true;
}
return result;
return false; // TODO: update for XMR?
}
ReadOnlyObjectProperty<Coin> getAmount() {
ReadOnlyObjectProperty<BigInteger> getAmount() {
return amount;
}
@ -493,7 +478,7 @@ class TakeOfferDataModel extends OfferDataModel {
}
@NotNull
private Coin getFundsNeededForTrade() {
private BigInteger getFundsNeededForTrade() {
return getSecurityDeposit();
}
@ -501,15 +486,15 @@ class TakeOfferDataModel extends OfferDataModel {
return addressEntry;
}
public Coin getSecurityDeposit() {
public BigInteger getSecurityDeposit() {
return securityDeposit;
}
public Coin getBuyerSecurityDeposit() {
public BigInteger getBuyerSecurityDeposit() {
return offer.getBuyerSecurityDeposit();
}
public Coin getSellerSecurityDeposit() {
public BigInteger getSellerSecurityDeposit() {
return offer.getSellerSecurityDeposit();
}

View file

@ -54,6 +54,7 @@ import bisq.core.offer.Offer;
import bisq.core.payment.FasterPaymentsAccount;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.trade.HavenoUtils;
import bisq.core.user.DontShowAgainLookup;
import bisq.core.util.FormattingUtils;
import bisq.core.util.coin.CoinFormatter;
@ -65,8 +66,6 @@ import bisq.common.util.Tuple3;
import bisq.common.util.Tuple4;
import bisq.common.util.Utilities;
import org.bitcoinj.core.Coin;
import net.glxn.qrgen.QRCode;
import net.glxn.qrgen.image.ImageType;
@ -108,6 +107,7 @@ import javafx.beans.value.ChangeListener;
import java.net.URI;
import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
@ -208,7 +208,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
if (newValue) {
Notification walletFundedNotification = new Notification()
.headLine(Res.get("notification.walletUpdate.headline"))
.notification(Res.get("notification.walletUpdate.msg", formatter.formatCoinWithCode(model.dataModel.getTotalToPayAsCoin().get())))
.notification(Res.get("notification.walletUpdate.msg", HavenoUtils.formatToXmrWithCode(model.dataModel.getTotalToPay().get())))
.autoClose();
walletFundedNotification.show();
@ -262,7 +262,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
model.onPaymentAccountSelected(lastPaymentAccount);
}
balanceTextField.setTargetAmount(model.dataModel.getTotalToPayAsCoin().get());
balanceTextField.setTargetAmount(model.dataModel.getTotalToPay().get());
maybeShowTakeOfferFromUnsignedAccountWarning(model.dataModel.getOffer());
maybeShowClearXchangeWarning(lastPaymentAccount);
@ -359,8 +359,8 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
// Called from parent as the view does not get notified when the tab is closed
public void onClose() {
Coin availableBalance = model.dataModel.getAvailableBalance().get();
if (availableBalance != null && availableBalance.isPositive() && !model.takeOfferCompleted.get() && !DevEnv.isDevMode()) {
BigInteger availableBalance = model.dataModel.getAvailableBalance().get();
if (availableBalance != null && availableBalance.compareTo(BigInteger.valueOf(0)) > 0 && !model.takeOfferCompleted.get() && !DevEnv.isDevMode()) {
model.dataModel.swapTradeToSavings();
}
}
@ -445,7 +445,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
updateOfferElementsStyle();
balanceTextField.setTargetAmount(model.dataModel.getTotalToPayAsCoin().get());
balanceTextField.setTargetAmount(model.dataModel.getTotalToPay().get());
if (!DevEnv.isDevMode()) {
String tradeAmountText = model.isSeller() ? Res.get("takeOffer.takeOfferFundWalletInfo.tradeAmount", model.getTradeAmount()) : "";
@ -481,7 +481,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
if (walletFundedNotification == null) {
walletFundedNotification = new Notification()
.headLine(Res.get("notification.walletUpdate.headline"))
.notification(Res.get("notification.takeOffer.walletUpdate.msg", formatter.formatCoinWithCode(model.dataModel.getTotalToPayAsCoin().get())))
.notification(Res.get("notification.takeOffer.walletUpdate.msg", HavenoUtils.formatToXmrWithCode(model.dataModel.getTotalToPay().get())))
.autoClose();
walletFundedNotification.show();
}
@ -542,7 +542,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
amountTextField.textProperty().bindBidirectional(model.amount);
volumeTextField.textProperty().bindBidirectional(model.volume);
totalToPayTextField.textProperty().bind(model.totalToPay);
addressTextField.amountAsCoinProperty().bind(model.dataModel.getMissingCoin());
addressTextField.amountAsProperty().bind(model.dataModel.getMissingCoin());
amountTextField.validationResultProperty().bind(model.amountValidationResult);
priceCurrencyLabel.textProperty().bind(createStringBinding(() -> CurrencyUtil.getCounterCurrency(model.dataModel.getCurrencyCode())));
priceAsPercentageLabel.prefWidthProperty().bind(priceCurrencyLabel.widthProperty());
@ -566,7 +566,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
amountTextField.textProperty().unbindBidirectional(model.amount);
volumeTextField.textProperty().unbindBidirectional(model.volume);
totalToPayTextField.textProperty().unbind();
addressTextField.amountAsCoinProperty().unbind();
addressTextField.amountAsProperty().unbind();
amountTextField.validationResultProperty().unbind();
priceCurrencyLabel.textProperty().unbind();
priceAsPercentageLabel.prefWidthProperty().unbind();

View file

@ -37,7 +37,7 @@ import bisq.core.offer.OfferRestrictions;
import bisq.core.offer.OfferUtil;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.payment.validation.BtcValidator;
import bisq.core.payment.validation.XmrValidator;
import bisq.core.trade.HavenoUtils;
import bisq.core.trade.Trade;
import bisq.core.util.FormattingUtils;
@ -52,8 +52,6 @@ import bisq.network.p2p.network.Connection;
import bisq.network.p2p.network.ConnectionListener;
import bisq.common.UserThread;
import org.bitcoinj.core.Coin;
import javax.inject.Inject;
import javax.inject.Named;
@ -78,10 +76,12 @@ import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
import static javafx.beans.binding.Bindings.createStringBinding;
import java.math.BigInteger;
class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> implements ViewModel {
final TakeOfferDataModel dataModel;
private final OfferUtil offerUtil;
private final BtcValidator btcValidator;
private final XmrValidator btcValidator;
private final P2PService p2PService;
private final AccountAgeWitnessService accountAgeWitnessService;
private final Navigation navigation;
@ -118,8 +118,8 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
final ObjectProperty<InputValidator.ValidationResult> amountValidationResult = new SimpleObjectProperty<>();
private ChangeListener<String> amountListener;
private ChangeListener<Coin> amountAsCoinListener;
private ChangeListener<String> amountStrListener;
private ChangeListener<BigInteger> amountListener;
private ChangeListener<Boolean> isWalletFundedListener;
private ChangeListener<Trade.State> tradeStateListener;
private ChangeListener<Offer.State> offerStateListener;
@ -136,7 +136,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
@Inject
public TakeOfferViewModel(TakeOfferDataModel dataModel,
OfferUtil offerUtil,
BtcValidator btcValidator,
XmrValidator btcValidator,
P2PService p2PService,
AccountAgeWitnessService accountAgeWitnessService,
Navigation navigation,
@ -168,7 +168,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
volumeDescriptionLabel.set(Res.get(sellVolumeDescriptionKey, dataModel.getCurrencyCode()));
}
amount.set(xmrFormatter.formatCoin(dataModel.getAmount().get()));
amount.set(HavenoUtils.formatToXmr(dataModel.getAmount().get()));
showTransactionPublishedScreen.set(false);
// when getting back to an open screen we want to re-check again
@ -209,7 +209,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
? Res.get(buyAmountDescriptionKey)
: Res.get(sellAmountDescriptionKey);
amountRange = xmrFormatter.formatCoin(offer.getMinAmount()) + " - " + xmrFormatter.formatCoin(offer.getAmount());
amountRange = HavenoUtils.formatToXmr(offer.getMinAmount()) + " - " + HavenoUtils.formatToXmr(offer.getAmount());
price = FormattingUtils.formatPrice(dataModel.tradePrice);
marketPriceMargin = FormattingUtils.formatToPercent(offer.getMarketPriceMarginPct());
paymentLabel = Res.get("takeOffer.fundsBox.paymentLabel", offer.getShortId());
@ -219,7 +219,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
errorMessage.set(offer.getErrorMessage());
btcValidator.setMaxValue(offer.getAmount());
btcValidator.setMaxTradeLimit(Coin.valueOf(Math.min(dataModel.getMaxTradeLimit(), offer.getAmount().value)));
btcValidator.setMaxTradeLimit(BigInteger.valueOf(dataModel.getMaxTradeLimit()).min(offer.getAmount()));
btcValidator.setMinValue(offer.getMinAmount());
}
@ -248,7 +248,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
public void onPaymentAccountSelected(PaymentAccount paymentAccount) {
dataModel.onPaymentAccountSelected(paymentAccount);
btcValidator.setMaxTradeLimit(Coin.valueOf(Math.min(dataModel.getMaxTradeLimit(), offer.getAmount().value)));
btcValidator.setMaxTradeLimit(BigInteger.valueOf(dataModel.getMaxTradeLimit()).min(offer.getAmount()));
updateButtonDisableState();
}
@ -265,8 +265,8 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
return true;
} else {
new Popup().warning(Res.get("shared.notEnoughFunds",
xmrFormatter.formatCoinWithCode(dataModel.getTotalToPayAsCoin().get()),
xmrFormatter.formatCoinWithCode(dataModel.getTotalAvailableBalance())))
HavenoUtils.formatToXmrWithCode(dataModel.getTotalToPay().get()),
HavenoUtils.formatToXmrWithCode(dataModel.getTotalAvailableBalance())))
.actionButtonTextWithGoTo("navigation.funds.depositFunds")
.onAction(() -> navigation.navigateTo(MainView.class, FundsView.class, DepositView.class))
.show();
@ -276,13 +276,13 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
private void applyTakerFee() {
tradeFeeDescription.set(Res.get("createOffer.tradeFee.descriptionBTCOnly"));
Coin takerFeeAsCoin = dataModel.getTakerFee();
if (takerFeeAsCoin == null) {
BigInteger takerFee = dataModel.getTakerFee();
if (takerFee == null) {
return;
}
isTradeFeeVisible.setValue(true);
tradeFee.set(getFormatterForTakerFee().formatCoin(takerFeeAsCoin));
tradeFee.set(HavenoUtils.formatToXmr(takerFee));
tradeFeeInXmrWithFiat.set(OfferViewModelUtil.getTradeFeeWithFiatEquivalent(offerUtil,
dataModel.getTakerFee(),
xmrFormatter));
@ -303,27 +303,27 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
// only allow max 4 decimal places for btc values
setAmountToModel();
// reformat input
amount.set(xmrFormatter.formatCoin(dataModel.getAmount().get()));
amount.set(HavenoUtils.formatToXmr(dataModel.getAmount().get()));
calculateVolume();
Price tradePrice = dataModel.tradePrice;
long maxTradeLimit = dataModel.getMaxTradeLimit();
if (dataModel.getPaymentMethod().getId().equals(PaymentMethod.HAL_CASH_ID)) {
Coin adjustedAmountForHalCash = CoinUtil.getAdjustedAmountForHalCash(dataModel.getAmount().get(),
BigInteger adjustedAmountForHalCash = CoinUtil.getAdjustedAmountForHalCash(dataModel.getAmount().get(),
tradePrice,
maxTradeLimit);
dataModel.applyAmount(adjustedAmountForHalCash);
amount.set(xmrFormatter.formatCoin(dataModel.getAmount().get()));
amount.set(HavenoUtils.formatToXmr(dataModel.getAmount().get()));
} else if (dataModel.getOffer().isFiatOffer()) {
if (!isAmountEqualMinAmount(dataModel.getAmount().get()) && (!isAmountEqualMaxAmount(dataModel.getAmount().get()))) {
// We only apply the rounding if the amount is variable (minAmount is lower as amount).
// Otherwise we could get an amount lower then the minAmount set by rounding
Coin roundedAmount = CoinUtil.getRoundedFiatAmount(dataModel.getAmount().get(), tradePrice,
BigInteger roundedAmount = CoinUtil.getRoundedFiatAmount(dataModel.getAmount().get(), tradePrice,
maxTradeLimit);
dataModel.applyAmount(roundedAmount);
}
amount.set(xmrFormatter.formatCoin(dataModel.getAmount().get()));
amount.set(HavenoUtils.formatToXmr(dataModel.getAmount().get()));
}
if (!dataModel.isMinAmountLessOrEqualAmount())
@ -337,16 +337,16 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
if (dataModel.wouldCreateDustForMaker())
amountValidationResult.set(new InputValidator.ValidationResult(false,
Res.get("takeOffer.validation.amountLargerThanOfferAmountMinusFee")));
} else if (btcValidator.getMaxTradeLimit() != null && btcValidator.getMaxTradeLimit().value == OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.value) {
} else if (btcValidator.getMaxTradeLimit() != null && btcValidator.getMaxTradeLimit().equals(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT)) {
if (dataModel.getDirection() == OfferDirection.BUY) {
new Popup().information(Res.get("popup.warning.tradeLimitDueAccountAgeRestriction.seller",
xmrFormatter.formatCoinWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT),
HavenoUtils.formatToXmrWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT),
Res.get("offerbook.warning.newVersionAnnouncement")))
.width(900)
.show();
} else {
new Popup().information(Res.get("popup.warning.tradeLimitDueAccountAgeRestriction.buyer",
xmrFormatter.formatCoinWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT),
HavenoUtils.formatToXmrWithCode(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT),
Res.get("offerbook.warning.newVersionAnnouncement")))
.width(900)
.show();
@ -468,7 +468,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
private void addBindings() {
volume.bind(createStringBinding(() -> VolumeUtil.formatVolume(dataModel.volume.get()), dataModel.volume));
totalToPay.bind(createStringBinding(() -> xmrFormatter.formatCoinWithCode(dataModel.getTotalToPayAsCoin().get()), dataModel.getTotalToPayAsCoin()));
totalToPay.bind(createStringBinding(() -> HavenoUtils.formatToXmrWithCode(dataModel.getTotalToPay().get()), dataModel.getTotalToPay()));
}
@ -479,7 +479,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
}
private void createListeners() {
amountListener = (ov, oldValue, newValue) -> {
amountStrListener = (ov, oldValue, newValue) -> {
if (isBtcInputValid(newValue).isValid) {
setAmountToModel();
calculateVolume();
@ -488,8 +488,8 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
}
updateButtonDisableState();
};
amountAsCoinListener = (ov, oldValue, newValue) -> {
amount.set(xmrFormatter.formatCoin(newValue));
amountListener = (ov, oldValue, newValue) -> {
amount.set(HavenoUtils.formatToXmr(newValue));
applyTakerFee();
};
isWalletFundedListener = (ov, oldValue, newValue) -> updateButtonDisableState();
@ -548,10 +548,10 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
private void addListeners() {
// Bidirectional bindings are used for all input fields: amount, price, volume and minAmount
// We do volume/amount calculation during input, so user has immediate feedback
amount.addListener(amountListener);
amount.addListener(amountStrListener);
// Binding with Bindings.createObjectBinding does not work because of bi-directional binding
dataModel.getAmount().addListener(amountAsCoinListener);
dataModel.getAmount().addListener(amountListener);
dataModel.getIsXmrWalletFunded().addListener(isWalletFundedListener);
dataModel.getMempoolStatus().addListener(getMempoolStatusListener);
@ -563,10 +563,10 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
}
private void removeListeners() {
amount.removeListener(amountListener);
amount.removeListener(amountStrListener);
// Binding with Bindings.createObjectBinding does not work because of bi-directional binding
dataModel.getAmount().removeListener(amountAsCoinListener);
dataModel.getAmount().removeListener(amountListener);
dataModel.getMempoolStatus().removeListener(getMempoolStatusListener);
dataModel.getIsXmrWalletFunded().removeListener(isWalletFundedListener);
@ -592,7 +592,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
private void setAmountToModel() {
if (amount.get() != null && !amount.get().isEmpty()) {
Coin amount = DisplayUtils.parseToCoinWith4Decimals(this.amount.get(), xmrFormatter);
BigInteger amount = HavenoUtils.coinToAtomicUnits(DisplayUtils.parseToCoinWith4Decimals(this.amount.get(), xmrFormatter));
long maxTradeLimit = dataModel.getMaxTradeLimit();
Price price = dataModel.tradePrice;
if (price != null) {
@ -609,12 +609,12 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
}
}
private boolean isAmountEqualMinAmount(Coin amount) {
return amount.value == offer.getMinAmount().value;
private boolean isAmountEqualMinAmount(BigInteger amount) {
return offer.getMinAmount().equals(amount);
}
private boolean isAmountEqualMaxAmount(Coin amount) {
return amount.value == offer.getAmount().value;
private boolean isAmountEqualMaxAmount(BigInteger amount) {
return offer.getAmount().equals(amount);
}
///////////////////////////////////////////////////////////////////////////////////////////
@ -679,12 +679,12 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
dataModel.getSecurityDeposit(),
dataModel.getAmount().get(),
xmrFormatter,
Restrictions.getMinBuyerSecurityDepositAsCoin()
Restrictions.getMinBuyerSecurityDeposit()
);
}
public String getSecurityDepositWithCode() {
return xmrFormatter.formatCoinWithCode(dataModel.getSecurityDeposit());
return HavenoUtils.formatToXmrWithCode(dataModel.getSecurityDeposit());
}
public String getTradeFee() {
@ -696,8 +696,8 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
}
public String getTakerFeePercentage() {
final Coin takerFeeAsCoin = dataModel.getTakerFee();
return takerFeeAsCoin != null ? GUIUtil.getPercentage(takerFeeAsCoin, dataModel.getAmount().get()) : Res.get("shared.na");
final BigInteger takerFee = dataModel.getTakerFee();
return takerFee != null ? GUIUtil.getPercentage(takerFee, dataModel.getAmount().get()) : Res.get("shared.na");
}
public String getTotalToPayInfo() {

View file

@ -25,10 +25,8 @@ import bisq.desktop.util.Layout;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.locale.CountryUtil;
import bisq.core.locale.CurrencyUtil;
import bisq.core.locale.Res;
import bisq.core.offer.Offer;
import bisq.core.payment.payload.PaymentAccountPayload;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.support.dispute.Dispute;
import bisq.core.support.dispute.DisputeList;
@ -37,19 +35,17 @@ import bisq.core.support.dispute.arbitration.ArbitrationManager;
import bisq.core.support.dispute.mediation.MediationManager;
import bisq.core.support.dispute.refund.RefundManager;
import bisq.core.trade.Contract;
import bisq.core.trade.HavenoUtils;
import bisq.core.util.FormattingUtils;
import bisq.core.util.VolumeUtil;
import bisq.core.util.coin.CoinFormatter;
import bisq.network.p2p.NodeAddress;
import bisq.common.UserThread;
import bisq.common.crypto.PubKeyRing;
import org.bitcoinj.core.Utils;
import javax.inject.Inject;
import javax.inject.Named;
import com.google.common.base.Joiner;
@ -80,7 +76,6 @@ public class ContractWindow extends Overlay<ContractWindow> {
private final MediationManager mediationManager;
private final RefundManager refundManager;
private final AccountAgeWitnessService accountAgeWitnessService;
private final CoinFormatter formatter;
private Dispute dispute;
@ -92,13 +87,11 @@ public class ContractWindow extends Overlay<ContractWindow> {
public ContractWindow(ArbitrationManager arbitrationManager,
MediationManager mediationManager,
RefundManager refundManager,
AccountAgeWitnessService accountAgeWitnessService,
@Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter) {
AccountAgeWitnessService accountAgeWitnessService) {
this.arbitrationManager = arbitrationManager;
this.mediationManager = mediationManager;
this.refundManager = refundManager;
this.accountAgeWitnessService = accountAgeWitnessService;
this.formatter = formatter;
type = Type.Confirmation;
}
@ -160,18 +153,18 @@ public class ContractWindow extends Overlay<ContractWindow> {
addConfirmationLabelTextField(gridPane, ++rowIndex, Res.get("shared.tradePrice"),
FormattingUtils.formatPrice(contract.getPrice()));
addConfirmationLabelTextField(gridPane, ++rowIndex, Res.get("shared.tradeAmount"),
formatter.formatCoinWithCode(contract.getTradeAmount()));
HavenoUtils.formatToXmrWithCode(contract.getTradeAmount()));
addConfirmationLabelTextField(gridPane,
++rowIndex,
VolumeUtil.formatVolumeLabel(currencyCode, ":"),
VolumeUtil.formatVolumeWithCode(contract.getTradeVolume()));
String securityDeposit = Res.getWithColAndCap("shared.buyer") +
" " +
formatter.formatCoinWithCode(offer.getBuyerSecurityDeposit()) +
HavenoUtils.formatToXmrWithCode(offer.getBuyerSecurityDeposit()) +
" / " +
Res.getWithColAndCap("shared.seller") +
" " +
formatter.formatCoinWithCode(offer.getSellerSecurityDeposit());
HavenoUtils.formatToXmrWithCode(offer.getSellerSecurityDeposit());
addConfirmationLabelTextField(gridPane, ++rowIndex, Res.get("shared.securityDeposit"), securityDeposit);
addConfirmationLabelTextField(gridPane,
++rowIndex,

View file

@ -43,7 +43,6 @@ import bisq.core.trade.HavenoUtils;
import bisq.core.trade.Trade;
import bisq.core.trade.TradeManager;
import bisq.core.util.FormattingUtils;
import bisq.core.util.ParsingUtils;
import bisq.core.util.VolumeUtil;
import bisq.core.util.coin.CoinFormatter;
@ -76,6 +75,7 @@ import javafx.geometry.Insets;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ChangeListener;
import java.math.BigInteger;
import java.util.Date;
import java.util.Optional;
@ -278,26 +278,26 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
}
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("disputeSummaryWindow.role"), role);
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.tradeAmount"),
formatter.formatCoinWithCode(contract.getTradeAmount()));
HavenoUtils.formatToXmrWithCode(contract.getTradeAmount()));
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.tradePrice"),
FormattingUtils.formatPrice(contract.getPrice()));
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.tradeVolume"),
VolumeUtil.formatVolumeWithCode(contract.getTradeVolume()));
String tradeFee = Res.getWithColAndCap("shared.buyer") +
" " +
formatter.formatCoinWithCode(trade.getBuyer() == trade.getMaker() ? trade.getMakerFee() : trade.getTakerFee()) +
HavenoUtils.formatToXmrWithCode(trade.getBuyer() == trade.getMaker() ? trade.getMakerFee() : trade.getTakerFee()) +
" / " +
Res.getWithColAndCap("shared.seller") +
" " +
formatter.formatCoinWithCode(trade.getSeller() == trade.getMaker() ? trade.getMakerFee() : trade.getTakerFee());
HavenoUtils.formatToXmrWithCode(trade.getSeller() == trade.getMaker() ? trade.getMakerFee() : trade.getTakerFee());
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.tradeFee"), tradeFee);
String securityDeposit = Res.getWithColAndCap("shared.buyer") +
" " +
formatter.formatCoinWithCode(trade.getBuyerSecurityDeposit()) +
HavenoUtils.formatToXmrWithCode(trade.getBuyerSecurityDeposit()) +
" / " +
Res.getWithColAndCap("shared.seller") +
" " +
formatter.formatCoinWithCode(trade.getSellerSecurityDeposit());
HavenoUtils.formatToXmrWithCode(trade.getSellerSecurityDeposit());
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.securityDeposit"), securityDeposit);
}
@ -356,14 +356,14 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
}
private boolean isPayoutAmountValid() {
Coin buyerAmount = ParsingUtils.parseToCoin(buyerPayoutAmountInputTextField.getText(), formatter);
Coin sellerAmount = ParsingUtils.parseToCoin(sellerPayoutAmountInputTextField.getText(), formatter);
BigInteger buyerAmount = HavenoUtils.parseXmr(buyerPayoutAmountInputTextField.getText());
BigInteger sellerAmount = HavenoUtils.parseXmr(sellerPayoutAmountInputTextField.getText());
Contract contract = dispute.getContract();
Coin tradeAmount = contract.getTradeAmount();
Coin available = tradeAmount
BigInteger tradeAmount = contract.getTradeAmount();
BigInteger available = tradeAmount
.add(trade.getBuyerSecurityDeposit())
.add(trade.getSellerSecurityDeposit());
Coin totalAmount = buyerAmount.add(sellerAmount);
BigInteger totalAmount = buyerAmount.add(sellerAmount);
boolean isRefundAgent = getDisputeManager(dispute) instanceof RefundManager;
if (isRefundAgent) {
@ -371,7 +371,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
// be made
return totalAmount.compareTo(available) <= 0;
} else {
if (!totalAmount.isPositive()) {
if (totalAmount.compareTo(BigInteger.valueOf(0)) <= 0) {
return false;
}
return totalAmount.compareTo(available) == 0;
@ -386,26 +386,26 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
}
Contract contract = dispute.getContract();
Coin available = contract.getTradeAmount()
BigInteger available = contract.getTradeAmount()
.add(trade.getBuyerSecurityDeposit())
.add(trade.getSellerSecurityDeposit());
Coin enteredAmount = ParsingUtils.parseToCoin(inputTextField.getText(), formatter);
BigInteger enteredAmount = HavenoUtils.parseXmr(inputTextField.getText());
if (enteredAmount.compareTo(available) > 0) {
enteredAmount = available;
Coin finalEnteredAmount = enteredAmount;
inputTextField.setText(formatter.formatCoin(finalEnteredAmount));
BigInteger finalEnteredAmount = enteredAmount;
inputTextField.setText(HavenoUtils.formatToXmr(finalEnteredAmount));
}
Coin counterPartAsCoin = available.subtract(enteredAmount);
String formattedCounterPartAmount = formatter.formatCoin(counterPartAsCoin);
Coin buyerAmount;
Coin sellerAmount;
BigInteger counterPart = available.subtract(enteredAmount);
String formattedCounterPartAmount = HavenoUtils.formatToXmr(counterPart);
BigInteger buyerAmount;
BigInteger sellerAmount;
if (inputTextField == buyerPayoutAmountInputTextField) {
buyerAmount = enteredAmount;
sellerAmount = counterPartAsCoin;
sellerAmount = counterPart;
sellerPayoutAmountInputTextField.setText(formattedCounterPartAmount);
} else {
sellerAmount = enteredAmount;
buyerAmount = counterPartAsCoin;
buyerAmount = counterPart;
buyerPayoutAmountInputTextField.setText(formattedCounterPartAmount);
}
@ -619,28 +619,28 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
}
private void showPayoutTxConfirmation(Contract contract, DisputeResult disputeResult, MoneroTxWallet payoutTx, ResultHandler resultHandler) {
Coin buyerPayoutAmount = disputeResult.getBuyerPayoutAmount();
BigInteger buyerPayoutAmount = disputeResult.getBuyerPayoutAmount();
String buyerPayoutAddressString = contract.getBuyerPayoutAddressString();
Coin sellerPayoutAmount = disputeResult.getSellerPayoutAmount();
BigInteger sellerPayoutAmount = disputeResult.getSellerPayoutAmount();
String sellerPayoutAddressString = contract.getSellerPayoutAddressString();
Coin outputAmount = buyerPayoutAmount.add(sellerPayoutAmount);
BigInteger outputAmount = buyerPayoutAmount.add(sellerPayoutAmount);
String buyerDetails = "";
if (buyerPayoutAmount.isPositive()) {
if (buyerPayoutAmount.compareTo(BigInteger.valueOf(0)) > 0) {
buyerDetails = Res.get("disputeSummaryWindow.close.txDetails.buyer",
formatter.formatCoinWithCode(buyerPayoutAmount),
HavenoUtils.formatToXmrWithCode(buyerPayoutAmount),
buyerPayoutAddressString);
}
String sellerDetails = "";
if (sellerPayoutAmount.isPositive()) {
if (sellerPayoutAmount.compareTo(BigInteger.valueOf(0)) > 0) {
sellerDetails = Res.get("disputeSummaryWindow.close.txDetails.seller",
formatter.formatCoinWithCode(sellerPayoutAmount),
HavenoUtils.formatToXmrWithCode(sellerPayoutAmount),
sellerPayoutAddressString);
}
if (outputAmount.isPositive()) {
if (outputAmount.compareTo(BigInteger.valueOf(0)) > 0) {
new Popup().width(900)
.headLine(Res.get("disputeSummaryWindow.close.txDetails.headline"))
.confirmation(Res.get("disputeSummaryWindow.close.txDetails",
formatter.formatCoinWithCode(outputAmount),
HavenoUtils.formatToXmrWithCode(outputAmount),
buyerDetails,
sellerDetails,
formatter.formatCoinWithCode(HavenoUtils.atomicUnitsToCoin(payoutTx.getFee()))))
@ -716,21 +716,21 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
throw new IllegalStateException("Unknown radio button");
}
disputesService.applyPayoutAmountsToDisputeResult(payout, dispute, disputeResult, -1);
buyerPayoutAmountInputTextField.setText(formatter.formatCoin(disputeResult.getBuyerPayoutAmount()));
sellerPayoutAmountInputTextField.setText(formatter.formatCoin(disputeResult.getSellerPayoutAmount()));
buyerPayoutAmountInputTextField.setText(HavenoUtils.formatToXmr(disputeResult.getBuyerPayoutAmount()));
sellerPayoutAmountInputTextField.setText(HavenoUtils.formatToXmr(disputeResult.getSellerPayoutAmount()));
}
private void applyTradeAmountRadioButtonStates() {
Contract contract = dispute.getContract();
Coin buyerSecurityDeposit = trade.getBuyerSecurityDeposit();
Coin sellerSecurityDeposit = trade.getSellerSecurityDeposit();
Coin tradeAmount = contract.getTradeAmount();
BigInteger buyerSecurityDeposit = trade.getBuyerSecurityDeposit();
BigInteger sellerSecurityDeposit = trade.getSellerSecurityDeposit();
BigInteger tradeAmount = contract.getTradeAmount();
Coin buyerPayoutAmount = disputeResult.getBuyerPayoutAmount();
Coin sellerPayoutAmount = disputeResult.getSellerPayoutAmount();
BigInteger buyerPayoutAmount = disputeResult.getBuyerPayoutAmount();
BigInteger sellerPayoutAmount = disputeResult.getSellerPayoutAmount();
buyerPayoutAmountInputTextField.setText(formatter.formatCoin(buyerPayoutAmount));
sellerPayoutAmountInputTextField.setText(formatter.formatCoin(sellerPayoutAmount));
buyerPayoutAmountInputTextField.setText(HavenoUtils.formatToXmr(buyerPayoutAmount));
sellerPayoutAmountInputTextField.setText(HavenoUtils.formatToXmr(sellerPayoutAmount));
if (buyerPayoutAmount.equals(tradeAmount.add(buyerSecurityDeposit)) &&
sellerPayoutAmount.equals(sellerSecurityDeposit)) {

View file

@ -32,6 +32,7 @@ import bisq.core.offer.Offer;
import bisq.core.offer.OfferDirection;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.trade.HavenoUtils;
import bisq.core.trade.Trade;
import bisq.core.trade.TradeManager;
import bisq.core.trade.Trade.State;
@ -44,7 +45,6 @@ import bisq.common.crypto.KeyRing;
import bisq.common.util.Tuple2;
import bisq.common.util.Tuple4;
import org.bitcoinj.core.Coin;
import org.fxmisc.easybind.EasyBind;
import org.fxmisc.easybind.Subscription;
@ -64,6 +64,7 @@ import javafx.scene.layout.HBox;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import java.math.BigInteger;
import java.util.List;
import java.util.Optional;
@ -80,7 +81,7 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
private final KeyRing keyRing;
private final Navigation navigation;
private Offer offer;
private Coin tradeAmount;
private BigInteger tradeAmount;
private Price tradePrice;
private Optional<Runnable> placeOfferHandlerOptional = Optional.empty();
private Optional<Runnable> takeOfferHandlerOptional = Optional.empty();
@ -106,7 +107,7 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
type = Type.Confirmation;
}
public void show(Offer offer, Coin tradeAmount, Price tradePrice) {
public void show(Offer offer, BigInteger tradeAmount, Price tradePrice) {
this.offer = offer;
this.tradeAmount = tradeAmount;
this.tradePrice = tradePrice;
@ -208,14 +209,14 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
String btcAmount = Res.get("shared.btcAmount");
if (takeOfferHandlerOptional.isPresent()) {
addConfirmationLabelLabel(gridPane, ++rowIndex, btcAmount + btcDirectionInfo,
formatter.formatCoinWithCode(tradeAmount));
HavenoUtils.formatToXmrWithCode(tradeAmount));
addConfirmationLabelLabel(gridPane, ++rowIndex, VolumeUtil.formatVolumeLabel(currencyCode) + fiatDirectionInfo,
VolumeUtil.formatVolumeWithCode(offer.getVolumeByAmount(tradeAmount)));
} else {
addConfirmationLabelLabel(gridPane, ++rowIndex, btcAmount + btcDirectionInfo,
formatter.formatCoinWithCode(offer.getAmount()));
HavenoUtils.formatToXmrWithCode(offer.getAmount()));
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("offerDetailsWindow.minBtcAmount"),
formatter.formatCoinWithCode(offer.getMinAmount()));
HavenoUtils.formatToXmrWithCode(offer.getMinAmount()));
String volume = VolumeUtil.formatVolumeWithCode(offer.getVolume());
String minVolume = "";
if (offer.getVolume() != null && offer.getMinVolume() != null &&
@ -324,11 +325,11 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
DisplayUtils.formatDateTime(offer.getDate()));
String value = Res.getWithColAndCap("shared.buyer") +
" " +
formatter.formatCoinWithCode(offer.getBuyerSecurityDeposit()) +
HavenoUtils.formatToXmrWithCode(offer.getBuyerSecurityDeposit()) +
" / " +
Res.getWithColAndCap("shared.seller") +
" " +
formatter.formatCoinWithCode(offer.getSellerSecurityDeposit());
HavenoUtils.formatToXmrWithCode(offer.getSellerSecurityDeposit());
addConfirmationLabelLabel(gridPane, ++rowIndex, Res.get("shared.securityDeposit"), value);
if (countryCode != null && !isF2F)

View file

@ -31,6 +31,7 @@ import bisq.core.offer.Offer;
import bisq.core.payment.payload.PaymentAccountPayload;
import bisq.core.support.dispute.arbitration.ArbitrationManager;
import bisq.core.trade.Contract;
import bisq.core.trade.HavenoUtils;
import bisq.core.trade.Trade;
import bisq.core.trade.TradeManager;
import bisq.core.trade.txproof.AssetTxProofResult;
@ -162,7 +163,7 @@ public class TradeDetailsWindow extends Overlay<TradeDetailsWindow> {
}
addConfirmationLabelTextField(gridPane, ++rowIndex, Res.get("shared.btcAmount") + btcDirectionInfo,
formatter.formatCoinWithCode(trade.getAmount()));
HavenoUtils.formatToXmrWithCode(trade.getAmount()));
addConfirmationLabelTextField(gridPane, ++rowIndex,
VolumeUtil.formatVolumeLabel(offer.getCurrencyCode()) + fiatDirectionInfo,
VolumeUtil.formatVolumeWithCode(trade.getVolume()));
@ -215,11 +216,11 @@ public class TradeDetailsWindow extends Overlay<TradeDetailsWindow> {
DisplayUtils.formatDateTime(trade.getDate()));
String securityDeposit = Res.getWithColAndCap("shared.buyer") +
" " +
formatter.formatCoinWithCode(offer.getBuyerSecurityDeposit()) +
HavenoUtils.formatToXmrWithCode(offer.getBuyerSecurityDeposit()) +
" / " +
Res.getWithColAndCap("shared.seller") +
" " +
formatter.formatCoinWithCode(offer.getSellerSecurityDeposit());
HavenoUtils.formatToXmrWithCode(offer.getSellerSecurityDeposit());
addConfirmationLabelTextField(gridPane, ++rowIndex, Res.get("shared.securityDeposit"), securityDeposit);
NodeAddress arbitratorNodeAddress = trade.getArbitratorNodeAddress();

View file

@ -29,10 +29,10 @@ import bisq.core.trade.ClosedTradableFormatter;
import bisq.core.trade.ClosedTradableManager;
import bisq.core.trade.Tradable;
import bisq.core.trade.Trade;
import org.bitcoinj.core.Coin;
import org.apache.commons.lang3.StringUtils;
import java.math.BigInteger;
import java.util.Date;
import lombok.Getter;
@ -57,7 +57,7 @@ public class ClosedTradesListItem implements FilterableListItem {
return tradable.getShortId();
}
public Coin getAmount() {
public BigInteger getAmount() {
return tradable.getOptionalAmount().orElse(null);
}

View file

@ -41,12 +41,11 @@ import bisq.core.util.coin.CoinUtil;
import bisq.network.p2p.P2PService;
import org.bitcoinj.core.Coin;
import com.google.inject.Inject;
import javax.inject.Named;
import java.math.BigInteger;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@ -100,7 +99,7 @@ class DuplicateOfferDataModel extends MutableOfferDataModel {
}
private double getBuyerSecurityAsPercent(Offer offer) {
Coin offerBuyerSecurityDeposit = getBoundedBuyerSecurityDepositAsCoin(offer.getBuyerSecurityDeposit());
BigInteger offerBuyerSecurityDeposit = getBoundedBuyerSecurityDeposit(offer.getBuyerSecurityDeposit());
double offerBuyerSecurityDepositAsPercent = CoinUtil.getAsPercentPerBtc(offerBuyerSecurityDeposit,
offer.getAmount());
return Math.min(offerBuyerSecurityDepositAsPercent,

View file

@ -23,7 +23,7 @@ import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.offer.Offer;
import bisq.core.offer.OfferPayload;
import bisq.core.offer.OfferUtil;
import bisq.core.payment.validation.BtcValidator;
import bisq.core.payment.validation.XmrValidator;
import bisq.core.payment.validation.FiatVolumeValidator;
import bisq.core.payment.validation.SecurityDepositValidator;
import bisq.core.provider.price.PriceFeedService;
@ -46,7 +46,7 @@ class DuplicateOfferViewModel extends MutableOfferViewModel<DuplicateOfferDataMo
FiatVolumeValidator fiatVolumeValidator,
FiatPriceValidator fiatPriceValidator,
AltcoinValidator altcoinValidator,
BtcValidator btcValidator,
XmrValidator btcValidator,
SecurityDepositValidator securityDepositValidator,
PriceFeedService priceFeedService,
AccountAgeWitnessService accountAgeWitnessService,

View file

@ -101,7 +101,7 @@ class EditOfferDataModel extends MutableOfferDataModel {
price.set(null);
volume.set(null);
minVolume.set(null);
buyerSecurityDeposit.set(0);
buyerSecurityDepositPct.set(0);
paymentAccounts.clear();
paymentAccount = null;
marketPriceMargin = 0;
@ -133,10 +133,10 @@ class EditOfferDataModel extends MutableOfferDataModel {
// creation, so just use the default value as it doesn't matter anyway.
double buyerSecurityDepositPercent = CoinUtil.getAsPercentPerBtc(offer.getBuyerSecurityDeposit(), offer.getAmount());
if (buyerSecurityDepositPercent > Restrictions.getMaxBuyerSecurityDepositAsPercent()
&& offer.getBuyerSecurityDeposit().value == Restrictions.getMinBuyerSecurityDepositAsCoin().value)
buyerSecurityDeposit.set(Restrictions.getDefaultBuyerSecurityDepositAsPercent());
&& offer.getBuyerSecurityDeposit().equals(Restrictions.getMinBuyerSecurityDeposit()))
buyerSecurityDepositPct.set(Restrictions.getDefaultBuyerSecurityDepositAsPercent());
else
buyerSecurityDeposit.set(buyerSecurityDepositPercent);
buyerSecurityDepositPct.set(buyerSecurityDepositPercent);
allowAmountUpdate = false;
}

View file

@ -22,7 +22,7 @@ import bisq.desktop.main.offer.MutableOfferViewModel;
import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.offer.OfferUtil;
import bisq.core.offer.OpenOffer;
import bisq.core.payment.validation.BtcValidator;
import bisq.core.payment.validation.XmrValidator;
import bisq.core.payment.validation.FiatVolumeValidator;
import bisq.core.payment.validation.SecurityDepositValidator;
import bisq.core.provider.price.PriceFeedService;
@ -46,7 +46,7 @@ class EditOfferViewModel extends MutableOfferViewModel<EditOfferDataModel> {
FiatVolumeValidator fiatVolumeValidator,
FiatPriceValidator fiatPriceValidator,
AltcoinValidator altcoinValidator,
BtcValidator btcValidator,
XmrValidator btcValidator,
SecurityDepositValidator securityDepositValidator,
PriceFeedService priceFeedService,
AccountAgeWitnessService accountAgeWitnessService,

View file

@ -38,8 +38,6 @@ import bisq.core.trade.Trade;
import bisq.common.util.Utilities;
import org.bitcoinj.core.Coin;
import com.googlecode.jcsv.writer.CSVEntryConverter;
import javax.inject.Inject;
@ -82,6 +80,7 @@ import javafx.collections.transformation.SortedList;
import javafx.util.Callback;
import java.math.BigInteger;
import java.util.Comparator;
@FxmlView
@ -273,14 +272,14 @@ public class FailedTradesView extends ActivatableViewAndModel<VBox, FailedTrades
applyFilteredListPredicate(filterTextField.getText());
}
private void handleContextMenu(String msgKey, String buyerOrSeller, String makerOrTaker, Coin fee, String reserveTxHash, String reserveTxHex) {
private void handleContextMenu(String msgKey, String buyerOrSeller, String makerOrTaker, BigInteger fee, String reserveTxHash, String reserveTxHex) {
final Trade failedTrade = tableView.getSelectionModel().getSelectedItem().getTrade();
log.debug("Found {} matching trade.", (failedTrade != null ? failedTrade.getId() : null));
if(failedTrade != null) {
new Popup().warning(Res.get(msgKey,
buyerOrSeller,
makerOrTaker,
HavenoUtils.formatXmrWithCode(fee),
HavenoUtils.formatToXmrWithCode(fee),
"todo", // TODO: set reserve tx miner fee when verified
reserveTxHash
)

View file

@ -23,6 +23,7 @@ import bisq.desktop.util.DisplayUtils;
import bisq.core.locale.CurrencyUtil;
import bisq.core.locale.Res;
import bisq.core.trade.HavenoUtils;
import bisq.core.util.FormattingUtils;
import bisq.core.util.VolumeUtil;
import bisq.core.util.coin.CoinFormatter;
@ -54,7 +55,7 @@ class FailedTradesViewModel extends ActivatableWithDataModel<FailedTradesDataMod
String getAmount(FailedTradesListItem item) {
if (item != null && item.getTrade() != null)
return formatter.formatCoin(item.getTrade().getAmount());
return HavenoUtils.formatToXmr(item.getTrade().getAmount());
else
return "";
}

View file

@ -27,6 +27,7 @@ import bisq.core.locale.Res;
import bisq.core.monetary.Price;
import bisq.core.offer.Offer;
import bisq.core.offer.OpenOffer;
import bisq.core.trade.HavenoUtils;
import bisq.core.util.FormattingUtils;
import bisq.core.util.PriceUtil;
import bisq.core.util.VolumeUtil;
@ -163,7 +164,7 @@ class OpenOffersViewModel extends ActivatableWithDataModel<OpenOffersDataModel>
public String getMakerFeeAsString(OpenOffer openOffer) {
Offer offer = openOffer.getOffer();
return btcFormatter.formatCoinWithCode(offer.getMakerFee());
return HavenoUtils.formatToXmrWithCode(offer.getMakerFee());
}
String getTriggerPrice(OpenOfferListItem item) {

View file

@ -78,6 +78,7 @@ import javafx.collections.ObservableList;
import org.bouncycastle.crypto.params.KeyParameter;
import java.math.BigInteger;
import java.util.Date;
import java.util.stream.Collectors;
@ -274,7 +275,7 @@ public class PendingTradesDataModel extends ActivatableDataModel {
return isMaker;
}
Coin getTradeFeeInBTC() {
BigInteger getTradeFeeInBTC() {
Trade trade = getTrade();
if (trade != null) {
Offer offer = trade.getOffer();
@ -283,14 +284,14 @@ public class PendingTradesDataModel extends ActivatableDataModel {
return offer.getMakerFee();
} else {
log.error("offer is null");
return Coin.ZERO;
return BigInteger.valueOf(0);
}
} else {
return trade.getTakerFee();
}
} else {
log.error("Trade is null at getTotalFees");
return Coin.ZERO;
return BigInteger.valueOf(0);
}
}

View file

@ -20,6 +20,7 @@ package bisq.desktop.main.portfolio.pendingtrades;
import bisq.desktop.util.filtering.FilterableListItem;
import bisq.core.monetary.Price;
import bisq.core.trade.HavenoUtils;
import bisq.core.trade.Trade;
import bisq.core.util.FormattingUtils;
import bisq.core.util.coin.CoinFormatter;
@ -57,7 +58,7 @@ public class PendingTradesListItem implements FilterableListItem {
}
public String getAmountAsString() {
return btcFormatter.formatCoin(trade.getAmount());
return HavenoUtils.formatToXmr(trade.getAmount());
}
public String getPaymentMethod() {

View file

@ -41,6 +41,7 @@ import bisq.core.support.messages.ChatMessage;
import bisq.core.support.traderchat.TradeChatSession;
import bisq.core.support.traderchat.TraderChatManager;
import bisq.core.trade.Contract;
import bisq.core.trade.HavenoUtils;
import bisq.core.trade.Trade;
import bisq.core.user.Preferences;
import bisq.core.util.FormattingUtils;
@ -699,7 +700,7 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
public void updateItem(final PendingTradesListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setGraphic(new AutoTooltipLabel(formatter.formatCoin(item.getTrade().getAmount())));
setGraphic(new AutoTooltipLabel(HavenoUtils.formatToXmr(item.getTrade().getAmount())));
else
setGraphic(null);
}

View file

@ -48,8 +48,6 @@ import bisq.common.ClockWatcher;
import bisq.common.UserThread;
import bisq.common.app.DevEnv;
import org.bitcoinj.core.Coin;
import com.google.inject.Inject;
import javax.inject.Named;
@ -63,6 +61,7 @@ import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import java.math.BigInteger;
import java.util.Date;
import java.util.stream.Collectors;
@ -236,7 +235,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
public String getPayoutAmount() {
return dataModel.getTrade() != null
? btcFormatter.formatCoinWithCode(dataModel.getTrade().getPayoutAmount())
? HavenoUtils.formatToXmrWithCode(dataModel.getTrade().getPayoutAmount())
: "";
}
@ -282,7 +281,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
// summary
public String getTradeVolume() {
return dataModel.getTrade() != null
? btcFormatter.formatCoinWithCode(dataModel.getTrade().getAmount())
? HavenoUtils.formatToXmrWithCode(dataModel.getTrade().getAmount())
: "";
}
@ -296,15 +295,15 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
if (trade != null && dataModel.getOffer() != null && trade.getAmount() != null) {
checkNotNull(dataModel.getTrade());
Coin tradeFeeInBTC = dataModel.getTradeFeeInBTC();
BigInteger tradeFeeInBTC = dataModel.getTradeFeeInBTC();
Coin minTradeFee = dataModel.isMaker() ?
BigInteger minTradeFee = dataModel.isMaker() ?
HavenoUtils.getMinMakerFee() :
HavenoUtils.getMinTakerFee();
String percentage = GUIUtil.getPercentageOfTradeAmount(tradeFeeInBTC, trade.getAmount(),
minTradeFee);
return btcFormatter.formatCoinWithCode(tradeFeeInBTC) + percentage;
return HavenoUtils.formatToXmrWithCode(tradeFeeInBTC) + percentage;
} else {
return "";
}
@ -314,18 +313,18 @@ public class PendingTradesViewModel extends ActivatableWithDataModel<PendingTrad
Offer offer = dataModel.getOffer();
Trade trade = dataModel.getTrade();
if (offer != null && trade != null && trade.getAmount() != null) {
Coin securityDeposit = dataModel.isBuyer() ?
BigInteger securityDeposit = dataModel.isBuyer() ?
offer.getBuyerSecurityDeposit()
: offer.getSellerSecurityDeposit();
Coin minSecurityDeposit = dataModel.isBuyer() ?
Restrictions.getMinBuyerSecurityDepositAsCoin() :
Restrictions.getMinSellerSecurityDepositAsCoin();
BigInteger minSecurityDeposit = dataModel.isBuyer() ?
Restrictions.getMinBuyerSecurityDeposit() :
Restrictions.getMinSellerSecurityDeposit();
String percentage = GUIUtil.getPercentageOfTradeAmount(securityDeposit,
trade.getAmount(),
minSecurityDeposit);
return btcFormatter.formatCoinWithCode(securityDeposit) + percentage;
return HavenoUtils.formatToXmrWithCode(securityDeposit) + percentage;
} else {
return "";
}

View file

@ -33,6 +33,7 @@ import bisq.core.support.dispute.DisputeResult;
import bisq.core.support.dispute.mediation.MediationResultState;
import bisq.core.trade.ArbitratorTrade;
import bisq.core.trade.Contract;
import bisq.core.trade.HavenoUtils;
import bisq.core.trade.MakerTrade;
import bisq.core.trade.TakerTrade;
import bisq.core.trade.Trade;
@ -673,8 +674,8 @@ public abstract class TradeStepView extends AnchorPane {
DisputeResult disputeResult = optionalDispute.get().getDisputeResultProperty().get();
Contract contract = checkNotNull(trade.getContract(), "contract must not be null");
boolean isMyRoleBuyer = contract.isMyRoleBuyer(model.dataModel.getPubKeyRingProvider().get());
String buyerPayoutAmount = model.btcFormatter.formatCoinWithCode(disputeResult.getBuyerPayoutAmount());
String sellerPayoutAmount = model.btcFormatter.formatCoinWithCode(disputeResult.getSellerPayoutAmount());
String buyerPayoutAmount = HavenoUtils.formatToXmrWithCode(disputeResult.getBuyerPayoutAmount());
String sellerPayoutAmount = HavenoUtils.formatToXmrWithCode(disputeResult.getSellerPayoutAmount());
String myPayoutAmount = isMyRoleBuyer ? buyerPayoutAmount : sellerPayoutAmount;
String peersPayoutAmount = isMyRoleBuyer ? sellerPayoutAmount : buyerPayoutAmount;

View file

@ -42,7 +42,8 @@ import bisq.core.locale.Res;
import bisq.core.locale.TradeCurrency;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.payment.validation.BtcValidator;
import bisq.core.payment.validation.XmrValidator;
import bisq.core.trade.HavenoUtils;
import bisq.core.user.Preferences;
import bisq.core.user.User;
import bisq.core.util.FormattingUtils;
@ -94,7 +95,7 @@ import javafx.util.Callback;
import javafx.util.StringConverter;
import java.io.File;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@ -537,7 +538,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
autoConfRequiredConfirmationsTf.setValidator(new IntegerValidator(1, DevEnv.isDevMode() ? 100000000 : 1000));
autoConfTradeLimitTf = addInputTextField(autoConfirmGridPane, ++localRowIndex, Res.get("setting.preferences.autoConfirmMaxTradeSize"));
autoConfTradeLimitTf.setValidator(new BtcValidator(formatter));
autoConfTradeLimitTf.setValidator(new XmrValidator());
autoConfServiceAddressTf = addInputTextField(autoConfirmGridPane, ++localRowIndex, Res.get("setting.preferences.autoConfirmServiceAddresses"));
GridPane.setHgrow(autoConfServiceAddressTf, Priority.ALWAYS);
@ -585,8 +586,8 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
autoConfTradeLimitListener = (observable, oldValue, newValue) -> {
if (!newValue.equals(oldValue) && autoConfTradeLimitTf.getValidator().validate(newValue).isValid) {
Coin amountAsCoin = ParsingUtils.parseToCoin(newValue, formatter);
preferences.setAutoConfTradeLimit("XMR", amountAsCoin.value);
BigInteger amount = HavenoUtils.parseXmr(newValue);
preferences.setAutoConfTradeLimit("XMR", amount.longValueExact());
}
};

View file

@ -48,6 +48,7 @@ import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
import bisq.core.support.dispute.mediation.MediationManager;
import bisq.core.support.messages.ChatMessage;
import bisq.core.trade.Contract;
import bisq.core.trade.HavenoUtils;
import bisq.core.trade.Trade;
import bisq.core.trade.TradeManager;
import bisq.core.trade.Trade.DisputeState;
@ -659,8 +660,8 @@ public abstract class DisputeView extends ActivatableView<VBox, Void> {
DisputeResult disputeResult = firstDispute.getDisputeResultProperty().get();
String winner = disputeResult != null &&
disputeResult.getWinner() == DisputeResult.Winner.BUYER ? "Buyer" : "Seller";
String buyerPayoutAmount = disputeResult != null ? disputeResult.getBuyerPayoutAmount().toFriendlyString() : "";
String sellerPayoutAmount = disputeResult != null ? disputeResult.getSellerPayoutAmount().toFriendlyString() : "";
String buyerPayoutAmount = disputeResult != null ? HavenoUtils.formatToXmrWithCode(disputeResult.getBuyerPayoutAmount()) : "";
String sellerPayoutAmount = disputeResult != null ? HavenoUtils.formatToXmrWithCode(disputeResult.getSellerPayoutAmount()) : "";
int index = disputeIndex.incrementAndGet();
String tradeDateString = dateFormatter.format(firstDispute.getTradeDate());
@ -707,7 +708,7 @@ public abstract class DisputeView extends ActivatableView<VBox, Void> {
String paymentMethod = Res.get(contract.getPaymentMethodId());
String currency = CurrencyUtil.getNameAndCode(contract.getOfferPayload().getCurrencyCode());
String tradeAmount = contract.getTradeAmount().toFriendlyString();
String tradeAmount = HavenoUtils.formatToXmrWithCode(contract.getTradeAmount());
String buyerDeposit = Coin.valueOf(contract.getOfferPayload().getBuyerSecurityDeposit()).toFriendlyString();
String sellerDeposit = Coin.valueOf(contract.getOfferPayload().getSellerSecurityDeposit()).toFriendlyString();
stringBuilder.append("Payment method: ")

View file

@ -164,8 +164,8 @@ public class SignedOfferView extends ActivatableView<VBox, Void> {
if(selectedSignedOffer != null) {
new Popup().warning(Res.get("support.prompt.signedOffer.penalty.msg",
selectedSignedOffer.getOfferId(),
HavenoUtils.formatXmrWithCode(selectedSignedOffer.getMakerTradeFee()),
HavenoUtils.formatXmrWithCode(selectedSignedOffer.getReserveTxMinerFee()),
HavenoUtils.formatToXmrWithCode(selectedSignedOffer.getMakerTradeFee()),
HavenoUtils.formatToXmrWithCode(selectedSignedOffer.getReserveTxMinerFee()),
selectedSignedOffer.getReserveTxHash(),
selectedSignedOffer.getReserveTxKeyImages())
).onAction(() -> OfferViewUtil.submitTransactionHex(xmrWalletService, tableView,
@ -406,7 +406,7 @@ public class SignedOfferView extends ActivatableView<VBox, Void> {
public void updateItem(final SignedOffer item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(HavenoUtils.formatXmrWithCode(item.getMakerTradeFee()));
setText(HavenoUtils.formatToXmrWithCode(item.getMakerTradeFee()));
else
setText("");
}
@ -432,7 +432,7 @@ public class SignedOfferView extends ActivatableView<VBox, Void> {
public void updateItem(final SignedOffer item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty)
setText(HavenoUtils.formatXmrWithCode(item.getReserveTxMinerFee()));
setText(HavenoUtils.formatToXmrWithCode(item.getReserveTxMinerFee()));
else
setText("");
}

View file

@ -10,6 +10,7 @@ import bisq.core.monetary.Volume;
import bisq.core.offer.Offer;
import bisq.core.payment.payload.PaymentAccountPayload;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.trade.HavenoUtils;
import bisq.core.util.FormattingUtils;
import bisq.core.offer.OfferDirection;
import bisq.core.payment.PaymentAccount;
@ -28,6 +29,7 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.Date;
@ -193,8 +195,8 @@ public class DisplayUtils {
public static String formatAmount(Offer offer, CoinFormatter coinFormatter) {
return offer.isRange()
? coinFormatter.formatCoin(offer.getMinAmount()) + FormattingUtils.RANGE_SEPARATOR + coinFormatter.formatCoin(offer.getAmount())
: coinFormatter.formatCoin(offer.getAmount());
? HavenoUtils.formatToXmr(offer.getMinAmount()) + FormattingUtils.RANGE_SEPARATOR + HavenoUtils.formatToXmr(offer.getAmount())
: HavenoUtils.formatToXmr(offer.getAmount());
}
public static String formatAmount(Offer offer,
@ -203,8 +205,8 @@ public class DisplayUtils {
int maxPlaces,
CoinFormatter coinFormatter) {
String formattedAmount = offer.isRange()
? coinFormatter.formatCoin(offer.getMinAmount(), decimalPlaces) + FormattingUtils.RANGE_SEPARATOR + coinFormatter.formatCoin(offer.getAmount(), decimalPlaces)
: coinFormatter.formatCoin(offer.getAmount(), decimalPlaces);
? HavenoUtils.formatToXmr(offer.getMinAmount(), decimalPlaces) + FormattingUtils.RANGE_SEPARATOR + HavenoUtils.formatToXmr(offer.getAmount(), decimalPlaces)
: HavenoUtils.formatToXmr(offer.getAmount(), decimalPlaces);
if (decimalAligned) {
formattedAmount = FormattingUtils.fillUpPlacesWithEmptyStrings(formattedAmount, maxPlaces);
@ -225,15 +227,15 @@ public class DisplayUtils {
return formattedPrice;
}
public static String getFeeWithFiatAmount(Coin makerFeeAsCoin,
public static String getFeeWithFiatAmount(BigInteger makerFee,
Optional<Volume> optionalFeeInFiat,
CoinFormatter formatter) {
String feeInBtc = makerFeeAsCoin != null ? formatter.formatCoinWithCode(makerFeeAsCoin) : Res.get("shared.na");
String feeInXmr = makerFee != null ? HavenoUtils.formatToXmrWithCode(makerFee) : Res.get("shared.na");
if (optionalFeeInFiat != null && optionalFeeInFiat.isPresent()) {
String feeInFiat = VolumeUtil.formatAverageVolumeWithCode(optionalFeeInFiat.get());
return Res.get("feeOptionWindow.fee", feeInBtc, feeInFiat);
return Res.get("feeOptionWindow.fee", feeInXmr, feeInFiat);
} else {
return feeInBtc;
return feeInXmr;
}
}

View file

@ -41,19 +41,16 @@ import bisq.core.locale.TradeCurrency;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.PaymentAccountList;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.trade.HavenoUtils;
import bisq.core.trade.txproof.AssetTxProofResult;
import bisq.core.user.DontShowAgainLookup;
import bisq.core.user.Preferences;
import bisq.core.user.User;
import bisq.core.util.FormattingUtils;
import bisq.core.util.ParsingUtils;
import bisq.core.util.coin.CoinFormatter;
import bisq.network.p2p.P2PService;
import bisq.common.UserThread;
import bisq.common.app.DevEnv;
import bisq.common.config.Config;
import bisq.common.crypto.KeyRing;
import bisq.common.file.CorruptedStorageFileHandler;
@ -123,7 +120,8 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@ -650,19 +648,19 @@ public class GUIUtil {
}
}
public static String getPercentageOfTradeAmount(Coin fee, Coin tradeAmount, Coin minFee) {
public static String getPercentageOfTradeAmount(BigInteger fee, BigInteger tradeAmount, BigInteger minFee) {
String result = " (" + getPercentage(fee, tradeAmount) +
" " + Res.get("guiUtil.ofTradeAmount") + ")";
if (!fee.isGreaterThan(minFee)) {
if (fee.compareTo(minFee) <= 0) {
result = " " + Res.get("guiUtil.requiredMinimum");
}
return result;
}
public static String getPercentage(Coin part, Coin total) {
return FormattingUtils.formatToPercentWithSymbol((double) part.value / (double) total.value);
public static String getPercentage(BigInteger part, BigInteger total) {
return FormattingUtils.formatToPercentWithSymbol(new BigDecimal(part).divide(new BigDecimal(total)).doubleValue());
}
public static <T> T getParentOfType(Node node, Class<T> t) {
@ -701,10 +699,10 @@ public class GUIUtil {
.show();
}
public static String getMoneroURI(String address, Coin amount, String label, MoneroWallet wallet) {
public static String getMoneroURI(String address, BigInteger amount, String label, MoneroWallet wallet) {
return wallet.getPaymentUri(new MoneroTxConfig()
.setAddress(address)
.setAmount(HavenoUtils.coinToAtomicUnits(amount))
.setAmount(amount)
.setNote(label));
}