diff --git a/src/main/java/com/sparrowwallet/sparrow/control/CoinTreeTable.java b/src/main/java/com/sparrowwallet/sparrow/control/CoinTreeTable.java index 0d5da3a9..24002fd1 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/CoinTreeTable.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/CoinTreeTable.java @@ -38,18 +38,21 @@ public class CoinTreeTable extends TreeTableView { } public void updateHistoryStatus(WalletHistoryStatusEvent event) { - Platform.runLater(() -> { - if(event.getErrorMessage() != null) { - setPlaceholder(new Label("Error loading transactions: " + event.getErrorMessage())); - } else if(event.isLoading()) { - if(event.getStatusMessage() != null) { - setPlaceholder(new Label(event.getStatusMessage() + "...")); + Entry entry = getRoot().getValue(); + if(entry != null && event.getWallet() != null && entry.getWallet() == event.getWallet()) { + Platform.runLater(() -> { + if(event.getErrorMessage() != null) { + setPlaceholder(new Label("Error loading transactions: " + event.getErrorMessage())); + } else if(event.isLoading()) { + if(event.getStatusMessage() != null) { + setPlaceholder(new Label(event.getStatusMessage() + "...")); + } else { + setPlaceholder(new Label("Loading transactions...")); + } } else { - setPlaceholder(new Label("Loading transactions...")); + setPlaceholder(new Label("No transactions")); } - } else { - setPlaceholder(new Label("No transactions")); - } - }); + }); + } } } diff --git a/src/main/java/com/sparrowwallet/sparrow/event/WalletHistoryStatusEvent.java b/src/main/java/com/sparrowwallet/sparrow/event/WalletHistoryStatusEvent.java index 5a19b63c..a40771bb 100644 --- a/src/main/java/com/sparrowwallet/sparrow/event/WalletHistoryStatusEvent.java +++ b/src/main/java/com/sparrowwallet/sparrow/event/WalletHistoryStatusEvent.java @@ -1,28 +1,38 @@ package com.sparrowwallet.sparrow.event; +import com.sparrowwallet.drongo.wallet.Wallet; + public class WalletHistoryStatusEvent { + private final Wallet wallet; private final boolean loaded; private final String statusMessage; private final String errorMessage; - public WalletHistoryStatusEvent(boolean loaded) { + public WalletHistoryStatusEvent(Wallet wallet, boolean loaded) { + this.wallet = wallet; this.loaded = loaded; this.statusMessage = null; this.errorMessage = null; } - public WalletHistoryStatusEvent(boolean loaded, String statusMessage) { + public WalletHistoryStatusEvent(Wallet wallet,boolean loaded, String statusMessage) { + this.wallet = wallet; this.loaded = false; this.statusMessage = statusMessage; this.errorMessage = null; } - public WalletHistoryStatusEvent(String errorMessage) { + public WalletHistoryStatusEvent(Wallet wallet,String errorMessage) { + this.wallet = wallet; this.loaded = false; this.statusMessage = null; this.errorMessage = errorMessage; } + public Wallet getWallet() { + return wallet; + } + public boolean isLoading() { return !loaded; } diff --git a/src/main/java/com/sparrowwallet/sparrow/net/BatchedElectrumServerRpc.java b/src/main/java/com/sparrowwallet/sparrow/net/BatchedElectrumServerRpc.java index 11963d38..65005697 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/BatchedElectrumServerRpc.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/BatchedElectrumServerRpc.java @@ -6,6 +6,7 @@ import com.github.arteam.simplejsonrpc.client.builder.BatchRequestBuilder; import com.github.arteam.simplejsonrpc.client.exception.JsonRpcBatchException; import com.github.arteam.simplejsonrpc.client.exception.JsonRpcException; import com.sparrowwallet.drongo.protocol.Sha256Hash; +import com.sparrowwallet.drongo.wallet.Wallet; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.event.WalletHistoryStatusEvent; import org.slf4j.Logger; @@ -69,10 +70,10 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc { @Override @SuppressWarnings("unchecked") - public Map getScriptHashHistory(Transport transport, Map pathScriptHashes, boolean failOnError) { + public Map getScriptHashHistory(Transport transport, Wallet wallet, Map pathScriptHashes, boolean failOnError) { JsonRpcClient client = new JsonRpcClient(transport); BatchRequestBuilder batchRequest = client.createBatchRequest().keysType(String.class).returnType(ScriptHashTx[].class); - EventManager.get().post(new WalletHistoryStatusEvent(false, "Loading transactions")); + EventManager.get().post(new WalletHistoryStatusEvent(wallet, false, "Loading transactions")); for(String path : pathScriptHashes.keySet()) { batchRequest.add(path, "blockchain.scripthash.get_history", pathScriptHashes.get(path)); @@ -98,7 +99,7 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc { @Override @SuppressWarnings("unchecked") - public Map getScriptHashMempool(Transport transport, Map pathScriptHashes, boolean failOnError) { + public Map getScriptHashMempool(Transport transport, Wallet wallet, Map pathScriptHashes, boolean failOnError) { JsonRpcClient client = new JsonRpcClient(transport); BatchRequestBuilder batchRequest = client.createBatchRequest().keysType(String.class).returnType(ScriptHashTx[].class); @@ -125,10 +126,10 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc { } @Override - public Map subscribeScriptHashes(Transport transport, Map pathScriptHashes) { + public Map subscribeScriptHashes(Transport transport, Wallet wallet, Map pathScriptHashes) { JsonRpcClient client = new JsonRpcClient(transport); BatchRequestBuilder batchRequest = client.createBatchRequest().keysType(String.class).returnType(String.class); - EventManager.get().post(new WalletHistoryStatusEvent(false, "Finding transactions")); + EventManager.get().post(new WalletHistoryStatusEvent(wallet, false, "Finding transactions")); for(String path : pathScriptHashes.keySet()) { batchRequest.add(path, "blockchain.scripthash.subscribe", pathScriptHashes.get(path)); @@ -146,10 +147,10 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc { @Override @SuppressWarnings("unchecked") - public Map getBlockHeaders(Transport transport, Set blockHeights) { + public Map getBlockHeaders(Transport transport, Wallet wallet, Set blockHeights) { JsonRpcClient client = new JsonRpcClient(transport); BatchRequestBuilder batchRequest = client.createBatchRequest().keysType(Integer.class).returnType(String.class); - EventManager.get().post(new WalletHistoryStatusEvent(false, "Retrieving blocks")); + EventManager.get().post(new WalletHistoryStatusEvent(wallet, false, "Retrieving blocks")); for(Integer height : blockHeights) { batchRequest.add(height, "blockchain.block.header", height); @@ -166,10 +167,10 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc { @Override @SuppressWarnings("unchecked") - public Map getTransactions(Transport transport, Set txids) { + public Map getTransactions(Transport transport, Wallet wallet, Set txids) { JsonRpcClient client = new JsonRpcClient(transport); BatchRequestBuilder batchRequest = client.createBatchRequest().keysType(String.class).returnType(String.class); - EventManager.get().post(new WalletHistoryStatusEvent(false, "Retrieving transactions")); + EventManager.get().post(new WalletHistoryStatusEvent(wallet, false, "Retrieving transactions")); for(String txid : txids) { batchRequest.add(txid, "blockchain.transaction.get", txid); diff --git a/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java b/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java index 0ffadf86..8471307b 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServer.java @@ -224,7 +224,7 @@ public class ElectrumServer { } //Even if we have some successes, failure to retrieve all references will result in an incomplete wallet history. Don't proceed if that's the case. - Map result = electrumServerRpc.getScriptHashHistory(getTransport(), pathScriptHashes, true); + Map result = electrumServerRpc.getScriptHashHistory(getTransport(), wallet, pathScriptHashes, true); for(String path : result.keySet()) { ScriptHashTx[] txes = result.get(path); @@ -298,7 +298,7 @@ public class ElectrumServer { return; } - Map result = electrumServerRpc.subscribeScriptHashes(getTransport(), pathScriptHashes); + Map result = electrumServerRpc.subscribeScriptHashes(getTransport(), wallet, pathScriptHashes); for(String path : result.keySet()) { String status = result.get(path); @@ -332,7 +332,7 @@ public class ElectrumServer { pathScriptHashes.put(Integer.toString(i), getScriptHash(output)); } - Map result = electrumServerRpc.getScriptHashHistory(getTransport(), pathScriptHashes, false); + Map result = electrumServerRpc.getScriptHashHistory(getTransport(), null, pathScriptHashes, false); List> blockTransactionHashes = new ArrayList<>(transaction.getOutputs().size()); for(int i = 0; i < transaction.getOutputs().size(); i++) { @@ -384,8 +384,8 @@ public class ElectrumServer { Map transactionMap = new HashMap<>(); if(!references.isEmpty()) { - Map blockHeaderMap = getBlockHeaders(references); - transactionMap = getTransactions(references, blockHeaderMap); + Map blockHeaderMap = getBlockHeaders(wallet, references); + transactionMap = getTransactions(wallet, references, blockHeaderMap); } if(!transactionMap.equals(wallet.getTransactions())) { @@ -393,7 +393,7 @@ public class ElectrumServer { } } - public Map getBlockHeaders(Set references) throws ServerException { + public Map getBlockHeaders(Wallet wallet, Set references) throws ServerException { try { Set blockHeights = new TreeSet<>(); for(BlockTransactionHash reference : references) { @@ -406,7 +406,7 @@ public class ElectrumServer { return Collections.emptyMap(); } - Map result = electrumServerRpc.getBlockHeaders(getTransport(), blockHeights); + Map result = electrumServerRpc.getBlockHeaders(getTransport(), wallet, blockHeights); Map blockHeaderMap = new TreeMap<>(); for(Integer height : result.keySet()) { @@ -428,7 +428,7 @@ public class ElectrumServer { } } - public Map getTransactions(Set references, Map blockHeaderMap) throws ServerException { + public Map getTransactions(Wallet wallet, Set references, Map blockHeaderMap) throws ServerException { try { Set checkReferences = new TreeSet<>(references); @@ -437,7 +437,7 @@ public class ElectrumServer { txids.add(reference.getHashAsString()); } - Map result = electrumServerRpc.getTransactions(getTransport(), txids); + Map result = electrumServerRpc.getTransactions(getTransport(), wallet, txids); String strErrorTx = Sha256Hash.ZERO_HASH.toString(); Map transactionMap = new HashMap<>(); @@ -946,8 +946,8 @@ public class ElectrumServer { Map transactionMap = new HashMap<>(); if(!setReferences.isEmpty()) { - Map blockHeaderMap = electrumServer.getBlockHeaders(setReferences); - transactionMap = electrumServer.getTransactions(setReferences, blockHeaderMap); + Map blockHeaderMap = electrumServer.getBlockHeaders(null, setReferences); + transactionMap = electrumServer.getTransactions(null, setReferences, blockHeaderMap); } for(int i = 0; i < outputTransactionReferences.size(); i++) { diff --git a/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServerRpc.java b/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServerRpc.java index 62744f11..09255cbc 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServerRpc.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/ElectrumServerRpc.java @@ -1,6 +1,7 @@ package com.sparrowwallet.sparrow.net; import com.github.arteam.simplejsonrpc.client.Transport; +import com.sparrowwallet.drongo.wallet.Wallet; import java.util.List; import java.util.Map; @@ -15,15 +16,15 @@ public interface ElectrumServerRpc { BlockHeaderTip subscribeBlockHeaders(Transport transport); - Map getScriptHashHistory(Transport transport, Map pathScriptHashes, boolean failOnError); + Map getScriptHashHistory(Transport transport, Wallet wallet, Map pathScriptHashes, boolean failOnError); - Map getScriptHashMempool(Transport transport, Map pathScriptHashes, boolean failOnError); + Map getScriptHashMempool(Transport transport, Wallet wallet, Map pathScriptHashes, boolean failOnError); - Map subscribeScriptHashes(Transport transport, Map pathScriptHashes); + Map subscribeScriptHashes(Transport transport, Wallet wallet, Map pathScriptHashes); - Map getBlockHeaders(Transport transport, Set blockHeights); + Map getBlockHeaders(Transport transport, Wallet wallet, Set blockHeights); - Map getTransactions(Transport transport, Set txids); + Map getTransactions(Transport transport, Wallet wallet, Set txids); Map getVerboseTransactions(Transport transport, Set txids, String scriptHash); diff --git a/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java b/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java index 63dbdb52..c0eef1d0 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java @@ -6,6 +6,7 @@ import com.github.arteam.simplejsonrpc.client.exception.JsonRpcException; import com.sparrowwallet.drongo.Utils; import com.sparrowwallet.drongo.protocol.Sha256Hash; import com.sparrowwallet.drongo.protocol.Transaction; +import com.sparrowwallet.drongo.wallet.Wallet; import com.sparrowwallet.sparrow.AppController; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.event.WalletHistoryStatusEvent; @@ -69,12 +70,12 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc { } @Override - public Map getScriptHashHistory(Transport transport, Map pathScriptHashes, boolean failOnError) { + public Map getScriptHashHistory(Transport transport, Wallet wallet, Map pathScriptHashes, boolean failOnError) { JsonRpcClient client = new JsonRpcClient(transport); Map result = new LinkedHashMap<>(); for(String path : pathScriptHashes.keySet()) { - EventManager.get().post(new WalletHistoryStatusEvent(false, "Loading transactions for " + path)); + EventManager.get().post(new WalletHistoryStatusEvent(wallet, false, "Loading transactions for " + path)); try { ScriptHashTx[] scriptHashTxes = new RetryLogic(MAX_RETRIES, RETRY_DELAY, List.of(IllegalStateException.class, IllegalArgumentException.class)).getResult(() -> client.createRequest().returnAs(ScriptHashTx[].class).method("blockchain.scripthash.get_history").id(path + "-" + idCounter.incrementAndGet()).params(pathScriptHashes.get(path)).execute()); @@ -92,7 +93,7 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc { } @Override - public Map getScriptHashMempool(Transport transport, Map pathScriptHashes, boolean failOnError) { + public Map getScriptHashMempool(Transport transport, Wallet wallet, Map pathScriptHashes, boolean failOnError) { JsonRpcClient client = new JsonRpcClient(transport); Map result = new LinkedHashMap<>(); @@ -114,12 +115,12 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc { } @Override - public Map subscribeScriptHashes(Transport transport, Map pathScriptHashes) { + public Map subscribeScriptHashes(Transport transport, Wallet wallet, Map pathScriptHashes) { JsonRpcClient client = new JsonRpcClient(transport); Map result = new LinkedHashMap<>(); for(String path : pathScriptHashes.keySet()) { - EventManager.get().post(new WalletHistoryStatusEvent(false, "Finding transactions for " + path)); + EventManager.get().post(new WalletHistoryStatusEvent(wallet, false, "Finding transactions for " + path)); try { String scriptHash = new RetryLogic(MAX_RETRIES, RETRY_DELAY, List.of(IllegalStateException.class, IllegalArgumentException.class)).getResult(() -> client.createRequest().returnAs(String.class).method("blockchain.scripthash.subscribe").id(path + "-" + idCounter.incrementAndGet()).params(pathScriptHashes.get(path)).executeNullable()); @@ -134,12 +135,12 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc { } @Override - public Map getBlockHeaders(Transport transport, Set blockHeights) { + public Map getBlockHeaders(Transport transport, Wallet wallet, Set blockHeights) { JsonRpcClient client = new JsonRpcClient(transport); Map result = new LinkedHashMap<>(); for(Integer blockHeight : blockHeights) { - EventManager.get().post(new WalletHistoryStatusEvent(false, "Retrieving block at height " + blockHeight)); + EventManager.get().post(new WalletHistoryStatusEvent(wallet, false, "Retrieving block at height " + blockHeight)); try { String blockHeader = new RetryLogic(MAX_RETRIES, RETRY_DELAY, List.of(IllegalStateException.class, IllegalArgumentException.class)).getResult(() -> client.createRequest().returnAs(String.class).method("blockchain.block.header").id(idCounter.incrementAndGet()).params(blockHeight).execute()); @@ -155,12 +156,12 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc { } @Override - public Map getTransactions(Transport transport, Set txids) { + public Map getTransactions(Transport transport, Wallet wallet, Set txids) { JsonRpcClient client = new JsonRpcClient(transport); Map result = new LinkedHashMap<>(); for(String txid : txids) { - EventManager.get().post(new WalletHistoryStatusEvent(false, "Retrieving transaction [" + txid.substring(0, 6) + "]")); + EventManager.get().post(new WalletHistoryStatusEvent(wallet, false, "Retrieving transaction [" + txid.substring(0, 6) + "]")); try { String rawTxHex = new RetryLogic(MAX_RETRIES, RETRY_DELAY, List.of(IllegalStateException.class, IllegalArgumentException.class)).getResult(() -> client.createRequest().returnAs(String.class).method("blockchain.transaction.get").id(idCounter.incrementAndGet()).params(txid).execute()); diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/WalletForm.java b/src/main/java/com/sparrowwallet/sparrow/wallet/WalletForm.java index d6847ed1..92426abb 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/WalletForm.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/WalletForm.java @@ -79,14 +79,14 @@ public class WalletForm { log.debug(node == null ? "Refreshing full wallet history" : "Requesting node wallet history for " + node.getDerivationPath()); ElectrumServer.TransactionHistoryService historyService = new ElectrumServer.TransactionHistoryService(wallet, getWalletTransactionNodes(node)); historyService.setOnSucceeded(workerStateEvent -> { - EventManager.get().post(new WalletHistoryStatusEvent(true)); + EventManager.get().post(new WalletHistoryStatusEvent(wallet, true)); updateWallet(previousWallet, blockHeight); }); historyService.setOnFailed(workerStateEvent -> { log.error("Error retrieving wallet history", workerStateEvent.getSource().getException()); - EventManager.get().post(new WalletHistoryStatusEvent(workerStateEvent.getSource().getException().getMessage())); + EventManager.get().post(new WalletHistoryStatusEvent(wallet, workerStateEvent.getSource().getException().getMessage())); }); - EventManager.get().post(new WalletHistoryStatusEvent(false)); + EventManager.get().post(new WalletHistoryStatusEvent(wallet, false)); historyService.start(); } }