mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 07:07:43 +01:00
Fix BSQ balance display for unconfirmed change outputs
- Add verifiedBsqBalance and unconfirmedChangeBalance - Remove totalBsqBalance - Make text for different balances more explicit
This commit is contained in:
parent
9475cf2897
commit
1802508c7c
8 changed files with 117 additions and 70 deletions
|
@ -103,7 +103,8 @@ public abstract class BisqDefaultCoinSelector implements CoinSelector {
|
|||
return Coin.valueOf(change);
|
||||
}
|
||||
|
||||
// We allow spending own pending txs and if permitForeignPendingTx is set as well foreign unconfirmed txs.
|
||||
// We allow spending from own unconfirmed txs and if permitForeignPendingTx is set as well from foreign
|
||||
// unconfirmed txs.
|
||||
protected boolean isTxSpendable(Transaction tx) {
|
||||
TransactionConfidence confidence = tx.getConfidence();
|
||||
TransactionConfidence.ConfidenceType type = confidence.getConfidenceType();
|
||||
|
|
|
@ -39,7 +39,8 @@ public class BsqCoinSelector extends BisqDefaultCoinSelector {
|
|||
|
||||
@Inject
|
||||
public BsqCoinSelector(DaoStateService daoStateService, UnconfirmedBsqChangeOutputListService unconfirmedBsqChangeOutputListService) {
|
||||
super(true);
|
||||
// permitForeignPendingTx is not relevant here as we do not support pending foreign utxos anyway.
|
||||
super(false);
|
||||
this.daoStateService = daoStateService;
|
||||
this.unconfirmedBsqChangeOutputListService = unconfirmedBsqChangeOutputListService;
|
||||
}
|
||||
|
|
|
@ -191,8 +191,10 @@ public class BsqWalletService extends WalletService implements DaoStateListener
|
|||
|
||||
@Override
|
||||
public void onParseTxsCompleteAfterBatchProcessing(Block block) {
|
||||
if (isWalletReady())
|
||||
if (isWalletReady()) {
|
||||
wallet.getTransactions(false).forEach(unconfirmedBsqChangeOutputListService::onTransactionConfidenceChanged);
|
||||
updateBsqWalletTransactions();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -249,6 +251,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener
|
|||
})
|
||||
.sum()
|
||||
);
|
||||
|
||||
Set<String> confirmedTxIdSet = getTransactions(false).stream()
|
||||
.filter(tx -> tx.getConfidence().getConfidenceType() == BUILDING)
|
||||
.map(Transaction::getHashAsString)
|
||||
|
|
|
@ -55,7 +55,10 @@ public class WalletsManager {
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public WalletsManager(BtcWalletService btcWalletService, TradeWalletService tradeWalletService, BsqWalletService bsqWalletService, WalletsSetup walletsSetup) {
|
||||
public WalletsManager(BtcWalletService btcWalletService,
|
||||
TradeWalletService tradeWalletService,
|
||||
BsqWalletService bsqWalletService,
|
||||
WalletsSetup walletsSetup) {
|
||||
this.btcWalletService = btcWalletService;
|
||||
this.tradeWalletService = tradeWalletService;
|
||||
this.bsqWalletService = bsqWalletService;
|
||||
|
|
|
@ -53,6 +53,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -68,6 +69,7 @@ public class DaoStateService implements DaoSetupService {
|
|||
private final GenesisTxInfo genesisTxInfo;
|
||||
private final BsqFormatter bsqFormatter;
|
||||
private final List<DaoStateListener> daoStateListeners = new CopyOnWriteArrayList<>();
|
||||
@Getter
|
||||
private boolean parseBlockChainComplete;
|
||||
|
||||
|
||||
|
|
|
@ -47,6 +47,11 @@ public class UnconfirmedBsqChangeOutputListService implements PersistedDataHost
|
|||
this.storage = storage;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PersistedDataHost
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void readPersisted() {
|
||||
if (DevEnv.isDaoActivated()) {
|
||||
|
|
|
@ -1228,11 +1228,13 @@ dao.tab.proofOfBurn=Asset listing fee/Proof of burn
|
|||
dao.tab.news=News
|
||||
|
||||
dao.paidWithBsq=paid with BSQ
|
||||
dao.availableBsqBalance=Available
|
||||
dao.availableNonBsqBalance=Available non-BSQ balance (BTC)
|
||||
dao.unverifiedBsqBalance=Unverified (awaiting block confirmation)
|
||||
dao.availableBsqBalance=Available for spending (verified + unconfirmed change outputs)
|
||||
dao.verifiedBsqBalance=Balance of all verified UTXOs
|
||||
dao.unconfirmedChangeBalance=Balance of all unconfirmed change outputs
|
||||
dao.unverifiedBsqBalance=Balance of all unverified transactions (awaiting block confirmation)
|
||||
dao.lockedForVoteBalance=Used for voting
|
||||
dao.lockedInBonds=Locked in bonds
|
||||
dao.availableNonBsqBalance=Available non-BSQ balance (BTC)
|
||||
dao.totalBsqBalance=Total BSQ balance
|
||||
|
||||
dao.tx.published.success=Your transaction has been successfully published.
|
||||
|
|
|
@ -17,12 +17,14 @@
|
|||
|
||||
package bisq.desktop.main.dao.wallet;
|
||||
|
||||
import bisq.desktop.components.TitledGroupBg;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
import bisq.core.btc.listeners.BsqBalanceListener;
|
||||
import bisq.core.btc.wallet.BsqWalletService;
|
||||
import bisq.core.dao.state.DaoStateListener;
|
||||
import bisq.core.dao.state.DaoStateService;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
|
||||
|
@ -42,45 +44,127 @@ import lombok.extern.slf4j.Slf4j;
|
|||
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
||||
|
||||
@Slf4j
|
||||
public class BsqBalanceUtil implements BsqBalanceListener {
|
||||
public class BsqBalanceUtil implements BsqBalanceListener, DaoStateListener {
|
||||
private final BsqWalletService bsqWalletService;
|
||||
private final DaoStateService daoStateService;
|
||||
private final BsqFormatter bsqFormatter;
|
||||
|
||||
// Displaying general BSQ info
|
||||
private TextField availableBalanceTextField, availableNonBsqBalanceTextField, unverifiedBalanceTextField, lockedForVoteBalanceTextField,
|
||||
lockedInBondsBalanceTextField, totalBalanceTextField;
|
||||
private TextField availableBalanceTextField, verifiedBalanceTextField, availableNonBsqBalanceTextField,
|
||||
unverifiedBalanceTextField, lockedForVoteBalanceTextField,
|
||||
lockedInBondsBalanceTextField, unconfirmedChangTextField;
|
||||
|
||||
// Displaying bond dashboard info
|
||||
private TextField lockupAmountTextField, unlockingAmountTextField;
|
||||
private TitledGroupBg titledGroupBg;
|
||||
private Label availableNonBsqBalanceLabel;
|
||||
|
||||
@Inject
|
||||
private BsqBalanceUtil(BsqWalletService bsqWalletService,
|
||||
DaoStateService daoStateService,
|
||||
BsqFormatter bsqFormatter) {
|
||||
this.bsqWalletService = bsqWalletService;
|
||||
this.daoStateService = daoStateService;
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
}
|
||||
|
||||
|
||||
public void activate() {
|
||||
bsqWalletService.addBsqBalanceListener(this);
|
||||
daoStateService.addBsqStateListener(this);
|
||||
triggerUpdate();
|
||||
}
|
||||
|
||||
public void deactivate() {
|
||||
bsqWalletService.removeBsqBalanceListener(this);
|
||||
daoStateService.removeBsqStateListener(this);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DaoStateListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onParseTxsCompleteAfterBatchProcessing(Block block) {
|
||||
bsqWalletService.addBsqBalanceListener(this);
|
||||
triggerUpdate();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BsqBalanceListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onUpdateBalances(Coin availableBalance,
|
||||
Coin availableNonBsqBalance,
|
||||
Coin unverifiedBalance,
|
||||
Coin unconfirmedChangeBalance,
|
||||
Coin lockedForVotingBalance,
|
||||
Coin lockupBondsBalance,
|
||||
Coin unlockingBondsBalance) {
|
||||
boolean isNonBsqBalanceAvailable = availableNonBsqBalance.value > 0;
|
||||
|
||||
availableBalanceTextField.setText(bsqFormatter.formatCoinWithCode(availableBalance));
|
||||
Coin verified = availableBalance.subtract(unconfirmedChangeBalance);
|
||||
verifiedBalanceTextField.setText(bsqFormatter.formatCoinWithCode(verified));
|
||||
unconfirmedChangTextField.setText(bsqFormatter.formatCoinWithCode(unconfirmedChangeBalance));
|
||||
unverifiedBalanceTextField.setText(bsqFormatter.formatCoinWithCode(unverifiedBalance));
|
||||
|
||||
lockedForVoteBalanceTextField.setText(bsqFormatter.formatCoinWithCode(lockedForVotingBalance));
|
||||
lockedInBondsBalanceTextField.setText(bsqFormatter.formatCoinWithCode(
|
||||
lockupBondsBalance.add(unlockingBondsBalance)));
|
||||
if (lockupAmountTextField != null && unlockingAmountTextField != null) {
|
||||
lockupAmountTextField.setText(bsqFormatter.formatCoinWithCode(lockupBondsBalance));
|
||||
unlockingAmountTextField.setText(bsqFormatter.formatCoinWithCode(unlockingBondsBalance));
|
||||
}
|
||||
|
||||
availableNonBsqBalanceLabel.setVisible(isNonBsqBalanceAvailable);
|
||||
availableNonBsqBalanceLabel.setManaged(isNonBsqBalanceAvailable);
|
||||
availableNonBsqBalanceTextField.setVisible(isNonBsqBalanceAvailable);
|
||||
availableNonBsqBalanceTextField.setManaged(isNonBsqBalanceAvailable);
|
||||
availableNonBsqBalanceTextField.setText(bsqFormatter.formatBTCWithCode(availableNonBsqBalance.value));
|
||||
}
|
||||
|
||||
|
||||
private void triggerUpdate() {
|
||||
onUpdateBalances(bsqWalletService.getAvailableConfirmedBalance(),
|
||||
bsqWalletService.getAvailableNonBsqBalance(),
|
||||
bsqWalletService.getUnverifiedBalance(),
|
||||
bsqWalletService.getUnconfirmedChangeBalance(),
|
||||
bsqWalletService.getLockedForVotingBalance(),
|
||||
bsqWalletService.getLockupBondsBalance(),
|
||||
bsqWalletService.getUnlockingBondsBalance());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public int addGroup(GridPane gridPane, int gridRow) {
|
||||
int startIndex = gridRow;
|
||||
titledGroupBg = addTitledGroupBg(gridPane, gridRow, 3, Res.get("dao.wallet.dashboard.myBalance"));
|
||||
addTitledGroupBg(gridPane, gridRow, 4, Res.get("dao.wallet.dashboard.myBalance"));
|
||||
availableBalanceTextField = FormBuilder.addTopLabelReadOnlyTextField(gridPane, gridRow,
|
||||
Res.get("dao.availableBsqBalance"), Layout.FIRST_ROW_DISTANCE).second;
|
||||
verifiedBalanceTextField = FormBuilder.addTopLabelReadOnlyTextField(gridPane, ++gridRow,
|
||||
Res.get("dao.verifiedBsqBalance")).second;
|
||||
unconfirmedChangTextField = FormBuilder.addTopLabelReadOnlyTextField(gridPane, ++gridRow,
|
||||
Res.get("dao.unconfirmedChangeBalance")).second;
|
||||
unverifiedBalanceTextField = FormBuilder.addTopLabelReadOnlyTextField(gridPane, ++gridRow,
|
||||
Res.get("dao.unverifiedBsqBalance")).second;
|
||||
totalBalanceTextField = FormBuilder.addTopLabelReadOnlyTextField(gridPane, ++gridRow,
|
||||
Res.get("dao.totalBsqBalance")).second;
|
||||
|
||||
gridRow = startIndex;
|
||||
int columnIndex = 2;
|
||||
titledGroupBg = addTitledGroupBg(gridPane, gridRow, columnIndex, 3, "");
|
||||
addTitledGroupBg(gridPane, gridRow, columnIndex, 4, "");
|
||||
lockedForVoteBalanceTextField = FormBuilder.addTopLabelReadOnlyTextField(gridPane, gridRow, columnIndex,
|
||||
Res.get("dao.lockedForVoteBalance"), Layout.FIRST_ROW_DISTANCE).second;
|
||||
lockedInBondsBalanceTextField = FormBuilder.addTopLabelReadOnlyTextField(gridPane, ++gridRow, columnIndex,
|
||||
Res.get("dao.lockedInBonds")).second;
|
||||
Tuple3<Label, TextField, VBox> tuple3 = FormBuilder.addTopLabelReadOnlyTextField(gridPane, ++gridRow, columnIndex,
|
||||
Res.get("dao.availableNonBsqBalance"));
|
||||
// Match left column
|
||||
++gridRow;
|
||||
|
||||
// TODO add unlockingBondsBalanceTextField
|
||||
|
||||
|
@ -104,58 +188,4 @@ public class BsqBalanceUtil implements BsqBalanceListener {
|
|||
|
||||
return gridRow;
|
||||
}
|
||||
|
||||
public void activate() {
|
||||
onUpdateBalances(bsqWalletService.getAvailableConfirmedBalance(),
|
||||
bsqWalletService.getAvailableNonBsqBalance(),
|
||||
bsqWalletService.getUnverifiedBalance(),
|
||||
bsqWalletService.getUnconfirmedChangeBalance(),
|
||||
bsqWalletService.getLockedForVotingBalance(),
|
||||
bsqWalletService.getLockupBondsBalance(),
|
||||
bsqWalletService.getUnlockingBondsBalance());
|
||||
bsqWalletService.addBsqBalanceListener(this);
|
||||
}
|
||||
|
||||
public void deactivate() {
|
||||
bsqWalletService.removeBsqBalanceListener(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onUpdateBalances(Coin availableBalance,
|
||||
Coin availableNonBsqBalance,
|
||||
Coin unverifiedBalance,
|
||||
Coin unconfirmedChangeBalance,
|
||||
Coin lockedForVotingBalance,
|
||||
Coin lockupBondsBalance,
|
||||
Coin unlockingBondsBalance) {
|
||||
|
||||
boolean isNonBsqBalanceAvailable = availableNonBsqBalance.value > 0;
|
||||
|
||||
//TODO MK
|
||||
// Coin availableAndChange = availableBalance.add(unconfirmedChangeBalance);
|
||||
availableBalanceTextField.setText(bsqFormatter.formatCoinWithCode(availableBalance));
|
||||
unverifiedBalanceTextField.setText(bsqFormatter.formatCoinWithCode(unverifiedBalance));
|
||||
lockedForVoteBalanceTextField.setText(bsqFormatter.formatCoinWithCode(lockedForVotingBalance));
|
||||
lockedInBondsBalanceTextField.setText(bsqFormatter.formatCoinWithCode(
|
||||
lockupBondsBalance.add(unlockingBondsBalance)));
|
||||
|
||||
if (lockupAmountTextField != null && unlockingAmountTextField != null) {
|
||||
lockupAmountTextField.setText(bsqFormatter.formatCoinWithCode(lockupBondsBalance));
|
||||
unlockingAmountTextField.setText(bsqFormatter.formatCoinWithCode(unlockingBondsBalance));
|
||||
}
|
||||
|
||||
availableNonBsqBalanceLabel.setVisible(isNonBsqBalanceAvailable);
|
||||
availableNonBsqBalanceLabel.setManaged(isNonBsqBalanceAvailable);
|
||||
availableNonBsqBalanceTextField.setVisible(isNonBsqBalanceAvailable);
|
||||
availableNonBsqBalanceTextField.setManaged(isNonBsqBalanceAvailable);
|
||||
availableNonBsqBalanceTextField.setText(bsqFormatter.formatBTCWithCode(availableNonBsqBalance.value));
|
||||
|
||||
final Coin total = availableBalance
|
||||
.add(unverifiedBalance)
|
||||
.add(lockedForVotingBalance)
|
||||
.add(lockupBondsBalance)
|
||||
.add(unlockingBondsBalance);
|
||||
totalBalanceTextField.setText(bsqFormatter.formatCoinWithCode(total));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue