diff --git a/src/main/java/com/sparrowwallet/sparrow/AppController.java b/src/main/java/com/sparrowwallet/sparrow/AppController.java index ab5da962..57720a6f 100644 --- a/src/main/java/com/sparrowwallet/sparrow/AppController.java +++ b/src/main/java/com/sparrowwallet/sparrow/AppController.java @@ -79,6 +79,7 @@ public class AppController implements Initializable { public static final double TAB_LABEL_GRAPHIC_OPACITY_ACTIVE = 0.95; public static final String LOADING_TRANSACTIONS_MESSAGE = "Loading wallet, select Transactions tab to view..."; public static final String CONNECTION_FAILED_PREFIX = "Connection failed: "; + public static final String TRYING_ANOTHER_SERVER_MESSAGE = "trying another server..."; @FXML private MenuItem saveTransaction; @@ -1539,7 +1540,9 @@ public class AppController implements Initializable { @Subscribe public void connectionStart(ConnectionStartEvent event) { - statusUpdated(new StatusEvent(event.getStatus(), 120)); + if(!statusBar.getText().contains(TRYING_ANOTHER_SERVER_MESSAGE)) { + statusUpdated(new StatusEvent(event.getStatus(), 120)); + } } @Subscribe @@ -1558,12 +1561,15 @@ public class AppController implements Initializable { @Subscribe public void disconnection(DisconnectionEvent event) { serverToggle.setDisable(false); - if(!AppServices.isConnecting() && !AppServices.isConnected() && !statusBar.getText().startsWith(CONNECTION_FAILED_PREFIX)) { + if(!AppServices.isConnecting() && !AppServices.isConnected() && !statusBar.getText().startsWith(CONNECTION_FAILED_PREFIX) && !statusBar.getText().contains(TRYING_ANOTHER_SERVER_MESSAGE)) { statusUpdated(new StatusEvent("Disconnected")); } if(statusTimeline == null || statusTimeline.getStatus() != Animation.Status.RUNNING) { statusBar.setProgress(0); } + for(Wallet wallet : getOpenWallets().keySet()) { + tabLabelStopAnimation(wallet); + } } @Subscribe @@ -1620,6 +1626,9 @@ public class AppController implements Initializable { public void walletHistoryFailed(WalletHistoryFailedEvent event) { walletHistoryFinished(new WalletHistoryFinishedEvent(event.getWallet())); tabs.getTabs().stream().filter(tab -> tab.getUserData() instanceof WalletTabData && ((WalletTabData) tab.getUserData()).getWallet() == event.getWallet()).forEach(this::tabLabelAddFailure); + if(getOpenWallets().containsKey(event.getWallet())) { + statusUpdated(new StatusEvent("Error retrieving wallet history" + (Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER ? ", " + TRYING_ANOTHER_SERVER_MESSAGE : ""))); + } } @Subscribe diff --git a/src/main/java/com/sparrowwallet/sparrow/AppServices.java b/src/main/java/com/sparrowwallet/sparrow/AppServices.java index 569b5107..99983478 100644 --- a/src/main/java/com/sparrowwallet/sparrow/AppServices.java +++ b/src/main/java/com/sparrowwallet/sparrow/AppServices.java @@ -250,8 +250,7 @@ public class AppServices { onlineProperty.addListener(onlineServicesListener); if(Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER) { - List otherServers = Arrays.stream(PublicElectrumServer.values()).map(PublicElectrumServer::getUrl).filter(url -> !url.equals(Config.get().getPublicElectrumServer())).collect(Collectors.toList()); - Config.get().setPublicElectrumServer(otherServers.get(new Random().nextInt(otherServers.size()))); + Config.get().changePublicServer(); connectionService.setPeriod(Duration.seconds(PUBLIC_SERVER_RETRY_PERIOD_SECS)); } @@ -715,4 +714,14 @@ public class AppServices { connectionService.start(); } } + + @Subscribe + public void walletHistoryFailed(WalletHistoryFailedEvent event) { + if(Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER && connectionService != null && connectionService.isRunning()) { + onlineProperty.set(false); + log.info("Connection to " + Config.get().getServerAddress() + " failed, reconnecting to another server..."); + Config.get().changePublicServer(); + onlineProperty.set(true); + } + } } diff --git a/src/main/java/com/sparrowwallet/sparrow/io/Config.java b/src/main/java/com/sparrowwallet/sparrow/io/Config.java index f7231a59..625ea1ee 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/Config.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/Config.java @@ -11,8 +11,11 @@ import org.slf4j.LoggerFactory; import java.io.*; import java.lang.reflect.Type; +import java.util.Arrays; import java.util.Currency; import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; public class Config { private static final Logger log = LoggerFactory.getLogger(Config.class); @@ -333,6 +336,11 @@ public class Config { flush(); } + public void changePublicServer() { + List otherServers = Arrays.stream(PublicElectrumServer.values()).map(PublicElectrumServer::getUrl).filter(url -> !url.equals(getPublicElectrumServer())).collect(Collectors.toList()); + setPublicElectrumServer(otherServers.get(new Random().nextInt(otherServers.size()))); + } + public String getCoreServer() { return coreServer; } diff --git a/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java b/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java index 14dfb288..94104d8b 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java @@ -19,7 +19,7 @@ import java.util.concurrent.atomic.AtomicLong; public class SimpleElectrumServerRpc implements ElectrumServerRpc { private static final Logger log = LoggerFactory.getLogger(SimpleElectrumServerRpc.class); private static final int MAX_TARGET_BLOCKS = 25; - private static final int MAX_RETRIES = 10; + private static final int MAX_RETRIES = 5; private static final int RETRY_DELAY = 1; private final AtomicLong idCounter = new AtomicLong(); diff --git a/src/main/java/com/sparrowwallet/sparrow/net/TcpTransport.java b/src/main/java/com/sparrowwallet/sparrow/net/TcpTransport.java index c04eebdf..db192213 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/TcpTransport.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/TcpTransport.java @@ -24,6 +24,7 @@ public class TcpTransport implements Transport, Closeable { public static final int DEFAULT_PORT = 50001; private static final int[] READ_TIMEOUT_SECS = {3, 8, 16, 34}; + public static final int SOCKET_READ_TIMEOUT = 60000; protected final HostAndPort server; protected final SocketFactory socketFactory; @@ -107,8 +108,9 @@ public class TcpTransport implements Transport, Closeable { try { readingCondition.await(); } catch(InterruptedException e) { - //Restore interrupt status and continue + //Restore interrupt status and break Thread.currentThread().interrupt(); + break; } } @@ -192,6 +194,7 @@ public class TcpTransport implements Transport, Closeable { public void connect() throws ServerException { try { socket = createSocket(); + socket.setSoTimeout(SOCKET_READ_TIMEOUT); running = true; } catch(SSLHandshakeException e) { throw new TlsServerException(server, e);