diff --git a/core/src/main/java/bisq/core/account/sign/SignedWitnessService.java b/core/src/main/java/bisq/core/account/sign/SignedWitnessService.java index 1db0e312..c6a881d8 100644 --- a/core/src/main/java/bisq/core/account/sign/SignedWitnessService.java +++ b/core/src/main/java/bisq/core/account/sign/SignedWitnessService.java @@ -20,6 +20,7 @@ package bisq.core.account.sign; import bisq.core.account.witness.AccountAgeWitness; import bisq.core.filter.FilterManager; import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager; +import bisq.core.trade.HavenoUtils; import bisq.core.user.User; import bisq.network.p2p.BootstrapListener; @@ -43,6 +44,7 @@ import javax.inject.Inject; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Charsets; +import java.math.BigInteger; import java.security.PublicKey; import java.security.SignatureException; @@ -68,7 +70,7 @@ import lombok.extern.slf4j.Slf4j; public class SignedWitnessService { public static final long SIGNER_AGE_DAYS = 30; private static final long SIGNER_AGE = SIGNER_AGE_DAYS * ChronoUnit.DAYS.getDuration().toMillis(); - public static final Coin MINIMUM_TRADE_AMOUNT_FOR_SIGNING = Coin.parseCoin("0.0025"); + public static final BigInteger MINIMUM_TRADE_AMOUNT_FOR_SIGNING = HavenoUtils.coinToAtomicUnits(Coin.parseCoin("0.0025")); private final KeyRing keyRing; private final P2PService p2PService; @@ -237,7 +239,7 @@ public class SignedWitnessService { } // Arbitrators sign with EC key - public void signAndPublishAccountAgeWitness(Coin tradeAmount, + public void signAndPublishAccountAgeWitness(BigInteger tradeAmount, AccountAgeWitness accountAgeWitness, ECKey key, PublicKey peersPubKey) { @@ -263,7 +265,7 @@ public class SignedWitnessService { } // Arbitrators sign with EC key - private String signAndPublishAccountAgeWitness(Coin tradeAmount, + private String signAndPublishAccountAgeWitness(BigInteger tradeAmount, AccountAgeWitness accountAgeWitness, ECKey key, byte[] peersPubKey, @@ -287,7 +289,7 @@ public class SignedWitnessService { key.getPubKey(), peersPubKey, time, - tradeAmount.value); + tradeAmount.longValueExact()); publishSignedWitness(signedWitness); log.info("Arbitrator signed witness {}", signedWitness.toString()); return ""; @@ -300,7 +302,7 @@ public class SignedWitnessService { } // Any peer can sign with DSA key - public Optional<SignedWitness> signAndPublishAccountAgeWitness(Coin tradeAmount, + public Optional<SignedWitness> signAndPublishAccountAgeWitness(BigInteger tradeAmount, AccountAgeWitness accountAgeWitness, PublicKey peersPubKey) throws CryptoException { if (isSignedAccountAgeWitness(accountAgeWitness)) { @@ -320,7 +322,7 @@ public class SignedWitnessService { keyRing.getSignatureKeyPair().getPublic().getEncoded(), peersPubKey.getEncoded(), new Date().getTime(), - tradeAmount.value); + tradeAmount.longValueExact()); publishSignedWitness(signedWitness); log.info("Trader signed witness {}", signedWitness.toString()); return Optional.of(signedWitness); @@ -438,8 +440,8 @@ public class SignedWitnessService { return isSignerAccountAgeWitness(accountAgeWitness, new Date().getTime()); } - public boolean isSufficientTradeAmountForSigning(Coin tradeAmount) { - return !tradeAmount.isLessThan(MINIMUM_TRADE_AMOUNT_FOR_SIGNING); + public boolean isSufficientTradeAmountForSigning(BigInteger tradeAmount) { + return tradeAmount.compareTo(MINIMUM_TRADE_AMOUNT_FOR_SIGNING) >= 0; } private boolean verifySigner(SignedWitness signedWitness) { diff --git a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java index 9cc197a3..389afa36 100644 --- a/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java +++ b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java @@ -53,7 +53,6 @@ import bisq.common.util.MathUtils; import bisq.common.util.Tuple2; import bisq.common.util.Utilities; -import org.bitcoinj.core.Coin; import org.bitcoinj.core.ECKey; import org.bitcoinj.core.Utils; @@ -61,6 +60,7 @@ import javax.inject.Inject; import com.google.common.annotations.VisibleForTesting; +import java.math.BigInteger; import java.security.PublicKey; import java.time.Clock; @@ -423,7 +423,7 @@ public class AccountAgeWitnessService { // Non fiat always has max limit // Account types that can get signed will use time since signing, other methods use time since account age creation // when measuring account age - private long getTradeLimit(Coin maxTradeLimit, + private BigInteger getTradeLimit(BigInteger maxTradeLimit, String currencyCode, AccountAgeWitness accountAgeWitness, AccountAge accountAgeCategory, @@ -432,17 +432,17 @@ public class AccountAgeWitnessService { if (CurrencyUtil.isCryptoCurrency(currencyCode) || !PaymentMethod.hasChargebackRisk(paymentMethod, currencyCode) || direction == OfferDirection.SELL) { - return maxTradeLimit.value; + return maxTradeLimit; } - long limit = OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.value; + BigInteger limit = OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT; var factor = signedBuyFactor(accountAgeCategory); if (factor > 0) { - limit = MathUtils.roundDoubleToLong(maxTradeLimit.value * factor); + limit = BigInteger.valueOf(MathUtils.roundDoubleToLong(maxTradeLimit.longValueExact() * factor)); } log.debug("limit={}, factor={}, accountAgeWitnessHash={}", - Coin.valueOf(limit).toFriendlyString(), + limit, factor, Utilities.bytesAsHexString(accountAgeWitness.getHash())); return limit; @@ -511,9 +511,9 @@ public class AccountAgeWitnessService { return 0; AccountAgeWitness accountAgeWitness = getMyWitness(paymentAccount.getPaymentAccountPayload()); - Coin maxTradeLimit = paymentAccount.getPaymentMethod().getMaxTradeLimitAsCoin(currencyCode); + BigInteger maxTradeLimit = paymentAccount.getPaymentMethod().getMaxTradeLimit(currencyCode); if (hasTradeLimitException(accountAgeWitness)) { - return maxTradeLimit.value; + return maxTradeLimit.longValueExact(); } final long accountSignAge = getWitnessSignAge(accountAgeWitness, new Date()); AccountAge accountAgeCategory = getAccountAgeCategory(accountSignAge); @@ -523,7 +523,7 @@ public class AccountAgeWitnessService { accountAgeWitness, accountAgeCategory, direction, - paymentAccount.getPaymentMethod()); + paymentAccount.getPaymentMethod()).longValueExact(); } /////////////////////////////////////////////////////////////////////////////////////////// @@ -582,7 +582,7 @@ public class AccountAgeWitnessService { } public boolean verifyPeersTradeAmount(Offer offer, - Coin tradeAmount, + BigInteger tradeAmount, ErrorMessageHandler errorMessageHandler) { checkNotNull(offer); @@ -593,8 +593,8 @@ public class AccountAgeWitnessService { .orElse(isToleratedSmalleAmount(tradeAmount)); } - private boolean isToleratedSmalleAmount(Coin tradeAmount) { - return tradeAmount.value <= OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.value; + private boolean isToleratedSmalleAmount(BigInteger tradeAmount) { + return tradeAmount.longValueExact() <= OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.longValueExact(); } @@ -642,14 +642,14 @@ public class AccountAgeWitnessService { } private boolean verifyPeersTradeLimit(Offer offer, - Coin tradeAmount, + BigInteger tradeAmount, AccountAgeWitness peersWitness, Date peersCurrentDate, ErrorMessageHandler errorMessageHandler) { checkNotNull(offer); final String currencyCode = offer.getCurrencyCode(); - final Coin defaultMaxTradeLimit = offer.getPaymentMethod().getMaxTradeLimitAsCoin(currencyCode); - long peersCurrentTradeLimit = defaultMaxTradeLimit.value; + final BigInteger defaultMaxTradeLimit = offer.getPaymentMethod().getMaxTradeLimit(currencyCode); + BigInteger peersCurrentTradeLimit = defaultMaxTradeLimit; if (!hasTradeLimitException(peersWitness)) { final long accountSignAge = getWitnessSignAge(peersWitness, peersCurrentDate); AccountAge accountAgeCategory = getPeersAccountAgeCategory(accountSignAge); @@ -659,11 +659,11 @@ public class AccountAgeWitnessService { accountAgeCategory, direction, offer.getPaymentMethod()); } // Makers current trade limit cannot be smaller than that in the offer - boolean result = tradeAmount.value <= peersCurrentTradeLimit; + boolean result = tradeAmount.longValueExact() <= peersCurrentTradeLimit.longValueExact(); if (!result) { String msg = "The peers trade limit is less than the traded amount.\n" + - "tradeAmount=" + tradeAmount.toFriendlyString() + - "\nPeers trade limit=" + Coin.valueOf(peersCurrentTradeLimit).toFriendlyString() + + "tradeAmount=" + tradeAmount + + "\nPeers trade limit=" + peersCurrentTradeLimit + "\nOffer ID=" + offer.getShortId() + "\nPaymentMethod=" + offer.getPaymentMethod().getId() + "\nCurrencyCode=" + offer.getCurrencyCode(); @@ -698,7 +698,7 @@ public class AccountAgeWitnessService { // Witness signing /////////////////////////////////////////////////////////////////////////////////////////// - public void arbitratorSignAccountAgeWitness(Coin tradeAmount, + public void arbitratorSignAccountAgeWitness(BigInteger tradeAmount, AccountAgeWitness accountAgeWitness, ECKey key, PublicKey peersPubKey) { @@ -737,7 +737,7 @@ public class AccountAgeWitnessService { public Optional<SignedWitness> traderSignAndPublishPeersAccountAgeWitness(Trade trade) { AccountAgeWitness peersWitness = findTradePeerWitness(trade).orElse(null); - Coin tradeAmount = trade.getAmount(); + BigInteger tradeAmount = trade.getAmount(); checkNotNull(trade.getTradePeer().getPubKeyRing(), "Peer must have a keyring"); PublicKey peersPubKey = trade.getTradePeer().getPubKeyRing().getSignaturePubKey(); checkNotNull(peersWitness, "Not able to find peers witness, unable to sign for trade {}", @@ -800,7 +800,7 @@ public class AccountAgeWitnessService { } private Stream<TraderDataItem> getTraderData(Dispute dispute) { - Coin tradeAmount = dispute.getContract().getTradeAmount(); + BigInteger tradeAmount = dispute.getContract().getTradeAmount(); PubKeyRing buyerPubKeyRing = dispute.getContract().getBuyerPubKeyRing(); PubKeyRing sellerPubKeyRing = dispute.getContract().getSellerPubKeyRing(); @@ -841,7 +841,7 @@ public class AccountAgeWitnessService { return signedWitnessService.isSignerAccountAgeWitness(accountAgeWitness); } - public boolean tradeAmountIsSufficient(Coin tradeAmount) { + public boolean tradeAmountIsSufficient(BigInteger tradeAmount) { return signedWitnessService.isSufficientTradeAmountForSigning(tradeAmount); } diff --git a/core/src/main/java/bisq/core/api/CoreApi.java b/core/src/main/java/bisq/core/api/CoreApi.java index 7278df2d..8285cc19 100644 --- a/core/src/main/java/bisq/core/api/CoreApi.java +++ b/core/src/main/java/bisq/core/api/CoreApi.java @@ -48,7 +48,6 @@ import bisq.common.handlers.ResultHandler; import bisq.proto.grpc.NotificationMessage; -import org.bitcoinj.core.Coin; import org.bitcoinj.core.Transaction; import javax.inject.Inject; @@ -58,7 +57,7 @@ import com.google.common.util.concurrent.FutureCallback; import java.io.IOException; import java.io.InputStream; - +import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -446,8 +445,8 @@ public class CoreApi { Price price, boolean useMarketBasedPrice, double marketPriceMargin, - Coin amount, - Coin minAmount, + BigInteger amount, + BigInteger minAmount, double buyerSecurityDeposit, PaymentAccount paymentAccount) { return coreOffersService.editOffer(offerId, @@ -552,10 +551,6 @@ public class CoreApi { coreTradesService.closeTrade(tradeId); } - public void withdrawFunds(String tradeId, String address, String memo) { - coreTradesService.withdrawFunds(tradeId, address, memo); - } - public Trade getTrade(String tradeId) { return coreTradesService.getTrade(tradeId); } diff --git a/core/src/main/java/bisq/core/api/CoreDisputesService.java b/core/src/main/java/bisq/core/api/CoreDisputesService.java index 347ace22..e792aba3 100644 --- a/core/src/main/java/bisq/core/api/CoreDisputesService.java +++ b/core/src/main/java/bisq/core/api/CoreDisputesService.java @@ -24,8 +24,6 @@ import bisq.common.crypto.PubKeyRing; import bisq.common.handlers.FaultHandler; import bisq.common.handlers.ResultHandler; -import org.bitcoinj.core.Coin; - import com.google.inject.name.Named; import javax.inject.Inject; import javax.inject.Singleton; @@ -40,6 +38,8 @@ import lombok.extern.slf4j.Slf4j; import static com.google.common.base.Preconditions.checkNotNull; import static java.lang.String.format; +import java.math.BigInteger; + @Singleton @Slf4j @@ -217,33 +217,32 @@ public class CoreDisputesService { public void applyPayoutAmountsToDisputeResult(DisputePayout payout, Dispute dispute, DisputeResult disputeResult, long customWinnerAmount) { Contract contract = dispute.getContract(); Trade trade = tradeManager.getTrade(dispute.getTradeId()); - Coin buyerSecurityDeposit = trade.getBuyerSecurityDeposit(); - Coin sellerSecurityDeposit = trade.getSellerSecurityDeposit(); - Coin tradeAmount = contract.getTradeAmount(); + BigInteger buyerSecurityDeposit = trade.getBuyerSecurityDeposit(); + BigInteger sellerSecurityDeposit = trade.getSellerSecurityDeposit(); + BigInteger tradeAmount = contract.getTradeAmount(); if (payout == DisputePayout.BUYER_GETS_TRADE_AMOUNT) { disputeResult.setBuyerPayoutAmount(tradeAmount.add(buyerSecurityDeposit)); disputeResult.setSellerPayoutAmount(sellerSecurityDeposit); } else if (payout == DisputePayout.BUYER_GETS_ALL) { disputeResult.setBuyerPayoutAmount(tradeAmount .add(buyerSecurityDeposit) - .add(sellerSecurityDeposit)); // TODO (woodser): apply min payout to incentivize loser (see post v1.1.7) - disputeResult.setSellerPayoutAmount(Coin.ZERO); + .add(sellerSecurityDeposit)); // TODO (woodser): apply min payout to incentivize loser? (see post v1.1.7) + disputeResult.setSellerPayoutAmount(BigInteger.valueOf(0)); } else if (payout == DisputePayout.SELLER_GETS_TRADE_AMOUNT) { disputeResult.setBuyerPayoutAmount(buyerSecurityDeposit); disputeResult.setSellerPayoutAmount(tradeAmount.add(sellerSecurityDeposit)); } else if (payout == DisputePayout.SELLER_GETS_ALL) { - disputeResult.setBuyerPayoutAmount(Coin.ZERO); + disputeResult.setBuyerPayoutAmount(BigInteger.valueOf(0)); disputeResult.setSellerPayoutAmount(tradeAmount .add(sellerSecurityDeposit) .add(buyerSecurityDeposit)); } else if (payout == DisputePayout.CUSTOM) { - Coin winnerAmount = Coin.valueOf(customWinnerAmount); - if (winnerAmount.compareTo(HavenoUtils.atomicUnitsToCoin(trade.getWallet().getBalance())) > 0) { + if (customWinnerAmount > trade.getWallet().getBalance().longValueExact()) { throw new RuntimeException("The custom winner payout amount is more than the trade wallet's balance"); } - Coin loserAmount = tradeAmount.add(buyerSecurityDeposit).add(sellerSecurityDeposit).minus(winnerAmount); - disputeResult.setBuyerPayoutAmount(disputeResult.getWinner() == DisputeResult.Winner.BUYER ? winnerAmount : loserAmount); - disputeResult.setSellerPayoutAmount(disputeResult.getWinner() == DisputeResult.Winner.BUYER ? loserAmount : winnerAmount); + long loserAmount = tradeAmount.add(buyerSecurityDeposit).add(sellerSecurityDeposit).subtract(BigInteger.valueOf(customWinnerAmount)).longValueExact(); + disputeResult.setBuyerPayoutAmount(BigInteger.valueOf(disputeResult.getWinner() == DisputeResult.Winner.BUYER ? customWinnerAmount : loserAmount)); + disputeResult.setSellerPayoutAmount(BigInteger.valueOf(disputeResult.getWinner() == DisputeResult.Winner.BUYER ? loserAmount : customWinnerAmount)); } } @@ -254,7 +253,7 @@ public class CoreDisputesService { String agentNodeAddress = checkNotNull(disputeManager.getAgentNodeAddress(dispute)).getFullAddress(); Contract contract = dispute.getContract(); String currencyCode = contract.getOfferPayload().getCurrencyCode(); - String amount = formatter.formatCoinWithCode(contract.getTradeAmount()); + String amount = HavenoUtils.formatToXmrWithCode(contract.getTradeAmount()); String textToSign = Res.get("disputeSummaryWindow.close.msg", FormattingUtils.formatDateTime(disputeResult.getCloseDate(), true), @@ -264,8 +263,8 @@ public class CoreDisputesService { currencyCode, Res.get("disputeSummaryWindow.reason." + reason.name()), amount, - formatter.formatCoinWithCode(disputeResult.getBuyerPayoutAmount()), - formatter.formatCoinWithCode(disputeResult.getSellerPayoutAmount()), + HavenoUtils.formatToXmrWithCode(disputeResult.getBuyerPayoutAmount()), + HavenoUtils.formatToXmrWithCode(disputeResult.getSellerPayoutAmount()), disputeResult.summaryNotesProperty().get() ); diff --git a/core/src/main/java/bisq/core/api/CoreOffersService.java b/core/src/main/java/bisq/core/api/CoreOffersService.java index 28e775cd..569b266a 100644 --- a/core/src/main/java/bisq/core/api/CoreOffersService.java +++ b/core/src/main/java/bisq/core/api/CoreOffersService.java @@ -41,6 +41,7 @@ import javax.inject.Inject; import javax.inject.Singleton; import java.math.BigDecimal; +import java.math.BigInteger; import java.util.ArrayList; import java.util.Comparator; import java.util.HashSet; @@ -181,8 +182,8 @@ public class CoreOffersService { String offerId = createOfferService.getRandomOfferId(); OfferDirection direction = OfferDirection.valueOf(directionAsString.toUpperCase()); Price price = priceAsString.isEmpty() ? null : Price.valueOf(upperCaseCurrencyCode, priceStringToLong(priceAsString, upperCaseCurrencyCode)); - Coin amount = Coin.valueOf(amountAsLong); - Coin minAmount = Coin.valueOf(minAmountAsLong); + BigInteger amount = BigInteger.valueOf(amountAsLong); + BigInteger minAmount = BigInteger.valueOf(minAmountAsLong); Coin useDefaultTxFee = Coin.ZERO; Offer offer = createOfferService.createAndGetOffer(offerId, direction, @@ -214,8 +215,8 @@ public class CoreOffersService { Price price, boolean useMarketBasedPrice, double marketPriceMargin, - Coin amount, - Coin minAmount, + BigInteger amount, + BigInteger minAmount, double buyerSecurityDeposit, PaymentAccount paymentAccount) { Coin useDefaultTxFee = Coin.ZERO; diff --git a/core/src/main/java/bisq/core/api/CorePriceService.java b/core/src/main/java/bisq/core/api/CorePriceService.java index 00d4457a..e9221b77 100644 --- a/core/src/main/java/bisq/core/api/CorePriceService.java +++ b/core/src/main/java/bisq/core/api/CorePriceService.java @@ -25,6 +25,7 @@ import bisq.core.offer.Offer; import bisq.core.offer.OfferBookService; import bisq.core.offer.OfferDirection; import bisq.core.provider.price.PriceFeedService; +import bisq.core.trade.HavenoUtils; import javax.inject.Inject; import javax.inject.Singleton; @@ -111,7 +112,7 @@ class CorePriceService { for(Offer offer: buyOffers) { 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; double priceAsDouble = (double) price.getValue() / LongMath.pow(10, price.smallestUnitExponent()); buyTM.put(mapPriceFeedServicePrice(priceAsDouble, currencyCode), accumulatedAmount); @@ -124,7 +125,7 @@ class CorePriceService { for(Offer offer: sellOffers){ 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; double priceAsDouble = (double) price.getValue() / LongMath.pow(10, price.smallestUnitExponent()); sellTM.put(mapPriceFeedServicePrice(priceAsDouble, currencyCode), accumulatedAmount); diff --git a/core/src/main/java/bisq/core/api/CoreTradesService.java b/core/src/main/java/bisq/core/api/CoreTradesService.java index 9f71aebf..2c314c0a 100644 --- a/core/src/main/java/bisq/core/api/CoreTradesService.java +++ b/core/src/main/java/bisq/core/api/CoreTradesService.java @@ -50,6 +50,8 @@ import lombok.extern.slf4j.Slf4j; import static bisq.core.btc.model.AddressEntry.Context.TRADE_PAYOUT; import static java.lang.String.format; +import java.math.BigInteger; + @Singleton @Slf4j class CoreTradesService { @@ -103,8 +105,8 @@ class CoreTradesService { var useSavingsWallet = true; // synchronize access to take offer model // TODO (woodser): to avoid synchronizing, don't use stateful model - Coin takerFee; - Coin fundsNeededForTrade; + BigInteger takerFee; + BigInteger fundsNeededForTrade; synchronized (takeOfferModel) { takeOfferModel.initModel(offer, paymentAccount, useSavingsWallet); takerFee = takeOfferModel.getTakerFee(); @@ -164,47 +166,6 @@ class CoreTradesService { tradeManager.onTradeCompleted(trade); } - void withdrawFunds(String tradeId, String toAddress, String memo) { - coreWalletsService.verifyWalletsAreAvailable(); - coreWalletsService.verifyEncryptedWalletIsUnlocked(); - - verifyTradeIsNotClosed(tradeId); - var trade = getOpenTrade(tradeId).orElseThrow(() -> - new IllegalArgumentException(format("trade with id '%s' not found", tradeId))); - - verifyIsValidBTCAddress(toAddress); - - var fromAddressEntry = btcWalletService.getOrCreateAddressEntry(trade.getId(), TRADE_PAYOUT); - verifyFundsNotWithdrawn(fromAddressEntry); - - var amount = trade.getPayoutAmount(); - var fee = getEstimatedTxFee(fromAddressEntry.getAddressString(), toAddress, amount); - var receiverAmount = amount.subtract(fee); - - log.info(format("Withdrawing funds received from trade %s:" - + "%n From %s%n To %s%n Amt %s%n Tx Fee %s%n Receiver Amt %s%n Memo %s%n", - tradeId, - fromAddressEntry.getAddressString(), - toAddress, - amount.toFriendlyString(), - fee.toFriendlyString(), - receiverAmount.toFriendlyString(), - memo)); - tradeManager.onWithdrawRequest( - toAddress, - amount, - fee, - coreWalletsService.getKey(), - trade, - memo.isEmpty() ? null : memo, - () -> { - }, - (errorMessage, throwable) -> { - log.error(errorMessage, throwable); - throw new IllegalStateException(errorMessage, throwable); - }); - } - String getTradeRole(String tradeId) { coreWalletsService.verifyWalletsAreAvailable(); coreWalletsService.verifyEncryptedWalletIsUnlocked(); diff --git a/core/src/main/java/bisq/core/api/model/OfferInfo.java b/core/src/main/java/bisq/core/api/model/OfferInfo.java index 45a81bf1..c9079ffe 100644 --- a/core/src/main/java/bisq/core/api/model/OfferInfo.java +++ b/core/src/main/java/bisq/core/api/model/OfferInfo.java @@ -21,7 +21,6 @@ import bisq.core.api.model.builder.OfferInfoBuilder; import bisq.core.monetary.Price; import bisq.core.offer.Offer; import bisq.core.offer.OpenOffer; -import bisq.core.trade.HavenoUtils; import bisq.common.Payload; import bisq.common.proto.ProtoUtil; import java.util.Optional; @@ -151,14 +150,14 @@ public class OfferInfo implements Payload { .withPrice(preciseOfferPrice) .withUseMarketBasedPrice(offer.isUseMarketBasedPrice()) .withMarketPriceMarginPct(marketPriceMarginAsPctLiteral) - .withAmount(HavenoUtils.centinerosToAtomicUnits(offer.getAmount().value).longValueExact()) - .withMinAmount(HavenoUtils.centinerosToAtomicUnits(offer.getMinAmount().value).longValueExact()) + .withAmount(offer.getAmount().longValueExact()) + .withMinAmount(offer.getMinAmount().longValueExact()) .withVolume(roundedVolume) .withMinVolume(roundedMinVolume) - .withMakerFee(HavenoUtils.centinerosToAtomicUnits(offer.getMakerFee().value).longValueExact()) + .withMakerFee(offer.getMakerFee().longValueExact()) .withOfferFeePaymentTxId(offer.getOfferFeePaymentTxId()) - .withBuyerSecurityDeposit(HavenoUtils.centinerosToAtomicUnits(offer.getBuyerSecurityDeposit().value).longValueExact()) - .withSellerSecurityDeposit(HavenoUtils.centinerosToAtomicUnits(offer.getSellerSecurityDeposit().value).longValueExact()) + .withBuyerSecurityDeposit(offer.getBuyerSecurityDeposit().longValueExact()) + .withSellerSecurityDeposit(offer.getSellerSecurityDeposit().longValueExact()) .withPaymentAccountId(offer.getMakerPaymentAccountId()) .withPaymentMethodId(offer.getPaymentMethod().getId()) .withPaymentMethodShortName(offer.getPaymentMethod().getShortName()) diff --git a/core/src/main/java/bisq/core/api/model/TradeInfo.java b/core/src/main/java/bisq/core/api/model/TradeInfo.java index 4693c860..79093c55 100644 --- a/core/src/main/java/bisq/core/api/model/TradeInfo.java +++ b/core/src/main/java/bisq/core/api/model/TradeInfo.java @@ -161,8 +161,8 @@ public class TradeInfo implements Payload { .withTakerDepositTxId(trade.getTaker().getDepositTxHash()) .withPayoutTxId(trade.getPayoutTxId()) .withAmountAsLong(trade.getAmountAsLong()) - .withBuyerSecurityDeposit(trade.getBuyerSecurityDeposit() == null ? -1 : trade.getBuyerSecurityDeposit().value) - .withSellerSecurityDeposit(trade.getSellerSecurityDeposit() == null ? -1 : trade.getSellerSecurityDeposit().value) + .withBuyerSecurityDeposit(trade.getBuyerSecurityDeposit() == null ? -1 : trade.getBuyerSecurityDeposit().longValueExact()) + .withSellerSecurityDeposit(trade.getSellerSecurityDeposit() == null ? -1 : trade.getSellerSecurityDeposit().longValueExact()) .withPrice(toPreciseTradePrice.apply(trade)) .withVolume(toRoundedVolume.apply(trade)) .withArbitratorNodeAddress(toArbitratorNodeAddress.apply(trade)) diff --git a/core/src/main/java/bisq/core/btc/wallet/Restrictions.java b/core/src/main/java/bisq/core/btc/wallet/Restrictions.java index 66b94a48..68c1a714 100644 --- a/core/src/main/java/bisq/core/btc/wallet/Restrictions.java +++ b/core/src/main/java/bisq/core/btc/wallet/Restrictions.java @@ -18,18 +18,21 @@ package bisq.core.btc.wallet; import bisq.common.config.Config; +import bisq.core.trade.HavenoUtils; + +import java.math.BigInteger; import org.bitcoinj.core.Coin; public class Restrictions { - private static Coin MIN_TRADE_AMOUNT; - private static Coin MIN_BUYER_SECURITY_DEPOSIT; + private static BigInteger MIN_TRADE_AMOUNT; + private static BigInteger MIN_BUYER_SECURITY_DEPOSIT; // For the seller we use a fixed one as there is no way the seller can cancel the trade // To make it editable would just increase complexity. - private static Coin SELLER_SECURITY_DEPOSIT; + private static BigInteger SELLER_SECURITY_DEPOSIT; // At mediation we require a min. payout to the losing party to keep incentive for the trader to accept the // mediated payout. For Refund agent cases we do not have that restriction. - private static Coin MIN_REFUND_AT_MEDIATED_DISPUTE; + private static BigInteger MIN_REFUND_AT_MEDIATED_DISPUTE; public static Coin getMinNonDustOutput() { if (minNonDustOutput == null) @@ -47,9 +50,9 @@ public class Restrictions { return !isAboveDust(amount); } - public static Coin getMinTradeAmount() { + public static BigInteger getMinTradeAmount() { if (MIN_TRADE_AMOUNT == null) - MIN_TRADE_AMOUNT = Coin.valueOf(10_000); // 0,7 USD @ 7000 USD/BTC + MIN_TRADE_AMOUNT = HavenoUtils.centinerosToAtomicUnits(10000); // TODO: increase for xmr return MIN_TRADE_AMOUNT; } @@ -67,9 +70,9 @@ public class Restrictions { // We use MIN_BUYER_SECURITY_DEPOSIT as well as lower bound in case of small trade amounts. // So 0.0005 BTC is the min. buyer security deposit even with amount of 0.0001 BTC and 0.05% percentage value. - public static Coin getMinBuyerSecurityDepositAsCoin() { + public static BigInteger getMinBuyerSecurityDeposit() { if (MIN_BUYER_SECURITY_DEPOSIT == null) - MIN_BUYER_SECURITY_DEPOSIT = Coin.parseCoin("0.001"); // 0.001 BTC is 60 USD @ 60000 USD/BTC + MIN_BUYER_SECURITY_DEPOSIT = HavenoUtils.xmrToAtomicUnits(0.001); // TODO: increase for xmr return MIN_BUYER_SECURITY_DEPOSIT; } @@ -78,16 +81,16 @@ public class Restrictions { return 0.15; // 15% of trade amount. } - public static Coin getMinSellerSecurityDepositAsCoin() { + public static BigInteger getMinSellerSecurityDeposit() { if (SELLER_SECURITY_DEPOSIT == null) - SELLER_SECURITY_DEPOSIT = Coin.parseCoin("0.001"); // 0.001 BTC is 60 USD @ 60000 USD/BTC + SELLER_SECURITY_DEPOSIT = HavenoUtils.xmrToAtomicUnits(0.001); return SELLER_SECURITY_DEPOSIT; } // This value must be lower than MIN_BUYER_SECURITY_DEPOSIT and SELLER_SECURITY_DEPOSIT - public static Coin getMinRefundAtMediatedDispute() { + public static BigInteger getMinRefundAtMediatedDispute() { if (MIN_REFUND_AT_MEDIATED_DISPUTE == null) - MIN_REFUND_AT_MEDIATED_DISPUTE = Coin.parseCoin("0.0005"); // 0.0005 BTC is 30 USD @ 60000 USD/BTC + MIN_REFUND_AT_MEDIATED_DISPUTE = HavenoUtils.xmrToAtomicUnits(0.0005); return MIN_REFUND_AT_MEDIATED_DISPUTE; } diff --git a/core/src/main/java/bisq/core/btc/wallet/XmrWalletService.java b/core/src/main/java/bisq/core/btc/wallet/XmrWalletService.java index 178150c5..ae329856 100644 --- a/core/src/main/java/bisq/core/btc/wallet/XmrWalletService.java +++ b/core/src/main/java/bisq/core/btc/wallet/XmrWalletService.java @@ -66,7 +66,6 @@ import monero.wallet.model.MoneroTxWallet; import monero.wallet.model.MoneroWalletConfig; import monero.wallet.model.MoneroWalletListener; import monero.wallet.model.MoneroWalletListenerI; -import org.bitcoinj.core.Coin; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -314,9 +313,9 @@ public class XmrWalletService { public MoneroTxWallet createDepositTx(Trade trade) { Offer offer = trade.getProcessModel().getOffer(); String multisigAddress = trade.getProcessModel().getMultisigAddress(); - BigInteger tradeFee = HavenoUtils.coinToAtomicUnits(trade instanceof MakerTrade ? trade.getOffer().getMakerFee() : trade.getTakerFee()); - BigInteger sendAmount = HavenoUtils.coinToAtomicUnits(trade instanceof BuyerTrade ? Coin.ZERO : offer.getAmount()); - BigInteger securityDeposit = HavenoUtils.coinToAtomicUnits(trade instanceof BuyerTrade ? offer.getBuyerSecurityDeposit() : offer.getSellerSecurityDeposit()); + BigInteger tradeFee = trade instanceof MakerTrade ? trade.getOffer().getMakerFee() : trade.getTakerFee(); + BigInteger sendAmount = trade instanceof BuyerTrade ? BigInteger.valueOf(0) : offer.getAmount(); + BigInteger securityDeposit = trade instanceof BuyerTrade ? offer.getBuyerSecurityDeposit() : offer.getSellerSecurityDeposit(); // thaw reserved outputs then create deposit tx MoneroWallet wallet = getWallet(); @@ -683,13 +682,13 @@ public class XmrWalletService { private void notifyBalanceListeners() { for (XmrBalanceListener balanceListener : balanceListeners) { - Coin balance; + BigInteger balance; if (balanceListener.getSubaddressIndex() != null && balanceListener.getSubaddressIndex() != 0) balance = getBalanceForSubaddress(balanceListener.getSubaddressIndex()); else balance = getAvailableBalance(); UserThread.execute(new Runnable() { // TODO (woodser): don't execute on UserThread @Override public void run() { - balanceListener.onBalanceChanged(BigInteger.valueOf(balance.value)); + balanceListener.onBalanceChanged(balance); } }); } @@ -847,7 +846,7 @@ public class XmrWalletService { } public List<XmrAddressEntry> getFundedAvailableAddressEntries() { - return getAvailableAddressEntries().stream().filter(addressEntry -> getBalanceForSubaddress(addressEntry.getSubaddressIndex()).isPositive()).collect(Collectors.toList()); + return getAvailableAddressEntries().stream().filter(addressEntry -> getBalanceForSubaddress(addressEntry.getSubaddressIndex()).compareTo(BigInteger.valueOf(0)) > 0).collect(Collectors.toList()); } public List<XmrAddressEntry> getAddressEntryListAsImmutableList() { @@ -895,31 +894,31 @@ public class XmrWalletService { .setIncludeOutputs(true)); } - public Coin getBalanceForAddress(String address) { + public BigInteger getBalanceForAddress(String address) { return getBalanceForSubaddress(wallet.getAddressIndex(address).getIndex()); } - public Coin getBalanceForSubaddress(int subaddressIndex) { - return HavenoUtils.atomicUnitsToCoin(wallet.getBalance(0, subaddressIndex)); + public BigInteger getBalanceForSubaddress(int subaddressIndex) { + return wallet.getBalance(0, subaddressIndex); } - public Coin getAvailableBalanceForSubaddress(int subaddressIndex) { - return HavenoUtils.atomicUnitsToCoin(wallet.getUnlockedBalance(0, subaddressIndex)); + public BigInteger getAvailableBalanceForSubaddress(int subaddressIndex) { + return wallet.getUnlockedBalance(0, subaddressIndex); } - public Coin getBalance() { - return wallet != null ? HavenoUtils.atomicUnitsToCoin(wallet.getBalance(0)) : Coin.ZERO; + public BigInteger getBalance() { + return wallet != null ? wallet.getBalance(0) : BigInteger.valueOf(0); } - public Coin getAvailableBalance() { - return wallet != null ? HavenoUtils.atomicUnitsToCoin(wallet.getUnlockedBalance(0)) : Coin.ZERO; + public BigInteger getAvailableBalance() { + return wallet != null ? wallet.getUnlockedBalance(0) : BigInteger.valueOf(0); } public Stream<XmrAddressEntry> getAddressEntriesForAvailableBalanceStream() { Stream<XmrAddressEntry> availableAndPayout = Stream.concat(getAddressEntries(XmrAddressEntry.Context.TRADE_PAYOUT).stream(), getFundedAvailableAddressEntries().stream()); Stream<XmrAddressEntry> available = Stream.concat(availableAndPayout, getAddressEntries(XmrAddressEntry.Context.ARBITRATOR).stream()); available = Stream.concat(available, getAddressEntries(XmrAddressEntry.Context.OFFER_FUNDING).stream()); - return available.filter(addressEntry -> getBalanceForSubaddress(addressEntry.getSubaddressIndex()).isPositive()); + return available.filter(addressEntry -> getBalanceForSubaddress(addressEntry.getSubaddressIndex()).compareTo(BigInteger.valueOf(0)) > 0); } public void addWalletListener(MoneroWalletListenerI listener) { diff --git a/core/src/main/java/bisq/core/monetary/Price.java b/core/src/main/java/bisq/core/monetary/Price.java index a3129e5c..ac30715b 100644 --- a/core/src/main/java/bisq/core/monetary/Price.java +++ b/core/src/main/java/bisq/core/monetary/Price.java @@ -18,11 +18,12 @@ package bisq.core.monetary; import bisq.core.locale.CurrencyUtil; +import bisq.core.trade.HavenoUtils; import bisq.core.util.ParsingUtils; import java.math.BigDecimal; +import java.math.BigInteger; -import org.bitcoinj.core.Coin; import org.bitcoinj.core.Monetary; import org.bitcoinj.utils.ExchangeRate; import org.bitcoinj.utils.Fiat; @@ -33,7 +34,7 @@ import org.slf4j.LoggerFactory; import org.jetbrains.annotations.NotNull; /** - * Bitcoin price value with variable precision. + * Monero price value with variable precision. * <p> * <br/> * We wrap an object implementing the {@link Monetary} interface from bitcoinj. We respect the @@ -82,23 +83,23 @@ public class Price extends MonetaryWrapper implements Comparable<Price> { } } - public Volume getVolumeByAmount(Coin amount) { + public Volume getVolumeByAmount(BigInteger amount) { if (monetary instanceof Fiat) - return new Volume(new ExchangeRate((Fiat) monetary).coinToFiat(amount)); + return new Volume(new ExchangeRate((Fiat) monetary).coinToFiat(HavenoUtils.atomicUnitsToCoin(amount))); else if (monetary instanceof Altcoin) - return new Volume(new AltcoinExchangeRate((Altcoin) monetary).coinToAltcoin(amount)); + return new Volume(new AltcoinExchangeRate((Altcoin) monetary).coinToAltcoin(HavenoUtils.atomicUnitsToCoin(amount))); else throw new IllegalStateException("Monetary must be either of type Fiat or Altcoin"); } - public Coin getAmountByVolume(Volume volume) { + public BigInteger getAmountByVolume(Volume volume) { Monetary monetary = volume.getMonetary(); if (monetary instanceof Fiat && this.monetary instanceof Fiat) - return new ExchangeRate((Fiat) this.monetary).fiatToCoin((Fiat) monetary); + return HavenoUtils.coinToAtomicUnits(new ExchangeRate((Fiat) this.monetary).fiatToCoin((Fiat) monetary)); else if (monetary instanceof Altcoin && this.monetary instanceof Altcoin) - return new AltcoinExchangeRate((Altcoin) this.monetary).altcoinToCoin((Altcoin) monetary); + return HavenoUtils.coinToAtomicUnits(new AltcoinExchangeRate((Altcoin) this.monetary).altcoinToCoin((Altcoin) monetary)); else - return Coin.ZERO; + return BigInteger.valueOf(0); } public String getCurrencyCode() { diff --git a/core/src/main/java/bisq/core/offer/CreateOfferService.java b/core/src/main/java/bisq/core/offer/CreateOfferService.java index 92a96bdb..b72cedd3 100644 --- a/core/src/main/java/bisq/core/offer/CreateOfferService.java +++ b/core/src/main/java/bisq/core/offer/CreateOfferService.java @@ -45,6 +45,7 @@ import org.bitcoinj.core.Coin; import javax.inject.Inject; import javax.inject.Singleton; +import java.math.BigInteger; import java.util.Date; import java.util.List; import java.util.Map; @@ -104,8 +105,8 @@ public class CreateOfferService { public Offer createAndGetOffer(String offerId, OfferDirection direction, String currencyCode, - Coin amount, - Coin minAmount, + BigInteger amount, + BigInteger minAmount, Price price, Coin txFee, boolean useMarketBasedPrice, @@ -128,8 +129,8 @@ public class CreateOfferService { price == null ? null : price.getValue(), useMarketBasedPrice, marketPriceMargin, - amount.value, - minAmount.value, + amount, + minAmount, buyerSecurityDepositAsDouble); long creationTime = new Date().getTime(); @@ -146,8 +147,8 @@ public class CreateOfferService { long priceAsLong = price != null ? price.getValue() : 0L; double marketPriceMarginParam = useMarketBasedPriceValue ? marketPriceMargin : 0; - long amountAsLong = amount != null ? amount.getValue() : 0L; - long minAmountAsLong = minAmount != null ? minAmount.getValue() : 0L; + long amountAsLong = amount != null ? amount.longValueExact() : 0L; + long minAmountAsLong = minAmount != null ? minAmount.longValueExact() : 0L; boolean isCryptoCurrency = CurrencyUtil.isCryptoCurrency(currencyCode); String baseCurrencyCode = isCryptoCurrency ? currencyCode : Res.getBaseCurrencyCode(); String counterCurrencyCode = isCryptoCurrency ? Res.getBaseCurrencyCode() : currencyCode; @@ -155,10 +156,10 @@ public class CreateOfferService { List<String> acceptedCountryCodes = PaymentAccountUtil.getAcceptedCountryCodes(paymentAccount); String bankId = PaymentAccountUtil.getBankId(paymentAccount); List<String> acceptedBanks = PaymentAccountUtil.getAcceptedBanks(paymentAccount); - double sellerSecurityDeposit = getSellerSecurityDepositAsDouble(buyerSecurityDepositAsDouble); - Coin makerFeeAsCoin = HavenoUtils.getMakerFee(amount); - Coin buyerSecurityDepositAsCoin = getBuyerSecurityDeposit(amount, buyerSecurityDepositAsDouble); - Coin sellerSecurityDepositAsCoin = getSellerSecurityDeposit(amount, sellerSecurityDeposit); + double sellerSecurityDepositAsDouble = getSellerSecurityDepositAsDouble(buyerSecurityDepositAsDouble); + BigInteger makerFee = HavenoUtils.getMakerFee(amount); + BigInteger buyerSecurityDeposit = getBuyerSecurityDeposit(amount, buyerSecurityDepositAsDouble); + BigInteger sellerSecurityDeposit = getSellerSecurityDeposit(amount, sellerSecurityDepositAsDouble); long maxTradeLimit = offerUtil.getMaxTradeLimit(paymentAccount, currencyCode, direction); long maxTradePeriod = paymentAccount.getMaxTradePeriod(); @@ -178,7 +179,7 @@ public class CreateOfferService { buyerSecurityDepositAsDouble, paymentAccount, currencyCode, - makerFeeAsCoin); + makerFee); OfferPayload offerPayload = new OfferPayload(offerId, creationTime, @@ -201,9 +202,9 @@ public class CreateOfferService { acceptedBanks, Version.VERSION, xmrWalletService.getWallet().getHeight(), - makerFeeAsCoin.value, - buyerSecurityDepositAsCoin.value, - sellerSecurityDepositAsCoin.value, + makerFee.longValueExact(), + buyerSecurityDeposit.longValueExact(), + sellerSecurityDeposit.longValueExact(), maxTradeLimit, maxTradePeriod, useAutoClose, @@ -222,12 +223,12 @@ public class CreateOfferService { return offer; } - public Coin getReservedFundsForOffer(OfferDirection direction, - Coin amount, + public BigInteger getReservedFundsForOffer(OfferDirection direction, + BigInteger amount, double buyerSecurityDeposit, double sellerSecurityDeposit) { - Coin reservedFundsForOffer = getSecurityDeposit(direction, + BigInteger reservedFundsForOffer = getSecurityDeposit(direction, amount, buyerSecurityDeposit, sellerSecurityDeposit); @@ -237,8 +238,8 @@ public class CreateOfferService { return reservedFundsForOffer; } - public Coin getSecurityDeposit(OfferDirection direction, - Coin amount, + public BigInteger getSecurityDeposit(OfferDirection direction, + BigInteger amount, double buyerSecurityDeposit, double sellerSecurityDeposit) { return offerUtil.isBuyOffer(direction) ? @@ -260,26 +261,25 @@ public class CreateOfferService { return marketPrice != null && marketPrice.isExternallyProvidedPrice(); } - private Coin getBuyerSecurityDeposit(Coin amount, double buyerSecurityDeposit) { - Coin percentOfAmountAsCoin = CoinUtil.getPercentOfAmountAsCoin(buyerSecurityDeposit, amount); - return getBoundedBuyerSecurityDeposit(percentOfAmountAsCoin); + private BigInteger getBuyerSecurityDeposit(BigInteger amount, double buyerSecurityDeposit) { + BigInteger percentOfAmount = CoinUtil.getPercentOfAmount(buyerSecurityDeposit, amount); + return getBoundedBuyerSecurityDeposit(percentOfAmount); } - private Coin getSellerSecurityDeposit(Coin amount, double sellerSecurityDeposit) { - Coin amountAsCoin = (amount == null) ? Coin.ZERO : amount; - Coin percentOfAmountAsCoin = CoinUtil.getPercentOfAmountAsCoin(sellerSecurityDeposit, amountAsCoin); - return getBoundedSellerSecurityDeposit(percentOfAmountAsCoin); + private BigInteger getSellerSecurityDeposit(BigInteger amount, double sellerSecurityDeposit) { + BigInteger percentOfAmount = CoinUtil.getPercentOfAmount(sellerSecurityDeposit, amount); + return getBoundedSellerSecurityDeposit(percentOfAmount); } - private Coin getBoundedBuyerSecurityDeposit(Coin value) { + private 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 getBoundedSellerSecurityDeposit(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); } } diff --git a/core/src/main/java/bisq/core/offer/Offer.java b/core/src/main/java/bisq/core/offer/Offer.java index 7b6d7793..726298f1 100644 --- a/core/src/main/java/bisq/core/offer/Offer.java +++ b/core/src/main/java/bisq/core/offer/Offer.java @@ -40,7 +40,6 @@ import bisq.common.util.JsonExclude; import bisq.common.util.MathUtils; import bisq.common.util.Utilities; -import org.bitcoinj.core.Coin; import org.bitcoinj.utils.Fiat; import javafx.beans.property.ObjectProperty; @@ -49,6 +48,7 @@ import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; +import java.math.BigInteger; import java.security.PublicKey; import java.util.Date; @@ -246,7 +246,7 @@ public class Offer implements NetworkPayload, PersistablePayload { } @Nullable - public Volume getVolumeByAmount(Coin amount) { + public Volume getVolumeByAmount(BigInteger amount) { Price price = getPrice(); if (price == null || amount == null) { return null; @@ -291,34 +291,34 @@ public class Offer implements NetworkPayload, PersistablePayload { /////////////////////////////////////////////////////////////////////////////////////////// // get the amount needed for the maker to reserve the offer - public Coin getReserveAmount() { - Coin reserveAmount = getDirection() == OfferDirection.BUY ? getBuyerSecurityDeposit() : getSellerSecurityDeposit(); + public BigInteger getReserveAmount() { + BigInteger reserveAmount = getDirection() == OfferDirection.BUY ? getBuyerSecurityDeposit() : getSellerSecurityDeposit(); if (getDirection() == OfferDirection.SELL) reserveAmount = reserveAmount.add(getAmount()); return reserveAmount; } - public Coin getMakerFee() { - return Coin.valueOf(offerPayload.getMakerFee()); + public BigInteger getMakerFee() { + return BigInteger.valueOf(offerPayload.getMakerFee()); } - public Coin getBuyerSecurityDeposit() { - return Coin.valueOf(offerPayload.getBuyerSecurityDeposit()); + public BigInteger getBuyerSecurityDeposit() { + return BigInteger.valueOf(offerPayload.getBuyerSecurityDeposit()); } - public Coin getSellerSecurityDeposit() { - return Coin.valueOf(offerPayload.getSellerSecurityDeposit()); + public BigInteger getSellerSecurityDeposit() { + return BigInteger.valueOf(offerPayload.getSellerSecurityDeposit()); } - public Coin getMaxTradeLimit() { - return Coin.valueOf(offerPayload.getMaxTradeLimit()); + public BigInteger getMaxTradeLimit() { + return BigInteger.valueOf(offerPayload.getMaxTradeLimit()); } - public Coin getAmount() { - return Coin.valueOf(offerPayload.getAmount()); + public BigInteger getAmount() { + return BigInteger.valueOf(offerPayload.getAmount()); } - public Coin getMinAmount() { - return Coin.valueOf(offerPayload.getMinAmount()); + public BigInteger getMinAmount() { + return BigInteger.valueOf(offerPayload.getMinAmount()); } public boolean isRange() { diff --git a/core/src/main/java/bisq/core/offer/OfferFilterService.java b/core/src/main/java/bisq/core/offer/OfferFilterService.java index d4161946..87847363 100644 --- a/core/src/main/java/bisq/core/offer/OfferFilterService.java +++ b/core/src/main/java/bisq/core/offer/OfferFilterService.java @@ -208,7 +208,7 @@ public class OfferFilterService { .map(paymentAccount -> accountAgeWitnessService.getMyTradeLimit(paymentAccount, offer.getCurrencyCode(), offer.getMirroredDirection())) .orElse(0L); - long offerMinAmount = offer.getMinAmount().value; + long offerMinAmount = offer.getMinAmount().longValueExact(); log.debug("isInsufficientTradeLimit accountOptional={}, myTradeLimit={}, offerMinAmount={}, ", accountOptional.isPresent() ? accountOptional.get().getAccountName() : "null", Coin.valueOf(myTradeLimit).toFriendlyString(), diff --git a/core/src/main/java/bisq/core/offer/OfferForJson.java b/core/src/main/java/bisq/core/offer/OfferForJson.java index 093d5be8..3eb5483a 100644 --- a/core/src/main/java/bisq/core/offer/OfferForJson.java +++ b/core/src/main/java/bisq/core/offer/OfferForJson.java @@ -22,14 +22,14 @@ import bisq.core.locale.Res; import bisq.core.monetary.Price; import bisq.core.monetary.Volume; import bisq.core.payment.payload.PaymentMethod; - +import bisq.core.trade.HavenoUtils; import bisq.common.util.MathUtils; -import org.bitcoinj.core.Coin; import org.bitcoinj.utils.MonetaryFormat; import com.fasterxml.jackson.annotation.JsonIgnore; +import java.math.BigInteger; import java.util.Date; import org.slf4j.Logger; @@ -77,8 +77,8 @@ public class OfferForJson { public OfferForJson(OfferDirection direction, String currencyCode, - Coin minAmount, - Coin amount, + BigInteger minAmount, + BigInteger amount, @Nullable Price price, Date date, String id, @@ -88,8 +88,8 @@ public class OfferForJson { this.direction = direction; this.currencyCode = currencyCode; - this.minAmount = minAmount.value; - this.amount = amount.value; + this.minAmount = minAmount.longValueExact(); + this.amount = amount.longValueExact(); this.price = price.getValue(); this.date = date.getTime(); this.id = id; @@ -114,21 +114,21 @@ public class OfferForJson { priceDisplayString = altcoinFormat.noCode().format(price.getMonetary()).toString(); primaryMarketMinAmountDisplayString = altcoinFormat.noCode().format(getMinVolume().getMonetary()).toString(); primaryMarketAmountDisplayString = altcoinFormat.noCode().format(getVolume().getMonetary()).toString(); - primaryMarketMinVolumeDisplayString = coinFormat.noCode().format(getMinAmountAsCoin()).toString(); - primaryMarketVolumeDisplayString = coinFormat.noCode().format(getAmountAsCoin()).toString(); + primaryMarketMinVolumeDisplayString = HavenoUtils.formatToXmr(getMinAmount()).toString(); + primaryMarketVolumeDisplayString = HavenoUtils.formatToXmr(getAmount()).toString(); primaryMarketPrice = price.getValue(); primaryMarketMinAmount = getMinVolume().getValue(); primaryMarketAmount = getVolume().getValue(); - primaryMarketMinVolume = getMinAmountAsCoin().getValue(); - primaryMarketVolume = getAmountAsCoin().getValue(); + primaryMarketMinVolume = getMinAmount().longValueExact(); + primaryMarketVolume = getAmount().longValueExact(); } else { primaryMarketDirection = direction; currencyPair = Res.getBaseCurrencyCode() + "/" + currencyCode; priceDisplayString = fiatFormat.noCode().format(price.getMonetary()).toString(); - primaryMarketMinAmountDisplayString = coinFormat.noCode().format(getMinAmountAsCoin()).toString(); - primaryMarketAmountDisplayString = coinFormat.noCode().format(getAmountAsCoin()).toString(); + primaryMarketMinAmountDisplayString = HavenoUtils.formatToXmr(getMinAmount()).toString(); + primaryMarketAmountDisplayString = HavenoUtils.formatToXmr(getAmount()).toString(); primaryMarketMinVolumeDisplayString = fiatFormat.noCode().format(getMinVolume().getMonetary()).toString(); primaryMarketVolumeDisplayString = fiatFormat.noCode().format(getVolume().getMonetary()).toString(); @@ -137,8 +137,8 @@ public class OfferForJson { primaryMarketMinVolume = (long) MathUtils.scaleUpByPowerOf10(getMinVolume().getValue(), 4); primaryMarketVolume = (long) MathUtils.scaleUpByPowerOf10(getVolume().getValue(), 4); - primaryMarketMinAmount = getMinAmountAsCoin().getValue(); - primaryMarketAmount = getAmountAsCoin().getValue(); + primaryMarketMinAmount = getMinAmount().longValueExact(); + primaryMarketAmount = getAmount().longValueExact(); } } catch (Throwable t) { @@ -150,19 +150,19 @@ public class OfferForJson { return Price.valueOf(currencyCode, price); } - private Coin getAmountAsCoin() { - return Coin.valueOf(amount); + private BigInteger getAmount() { + return BigInteger.valueOf(amount); } - private Coin getMinAmountAsCoin() { - return Coin.valueOf(minAmount); + private BigInteger getMinAmount() { + return BigInteger.valueOf(minAmount); } private Volume getVolume() { - return getPrice().getVolumeByAmount(getAmountAsCoin()); + return getPrice().getVolumeByAmount(getAmount()); } private Volume getMinVolume() { - return getPrice().getVolumeByAmount(getMinAmountAsCoin()); + return getPrice().getVolumeByAmount(getMinAmount()); } } diff --git a/core/src/main/java/bisq/core/offer/OfferRestrictions.java b/core/src/main/java/bisq/core/offer/OfferRestrictions.java index 06b31891..5a91bf66 100644 --- a/core/src/main/java/bisq/core/offer/OfferRestrictions.java +++ b/core/src/main/java/bisq/core/offer/OfferRestrictions.java @@ -21,9 +21,9 @@ import bisq.common.app.Capabilities; import bisq.common.app.Capability; import bisq.common.config.Config; import bisq.common.util.Utilities; +import bisq.core.trade.HavenoUtils; -import org.bitcoinj.core.Coin; - +import java.math.BigInteger; import java.util.Date; import java.util.GregorianCalendar; import java.util.Map; @@ -37,7 +37,7 @@ public class OfferRestrictions { return new Date().after(REQUIRE_TOR_NODE_ADDRESS_V3_DATE) && Config.baseCurrencyNetwork().isMainnet(); } - public static Coin TOLERATED_SMALL_TRADE_AMOUNT = Coin.parseCoin("2.0"); + public static BigInteger TOLERATED_SMALL_TRADE_AMOUNT = HavenoUtils.xmrToAtomicUnits(2.0); static boolean hasOfferMandatoryCapability(Offer offer, Capability mandatoryCapability) { Map<String, String> extraDataMap = offer.getExtraDataMap(); diff --git a/core/src/main/java/bisq/core/offer/OfferUtil.java b/core/src/main/java/bisq/core/offer/OfferUtil.java index ca1dd9c8..f4258a7e 100644 --- a/core/src/main/java/bisq/core/offer/OfferUtil.java +++ b/core/src/main/java/bisq/core/offer/OfferUtil.java @@ -40,7 +40,6 @@ import bisq.common.app.Capabilities; import bisq.common.app.Version; import bisq.common.util.MathUtils; import bisq.common.util.Utilities; -import org.bitcoinj.core.Coin; import org.bitcoinj.core.Transaction; import org.bitcoinj.core.TransactionInput; import org.bitcoinj.core.TransactionOutput; @@ -49,6 +48,7 @@ import org.bitcoinj.utils.Fiat; import javax.inject.Inject; import javax.inject.Singleton; +import java.math.BigInteger; import java.util.HashMap; import java.util.Map; import java.util.Optional; @@ -129,7 +129,7 @@ public class OfferUtil { * @param balance a wallet balance * @return true if balance >= cost */ - public boolean isBalanceSufficient(Coin cost, Coin balance) { + public boolean isBalanceSufficient(BigInteger cost, BigInteger balance) { return cost != null && balance.compareTo(cost) >= 0; } @@ -141,16 +141,15 @@ public class OfferUtil { * @param balance a wallet balance * @return the wallet balance shortage for the given cost, else zero. */ - public Coin getBalanceShortage(Coin cost, Coin balance) { + public BigInteger getBalanceShortage(BigInteger cost, BigInteger balance) { if (cost != null) { - Coin shortage = cost.subtract(balance); - return shortage.isNegative() ? Coin.ZERO : shortage; + BigInteger shortage = cost.subtract(balance); + return shortage.compareTo(BigInteger.valueOf(0)) < 0 ? BigInteger.valueOf(0) : shortage; } else { - return Coin.ZERO; + return BigInteger.valueOf(0); } } - public double calculateManualPrice(double volumeAsDouble, double amountAsDouble) { return volumeAsDouble / amountAsDouble; } @@ -163,7 +162,7 @@ public class OfferUtil { return offer != null && offer.getPaymentMethod().isBlockchain(); } - public Optional<Volume> getFeeInUserFiatCurrency(Coin makerFee, + public Optional<Volume> getFeeInUserFiatCurrency(BigInteger makerFee, CoinFormatter formatter) { String userCurrencyCode = preferences.getPreferredTradeCurrency().getCode(); if (CurrencyUtil.isCryptoCurrency(userCurrencyCode)) { @@ -216,8 +215,8 @@ public class OfferUtil { public void validateOfferData(double buyerSecurityDeposit, PaymentAccount paymentAccount, String currencyCode, - Coin makerFeeAsCoin) { - checkNotNull(makerFeeAsCoin, "makerFee must not be null"); + BigInteger makerFee) { + checkNotNull(makerFee, "makerFee must not be null"); checkNotNull(p2PService.getAddress(), "Address must not be null"); checkArgument(buyerSecurityDeposit <= getMaxBuyerSecurityDepositAsPercent(), "securityDeposit must not exceed " + @@ -231,7 +230,7 @@ public class OfferUtil { Res.get("offerbook.warning.paymentMethodBanned")); } - private Optional<Volume> getFeeInUserFiatCurrency(Coin makerFee, String userCurrencyCode, CoinFormatter formatter) { + private Optional<Volume> getFeeInUserFiatCurrency(BigInteger makerFee, String userCurrencyCode, CoinFormatter formatter) { MarketPrice marketPrice = priceFeedService.getMarketPrice(userCurrencyCode); if (marketPrice != null && makerFee != null) { long marketPriceAsLong = roundDoubleToLong(scaleUpByPowerOf10(marketPrice.getPrice(), Fiat.SMALLEST_UNIT_EXPONENT)); diff --git a/core/src/main/java/bisq/core/offer/OpenOfferManager.java b/core/src/main/java/bisq/core/offer/OpenOfferManager.java index ec081c30..9e867e13 100644 --- a/core/src/main/java/bisq/core/offer/OpenOfferManager.java +++ b/core/src/main/java/bisq/core/offer/OpenOfferManager.java @@ -73,7 +73,6 @@ import bisq.common.persistence.PersistenceManager; import bisq.common.proto.network.NetworkEnvelope; import bisq.common.proto.persistable.PersistedDataHost; import bisq.common.util.Tuple2; -import org.bitcoinj.core.Coin; import javax.inject.Inject; @@ -800,8 +799,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe } // get offer reserve amount - Coin offerReserveAmountCoin = openOffer.getOffer().getReserveAmount(); - BigInteger offerReserveAmount = HavenoUtils.centinerosToAtomicUnits(offerReserveAmountCoin.value); + BigInteger offerReserveAmount = openOffer.getOffer().getReserveAmount(); // handle sufficient available balance if (xmrWalletService.getWallet().getUnlockedBalance(0).compareTo(offerReserveAmount) >= 0) { @@ -814,7 +812,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe // otherwise sign and post offer else { - signAndPostOffer(openOffer, offerReserveAmountCoin, true, resultHandler, errorMessageHandler); + signAndPostOffer(openOffer, offerReserveAmount, true, resultHandler, errorMessageHandler); } return; } @@ -887,7 +885,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe } private void signAndPostOffer(OpenOffer openOffer, - Coin offerReserveAmount, + BigInteger offerReserveAmount, boolean useSavingsWallet, // TODO: remove this TransactionResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) { log.info("Signing and posting offer " + openOffer.getId()); @@ -980,8 +978,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe // verify maker's trade fee Offer offer = new Offer(request.getOfferPayload()); - BigInteger tradeFee = HavenoUtils.coinToAtomicUnits(HavenoUtils.getMakerFee(offer.getAmount())); - if (!tradeFee.equals(HavenoUtils.coinToAtomicUnits(offer.getMakerFee()))) { + BigInteger tradeFee = HavenoUtils.getMakerFee(offer.getAmount()); + if (!tradeFee.equals(offer.getMakerFee())) { errorMessage = "Wrong trade fee for offer " + request.offerId; log.info(errorMessage); sendAckMessage(request.getClass(), peer, request.getPubKeyRing(), request.getOfferId(), request.getUid(), false, errorMessage); @@ -989,8 +987,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe } // verify maker's reserve tx (double spend, trade fee, trade amount, mining fee) - BigInteger sendAmount = HavenoUtils.coinToAtomicUnits(offer.getDirection() == OfferDirection.BUY ? Coin.ZERO : offer.getAmount()); - BigInteger securityDeposit = HavenoUtils.coinToAtomicUnits(offer.getDirection() == OfferDirection.BUY ? offer.getBuyerSecurityDeposit() : offer.getSellerSecurityDeposit()); + BigInteger sendAmount = offer.getDirection() == OfferDirection.BUY ? BigInteger.valueOf(0) : offer.getAmount(); + BigInteger securityDeposit = offer.getDirection() == OfferDirection.BUY ? offer.getBuyerSecurityDeposit() : offer.getSellerSecurityDeposit(); MoneroTx reserveTx = xmrWalletService.verifyTradeTx( tradeFee, sendAmount, @@ -1011,8 +1009,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe SignedOffer signedOffer = new SignedOffer( System.currentTimeMillis(), signedOfferPayload.getId(), - HavenoUtils.coinToAtomicUnits(offer.getAmount()).longValueExact(), - HavenoUtils.coinToAtomicUnits(HavenoUtils.getMakerFee(offer.getAmount())).longValueExact(), + offer.getAmount().longValueExact(), + HavenoUtils.getMakerFee(offer.getAmount()).longValueExact(), request.getReserveTxHash(), request.getReserveTxHex(), request.getReserveTxKeyImages(), diff --git a/core/src/main/java/bisq/core/offer/availability/tasks/SendOfferAvailabilityRequest.java b/core/src/main/java/bisq/core/offer/availability/tasks/SendOfferAvailabilityRequest.java index cf5238aa..7198c773 100644 --- a/core/src/main/java/bisq/core/offer/availability/tasks/SendOfferAvailabilityRequest.java +++ b/core/src/main/java/bisq/core/offer/availability/tasks/SendOfferAvailabilityRequest.java @@ -21,7 +21,6 @@ import bisq.core.btc.model.XmrAddressEntry; import bisq.core.btc.wallet.XmrWalletService; import bisq.core.monetary.Price; import bisq.core.offer.Offer; -import bisq.core.offer.OfferUtil; import bisq.core.offer.availability.OfferAvailabilityModel; import bisq.core.offer.messages.OfferAvailabilityRequest; import bisq.core.trade.HavenoUtils; @@ -72,9 +71,9 @@ public class SendOfferAvailabilityRequest extends Task<OfferAvailabilityModel> { offer.getId(), P2PService.getMyNodeAddress(), p2PService.getKeyRing().getPubKeyRing(), - offer.getAmount().value, + offer.getAmount().longValueExact(), price.getValue(), - HavenoUtils.getTakerFee(offer.getAmount()).value, + HavenoUtils.getTakerFee(offer.getAmount()).longValueExact(), user.getAccountId(), paymentAccountId, paymentMethodId, diff --git a/core/src/main/java/bisq/core/offer/placeoffer/PlaceOfferModel.java b/core/src/main/java/bisq/core/offer/placeoffer/PlaceOfferModel.java index 948e6dfc..9fe49ce3 100644 --- a/core/src/main/java/bisq/core/offer/placeoffer/PlaceOfferModel.java +++ b/core/src/main/java/bisq/core/offer/placeoffer/PlaceOfferModel.java @@ -34,7 +34,8 @@ import bisq.common.taskrunner.Model; import bisq.network.p2p.P2PService; -import org.bitcoinj.core.Coin; +import java.math.BigInteger; + import org.bitcoinj.core.Transaction; import lombok.Getter; @@ -50,7 +51,7 @@ import monero.wallet.model.MoneroTxWallet; public class PlaceOfferModel implements Model { // Immutable private final Offer offer; - private final Coin reservedFundsForOffer; + private final BigInteger reservedFundsForOffer; private final boolean useSavingsWallet; private final P2PService p2PService; private final BtcWalletService walletService; @@ -78,7 +79,7 @@ public class PlaceOfferModel implements Model { private SignOfferResponse signOfferResponse; public PlaceOfferModel(Offer offer, - Coin reservedFundsForOffer, + BigInteger reservedFundsForOffer, boolean useSavingsWallet, P2PService p2PService, BtcWalletService walletService, diff --git a/core/src/main/java/bisq/core/offer/placeoffer/tasks/MakerReserveOfferFunds.java b/core/src/main/java/bisq/core/offer/placeoffer/tasks/MakerReserveOfferFunds.java index 8a9d611c..cac12924 100644 --- a/core/src/main/java/bisq/core/offer/placeoffer/tasks/MakerReserveOfferFunds.java +++ b/core/src/main/java/bisq/core/offer/placeoffer/tasks/MakerReserveOfferFunds.java @@ -23,14 +23,12 @@ import bisq.core.btc.model.XmrAddressEntry; import bisq.core.offer.Offer; import bisq.core.offer.OfferDirection; import bisq.core.offer.placeoffer.PlaceOfferModel; -import bisq.core.trade.HavenoUtils; import lombok.extern.slf4j.Slf4j; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; -import org.bitcoinj.core.Coin; import monero.daemon.model.MoneroOutput; import monero.wallet.model.MoneroTxWallet; @@ -54,9 +52,9 @@ public class MakerReserveOfferFunds extends Task<PlaceOfferModel> { model.getXmrWalletService().getConnectionsService().verifyConnection(); // create reserve tx - BigInteger makerFee = HavenoUtils.coinToAtomicUnits(offer.getMakerFee()); - BigInteger sendAmount = HavenoUtils.coinToAtomicUnits(offer.getDirection() == OfferDirection.BUY ? Coin.ZERO : offer.getAmount()); - BigInteger securityDeposit = HavenoUtils.coinToAtomicUnits(offer.getDirection() == OfferDirection.BUY ? offer.getBuyerSecurityDeposit() : offer.getSellerSecurityDeposit()); + BigInteger makerFee = offer.getMakerFee(); + BigInteger sendAmount = offer.getDirection() == OfferDirection.BUY ? BigInteger.valueOf(0) : offer.getAmount(); + BigInteger securityDeposit = offer.getDirection() == OfferDirection.BUY ? offer.getBuyerSecurityDeposit() : offer.getSellerSecurityDeposit(); String returnAddress = model.getXmrWalletService().getOrCreateAddressEntry(offer.getId(), XmrAddressEntry.Context.TRADE_PAYOUT).getAddressString(); MoneroTxWallet reserveTx = model.getXmrWalletService().createReserveTx(makerFee, sendAmount, securityDeposit, returnAddress); diff --git a/core/src/main/java/bisq/core/offer/placeoffer/tasks/ValidateOffer.java b/core/src/main/java/bisq/core/offer/placeoffer/tasks/ValidateOffer.java index bf99b7a2..bd8a6cea 100644 --- a/core/src/main/java/bisq/core/offer/placeoffer/tasks/ValidateOffer.java +++ b/core/src/main/java/bisq/core/offer/placeoffer/tasks/ValidateOffer.java @@ -30,6 +30,8 @@ import org.bitcoinj.core.Coin; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import java.math.BigInteger; + public class ValidateOffer extends Task<PlaceOfferModel> { public ValidateOffer(TaskRunner<PlaceOfferModel> taskHandler, PlaceOfferModel model) { super(taskHandler, model); @@ -42,13 +44,13 @@ public class ValidateOffer extends Task<PlaceOfferModel> { runInterceptHook(); // Coins - checkCoinNotNullOrZero(offer.getAmount(), "Amount"); - checkCoinNotNullOrZero(offer.getMinAmount(), "MinAmount"); - checkCoinNotNullOrZero(offer.getMakerFee(), "MakerFee"); - checkCoinNotNullOrZero(offer.getBuyerSecurityDeposit(), "buyerSecurityDeposit"); - checkCoinNotNullOrZero(offer.getSellerSecurityDeposit(), "sellerSecurityDeposit"); + checkBINotNullOrZero(offer.getAmount(), "Amount"); + checkBINotNullOrZero(offer.getMinAmount(), "MinAmount"); + checkBINotNullOrZero(offer.getMakerFee(), "MakerFee"); + checkBINotNullOrZero(offer.getBuyerSecurityDeposit(), "buyerSecurityDeposit"); + checkBINotNullOrZero(offer.getSellerSecurityDeposit(), "sellerSecurityDeposit"); //checkCoinNotNullOrZero(offer.getTxFee(), "txFee"); // TODO: remove from data model - checkCoinNotNullOrZero(offer.getMaxTradeLimit(), "MaxTradeLimit"); + checkBINotNullOrZero(offer.getMaxTradeLimit(), "MaxTradeLimit"); // We remove those checks to be more flexible with future changes. /*checkArgument(offer.getMakerFee().value >= FeeService.getMinMakerFee(offer.isCurrencyForMakerFeeBtc()).value, @@ -67,8 +69,8 @@ public class ValidateOffer extends Task<PlaceOfferModel> { "MinAmount is less than " + ProposalConsensus.getMinTradeAmount().toFriendlyString());*/ long maxAmount = model.getAccountAgeWitnessService().getMyTradeLimit(model.getUser().getPaymentAccount(offer.getMakerPaymentAccountId()), offer.getCurrencyCode(), offer.getDirection()); - checkArgument(offer.getAmount().longValue() <= maxAmount, - "Amount is larger than " + HavenoUtils.coinToXmr(offer.getPaymentMethod().getMaxTradeLimitAsCoin(offer.getCurrencyCode())) + " XMR"); + checkArgument(offer.getAmount().longValueExact() <= maxAmount, + "Amount is larger than " + HavenoUtils.atomicUnitsToXmr(offer.getPaymentMethod().getMaxTradeLimit(offer.getCurrencyCode())) + " XMR"); checkArgument(offer.getAmount().compareTo(offer.getMinAmount()) >= 0, "MinAmount is larger than Amount"); checkNotNull(offer.getPrice(), "Price is null"); @@ -100,6 +102,12 @@ public class ValidateOffer extends Task<PlaceOfferModel> { } } + public static void checkBINotNullOrZero(BigInteger value, String name) { + checkNotNull(value, name + " is null"); + checkArgument(value.compareTo(BigInteger.valueOf(0)) > 0, + name + " must be positive. " + name + "=" + value); + } + public static void checkCoinNotNullOrZero(Coin value, String name) { checkNotNull(value, name + " is null"); checkArgument(value.isPositive(), diff --git a/core/src/main/java/bisq/core/offer/takeoffer/TakeOfferModel.java b/core/src/main/java/bisq/core/offer/takeoffer/TakeOfferModel.java index a0a5d6c5..23a4e4d5 100644 --- a/core/src/main/java/bisq/core/offer/takeoffer/TakeOfferModel.java +++ b/core/src/main/java/bisq/core/offer/takeoffer/TakeOfferModel.java @@ -31,10 +31,9 @@ import bisq.core.provider.price.PriceFeedService; import bisq.core.trade.HavenoUtils; import bisq.common.taskrunner.Model; -import org.bitcoinj.core.Coin; - import javax.inject.Inject; +import java.math.BigInteger; import java.util.Objects; import lombok.Getter; @@ -46,11 +45,8 @@ import static bisq.core.btc.model.XmrAddressEntry.Context.OFFER_FUNDING; import static bisq.core.offer.OfferDirection.SELL; import static bisq.core.util.VolumeUtil.getAdjustedVolumeForHalCash; import static bisq.core.util.VolumeUtil.getRoundedFiatVolume; -import static bisq.core.util.coin.CoinUtil.minCoin; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; -import static org.bitcoinj.core.Coin.ZERO; -import static org.bitcoinj.core.Coin.valueOf; @Slf4j public class TakeOfferModel implements Model { @@ -64,23 +60,23 @@ public class TakeOfferModel implements Model { @Getter private XmrAddressEntry addressEntry; @Getter - private Coin amount; + private BigInteger amount; private Offer offer; private PaymentAccount paymentAccount; @Getter - private Coin securityDeposit; + private BigInteger securityDeposit; private boolean useSavingsWallet; @Getter - private Coin takerFee; + private BigInteger takerFee; @Getter - private Coin totalToPayAsCoin; + private BigInteger totalToPay; @Getter - private Coin missingCoin = ZERO; + private BigInteger missingCoin = BigInteger.valueOf(0); @Getter - private Coin totalAvailableBalance; + private BigInteger totalAvailableBalance; @Getter - private Coin availableBalance; + private BigInteger availableBalance; @Getter private boolean isXmrWalletFunded; @Getter @@ -107,7 +103,7 @@ public class TakeOfferModel implements Model { validateModelInputs(); this.useSavingsWallet = useSavingsWallet; - this.amount = valueOf(Math.min(offer.getAmount().value, getMaxTradeLimit())); + this.amount = offer.getAmount().min(BigInteger.valueOf(getMaxTradeLimit())); this.securityDeposit = offer.getDirection() == SELL ? offer.getBuyerSecurityDeposit() : offer.getSellerSecurityDeposit(); @@ -130,9 +126,9 @@ public class TakeOfferModel implements Model { // 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. - Coin feeAndSecDeposit = securityDeposit.add(takerFee); + BigInteger feeAndSecDeposit = securityDeposit.add(takerFee); - totalToPayAsCoin = offer.isBuyOffer() + totalToPay = offer.isBuyOffer() ? feeAndSecDeposit.add(amount) : feeAndSecDeposit; @@ -155,9 +151,9 @@ public class TakeOfferModel implements Model { private void updateBalance() { totalAvailableBalance = xmrWalletService.getAvailableBalance(); - if (totalToPayAsCoin != null) availableBalance = minCoin(totalToPayAsCoin, totalAvailableBalance); - missingCoin = offerUtil.getBalanceShortage(totalToPayAsCoin, availableBalance); - isXmrWalletFunded = offerUtil.isBalanceSufficient(totalToPayAsCoin, availableBalance); + if (totalToPay != null) availableBalance = totalToPay.min(totalAvailableBalance); + missingCoin = offerUtil.getBalanceShortage(totalToPay, availableBalance); + isXmrWalletFunded = offerUtil.isBalanceSufficient(totalToPay, availableBalance); } private long getMaxTradeLimit() { @@ -167,15 +163,15 @@ public class TakeOfferModel implements Model { } @NotNull - public Coin getFundsNeededForTrade() { + public BigInteger getFundsNeededForTrade() { // If taking a buy offer, taker needs to reserve the offer.amt too. - return securityDeposit.add(offer.isBuyOffer() ? amount : ZERO); + return securityDeposit.add(offer.isBuyOffer() ? amount : BigInteger.valueOf(0)); } private void validateModelInputs() { checkNotNull(offer, "offer must not be null"); checkNotNull(offer.getAmount(), "offer amount must not be null"); - checkArgument(offer.getAmount().value > 0, "offer amount must not be zero"); + checkArgument(offer.getAmount().longValueExact() > 0, "offer amount must not be zero"); checkNotNull(offer.getPrice(), "offer price must not be null"); checkNotNull(paymentAccount, "payment account must not be null"); checkNotNull(addressEntry, "address entry must not be null"); @@ -186,13 +182,13 @@ public class TakeOfferModel implements Model { this.amount = null; this.availableBalance = null; this.isXmrWalletFunded = false; - this.missingCoin = ZERO; + this.missingCoin = BigInteger.valueOf(0); this.offer = null; this.paymentAccount = null; this.securityDeposit = null; this.takerFee = null; this.totalAvailableBalance = null; - this.totalToPayAsCoin = null; + this.totalToPay = null; this.useSavingsWallet = true; this.volume = null; } @@ -209,7 +205,7 @@ public class TakeOfferModel implements Model { ", amount=" + amount + "\n" + ", securityDeposit=" + securityDeposit + "\n" + ", takerFee=" + takerFee + "\n" + - ", totalToPayAsCoin=" + totalToPayAsCoin + "\n" + + ", totalToPay=" + totalToPay + "\n" + ", missingCoin=" + missingCoin + "\n" + ", totalAvailableBalance=" + totalAvailableBalance + "\n" + ", availableBalance=" + availableBalance + "\n" + diff --git a/core/src/main/java/bisq/core/payment/PaymentAccountUtil.java b/core/src/main/java/bisq/core/payment/PaymentAccountUtil.java index 92ad49d6..e44a5010 100644 --- a/core/src/main/java/bisq/core/payment/PaymentAccountUtil.java +++ b/core/src/main/java/bisq/core/payment/PaymentAccountUtil.java @@ -71,7 +71,7 @@ public class PaymentAccountUtil { AccountAgeWitnessService accountAgeWitnessService) { boolean hasChargebackRisk = hasChargebackRisk(offer.getPaymentMethod(), offer.getCurrencyCode()); boolean hasValidAccountAgeWitness = accountAgeWitnessService.getMyTradeLimit(paymentAccount, - offer.getCurrencyCode(), offer.getMirroredDirection()) >= offer.getMinAmount().value; + offer.getCurrencyCode(), offer.getMirroredDirection()) >= offer.getMinAmount().longValueExact(); return !hasChargebackRisk || hasValidAccountAgeWitness; } diff --git a/core/src/main/java/bisq/core/payment/TradeLimits.java b/core/src/main/java/bisq/core/payment/TradeLimits.java index 83ff61f8..c922578d 100644 --- a/core/src/main/java/bisq/core/payment/TradeLimits.java +++ b/core/src/main/java/bisq/core/payment/TradeLimits.java @@ -18,8 +18,7 @@ package bisq.core.payment; import bisq.common.util.MathUtils; - -import org.bitcoinj.core.Coin; +import bisq.core.trade.HavenoUtils; import javax.inject.Inject; import javax.inject.Singleton; @@ -29,12 +28,14 @@ import com.google.common.annotations.VisibleForTesting; import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import java.math.BigInteger; + import javax.annotation.Nullable; @Slf4j @Singleton public class TradeLimits { - private static final Coin MAX_TRADE_LIMIT = Coin.parseCoin("20"); // max trade limit for lowest risk payment method. Others will get derived from that. + private static final BigInteger MAX_TRADE_LIMIT = HavenoUtils.xmrToAtomicUnits(20.0); // max trade limit for lowest risk payment method. Others will get derived from that. @Nullable @Getter private static TradeLimits INSTANCE; @@ -57,7 +58,7 @@ public class TradeLimits { * @see bisq.core.payment.payload.PaymentMethod * @return the maximum trade limit */ - public Coin getMaxTradeLimit() { + public BigInteger getMaxTradeLimit() { return MAX_TRADE_LIMIT; } diff --git a/core/src/main/java/bisq/core/payment/payload/PaymentMethod.java b/core/src/main/java/bisq/core/payment/payload/PaymentMethod.java index 96f70183..55237ee5 100644 --- a/core/src/main/java/bisq/core/payment/payload/PaymentMethod.java +++ b/core/src/main/java/bisq/core/payment/payload/PaymentMethod.java @@ -77,8 +77,7 @@ import bisq.common.config.BaseCurrencyNetwork; import bisq.common.config.Config; import bisq.common.proto.persistable.PersistablePayload; -import org.bitcoinj.core.Coin; - +import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -113,10 +112,10 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme // risk factor so the relation between the risk categories stays the same as with the default values. // We must not change those values as it could lead to invalid offers if amount becomes lower then new trade limit. // Increasing might be ok, but needs more thought as well... - private static final Coin DEFAULT_TRADE_LIMIT_VERY_LOW_RISK = Coin.parseCoin("100"); - private static final Coin DEFAULT_TRADE_LIMIT_LOW_RISK = Coin.parseCoin("50"); - private static final Coin DEFAULT_TRADE_LIMIT_MID_RISK = Coin.parseCoin("25"); - private static final Coin DEFAULT_TRADE_LIMIT_HIGH_RISK = Coin.parseCoin("12.5"); + private static final BigInteger DEFAULT_TRADE_LIMIT_VERY_LOW_RISK = HavenoUtils.xmrToAtomicUnits(100); + private static final BigInteger DEFAULT_TRADE_LIMIT_LOW_RISK = HavenoUtils.xmrToAtomicUnits(50); + private static final BigInteger DEFAULT_TRADE_LIMIT_MID_RISK = HavenoUtils.xmrToAtomicUnits(25); + private static final BigInteger DEFAULT_TRADE_LIMIT_HIGH_RISK = HavenoUtils.xmrToAtomicUnits(12.5); public static final String UPHOLD_ID = "UPHOLD"; public static final String MONEY_BEAM_ID = "MONEY_BEAM"; @@ -291,19 +290,19 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme TRANSFERWISE_USD = new PaymentMethod(TRANSFERWISE_USD_ID, 4 * DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(TransferwiseUsdAccount.SUPPORTED_CURRENCIES)), PAYSERA = new PaymentMethod(PAYSERA_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(PayseraAccount.SUPPORTED_CURRENCIES)), PAXUM = new PaymentMethod(PAXUM_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(PaxumAccount.SUPPORTED_CURRENCIES)), - NEFT = new PaymentMethod(NEFT_ID, DAY, Coin.parseCoin("0.02"), getAssetCodes(NeftAccount.SUPPORTED_CURRENCIES)), + NEFT = new PaymentMethod(NEFT_ID, DAY, HavenoUtils.xmrToAtomicUnits(0.02), getAssetCodes(NeftAccount.SUPPORTED_CURRENCIES)), RTGS = new PaymentMethod(RTGS_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(RtgsAccount.SUPPORTED_CURRENCIES)), IMPS = new PaymentMethod(IMPS_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(ImpsAccount.SUPPORTED_CURRENCIES)), - UPI = new PaymentMethod(UPI_ID, DAY, Coin.parseCoin("0.05"), getAssetCodes(UpiAccount.SUPPORTED_CURRENCIES)), - PAYTM = new PaymentMethod(PAYTM_ID, DAY, Coin.parseCoin("0.05"), getAssetCodes(PaytmAccount.SUPPORTED_CURRENCIES)), + UPI = new PaymentMethod(UPI_ID, DAY, HavenoUtils.xmrToAtomicUnits(0.05), getAssetCodes(UpiAccount.SUPPORTED_CURRENCIES)), + PAYTM = new PaymentMethod(PAYTM_ID, DAY, HavenoUtils.xmrToAtomicUnits(0.05), getAssetCodes(PaytmAccount.SUPPORTED_CURRENCIES)), NEQUI = new PaymentMethod(NEQUI_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(NequiAccount.SUPPORTED_CURRENCIES)), - BIZUM = new PaymentMethod(BIZUM_ID, DAY, Coin.parseCoin("0.04"), getAssetCodes(BizumAccount.SUPPORTED_CURRENCIES)), + BIZUM = new PaymentMethod(BIZUM_ID, DAY, HavenoUtils.xmrToAtomicUnits(0.04), getAssetCodes(BizumAccount.SUPPORTED_CURRENCIES)), PIX = new PaymentMethod(PIX_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(PixAccount.SUPPORTED_CURRENCIES)), CAPITUAL = new PaymentMethod(CAPITUAL_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(CapitualAccount.SUPPORTED_CURRENCIES)), CELPAY = new PaymentMethod(CELPAY_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(CelPayAccount.SUPPORTED_CURRENCIES)), MONESE = new PaymentMethod(MONESE_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(MoneseAccount.SUPPORTED_CURRENCIES)), SATISPAY = new PaymentMethod(SATISPAY_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(SatispayAccount.SUPPORTED_CURRENCIES)), - TIKKIE = new PaymentMethod(TIKKIE_ID, DAY, Coin.parseCoin("0.05"), getAssetCodes(TikkieAccount.SUPPORTED_CURRENCIES)), + TIKKIE = new PaymentMethod(TIKKIE_ID, DAY, HavenoUtils.xmrToAtomicUnits(0.05), getAssetCodes(TikkieAccount.SUPPORTED_CURRENCIES)), VERSE = new PaymentMethod(VERSE_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(VerseAccount.SUPPORTED_CURRENCIES)), STRIKE = new PaymentMethod(STRIKE_ID, DAY, DEFAULT_TRADE_LIMIT_HIGH_RISK, getAssetCodes(StrikeAccount.SUPPORTED_CURRENCIES)), SWIFT = new PaymentMethod(SWIFT_ID, 7 * DAY, DEFAULT_TRADE_LIMIT_MID_RISK, getAssetCodes(SwiftAccount.SUPPORTED_CURRENCIES)), @@ -365,7 +364,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme } public static PaymentMethod getDummyPaymentMethod(String id) { - return new PaymentMethod(id, 0, Coin.ZERO, Arrays.asList()); + return new PaymentMethod(id, 0, BigInteger.valueOf(0), Arrays.asList()); } @@ -405,16 +404,16 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme * @param maxTradeLimit The max. allowed trade amount in Bitcoin for that payment method (depending on charge back risk) * @param supportedAssetCodes Supported asset codes. */ - private PaymentMethod(String id, long maxTradePeriod, Coin maxTradeLimit, List<String> supportedAssetCodes) { + private PaymentMethod(String id, long maxTradePeriod, BigInteger maxTradeLimit, List<String> supportedAssetCodes) { this.id = id; this.maxTradePeriod = maxTradePeriod; - this.maxTradeLimit = maxTradeLimit.value; + this.maxTradeLimit = maxTradeLimit.longValueExact(); this.supportedAssetCodes = supportedAssetCodes; } // Used for dummy entries in payment methods list (SHOW_ALL) private PaymentMethod(String id) { - this(id, 0, Coin.ZERO, new ArrayList<String>()); + this(id, 0, BigInteger.valueOf(0), new ArrayList<String>()); } @@ -435,7 +434,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme public static PaymentMethod fromProto(protobuf.PaymentMethod proto) { return new PaymentMethod(proto.getId(), proto.getMaxTradePeriod(), - Coin.valueOf(proto.getMaxTradeLimit()), + BigInteger.valueOf(proto.getMaxTradeLimit()), proto.getSupportedAssetCodesList()); } @@ -456,44 +455,43 @@ public final class PaymentMethod implements PersistablePayload, Comparable<Payme .findFirst(); } - public Coin getMaxTradeLimitAsCoin(String currencyCode) { + public BigInteger getMaxTradeLimit(String currencyCode) { // Hack for SF as the smallest unit is 1 SF ;-( and price is about 3 BTC! if (currencyCode.equals("SF")) - return Coin.parseCoin("4"); + return HavenoUtils.xmrToAtomicUnits(4); // payment methods which define their own trade limits if (id.equals(NEFT_ID) || id.equals(UPI_ID) || id.equals(PAYTM_ID) || id.equals(BIZUM_ID) || id.equals(TIKKIE_ID)) { - return Coin.valueOf(maxTradeLimit); + return BigInteger.valueOf(maxTradeLimit); } // We use the class field maxTradeLimit only for mapping the risk factor. long riskFactor; - if (maxTradeLimit == DEFAULT_TRADE_LIMIT_VERY_LOW_RISK.value) + if (maxTradeLimit == DEFAULT_TRADE_LIMIT_VERY_LOW_RISK.longValueExact()) riskFactor = 1; - else if (maxTradeLimit == DEFAULT_TRADE_LIMIT_LOW_RISK.value) + else if (maxTradeLimit == DEFAULT_TRADE_LIMIT_LOW_RISK.longValueExact()) riskFactor = 2; - else if (maxTradeLimit == DEFAULT_TRADE_LIMIT_MID_RISK.value) + else if (maxTradeLimit == DEFAULT_TRADE_LIMIT_MID_RISK.longValueExact()) riskFactor = 4; - else if (maxTradeLimit == DEFAULT_TRADE_LIMIT_HIGH_RISK.value) + else if (maxTradeLimit == DEFAULT_TRADE_LIMIT_HIGH_RISK.longValueExact()) riskFactor = 8; else { riskFactor = 8; log.warn("maxTradeLimit is not matching one of our default values. We use highest risk factor. " + - "maxTradeLimit={}. PaymentMethod={}", - Coin.valueOf(maxTradeLimit).toFriendlyString(), this); + "maxTradeLimit={}. PaymentMethod={}", maxTradeLimit, this); } // get risk based trade limit TradeLimits tradeLimits = new TradeLimits(); - long maxTradeLimit = tradeLimits.getMaxTradeLimit().value; - long riskBasedTradeLimit = tradeLimits.getRoundedRiskBasedTradeLimit(maxTradeLimit, riskFactor); // as centineros + long maxTradeLimit = tradeLimits.getMaxTradeLimit().longValueExact(); + long riskBasedTradeLimit = tradeLimits.getRoundedRiskBasedTradeLimit(maxTradeLimit, riskFactor); // if fiat and stagenet, cap offer amounts to avoid offers which cannot be taken boolean isFiat = CurrencyUtil.isFiatCurrency(currencyCode); boolean isStagenet = Config.baseCurrencyNetwork() == BaseCurrencyNetwork.XMR_STAGENET; - if (isFiat && isStagenet && HavenoUtils.centinerosToXmr(riskBasedTradeLimit) > OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.value) { - riskBasedTradeLimit = HavenoUtils.xmrToCentineros(OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.value); + if (isFiat && isStagenet && riskBasedTradeLimit > OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.longValueExact()) { + riskBasedTradeLimit = OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.longValueExact(); } - return Coin.valueOf(riskBasedTradeLimit); + return BigInteger.valueOf(riskBasedTradeLimit); } public String getShortName() { diff --git a/core/src/main/java/bisq/core/payment/validation/BtcValidator.java b/core/src/main/java/bisq/core/payment/validation/XmrValidator.java similarity index 58% rename from core/src/main/java/bisq/core/payment/validation/BtcValidator.java rename to core/src/main/java/bisq/core/payment/validation/XmrValidator.java index 0d03ecf6..7df7f14b 100644 --- a/core/src/main/java/bisq/core/payment/validation/BtcValidator.java +++ b/core/src/main/java/bisq/core/payment/validation/XmrValidator.java @@ -17,47 +17,39 @@ package bisq.core.payment.validation; -import bisq.core.btc.wallet.Restrictions; import bisq.core.locale.Res; -import bisq.core.util.FormattingUtils; -import bisq.core.util.coin.CoinFormatter; +import bisq.core.trade.HavenoUtils; import bisq.core.util.validation.NumberValidator; -import org.bitcoinj.core.Coin; - import javax.inject.Inject; -import javax.inject.Named; import java.math.BigDecimal; +import java.math.BigInteger; import lombok.Getter; import lombok.Setter; import javax.annotation.Nullable; -public class BtcValidator extends NumberValidator { - - protected final CoinFormatter formatter; +public class XmrValidator extends NumberValidator { @Nullable @Setter - protected Coin minValue; + protected BigInteger minValue; @Nullable @Setter - protected Coin maxValue; + protected BigInteger maxValue; @Nullable @Setter @Getter - protected Coin maxTradeLimit; + protected BigInteger maxTradeLimit; @Inject - public BtcValidator(@Named(FormattingUtils.BTC_FORMATTER_KEY) CoinFormatter formatter) { - this.formatter = formatter; + public XmrValidator() { } - @Override public ValidationResult validate(String input) { ValidationResult result = validateIfNotEmpty(input); @@ -70,34 +62,20 @@ public class BtcValidator extends NumberValidator { result = result.andValidation(input, this::validateIfNotZero, this::validateIfNotNegative, - this::validateIfNotFractionalBtcValue, + this::validateIfNotFractionalXmrValue, this::validateIfNotExceedsMaxTradeLimit, - this::validateIfNotExceedsMaxBtcValue, - this::validateIfNotUnderMinValue, - this::validateIfAboveDust); + this::validateIfNotExceedsMaxValue, + this::validateIfNotUnderMinValue); } return result; } - protected ValidationResult validateIfAboveDust(String input) { - try { - final Coin coin = Coin.parseCoin(input); - if (Restrictions.isAboveDust(coin)) - return new ValidationResult(true); - else - return new ValidationResult(false, Res.get("validation.amountBelowDust", - formatter.formatCoinWithCode(Restrictions.getMinNonDustOutput()))); - } catch (Throwable t) { - return new ValidationResult(false, Res.get("validation.invalidInput", t.getMessage())); - } - } - - protected ValidationResult validateIfNotFractionalBtcValue(String input) { + protected ValidationResult validateIfNotFractionalXmrValue(String input) { try { BigDecimal bd = new BigDecimal(input); - final BigDecimal satoshis = bd.movePointRight(8); - if (satoshis.scale() > 0) + final BigDecimal atomicUnits = bd.movePointRight(HavenoUtils.XMR_SMALLEST_UNIT_EXPONENT); + if (atomicUnits.scale() > 0) return new ValidationResult(false, Res.get("validation.btc.fraction")); else return new ValidationResult(true); @@ -106,11 +84,11 @@ public class BtcValidator extends NumberValidator { } } - protected ValidationResult validateIfNotExceedsMaxBtcValue(String input) { + protected ValidationResult validateIfNotExceedsMaxValue(String input) { try { - final Coin coin = Coin.parseCoin(input); - if (maxValue != null && coin.compareTo(maxValue) > 0) - return new ValidationResult(false, Res.get("validation.btc.toLarge", formatter.formatCoinWithCode(maxValue))); + final BigInteger amount = HavenoUtils.parseXmr(input); + if (maxValue != null && amount.compareTo(maxValue) > 0) + return new ValidationResult(false, Res.get("validation.btc.toLarge", HavenoUtils.formatToXmrWithCode(maxValue))); else return new ValidationResult(true); } catch (Throwable t) { @@ -120,9 +98,9 @@ public class BtcValidator extends NumberValidator { protected ValidationResult validateIfNotExceedsMaxTradeLimit(String input) { try { - final Coin coin = Coin.parseCoin(input); - if (maxTradeLimit != null && coin.compareTo(maxTradeLimit) > 0) - return new ValidationResult(false, Res.get("validation.btc.exceedsMaxTradeLimit", formatter.formatCoinWithCode(maxTradeLimit))); + final BigInteger amount = HavenoUtils.parseXmr(input); + if (maxTradeLimit != null && amount.compareTo(maxTradeLimit) > 0) + return new ValidationResult(false, Res.get("validation.btc.exceedsMaxTradeLimit", HavenoUtils.formatToXmrWithCode(maxTradeLimit))); else return new ValidationResult(true); } catch (Throwable t) { @@ -132,9 +110,9 @@ public class BtcValidator extends NumberValidator { protected ValidationResult validateIfNotUnderMinValue(String input) { try { - final Coin coin = Coin.parseCoin(input); - if (minValue != null && coin.compareTo(minValue) < 0) - return new ValidationResult(false, Res.get("validation.btc.toSmall", formatter.formatCoinWithCode(minValue))); + final BigInteger amount = HavenoUtils.parseXmr(input); + if (minValue != null && amount.compareTo(minValue) < 0) + return new ValidationResult(false, Res.get("validation.btc.toSmall", HavenoUtils.formatToXmr(minValue))); else return new ValidationResult(true); } catch (Throwable t) { diff --git a/core/src/main/java/bisq/core/support/dispute/DisputeManager.java b/core/src/main/java/bisq/core/support/dispute/DisputeManager.java index 2634043a..e6d33b50 100644 --- a/core/src/main/java/bisq/core/support/dispute/DisputeManager.java +++ b/core/src/main/java/bisq/core/support/dispute/DisputeManager.java @@ -56,7 +56,6 @@ import bisq.common.handlers.ResultHandler; import bisq.common.util.MathUtils; import bisq.common.util.Tuple2; -import org.bitcoinj.core.Coin; import org.bitcoinj.utils.Fiat; import javafx.beans.property.IntegerProperty; @@ -844,8 +843,8 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup (contract.isBuyerMakerAndSellerTaker() ? contract.getMakerPayoutAddressString() : contract.getTakerPayoutAddressString()) : (contract.isBuyerMakerAndSellerTaker() ? contract.getTakerPayoutAddressString() : contract.getMakerPayoutAddressString()); String loserPayoutAddress = winnerPayoutAddress.equals(contract.getMakerPayoutAddressString()) ? contract.getTakerPayoutAddressString() : contract.getMakerPayoutAddressString(); - BigInteger winnerPayoutAmount = HavenoUtils.coinToAtomicUnits(disputeResult.getWinner() == Winner.BUYER ? disputeResult.getBuyerPayoutAmount() : disputeResult.getSellerPayoutAmount()); - BigInteger loserPayoutAmount = HavenoUtils.coinToAtomicUnits(disputeResult.getWinner() == Winner.BUYER ? disputeResult.getSellerPayoutAmount() : disputeResult.getBuyerPayoutAmount()); + BigInteger winnerPayoutAmount = disputeResult.getWinner() == Winner.BUYER ? disputeResult.getBuyerPayoutAmount() : disputeResult.getSellerPayoutAmount(); + BigInteger loserPayoutAmount = disputeResult.getWinner() == Winner.BUYER ? disputeResult.getSellerPayoutAmount() : disputeResult.getBuyerPayoutAmount(); // check sufficient balance if (winnerPayoutAmount.compareTo(BigInteger.ZERO) < 0) throw new RuntimeException("Winner payout cannot be negative"); @@ -1039,26 +1038,26 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup } // The amount we would get if we do a new trade with current price - Coin potentialAmountAtDisputeOpening = priceAtDisputeOpening.getAmountByVolume(contract.getTradeVolume()); - Coin buyerSecurityDeposit = Coin.valueOf(offerPayload.getBuyerSecurityDeposit()); - Coin minRefundAtMediatedDispute = Restrictions.getMinRefundAtMediatedDispute(); + BigInteger potentialAmountAtDisputeOpening = priceAtDisputeOpening.getAmountByVolume(contract.getTradeVolume()); + BigInteger buyerSecurityDeposit = BigInteger.valueOf(offerPayload.getBuyerSecurityDeposit()); + BigInteger minRefundAtMediatedDispute = Restrictions.getMinRefundAtMediatedDispute(); // minRefundAtMediatedDispute is always larger as buyerSecurityDeposit at mediated payout, we ignore refund agent case here as there it can be 0. - Coin maxLossSecDeposit = buyerSecurityDeposit.subtract(minRefundAtMediatedDispute); - Coin tradeAmount = contract.getTradeAmount(); - Coin potentialGain = potentialAmountAtDisputeOpening.subtract(tradeAmount).subtract(maxLossSecDeposit); + BigInteger maxLossSecDeposit = buyerSecurityDeposit.subtract(minRefundAtMediatedDispute); + BigInteger tradeAmount = contract.getTradeAmount(); + BigInteger potentialGain = potentialAmountAtDisputeOpening.subtract(tradeAmount).subtract(maxLossSecDeposit); String optionTradeDetails; // We don't translate those strings (yet) as it is only displayed to mediators/arbitrators. String headline; - if (potentialGain.isPositive()) { + if (potentialGain.compareTo(BigInteger.valueOf(0)) > 0) { headline = "This might be a potential option trade!"; - optionTradeDetails = "\nBTC amount calculated with price at dispute opening: " + potentialAmountAtDisputeOpening.toFriendlyString() + - "\nMax loss of security deposit is: " + maxLossSecDeposit.toFriendlyString() + - "\nPossible gain from an option trade is: " + potentialGain.toFriendlyString(); + optionTradeDetails = "\nBTC amount calculated with price at dispute opening: " + HavenoUtils.formatToXmrWithCode(potentialAmountAtDisputeOpening) + + "\nMax loss of security deposit is: " + HavenoUtils.formatToXmrWithCode(maxLossSecDeposit) + + "\nPossible gain from an option trade is: " + HavenoUtils.formatToXmrWithCode(potentialGain); } else { headline = "It does not appear to be an option trade."; - optionTradeDetails = "\nBTC amount calculated with price at dispute opening: " + potentialAmountAtDisputeOpening.toFriendlyString() + - "\nMax loss of security deposit is: " + maxLossSecDeposit.toFriendlyString() + - "\nPossible loss from an option trade is: " + potentialGain.multiply(-1).toFriendlyString(); + optionTradeDetails = "\nBTC amount calculated with price at dispute opening: " + HavenoUtils.formatToXmrWithCode(potentialAmountAtDisputeOpening) + + "\nMax loss of security deposit is: " + HavenoUtils.formatToXmrWithCode(maxLossSecDeposit) + + "\nPossible loss from an option trade is: " + HavenoUtils.formatToXmrWithCode(potentialGain.multiply(BigInteger.valueOf(-1))); } String percentagePriceDetails = offerPayload.isUseMarketBasedPrice() ? @@ -1067,7 +1066,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup String priceInfoText = "System message: " + headline + "\n\nTrade price: " + contract.getPrice().toFriendlyString() + percentagePriceDetails + - "\nTrade amount: " + tradeAmount.toFriendlyString() + + "\nTrade amount: " + HavenoUtils.formatToXmrWithCode(tradeAmount) + "\nPrice at dispute opening: " + priceAtDisputeOpening.toFriendlyString() + optionTradeDetails; diff --git a/core/src/main/java/bisq/core/support/dispute/DisputeResult.java b/core/src/main/java/bisq/core/support/dispute/DisputeResult.java index 9af1a0a3..d1e81aa2 100644 --- a/core/src/main/java/bisq/core/support/dispute/DisputeResult.java +++ b/core/src/main/java/bisq/core/support/dispute/DisputeResult.java @@ -23,8 +23,6 @@ import bisq.common.proto.ProtoUtil; import bisq.common.proto.network.NetworkPayload; import bisq.common.util.Utilities; -import org.bitcoinj.core.Coin; - import com.google.protobuf.ByteString; import javafx.beans.property.BooleanProperty; @@ -32,6 +30,7 @@ import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; +import java.math.BigInteger; import java.util.Date; import java.util.Optional; @@ -206,20 +205,20 @@ public final class DisputeResult implements NetworkPayload { return summaryNotesProperty; } - public void setBuyerPayoutAmount(Coin buyerPayoutAmount) { - this.buyerPayoutAmount = buyerPayoutAmount.value; + public void setBuyerPayoutAmount(BigInteger buyerPayoutAmount) { + this.buyerPayoutAmount = buyerPayoutAmount.longValueExact(); } - public Coin getBuyerPayoutAmount() { - return Coin.valueOf(buyerPayoutAmount); + public BigInteger getBuyerPayoutAmount() { + return BigInteger.valueOf(buyerPayoutAmount); } - public void setSellerPayoutAmount(Coin sellerPayoutAmount) { - this.sellerPayoutAmount = sellerPayoutAmount.value; + public void setSellerPayoutAmount(BigInteger sellerPayoutAmount) { + this.sellerPayoutAmount = sellerPayoutAmount.longValueExact(); } - public Coin getSellerPayoutAmount() { - return Coin.valueOf(sellerPayoutAmount); + public BigInteger getSellerPayoutAmount() { + return BigInteger.valueOf(sellerPayoutAmount); } public void setCloseDate(Date closeDate) { diff --git a/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationManager.java b/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationManager.java index 39c540ba..ef0f7037 100644 --- a/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationManager.java +++ b/core/src/main/java/bisq/core/support/dispute/arbitration/ArbitrationManager.java @@ -386,13 +386,13 @@ public final class ArbitrationManager extends DisputeManager<ArbitrationDisputeL // verify payouts sum to unlocked balance within loss of precision due to conversion to centineros BigInteger txCost = arbitratorSignedPayoutTx.getFee().add(arbitratorSignedPayoutTx.getChangeAmount()); // fee + lost dust change - if (trade.getWallet().getUnlockedBalance().subtract(actualWinnerAmount.add(actualLoserAmount).add(txCost)).compareTo(HavenoUtils.CENTINEROS_AU_MULTIPLIER) > 0) { + if (trade.getWallet().getUnlockedBalance().subtract(actualWinnerAmount.add(actualLoserAmount).add(txCost)).compareTo(BigInteger.valueOf(0)) > 0) { throw new RuntimeException("The dispute payout amounts do not sum to the wallet's unlocked balance while verifying the dispute payout tx, unlocked balance=" + trade.getWallet().getUnlockedBalance() + " vs sum payout amount=" + actualWinnerAmount.add(actualLoserAmount) + ", winner payout=" + actualWinnerAmount + ", loser payout=" + actualLoserAmount); } // get expected payout amounts - BigInteger expectedWinnerAmount = HavenoUtils.coinToAtomicUnits(disputeResult.getWinner() == Winner.BUYER ? disputeResult.getBuyerPayoutAmount() : disputeResult.getSellerPayoutAmount()); - BigInteger expectedLoserAmount = HavenoUtils.coinToAtomicUnits(disputeResult.getWinner() == Winner.BUYER ? disputeResult.getSellerPayoutAmount() : disputeResult.getBuyerPayoutAmount()); + BigInteger expectedWinnerAmount = disputeResult.getWinner() == Winner.BUYER ? disputeResult.getBuyerPayoutAmount() : disputeResult.getSellerPayoutAmount(); + BigInteger expectedLoserAmount = disputeResult.getWinner() == Winner.BUYER ? disputeResult.getSellerPayoutAmount() : disputeResult.getBuyerPayoutAmount(); // add any loss of precision to winner amount expectedWinnerAmount = expectedWinnerAmount.add(trade.getWallet().getUnlockedBalance().subtract(expectedWinnerAmount.add(expectedLoserAmount))); diff --git a/core/src/main/java/bisq/core/support/dispute/arbitration/TraderDataItem.java b/core/src/main/java/bisq/core/support/dispute/arbitration/TraderDataItem.java index 7fe6706f..32ad3503 100644 --- a/core/src/main/java/bisq/core/support/dispute/arbitration/TraderDataItem.java +++ b/core/src/main/java/bisq/core/support/dispute/arbitration/TraderDataItem.java @@ -20,8 +20,7 @@ package bisq.core.support.dispute.arbitration; import bisq.core.account.witness.AccountAgeWitness; import bisq.core.payment.payload.PaymentAccountPayload; -import org.bitcoinj.core.Coin; - +import java.math.BigInteger; import java.security.PublicKey; import lombok.EqualsAndHashCode; @@ -34,12 +33,12 @@ public class TraderDataItem { private final PaymentAccountPayload paymentAccountPayload; @EqualsAndHashCode.Include private final AccountAgeWitness accountAgeWitness; - private final Coin tradeAmount; + private final BigInteger tradeAmount; private final PublicKey peersPubKey; public TraderDataItem(PaymentAccountPayload paymentAccountPayload, AccountAgeWitness accountAgeWitness, - Coin tradeAmount, + BigInteger tradeAmount, PublicKey peersPubKey) { this.paymentAccountPayload = paymentAccountPayload; this.accountAgeWitness = accountAgeWitness; diff --git a/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java b/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java index 876f2ae9..259ca368 100644 --- a/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java +++ b/core/src/main/java/bisq/core/support/dispute/mediation/MediationManager.java @@ -51,11 +51,10 @@ import bisq.common.crypto.KeyRing; import bisq.common.handlers.ErrorMessageHandler; import bisq.common.handlers.ResultHandler; -import org.bitcoinj.core.Coin; - import com.google.inject.Inject; import com.google.inject.Singleton; +import java.math.BigInteger; import java.util.Optional; import lombok.extern.slf4j.Slf4j; @@ -194,8 +193,8 @@ public final class MediationManager extends DisputeManager<MediationDisputeList> Trade trade = tradeOptional.get(); if (trade.getDisputeState() == Trade.DisputeState.MEDIATION_REQUESTED || trade.getDisputeState() == Trade.DisputeState.MEDIATION_STARTED_BY_PEER) { - trade.getProcessModel().setBuyerPayoutAmountFromMediation(disputeResult.getBuyerPayoutAmount().value); - trade.getProcessModel().setSellerPayoutAmountFromMediation(disputeResult.getSellerPayoutAmount().value); + trade.getProcessModel().setBuyerPayoutAmountFromMediation(disputeResult.getBuyerPayoutAmount().longValueExact()); + trade.getProcessModel().setSellerPayoutAmountFromMediation(disputeResult.getSellerPayoutAmount().longValueExact()); trade.setDisputeState(Trade.DisputeState.MEDIATION_CLOSED); @@ -228,11 +227,11 @@ public final class MediationManager extends DisputeManager<MediationDisputeList> Optional<Dispute> optionalDispute = findDispute(tradeId); checkArgument(optionalDispute.isPresent(), "dispute must be present"); DisputeResult disputeResult = optionalDispute.get().getDisputeResultProperty().get(); - Coin buyerPayoutAmount = disputeResult.getBuyerPayoutAmount(); - Coin sellerPayoutAmount = disputeResult.getSellerPayoutAmount(); + BigInteger buyerPayoutAmount = disputeResult.getBuyerPayoutAmount(); + BigInteger sellerPayoutAmount = disputeResult.getSellerPayoutAmount(); ProcessModel processModel = trade.getProcessModel(); - processModel.setBuyerPayoutAmountFromMediation(buyerPayoutAmount.value); - processModel.setSellerPayoutAmountFromMediation(sellerPayoutAmount.value); + processModel.setBuyerPayoutAmountFromMediation(buyerPayoutAmount.longValueExact()); + processModel.setSellerPayoutAmountFromMediation(sellerPayoutAmount.longValueExact()); DisputeProtocol tradeProtocol = (DisputeProtocol) tradeManager.getTradeProtocol(trade); trade.setMediationResultState(MediationResultState.MEDIATION_RESULT_ACCEPTED); diff --git a/core/src/main/java/bisq/core/trade/ArbitratorTrade.java b/core/src/main/java/bisq/core/trade/ArbitratorTrade.java index d3b51f9c..de64f989 100644 --- a/core/src/main/java/bisq/core/trade/ArbitratorTrade.java +++ b/core/src/main/java/bisq/core/trade/ArbitratorTrade.java @@ -9,8 +9,7 @@ import bisq.network.p2p.NodeAddress; import bisq.common.proto.ProtoUtil; -import org.bitcoinj.core.Coin; - +import java.math.BigInteger; import java.util.UUID; import lombok.extern.slf4j.Slf4j; @@ -22,8 +21,8 @@ import lombok.extern.slf4j.Slf4j; public class ArbitratorTrade extends Trade { public ArbitratorTrade(Offer offer, - Coin tradeAmount, - Coin takerFee, + BigInteger tradeAmount, + BigInteger takerFee, long tradePrice, XmrWalletService xmrWalletService, ProcessModel processModel, @@ -35,7 +34,7 @@ public class ArbitratorTrade extends Trade { } @Override - public Coin getPayoutAmount() { + public BigInteger getPayoutAmount() { throw new RuntimeException("Arbitrator does not have a payout amount"); } @@ -62,8 +61,8 @@ public class ArbitratorTrade extends Trade { } return fromProto(new ArbitratorTrade( Offer.fromProto(proto.getOffer()), - Coin.valueOf(proto.getAmountAsLong()), - Coin.valueOf(proto.getTakerFeeAsLong()), + BigInteger.valueOf(proto.getAmountAsLong()), + BigInteger.valueOf(proto.getTakerFeeAsLong()), proto.getPrice(), xmrWalletService, processModel, diff --git a/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java b/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java index cb3d049f..a205329b 100644 --- a/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerAsMakerTrade.java @@ -26,8 +26,7 @@ import bisq.network.p2p.NodeAddress; import bisq.common.proto.ProtoUtil; -import org.bitcoinj.core.Coin; - +import java.math.BigInteger; import java.util.UUID; import lombok.extern.slf4j.Slf4j; @@ -40,8 +39,8 @@ public final class BuyerAsMakerTrade extends BuyerTrade implements MakerTrade { /////////////////////////////////////////////////////////////////////////////////////////// public BuyerAsMakerTrade(Offer offer, - Coin tradeAmount, - Coin takeOfferFee, + BigInteger tradeAmount, + BigInteger takeOfferFee, long tradePrice, XmrWalletService xmrWalletService, ProcessModel processModel, @@ -84,8 +83,8 @@ public final class BuyerAsMakerTrade extends BuyerTrade implements MakerTrade { } BuyerAsMakerTrade trade = new BuyerAsMakerTrade( Offer.fromProto(proto.getOffer()), - Coin.valueOf(proto.getAmountAsLong()), - Coin.valueOf(proto.getTakerFeeAsLong()), + BigInteger.valueOf(proto.getAmountAsLong()), + BigInteger.valueOf(proto.getTakerFeeAsLong()), proto.getPrice(), xmrWalletService, processModel, diff --git a/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java b/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java index 4126e7d6..76c4fcd1 100644 --- a/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerAsTakerTrade.java @@ -26,8 +26,7 @@ import bisq.network.p2p.NodeAddress; import bisq.common.proto.ProtoUtil; -import org.bitcoinj.core.Coin; - +import java.math.BigInteger; import java.util.UUID; import lombok.extern.slf4j.Slf4j; @@ -42,8 +41,8 @@ public final class BuyerAsTakerTrade extends BuyerTrade implements TakerTrade { /////////////////////////////////////////////////////////////////////////////////////////// public BuyerAsTakerTrade(Offer offer, - Coin tradeAmount, - Coin takerFee, + BigInteger tradeAmount, + BigInteger takerFee, long tradePrice, XmrWalletService xmrWalletService, ProcessModel processModel, @@ -87,8 +86,8 @@ public final class BuyerAsTakerTrade extends BuyerTrade implements TakerTrade { } return fromProto(new BuyerAsTakerTrade( Offer.fromProto(proto.getOffer()), - Coin.valueOf(proto.getAmountAsLong()), - Coin.valueOf(proto.getTakerFeeAsLong()), + BigInteger.valueOf(proto.getAmountAsLong()), + BigInteger.valueOf(proto.getTakerFeeAsLong()), proto.getPrice(), xmrWalletService, processModel, diff --git a/core/src/main/java/bisq/core/trade/BuyerTrade.java b/core/src/main/java/bisq/core/trade/BuyerTrade.java index 2ef64f20..6db586c1 100644 --- a/core/src/main/java/bisq/core/trade/BuyerTrade.java +++ b/core/src/main/java/bisq/core/trade/BuyerTrade.java @@ -23,19 +23,19 @@ import bisq.core.trade.protocol.ProcessModel; import bisq.network.p2p.NodeAddress; -import org.bitcoinj.core.Coin; - import lombok.extern.slf4j.Slf4j; import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; +import java.math.BigInteger; + @Slf4j public abstract class BuyerTrade extends Trade { BuyerTrade(Offer offer, - Coin tradeAmount, - Coin takerFee, + BigInteger tradeAmount, + BigInteger takerFee, long tradePrice, XmrWalletService xmrWalletService, ProcessModel processModel, @@ -56,7 +56,7 @@ public abstract class BuyerTrade extends Trade { } @Override - public Coin getPayoutAmount() { + public BigInteger getPayoutAmount() { checkNotNull(getAmount(), "Invalid state: getTradeAmount() = null"); return checkNotNull(getOffer()).getBuyerSecurityDeposit().add(getAmount()); } diff --git a/core/src/main/java/bisq/core/trade/ClosedTradableFormatter.java b/core/src/main/java/bisq/core/trade/ClosedTradableFormatter.java index cf121ee5..3e634551 100644 --- a/core/src/main/java/bisq/core/trade/ClosedTradableFormatter.java +++ b/core/src/main/java/bisq/core/trade/ClosedTradableFormatter.java @@ -48,8 +48,6 @@ import static bisq.core.util.FormattingUtils.formatPercentagePrice; import static bisq.core.util.FormattingUtils.formatToPercentWithSymbol; import static bisq.core.util.VolumeUtil.formatVolume; import static bisq.core.util.VolumeUtil.formatVolumeWithCode; -import static org.bitcoinj.core.TransactionConfidence.ConfidenceType.BUILDING; -import static org.bitcoinj.core.TransactionConfidence.ConfidenceType.PENDING; @Slf4j @Singleton @@ -59,7 +57,6 @@ public class ClosedTradableFormatter { private static final String I18N_KEY_TOTAL_AMOUNT = "closedTradesSummaryWindow.totalAmount.value"; private static final String I18N_KEY_TOTAL_TX_FEE = "closedTradesSummaryWindow.totalMinerFee.value"; private static final String I18N_KEY_TOTAL_TRADE_FEE_BTC = "closedTradesSummaryWindow.totalTradeFeeInBtc.value"; - private static final String I18N_KEY_TOTAL_TRADE_FEE_BSQ = "closedTradesSummaryWindow.totalTradeFeeInBsq.value"; private final CoinFormatter btcFormatter; private final ClosedTradableManager closedTradableManager; @@ -72,7 +69,7 @@ public class ClosedTradableFormatter { } public String getAmountAsString(Tradable tradable) { - return tradable.getOptionalAmount().map(btcFormatter::formatCoin).orElse(""); + return tradable.getOptionalAmount().map(HavenoUtils::formatToXmr).orElse(""); } public String getTotalAmountWithVolumeAsString(Coin totalTradeAmount, Volume volume) { @@ -93,11 +90,11 @@ public class ClosedTradableFormatter { } public String getBuyerSecurityDepositAsString(Tradable tradable) { - return btcFormatter.formatCoin(tradable.getOffer().getBuyerSecurityDeposit()); + return HavenoUtils.formatToXmr(tradable.getOffer().getBuyerSecurityDeposit()); } public String getSellerSecurityDepositAsString(Tradable tradable) { - return btcFormatter.formatCoin(tradable.getOffer().getSellerSecurityDeposit()); + return HavenoUtils.formatToXmr(tradable.getOffer().getSellerSecurityDeposit()); } public String getTradeFeeAsString(Tradable tradable, boolean appendCode) { diff --git a/core/src/main/java/bisq/core/trade/ClosedTradableManager.java b/core/src/main/java/bisq/core/trade/ClosedTradableManager.java index 38419132..849b2599 100644 --- a/core/src/main/java/bisq/core/trade/ClosedTradableManager.java +++ b/core/src/main/java/bisq/core/trade/ClosedTradableManager.java @@ -41,6 +41,7 @@ import com.google.common.collect.ImmutableList; import javafx.collections.ObservableList; +import java.math.BigInteger; import java.time.Instant; import java.util.ArrayList; @@ -229,8 +230,8 @@ public class ClosedTradableManager implements PersistedDataHost { public long getBtcTradeFee(Tradable tradable) { return isMaker(tradable) ? - tradable.getOptionalMakerFee().orElse(Coin.ZERO).value : - tradable.getOptionalTakerFee().orElse(Coin.ZERO).value; + tradable.getOptionalMakerFee().orElse(BigInteger.valueOf(0)).longValueExact() : + tradable.getOptionalTakerFee().orElse(BigInteger.valueOf(0)).longValueExact(); } public boolean isMaker(Tradable tradable) { diff --git a/core/src/main/java/bisq/core/trade/Contract.java b/core/src/main/java/bisq/core/trade/Contract.java index 35d4d03b..f651830d 100644 --- a/core/src/main/java/bisq/core/trade/Contract.java +++ b/core/src/main/java/bisq/core/trade/Contract.java @@ -33,8 +33,6 @@ import bisq.common.proto.network.NetworkPayload; import bisq.common.util.JsonExclude; import bisq.common.util.Utilities; -import org.bitcoinj.core.Coin; - import org.apache.commons.lang3.StringUtils; import lombok.Value; @@ -44,6 +42,8 @@ import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkArgument; +import java.math.BigInteger; + @Slf4j @Value public final class Contract implements NetworkPayload { @@ -209,8 +209,8 @@ public final class Contract implements NetworkPayload { return makerPaymentMethodId; } - public Coin getTradeAmount() { - return Coin.valueOf(tradeAmount); + public BigInteger getTradeAmount() { + return BigInteger.valueOf(tradeAmount); } public Volume getTradeVolume() { diff --git a/core/src/main/java/bisq/core/trade/HavenoUtils.java b/core/src/main/java/bisq/core/trade/HavenoUtils.java index 847fd400..aef977c4 100644 --- a/core/src/main/java/bisq/core/trade/HavenoUtils.java +++ b/core/src/main/java/bisq/core/trade/HavenoUtils.java @@ -25,8 +25,6 @@ import bisq.core.trade.messages.InitTradeRequest; import bisq.core.trade.messages.PaymentReceivedMessage; import bisq.core.trade.messages.PaymentSentMessage; import bisq.core.util.JsonUtil; -import bisq.core.util.ParsingUtils; -import bisq.core.util.coin.CoinUtil; import bisq.network.p2p.NodeAddress; import bisq.common.config.Config; @@ -36,7 +34,6 @@ import bisq.common.crypto.Sig; import bisq.common.util.Utilities; import org.bitcoinj.core.Coin; -import org.bitcoinj.utils.MonetaryFormat; import com.google.common.base.CaseFormat; import com.google.common.base.Charsets; @@ -68,9 +65,10 @@ import javax.annotation.Nullable; @Slf4j public class HavenoUtils { + public static int XMR_SMALLEST_UNIT_EXPONENT = 12; public static final String LOOPBACK_HOST = "127.0.0.1"; // local loopback address to host Monero node public static final String LOCALHOST = "localhost"; - public static final BigInteger CENTINEROS_AU_MULTIPLIER = new BigInteger("10000"); + private static final long CENTINEROS_AU_MULTIPLIER = 10000; private static final BigInteger XMR_AU_MULTIPLIER = new BigInteger("1000000000000"); public static final DecimalFormat XMR_FORMATTER = new DecimalFormat("0.000000000000"); public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); @@ -79,12 +77,15 @@ public class HavenoUtils { public static ArbitrationManager arbitrationManager; // TODO: better way to share reference? + + // ----------------------- CONVERSION UTILS ------------------------------- + public static BigInteger coinToAtomicUnits(Coin coin) { return centinerosToAtomicUnits(coin.value); } public static BigInteger centinerosToAtomicUnits(long centineros) { - return BigInteger.valueOf(centineros).multiply(CENTINEROS_AU_MULTIPLIER); + return BigInteger.valueOf(centineros).multiply(BigInteger.valueOf(CENTINEROS_AU_MULTIPLIER)); } public static double centinerosToXmr(long centineros) { @@ -95,12 +96,12 @@ public class HavenoUtils { return atomicUnitsToCoin(centinerosToAtomicUnits(centineros)); } - public static long atomicUnitsToCentineros(long atomicUnits) { // TODO: atomic units should be BigInteger; remove this? - return atomicUnits / CENTINEROS_AU_MULTIPLIER.longValue(); + public static long atomicUnitsToCentineros(long atomicUnits) { + return atomicUnits / CENTINEROS_AU_MULTIPLIER; } public static long atomicUnitsToCentineros(BigInteger atomicUnits) { - return atomicUnits.divide(CENTINEROS_AU_MULTIPLIER).longValueExact(); + return atomicUnits.divide(BigInteger.valueOf(CENTINEROS_AU_MULTIPLIER)).longValueExact(); } public static Coin atomicUnitsToCoin(long atomicUnits) { @@ -131,11 +132,19 @@ public class HavenoUtils { return atomicUnitsToXmr(coinToAtomicUnits(coin)); } - public static String formatXmrWithCode(Coin coin) { - return formatXmrWithCode(coinToAtomicUnits(coin).longValueExact()); + + // ------------------------- FORMAT UTILS --------------------------------- + + public static String formatToXmr(BigInteger atomicUnits) { + if (atomicUnits == null) return ""; + return formatToXmr(atomicUnits.longValueExact()); } - public static String formatXmrWithCode(long atomicUnits) { + public static String formatToXmr(BigInteger atomicUnits, int decimalPlaces) { + return applyDecimals(formatToXmr(atomicUnits), decimalPlaces); + } + + public static String formatToXmr(long atomicUnits) { String formatted = XMR_FORMATTER.format(atomicUnitsToXmr(atomicUnits)); // strip trailing 0s @@ -144,55 +153,87 @@ public class HavenoUtils { formatted = formatted.substring(0, formatted.length() - 1); } } - return formatted.concat(" ").concat("XMR"); + return applyDecimals(formatted, 2); } - private static final MonetaryFormat xmrCoinFormat = Config.baseCurrencyNetworkParameters().getMonetaryFormat(); + private static String applyDecimals(String decimalStr, int decimalPlaces) { + if (decimalStr.contains(".")) return decimalStr + getNumZeros(decimalPlaces - (decimalStr.length() - decimalStr.indexOf(".") - 1)); + else return decimalStr + "." + getNumZeros(decimalPlaces); + } + + private static String getNumZeros(int numZeros) { + String zeros = ""; + for (int i = 0; i < numZeros; i++) zeros += "0"; + return zeros; + } + + public static String formatToXmrWithCode(BigInteger atomicUnits) { + if (atomicUnits == null) return ""; + return formatToXmrWithCode(atomicUnits.longValueExact()); + } + + public static String formatToXmrWithCode(long atomicUnits) { + return formatToXmr(atomicUnits).concat(" XMR"); + } + + public static BigInteger parseXmr(String input) { + if (input == null || input.length() == 0) return BigInteger.valueOf(0); + try { + return xmrToAtomicUnits(new BigDecimal(input).doubleValue()); + } catch (Exception e) { + log.warn("Exception at parseXmr: " + e.toString()); + return BigInteger.valueOf(0); + } + } + + // ------------------------------ FEE UTILS ------------------------------- @Nullable - public static Coin getMakerFee(@Nullable Coin amount) { + public static BigInteger getMakerFee(@Nullable BigInteger amount) { if (amount != null) { - Coin feePerXmr = getFeePerXmr(HavenoUtils.getMakerFeePerXmr(), amount); - return CoinUtil.maxCoin(feePerXmr, HavenoUtils.getMinMakerFee()); + BigInteger feePerXmr = getFeePerXmr(HavenoUtils.getMakerFeePerXmr(), amount); + return feePerXmr.max(HavenoUtils.getMinMakerFee()); } else { return null; } } @Nullable - public static Coin getTakerFee(@Nullable Coin amount) { + public static BigInteger getTakerFee(@Nullable BigInteger amount) { if (amount != null) { - Coin feePerXmr = HavenoUtils.getFeePerXmr(HavenoUtils.getTakerFeePerXmr(), amount); - return CoinUtil.maxCoin(feePerXmr, HavenoUtils.getMinTakerFee()); + BigInteger feePerXmr = HavenoUtils.getFeePerXmr(HavenoUtils.getTakerFeePerXmr(), amount); + return feePerXmr.max(HavenoUtils.getMinTakerFee()); } else { return null; } } - private static Coin getMakerFeePerXmr() { - return ParsingUtils.parseToCoin("0.001", xmrCoinFormat); + private static BigInteger getMakerFeePerXmr() { + return HavenoUtils.xmrToAtomicUnits(0.001); } - public static Coin getMinMakerFee() { - return ParsingUtils.parseToCoin("0.00005", xmrCoinFormat); + public static BigInteger getMinMakerFee() { + return HavenoUtils.xmrToAtomicUnits(0.00005); } - private static Coin getTakerFeePerXmr() { - return ParsingUtils.parseToCoin("0.003", xmrCoinFormat); + private static BigInteger getTakerFeePerXmr() { + return HavenoUtils.xmrToAtomicUnits(0.003); } - public static Coin getMinTakerFee() { - return ParsingUtils.parseToCoin("0.00005", xmrCoinFormat); + public static BigInteger getMinTakerFee() { + return HavenoUtils.xmrToAtomicUnits(0.00005); } - public static Coin getFeePerXmr(Coin feePerXmr, Coin amount) { - double feePerBtcAsDouble = feePerXmr != null ? (double) feePerXmr.value : 0; - double amountAsDouble = amount != null ? (double) amount.value : 0; - double btcAsDouble = (double) Coin.COIN.value; - double fact = amountAsDouble / btcAsDouble; - return Coin.valueOf(Math.round(feePerBtcAsDouble * fact)); + public static BigInteger getFeePerXmr(BigInteger feePerXmr, BigInteger amount) { + BigDecimal feePerXmrAsDecimal = feePerXmr == null ? BigDecimal.valueOf(0) : new BigDecimal(feePerXmr); + BigDecimal amountAsDecimal = amount == null ? BigDecimal.valueOf(0) : new BigDecimal(amount); + BigDecimal xmrAsDecimal = new BigDecimal(HavenoUtils.xmrToAtomicUnits(1.0)); + return feePerXmrAsDecimal.multiply(amountAsDecimal.divide(xmrAsDecimal)).toBigInteger(); } + + // ----------------------------- OTHER UTILS ------------------------------ + /** * Get address to collect trade fees. * diff --git a/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java b/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java index 2128fbf9..a08726dc 100644 --- a/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerAsMakerTrade.java @@ -26,8 +26,7 @@ import bisq.network.p2p.NodeAddress; import bisq.common.proto.ProtoUtil; -import org.bitcoinj.core.Coin; - +import java.math.BigInteger; import java.util.UUID; import lombok.extern.slf4j.Slf4j; @@ -42,8 +41,8 @@ public final class SellerAsMakerTrade extends SellerTrade implements MakerTrade /////////////////////////////////////////////////////////////////////////////////////////// public SellerAsMakerTrade(Offer offer, - Coin tradeAmount, - Coin takerFee, + BigInteger tradeAmount, + BigInteger takerFee, long tradePrice, XmrWalletService xmrWalletService, ProcessModel processModel, @@ -87,8 +86,8 @@ public final class SellerAsMakerTrade extends SellerTrade implements MakerTrade } SellerAsMakerTrade trade = new SellerAsMakerTrade( Offer.fromProto(proto.getOffer()), - Coin.valueOf(proto.getAmountAsLong()), - Coin.valueOf(proto.getTakerFeeAsLong()), + BigInteger.valueOf(proto.getAmountAsLong()), + BigInteger.valueOf(proto.getTakerFeeAsLong()), proto.getPrice(), xmrWalletService, processModel, diff --git a/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java b/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java index 6c2c021c..364a7696 100644 --- a/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerAsTakerTrade.java @@ -26,8 +26,7 @@ import bisq.network.p2p.NodeAddress; import bisq.common.proto.ProtoUtil; -import org.bitcoinj.core.Coin; - +import java.math.BigInteger; import java.util.UUID; import lombok.extern.slf4j.Slf4j; @@ -42,8 +41,8 @@ public final class SellerAsTakerTrade extends SellerTrade implements TakerTrade /////////////////////////////////////////////////////////////////////////////////////////// public SellerAsTakerTrade(Offer offer, - Coin tradeAmount, - Coin takerFee, + BigInteger tradeAmount, + BigInteger takerFee, long tradePrice, XmrWalletService xmrWalletService, ProcessModel processModel, @@ -87,8 +86,8 @@ public final class SellerAsTakerTrade extends SellerTrade implements TakerTrade } return fromProto(new SellerAsTakerTrade( Offer.fromProto(proto.getOffer()), - Coin.valueOf(proto.getAmountAsLong()), - Coin.valueOf(proto.getTakerFeeAsLong()), + BigInteger.valueOf(proto.getAmountAsLong()), + BigInteger.valueOf(proto.getTakerFeeAsLong()), proto.getPrice(), xmrWalletService, processModel, diff --git a/core/src/main/java/bisq/core/trade/SellerTrade.java b/core/src/main/java/bisq/core/trade/SellerTrade.java index 51f844f3..28a30375 100644 --- a/core/src/main/java/bisq/core/trade/SellerTrade.java +++ b/core/src/main/java/bisq/core/trade/SellerTrade.java @@ -18,25 +18,24 @@ package bisq.core.trade; import bisq.core.btc.wallet.XmrWalletService; -import bisq.core.locale.CurrencyUtil; import bisq.core.offer.Offer; import bisq.core.trade.protocol.ProcessModel; import bisq.network.p2p.NodeAddress; -import org.bitcoinj.core.Coin; - import lombok.extern.slf4j.Slf4j; import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; +import java.math.BigInteger; + @Slf4j public abstract class SellerTrade extends Trade { SellerTrade(Offer offer, - Coin tradeAmount, - Coin takerFee, + BigInteger tradeAmount, + BigInteger takerFee, long tradePrice, XmrWalletService xmrWalletService, ProcessModel processModel, @@ -57,7 +56,7 @@ public abstract class SellerTrade extends Trade { } @Override - public Coin getPayoutAmount() { + public BigInteger getPayoutAmount() { return checkNotNull(getOffer()).getSellerSecurityDeposit(); } diff --git a/core/src/main/java/bisq/core/trade/Tradable.java b/core/src/main/java/bisq/core/trade/Tradable.java index e8f420f7..eed872b7 100644 --- a/core/src/main/java/bisq/core/trade/Tradable.java +++ b/core/src/main/java/bisq/core/trade/Tradable.java @@ -26,6 +26,7 @@ import bisq.common.proto.persistable.PersistablePayload; import org.bitcoinj.core.Coin; +import java.math.BigInteger; import java.util.Date; import java.util.Optional; @@ -54,7 +55,7 @@ public interface Tradable extends PersistablePayload { return asTradeModel().map(Trade::getPrice).or(() -> Optional.ofNullable(getOffer().getPrice())); } - default Optional<Coin> getOptionalAmount() { + default Optional<BigInteger> getOptionalAmount() { return asTradeModel().map(Trade::getAmount); } @@ -66,11 +67,11 @@ public interface Tradable extends PersistablePayload { return asTradeModel().map(Trade::getTxFee); } - default Optional<Coin> getOptionalTakerFee() { + default Optional<BigInteger> getOptionalTakerFee() { return asTradeModel().map(Trade::getTakerFee); } - default Optional<Coin> getOptionalMakerFee() { + default Optional<BigInteger> getOptionalMakerFee() { return asTradeModel().map(Trade::getOffer).map(Offer::getMakerFee).or(() -> Optional.ofNullable(getOffer().getMakerFee())); } diff --git a/core/src/main/java/bisq/core/trade/Trade.java b/core/src/main/java/bisq/core/trade/Trade.java index 9d448182..aa3c9154 100644 --- a/core/src/main/java/bisq/core/trade/Trade.java +++ b/core/src/main/java/bisq/core/trade/Trade.java @@ -375,7 +375,7 @@ public abstract class Trade implements Tradable, Model { @Getter transient final private Coin txFee; @Getter - transient final private Coin takerFee; + transient final private BigInteger takerFee; @Getter transient final private XmrWalletService xmrWalletService; @@ -402,9 +402,9 @@ public abstract class Trade implements Tradable, Model { // Added in v1.2.0 @Nullable - transient private Coin tradeAmount; + transient private BigInteger tradeAmount; - transient private ObjectProperty<Coin> tradeAmountProperty; + transient private ObjectProperty<BigInteger> tradeAmountProperty; transient private ObjectProperty<Volume> tradeVolumeProperty; // Added in v1.1.6 @@ -469,8 +469,8 @@ public abstract class Trade implements Tradable, Model { // maker protected Trade(Offer offer, - Coin tradeAmount, - Coin takerFee, // TODO (woodser): makerFee, takerFee, but not given one during construction + BigInteger tradeAmount, + BigInteger takerFee, long tradePrice, XmrWalletService xmrWalletService, ProcessModel processModel, @@ -487,7 +487,7 @@ public abstract class Trade implements Tradable, Model { this.processModel = processModel; this.uid = uid; - this.takerFeeAsLong = takerFee.value; + this.takerFeeAsLong = takerFee.longValueExact(); this.takeOfferDate = new Date().getTime(); this.tradeListeners = new ArrayList<TradeListener>(); @@ -503,9 +503,9 @@ public abstract class Trade implements Tradable, Model { // taker @SuppressWarnings("NullableProblems") protected Trade(Offer offer, - Coin tradeAmount, - Coin txFee, - Coin takerFee, + BigInteger tradeAmount, + BigInteger txFee, + BigInteger takerFee, long tradePrice, @Nullable NodeAddress mediatorNodeAddress, // TODO (woodser): remove mediator, refund agent from trade @Nullable NodeAddress refundAgentNodeAddress, @@ -532,9 +532,9 @@ public abstract class Trade implements Tradable, Model { // arbitrator @SuppressWarnings("NullableProblems") protected Trade(Offer offer, - Coin tradeAmount, + BigInteger tradeAmount, Coin txFee, - Coin takerFee, + BigInteger takerFee, long tradePrice, NodeAddress makerNodeAddress, NodeAddress takerNodeAddress, @@ -860,7 +860,7 @@ public abstract class Trade implements Tradable, Model { boolean isBuyerMakerAndSellerTaker = getOffer().getDirection() == OfferDirection.BUY; Contract contract = new Contract( getOffer().getOfferPayload(), - checkNotNull(getAmount()).value, + checkNotNull(getAmount()).longValueExact(), getPrice().getValue(), (isBuyerMakerAndSellerTaker ? getMaker() : getTaker()).getNodeAddress(), // buyer node address // TODO (woodser): use maker and taker node address instead of buyer and seller node address for consistency (isBuyerMakerAndSellerTaker ? getTaker() : getMaker()).getNodeAddress(), // seller node address @@ -905,7 +905,7 @@ public abstract class Trade implements Tradable, Model { Preconditions.checkNotNull(buyerPayoutAddress, "Buyer payout address must not be null"); BigInteger sellerDepositAmount = multisigWallet.getTx(this.getSeller().getDepositTxHash()).getIncomingAmount(); BigInteger buyerDepositAmount = multisigWallet.getTx(this.getBuyer().getDepositTxHash()).getIncomingAmount(); - BigInteger tradeAmount = HavenoUtils.coinToAtomicUnits(this.getAmount()); + BigInteger tradeAmount = getAmount(); BigInteger buyerPayoutAmount = buyerDepositAmount.add(tradeAmount); BigInteger sellerPayoutAmount = sellerDepositAmount.subtract(tradeAmount); @@ -956,7 +956,7 @@ public abstract class Trade implements Tradable, Model { Contract contract = getContract(); BigInteger sellerDepositAmount = wallet.getTx(getSeller().getDepositTxHash()).getIncomingAmount(); // TODO (woodser): redundancy of processModel.getPreparedDepositTxId() vs this.getDepositTxId() necessary or avoidable? BigInteger buyerDepositAmount = wallet.getTx(getBuyer().getDepositTxHash()).getIncomingAmount(); - BigInteger tradeAmount = HavenoUtils.coinToAtomicUnits(getAmount()); + BigInteger tradeAmount = getAmount(); // describe payout tx MoneroTxSet describedTxSet = wallet.describeTxSet(new MoneroTxSet().setMultisigTxHex(payoutTxHex)); @@ -1111,7 +1111,7 @@ public abstract class Trade implements Tradable, Model { // by mediators and we keep the confirm disabled to avoid that the seller can complete the trade // without the penalty. long payoutAmountFromMediation = processModel.getSellerPayoutAmountFromMediation(); - long normalPayoutAmount = getSellerSecurityDeposit().value; + long normalPayoutAmount = getSellerSecurityDeposit().longValueExact(); return payoutAmountFromMediation < normalPayoutAmount; } @@ -1157,7 +1157,7 @@ public abstract class Trade implements Tradable, Model { // Abstract /////////////////////////////////////////////////////////////////////////////////////////// - public abstract Coin getPayoutAmount(); + public abstract BigInteger getPayoutAmount(); public abstract boolean confirmPermitted(); @@ -1263,9 +1263,9 @@ public abstract class Trade implements Tradable, Model { tradePeriodStateProperty.set(tradePeriodState); } - public void setAmount(Coin tradeAmount) { + public void setAmount(BigInteger tradeAmount) { this.tradeAmount = tradeAmount; - amountAsLong = tradeAmount.value; + amountAsLong = tradeAmount.longValueExact(); getAmountProperty().set(tradeAmount); getVolumeProperty().set(getVolume()); } @@ -1535,7 +1535,7 @@ public abstract class Trade implements Tradable, Model { return tradePeriodStateProperty; } - public ReadOnlyObjectProperty<Coin> tradeAmountProperty() { + public ReadOnlyObjectProperty<BigInteger> tradeAmountProperty() { return tradeAmountProperty; } @@ -1567,24 +1567,24 @@ public abstract class Trade implements Tradable, Model { } @Nullable - public Coin getAmount() { + public BigInteger getAmount() { if (tradeAmount == null) - tradeAmount = Coin.valueOf(amountAsLong); + tradeAmount = BigInteger.valueOf(amountAsLong); return tradeAmount; } - public Coin getMakerFee() { + public BigInteger getMakerFee() { return offer.getMakerFee(); } - public Coin getBuyerSecurityDeposit() { + public BigInteger getBuyerSecurityDeposit() { if (getBuyer().getDepositTxHash() == null) return null; - return HavenoUtils.centinerosToCoin(getBuyer().getSecurityDeposit()); + return BigInteger.valueOf(getBuyer().getSecurityDeposit()); } - public Coin getSellerSecurityDeposit() { + public BigInteger getSellerSecurityDeposit() { if (getSeller().getDepositTxHash() == null) return null; - return HavenoUtils.centinerosToCoin(getSeller().getSecurityDeposit()); + return BigInteger.valueOf(getSeller().getSecurityDeposit()); } @Nullable @@ -1627,7 +1627,7 @@ public abstract class Trade implements Tradable, Model { /////////////////////////////////////////////////////////////////////////////////////////// // lazy initialization - private ObjectProperty<Coin> getAmountProperty() { + private ObjectProperty<BigInteger> getAmountProperty() { if (tradeAmountProperty == null) tradeAmountProperty = getAmount() != null ? new SimpleObjectProperty<>(getAmount()) : new SimpleObjectProperty<>(); @@ -1730,9 +1730,9 @@ public abstract class Trade implements Tradable, Model { // set security deposits if (getBuyer().getSecurityDeposit() == 0) { BigInteger buyerSecurityDeposit = ((MoneroTxWallet) getBuyer().getDepositTx()).getIncomingAmount(); - BigInteger sellerSecurityDeposit = ((MoneroTxWallet) getSeller().getDepositTx()).getIncomingAmount().subtract(HavenoUtils.coinToAtomicUnits(getAmount())); - getBuyer().setSecurityDeposit(HavenoUtils.atomicUnitsToCentineros(buyerSecurityDeposit)); - getSeller().setSecurityDeposit(HavenoUtils.atomicUnitsToCentineros(sellerSecurityDeposit)); + BigInteger sellerSecurityDeposit = ((MoneroTxWallet) getSeller().getDepositTx()).getIncomingAmount().subtract(getAmount()); + getBuyer().setSecurityDeposit(buyerSecurityDeposit.longValueExact()); + getSeller().setSecurityDeposit(sellerSecurityDeposit.longValueExact()); } // set deposits published state diff --git a/core/src/main/java/bisq/core/trade/TradeDataValidation.java b/core/src/main/java/bisq/core/trade/TradeDataValidation.java index 0ac7955a..1524e180 100644 --- a/core/src/main/java/bisq/core/trade/TradeDataValidation.java +++ b/core/src/main/java/bisq/core/trade/TradeDataValidation.java @@ -22,12 +22,13 @@ import bisq.core.offer.Offer; import bisq.core.support.dispute.Dispute; import org.bitcoinj.core.Address; -import org.bitcoinj.core.Coin; import org.bitcoinj.core.NetworkParameters; import org.bitcoinj.core.Transaction; import org.bitcoinj.core.TransactionInput; import org.bitcoinj.core.TransactionOutPoint; import org.bitcoinj.core.TransactionOutput; + +import java.math.BigInteger; import java.util.function.Consumer; import lombok.Getter; @@ -130,7 +131,7 @@ public class TradeDataValidation { // Check amount TransactionOutput output = delayedPayoutTx.getOutput(0); Offer offer = checkNotNull(trade.getOffer()); - Coin msOutputAmount = offer.getBuyerSecurityDeposit() + BigInteger msOutputAmount = offer.getBuyerSecurityDeposit() .add(offer.getSellerSecurityDeposit()) .add(checkNotNull(trade.getAmount())); diff --git a/core/src/main/java/bisq/core/trade/TradeManager.java b/core/src/main/java/bisq/core/trade/TradeManager.java index 3066f344..c7edbb7a 100644 --- a/core/src/main/java/bisq/core/trade/TradeManager.java +++ b/core/src/main/java/bisq/core/trade/TradeManager.java @@ -88,6 +88,8 @@ import javafx.collections.ObservableList; import org.bouncycastle.crypto.params.KeyParameter; import org.fxmisc.easybind.EasyBind; + +import java.math.BigInteger; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; @@ -505,11 +507,11 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi } // get expected taker fee - Coin takerFee = HavenoUtils.getTakerFee(Coin.valueOf(offer.getOfferPayload().getAmount())); + BigInteger takerFee = HavenoUtils.getTakerFee(BigInteger.valueOf(offer.getOfferPayload().getAmount())); // create arbitrator trade trade = new ArbitratorTrade(offer, - Coin.valueOf(offer.getOfferPayload().getAmount()), + BigInteger.valueOf(offer.getOfferPayload().getAmount()), takerFee, offer.getOfferPayload().getPrice(), xmrWalletService, @@ -577,12 +579,12 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi openOfferManager.reserveOpenOffer(openOffer); // TODO (woodser): reserve offer if arbitrator? probably. or, arbitrator does not have open offer? // get expected taker fee - Coin takerFee = HavenoUtils.getTakerFee(Coin.valueOf(offer.getOfferPayload().getAmount())); + BigInteger takerFee = HavenoUtils.getTakerFee(BigInteger.valueOf(offer.getOfferPayload().getAmount())); Trade trade; if (offer.isBuyOffer()) trade = new BuyerAsMakerTrade(offer, - Coin.valueOf(offer.getOfferPayload().getAmount()), + BigInteger.valueOf(offer.getOfferPayload().getAmount()), takerFee, offer.getOfferPayload().getPrice(), xmrWalletService, @@ -593,7 +595,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi request.getArbitratorNodeAddress()); else trade = new SellerAsMakerTrade(offer, - Coin.valueOf(offer.getOfferPayload().getAmount()), + BigInteger.valueOf(offer.getOfferPayload().getAmount()), takerFee, offer.getOfferPayload().getPrice(), xmrWalletService, @@ -742,9 +744,9 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi } // First we check if offer is still available then we create the trade with the protocol - public void onTakeOffer(Coin amount, - Coin takerFee, - Coin fundsNeededForTrade, + public void onTakeOffer(BigInteger amount, + BigInteger takerFee, + BigInteger fundsNeededForTrade, Offer offer, String paymentAccountId, boolean useSavingsWallet, @@ -786,7 +788,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi trade.getProcessModel().setTradeMessage(model.getTradeRequest()); trade.getProcessModel().setMakerSignature(model.getMakerSignature()); trade.getProcessModel().setUseSavingsWallet(useSavingsWallet); - trade.getProcessModel().setFundsNeededForTradeAsLong(fundsNeededForTrade.value); + trade.getProcessModel().setFundsNeededForTradeAsLong(fundsNeededForTrade.longValueExact()); trade.getMaker().setPubKeyRing(trade.getOffer().getPubKeyRing()); trade.getSelf().setPubKeyRing(model.getPubKeyRing()); trade.getSelf().setPaymentAccountId(paymentAccountId); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/ArbitratorProcessDepositRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/ArbitratorProcessDepositRequest.java index 2b6e069f..97fce089 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/ArbitratorProcessDepositRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/ArbitratorProcessDepositRequest.java @@ -23,7 +23,6 @@ import bisq.common.crypto.PubKeyRing; import bisq.common.crypto.Sig; import bisq.common.taskrunner.TaskRunner; import bisq.core.offer.Offer; -import bisq.core.trade.HavenoUtils; import bisq.core.trade.Trade; import bisq.core.trade.messages.DepositRequest; import bisq.core.trade.messages.DepositResponse; @@ -37,8 +36,6 @@ import java.util.Arrays; import java.util.Date; import java.util.UUID; -import org.bitcoinj.core.Coin; - import lombok.extern.slf4j.Slf4j; import monero.daemon.MoneroDaemon; import monero.daemon.model.MoneroSubmitTxResult; @@ -79,9 +76,9 @@ public class ArbitratorProcessDepositRequest extends TradeTask { Offer offer = trade.getOffer(); boolean isFromTaker = trader == trade.getTaker(); boolean isFromBuyer = trader == trade.getBuyer(); - BigInteger tradeFee = HavenoUtils.coinToAtomicUnits(isFromTaker ? trade.getTakerFee() : trade.getMakerFee()); - BigInteger sendAmount = HavenoUtils.coinToAtomicUnits(isFromBuyer ? Coin.ZERO : offer.getAmount()); - BigInteger securityDeposit = HavenoUtils.coinToAtomicUnits(isFromBuyer ? offer.getBuyerSecurityDeposit() : offer.getSellerSecurityDeposit()); + BigInteger tradeFee = isFromTaker ? trade.getTakerFee() : trade.getMakerFee(); + BigInteger sendAmount = isFromBuyer ? BigInteger.valueOf(0) : offer.getAmount(); + BigInteger securityDeposit = isFromBuyer ? offer.getBuyerSecurityDeposit() : offer.getSellerSecurityDeposit(); String depositAddress = processModel.getMultisigAddress(); // verify deposit tx diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/ArbitratorProcessReserveTx.java b/core/src/main/java/bisq/core/trade/protocol/tasks/ArbitratorProcessReserveTx.java index c4ba2629..c5ea3cbb 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/ArbitratorProcessReserveTx.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/ArbitratorProcessReserveTx.java @@ -20,14 +20,11 @@ package bisq.core.trade.protocol.tasks; import bisq.common.taskrunner.TaskRunner; import bisq.core.offer.Offer; import bisq.core.offer.OfferDirection; -import bisq.core.trade.HavenoUtils; import bisq.core.trade.Trade; import bisq.core.trade.messages.InitTradeRequest; import bisq.core.trade.protocol.TradePeer; import java.math.BigInteger; -import org.bitcoinj.core.Coin; - import lombok.extern.slf4j.Slf4j; /** @@ -55,9 +52,9 @@ public class ArbitratorProcessReserveTx extends TradeTask { // TODO (woodser): if signer online, should never be called by maker // process reserve tx with expected values - BigInteger tradeFee = HavenoUtils.coinToAtomicUnits(isFromTaker ? trade.getTakerFee() : trade.getMakerFee()); - BigInteger sendAmount = HavenoUtils.coinToAtomicUnits(isFromBuyer ? Coin.ZERO : offer.getAmount()); - BigInteger securityDeposit = HavenoUtils.coinToAtomicUnits(isFromBuyer ? offer.getBuyerSecurityDeposit() : offer.getSellerSecurityDeposit()); + BigInteger tradeFee = isFromTaker ? trade.getTakerFee() : trade.getMakerFee(); + BigInteger sendAmount = isFromBuyer ? BigInteger.valueOf(0) : offer.getAmount(); + BigInteger securityDeposit = isFromBuyer ? offer.getBuyerSecurityDeposit() : offer.getSellerSecurityDeposit(); try { trade.getXmrWalletService().verifyTradeTx( tradeFee, diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/ArbitratorSendInitTradeOrMultisigRequests.java b/core/src/main/java/bisq/core/trade/protocol/tasks/ArbitratorSendInitTradeOrMultisigRequests.java index 58b5ae27..6a7f0acc 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/ArbitratorSendInitTradeOrMultisigRequests.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/ArbitratorSendInitTradeOrMultisigRequests.java @@ -57,9 +57,9 @@ public class ArbitratorSendInitTradeOrMultisigRequests extends TradeTask { processModel.getOfferId(), request.getSenderNodeAddress(), request.getPubKeyRing(), - trade.getAmount().value, + trade.getAmount().longValueExact(), trade.getPrice().getValue(), - trade.getTakerFee().getValue(), + trade.getTakerFee().longValueExact(), request.getAccountId(), request.getPaymentAccountId(), request.getPaymentMethodId(), diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/MakerSendInitTradeRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/MakerSendInitTradeRequest.java index 33b0b95a..23b7bd47 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/MakerSendInitTradeRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/MakerSendInitTradeRequest.java @@ -24,11 +24,8 @@ import bisq.core.trade.messages.InitTradeRequest; import bisq.network.p2p.SendDirectMessageListener; import bisq.common.app.Version; -import bisq.common.crypto.Sig; import bisq.common.taskrunner.TaskRunner; -import com.google.common.base.Charsets; - import java.util.UUID; import lombok.extern.slf4j.Slf4j; @@ -59,9 +56,9 @@ public class MakerSendInitTradeRequest extends TradeTask { offer.getId(), processModel.getMyNodeAddress(), processModel.getPubKeyRing(), - offer.getAmount().value, + offer.getAmount().longValueExact(), trade.getPrice().getValue(), - offer.getMakerFee().value, + offer.getMakerFee().longValueExact(), trade.getProcessModel().getAccountId(), offer.getMakerPaymentAccountId(), offer.getOfferPayload().getPaymentMethodId(), diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessInitTradeRequest.java b/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessInitTradeRequest.java index b4949cd3..18bf158d 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessInitTradeRequest.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/ProcessInitTradeRequest.java @@ -27,7 +27,6 @@ import bisq.core.trade.messages.InitTradeRequest; import bisq.core.trade.protocol.TradePeer; import bisq.common.taskrunner.TaskRunner; -import org.bitcoinj.core.Coin; import com.google.common.base.Charsets; @@ -38,6 +37,7 @@ import static bisq.core.util.Validator.nonEmptyStringOf; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import java.math.BigInteger; import java.util.Date; @Slf4j @@ -134,7 +134,7 @@ public class ProcessInitTradeRequest extends TradeTask { // check trade amount checkArgument(request.getTradeAmount() > 0); - trade.setAmount(Coin.valueOf(request.getTradeAmount())); + trade.setAmount(BigInteger.valueOf(request.getTradeAmount())); // persist trade processModel.getTradeManager().requestPersistence(); diff --git a/core/src/main/java/bisq/core/trade/protocol/tasks/TakerReserveTradeFunds.java b/core/src/main/java/bisq/core/trade/protocol/tasks/TakerReserveTradeFunds.java index 1122632b..7e3a4cc4 100644 --- a/core/src/main/java/bisq/core/trade/protocol/tasks/TakerReserveTradeFunds.java +++ b/core/src/main/java/bisq/core/trade/protocol/tasks/TakerReserveTradeFunds.java @@ -20,14 +20,11 @@ package bisq.core.trade.protocol.tasks; import bisq.common.taskrunner.TaskRunner; import bisq.core.btc.model.XmrAddressEntry; import bisq.core.offer.OfferDirection; -import bisq.core.trade.HavenoUtils; import bisq.core.trade.Trade; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; -import org.bitcoinj.core.Coin; - import monero.daemon.model.MoneroOutput; import monero.wallet.model.MoneroTxWallet; @@ -43,9 +40,9 @@ public class TakerReserveTradeFunds extends TradeTask { runInterceptHook(); // create reserve tx - BigInteger takerFee = HavenoUtils.coinToAtomicUnits(trade.getTakerFee()); - BigInteger sendAmount = HavenoUtils.coinToAtomicUnits(trade.getOffer().getDirection() == OfferDirection.BUY ? trade.getOffer().getAmount() : Coin.ZERO); - BigInteger securityDeposit = HavenoUtils.coinToAtomicUnits(trade.getOffer().getDirection() == OfferDirection.BUY ? trade.getOffer().getSellerSecurityDeposit() : trade.getOffer().getBuyerSecurityDeposit()); + BigInteger takerFee = trade.getTakerFee(); + BigInteger sendAmount = trade.getOffer().getDirection() == OfferDirection.BUY ? trade.getOffer().getAmount() : BigInteger.valueOf(0); + BigInteger securityDeposit = trade.getOffer().getDirection() == OfferDirection.BUY ? trade.getOffer().getSellerSecurityDeposit() : trade.getOffer().getBuyerSecurityDeposit(); String returnAddress = model.getXmrWalletService().getOrCreateAddressEntry(trade.getOffer().getId(), XmrAddressEntry.Context.TRADE_PAYOUT).getAddressString(); MoneroTxWallet reserveTx = model.getXmrWalletService().createReserveTx(takerFee, sendAmount, securityDeposit, returnAddress); diff --git a/core/src/main/java/bisq/core/trade/statistics/TradeStatistics2.java b/core/src/main/java/bisq/core/trade/statistics/TradeStatistics2.java index 8ab7915c..9c8a6f4c 100644 --- a/core/src/main/java/bisq/core/trade/statistics/TradeStatistics2.java +++ b/core/src/main/java/bisq/core/trade/statistics/TradeStatistics2.java @@ -24,6 +24,7 @@ import bisq.core.monetary.Volume; import bisq.core.offer.Offer; import bisq.core.offer.OfferDirection; import bisq.core.offer.OfferPayload; +import bisq.core.trade.HavenoUtils; import bisq.core.trade.Trade; import bisq.core.util.JsonUtil; import bisq.core.util.VolumeUtil; @@ -44,12 +45,12 @@ import bisq.common.util.Utilities; import com.google.protobuf.ByteString; -import org.bitcoinj.core.Coin; import org.bitcoinj.utils.ExchangeRate; import org.bitcoinj.utils.Fiat; import com.google.common.base.Charsets; +import java.math.BigInteger; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -144,7 +145,7 @@ public final class TradeStatistics2 implements ProcessOncePersistableNetworkPayl public TradeStatistics2(OfferPayload offerPayload, Price tradePrice, - Coin tradeAmount, + BigInteger tradeAmount, Date tradeDate, String makerDepositTxId, String takerDepositTxId, @@ -160,7 +161,7 @@ public final class TradeStatistics2 implements ProcessOncePersistableNetworkPayl offerPayload.getMinAmount(), offerPayload.getId(), tradePrice.getValue(), - tradeAmount.value, + tradeAmount.longValueExact(), tradeDate.getTime(), makerDepositTxId, takerDepositTxId, @@ -312,15 +313,15 @@ public final class TradeStatistics2 implements ProcessOncePersistableNetworkPayl return baseCurrency.equals("XMR") ? counterCurrency : baseCurrency; } - public Coin getTradeAmount() { - return Coin.valueOf(tradeAmount); + public BigInteger getTradeAmount() { + return BigInteger.valueOf(tradeAmount); } public Volume getTradeVolume() { if (getPrice().getMonetary() instanceof Altcoin) { - return new Volume(new AltcoinExchangeRate((Altcoin) getPrice().getMonetary()).coinToAltcoin(getTradeAmount())); + return new Volume(new AltcoinExchangeRate((Altcoin) getPrice().getMonetary()).coinToAltcoin(HavenoUtils.atomicUnitsToCoin(getTradeAmount()))); } else { - Volume volume = new Volume(new ExchangeRate((Fiat) getPrice().getMonetary()).coinToFiat(getTradeAmount())); + Volume volume = new Volume(new ExchangeRate((Fiat) getPrice().getMonetary()).coinToFiat(HavenoUtils.atomicUnitsToCoin(getTradeAmount()))); return VolumeUtil.getRoundedFiatVolume(volume); } } diff --git a/core/src/main/java/bisq/core/trade/statistics/TradeStatisticsConverter.java b/core/src/main/java/bisq/core/trade/statistics/TradeStatisticsConverter.java index c8a3c895..d7cc50f3 100644 --- a/core/src/main/java/bisq/core/trade/statistics/TradeStatisticsConverter.java +++ b/core/src/main/java/bisq/core/trade/statistics/TradeStatisticsConverter.java @@ -168,7 +168,7 @@ public class TradeStatisticsConverter { byte[] hash = tradeStatistics2.getHash(); return new TradeStatistics3(tradeStatistics2.getCurrencyCode(), tradeStatistics2.getPrice().getValue(), - tradeStatistics2.getTradeAmount().getValue(), + tradeStatistics2.getTradeAmount().longValueExact(), tradeStatistics2.getOfferPaymentMethod(), time, mediator, diff --git a/core/src/main/java/bisq/core/trade/statistics/TradeStatisticsForJson.java b/core/src/main/java/bisq/core/trade/statistics/TradeStatisticsForJson.java index 5833fbc0..1eaabaec 100644 --- a/core/src/main/java/bisq/core/trade/statistics/TradeStatisticsForJson.java +++ b/core/src/main/java/bisq/core/trade/statistics/TradeStatisticsForJson.java @@ -24,12 +24,12 @@ import bisq.core.monetary.Volume; import bisq.common.util.MathUtils; -import org.bitcoinj.core.Coin; - import lombok.EqualsAndHashCode; import lombok.ToString; import lombok.extern.slf4j.Slf4j; +import java.math.BigInteger; + import javax.annotation.concurrent.Immutable; @Immutable @@ -65,12 +65,12 @@ public final class TradeStatisticsForJson { primaryMarketTradeAmount = getTradeVolume() != null ? getTradeVolume().getValue() : 0; - primaryMarketTradeVolume = getTradeAmount().getValue(); + primaryMarketTradeVolume = getTradeAmount().longValueExact(); } else { currencyPair = Res.getBaseCurrencyCode() + "/" + currency; // we use precision 4 for fiat based price but on the markets api we use precision 8 so we scale up by 10000 primaryMarketTradePrice = (long) MathUtils.scaleUpByPowerOf10(tradePrice.getValue(), 4); - primaryMarketTradeAmount = getTradeAmount().getValue(); + primaryMarketTradeAmount = getTradeAmount().longValueExact(); // we use precision 4 for fiat but on the markets api we use precision 8 so we scale up by 10000 primaryMarketTradeVolume = getTradeVolume() != null ? (long) MathUtils.scaleUpByPowerOf10(getTradeVolume().getValue(), 4) : @@ -86,8 +86,8 @@ public final class TradeStatisticsForJson { return Price.valueOf(currency, tradePrice); } - public Coin getTradeAmount() { - return Coin.valueOf(tradeAmount); + public BigInteger getTradeAmount() { + return BigInteger.valueOf(tradeAmount); } public Volume getTradeVolume() { diff --git a/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofRequestsPerTrade.java b/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofRequestsPerTrade.java index 766c8d56..a93fd6c2 100644 --- a/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofRequestsPerTrade.java +++ b/core/src/main/java/bisq/core/trade/txproof/xmr/XmrTxProofRequestsPerTrade.java @@ -22,6 +22,7 @@ import bisq.core.locale.Res; import bisq.core.support.dispute.Dispute; import bisq.core.support.dispute.mediation.MediationManager; import bisq.core.support.dispute.refund.RefundManager; +import bisq.core.trade.HavenoUtils; import bisq.core.trade.Trade; import bisq.core.trade.txproof.AssetTxProofRequestsPerTrade; import bisq.core.trade.txproof.AssetTxProofResult; @@ -31,13 +32,12 @@ import bisq.network.Socks5ProxyProvider; import bisq.common.handlers.FaultHandler; -import org.bitcoinj.core.Coin; - import javafx.beans.value.ChangeListener; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; +import java.math.BigInteger; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -327,11 +327,11 @@ class XmrTxProofRequestsPerTrade implements AssetTxProofRequestsPerTrade { /////////////////////////////////////////////////////////////////////////////////////////// private boolean isTradeAmountAboveLimit(Trade trade) { - Coin tradeAmount = trade.getAmount(); - Coin tradeLimit = Coin.valueOf(autoConfirmSettings.getTradeLimit()); - if (tradeAmount != null && tradeAmount.isGreaterThan(tradeLimit)) { + BigInteger tradeAmount = trade.getAmount(); + BigInteger tradeLimit = BigInteger.valueOf(autoConfirmSettings.getTradeLimit()); + if (tradeAmount != null && tradeAmount.compareTo(tradeLimit) > 0) { log.warn("Trade amount {} is higher than limit from auto-conf setting {}.", - tradeAmount.toFriendlyString(), tradeLimit.toFriendlyString()); + HavenoUtils.formatToXmrWithCode(tradeAmount), HavenoUtils.formatToXmrWithCode(tradeLimit)); return true; } return false; diff --git a/core/src/main/java/bisq/core/util/coin/CoinUtil.java b/core/src/main/java/bisq/core/util/coin/CoinUtil.java index f92210e3..4dd599c1 100644 --- a/core/src/main/java/bisq/core/util/coin/CoinUtil.java +++ b/core/src/main/java/bisq/core/util/coin/CoinUtil.java @@ -20,6 +20,7 @@ package bisq.core.util.coin; import bisq.core.btc.wallet.Restrictions; import bisq.core.monetary.Price; import bisq.core.monetary.Volume; +import bisq.core.trade.HavenoUtils; import bisq.common.util.MathUtils; import org.bitcoinj.core.Coin; @@ -29,6 +30,9 @@ import com.google.common.annotations.VisibleForTesting; import static bisq.core.util.VolumeUtil.getAdjustedFiatVolume; import static com.google.common.base.Preconditions.checkArgument; +import java.math.BigDecimal; +import java.math.BigInteger; + public class CoinUtil { @@ -49,8 +53,8 @@ public class CoinUtil { * @param value Btc amount to be converted to percent value. E.g. 0.01 BTC is 1% (of 1 BTC) * @return The percentage value as double (e.g. 1% is 0.01) */ - public static double getAsPercentPerBtc(Coin value) { - return getAsPercentPerBtc(value, Coin.COIN); + public static double getAsPercentPerBtc(BigInteger value) { + return getAsPercentPerBtc(value, HavenoUtils.xmrToAtomicUnits(1.0)); } /** @@ -60,20 +64,20 @@ public class CoinUtil { * * @return The percentage value as double (e.g. 1% is 0.01) */ - public static double getAsPercentPerBtc(Coin part, Coin total) { - double asDouble = part != null ? (double) part.value : 0; - double btcAsDouble = total != null ? (double) total.value : 1; - return MathUtils.roundDouble(asDouble / btcAsDouble, 4); + public static double getAsPercentPerBtc(BigInteger part, BigInteger total) { + BigDecimal partDecimal = part == null ? BigDecimal.valueOf(0) : new BigDecimal(part); + BigDecimal totalDecimal = total == null ? BigDecimal.valueOf(1) : new BigDecimal(total); + return MathUtils.roundDouble(partDecimal.divide(totalDecimal).doubleValue(), 4); } /** * @param percent The percentage value as double (e.g. 1% is 0.01) - * @param amount The amount as Coin for the percentage calculation - * @return The percentage as Coin (e.g. 1% of 1 BTC is 0.01 BTC) + * @param amount The amount as atomic units for the percentage calculation + * @return The percentage as atomic units (e.g. 1% of 1 BTC is 0.01 BTC) */ - public static Coin getPercentOfAmountAsCoin(double percent, Coin amount) { - double amountAsDouble = amount != null ? (double) amount.value : 0; - return Coin.valueOf(Math.round(percent * amountAsDouble)); + public static BigInteger getPercentOfAmount(double percent, BigInteger amount) { + if (amount == null) amount = BigInteger.valueOf(0); + return BigDecimal.valueOf(percent).multiply(new BigDecimal(amount)).toBigInteger(); } /** @@ -85,11 +89,11 @@ public class CoinUtil { * @param maxTradeLimit The max. trade limit of the users account, in satoshis. * @return The adjusted amount */ - public static Coin getRoundedFiatAmount(Coin amount, Price price, long maxTradeLimit) { + public static BigInteger getRoundedFiatAmount(BigInteger amount, Price price, long maxTradeLimit) { return getAdjustedAmount(amount, price, maxTradeLimit, 1); } - public static Coin getAdjustedAmountForHalCash(Coin amount, Price price, long maxTradeLimit) { + public static BigInteger getAdjustedAmountForHalCash(BigInteger amount, Price price, long maxTradeLimit) { return getAdjustedAmount(amount, price, maxTradeLimit, 10); } @@ -97,7 +101,7 @@ public class CoinUtil { * Calculate the possibly adjusted amount for {@code amount}, taking into account the * {@code price} and {@code maxTradeLimit} and {@code factor}. * - * @param amount Bitcoin amount which is a candidate for getting rounded. + * @param amount amount which is a candidate for getting rounded. * @param price Price used in relation to that amount. * @param maxTradeLimit The max. trade limit of the users account, in satoshis. * @param factor The factor used for rounding. E.g. 1 means rounded to units of @@ -105,10 +109,10 @@ public class CoinUtil { * @return The adjusted amount */ @VisibleForTesting - static Coin getAdjustedAmount(Coin amount, Price price, long maxTradeLimit, int factor) { + static BigInteger getAdjustedAmount(BigInteger amount, Price price, long maxTradeLimit, int factor) { checkArgument( - amount.getValue() >= 10_000, - "amount needs to be above minimum of 10k satoshis" + amount.longValueExact() >= HavenoUtils.xmrToAtomicUnits(0.0001).longValueExact(), + "amount needs to be above minimum of 0.0001 xmr" // TODO: update amount for XMR ); checkArgument( factor > 0, @@ -118,17 +122,17 @@ public class CoinUtil { // 10 EUR in case of HalCash. Volume smallestUnitForVolume = Volume.parse(String.valueOf(factor), price.getCurrencyCode()); if (smallestUnitForVolume.getValue() <= 0) - return Coin.ZERO; + return BigInteger.valueOf(0); - Coin smallestUnitForAmount = price.getAmountByVolume(smallestUnitForVolume); - long minTradeAmount = Restrictions.getMinTradeAmount().value; + BigInteger smallestUnitForAmount = price.getAmountByVolume(smallestUnitForVolume); + long minTradeAmount = Restrictions.getMinTradeAmount().longValueExact(); // We use 10 000 satoshi as min allowed amount checkArgument( - minTradeAmount >= 10_000, - "MinTradeAmount must be at least 10k satoshis" + minTradeAmount >= HavenoUtils.xmrToAtomicUnits(0.0001).longValueExact(), + "MinTradeAmount must be at least 0.0001 xmr" // TODO: update amount for XMR ); - smallestUnitForAmount = Coin.valueOf(Math.max(minTradeAmount, smallestUnitForAmount.value)); + smallestUnitForAmount = BigInteger.valueOf(Math.max(minTradeAmount, smallestUnitForAmount.longValueExact())); // We don't allow smaller amount values than smallestUnitForAmount boolean useSmallestUnitForAmount = amount.compareTo(smallestUnitForAmount) < 0; @@ -137,21 +141,22 @@ public class CoinUtil { ? getAdjustedFiatVolume(price.getVolumeByAmount(smallestUnitForAmount), factor) : getAdjustedFiatVolume(price.getVolumeByAmount(amount), factor); if (volume.getValue() <= 0) - return Coin.ZERO; + return BigInteger.valueOf(0); // From that adjusted volume we calculate back the amount. It might be a bit different as // the amount used as input before due rounding. - Coin amountByVolume = price.getAmountByVolume(volume); + BigInteger amountByVolume = price.getAmountByVolume(volume); // For the amount we allow only 4 decimal places - long adjustedAmount = Math.round((double) amountByVolume.value / 10000d) * 10000; + // TODO: remove rounding for XMR? + long adjustedAmount = HavenoUtils.centinerosToAtomicUnits(Math.round((double) HavenoUtils.atomicUnitsToCentineros(amountByVolume) / 10000d) * 10000).longValueExact(); // If we are above our trade limit we reduce the amount by the smallestUnitForAmount while (adjustedAmount > maxTradeLimit) { - adjustedAmount -= smallestUnitForAmount.value; + adjustedAmount -= smallestUnitForAmount.longValueExact(); } adjustedAmount = Math.max(minTradeAmount, adjustedAmount); adjustedAmount = Math.min(maxTradeLimit, adjustedAmount); - return Coin.valueOf(adjustedAmount); + return BigInteger.valueOf(adjustedAmount); } } diff --git a/core/src/test/java/bisq/core/account/sign/SignedWitnessServiceTest.java b/core/src/test/java/bisq/core/account/sign/SignedWitnessServiceTest.java index 8efc5b35..3565a4bc 100644 --- a/core/src/test/java/bisq/core/account/sign/SignedWitnessServiceTest.java +++ b/core/src/test/java/bisq/core/account/sign/SignedWitnessServiceTest.java @@ -31,11 +31,11 @@ import bisq.common.crypto.KeyRing; import bisq.common.crypto.Sig; import bisq.common.util.Utilities; -import org.bitcoinj.core.Coin; import org.bitcoinj.core.ECKey; import com.google.common.base.Charsets; +import java.math.BigInteger; import java.security.KeyPair; import java.time.Instant; @@ -354,7 +354,7 @@ public class SignedWitnessServiceTest { when(keyRing.getSignatureKeyPair()).thenReturn(signerKeyPair); AccountAgeWitness accountAgeWitness = new AccountAgeWitness(account1DataHash, accountCreationTime); - signedWitnessService.signAndPublishAccountAgeWitness(Coin.ZERO, accountAgeWitness, peerKeyPair.getPublic()); + signedWitnessService.signAndPublishAccountAgeWitness(BigInteger.valueOf(0), accountAgeWitness, peerKeyPair.getPublic()); verify(p2pService, never()).addPersistableNetworkPayload(any(PersistableNetworkPayload.class), anyBoolean()); } diff --git a/core/src/test/java/bisq/core/account/witness/AccountAgeWitnessServiceTest.java b/core/src/test/java/bisq/core/account/witness/AccountAgeWitnessServiceTest.java index 6153b1df..ce65fb36 100644 --- a/core/src/test/java/bisq/core/account/witness/AccountAgeWitnessServiceTest.java +++ b/core/src/test/java/bisq/core/account/witness/AccountAgeWitnessServiceTest.java @@ -32,7 +32,7 @@ import bisq.core.support.dispute.DisputeResult; import bisq.core.support.dispute.arbitration.TraderDataItem; import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager; import bisq.core.trade.Contract; - +import bisq.core.trade.HavenoUtils; import bisq.network.p2p.P2PService; import bisq.network.p2p.storage.persistence.AppendOnlyDataStoreService; @@ -44,7 +44,6 @@ import bisq.common.crypto.PubKeyRing; import bisq.common.crypto.Sig; import bisq.common.util.Utilities; -import org.bitcoinj.core.Coin; import org.bitcoinj.core.ECKey; import java.security.KeyPair; @@ -52,7 +51,6 @@ import java.security.PublicKey; import java.io.File; import java.io.IOException; - import java.util.ArrayList; import java.util.Calendar; import java.util.Date; @@ -227,7 +225,7 @@ public class AccountAgeWitnessServiceTest { when(chargeBackRisk.hasChargebackRisk(any(), any())).thenReturn(true); when(contract.getPaymentMethodId()).thenReturn(PaymentMethod.SEPA_ID); - when(contract.getTradeAmount()).thenReturn(Coin.parseCoin("0.01")); + when(contract.getTradeAmount()).thenReturn(HavenoUtils.xmrToAtomicUnits(0.01)); when(contract.getBuyerPubKeyRing()).thenReturn(buyerPubKeyRing); when(contract.getSellerPubKeyRing()).thenReturn(sellerPubKeyRing); when(contract.getOfferPayload()).thenReturn(mock(OfferPayload.class)); @@ -357,7 +355,7 @@ public class AccountAgeWitnessServiceTest { signerKeyRing.getSignatureKeyPair().getPublic().getEncoded(), witnessOwnerPubKey.getEncoded(), time, - SignedWitnessService.MINIMUM_TRADE_AMOUNT_FOR_SIGNING.value); + SignedWitnessService.MINIMUM_TRADE_AMOUNT_FOR_SIGNING.longValueExact()); signedWitnessService.addToMap(signedWitness); } diff --git a/core/src/test/java/bisq/core/arbitration/TraderDataItemTest.java b/core/src/test/java/bisq/core/arbitration/TraderDataItemTest.java index 3a743153..3b3ff01f 100644 --- a/core/src/test/java/bisq/core/arbitration/TraderDataItemTest.java +++ b/core/src/test/java/bisq/core/arbitration/TraderDataItemTest.java @@ -4,8 +4,7 @@ import bisq.core.account.witness.AccountAgeWitness; import bisq.core.support.dispute.arbitration.TraderDataItem; import bisq.core.payment.payload.PaymentAccountPayload; -import org.bitcoinj.core.Coin; - +import java.math.BigInteger; import java.security.PublicKey; import org.junit.Before; @@ -44,11 +43,11 @@ public class TraderDataItemTest { public void setup() { accountAgeWitness1 = new AccountAgeWitness(hash1, 123); accountAgeWitness2 = new AccountAgeWitness(hash2, 124); - traderDataItem1 = new TraderDataItem(mock(PaymentAccountPayload.class), accountAgeWitness1, Coin.valueOf(546), + traderDataItem1 = new TraderDataItem(mock(PaymentAccountPayload.class), accountAgeWitness1, BigInteger.valueOf(546), mock(PublicKey.class)); - traderDataItem2 = new TraderDataItem(mock(PaymentAccountPayload.class), accountAgeWitness1, Coin.valueOf(547), + traderDataItem2 = new TraderDataItem(mock(PaymentAccountPayload.class), accountAgeWitness1, BigInteger.valueOf(547), mock(PublicKey.class)); - traderDataItem3 = new TraderDataItem(mock(PaymentAccountPayload.class), accountAgeWitness2, Coin.valueOf(548), + traderDataItem3 = new TraderDataItem(mock(PaymentAccountPayload.class), accountAgeWitness2, BigInteger.valueOf(548), mock(PublicKey.class)); } diff --git a/core/src/test/java/bisq/core/util/coin/CoinUtilTest.java b/core/src/test/java/bisq/core/util/coin/CoinUtilTest.java index 5bb1c8b0..a8b4e837 100644 --- a/core/src/test/java/bisq/core/util/coin/CoinUtilTest.java +++ b/core/src/test/java/bisq/core/util/coin/CoinUtilTest.java @@ -27,14 +27,16 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; +import java.math.BigInteger; + public class CoinUtilTest { @Test public void testGetFeePerBtc() { - assertEquals(Coin.parseCoin("1"), HavenoUtils.getFeePerXmr(Coin.parseCoin("1"), Coin.parseCoin("1"))); - assertEquals(Coin.parseCoin("0.1"), HavenoUtils.getFeePerXmr(Coin.parseCoin("0.1"), Coin.parseCoin("1"))); - assertEquals(Coin.parseCoin("0.01"), HavenoUtils.getFeePerXmr(Coin.parseCoin("0.1"), Coin.parseCoin("0.1"))); - assertEquals(Coin.parseCoin("0.015"), HavenoUtils.getFeePerXmr(Coin.parseCoin("0.3"), Coin.parseCoin("0.05"))); + assertEquals(HavenoUtils.xmrToAtomicUnits(1), HavenoUtils.getFeePerXmr(HavenoUtils.xmrToAtomicUnits(1), HavenoUtils.xmrToAtomicUnits(1))); + assertEquals(HavenoUtils.xmrToAtomicUnits(0.1), HavenoUtils.getFeePerXmr(HavenoUtils.xmrToAtomicUnits(0.1), HavenoUtils.xmrToAtomicUnits(1))); + assertEquals(HavenoUtils.xmrToAtomicUnits(0.01), HavenoUtils.getFeePerXmr(HavenoUtils.xmrToAtomicUnits(0.1), HavenoUtils.xmrToAtomicUnits(0.1))); + assertEquals(HavenoUtils.xmrToAtomicUnits(0.015), HavenoUtils.getFeePerXmr(HavenoUtils.xmrToAtomicUnits(0.3), HavenoUtils.xmrToAtomicUnits(0.05))); } @Test @@ -57,52 +59,52 @@ public class CoinUtilTest { @Test public void testGetAdjustedAmount() { - Coin result = CoinUtil.getAdjustedAmount( - Coin.valueOf(100_000), + BigInteger result = CoinUtil.getAdjustedAmount( + HavenoUtils.xmrToAtomicUnits(0.001), Price.valueOf("USD", 1000_0000), - 20_000_000, + HavenoUtils.xmrToAtomicUnits(0.2).longValueExact(), 1); assertEquals( "Minimum trade amount allowed should be adjusted to the smallest trade allowed.", - "0.001 BTC", - result.toFriendlyString() + "0.001 XMR", + HavenoUtils.formatToXmrWithCode(result) ); try { CoinUtil.getAdjustedAmount( - Coin.ZERO, + BigInteger.valueOf(0), Price.valueOf("USD", 1000_0000), - 20_000_000, + HavenoUtils.xmrToAtomicUnits(0.2).longValueExact(), 1); fail("Expected IllegalArgumentException to be thrown when amount is too low."); } catch (IllegalArgumentException iae) { assertEquals( "Unexpected exception message.", - "amount needs to be above minimum of 10k satoshis", + "amount needs to be above minimum of 0.0001 xmr", iae.getMessage() ); } result = CoinUtil.getAdjustedAmount( - Coin.valueOf(1_000_000), + HavenoUtils.xmrToAtomicUnits(0.01), Price.valueOf("USD", 1000_0000), - 20_000_000, + HavenoUtils.xmrToAtomicUnits(0.2).longValueExact(), 1); assertEquals( "Minimum allowed trade amount should not be adjusted.", - "0.01 BTC", - result.toFriendlyString() + "0.01 XMR", + HavenoUtils.formatToXmrWithCode(result) ); result = CoinUtil.getAdjustedAmount( - Coin.valueOf(100_000), + HavenoUtils.xmrToAtomicUnits(0.001), Price.valueOf("USD", 1000_0000), - 1_000_000, + HavenoUtils.xmrToAtomicUnits(0.1).longValueExact(), 1); assertEquals( "Minimum trade amount allowed should respect maxTradeLimit and factor, if possible.", - "0.001 BTC", - result.toFriendlyString() + "0.001 XMR", + HavenoUtils.formatToXmrWithCode(result) ); // TODO(chirhonul): The following seems like it should raise an exception or otherwise fail. @@ -111,14 +113,14 @@ public class CoinUtilTest { // 0.05 USD worth, which is below the factor of 1 USD, but does respect the maxTradeLimit. // Basically the given constraints (maxTradeLimit vs factor) are impossible to both fulfill.. result = CoinUtil.getAdjustedAmount( - Coin.valueOf(100_000), + HavenoUtils.xmrToAtomicUnits(0.001), Price.valueOf("USD", 1000_0000), - 5_000, + HavenoUtils.xmrToAtomicUnits(0.00005).longValueExact(), 1); assertEquals( "Minimum trade amount allowed with low maxTradeLimit should still respect that limit, even if result does not respect the factor specified.", - "0.00005 BTC", - result.toFriendlyString() + "0.00005 XMR", + HavenoUtils.formatToXmrWithCode(result) ); } } diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcDisputesService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcDisputesService.java index 82de58a7..70268bef 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcDisputesService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcDisputesService.java @@ -3,7 +3,6 @@ package bisq.daemon.grpc; import bisq.core.api.CoreApi; import bisq.core.support.dispute.Attachment; import bisq.core.support.dispute.DisputeResult; -import bisq.core.trade.HavenoUtils; import bisq.common.proto.ProtoUtil; @@ -108,9 +107,7 @@ public class GrpcDisputesService extends DisputesImplBase { try { var winner = ProtoUtil.enumFromProto(DisputeResult.Winner.class, req.getWinner().name()); var reason = ProtoUtil.enumFromProto(DisputeResult.Reason.class, req.getReason().name()); - // scale atomic unit to centineros for consistency TODO switch base to atomic units? - var customPayoutAmount = HavenoUtils.atomicUnitsToCentineros(req.getCustomPayoutAmount()); - coreApi.resolveDispute(req.getTradeId(), winner, reason, req.getSummaryNotes(), customPayoutAmount); + coreApi.resolveDispute(req.getTradeId(), winner, reason, req.getSummaryNotes(), req.getCustomPayoutAmount()); var reply = ResolveDisputeReply.newBuilder().build(); responseObserver.onNext(reply); responseObserver.onCompleted(); diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java index 7773c1b2..9e8bd6f4 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcOffersService.java @@ -21,7 +21,6 @@ import bisq.core.api.CoreApi; import bisq.core.api.model.OfferInfo; import bisq.core.offer.Offer; import bisq.core.offer.OpenOffer; -import bisq.core.trade.HavenoUtils; import bisq.proto.grpc.CancelOfferReply; import bisq.proto.grpc.CancelOfferRequest; import bisq.proto.grpc.PostOfferReply; @@ -154,8 +153,8 @@ class GrpcOffersService extends OffersImplBase { req.getPrice(), req.getUseMarketBasedPrice(), req.getMarketPriceMarginPct(), - HavenoUtils.atomicUnitsToCentineros(req.getAmount()), // scale atomic unit to centineros for consistency TODO switch base to atomic units? - HavenoUtils.atomicUnitsToCentineros(req.getMinAmount()), + req.getAmount(), + req.getMinAmount(), req.getBuyerSecurityDepositPct(), req.getTriggerPrice(), req.getPaymentAccountId(), diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java index dae89ff4..94c4b9ef 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcTradesService.java @@ -37,8 +37,6 @@ import bisq.proto.grpc.SendChatMessageReply; import bisq.proto.grpc.SendChatMessageRequest; import bisq.proto.grpc.TakeOfferReply; import bisq.proto.grpc.TakeOfferRequest; -import bisq.proto.grpc.WithdrawFundsReply; -import bisq.proto.grpc.WithdrawFundsRequest; import io.grpc.ServerInterceptor; import io.grpc.stub.StreamObserver; @@ -191,19 +189,6 @@ class GrpcTradesService extends TradesImplBase { } } - @Override - public void withdrawFunds(WithdrawFundsRequest req, - StreamObserver<WithdrawFundsReply> responseObserver) { - try { - coreApi.withdrawFunds(req.getTradeId(), req.getAddress(), req.getMemo()); - var reply = WithdrawFundsReply.newBuilder().build(); - responseObserver.onNext(reply); - responseObserver.onCompleted(); - } catch (Throwable cause) { - exceptionHandler.handleException(log, cause, responseObserver); - } - } - @Override public void getChatMessages(GetChatMessagesRequest req, StreamObserver<GetChatMessagesReply> responseObserver) { diff --git a/desktop/src/main/java/bisq/desktop/components/AccountStatusTooltipLabel.java b/desktop/src/main/java/bisq/desktop/components/AccountStatusTooltipLabel.java index edc53820..194dbd20 100644 --- a/desktop/src/main/java/bisq/desktop/components/AccountStatusTooltipLabel.java +++ b/desktop/src/main/java/bisq/desktop/components/AccountStatusTooltipLabel.java @@ -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(); } diff --git a/desktop/src/main/java/bisq/desktop/components/AddressTextField.java b/desktop/src/main/java/bisq/desktop/components/AddressTextField.java index 4ccf984f..5e37bb47 100644 --- a/desktop/src/main/java/bisq/desktop/components/AddressTextField.java +++ b/desktop/src/main/java/bisq/desktop/components/AddressTextField.java @@ -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()); } } diff --git a/desktop/src/main/java/bisq/desktop/components/BalanceTextField.java b/desktop/src/main/java/bisq/desktop/components/BalanceTextField.java index 00fb6a4a..b3a997a5 100644 --- a/desktop/src/main/java/bisq/desktop/components/BalanceTextField.java +++ b/desktop/src/main/java/bisq/desktop/components/BalanceTextField.java @@ -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) { diff --git a/desktop/src/main/java/bisq/desktop/main/MainView.java b/desktop/src/main/java/bisq/desktop/main/MainView.java index 67847225..13c91bf1 100644 --- a/desktop/src/main/java/bisq/desktop/main/MainView.java +++ b/desktop/src/main/java/bisq/desktop/main/MainView.java @@ -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()); diff --git a/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsView.java b/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsView.java index 6609c2d3..c12fc29c 100644 --- a/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsView.java +++ b/desktop/src/main/java/bisq/desktop/main/account/content/fiataccounts/FiatAccountsView.java @@ -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")) diff --git a/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositListItem.java b/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositListItem.java index e027581f..8186e70f 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositListItem.java @@ -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() { diff --git a/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositView.java b/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositView.java index bf6d3f6c..cff5aec5 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositView.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/deposit/DepositView.java @@ -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)); } diff --git a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionListItemFactory.java b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionListItemFactory.java index b3ace3e2..79244c2c 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionListItemFactory.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionListItemFactory.java @@ -51,8 +51,6 @@ public class TransactionListItemFactory { TransactionsListItem create(MoneroTxWallet transaction, @Nullable TransactionAwareTradable tradable) { return new TransactionsListItem(transaction, xmrWalletService, - tradable, - formatter, - preferences.getIgnoreDustThreshold()); + tradable); } } diff --git a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsListItem.java b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsListItem.java index 683d5a0a..2c0738fd 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsListItem.java @@ -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; } diff --git a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsView.java b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsView.java index cbc57d3f..14c5d6d3 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsView.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/transactions/TransactionsView.java @@ -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); } diff --git a/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalListItem.java b/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalListItem.java index a945b833..8e0ccf69 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalListItem.java @@ -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; } diff --git a/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java b/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java index 09e82ba9..c30b13dd 100644 --- a/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java +++ b/desktop/src/main/java/bisq/desktop/main/funds/withdrawal/WithdrawalView.java @@ -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")); diff --git a/desktop/src/main/java/bisq/desktop/main/market/offerbook/OfferBookChartViewModel.java b/desktop/src/main/java/bisq/desktop/main/market/offerbook/OfferBookChartViewModel.java index 3556ad29..d91bed66 100644 --- a/desktop/src/main/java/bisq/desktop/main/market/offerbook/OfferBookChartViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/market/offerbook/OfferBookChartViewModel.java @@ -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)); diff --git a/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadItem.java b/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadItem.java index 5ed0ed9b..d0bb8b82 100644 --- a/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadItem.java +++ b/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadItem.java @@ -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; diff --git a/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadView.java b/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadView.java index 1b37e4d4..e70abc4e 100644 --- a/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadView.java +++ b/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadView.java @@ -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))); diff --git a/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadViewModel.java b/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadViewModel.java index f7e512c1..63de530e 100644 --- a/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/market/spread/SpreadViewModel.java @@ -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()); } } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java index 9e3c5d31..897d582a 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferDataModel.java @@ -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) { diff --git a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java index 96d6c312..9cd4cd85 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferView.java @@ -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(); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferViewModel.java index a454ff70..8ca9388a 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/MutableOfferViewModel.java @@ -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); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/OfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/offer/OfferDataModel.java index f23de253..691cc16d 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/OfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/OfferDataModel.java @@ -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); } } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/OfferViewModelUtil.java b/desktop/src/main/java/bisq/desktop/main/offer/OfferViewModelUtil.java index b9c1575f..73b41b0f 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/OfferViewModelUtil.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/OfferViewModelUtil.java @@ -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(")", ""); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/createoffer/CreateOfferViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/createoffer/CreateOfferViewModel.java index 123be117..473b71c9 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/createoffer/CreateOfferViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/createoffer/CreateOfferViewModel.java @@ -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, diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java index 9fe47b82..23d7772c 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookView.java @@ -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 { diff --git a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java index 3df76c1e..d625f510 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/offerbook/OfferBookViewModel.java @@ -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() { diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java index 42f9b7e2..7ef6a693 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferDataModel.java @@ -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(); } diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java index de9ac430..a5e5baf2 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferView.java @@ -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(); diff --git a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java index ef4e3ddd..aa3d7754 100644 --- a/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/offer/takeoffer/TakeOfferViewModel.java @@ -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() { diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/ContractWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/ContractWindow.java index 6345e13d..482c20b2 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/ContractWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/ContractWindow.java @@ -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, diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/DisputeSummaryWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/DisputeSummaryWindow.java index ce85389f..07d00a77 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/DisputeSummaryWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/DisputeSummaryWindow.java @@ -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)) { diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/OfferDetailsWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/OfferDetailsWindow.java index 399e8e53..63091870 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/OfferDetailsWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/OfferDetailsWindow.java @@ -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) diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java b/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java index c96b1d88..8772bd6d 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/windows/TradeDetailsWindow.java @@ -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(); diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesListItem.java b/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesListItem.java index 16a09985..89ca791e 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/closedtrades/ClosedTradesListItem.java @@ -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); } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/duplicateoffer/DuplicateOfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/duplicateoffer/DuplicateOfferDataModel.java index 90c4bc49..aa364bb8 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/duplicateoffer/DuplicateOfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/duplicateoffer/DuplicateOfferDataModel.java @@ -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, diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/duplicateoffer/DuplicateOfferViewModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/duplicateoffer/DuplicateOfferViewModel.java index 544b60ae..d47f1df6 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/duplicateoffer/DuplicateOfferViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/duplicateoffer/DuplicateOfferViewModel.java @@ -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, diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferDataModel.java index 47b1dd78..c3c65447 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferDataModel.java @@ -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; } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferViewModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferViewModel.java index d5e32aec..603d0f40 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/editoffer/EditOfferViewModel.java @@ -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, diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.java index 1f75005a..9a26fb3d 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesView.java @@ -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 ) diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesViewModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesViewModel.java index 052a0299..56d4bda8 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/failedtrades/FailedTradesViewModel.java @@ -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 ""; } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersViewModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersViewModel.java index 099fdfd4..5d1b3bf4 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/openoffer/OpenOffersViewModel.java @@ -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) { diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java index e72aaf61..39c62565 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesDataModel.java @@ -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); } } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesListItem.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesListItem.java index 103f42c1..0cd8bea3 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesListItem.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesListItem.java @@ -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() { diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java index f1caf40a..d91be0ac 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesView.java @@ -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); } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java index e125f924..309524af 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/PendingTradesViewModel.java @@ -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 ""; } diff --git a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java index 8ec3a8d0..79150a6f 100644 --- a/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java +++ b/desktop/src/main/java/bisq/desktop/main/portfolio/pendingtrades/steps/TradeStepView.java @@ -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; diff --git a/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java b/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java index f41544fb..77d217a9 100644 --- a/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java +++ b/desktop/src/main/java/bisq/desktop/main/settings/preferences/PreferencesView.java @@ -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()); } }; diff --git a/desktop/src/main/java/bisq/desktop/main/support/dispute/DisputeView.java b/desktop/src/main/java/bisq/desktop/main/support/dispute/DisputeView.java index 46c76951..15935f5d 100644 --- a/desktop/src/main/java/bisq/desktop/main/support/dispute/DisputeView.java +++ b/desktop/src/main/java/bisq/desktop/main/support/dispute/DisputeView.java @@ -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: ") diff --git a/desktop/src/main/java/bisq/desktop/main/support/dispute/agent/SignedOfferView.java b/desktop/src/main/java/bisq/desktop/main/support/dispute/agent/SignedOfferView.java index 9ce14b9b..7338311b 100644 --- a/desktop/src/main/java/bisq/desktop/main/support/dispute/agent/SignedOfferView.java +++ b/desktop/src/main/java/bisq/desktop/main/support/dispute/agent/SignedOfferView.java @@ -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(""); } diff --git a/desktop/src/main/java/bisq/desktop/util/DisplayUtils.java b/desktop/src/main/java/bisq/desktop/util/DisplayUtils.java index afe74aa6..61ebc2f6 100644 --- a/desktop/src/main/java/bisq/desktop/util/DisplayUtils.java +++ b/desktop/src/main/java/bisq/desktop/util/DisplayUtils.java @@ -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; } } diff --git a/desktop/src/main/java/bisq/desktop/util/GUIUtil.java b/desktop/src/main/java/bisq/desktop/util/GUIUtil.java index 42e60e89..87ed2433 100644 --- a/desktop/src/main/java/bisq/desktop/util/GUIUtil.java +++ b/desktop/src/main/java/bisq/desktop/util/GUIUtil.java @@ -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)); } diff --git a/desktop/src/test/java/bisq/desktop/main/market/offerbook/OfferBookChartViewModelTest.java b/desktop/src/test/java/bisq/desktop/main/market/offerbook/OfferBookChartViewModelTest.java index db4ea05c..b617075d 100644 --- a/desktop/src/test/java/bisq/desktop/main/market/offerbook/OfferBookChartViewModelTest.java +++ b/desktop/src/test/java/bisq/desktop/main/market/offerbook/OfferBookChartViewModelTest.java @@ -122,9 +122,9 @@ public class OfferBookChartViewModelTest { final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, null, empty, service, null, null); model.activate(); assertEquals(1, model.maxPlacesForBuyVolume.intValue()); //0 - offerBookListItems.addAll(make(xmrBuyItem.but(with(OfferBookListItemMaker.amount, 100000000L)))); + offerBookListItems.addAll(make(xmrBuyItem.but(with(OfferBookListItemMaker.amount, 1000000000000L)))); assertEquals(2, model.maxPlacesForBuyVolume.intValue()); //10 - offerBookListItems.addAll(make(xmrBuyItem.but(with(OfferBookListItemMaker.amount, 22128600000L)))); + offerBookListItems.addAll(make(xmrBuyItem.but(with(OfferBookListItemMaker.amount, 221286000000000L)))); assertEquals(4, model.maxPlacesForBuyVolume.intValue()); //2213 } @@ -200,9 +200,9 @@ public class OfferBookChartViewModelTest { final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, null, empty, service, null, null); model.activate(); assertEquals(1, model.maxPlacesForSellVolume.intValue()); //0 - offerBookListItems.addAll(make(xmrSellItem.but(with(OfferBookListItemMaker.amount, 100000000L)))); + offerBookListItems.addAll(make(xmrSellItem.but(with(OfferBookListItemMaker.amount, 1000000000000L)))); assertEquals(2, model.maxPlacesForSellVolume.intValue()); //10 - offerBookListItems.addAll(make(xmrSellItem.but(with(OfferBookListItemMaker.amount, 22128600000L)))); + offerBookListItems.addAll(make(xmrSellItem.but(with(OfferBookListItemMaker.amount, 221286000000000L)))); assertEquals(4, model.maxPlacesForSellVolume.intValue()); //2213 } } diff --git a/desktop/src/test/java/bisq/desktop/main/market/spread/SpreadViewModelTest.java b/desktop/src/test/java/bisq/desktop/main/market/spread/SpreadViewModelTest.java index 01d63aad..8cf69ead 100644 --- a/desktop/src/test/java/bisq/desktop/main/market/spread/SpreadViewModelTest.java +++ b/desktop/src/test/java/bisq/desktop/main/market/spread/SpreadViewModelTest.java @@ -68,7 +68,7 @@ public class SpreadViewModelTest { SpreadViewModel model = new SpreadViewModel(offerBook, null, coinFormatter); model.activate(); assertEquals(6, model.maxPlacesForAmount.intValue()); // 0.001 - offerBookListItems.addAll(make(xmrBuyItem.but(with(OfferBookListItemMaker.amount, 1403000000L)))); + offerBookListItems.addAll(make(xmrBuyItem.but(with(OfferBookListItemMaker.amount, 14030000000000L)))); assertEquals(7, model.maxPlacesForAmount.intValue()); //14.0300 } diff --git a/desktop/src/test/java/bisq/desktop/main/offer/createoffer/CreateOfferViewModelTest.java b/desktop/src/test/java/bisq/desktop/main/offer/createoffer/CreateOfferViewModelTest.java index 1f8ae2eb..923a285b 100644 --- a/desktop/src/test/java/bisq/desktop/main/offer/createoffer/CreateOfferViewModelTest.java +++ b/desktop/src/test/java/bisq/desktop/main/offer/createoffer/CreateOfferViewModelTest.java @@ -26,11 +26,10 @@ import bisq.core.locale.GlobalSettings; import bisq.core.locale.Res; import bisq.core.offer.CreateOfferService; import bisq.core.offer.OfferDirection; -import bisq.core.offer.OfferPayload; 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.SecurityDepositValidator; import bisq.core.provider.price.MarketPrice; import bisq.core.provider.price.PriceFeedService; @@ -45,12 +44,11 @@ import bisq.core.util.validation.InputValidator; import bisq.common.config.Config; -import org.bitcoinj.core.Coin; - import javafx.beans.property.SimpleIntegerProperty; import javafx.collections.FXCollections; +import java.math.BigInteger; import java.time.Instant; import java.util.UUID; @@ -62,7 +60,6 @@ import static bisq.desktop.maker.PreferenceMakers.empty; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -79,7 +76,7 @@ public class CreateOfferViewModelTest { GlobalSettings.setDefaultTradeCurrency(btc); Res.setup(); - final BtcValidator btcValidator = new BtcValidator(coinFormatter); + final XmrValidator btcValidator = new XmrValidator(); final AltcoinValidator altcoinValidator = new AltcoinValidator(); final FiatPriceValidator fiatPriceValidator = new FiatPriceValidator(); @@ -96,7 +93,7 @@ public class CreateOfferViewModelTest { var tradeStats = mock(TradeStatisticsManager.class); when(xmrWalletService.getOrCreateAddressEntry(anyString(), any())).thenReturn(addressEntry); - when(xmrWalletService.getBalanceForSubaddress(any(Integer.class))).thenReturn(Coin.valueOf(1000L)); + when(xmrWalletService.getBalanceForSubaddress(any(Integer.class))).thenReturn(BigInteger.valueOf(10000000L)); when(priceFeedService.updateCounterProperty()).thenReturn(new SimpleIntegerProperty()); when(priceFeedService.getMarketPrice(anyString())).thenReturn( new MarketPrice("USD", diff --git a/desktop/src/test/java/bisq/desktop/main/offer/offerbook/OfferBookListItemMaker.java b/desktop/src/test/java/bisq/desktop/main/offer/offerbook/OfferBookListItemMaker.java index 82fe7a7e..e77c5a26 100644 --- a/desktop/src/test/java/bisq/desktop/main/offer/offerbook/OfferBookListItemMaker.java +++ b/desktop/src/test/java/bisq/desktop/main/offer/offerbook/OfferBookListItemMaker.java @@ -46,8 +46,8 @@ public class OfferBookListItemMaker { public static final Instantiator<OfferBookListItem> OfferBookListItem = lookup -> new OfferBookListItem(make(xmrUsdOffer.but( MakeItEasy.with(OfferMaker.price, lookup.valueOf(price, 100000L)), - with(OfferMaker.amount, lookup.valueOf(amount, 100000L)), - with(OfferMaker.minAmount, lookup.valueOf(amount, 100000L)), + with(OfferMaker.amount, lookup.valueOf(amount, 1000000000L)), + with(OfferMaker.minAmount, lookup.valueOf(amount, 1000000000L)), with(OfferMaker.direction, lookup.valueOf(direction, OfferDirection.BUY)), with(OfferMaker.useMarketBasedPrice, lookup.valueOf(useMarketBasedPrice, false)), with(OfferMaker.marketPriceMargin, lookup.valueOf(marketPriceMargin, 0.0)), @@ -59,8 +59,8 @@ public class OfferBookListItemMaker { public static final Instantiator<OfferBookListItem> OfferBookListItemWithRange = lookup -> new OfferBookListItem(make(xmrUsdOffer.but( MakeItEasy.with(OfferMaker.price, lookup.valueOf(price, 100000L)), - with(OfferMaker.minAmount, lookup.valueOf(minAmount, 100000L)), - with(OfferMaker.amount, lookup.valueOf(amount, 200000L))))); + with(OfferMaker.minAmount, lookup.valueOf(minAmount, 1000000000L)), + with(OfferMaker.amount, lookup.valueOf(amount, 2000000000L))))); public static final Maker<OfferBookListItem> xmrBuyItem = a(OfferBookListItem); public static final Maker<OfferBookListItem> xmrSellItem = a(OfferBookListItem, with(direction, OfferDirection.SELL)); diff --git a/desktop/src/test/java/bisq/desktop/main/offer/offerbook/OfferBookViewModelTest.java b/desktop/src/test/java/bisq/desktop/main/offer/offerbook/OfferBookViewModelTest.java index 05fd44df..dc8f38c3 100644 --- a/desktop/src/test/java/bisq/desktop/main/offer/offerbook/OfferBookViewModelTest.java +++ b/desktop/src/test/java/bisq/desktop/main/offer/offerbook/OfferBookViewModelTest.java @@ -261,7 +261,7 @@ public class OfferBookViewModelTest { model.activate(); assertEquals(6, model.maxPlacesForAmount.intValue()); - offerBookListItems.addAll(make(xmrBuyItem.but(with(amount, 2000000000L)))); + offerBookListItems.addAll(make(xmrBuyItem.but(with(amount, 20000000000000L)))); assertEquals(7, model.maxPlacesForAmount.intValue()); } @@ -279,10 +279,10 @@ public class OfferBookViewModelTest { model.activate(); assertEquals(15, model.maxPlacesForAmount.intValue()); - offerBookListItems.addAll(make(xmrItemWithRange.but(with(amount, 2000000000L)))); + offerBookListItems.addAll(make(xmrItemWithRange.but(with(amount, 20000000000000L)))); assertEquals(16, model.maxPlacesForAmount.intValue()); - offerBookListItems.addAll(make(xmrItemWithRange.but(with(minAmount, 30000000000L), - with(amount, 30000000000L)))); + offerBookListItems.addAll(make(xmrItemWithRange.but(with(minAmount, 300000000000000L), + with(amount, 300000000000000L)))); assertEquals(19, model.maxPlacesForAmount.intValue()); } @@ -312,7 +312,7 @@ public class OfferBookViewModelTest { model.activate(); assertEquals(5, model.maxPlacesForVolume.intValue()); - offerBookListItems.addAll(make(xmrBuyItem.but(with(amount, 2000000000L)))); + offerBookListItems.addAll(make(xmrBuyItem.but(with(amount, 20000000000000L)))); assertEquals(7, model.maxPlacesForVolume.intValue()); } @@ -330,10 +330,10 @@ public class OfferBookViewModelTest { model.activate(); assertEquals(9, model.maxPlacesForVolume.intValue()); - offerBookListItems.addAll(make(xmrItemWithRange.but(with(amount, 2000000000L)))); + offerBookListItems.addAll(make(xmrItemWithRange.but(with(amount, 20000000000000L)))); assertEquals(11, model.maxPlacesForVolume.intValue()); - offerBookListItems.addAll(make(xmrItemWithRange.but(with(minAmount, 30000000000L), - with(amount, 30000000000L)))); + offerBookListItems.addAll(make(xmrItemWithRange.but(with(minAmount, 300000000000000L), + with(amount, 300000000000000L)))); assertEquals(19, model.maxPlacesForVolume.intValue()); } @@ -453,7 +453,6 @@ public class OfferBookViewModelTest { offerBookListItems.addAll(lowItem, fixedItem); model.activate(); - assertEquals("12557.2046", model.getPrice(lowItem)); assertEquals("(1.00%)", model.getPriceAsPercentage(lowItem)); assertEquals("10.0000", model.getPrice(fixedItem)); diff --git a/desktop/src/test/java/bisq/desktop/util/DisplayUtilsTest.java b/desktop/src/test/java/bisq/desktop/util/DisplayUtilsTest.java index 63d73c10..3a734dbd 100644 --- a/desktop/src/test/java/bisq/desktop/util/DisplayUtilsTest.java +++ b/desktop/src/test/java/bisq/desktop/util/DisplayUtilsTest.java @@ -11,8 +11,7 @@ import bisq.core.util.coin.ImmutableCoinFormatter; import bisq.common.config.Config; -import org.bitcoinj.core.Coin; - +import java.math.BigInteger; import java.util.Locale; import java.util.concurrent.TimeUnit; @@ -91,8 +90,8 @@ public class DisplayUtilsTest { @Test public void testFormatSameAmount() { Offer offer = mock(Offer.class); - when(offer.getMinAmount()).thenReturn(Coin.valueOf(10000000)); - when(offer.getAmount()).thenReturn(Coin.valueOf(10000000)); + when(offer.getMinAmount()).thenReturn(BigInteger.valueOf(100000000000L)); + when(offer.getAmount()).thenReturn(BigInteger.valueOf(100000000000L)); assertEquals("0.10", DisplayUtils.formatAmount(offer, formatter)); } @@ -101,8 +100,8 @@ public class DisplayUtilsTest { public void testFormatDifferentAmount() { OfferPayload offerPayload = mock(OfferPayload.class); Offer offer = new Offer(offerPayload); - when(offerPayload.getMinAmount()).thenReturn(10000000L); - when(offerPayload.getAmount()).thenReturn(20000000L); + when(offerPayload.getMinAmount()).thenReturn(100000000000L); + when(offerPayload.getAmount()).thenReturn(200000000000L); assertEquals("0.10 - 0.20", DisplayUtils.formatAmount(offer, formatter)); } @@ -111,8 +110,8 @@ public class DisplayUtilsTest { public void testFormatAmountWithAlignmenWithDecimals() { OfferPayload offerPayload = mock(OfferPayload.class); Offer offer = new Offer(offerPayload); - when(offerPayload.getMinAmount()).thenReturn(10000000L); - when(offerPayload.getAmount()).thenReturn(20000000L); + when(offerPayload.getMinAmount()).thenReturn(100000000000L); + when(offerPayload.getAmount()).thenReturn(200000000000L); assertEquals("0.1000 - 0.2000", DisplayUtils.formatAmount(offer, 4, true, 15, formatter)); } @@ -121,8 +120,8 @@ public class DisplayUtilsTest { public void testFormatAmountWithAlignmenWithDecimalsNoRange() { OfferPayload offerPayload = mock(OfferPayload.class); Offer offer = new Offer(offerPayload); - when(offerPayload.getMinAmount()).thenReturn(10000000L); - when(offerPayload.getAmount()).thenReturn(10000000L); + when(offerPayload.getMinAmount()).thenReturn(100000000000L); + when(offerPayload.getAmount()).thenReturn(100000000000L); assertEquals("0.1000", DisplayUtils.formatAmount(offer, 4, true, 15, formatter)); } diff --git a/desktop/src/test/java/bisq/desktop/util/GUIUtilTest.java b/desktop/src/test/java/bisq/desktop/util/GUIUtilTest.java index 9b9a8a3c..4ddc370a 100644 --- a/desktop/src/test/java/bisq/desktop/util/GUIUtilTest.java +++ b/desktop/src/test/java/bisq/desktop/util/GUIUtilTest.java @@ -20,17 +20,14 @@ package bisq.desktop.util; import bisq.core.locale.GlobalSettings; import bisq.core.locale.Res; import bisq.core.locale.TradeCurrency; -import bisq.core.monetary.Price; -import bisq.core.provider.price.MarketPrice; -import bisq.core.provider.price.PriceFeedService; +import bisq.core.trade.HavenoUtils; import bisq.core.user.DontShowAgainLookup; import bisq.core.user.Preferences; -import org.bitcoinj.core.Coin; -import org.bitcoinj.core.CoinMaker; import javafx.util.StringConverter; +import java.math.BigInteger; import java.util.HashMap; import java.util.Locale; import java.util.Map; @@ -40,11 +37,6 @@ import org.junit.Test; import static bisq.desktop.maker.TradeCurrencyMakers.monero; import static bisq.desktop.maker.TradeCurrencyMakers.euro; -import static com.natpryce.makeiteasy.MakeItEasy.a; -import static com.natpryce.makeiteasy.MakeItEasy.make; -import static com.natpryce.makeiteasy.MakeItEasy.with; -import static org.bitcoinj.core.CoinMaker.oneBitcoin; -import static org.bitcoinj.core.CoinMaker.satoshis; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -116,28 +108,28 @@ public class GUIUtilTest { @Test public void percentageOfTradeAmount_higherFeeAsMin() { - Coin fee = make(a(CoinMaker.Coin).but(with(satoshis, 20000L))); - Coin min = make(a(CoinMaker.Coin).but(with(satoshis, 10000L))); + BigInteger fee = BigInteger.valueOf(200000000L); + BigInteger min = BigInteger.valueOf(100000000L); - assertEquals(" (0.02% of trade amount)", GUIUtil.getPercentageOfTradeAmount(fee, oneBitcoin, min)); + assertEquals(" (0.02% of trade amount)", GUIUtil.getPercentageOfTradeAmount(fee, HavenoUtils.xmrToAtomicUnits(1.0), min)); } @Test public void percentageOfTradeAmount_minFee() { - Coin fee = make(a(CoinMaker.Coin).but(with(satoshis, 10000L))); - Coin min = make(a(CoinMaker.Coin).but(with(satoshis, 10000L))); + BigInteger fee = BigInteger.valueOf(100000000L); + BigInteger min = BigInteger.valueOf(100000000L); assertEquals(" (required minimum)", - GUIUtil.getPercentageOfTradeAmount(fee, oneBitcoin, min)); + GUIUtil.getPercentageOfTradeAmount(fee, HavenoUtils.xmrToAtomicUnits(1.0), min)); } @Test public void percentageOfTradeAmount_minFeeZERO() { - Coin fee = make(a(CoinMaker.Coin).but(with(satoshis, 10000L))); + BigInteger fee = BigInteger.valueOf(100000000L); assertEquals(" (0.01% of trade amount)", - GUIUtil.getPercentageOfTradeAmount(fee, oneBitcoin, Coin.ZERO)); + GUIUtil.getPercentageOfTradeAmount(fee, HavenoUtils.xmrToAtomicUnits(1.0), BigInteger.valueOf(0))); } } diff --git a/desktop/src/test/java/bisq/desktop/util/validation/BtcValidatorTest.java b/desktop/src/test/java/bisq/desktop/util/validation/XmrValidatorTest.java similarity index 80% rename from desktop/src/test/java/bisq/desktop/util/validation/BtcValidatorTest.java rename to desktop/src/test/java/bisq/desktop/util/validation/XmrValidatorTest.java index a768ff72..07d6c41f 100644 --- a/desktop/src/test/java/bisq/desktop/util/validation/BtcValidatorTest.java +++ b/desktop/src/test/java/bisq/desktop/util/validation/XmrValidatorTest.java @@ -19,14 +19,10 @@ package bisq.desktop.util.validation; import bisq.common.config.BaseCurrencyNetwork; import bisq.common.config.Config; - import bisq.core.locale.CurrencyUtil; import bisq.core.locale.Res; -import bisq.core.payment.validation.BtcValidator; -import bisq.core.util.coin.CoinFormatter; -import bisq.core.util.coin.ImmutableCoinFormatter; - -import org.bitcoinj.core.Coin; +import bisq.core.payment.validation.XmrValidator; +import bisq.core.trade.HavenoUtils; import org.junit.Before; import org.junit.Test; @@ -34,9 +30,7 @@ import org.junit.Test; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -public class BtcValidatorTest { - - private final CoinFormatter coinFormatter = new ImmutableCoinFormatter(Config.baseCurrencyNetworkParameters().getMonetaryFormat()); +public class XmrValidatorTest { @Before public void setup() { @@ -49,7 +43,7 @@ public class BtcValidatorTest { @Test public void testIsValid() { - BtcValidator validator = new BtcValidator(coinFormatter); + XmrValidator validator = new XmrValidator(); assertTrue(validator.validate("1").isValid); assertTrue(validator.validate("0,1").isValid); @@ -57,7 +51,9 @@ public class BtcValidatorTest { assertTrue(validator.validate(",1").isValid); assertTrue(validator.validate(".1").isValid); assertTrue(validator.validate("0.12345678").isValid); - assertFalse(validator.validate(Coin.SATOSHI.toPlainString()).isValid); // below dust + assertTrue(validator.validate("0.0000001").isValid); + validator.setMinValue(HavenoUtils.xmrToAtomicUnits(0.0001)); + assertFalse(validator.validate("0.0000001").isValid); // below minimum assertFalse(validator.validate(null).isValid); assertFalse(validator.validate("").isValid); @@ -67,9 +63,8 @@ public class BtcValidatorTest { assertFalse(validator.validate("0.1.1").isValid); assertFalse(validator.validate("0,000.1").isValid); assertFalse(validator.validate("0.000,1").isValid); - assertFalse(validator.validate("0.123456789").isValid); + assertFalse(validator.validate("0.123456789123456").isValid); assertFalse(validator.validate("-1").isValid); // assertFalse(validator.validate(NetworkParameters.MAX_MONEY.toPlainString()).isValid); } - } diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index 6651f772..e0f52a10 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -518,11 +518,11 @@ message OfferInfo { string price = 3; bool use_market_based_price = 4; double market_price_margin_pct = 5; - uint64 amount = 6; - uint64 min_amount = 7; + uint64 amount = 6 [jstype = JS_STRING]; + uint64 min_amount = 7 [jstype = JS_STRING]; string volume = 8; string min_volume = 9; - uint64 buyer_security_deposit = 10; + uint64 buyer_security_deposit = 10 [jstype = JS_STRING]; string trigger_price = 11; string payment_account_id = 12; string payment_method_id = 13; @@ -531,10 +531,10 @@ message OfferInfo { string counter_currency_code = 16; uint64 date = 17; string state = 18; - uint64 seller_security_deposit = 19; + uint64 seller_security_deposit = 19 [jstype = JS_STRING]; string offer_fee_payment_tx_id = 20; - uint64 tx_fee = 21; - uint64 maker_fee = 22; + uint64 tx_fee = 21 [jstype = JS_STRING]; + uint64 maker_fee = 22 [jstype = JS_STRING]; bool is_activated = 23; bool is_my_offer = 24; string owner_node_address = 25; @@ -828,12 +828,12 @@ message TradeInfo { string short_id = 3; uint64 date = 4; string role = 5; - uint64 taker_fee_as_long = 6; + uint64 taker_fee_as_long = 6 [jstype = JS_STRING]; string taker_fee_tx_id = 7; string payout_tx_id = 8; - uint64 amount_as_long = 9; - uint64 buyer_security_deposit = 10; - uint64 seller_security_deposit = 11; + uint64 amount_as_long = 9 [jstype = JS_STRING]; + uint64 buyer_security_deposit = 10 [jstype = JS_STRING]; + uint64 seller_security_deposit = 11 [jstype = JS_STRING]; string price = 12; string arbitrator_node_address = 13; string trade_peer_node_address = 14;