From 2d4455b1a29ee02229f054973b4449a97377ed58 Mon Sep 17 00:00:00 2001
From: woodser <woodser@protonmail.com>
Date: Fri, 17 Jan 2025 16:09:12 -0500
Subject: [PATCH] update atomic unit conversion utils to use monero-java

---
 .../java/haveno/core/trade/HavenoUtils.java   |  9 ++++----
 .../core/xmr/wallet/XmrWalletService.java     | 21 +++++++++++++++++--
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/core/src/main/java/haveno/core/trade/HavenoUtils.java b/core/src/main/java/haveno/core/trade/HavenoUtils.java
index fcd5c556e1..d238d78843 100644
--- a/core/src/main/java/haveno/core/trade/HavenoUtils.java
+++ b/core/src/main/java/haveno/core/trade/HavenoUtils.java
@@ -71,6 +71,7 @@ import javax.sound.sampled.SourceDataLine;
 
 import lombok.extern.slf4j.Slf4j;
 import monero.common.MoneroRpcConnection;
+import monero.common.MoneroUtils;
 import monero.daemon.model.MoneroOutput;
 import monero.wallet.model.MoneroDestination;
 import monero.wallet.model.MoneroTxWallet;
@@ -204,11 +205,11 @@ public class HavenoUtils {
     }
 
     public static double atomicUnitsToXmr(BigInteger atomicUnits) {
-        return new BigDecimal(atomicUnits).divide(new BigDecimal(XMR_AU_MULTIPLIER)).doubleValue();
+        return MoneroUtils.atomicUnitsToXmr(atomicUnits);
     }
 
     public static BigInteger xmrToAtomicUnits(double xmr) {
-        return new BigDecimal(xmr).multiply(new BigDecimal(XMR_AU_MULTIPLIER)).toBigInteger();
+        return MoneroUtils.xmrToAtomicUnits(xmr);
     }
 
     public static long xmrToCentineros(double xmr) {
@@ -220,11 +221,11 @@ public class HavenoUtils {
     }
 
     public static double divide(BigInteger auDividend, BigInteger auDivisor) {
-        return atomicUnitsToXmr(auDividend) / atomicUnitsToXmr(auDivisor);
+        return MoneroUtils.divide(auDividend, auDivisor);
     }
 
     public static BigInteger multiply(BigInteger amount1, double amount2) {
-        return amount1 == null ? null : new BigDecimal(amount1).multiply(BigDecimal.valueOf(amount2)).toBigInteger();
+        return MoneroUtils.multiply(amount1, amount2);
     }
 
     // ------------------------- FORMAT UTILS ---------------------------------
diff --git a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java
index 4c45907720..8432da2aed 100644
--- a/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java
+++ b/core/src/main/java/haveno/core/xmr/wallet/XmrWalletService.java
@@ -781,11 +781,23 @@ public class XmrWalletService extends XmrWalletBase {
                 BigInteger actualSendAmount = transferCheck.getReceivedAmount();
 
                 // verify trade fee amount
-                if (!actualTradeFee.equals(tradeFeeAmount)) throw new RuntimeException("Invalid trade fee amount, expected " + tradeFeeAmount + " but was " + actualTradeFee);
+                if (!actualTradeFee.equals(tradeFeeAmount)) {
+                    if (equalsWithinFractionError(actualTradeFee, tradeFeeAmount)) {
+                        log.warn("Trade tx fee amount is within fraction error, expected " + tradeFeeAmount + " but was " + actualTradeFee);
+                    } else {
+                        throw new RuntimeException("Invalid trade fee amount, expected " + tradeFeeAmount + " but was " + actualTradeFee);
+                    }
+                }
 
                 // verify send amount
                 BigInteger expectedSendAmount = sendAmount.subtract(tx.getFee());
-                if (!actualSendAmount.equals(expectedSendAmount)) throw new RuntimeException("Invalid send amount, expected " + expectedSendAmount + " but was " + actualSendAmount + " with tx fee " + tx.getFee());
+                if (!actualSendAmount.equals(expectedSendAmount)) {
+                    if (equalsWithinFractionError(actualSendAmount, expectedSendAmount)) {
+                        log.warn("Trade tx send amount is within fraction error, expected " + expectedSendAmount + " but was " + actualSendAmount + " with tx fee " + tx.getFee());
+                    } else {
+                        throw new RuntimeException("Invalid send amount, expected " + expectedSendAmount + " but was " + actualSendAmount + " with tx fee " + tx.getFee());
+                    }
+                }
                 return tx;
             } catch (Exception e) {
                 log.warn("Error verifying trade tx with offer id=" + offerId + (tx == null ? "" : ", tx=\n" + tx) + ": " + e.getMessage());
@@ -801,6 +813,11 @@ public class XmrWalletService extends XmrWalletBase {
         }
     }
 
+    // TODO: old bug in atomic unit conversion could cause fractional difference error, remove this in future release, maybe re-sign all offers then
+    private static boolean equalsWithinFractionError(BigInteger a, BigInteger b) {
+        return a.subtract(b).abs().compareTo(new BigInteger("1")) <= 0;
+    }
+
     /**
      * Get the tx fee estimate based on its weight.
      *