mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-24 12:46:45 +00:00
add wallet transactions loading log viewer, and improve loading messages
This commit is contained in:
parent
c067300ee8
commit
438c13fe2d
11 changed files with 182 additions and 22 deletions
|
@ -120,6 +120,9 @@ public class AppController implements Initializable {
|
|||
@FXML
|
||||
private CheckMenuItem useHdCameraResolution;
|
||||
|
||||
@FXML
|
||||
private CheckMenuItem showLoadingLog;
|
||||
|
||||
@FXML
|
||||
private CheckMenuItem showTxHex;
|
||||
|
||||
|
@ -259,6 +262,7 @@ public class AppController implements Initializable {
|
|||
hideEmptyUsedAddresses.setSelected(Config.get().isHideEmptyUsedAddresses());
|
||||
useHdCameraResolution.setSelected(Config.get().isHdCapture());
|
||||
showTxHex.setSelected(Config.get().isShowTransactionHex());
|
||||
showLoadingLog.setSelected(Config.get().isShowLoadingLog());
|
||||
savePSBT.visibleProperty().bind(saveTransaction.visibleProperty().not());
|
||||
exportWallet.setDisable(true);
|
||||
refreshWallet.disableProperty().bind(Bindings.or(exportWallet.disableProperty(), Bindings.or(serverToggle.disableProperty(), AppServices.onlineProperty().not())));
|
||||
|
@ -664,6 +668,12 @@ public class AppController implements Initializable {
|
|||
Config.get().setHdCapture(item.isSelected());
|
||||
}
|
||||
|
||||
public void showLoadingLog(ActionEvent event) {
|
||||
CheckMenuItem item = (CheckMenuItem)event.getSource();
|
||||
Config.get().setShowLoadingLog(item.isSelected());
|
||||
EventManager.get().post(new LoadingLogChangedEvent(item.isSelected()));
|
||||
}
|
||||
|
||||
public void showTxHex(ActionEvent event) {
|
||||
CheckMenuItem item = (CheckMenuItem)event.getSource();
|
||||
Config.get().setShowTransactionHex(item.isSelected());
|
||||
|
@ -1364,6 +1374,7 @@ public class AppController implements Initializable {
|
|||
saveTransaction.setVisible(false);
|
||||
}
|
||||
exportWallet.setDisable(true);
|
||||
showLoadingLog.setDisable(true);
|
||||
showTxHex.setDisable(false);
|
||||
} else if(event instanceof WalletTabSelectedEvent) {
|
||||
WalletTabSelectedEvent walletTabEvent = (WalletTabSelectedEvent)event;
|
||||
|
@ -1371,6 +1382,7 @@ public class AppController implements Initializable {
|
|||
saveTransaction.setVisible(true);
|
||||
saveTransaction.setDisable(true);
|
||||
exportWallet.setDisable(walletTabData.getWallet() == null || !walletTabData.getWallet().isValid());
|
||||
showLoadingLog.setDisable(false);
|
||||
showTxHex.setDisable(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -219,7 +219,7 @@ public class AppServices {
|
|||
connectionService.setRestartOnFailure(false);
|
||||
if(tlsServerException.getCause().getMessage().contains("PKIX path building failed")) {
|
||||
File crtFile = Config.get().getElectrumServerCert();
|
||||
if(crtFile != null) {
|
||||
if(crtFile != null && Config.get().getServerType() == ServerType.ELECTRUM_SERVER) {
|
||||
AppServices.showErrorDialog("SSL Handshake Failed", "The configured server certificate at " + crtFile.getAbsolutePath() + " did not match the certificate provided by the server at " + tlsServerException.getServer().getHost() + "." +
|
||||
"\n\nThis may indicate a man-in-the-middle attack!" +
|
||||
"\n\nChange the configured server certificate if you would like to proceed.");
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package com.sparrowwallet.sparrow.event;
|
||||
|
||||
public class LoadingLogChangedEvent {
|
||||
private final boolean visible;
|
||||
|
||||
public LoadingLogChangedEvent(boolean visible) {
|
||||
this.visible = visible;
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return visible;
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ public class WalletHistoryFailedEvent extends WalletHistoryStatusEvent {
|
|||
private final Throwable exception;
|
||||
|
||||
public WalletHistoryFailedEvent(Wallet wallet, Throwable exception) {
|
||||
super(wallet, exception.getCause() == null ? exception.getMessage() : exception.getCause().getMessage());
|
||||
super(wallet, exception.getMessage());
|
||||
this.exception = exception;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ public class Config {
|
|||
private boolean openWalletsInNewWindows = false;
|
||||
private boolean hideEmptyUsedAddresses = false;
|
||||
private boolean showTransactionHex = true;
|
||||
private boolean showLoadingLog = false;
|
||||
private List<File> recentWalletFiles;
|
||||
private Integer keyDerivationPeriod;
|
||||
private File hwi;
|
||||
|
@ -249,6 +250,15 @@ public class Config {
|
|||
flush();
|
||||
}
|
||||
|
||||
public boolean isShowLoadingLog() {
|
||||
return showLoadingLog;
|
||||
}
|
||||
|
||||
public void setShowLoadingLog(boolean showLoadingLog) {
|
||||
this.showLoadingLog = showLoadingLog;
|
||||
flush();
|
||||
}
|
||||
|
||||
public List<File> getRecentWalletFiles() {
|
||||
return recentWalletFiles;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import com.github.arteam.simplejsonrpc.client.Transport;
|
|||
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.KeyDerivation;
|
||||
import com.sparrowwallet.drongo.crypto.ChildNumber;
|
||||
import com.sparrowwallet.drongo.protocol.Sha256Hash;
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
|
@ -12,11 +14,9 @@ import com.sparrowwallet.sparrow.event.WalletHistoryStatusEvent;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
||||
private static final Logger log = LoggerFactory.getLogger(BatchedElectrumServerRpc.class);
|
||||
|
@ -74,7 +74,7 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
|||
public Map<String, ScriptHashTx[]> getScriptHashHistory(Transport transport, Wallet wallet, Map<String, String> pathScriptHashes, boolean failOnError) {
|
||||
JsonRpcClient client = new JsonRpcClient(transport);
|
||||
BatchRequestBuilder<String, ScriptHashTx[]> batchRequest = client.createBatchRequest().keysType(String.class).returnType(ScriptHashTx[].class);
|
||||
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, "Loading transactions"));
|
||||
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, "Loading transactions for " + getScriptHashesAbbreviation(pathScriptHashes.keySet())));
|
||||
|
||||
for(String path : pathScriptHashes.keySet()) {
|
||||
batchRequest.add(path, "blockchain.scripthash.get_history", pathScriptHashes.get(path));
|
||||
|
@ -84,7 +84,7 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
|||
return new RetryLogic<Map<String, ScriptHashTx[]>>(MAX_RETRIES, RETRY_DELAY, IllegalStateException.class).getResult(batchRequest::execute);
|
||||
} catch (JsonRpcBatchException e) {
|
||||
if(failOnError) {
|
||||
throw new ElectrumServerRpcException("Failed to retrieve references for paths: " + e.getErrors().keySet(), e);
|
||||
throw new ElectrumServerRpcException("Failed to retrieve transaction history for paths: " + getScriptHashesAbbreviation((Collection<String>)e.getErrors().keySet()), e);
|
||||
}
|
||||
|
||||
Map<String, ScriptHashTx[]> result = (Map<String, ScriptHashTx[]>)e.getSuccesses();
|
||||
|
@ -94,7 +94,7 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
|||
|
||||
return result;
|
||||
} catch(Exception e) {
|
||||
throw new ElectrumServerRpcException("Failed to retrieve references for paths: " + pathScriptHashes.keySet(), e);
|
||||
throw new ElectrumServerRpcException("Failed to retrieve transaction history for paths: " + getScriptHashesAbbreviation(pathScriptHashes.keySet()), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
|||
return new RetryLogic<Map<String, ScriptHashTx[]>>(MAX_RETRIES, RETRY_DELAY, IllegalStateException.class).getResult(batchRequest::execute);
|
||||
} catch(JsonRpcBatchException e) {
|
||||
if(failOnError) {
|
||||
throw new ElectrumServerRpcException("Failed to retrieve references for paths: " + e.getErrors().keySet(), e);
|
||||
throw new ElectrumServerRpcException("Failed to retrieve mempool transactions for paths: " + getScriptHashesAbbreviation((Collection<String>)e.getErrors().keySet()), e);
|
||||
}
|
||||
|
||||
Map<String, ScriptHashTx[]> result = (Map<String, ScriptHashTx[]>)e.getSuccesses();
|
||||
|
@ -122,15 +122,16 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
|||
|
||||
return result;
|
||||
} catch(Exception e) {
|
||||
throw new ElectrumServerRpcException("Failed to retrieve references for paths: " + pathScriptHashes.keySet(), e);
|
||||
throw new ElectrumServerRpcException("Failed to retrieve mempool transactions for paths: " + getScriptHashesAbbreviation(pathScriptHashes.keySet()), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, String> subscribeScriptHashes(Transport transport, Wallet wallet, Map<String, String> pathScriptHashes) {
|
||||
JsonRpcClient client = new JsonRpcClient(transport);
|
||||
BatchRequestBuilder<String, String> batchRequest = client.createBatchRequest().keysType(String.class).returnType(String.class);
|
||||
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, "Finding transactions"));
|
||||
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, "Finding transactions for " + getScriptHashesAbbreviation(pathScriptHashes.keySet())));
|
||||
|
||||
for(String path : pathScriptHashes.keySet()) {
|
||||
batchRequest.add(path, "blockchain.scripthash.subscribe", pathScriptHashes.get(path));
|
||||
|
@ -140,9 +141,9 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
|||
return new RetryLogic<Map<String, String>>(MAX_RETRIES, RETRY_DELAY, IllegalStateException.class).getResult(batchRequest::execute);
|
||||
} catch(JsonRpcBatchException e) {
|
||||
//Even if we have some successes, failure to subscribe for all script hashes will result in outdated wallet view. Don't proceed.
|
||||
throw new ElectrumServerRpcException("Failed to subscribe for updates for paths: " + e.getErrors().keySet(), e);
|
||||
throw new ElectrumServerRpcException("Failed to subscribe to paths: " + getScriptHashesAbbreviation((Collection<String>)e.getErrors().keySet()), e);
|
||||
} catch(Exception e) {
|
||||
throw new ElectrumServerRpcException("Failed to subscribe for updates for paths: " + pathScriptHashes.keySet(), e);
|
||||
throw new ElectrumServerRpcException("Failed to subscribe to paths: " + getScriptHashesAbbreviation(pathScriptHashes.keySet()), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,7 +152,7 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
|||
public Map<Integer, String> getBlockHeaders(Transport transport, Wallet wallet, Set<Integer> blockHeights) {
|
||||
JsonRpcClient client = new JsonRpcClient(transport);
|
||||
BatchRequestBuilder<Integer, String> batchRequest = client.createBatchRequest().keysType(Integer.class).returnType(String.class);
|
||||
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, "Retrieving blocks"));
|
||||
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, "Retrieving " + blockHeights.size() + " block headers"));
|
||||
|
||||
for(Integer height : blockHeights) {
|
||||
batchRequest.add(height, "blockchain.block.header", height);
|
||||
|
@ -162,7 +163,7 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
|||
} catch(JsonRpcBatchException e) {
|
||||
return (Map<Integer, String>)e.getSuccesses();
|
||||
} catch(Exception e) {
|
||||
throw new ElectrumServerRpcException("Failed to block headers for block heights: " + blockHeights, e);
|
||||
throw new ElectrumServerRpcException("Failed to retrieve block headers for block heights: " + blockHeights, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,7 +172,7 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
|||
public Map<String, String> getTransactions(Transport transport, Wallet wallet, Set<String> txids) {
|
||||
JsonRpcClient client = new JsonRpcClient(transport);
|
||||
BatchRequestBuilder<String, String> batchRequest = client.createBatchRequest().keysType(String.class).returnType(String.class);
|
||||
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, "Retrieving transactions"));
|
||||
EventManager.get().post(new WalletHistoryStatusEvent(wallet, true, "Retrieving " + txids.size() + " transactions"));
|
||||
|
||||
for(String txid : txids) {
|
||||
batchRequest.add(txid, "blockchain.transaction.get", txid);
|
||||
|
@ -190,7 +191,7 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
|||
|
||||
return result;
|
||||
} catch(Exception e) {
|
||||
throw new ElectrumServerRpcException("Failed to retrieve transactions for txids: " + txids, e);
|
||||
throw new ElectrumServerRpcException("Failed to retrieve transactions for txids: " + txids.stream().map(txid -> "[" + txid.substring(0, 6) + "]").collect(Collectors.toList()), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -272,4 +273,65 @@ public class BatchedElectrumServerRpc implements ElectrumServerRpc {
|
|||
throw new ElectrumServerRpcException("Error broadcasting transaction", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getScriptHashesAbbreviation(Collection<String> scriptHashes) {
|
||||
List<String> sortedHashes = new ArrayList<>(scriptHashes);
|
||||
|
||||
if(scriptHashes.isEmpty()) {
|
||||
return "[]";
|
||||
}
|
||||
|
||||
List<List<String>> contiguous = splitToContiguous(sortedHashes);
|
||||
|
||||
String abbrev = "[";
|
||||
for(Iterator<List<String>> iter = contiguous.iterator(); iter.hasNext(); ) {
|
||||
List<String> range = iter.next();
|
||||
abbrev += range.get(0);
|
||||
if(range.size() > 1) {
|
||||
abbrev += "-" + range.get(range.size() - 1);
|
||||
}
|
||||
if(iter.hasNext()) {
|
||||
abbrev += ", ";
|
||||
}
|
||||
}
|
||||
abbrev += "]";
|
||||
|
||||
return abbrev;
|
||||
}
|
||||
|
||||
static List<List<String>> splitToContiguous(List<String> input) {
|
||||
List<List<String>> result = new ArrayList<>();
|
||||
int prev = 0;
|
||||
|
||||
int keyPurpose = getKeyPurpose(input.get(0));
|
||||
int index = getIndex(input.get(0));
|
||||
|
||||
for (int cur = 0; cur < input.size(); cur++) {
|
||||
if(getKeyPurpose(input.get(cur)) != keyPurpose || getIndex(input.get(cur)) != index) {
|
||||
result.add(input.subList(prev, cur));
|
||||
prev = cur;
|
||||
}
|
||||
index = getIndex(input.get(cur)) + 1;
|
||||
keyPurpose = getKeyPurpose(input.get(cur));
|
||||
}
|
||||
result.add(input.subList(prev, input.size()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int getKeyPurpose(String path) {
|
||||
List<ChildNumber> childNumbers = KeyDerivation.parsePath(path);
|
||||
if(childNumbers.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
return childNumbers.get(0).num();
|
||||
}
|
||||
|
||||
private static int getIndex(String path) {
|
||||
List<ChildNumber> childNumbers = KeyDerivation.parsePath(path);
|
||||
if(childNumbers.isEmpty()) {
|
||||
return -1;
|
||||
}
|
||||
return childNumbers.get(childNumbers.size() - 1).num();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -433,6 +433,8 @@ public class ElectrumServer {
|
|||
return blockTransactionHashes;
|
||||
} catch (IllegalStateException e) {
|
||||
throw new ServerException(e.getCause());
|
||||
} catch (ElectrumServerRpcException e) {
|
||||
throw new ServerException(e.getMessage(), e.getCause());
|
||||
} catch (Exception e) {
|
||||
throw new ServerException(e);
|
||||
}
|
||||
|
@ -493,6 +495,8 @@ public class ElectrumServer {
|
|||
return blockHeaderMap;
|
||||
} catch (IllegalStateException e) {
|
||||
throw new ServerException(e.getCause());
|
||||
} catch (ElectrumServerRpcException e) {
|
||||
throw new ServerException(e.getMessage(), e.getCause());
|
||||
} catch (Exception e) {
|
||||
throw new ServerException(e);
|
||||
}
|
||||
|
@ -561,6 +565,8 @@ public class ElectrumServer {
|
|||
return transactionMap;
|
||||
} catch (IllegalStateException e) {
|
||||
throw new ServerException(e.getCause());
|
||||
} catch (ElectrumServerRpcException e) {
|
||||
throw new ServerException(e.getMessage(), e.getCause());
|
||||
} catch (Exception e) {
|
||||
throw new ServerException(e);
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc {
|
|||
result.put(path, scriptHashTxes);
|
||||
} catch(Exception e) {
|
||||
if(failOnError) {
|
||||
throw new ElectrumServerRpcException("Failed to retrieve reference for path: " + path, e);
|
||||
throw new ElectrumServerRpcException("Failed to retrieve transaction history for path: " + path, e);
|
||||
}
|
||||
|
||||
result.put(path, new ScriptHashTx[] {ScriptHashTx.ERROR_TX});
|
||||
|
@ -104,7 +104,7 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc {
|
|||
result.put(path, scriptHashTxes);
|
||||
} catch(Exception e) {
|
||||
if(failOnError) {
|
||||
throw new ElectrumServerRpcException("Failed to retrieve reference for path: " + path, e);
|
||||
throw new ElectrumServerRpcException("Failed to retrieve mempool transactions for path: " + path, e);
|
||||
}
|
||||
|
||||
result.put(path, new ScriptHashTx[] {ScriptHashTx.ERROR_TX});
|
||||
|
@ -127,7 +127,7 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc {
|
|||
result.put(path, scriptHash);
|
||||
} catch(Exception e) {
|
||||
//Even if we have some successes, failure to subscribe for all script hashes will result in outdated wallet view. Don't proceed.
|
||||
throw new ElectrumServerRpcException("Failed to retrieve reference for path: " + path, e);
|
||||
throw new ElectrumServerRpcException("Failed to subscribe to path: " + path, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,6 +169,9 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc {
|
|||
String rawTxHex = new RetryLogic<String>(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());
|
||||
result.put(txid, rawTxHex);
|
||||
} catch(ServerException e) {
|
||||
//If there is an error with the server connection, don't keep trying - this may take too long given many txids
|
||||
throw new ElectrumServerRpcException("Failed to retrieve transaction for txid [" + txid.substring(0, 6) + "]", e);
|
||||
} catch(Exception e) {
|
||||
result.put(txid, Sha256Hash.ZERO_HASH.toString());
|
||||
}
|
||||
|
|
|
@ -9,15 +9,19 @@ import com.sparrowwallet.sparrow.CurrencyRate;
|
|||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import com.sparrowwallet.sparrow.control.*;
|
||||
import com.sparrowwallet.sparrow.event.*;
|
||||
import com.sparrowwallet.sparrow.io.Config;
|
||||
import com.sparrowwallet.sparrow.net.ExchangeSource;
|
||||
import javafx.application.Platform;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.TextArea;
|
||||
import javafx.scene.control.TreeItem;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
import org.controlsfx.control.MasterDetailPane;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -26,13 +30,18 @@ import java.io.FileOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class TransactionsController extends WalletFormController implements Initializable {
|
||||
private static final Logger log = LoggerFactory.getLogger(TransactionsController.class);
|
||||
|
||||
private static final DateFormat LOG_DATE_FORMAT = new SimpleDateFormat("[MMM dd HH:mm:ss]");
|
||||
|
||||
@FXML
|
||||
private CoinLabel balance;
|
||||
|
||||
|
@ -48,9 +57,15 @@ public class TransactionsController extends WalletFormController implements Init
|
|||
@FXML
|
||||
private CopyableLabel transactionCount;
|
||||
|
||||
@FXML
|
||||
private MasterDetailPane transactionsMasterDetail;
|
||||
|
||||
@FXML
|
||||
private TransactionsTreeTable transactionsTable;
|
||||
|
||||
@FXML
|
||||
private TextArea loadingLog;
|
||||
|
||||
@FXML
|
||||
private BalanceChart balanceChart;
|
||||
|
||||
|
@ -85,6 +100,10 @@ public class TransactionsController extends WalletFormController implements Init
|
|||
balanceChart.select((TransactionEntry)selectedItem.getValue());
|
||||
}
|
||||
});
|
||||
|
||||
transactionsMasterDetail.setShowDetailNode(Config.get().isShowLoadingLog());
|
||||
loadingLog.appendText("Wallet loading history for " + getWalletForm().getWallet().getName());
|
||||
loadingLog.setEditable(false);
|
||||
}
|
||||
|
||||
private void setFiatBalance(FiatLabel fiatLabel, CurrencyRate currencyRate, long balance) {
|
||||
|
@ -136,6 +155,15 @@ public class TransactionsController extends WalletFormController implements Init
|
|||
String.format(Locale.ENGLISH, "%d", value);
|
||||
}
|
||||
|
||||
private void logMessage(String logMessage) {
|
||||
if(logMessage != null) {
|
||||
logMessage = logMessage.replace("m/", "/");
|
||||
String date = LOG_DATE_FORMAT.format(new Date());
|
||||
String logLine = "\n" + date + " " + logMessage;
|
||||
Platform.runLater(() -> loadingLog.appendText(logLine));
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void walletNodesChanged(WalletNodesChangedEvent event) {
|
||||
if(event.getWallet().equals(walletForm.getWallet())) {
|
||||
|
@ -200,6 +228,18 @@ public class TransactionsController extends WalletFormController implements Init
|
|||
@Subscribe
|
||||
public void walletHistoryStatus(WalletHistoryStatusEvent event) {
|
||||
transactionsTable.updateHistoryStatus(event);
|
||||
|
||||
if(event.getWallet() != null && getWalletForm().getWallet() == event.getWallet()) {
|
||||
String logMessage = event.getStatusMessage();
|
||||
if(logMessage == null) {
|
||||
if(event instanceof WalletHistoryFinishedEvent) {
|
||||
logMessage = "Finished loading.";
|
||||
} else if(event instanceof WalletHistoryFailedEvent) {
|
||||
logMessage = event.getErrorMessage();
|
||||
}
|
||||
}
|
||||
logMessage(logMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
@ -233,4 +273,9 @@ public class TransactionsController extends WalletFormController implements Init
|
|||
public void includeMempoolOutputsChangedEvent(IncludeMempoolOutputsChangedEvent event) {
|
||||
walletHistoryChanged(new WalletHistoryChangedEvent(getWalletForm().getWallet(), getWalletForm().getStorage(), Collections.emptyList()));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void loadingLogChanged(LoadingLogChangedEvent event) {
|
||||
transactionsMasterDetail.setShowDetailNode(event.isVisible());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,6 +88,7 @@
|
|||
<CheckMenuItem fx:id="openWalletsInNewWindows" mnemonicParsing="false" text="Open Wallets in New Windows" onAction="#openWalletsInNewWindows"/>
|
||||
<CheckMenuItem fx:id="hideEmptyUsedAddresses" mnemonicParsing="false" text="Hide Empty Used Addresses" onAction="#hideEmptyUsedAddresses"/>
|
||||
<CheckMenuItem fx:id="useHdCameraResolution" mnemonicParsing="false" text="Use HD Camera Resolution" onAction="#useHdCameraResolution"/>
|
||||
<CheckMenuItem fx:id="showLoadingLog" mnemonicParsing="false" text="Show Wallet Loading Log" onAction="#showLoadingLog" />
|
||||
<CheckMenuItem fx:id="showTxHex" mnemonicParsing="false" text="Show Transaction Hex" onAction="#showTxHex"/>
|
||||
<SeparatorMenuItem />
|
||||
<MenuItem fx:id="minimizeToTray" mnemonicParsing="false" text="Minimize to System Tray" accelerator="Shortcut+Y" onAction="#minimizeToTray"/>
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<?import com.sparrowwallet.sparrow.control.FiatLabel?>
|
||||
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
||||
<?import org.controlsfx.glyphfont.Glyph?>
|
||||
<?import org.controlsfx.control.MasterDetailPane?>
|
||||
|
||||
<BorderPane stylesheets="@transactions.css, @wallet.css, @../general.css" styleClass="wallet-pane" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.wallet.TransactionsController">
|
||||
<center>
|
||||
|
@ -61,7 +62,14 @@
|
|||
</yAxis>
|
||||
</BalanceChart>
|
||||
</GridPane>
|
||||
<TransactionsTreeTable fx:id="transactionsTable" VBox.vgrow="ALWAYS" />
|
||||
<MasterDetailPane fx:id="transactionsMasterDetail" detailSide="BOTTOM" VBox.vgrow="ALWAYS">
|
||||
<masterNode>
|
||||
<TransactionsTreeTable fx:id="transactionsTable" />
|
||||
</masterNode>
|
||||
<detailNode>
|
||||
<TextArea fx:id="loadingLog" styleClass="readonly,fixed-width" />
|
||||
</detailNode>
|
||||
</MasterDetailPane>
|
||||
</VBox>
|
||||
</center>
|
||||
</BorderPane>
|
||||
|
|
Loading…
Reference in a new issue