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;