balances include unlocked, locked, reserved offers, reserved trades

This commit is contained in:
woodser 2021-09-10 15:41:42 -04:00
parent 58696fe633
commit 59f3fc6385
6 changed files with 73 additions and 70 deletions

View File

@ -38,6 +38,8 @@ class ColumnHeaderConstants {
static final String COL_HEADER_RESERVED_BALANCE = "Reserved Balance";
static final String COL_HEADER_TOTAL_AVAILABLE_BALANCE = "Total Available Balance";
static final String COL_HEADER_LOCKED_BALANCE = "Locked Balance";
static final String COL_HEADER_RESERVED_OFFER_BALANCE = "Reserved Offer Balance";
static final String COL_HEADER_RESERVED_TRADE_BALANCE = "Reserved Trade Balance";
static final String COL_HEADER_LOCKED_FOR_VOTING_BALANCE = "Locked For Voting Balance";
static final String COL_HEADER_LOCKUP_BONDS_BALANCE = "Lockup Bonds Balance";
static final String COL_HEADER_UNLOCKING_BONDS_BALANCE = "Unlocking Bonds Balance";

View File

@ -121,19 +121,19 @@ public class TableFormat {
public static String formatXmrBalanceInfoTbl(XmrBalanceInfo xmrBalanceInfo) {
String headerLine = COL_HEADER_BALANCE + COL_HEADER_DELIMITER
+ COL_HEADER_AVAILABLE_BALANCE + COL_HEADER_DELIMITER
+ COL_HEADER_RESERVED_BALANCE + COL_HEADER_DELIMITER
+ COL_HEADER_TOTAL_AVAILABLE_BALANCE + COL_HEADER_DELIMITER // TODO (woodser): column names are not quite right for XMR (balance, available balance, locked balance, reserved balance, total balance)
+ COL_HEADER_LOCKED_BALANCE + COL_HEADER_DELIMITER + "\n";
+ COL_HEADER_LOCKED_BALANCE + COL_HEADER_DELIMITER
+ COL_HEADER_RESERVED_OFFER_BALANCE + COL_HEADER_DELIMITER
+ COL_HEADER_RESERVED_TRADE_BALANCE + COL_HEADER_DELIMITER + "\n";
String colDataFormat = "%" + COL_HEADER_BALANCE.length() + "s" // rt justify
+ " %" + (COL_HEADER_AVAILABLE_BALANCE.length() + 1) + "s" // rt justify
+ " %" + (COL_HEADER_LOCKED_BALANCE.length() + 1) + "s" // rt justify
+ " %" + (COL_HEADER_RESERVED_BALANCE.length() + 1) + "s" // rt justify
+ " %" + (COL_HEADER_TOTAL_AVAILABLE_BALANCE.length() + 1) + "s" // rt justify
+ " %" + (COL_HEADER_LOCKED_BALANCE.length() + 1) + "s"; // rt justify
+ " %" + (COL_HEADER_TOTAL_AVAILABLE_BALANCE.length() + 1) + "s"; // rt justify
return headerLine + format(colDataFormat,
formatSatoshis(xmrBalanceInfo.getAvailableBalance()),
formatSatoshis(xmrBalanceInfo.getReservedBalance()),
formatSatoshis(xmrBalanceInfo.getTotalBalance()),
formatSatoshis(xmrBalanceInfo.getLockedBalance()));
formatSatoshis(xmrBalanceInfo.getUnlockedBalance() + xmrBalanceInfo.getLockedBalance()), // total balance
formatSatoshis(xmrBalanceInfo.getUnlockedBalance()),
formatSatoshis(xmrBalanceInfo.getReservedOfferBalance()),
formatSatoshis(xmrBalanceInfo.getReservedTradeBalance()));
}
public static String formatPaymentAcctTbl(List<PaymentAccount> paymentAccounts) {

View File

@ -636,19 +636,22 @@ class CoreWalletsService {
if (availableBalance == null)
throw new IllegalStateException("available balance is not yet available");
var reservedBalance = balances.getReservedBalance().get();
if (reservedBalance == null)
throw new IllegalStateException("reserved balance is not yet available");
var lockedBalance = balances.getLockedBalance().get();
if (lockedBalance == null)
throw new IllegalStateException("locked balance is not yet available");
return new XmrBalanceInfo(availableBalance.add(lockedBalance).value,
availableBalance.value,
lockedBalance.value,
reservedBalance.value,
availableBalance.add(lockedBalance).add(reservedBalance).value);
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(),
lockedBalance.longValue(),
reservedOfferBalance.longValue(),
reservedTradeBalance.longValue());
}
// Returns a Coin for the transfer amount string, or a RuntimeException if invalid.

View File

@ -10,42 +10,35 @@ import lombok.Getter;
public class XmrBalanceInfo implements Payload {
public static final XmrBalanceInfo EMPTY = new XmrBalanceInfo(-1,
-1,
-1,
-1,
-1);
// All balances are in XMR centineros: https://www.getmonero.org/resources/moneropedia/denominations.html
private final long balance;
private final long availableBalance;
// all balances are in atomic units
private final long unlockedBalance;
private final long lockedBalance;
private final long reservedBalance;
private final long totalBalance; // balance + reserved
private final long reservedOfferBalance;
private final long reservedTradeBalance;
public XmrBalanceInfo(long balance,
long availableBalance,
public XmrBalanceInfo(long unlockedBalance,
long lockedBalance,
long reservedBalance,
long totalBalance) {
this.balance = balance;
this.availableBalance = availableBalance;
long reservedOfferBalance,
long reservedTradeBalance) {
this.unlockedBalance = unlockedBalance;
this.lockedBalance = lockedBalance;
this.reservedBalance = reservedBalance;
this.totalBalance = totalBalance;
this.reservedOfferBalance = reservedOfferBalance;
this.reservedTradeBalance = reservedTradeBalance;
}
@VisibleForTesting
public static XmrBalanceInfo valueOf(long balance,
long availableBalance,
public static XmrBalanceInfo valueOf(long unlockedBalance,
long lockedBalance,
long reservedBalance,
long totalBalance) {
// Convenience for creating a model instance instead of a proto.
return new XmrBalanceInfo(balance,
availableBalance,
long reservedOfferBalance,
long reservedTradeBalance) {
return new XmrBalanceInfo(unlockedBalance,
lockedBalance,
reservedBalance,
totalBalance);
reservedOfferBalance,
reservedTradeBalance);
}
///////////////////////////////////////////////////////////////////////////////////////////
@ -55,30 +48,27 @@ public class XmrBalanceInfo implements Payload {
@Override
public bisq.proto.grpc.XmrBalanceInfo toProtoMessage() {
return bisq.proto.grpc.XmrBalanceInfo.newBuilder()
.setBalance(balance)
.setAvailableBalance(availableBalance)
.setUnlockedBalance(unlockedBalance)
.setLockedBalance(lockedBalance)
.setReservedBalance(reservedBalance)
.setTotalBalance(totalBalance)
.setReservedOfferBalance(reservedOfferBalance)
.setReservedTradeBalance(reservedTradeBalance)
.build();
}
public static XmrBalanceInfo fromProto(bisq.proto.grpc.XmrBalanceInfo proto) {
return new XmrBalanceInfo(proto.getBalance(),
proto.getAvailableBalance(),
return new XmrBalanceInfo(proto.getUnlockedBalance(),
proto.getLockedBalance(),
proto.getReservedBalance(),
proto.getTotalBalance());
proto.getReservedOfferBalance(),
proto.getReservedTradeBalance());
}
@Override
public String toString() {
return "BtcBalanceInfo{" +
"balance=" + balance +
", availableBalance=" + availableBalance +
"unlockedBalance=" + unlockedBalance +
", lockedBalance=" + lockedBalance +
", reservedBalance=" + reservedBalance +
", totalBalance=" + totalBalance +
", reservedOfferBalance=" + reservedOfferBalance +
", reservedTradeBalance=" + reservedTradeBalance +
'}';
}
}

View File

@ -56,9 +56,13 @@ public class Balances {
@Getter
private final ObjectProperty<Coin> availableBalance = new SimpleObjectProperty<>();
@Getter
private final ObjectProperty<Coin> reservedBalance = new SimpleObjectProperty<>();
@Getter
private final ObjectProperty<Coin> lockedBalance = new SimpleObjectProperty<>();
@Getter
private final ObjectProperty<Coin> reservedOfferBalance = new SimpleObjectProperty<>();
@Getter
private final ObjectProperty<Coin> reservedTradeBalance = new SimpleObjectProperty<>();
@Getter
private final ObjectProperty<Coin> reservedBalance = new SimpleObjectProperty<>(); // TODO (woodser): this balance is sum of reserved funds for offers and trade multisigs; remove?
@Inject
public Balances(TradeManager tradeManager,
@ -92,6 +96,8 @@ public class Balances {
UserThread.execute(() -> {
updateAvailableBalance();
updateLockedBalance();
updateReservedOfferBalance();
updateReservedTradeBalance();
updateReservedBalance();
});
}
@ -108,14 +114,15 @@ public class Balances {
lockedBalance.set(Coin.valueOf(balance.subtract(unlockedBalance).longValueExact()));
}
private void updateReservedBalance() {
// add frozen input amounts
private void updateReservedOfferBalance() {
Coin sum = Coin.valueOf(0);
List<MoneroOutputWallet> frozenOutputs = xmrWalletService.getWallet().getOutputs(new MoneroOutputQuery().setIsFrozen(true).setIsSpent(false));
for (MoneroOutputWallet frozenOutput : frozenOutputs) sum = sum.add(Coin.valueOf(frozenOutput.getAmount().longValueExact()));
reservedOfferBalance.set(sum);
}
// add multisig deposit amounts
private void updateReservedTradeBalance() {
Coin sum = Coin.valueOf(0);
List<Trade> openTrades = tradeManager.getTradesStreamWithFundsLockedIn().collect(Collectors.toList());
for (Trade trade : openTrades) {
if (trade.getContract() == null) continue;
@ -128,8 +135,10 @@ public class Balances {
}
sum = sum.add(Coin.valueOf(ParsingUtils.centinerosToAtomicUnits(reservedAmt).longValueExact()));
}
reservedTradeBalance.set(sum);
}
// set reserved balance
reservedBalance.set(sum);
private void updateReservedBalance() {
reservedBalance.set(reservedOfferBalance.get().add(reservedTradeBalance.get()));
}
}

View File

@ -606,11 +606,10 @@ message BtcBalanceInfo {
}
message XmrBalanceInfo {
uint64 balance = 1;
uint64 availableBalance = 2;
uint64 lockedBalance = 3;
uint64 reservedBalance = 4;
uint64 totalBalance = 5; // balance + reserved
uint64 unlockedBalance = 1;
uint64 lockedBalance = 2;
uint64 reservedOfferBalance = 3;
uint64 reservedTradeBalance = 4;
}
message AddressBalanceInfo {