mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-23 23:06:39 +01:00
Merge pull request #6552 from stejbac/speed-up-closed-trades-view-load
Speed up loading and scrolling of trade history
This commit is contained in:
commit
2239924225
3 changed files with 70 additions and 22 deletions
|
@ -72,6 +72,7 @@ import org.bitcoinj.wallet.listeners.WalletReorganizeEventListener;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.ImmutableSetMultimap;
|
||||
import com.google.common.collect.Multiset;
|
||||
|
@ -87,6 +88,7 @@ import org.bouncycastle.crypto.params.KeyParameter;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
@ -122,6 +124,7 @@ public abstract class WalletService {
|
|||
private final WalletChangeEventListener cacheInvalidationListener;
|
||||
private final AtomicReference<Multiset<Address>> txOutputAddressCache = new AtomicReference<>();
|
||||
private final AtomicReference<SetMultimap<Address, Transaction>> addressToMatchingTxSetCache = new AtomicReference<>();
|
||||
private final AtomicReference<Map<Sha256Hash, Transaction>> txByIdCache = new AtomicReference<>();
|
||||
@Getter
|
||||
protected Wallet wallet;
|
||||
@Getter
|
||||
|
@ -147,6 +150,7 @@ public abstract class WalletService {
|
|||
cacheInvalidationListener = wallet -> {
|
||||
txOutputAddressCache.set(null);
|
||||
addressToMatchingTxSetCache.set(null);
|
||||
txByIdCache.set(null);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -440,15 +444,15 @@ public abstract class WalletService {
|
|||
public TransactionConfidence getConfidenceForAddress(Address address) {
|
||||
List<TransactionConfidence> transactionConfidenceList = new ArrayList<>();
|
||||
if (wallet != null) {
|
||||
Set<Transaction> transactions = getAddressToMatchingTxSetMultiset().get(address);
|
||||
Set<Transaction> transactions = getAddressToMatchingTxSetMultimap().get(address);
|
||||
transactionConfidenceList.addAll(transactions.stream().map(tx ->
|
||||
getTransactionConfidence(tx, address)).collect(Collectors.toList()));
|
||||
}
|
||||
return getMostRecentConfidence(transactionConfidenceList);
|
||||
}
|
||||
|
||||
private SetMultimap<Address, Transaction> getAddressToMatchingTxSetMultiset() {
|
||||
return addressToMatchingTxSetCache.updateAndGet(set -> set != null ? set : computeAddressToMatchingTxSetMultimap());
|
||||
private SetMultimap<Address, Transaction> getAddressToMatchingTxSetMultimap() {
|
||||
return addressToMatchingTxSetCache.updateAndGet(map -> map != null ? map : computeAddressToMatchingTxSetMultimap());
|
||||
}
|
||||
|
||||
private SetMultimap<Address, Transaction> computeAddressToMatchingTxSetMultimap() {
|
||||
|
@ -463,17 +467,25 @@ public abstract class WalletService {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
public TransactionConfidence getConfidenceForTxId(String txId) {
|
||||
if (wallet != null) {
|
||||
Set<Transaction> transactions = wallet.getTransactions(false);
|
||||
for (Transaction tx : transactions) {
|
||||
if (tx.getTxId().toString().equals(txId))
|
||||
return tx.getConfidence();
|
||||
public TransactionConfidence getConfidenceForTxId(@Nullable String txId) {
|
||||
if (wallet != null && txId != null) {
|
||||
Transaction tx = getTxByIdMap().get(Sha256Hash.wrap(txId));
|
||||
if (tx != null) {
|
||||
return tx.getConfidence();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Map<Sha256Hash, Transaction> getTxByIdMap() {
|
||||
return txByIdCache.updateAndGet(map -> map != null ? map : computeTxByIdMap());
|
||||
}
|
||||
|
||||
private Map<Sha256Hash, Transaction> computeTxByIdMap() {
|
||||
return wallet.getTransactions(false).stream()
|
||||
.collect(ImmutableMap.toImmutableMap(Transaction::getTxId, tx -> tx));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private TransactionConfidence getTransactionConfidence(Transaction tx, Address address) {
|
||||
List<TransactionConfidence> transactionConfidenceList = getOutputsWithConnectedOutputs(tx).stream()
|
||||
|
@ -761,7 +773,7 @@ public abstract class WalletService {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
public Transaction getTransaction(String txId) {
|
||||
public Transaction getTransaction(@Nullable String txId) {
|
||||
if (txId == null) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,6 @@ import bisq.core.trade.bsq_swap.BsqSwapTradeManager;
|
|||
import bisq.core.trade.model.MakerTrade;
|
||||
import bisq.core.trade.model.Tradable;
|
||||
import bisq.core.trade.model.TradableList;
|
||||
import bisq.core.trade.model.TradeModel;
|
||||
import bisq.core.trade.model.bisq_v1.Trade;
|
||||
import bisq.core.trade.statistics.TradeStatisticsManager;
|
||||
import bisq.core.user.Preferences;
|
||||
|
@ -47,6 +46,8 @@ import org.bitcoinj.utils.Fiat;
|
|||
import com.google.inject.Inject;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.Multiset;
|
||||
|
||||
import javafx.collections.ObservableList;
|
||||
|
||||
|
@ -63,6 +64,8 @@ import java.util.stream.Stream;
|
|||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static bisq.core.offer.OpenOffer.State.CANCELED;
|
||||
import static bisq.core.trade.ClosedTradableUtil.castToTrade;
|
||||
import static bisq.core.trade.ClosedTradableUtil.castToTradeModel;
|
||||
|
@ -88,6 +91,8 @@ public class ClosedTradableManager implements PersistedDataHost {
|
|||
private final DumpDelayedPayoutTx dumpDelayedPayoutTx;
|
||||
|
||||
private final TradableList<Tradable> closedTradables = new TradableList<>();
|
||||
@Nullable
|
||||
private Multiset<NodeAddress> closedTradeNodeAddressCache;
|
||||
|
||||
@Inject
|
||||
public ClosedTradableManager(KeyRing keyRing,
|
||||
|
@ -109,6 +114,8 @@ public class ClosedTradableManager implements PersistedDataHost {
|
|||
this.dumpDelayedPayoutTx = dumpDelayedPayoutTx;
|
||||
this.persistenceManager = persistenceManager;
|
||||
|
||||
closedTradables.addListener(c -> closedTradeNodeAddressCache = null);
|
||||
|
||||
this.persistenceManager.initialize(closedTradables, "ClosedTrades", PersistenceManager.Source.PRIVATE);
|
||||
}
|
||||
|
||||
|
@ -206,8 +213,7 @@ public class ClosedTradableManager implements PersistedDataHost {
|
|||
Instant safeDate = getSafeDateForSensitiveDataClearing();
|
||||
return closedTradables.stream()
|
||||
.filter(e -> e.getId().equals(tradeId))
|
||||
.filter(e -> e.getDate().toInstant().isBefore(safeDate))
|
||||
.count() > 0;
|
||||
.anyMatch(e -> e.getDate().toInstant().isBefore(safeDate));
|
||||
}
|
||||
|
||||
public Instant getSafeDateForSensitiveDataClearing() {
|
||||
|
@ -220,8 +226,16 @@ public class ClosedTradableManager implements PersistedDataHost {
|
|||
.filter(Trade::isFundsLockedIn);
|
||||
}
|
||||
|
||||
public Stream<TradeModel> getTradeModelStream() {
|
||||
return Stream.concat(bsqSwapTradeManager.getConfirmedBsqSwapTrades(), getClosedTrades().stream());
|
||||
private Multiset<NodeAddress> getClosedTradeNodeAddresses() {
|
||||
var addresses = closedTradeNodeAddressCache;
|
||||
if (addresses == null) {
|
||||
closedTradeNodeAddressCache = addresses = closedTradables.stream()
|
||||
.filter(t -> t instanceof Trade)
|
||||
.map(t -> ((Trade) t).getTradingPeerNodeAddress())
|
||||
.filter(Objects::nonNull)
|
||||
.collect(ImmutableMultiset.toImmutableMultiset());
|
||||
}
|
||||
return addresses;
|
||||
}
|
||||
|
||||
public int getNumPastTrades(Tradable tradable) {
|
||||
|
@ -229,11 +243,8 @@ public class ClosedTradableManager implements PersistedDataHost {
|
|||
return 0;
|
||||
}
|
||||
NodeAddress addressInTrade = castToTradeModel(tradable).getTradingPeerNodeAddress();
|
||||
return (int) getTradeModelStream()
|
||||
.map(TradeModel::getTradingPeerNodeAddress)
|
||||
.filter(Objects::nonNull)
|
||||
.filter(address -> address.equals(addressInTrade))
|
||||
.count();
|
||||
return bsqSwapTradeManager.getConfirmedBsqSwapNodeAddresses().count(addressInTrade) +
|
||||
getClosedTradeNodeAddresses().count(addressInTrade);
|
||||
}
|
||||
|
||||
public boolean isCurrencyForTradeFeeBtc(Tradable tradable) {
|
||||
|
|
|
@ -22,8 +22,11 @@ import bisq.core.offer.Offer;
|
|||
import bisq.core.provider.price.PriceFeedService;
|
||||
import bisq.core.trade.model.Tradable;
|
||||
import bisq.core.trade.model.TradableList;
|
||||
import bisq.core.trade.model.TradeModel;
|
||||
import bisq.core.trade.model.bsq_swap.BsqSwapTrade;
|
||||
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
|
||||
import bisq.common.crypto.KeyRing;
|
||||
import bisq.common.persistence.PersistenceManager;
|
||||
import bisq.common.proto.persistable.PersistedDataHost;
|
||||
|
@ -34,6 +37,8 @@ import com.google.inject.Inject;
|
|||
import com.google.inject.Singleton;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.Multiset;
|
||||
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
|
@ -42,20 +47,25 @@ import javafx.collections.ObservableList;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Slf4j
|
||||
@Singleton
|
||||
public class BsqSwapTradeManager implements PersistedDataHost {
|
||||
private final KeyRing keyRing;
|
||||
private final PriceFeedService priceFeedService;
|
||||
private final BsqWalletService bsqWalletService;
|
||||
private final PersistenceManager<TradableList<BsqSwapTrade>> persistenceManager;
|
||||
private final TradableList<BsqSwapTrade> bsqSwapTrades = new TradableList<>();
|
||||
private final KeyRing keyRing;
|
||||
private final PriceFeedService priceFeedService;
|
||||
@Nullable
|
||||
private Multiset<NodeAddress> confirmedBsqSwapNodeAddressCache;
|
||||
|
||||
// Used for listening for notifications in the UI
|
||||
@Getter
|
||||
|
@ -71,6 +81,9 @@ public class BsqSwapTradeManager implements PersistedDataHost {
|
|||
this.bsqWalletService = bsqWalletService;
|
||||
this.persistenceManager = persistenceManager;
|
||||
|
||||
bsqWalletService.addWalletTransactionsChangeListener(() -> confirmedBsqSwapNodeAddressCache = null);
|
||||
bsqSwapTrades.addListener(c -> confirmedBsqSwapNodeAddressCache = null);
|
||||
|
||||
this.persistenceManager.initialize(bsqSwapTrades, "BsqSwapTrades", PersistenceManager.Source.PRIVATE);
|
||||
}
|
||||
|
||||
|
@ -133,6 +146,18 @@ public class BsqSwapTradeManager implements PersistedDataHost {
|
|||
return getObservableList().stream().filter(this::isConfirmed);
|
||||
}
|
||||
|
||||
public Multiset<NodeAddress> getConfirmedBsqSwapNodeAddresses() {
|
||||
var addresses = confirmedBsqSwapNodeAddressCache;
|
||||
if (addresses == null) {
|
||||
confirmedBsqSwapNodeAddressCache = addresses = bsqSwapTrades.stream()
|
||||
.filter(this::isConfirmed)
|
||||
.map(TradeModel::getTradingPeerNodeAddress)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(ImmutableMultiset.toImmutableMultiset());
|
||||
}
|
||||
return addresses;
|
||||
}
|
||||
|
||||
private boolean isUnconfirmed(BsqSwapTrade bsqSwapTrade) {
|
||||
return matchesConfidence(bsqSwapTrade, TransactionConfidence.ConfidenceType.PENDING);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue