Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speed up BSQ tx view load #6600

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,55 +26,82 @@
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionConfidence;

import com.google.common.base.Suppliers;

import javafx.scene.control.Tooltip;

import lombok.Data;
import java.util.function.Supplier;

import lombok.Getter;

@Data
public class TxConfidenceListItem {
@Getter
protected final BsqWalletService bsqWalletService;
@Getter
protected final String txId;
protected int confirmations = 0;
protected TxConfidenceIndicator txConfidenceIndicator;
protected TxConfidenceListener txConfidenceListener;
private final TxConfidenceListener txConfidenceListener;
private final Supplier<LazyFields> lazyFieldsSupplier;
private volatile LazyFields lazyFields;

private static class LazyFields {
int confirmations;
TxConfidenceIndicator txConfidenceIndicator;
Tooltip tooltip;
}

private LazyFields lazy() {
return lazyFieldsSupplier.get();
}

protected TxConfidenceListItem(Transaction transaction,
BsqWalletService bsqWalletService) {
this.bsqWalletService = bsqWalletService;

txId = transaction.getTxId().toString();
txConfidenceIndicator = new TxConfidenceIndicator();
txConfidenceIndicator.setId("funds-confidence");
Tooltip tooltip = new Tooltip();
txConfidenceIndicator.setProgress(0);
txConfidenceIndicator.setPrefSize(24, 24);
txConfidenceIndicator.setTooltip(tooltip);
lazyFieldsSupplier = Suppliers.memoize(() -> new LazyFields() {{
txConfidenceIndicator = new TxConfidenceIndicator();
txConfidenceIndicator.setId("funds-confidence");
tooltip = new Tooltip();
txConfidenceIndicator.setProgress(0);
txConfidenceIndicator.setPrefSize(24, 24);
txConfidenceIndicator.setTooltip(tooltip);

lazyFields = this;
updateConfidence(bsqWalletService.getConfidenceForTxId(txId));
}});

txConfidenceListener = new TxConfidenceListener(txId) {
@Override
public void onTransactionConfidenceChanged(TransactionConfidence confidence) {
updateConfidence(confidence, tooltip);
updateConfidence(confidence);
}
};
bsqWalletService.addTxConfidenceListener(txConfidenceListener);
updateConfidence(bsqWalletService.getConfidenceForTxId(txId), tooltip);
}

protected TxConfidenceListItem() {
this.bsqWalletService = null;
this.txId = null;
bsqWalletService = null;
txId = null;
txConfidenceListener = null;
lazyFieldsSupplier = null;
}

private void updateConfidence(TransactionConfidence confidence, Tooltip tooltip) {
if (confidence != null) {
GUIUtil.updateConfidence(confidence, tooltip, txConfidenceIndicator);
confirmations = confidence.getDepthInBlocks();
public int getNumConfirmations() {
return lazy().confirmations;
}

public TxConfidenceIndicator getTxConfidenceIndicator() {
return lazy().txConfidenceIndicator;
}

private void updateConfidence(TransactionConfidence confidence) {
if (confidence != null && lazyFields != null) {
GUIUtil.updateConfidence(confidence, lazyFields.tooltip, lazyFields.txConfidenceIndicator);
lazyFields.confirmations = confidence.getDepthInBlocks();
}
}

public void cleanup() {
bsqWalletService.removeTxConfidenceListener(txConfidenceListener);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
package bisq.desktop.main.dao.wallet.tx;

import bisq.desktop.components.TxConfidenceListItem;
import bisq.desktop.main.funds.transactions.TradableRepository;
import bisq.desktop.util.DisplayUtils;

import bisq.core.btc.wallet.BsqWalletService;
Expand All @@ -36,6 +35,7 @@
import org.bitcoinj.core.TransactionOutput;

import java.util.Date;
import java.util.Map;
import java.util.Optional;

import lombok.EqualsAndHashCode;
Expand Down Expand Up @@ -66,7 +66,7 @@ class BsqTxListItem extends TxConfidenceListItem {
DaoFacade daoFacade,
Date date,
BsqFormatter bsqFormatter,
TradableRepository tradableRepository) {
Map<String, BsqSwapTrade> swapTradeByTxIdMap) {
super(transaction, bsqWalletService);

this.daoFacade = daoFacade;
Expand Down Expand Up @@ -133,12 +133,7 @@ class BsqTxListItem extends TxConfidenceListItem {
else
address = "";


optionalBsqTrade = tradableRepository.getAll().stream()
.filter(tradable -> tradable instanceof BsqSwapTrade)
.map(tradable -> (BsqSwapTrade) tradable)
.filter(tradable -> txId.equals(tradable.getTxId()))
.findFirst();
optionalBsqTrade = Optional.ofNullable(swapTradeByTxIdMap.get(txId));
}

BsqTxListItem() {
Expand All @@ -156,7 +151,7 @@ class BsqTxListItem extends TxConfidenceListItem {
TxType getTxType() {
return daoFacade.getTx(txId)
.flatMap(tx -> daoFacade.getOptionalTxType(tx.getId()))
.orElse(confirmations == 0 ? TxType.UNVERIFIED : TxType.UNDEFINED_TX_TYPE);
.orElse(getNumConfirmations() == 0 ? TxType.UNVERIFIED : TxType.UNDEFINED_TX_TYPE);
}

boolean isWithdrawalToBTCWallet() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -202,14 +203,13 @@ protected void activate() {

daoFacade.addBsqStateListener(this);

updateList();

walletChainHeight = bsqWalletService.getBestChainHeight();
blockHeightBeforeProcessing = daoFacade.getChainHeight();
missingBlocks = walletChainHeight - blockHeightBeforeProcessing;
if (!daoStateService.isParseBlockChainComplete()) {
updateAnyChainHeightTimer = UserThread.runPeriodically(this::onUpdateAnyChainHeight, 100, TimeUnit.MILLISECONDS);
}
// This indirectly calls updateList(), as required:
onUpdateAnyChainHeight();

exportButton.setOnAction(event -> {
Expand All @@ -235,7 +235,7 @@ protected void activate() {
columns[3] = item.getAddress();
columns[4] = String.valueOf(item.isReceived());
columns[5] = item.getAmountAsString();
columns[6] = String.valueOf(item.getConfirmations());
columns[6] = String.valueOf(item.getNumConfirmations());
columns[7] = item.getTxType().name();
return columns;
};
Expand Down Expand Up @@ -352,17 +352,21 @@ private void updateList() {
observableList.forEach(BsqTxListItem::cleanup);

List<Transaction> walletTransactions = bsqWalletService.getClonedWalletTransactions();
Map<String, BsqSwapTrade> swapTradeByTxIdMap = tradableRepository.getAll().stream()
.filter(tradable -> tradable instanceof BsqSwapTrade)
.map(t -> (BsqSwapTrade) t)
.collect(Collectors.toMap(BsqSwapTrade::getTxId, t -> t));

List<BsqTxListItem> items = walletTransactions.stream()
.map(transaction -> {
return new BsqTxListItem(transaction,
bsqWalletService,
btcWalletService,
daoFacade,
// Use tx.getIncludedInBestChainAt() when available, otherwise use tx.getUpdateTime()
transaction.getIncludedInBestChainAt() != null ? transaction.getIncludedInBestChainAt() : transaction.getUpdateTime(),
bsqFormatter,
tradableRepository);
})
.map(transaction -> new BsqTxListItem(transaction,
bsqWalletService,
btcWalletService,
daoFacade,
// Use tx.getIncludedInBestChainAt() when available, otherwise use tx.getUpdateTime()
transaction.getIncludedInBestChainAt() != null ? transaction.getIncludedInBestChainAt() : transaction.getUpdateTime(),
bsqFormatter,
swapTradeByTxIdMap)
)
.collect(Collectors.toList());
observableList.setAll(items);
}
Expand Down Expand Up @@ -486,7 +490,7 @@ public void updateItem(final BsqTxListItem item, boolean empty) {
TxType txType = item.getTxType();
String labelString = Res.get("dao.tx.type.enum." + txType.name());
Label label;
if (item.getConfirmations() > 0 && isValidType(txType)) {
if (item.getNumConfirmations() > 0 && isValidType(txType)) {
if (item.getOptionalBsqTrade().isPresent()) {
if (field != null)
field.setOnAction(null);
Expand Down Expand Up @@ -574,7 +578,7 @@ public void updateItem(final BsqTxListItem item, boolean empty) {

String bsqAmount = Res.get("shared.na");

if (item.getConfirmations() > 0) {
if (item.getNumConfirmations() > 0) {
if (isValidType(txType))
bsqAmount = item.getAmountAsString();
else if (item.isWithdrawalToBTCWallet())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,11 @@ class DepositListItem implements FilterableListItem {
private Coin balanceAsCoin;
private final String addressString;
private String usage = "-";
private TxConfidenceListener txConfidenceListener;
private BalanceListener balanceListener;
private final TxConfidenceListener txConfidenceListener;
private final BalanceListener balanceListener;
private int numTxOutputs = 0;
private final Supplier<LazyFields> lazyFieldsSupplier;
private volatile LazyFields lazyFields;

private static class LazyFields {
TxConfidenceIndicator txConfidenceIndicator;
Expand All @@ -82,28 +83,29 @@ private LazyFields lazy() {
tooltip = new Tooltip(Res.get("shared.notUsedYet"));
txConfidenceIndicator.setProgress(0);
txConfidenceIndicator.setTooltip(tooltip);
if (confidence != null) {
GUIUtil.updateConfidence(confidence, tooltip, txConfidenceIndicator);
}

lazyFields = this;
updateConfidence(confidence);
}});

if (confidence != null) {
txConfidenceListener = new TxConfidenceListener(confidence.getTransactionHash().toString()) {
@Override
public void onTransactionConfidenceChanged(TransactionConfidence confidence) {
GUIUtil.updateConfidence(confidence, lazy().tooltip, lazy().txConfidenceIndicator);
updateConfidence(confidence);
}
};
walletService.addTxConfidenceListener(txConfidenceListener);
} else {
txConfidenceListener = null;
}

balanceListener = new BalanceListener(address) {
@Override
public void onBalanceChanged(Coin balanceAsCoin, Transaction tx) {
DepositListItem.this.balanceAsCoin = balanceAsCoin;
DepositListItem.this.balance.set(formatter.formatCoin(balanceAsCoin));
var confidence = walletService.getConfidenceForTxId(tx.getTxId().toString());
GUIUtil.updateConfidence(confidence, lazy().tooltip, lazy().txConfidenceIndicator);
updateConfidence(walletService.getConfidenceForTxId(tx.getTxId().toString()));
updateUsage(address);
}
};
Expand All @@ -115,6 +117,12 @@ public void onBalanceChanged(Coin balanceAsCoin, Transaction tx) {
updateUsage(address);
}

private void updateConfidence(TransactionConfidence confidence) {
if (confidence != null && lazyFields != null) {
GUIUtil.updateConfidence(confidence, lazyFields.tooltip, lazyFields.txConfidenceIndicator);
}
}

private void updateUsage(Address address) {
numTxOutputs = walletService.getNumTxOutputsForAddress(address);
usage = numTxOutputs == 0 ? Res.get("funds.deposit.unused") : Res.get("funds.deposit.usedInTx", numTxOutputs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,13 @@ class TransactionsListItem implements FilterableListItem {
private boolean received;
private Coin amountAsCoin = Coin.ZERO;
private String memo = "";
private int confirmations = 0;
@Getter
private final boolean isDustAttackTx;
private boolean initialTxConfidenceVisibility = true;
private final Supplier<LazyFields> lazyFieldsSupplier;

private static class LazyFields {
int confirmations;
TxConfidenceIndicator txConfidenceIndicator;
Tooltip tooltip;
}
Expand Down Expand Up @@ -349,7 +349,7 @@ public Tradable getTradable() {
}

public String getNumConfirmations() {
return String.valueOf(confirmations);
return String.valueOf(lazy().confirmations);
}

public String getMemo() {
Expand Down