get updated balances from Balances.java

This commit is contained in:
woodser 2024-03-14 14:35:30 -04:00
parent 82eb081089
commit 8d7bb250c5
5 changed files with 101 additions and 102 deletions

View file

@ -22,7 +22,6 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@ -41,10 +40,10 @@ public class ThreadUtils {
* @param command the command to execute
* @param threadId the thread id
*/
public static void execute(Runnable command, String threadId) {
public static Future<?> execute(Runnable command, String threadId) {
synchronized (EXECUTORS) {
if (!EXECUTORS.containsKey(threadId)) EXECUTORS.put(threadId, Executors.newFixedThreadPool(1));
EXECUTORS.get(threadId).execute(() -> {
return EXECUTORS.get(threadId).submit(() -> {
synchronized (THREADS) {
THREADS.put(threadId, Thread.currentThread());
}
@ -60,24 +59,10 @@ public class ThreadUtils {
* @param threadId the thread id
*/
public static void await(Runnable command, String threadId) {
if (isCurrentThread(Thread.currentThread(), threadId)) {
command.run();
} else {
CountDownLatch latch = new CountDownLatch(1);
execute(() -> {
try {
command.run();
} catch (Exception e) {
throw e;
} finally {
latch.countDown();
}
}, threadId);
try {
latch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
try {
execute(command, threadId).get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

View file

@ -133,7 +133,6 @@ class CoreWalletsService {
verifyWalletCurrencyCodeIsValid(currencyCode);
verifyWalletsAreAvailable();
verifyEncryptedWalletIsUnlocked();
if (balances.getAvailableBalance().get() == null) throw new IllegalStateException("balance is not yet available");
switch (currencyCode.trim().toUpperCase()) {
case "":
@ -418,28 +417,8 @@ class CoreWalletsService {
private XmrBalanceInfo getXmrBalances() {
verifyWalletsAreAvailable();
verifyEncryptedWalletIsUnlocked();
var availableBalance = balances.getAvailableBalance().get();
if (availableBalance == null)
throw new IllegalStateException("available balance is not yet available");
var pendingBalance = balances.getPendingBalance().get();
if (pendingBalance == null)
throw new IllegalStateException("locked balance is not yet available");
var reservedOfferBalance = balances.getReservedOfferBalance().get();
if (reservedOfferBalance == null)
throw new IllegalStateException("reserved offer balance is not yet available");
var reservedTradeBalance = balances.getReservedTradeBalance().get();
if (reservedTradeBalance == null)
throw new IllegalStateException("reserved trade balance is not yet available");
return new XmrBalanceInfo(availableBalance.longValue() + pendingBalance.longValue(),
availableBalance.longValue(),
pendingBalance.longValue(),
reservedOfferBalance.longValue(),
reservedTradeBalance.longValue());
if (balances.getAvailableBalance() == null) throw new IllegalStateException("Balances are not yet available");
return balances.getBalances();
}
// Returns a Coin for the transfer amount string, or a RuntimeException if invalid.

View file

@ -1,10 +1,10 @@
package haveno.core.api.model;
import java.math.BigInteger;
import com.google.common.annotations.VisibleForTesting;
import haveno.common.Payload;
import lombok.Getter;
@Getter
public class XmrBalanceInfo implements Payload {
public static final XmrBalanceInfo EMPTY = new XmrBalanceInfo(-1,
@ -19,17 +19,19 @@ public class XmrBalanceInfo implements Payload {
private final long pendingBalance;
private final long reservedOfferBalance;
private final long reservedTradeBalance;
private final long reservedBalance;
public XmrBalanceInfo(long balance,
long unlockedBalance,
long lockedBalance,
long pendingBalance,
long reservedOfferBalance,
long reservedTradeBalance) {
this.balance = balance;
this.availableBalance = unlockedBalance;
this.pendingBalance = lockedBalance;
this.pendingBalance = pendingBalance;
this.reservedOfferBalance = reservedOfferBalance;
this.reservedTradeBalance = reservedTradeBalance;
this.reservedBalance = reservedOfferBalance + reservedTradeBalance;
}
@VisibleForTesting
@ -45,6 +47,30 @@ public class XmrBalanceInfo implements Payload {
reservedTradeBalance);
}
public BigInteger getBalance() {
return BigInteger.valueOf(balance);
}
public BigInteger getAvailableBalance() {
return BigInteger.valueOf(availableBalance);
}
public BigInteger getPendingBalance() {
return BigInteger.valueOf(pendingBalance);
}
public BigInteger getReservedOfferBalance() {
return BigInteger.valueOf(reservedOfferBalance);
}
public BigInteger getReservedTradeBalance() {
return BigInteger.valueOf(reservedTradeBalance);
}
public BigInteger getReservedBalance() {
return BigInteger.valueOf(reservedBalance);
}
///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -19,6 +19,7 @@ package haveno.core.presentation;
import com.google.inject.Inject;
import haveno.common.UserThread;
import haveno.core.api.model.XmrBalanceInfo;
import haveno.core.trade.HavenoUtils;
import haveno.core.xmr.Balances;
import javafx.beans.property.SimpleStringProperty;
@ -38,14 +39,13 @@ public class BalancePresentation {
@Inject
public BalancePresentation(Balances balances) {
balances.getAvailableBalance().addListener((observable, oldValue, newValue) -> {
UserThread.execute(() -> availableBalance.set(HavenoUtils.formatXmr(newValue, true)));
});
balances.getPendingBalance().addListener((observable, oldValue, newValue) -> {
UserThread.execute(() -> pendingBalance.set(HavenoUtils.formatXmr(newValue, true)));
});
balances.getReservedBalance().addListener((observable, oldValue, newValue) -> {
UserThread.execute(() -> reservedBalance.set(HavenoUtils.formatXmr(newValue, true)));
balances.getUpdateCounter().addListener((observable, oldValue, newValue) -> {
XmrBalanceInfo info = balances.getBalances();
UserThread.execute(() -> {
availableBalance.set(HavenoUtils.formatXmr(info.getAvailableBalance(), true));
pendingBalance.set(HavenoUtils.formatXmr(info.getPendingBalance(), true));
reservedBalance.set(HavenoUtils.formatXmr(info.getReservedBalance(), true));
});
});
}
}

View file

@ -37,6 +37,7 @@ package haveno.core.xmr;
import com.google.inject.Inject;
import haveno.common.ThreadUtils;
import haveno.common.UserThread;
import haveno.core.api.model.XmrBalanceInfo;
import haveno.core.offer.OpenOffer;
import haveno.core.offer.OpenOfferManager;
import haveno.core.support.dispute.Dispute;
@ -51,8 +52,8 @@ import haveno.core.xmr.wallet.XmrWalletService;
import java.math.BigInteger;
import java.util.List;
import java.util.stream.Collectors;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.ListChangeListener;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@ -67,15 +68,18 @@ public class Balances {
private final RefundManager refundManager;
@Getter
private final ObjectProperty<BigInteger> availableBalance = new SimpleObjectProperty<>();
private BigInteger availableBalance;
@Getter
private final ObjectProperty<BigInteger> pendingBalance = new SimpleObjectProperty<>();
private BigInteger pendingBalance;
@Getter
private final ObjectProperty<BigInteger> reservedOfferBalance = new SimpleObjectProperty<>();
private BigInteger reservedOfferBalance;
@Getter
private final ObjectProperty<BigInteger> reservedTradeBalance = new SimpleObjectProperty<>();
private BigInteger reservedTradeBalance;
@Getter
private final ObjectProperty<BigInteger> reservedBalance = new SimpleObjectProperty<>(); // TODO (woodser): this balance is sum of reserved funds for offers and trade multisigs; remove?
private BigInteger reservedBalance; // TODO (woodser): this balance is sum of reserved funds for offers and trade multisigs; remove?
@Getter
private final IntegerProperty updateCounter = new SimpleIntegerProperty(0);
@Inject
public Balances(TradeManager tradeManager,
@ -103,52 +107,57 @@ public class Balances {
updateBalances();
}
public XmrBalanceInfo getBalances() {
synchronized (this) {
return new XmrBalanceInfo(availableBalance.longValue() + pendingBalance.longValue(),
availableBalance.longValue(),
pendingBalance.longValue(),
reservedOfferBalance.longValue(),
reservedTradeBalance.longValue());
}
}
private void updateBalances() {
ThreadUtils.submitToPool(() -> doUpdateBalances());
}
private void doUpdateBalances() {
synchronized (this) {
// get wallet balances
BigInteger balance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getBalance();
availableBalance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getAvailableBalance();
// get wallet balances
BigInteger balance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getWallet().getBalance(0);
BigInteger unlockedBalance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getWallet().getUnlockedBalance(0);
// calculate pending balance by adding frozen trade balances - reserved amounts
pendingBalance = balance.subtract(availableBalance);
List<Trade> trades = tradeManager.getTradesStreamWithFundsLockedIn().collect(Collectors.toList());
for (Trade trade : trades) {
if (trade.getFrozenAmount().equals(new BigInteger("0"))) continue;
BigInteger tradeFee = trade instanceof MakerTrade ? trade.getMakerFee() : trade.getTakerFee();
pendingBalance = pendingBalance.add(trade.getFrozenAmount()).subtract(trade.getReservedAmount()).subtract(tradeFee).subtract(trade.getSelf().getDepositTxFee());
}
// calculate pending balance by adding frozen trade balances - reserved amounts
BigInteger pendingBalance = balance.subtract(unlockedBalance);
List<Trade> trades = tradeManager.getTradesStreamWithFundsLockedIn().collect(Collectors.toList());
for (Trade trade : trades) {
if (trade.getFrozenAmount().equals(new BigInteger("0"))) continue;
BigInteger tradeFee = trade instanceof MakerTrade ? trade.getMakerFee() : trade.getTakerFee();
pendingBalance = pendingBalance.add(trade.getFrozenAmount()).subtract(trade.getReservedAmount()).subtract(tradeFee).subtract(trade.getSelf().getDepositTxFee());
// calculate reserved offer balance
reservedOfferBalance = BigInteger.ZERO;
if (xmrWalletService.getWallet() != null) {
List<MoneroOutputWallet> frozenOutputs = xmrWalletService.getWallet().getOutputs(new MoneroOutputQuery().setIsFrozen(true).setIsSpent(false));
for (MoneroOutputWallet frozenOutput : frozenOutputs) reservedOfferBalance = reservedOfferBalance.add(frozenOutput.getAmount());
}
for (Trade trade : trades) {
reservedOfferBalance = reservedOfferBalance.subtract(trade.getFrozenAmount()); // subtract frozen trade balances
}
// calculate reserved trade balance
reservedTradeBalance = BigInteger.ZERO;
for (Trade trade : trades) {
reservedTradeBalance = reservedTradeBalance.add(trade.getReservedAmount());
}
// calculate reserved balance
reservedBalance = reservedOfferBalance.add(reservedTradeBalance);
// notify balance update
UserThread.execute(() -> updateCounter.set(updateCounter.get() + 1));
}
// calculate reserved offer balance
BigInteger reservedOfferBalance = BigInteger.ZERO;
if (xmrWalletService.getWallet() != null) {
List<MoneroOutputWallet> frozenOutputs = xmrWalletService.getWallet().getOutputs(new MoneroOutputQuery().setIsFrozen(true).setIsSpent(false));
for (MoneroOutputWallet frozenOutput : frozenOutputs) reservedOfferBalance = reservedOfferBalance.add(frozenOutput.getAmount());
}
for (Trade trade : trades) {
reservedOfferBalance = reservedOfferBalance.subtract(trade.getFrozenAmount()); // subtract frozen trade balances
}
// calculate reserved trade balance
BigInteger reservedTradeBalance = BigInteger.ZERO;
for (Trade trade : trades) {
reservedTradeBalance = reservedTradeBalance.add(trade.getReservedAmount());
}
// set balances
setBalances(balance, unlockedBalance, pendingBalance, reservedOfferBalance, reservedTradeBalance);
}
private void setBalances(BigInteger balance, BigInteger unlockedBalance, BigInteger pendingBalance, BigInteger reservedOfferBalance, BigInteger reservedTradeBalance) {
UserThread.execute(() -> {
this.availableBalance.set(unlockedBalance);
this.pendingBalance.set(pendingBalance);
this.reservedOfferBalance.set(reservedOfferBalance);
this.reservedTradeBalance.set(reservedTradeBalance);
this.reservedBalance.set(reservedOfferBalance.add(reservedTradeBalance));
});
}
}