mirror of
https://github.com/haveno-dex/haveno.git
synced 2024-12-22 19:49:32 +00:00
get updated balances from Balances.java
This commit is contained in:
parent
82eb081089
commit
8d7bb250c5
5 changed files with 101 additions and 102 deletions
|
@ -22,7 +22,6 @@ import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
@ -41,10 +40,10 @@ public class ThreadUtils {
|
||||||
* @param command the command to execute
|
* @param command the command to execute
|
||||||
* @param threadId the thread id
|
* @param threadId the thread id
|
||||||
*/
|
*/
|
||||||
public static void execute(Runnable command, String threadId) {
|
public static Future<?> execute(Runnable command, String threadId) {
|
||||||
synchronized (EXECUTORS) {
|
synchronized (EXECUTORS) {
|
||||||
if (!EXECUTORS.containsKey(threadId)) EXECUTORS.put(threadId, Executors.newFixedThreadPool(1));
|
if (!EXECUTORS.containsKey(threadId)) EXECUTORS.put(threadId, Executors.newFixedThreadPool(1));
|
||||||
EXECUTORS.get(threadId).execute(() -> {
|
return EXECUTORS.get(threadId).submit(() -> {
|
||||||
synchronized (THREADS) {
|
synchronized (THREADS) {
|
||||||
THREADS.put(threadId, Thread.currentThread());
|
THREADS.put(threadId, Thread.currentThread());
|
||||||
}
|
}
|
||||||
|
@ -60,24 +59,10 @@ public class ThreadUtils {
|
||||||
* @param threadId the thread id
|
* @param threadId the thread id
|
||||||
*/
|
*/
|
||||||
public static void await(Runnable command, String threadId) {
|
public static void await(Runnable command, String threadId) {
|
||||||
if (isCurrentThread(Thread.currentThread(), threadId)) {
|
try {
|
||||||
command.run();
|
execute(command, threadId).get();
|
||||||
} else {
|
} catch (Exception e) {
|
||||||
CountDownLatch latch = new CountDownLatch(1);
|
throw new RuntimeException(e);
|
||||||
execute(() -> {
|
|
||||||
try {
|
|
||||||
command.run();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw e;
|
|
||||||
} finally {
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
}, threadId);
|
|
||||||
try {
|
|
||||||
latch.await();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,6 @@ class CoreWalletsService {
|
||||||
verifyWalletCurrencyCodeIsValid(currencyCode);
|
verifyWalletCurrencyCodeIsValid(currencyCode);
|
||||||
verifyWalletsAreAvailable();
|
verifyWalletsAreAvailable();
|
||||||
verifyEncryptedWalletIsUnlocked();
|
verifyEncryptedWalletIsUnlocked();
|
||||||
if (balances.getAvailableBalance().get() == null) throw new IllegalStateException("balance is not yet available");
|
|
||||||
|
|
||||||
switch (currencyCode.trim().toUpperCase()) {
|
switch (currencyCode.trim().toUpperCase()) {
|
||||||
case "":
|
case "":
|
||||||
|
@ -418,28 +417,8 @@ class CoreWalletsService {
|
||||||
private XmrBalanceInfo getXmrBalances() {
|
private XmrBalanceInfo getXmrBalances() {
|
||||||
verifyWalletsAreAvailable();
|
verifyWalletsAreAvailable();
|
||||||
verifyEncryptedWalletIsUnlocked();
|
verifyEncryptedWalletIsUnlocked();
|
||||||
|
if (balances.getAvailableBalance() == null) throw new IllegalStateException("Balances are not yet available");
|
||||||
var availableBalance = balances.getAvailableBalance().get();
|
return balances.getBalances();
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a Coin for the transfer amount string, or a RuntimeException if invalid.
|
// Returns a Coin for the transfer amount string, or a RuntimeException if invalid.
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package haveno.core.api.model;
|
package haveno.core.api.model;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import haveno.common.Payload;
|
import haveno.common.Payload;
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
public class XmrBalanceInfo implements Payload {
|
public class XmrBalanceInfo implements Payload {
|
||||||
|
|
||||||
public static final XmrBalanceInfo EMPTY = new XmrBalanceInfo(-1,
|
public static final XmrBalanceInfo EMPTY = new XmrBalanceInfo(-1,
|
||||||
|
@ -19,17 +19,19 @@ public class XmrBalanceInfo implements Payload {
|
||||||
private final long pendingBalance;
|
private final long pendingBalance;
|
||||||
private final long reservedOfferBalance;
|
private final long reservedOfferBalance;
|
||||||
private final long reservedTradeBalance;
|
private final long reservedTradeBalance;
|
||||||
|
private final long reservedBalance;
|
||||||
|
|
||||||
public XmrBalanceInfo(long balance,
|
public XmrBalanceInfo(long balance,
|
||||||
long unlockedBalance,
|
long unlockedBalance,
|
||||||
long lockedBalance,
|
long pendingBalance,
|
||||||
long reservedOfferBalance,
|
long reservedOfferBalance,
|
||||||
long reservedTradeBalance) {
|
long reservedTradeBalance) {
|
||||||
this.balance = balance;
|
this.balance = balance;
|
||||||
this.availableBalance = unlockedBalance;
|
this.availableBalance = unlockedBalance;
|
||||||
this.pendingBalance = lockedBalance;
|
this.pendingBalance = pendingBalance;
|
||||||
this.reservedOfferBalance = reservedOfferBalance;
|
this.reservedOfferBalance = reservedOfferBalance;
|
||||||
this.reservedTradeBalance = reservedTradeBalance;
|
this.reservedTradeBalance = reservedTradeBalance;
|
||||||
|
this.reservedBalance = reservedOfferBalance + reservedTradeBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
@ -45,6 +47,30 @@ public class XmrBalanceInfo implements Payload {
|
||||||
reservedTradeBalance);
|
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
|
// PROTO BUFFER
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -19,6 +19,7 @@ package haveno.core.presentation;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import haveno.common.UserThread;
|
import haveno.common.UserThread;
|
||||||
|
import haveno.core.api.model.XmrBalanceInfo;
|
||||||
import haveno.core.trade.HavenoUtils;
|
import haveno.core.trade.HavenoUtils;
|
||||||
import haveno.core.xmr.Balances;
|
import haveno.core.xmr.Balances;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
@ -38,14 +39,13 @@ public class BalancePresentation {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public BalancePresentation(Balances balances) {
|
public BalancePresentation(Balances balances) {
|
||||||
balances.getAvailableBalance().addListener((observable, oldValue, newValue) -> {
|
balances.getUpdateCounter().addListener((observable, oldValue, newValue) -> {
|
||||||
UserThread.execute(() -> availableBalance.set(HavenoUtils.formatXmr(newValue, true)));
|
XmrBalanceInfo info = balances.getBalances();
|
||||||
});
|
UserThread.execute(() -> {
|
||||||
balances.getPendingBalance().addListener((observable, oldValue, newValue) -> {
|
availableBalance.set(HavenoUtils.formatXmr(info.getAvailableBalance(), true));
|
||||||
UserThread.execute(() -> pendingBalance.set(HavenoUtils.formatXmr(newValue, true)));
|
pendingBalance.set(HavenoUtils.formatXmr(info.getPendingBalance(), true));
|
||||||
});
|
reservedBalance.set(HavenoUtils.formatXmr(info.getReservedBalance(), true));
|
||||||
balances.getReservedBalance().addListener((observable, oldValue, newValue) -> {
|
});
|
||||||
UserThread.execute(() -> reservedBalance.set(HavenoUtils.formatXmr(newValue, true)));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ package haveno.core.xmr;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import haveno.common.ThreadUtils;
|
import haveno.common.ThreadUtils;
|
||||||
import haveno.common.UserThread;
|
import haveno.common.UserThread;
|
||||||
|
import haveno.core.api.model.XmrBalanceInfo;
|
||||||
import haveno.core.offer.OpenOffer;
|
import haveno.core.offer.OpenOffer;
|
||||||
import haveno.core.offer.OpenOfferManager;
|
import haveno.core.offer.OpenOfferManager;
|
||||||
import haveno.core.support.dispute.Dispute;
|
import haveno.core.support.dispute.Dispute;
|
||||||
|
@ -51,8 +52,8 @@ import haveno.core.xmr.wallet.XmrWalletService;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.IntegerProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleIntegerProperty;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
@ -67,15 +68,18 @@ public class Balances {
|
||||||
private final RefundManager refundManager;
|
private final RefundManager refundManager;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final ObjectProperty<BigInteger> availableBalance = new SimpleObjectProperty<>();
|
private BigInteger availableBalance;
|
||||||
@Getter
|
@Getter
|
||||||
private final ObjectProperty<BigInteger> pendingBalance = new SimpleObjectProperty<>();
|
private BigInteger pendingBalance;
|
||||||
@Getter
|
@Getter
|
||||||
private final ObjectProperty<BigInteger> reservedOfferBalance = new SimpleObjectProperty<>();
|
private BigInteger reservedOfferBalance;
|
||||||
@Getter
|
@Getter
|
||||||
private final ObjectProperty<BigInteger> reservedTradeBalance = new SimpleObjectProperty<>();
|
private BigInteger reservedTradeBalance;
|
||||||
@Getter
|
@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
|
@Inject
|
||||||
public Balances(TradeManager tradeManager,
|
public Balances(TradeManager tradeManager,
|
||||||
|
@ -103,52 +107,57 @@ public class Balances {
|
||||||
updateBalances();
|
updateBalances();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public XmrBalanceInfo getBalances() {
|
||||||
|
synchronized (this) {
|
||||||
|
return new XmrBalanceInfo(availableBalance.longValue() + pendingBalance.longValue(),
|
||||||
|
availableBalance.longValue(),
|
||||||
|
pendingBalance.longValue(),
|
||||||
|
reservedOfferBalance.longValue(),
|
||||||
|
reservedTradeBalance.longValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateBalances() {
|
private void updateBalances() {
|
||||||
ThreadUtils.submitToPool(() -> doUpdateBalances());
|
ThreadUtils.submitToPool(() -> doUpdateBalances());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void 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
|
// calculate pending balance by adding frozen trade balances - reserved amounts
|
||||||
BigInteger balance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getWallet().getBalance(0);
|
pendingBalance = balance.subtract(availableBalance);
|
||||||
BigInteger unlockedBalance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getWallet().getUnlockedBalance(0);
|
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
|
// calculate reserved offer balance
|
||||||
BigInteger pendingBalance = balance.subtract(unlockedBalance);
|
reservedOfferBalance = BigInteger.ZERO;
|
||||||
List<Trade> trades = tradeManager.getTradesStreamWithFundsLockedIn().collect(Collectors.toList());
|
if (xmrWalletService.getWallet() != null) {
|
||||||
for (Trade trade : trades) {
|
List<MoneroOutputWallet> frozenOutputs = xmrWalletService.getWallet().getOutputs(new MoneroOutputQuery().setIsFrozen(true).setIsSpent(false));
|
||||||
if (trade.getFrozenAmount().equals(new BigInteger("0"))) continue;
|
for (MoneroOutputWallet frozenOutput : frozenOutputs) reservedOfferBalance = reservedOfferBalance.add(frozenOutput.getAmount());
|
||||||
BigInteger tradeFee = trade instanceof MakerTrade ? trade.getMakerFee() : trade.getTakerFee();
|
}
|
||||||
pendingBalance = pendingBalance.add(trade.getFrozenAmount()).subtract(trade.getReservedAmount()).subtract(tradeFee).subtract(trade.getSelf().getDepositTxFee());
|
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));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue