mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-24 12:46:45 +00:00
add support for configuring server aliases, and switching servers via the tools menu
This commit is contained in:
parent
bacbdb848b
commit
1f67692727
17 changed files with 649 additions and 140 deletions
|
@ -182,6 +182,9 @@ public class AppController implements Initializable {
|
||||||
@FXML
|
@FXML
|
||||||
private MenuItem showPayNym;
|
private MenuItem showPayNym;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Menu switchServer;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CheckMenuItem preventSleep;
|
private CheckMenuItem preventSleep;
|
||||||
private static final BooleanProperty preventSleepProperty = new SimpleBooleanProperty();
|
private static final BooleanProperty preventSleepProperty = new SimpleBooleanProperty();
|
||||||
|
@ -367,6 +370,7 @@ public class AppController implements Initializable {
|
||||||
findMixingPartner.setDisable(exportWallet.isDisable() || getSelectedWalletForm() == null || !SorobanServices.canWalletMix(getSelectedWalletForm().getWallet()) || !newValue);
|
findMixingPartner.setDisable(exportWallet.isDisable() || getSelectedWalletForm() == null || !SorobanServices.canWalletMix(getSelectedWalletForm().getWallet()) || !newValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
configureSwitchServer();
|
||||||
setServerType(Config.get().getServerType());
|
setServerType(Config.get().getServerType());
|
||||||
serverToggle.setSelected(isConnected());
|
serverToggle.setSelected(isConnected());
|
||||||
serverToggle.setDisable(Config.get().getServerType() == null);
|
serverToggle.setDisable(Config.get().getServerType() == null);
|
||||||
|
@ -408,8 +412,7 @@ public class AppController implements Initializable {
|
||||||
WelcomeDialog welcomeDialog = new WelcomeDialog();
|
WelcomeDialog welcomeDialog = new WelcomeDialog();
|
||||||
Optional<Mode> optionalMode = welcomeDialog.showAndWait();
|
Optional<Mode> optionalMode = welcomeDialog.showAndWait();
|
||||||
if(optionalMode.isPresent() && optionalMode.get().equals(Mode.ONLINE)) {
|
if(optionalMode.isPresent() && optionalMode.get().equals(Mode.ONLINE)) {
|
||||||
PreferencesDialog preferencesDialog = new PreferencesDialog(PreferenceGroup.SERVER);
|
openPreferences(PreferenceGroup.SERVER);
|
||||||
preferencesDialog.showAndWait();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -902,7 +905,7 @@ public class AppController implements Initializable {
|
||||||
|
|
||||||
private String getServerToggleTooltipText(Integer currentBlockHeight) {
|
private String getServerToggleTooltipText(Integer currentBlockHeight) {
|
||||||
if(AppServices.isConnected()) {
|
if(AppServices.isConnected()) {
|
||||||
return "Connected to " + Config.get().getServerAddress() + (currentBlockHeight != null ? " at height " + currentBlockHeight : "") +
|
return "Connected to " + Config.get().getServerDisplayName() + (currentBlockHeight != null ? " at height " + currentBlockHeight : "") +
|
||||||
(Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER ? "\nWarning! You are connected to a public server and sharing your transaction data with it.\nFor better privacy, consider using your own Bitcoin Core node or private Electrum server." : "");
|
(Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER ? "\nWarning! You are connected to a public server and sharing your transaction data with it.\nFor better privacy, consider using your own Bitcoin Core node or private Electrum server." : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1284,13 +1287,17 @@ public class AppController implements Initializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openPreferences(ActionEvent event) {
|
public void openPreferences(ActionEvent event) {
|
||||||
PreferencesDialog preferencesDialog = new PreferencesDialog();
|
openPreferences(PreferenceGroup.GENERAL);
|
||||||
preferencesDialog.showAndWait();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void openServerPreferences(ActionEvent event) {
|
public void openServerPreferences(ActionEvent event) {
|
||||||
PreferencesDialog preferencesDialog = new PreferencesDialog(PreferenceGroup.SERVER);
|
openPreferences(PreferenceGroup.SERVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openPreferences(PreferenceGroup preferenceGroup) {
|
||||||
|
PreferencesDialog preferencesDialog = new PreferencesDialog(preferenceGroup);
|
||||||
preferencesDialog.showAndWait();
|
preferencesDialog.showAndWait();
|
||||||
|
configureSwitchServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void signVerifyMessage(ActionEvent event) {
|
public void signVerifyMessage(ActionEvent event) {
|
||||||
|
@ -1996,6 +2003,48 @@ public class AppController implements Initializable {
|
||||||
return contextMenu;
|
return contextMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void configureSwitchServer() {
|
||||||
|
switchServer.getItems().clear();
|
||||||
|
|
||||||
|
Config config = Config.get();
|
||||||
|
if(config.getServerType() == ServerType.BITCOIN_CORE && config.getRecentCoreServers() != null && config.getRecentCoreServers().size() > 1) {
|
||||||
|
for(Server server : config.getRecentCoreServers()) {
|
||||||
|
switchServer.getItems().add(getSwitchServerMenuItem(ServerType.BITCOIN_CORE, server));
|
||||||
|
}
|
||||||
|
} else if(config.getServerType() == ServerType.ELECTRUM_SERVER && config.getRecentElectrumServers() != null && config.getRecentElectrumServers().size() > 1) {
|
||||||
|
for(Server server : config.getRecentElectrumServers()) {
|
||||||
|
switchServer.getItems().add(getSwitchServerMenuItem(ServerType.ELECTRUM_SERVER, server));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switchServer.setVisible(!switchServer.getItems().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckMenuItem getSwitchServerMenuItem(ServerType serverType, Server server) {
|
||||||
|
CheckMenuItem checkMenuItem = new CheckMenuItem(server.getDisplayName());
|
||||||
|
boolean selected = (serverType == ServerType.BITCOIN_CORE ? server.equals(Config.get().getCoreServer()) : server.equals(Config.get().getElectrumServer()));
|
||||||
|
checkMenuItem.setSelected(selected);
|
||||||
|
checkMenuItem.setOnAction(event -> {
|
||||||
|
if(!selected) {
|
||||||
|
boolean online = onlineProperty().get();
|
||||||
|
onlineProperty().set(false);
|
||||||
|
if(serverType == ServerType.BITCOIN_CORE) {
|
||||||
|
Config.get().setCoreServer(server);
|
||||||
|
} else if(serverType == ServerType.ELECTRUM_SERVER) {
|
||||||
|
Config.get().setElectrumServer(server);
|
||||||
|
}
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
onlineProperty().set(online);
|
||||||
|
configureSwitchServer();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
checkMenuItem.setSelected(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return checkMenuItem;
|
||||||
|
}
|
||||||
|
|
||||||
public void setServerType(ServerType serverType) {
|
public void setServerType(ServerType serverType) {
|
||||||
if(serverType == ServerType.PUBLIC_ELECTRUM_SERVER && !serverToggle.getStyleClass().contains("public-server")) {
|
if(serverType == ServerType.PUBLIC_ELECTRUM_SERVER && !serverToggle.getStyleClass().contains("public-server")) {
|
||||||
serverToggle.getStyleClass().add("public-server");
|
serverToggle.getStyleClass().add("public-server");
|
||||||
|
@ -2424,11 +2473,12 @@ public class AppController implements Initializable {
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void connection(ConnectionEvent event) {
|
public void connection(ConnectionEvent event) {
|
||||||
String status = "Connected to " + Config.get().getServerAddress() + " at height " + event.getBlockHeight();
|
String status = "Connected to " + Config.get().getServerDisplayName() + " at height " + event.getBlockHeight();
|
||||||
statusUpdated(new StatusEvent(status));
|
statusUpdated(new StatusEvent(status));
|
||||||
setServerToggleTooltip(event.getBlockHeight());
|
setServerToggleTooltip(event.getBlockHeight());
|
||||||
serverToggleStopAnimation();
|
serverToggleStopAnimation();
|
||||||
setTorIcon();
|
setTorIcon();
|
||||||
|
configureSwitchServer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
|
|
|
@ -203,7 +203,7 @@ public class AppServices {
|
||||||
|
|
||||||
private void restartServices() {
|
private void restartServices() {
|
||||||
Config config = Config.get();
|
Config config = Config.get();
|
||||||
if(config.hasServerAddress()) {
|
if(config.hasServer()) {
|
||||||
restartService(connectionService);
|
restartService(connectionService);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ public class AppServices {
|
||||||
connectionService.setOnRunning(workerStateEvent -> {
|
connectionService.setOnRunning(workerStateEvent -> {
|
||||||
connectionService.setDelay(Duration.ZERO);
|
connectionService.setDelay(Duration.ZERO);
|
||||||
if(!ElectrumServer.isConnected()) {
|
if(!ElectrumServer.isConnected()) {
|
||||||
EventManager.get().post(new ConnectionStartEvent(Config.get().getServerAddress()));
|
EventManager.get().post(new ConnectionStartEvent(Config.get().getServerDisplayName()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connectionService.setOnSucceeded(successEvent -> {
|
connectionService.setOnSucceeded(successEvent -> {
|
||||||
|
@ -1157,7 +1157,9 @@ public class AppServices {
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void requestConnect(RequestConnectEvent event) {
|
public void requestConnect(RequestConnectEvent event) {
|
||||||
onlineProperty.set(true);
|
if(Config.get().hasServer()) {
|
||||||
|
onlineProperty.set(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
|
@ -1209,7 +1211,7 @@ public class AppServices {
|
||||||
public void walletHistoryFailed(WalletHistoryFailedEvent event) {
|
public void walletHistoryFailed(WalletHistoryFailedEvent event) {
|
||||||
if(Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER && isConnected()) {
|
if(Config.get().getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER && isConnected()) {
|
||||||
onlineProperty.set(false);
|
onlineProperty.set(false);
|
||||||
log.warn("Failed to fetch wallet history from " + Config.get().getServerAddress() + ", reconnecting to another server...");
|
log.warn("Failed to fetch wallet history from " + Config.get().getServerDisplayName() + ", reconnecting to another server...");
|
||||||
Config.get().changePublicServer();
|
Config.get().changePublicServer();
|
||||||
onlineProperty.set(true);
|
onlineProperty.set(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ public class MainApp extends Application {
|
||||||
} else if(Network.get() == Network.MAINNET) {
|
} else if(Network.get() == Network.MAINNET) {
|
||||||
Config.get().setServerType(ServerType.PUBLIC_ELECTRUM_SERVER);
|
Config.get().setServerType(ServerType.PUBLIC_ELECTRUM_SERVER);
|
||||||
List<PublicElectrumServer> servers = PublicElectrumServer.getServers();
|
List<PublicElectrumServer> servers = PublicElectrumServer.getServers();
|
||||||
Config.get().setPublicElectrumServer(servers.get(new Random().nextInt(servers.size())).getUrl());
|
Config.get().setPublicElectrumServer(servers.get(new Random().nextInt(servers.size())).getServer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@ public class FontAwesome5 extends GlyphFont {
|
||||||
SNOWFLAKE('\uf2dc'),
|
SNOWFLAKE('\uf2dc'),
|
||||||
SORT_NUMERIC_DOWN('\uf162'),
|
SORT_NUMERIC_DOWN('\uf162'),
|
||||||
SUN('\uf185'),
|
SUN('\uf185'),
|
||||||
|
TAG('\uf02b'),
|
||||||
THEATER_MASKS('\uf630'),
|
THEATER_MASKS('\uf630'),
|
||||||
TIMES_CIRCLE('\uf057'),
|
TIMES_CIRCLE('\uf057'),
|
||||||
TOGGLE_OFF('\uf204'),
|
TOGGLE_OFF('\uf204'),
|
||||||
|
|
|
@ -53,14 +53,14 @@ public class Config {
|
||||||
private Boolean hdCapture;
|
private Boolean hdCapture;
|
||||||
private String webcamDevice;
|
private String webcamDevice;
|
||||||
private ServerType serverType;
|
private ServerType serverType;
|
||||||
private String publicElectrumServer;
|
private Server publicElectrumServer;
|
||||||
private String coreServer;
|
private Server coreServer;
|
||||||
private List<String> recentCoreServers;
|
private List<Server> recentCoreServers;
|
||||||
private CoreAuthType coreAuthType;
|
private CoreAuthType coreAuthType;
|
||||||
private File coreDataDir;
|
private File coreDataDir;
|
||||||
private String coreAuth;
|
private String coreAuth;
|
||||||
private String electrumServer;
|
private Server electrumServer;
|
||||||
private List<String> recentElectrumServers;
|
private List<Server> recentElectrumServers;
|
||||||
private File electrumServerCert;
|
private File electrumServerCert;
|
||||||
private boolean useProxy;
|
private boolean useProxy;
|
||||||
private String proxyServer;
|
private String proxyServer;
|
||||||
|
@ -77,6 +77,8 @@ public class Config {
|
||||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||||
gsonBuilder.registerTypeAdapter(File.class, new FileSerializer());
|
gsonBuilder.registerTypeAdapter(File.class, new FileSerializer());
|
||||||
gsonBuilder.registerTypeAdapter(File.class, new FileDeserializer());
|
gsonBuilder.registerTypeAdapter(File.class, new FileDeserializer());
|
||||||
|
gsonBuilder.registerTypeAdapter(Server.class, new ServerSerializer());
|
||||||
|
gsonBuilder.registerTypeAdapter(Server.class, new ServerDeserializer());
|
||||||
return gsonBuilder.setPrettyPrinting().disableHtmlEscaping().create();
|
return gsonBuilder.setPrettyPrinting().disableHtmlEscaping().create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,14 +364,18 @@ public class Config {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasServerAddress() {
|
public boolean hasServer() {
|
||||||
return getServerAddress() != null && !getServerAddress().isEmpty();
|
return getServer() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getServerAddress() {
|
public Server getServer() {
|
||||||
return getServerType() == ServerType.BITCOIN_CORE ? getCoreServer() : (getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER ? getPublicElectrumServer() : getElectrumServer());
|
return getServerType() == ServerType.BITCOIN_CORE ? getCoreServer() : (getServerType() == ServerType.PUBLIC_ELECTRUM_SERVER ? getPublicElectrumServer() : getElectrumServer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getServerDisplayName() {
|
||||||
|
return getServer() == null ? "server" : getServer().getDisplayName();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean requiresInternalTor() {
|
public boolean requiresInternalTor() {
|
||||||
if(isUseProxy()) {
|
if(isUseProxy()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -379,57 +385,71 @@ public class Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean requiresTor() {
|
public boolean requiresTor() {
|
||||||
if(!hasServerAddress()) {
|
if(!hasServer()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Protocol protocol = Protocol.getProtocol(getServerAddress());
|
return getServer().isOnionAddress();
|
||||||
if(protocol == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return protocol.isOnionAddress(protocol.getServerHostAndPort(getServerAddress()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPublicElectrumServer() {
|
public Server getPublicElectrumServer() {
|
||||||
return publicElectrumServer;
|
return publicElectrumServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPublicElectrumServer(String publicElectrumServer) {
|
public void setPublicElectrumServer(Server publicElectrumServer) {
|
||||||
this.publicElectrumServer = publicElectrumServer;
|
this.publicElectrumServer = publicElectrumServer;
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void changePublicServer() {
|
public void changePublicServer() {
|
||||||
List<String> otherServers = PublicElectrumServer.getServers().stream().map(PublicElectrumServer::getUrl).filter(url -> !url.equals(getPublicElectrumServer())).collect(Collectors.toList());
|
List<Server> otherServers = PublicElectrumServer.getServers().stream().map(PublicElectrumServer::getServer).filter(server -> !server.equals(getPublicElectrumServer())).collect(Collectors.toList());
|
||||||
if(!otherServers.isEmpty()) {
|
if(!otherServers.isEmpty()) {
|
||||||
setPublicElectrumServer(otherServers.get(new Random().nextInt(otherServers.size())));
|
setPublicElectrumServer(otherServers.get(new Random().nextInt(otherServers.size())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCoreServer() {
|
public Server getCoreServer() {
|
||||||
return coreServer;
|
return coreServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCoreServer(String coreServer) {
|
public void setCoreServer(Server coreServer) {
|
||||||
this.coreServer = coreServer;
|
this.coreServer = coreServer;
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getRecentCoreServers() {
|
public List<Server> getRecentCoreServers() {
|
||||||
return recentCoreServers;
|
return recentCoreServers == null ? new ArrayList<>() : recentCoreServers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addRecentCoreServer(String coreServer) {
|
public boolean addRecentCoreServer(Server coreServer) {
|
||||||
if(recentCoreServers == null) {
|
if(recentCoreServers == null) {
|
||||||
recentCoreServers = new ArrayList<>();
|
recentCoreServers = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!recentCoreServers.contains(coreServer)) {
|
int index = getRecentCoreServers().indexOf(coreServer);
|
||||||
recentCoreServers.stream().filter(url -> Objects.equals(Protocol.getHost(url), Protocol.getHost(coreServer)))
|
if(index < 0) {
|
||||||
.findFirst().ifPresent(existingUrl -> recentCoreServers.remove(existingUrl));
|
recentCoreServers.removeIf(server -> server.getHost().equals(coreServer.getHost()) && server.getAlias() == null);
|
||||||
recentCoreServers.add(coreServer);
|
recentCoreServers.add(coreServer);
|
||||||
flush();
|
flush();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeRecentCoreServer(Server server) {
|
||||||
|
int index = getRecentCoreServers().indexOf(server);
|
||||||
|
if(index >= 0) {
|
||||||
|
recentCoreServers.remove(index);
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCoreServerAlias(Server server) {
|
||||||
|
int index = getRecentCoreServers().indexOf(server);
|
||||||
|
if(index >= 0) {
|
||||||
|
recentCoreServers.set(index, server);
|
||||||
|
flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,37 +480,59 @@ public class Config {
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getElectrumServer() {
|
public Server getElectrumServer() {
|
||||||
return electrumServer;
|
return electrumServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setElectrumServer(String electrumServer) {
|
public void setElectrumServer(Server electrumServer) {
|
||||||
this.electrumServer = electrumServer;
|
this.electrumServer = electrumServer;
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getRecentElectrumServers() {
|
public List<Server> getRecentElectrumServers() {
|
||||||
return recentElectrumServers;
|
return recentElectrumServers == null ? new ArrayList<>() : recentElectrumServers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addRecentServer() {
|
public boolean addRecentServer() {
|
||||||
if(serverType == ServerType.BITCOIN_CORE && coreServer != null) {
|
if(serverType == ServerType.BITCOIN_CORE && coreServer != null) {
|
||||||
addRecentCoreServer(coreServer);
|
return addRecentCoreServer(coreServer);
|
||||||
} else if(serverType == ServerType.ELECTRUM_SERVER && electrumServer != null) {
|
} else if(serverType == ServerType.ELECTRUM_SERVER && electrumServer != null) {
|
||||||
addRecentElectrumServer(electrumServer);
|
return addRecentElectrumServer(electrumServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addRecentElectrumServer(String electrumServer) {
|
public boolean addRecentElectrumServer(Server electrumServer) {
|
||||||
if(recentElectrumServers == null) {
|
if(recentElectrumServers == null) {
|
||||||
recentElectrumServers = new ArrayList<>();
|
recentElectrumServers = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!recentElectrumServers.contains(electrumServer)) {
|
int index = getRecentElectrumServers().indexOf(electrumServer);
|
||||||
recentElectrumServers.stream().filter(url -> Objects.equals(Protocol.getHost(url), Protocol.getHost(electrumServer)))
|
if(index < 0) {
|
||||||
.findFirst().ifPresent(existingUrl -> recentElectrumServers.remove(existingUrl));
|
recentElectrumServers.removeIf(server -> server.getHost().equals(electrumServer.getHost()) && server.getAlias() == null);
|
||||||
recentElectrumServers.add(electrumServer);
|
recentElectrumServers.add(electrumServer);
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeRecentElectrumServer(Server server) {
|
||||||
|
int index = getRecentElectrumServers().indexOf(server);
|
||||||
|
if(index >= 0) {
|
||||||
|
recentElectrumServers.remove(index);
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setElectrumServerAlias(Server server) {
|
||||||
|
int index = getRecentElectrumServers().indexOf(server);
|
||||||
|
if(index >= 0) {
|
||||||
|
recentElectrumServers.set(index, server);
|
||||||
|
flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,4 +637,18 @@ public class Config {
|
||||||
return new File(json.getAsJsonPrimitive().getAsString());
|
return new File(json.getAsJsonPrimitive().getAsString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ServerSerializer implements JsonSerializer<Server> {
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(Server src, Type typeOfSrc, JsonSerializationContext context) {
|
||||||
|
return new JsonPrimitive(src.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ServerDeserializer implements JsonDeserializer<Server> {
|
||||||
|
@Override
|
||||||
|
public Server deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||||
|
return Server.fromString(json.getAsJsonPrimitive().getAsString());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
99
src/main/java/com/sparrowwallet/sparrow/io/Server.java
Normal file
99
src/main/java/com/sparrowwallet/sparrow/io/Server.java
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
package com.sparrowwallet.sparrow.io;
|
||||||
|
|
||||||
|
import com.google.common.net.HostAndPort;
|
||||||
|
import com.sparrowwallet.sparrow.net.Protocol;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class Server {
|
||||||
|
private final String url;
|
||||||
|
private final String alias;
|
||||||
|
|
||||||
|
public Server(String url) {
|
||||||
|
this(url, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Server(String url, String alias) {
|
||||||
|
if(url == null) {
|
||||||
|
throw new IllegalArgumentException("Url cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(url.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("Url cannot be empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Protocol.getProtocol(url) == null) {
|
||||||
|
throw new IllegalArgumentException("Unknown protocol for url " + url + ", must be one of " + Arrays.toString(Protocol.values()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Protocol.getHost(url) == null) {
|
||||||
|
throw new IllegalArgumentException("Cannot determine host for url " + url);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(alias != null && alias.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("Server alias cannot be an empty string");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.url = url;
|
||||||
|
this.alias = alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Protocol getProtocol() {
|
||||||
|
return Protocol.getProtocol(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HostAndPort getHostAndPort() {
|
||||||
|
return getProtocol().getServerHostAndPort(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHost() {
|
||||||
|
return getHostAndPort().getHost();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOnionAddress() {
|
||||||
|
return Protocol.isOnionAddress(getHostAndPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAlias() {
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayName() {
|
||||||
|
return alias == null ? url : alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return url + (alias == null ? "" : "|" + alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Server fromString(String server) {
|
||||||
|
String[] parts = server.split("\\|");
|
||||||
|
if(parts.length >= 2) {
|
||||||
|
return new Server(parts[0], parts[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Server(parts[0], null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if(this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Server server = (Server)o;
|
||||||
|
return url.equals(server.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return url.hashCode();
|
||||||
|
}
|
||||||
|
}
|
|
@ -143,8 +143,8 @@ public class Bwt {
|
||||||
bwtConfig.electrumSkipMerkle = true;
|
bwtConfig.electrumSkipMerkle = true;
|
||||||
|
|
||||||
Config config = Config.get();
|
Config config = Config.get();
|
||||||
bwtConfig.bitcoindUrl = config.getCoreServer();
|
if(config.getCoreServer() != null) {
|
||||||
if(bwtConfig.bitcoindUrl != null) {
|
bwtConfig.bitcoindUrl = config.getCoreServer().getUrl();
|
||||||
try {
|
try {
|
||||||
HostAndPort hostAndPort = Protocol.HTTP.getServerHostAndPort(bwtConfig.bitcoindUrl);
|
HostAndPort hostAndPort = Protocol.HTTP.getServerHostAndPort(bwtConfig.bitcoindUrl);
|
||||||
if(hostAndPort.getHost().endsWith(".local")) {
|
if(hostAndPort.getHost().endsWith(".local")) {
|
||||||
|
@ -308,7 +308,7 @@ public class Bwt {
|
||||||
Bwt.this.shutdown();
|
Bwt.this.shutdown();
|
||||||
terminating = false;
|
terminating = false;
|
||||||
} else {
|
} else {
|
||||||
Platform.runLater(() -> EventManager.get().post(new BwtBootStatusEvent("Connecting to Bitcoin Core node at " + Config.get().getCoreServer() + "...")));
|
Platform.runLater(() -> EventManager.get().post(new BwtBootStatusEvent("Connecting to Bitcoin Core node " + Config.get().getServerDisplayName() + "...")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.sparrowwallet.sparrow.net;
|
package com.sparrowwallet.sparrow.net;
|
||||||
|
|
||||||
import com.github.arteam.simplejsonrpc.client.Transport;
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
import com.google.common.net.HostAndPort;
|
import com.google.common.net.HostAndPort;
|
||||||
import com.sparrowwallet.drongo.KeyPurpose;
|
import com.sparrowwallet.drongo.KeyPurpose;
|
||||||
|
@ -15,6 +14,7 @@ import com.sparrowwallet.sparrow.AppServices;
|
||||||
import com.sparrowwallet.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.event.*;
|
import com.sparrowwallet.sparrow.event.*;
|
||||||
import com.sparrowwallet.sparrow.io.Config;
|
import com.sparrowwallet.sparrow.io.Config;
|
||||||
|
import com.sparrowwallet.sparrow.io.Server;
|
||||||
import com.sparrowwallet.sparrow.paynym.PayNym;
|
import com.sparrowwallet.sparrow.paynym.PayNym;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.property.IntegerProperty;
|
import javafx.beans.property.IntegerProperty;
|
||||||
|
@ -51,7 +51,7 @@ public class ElectrumServer {
|
||||||
|
|
||||||
private static final Map<String, List<String>> subscribedScriptHashes = Collections.synchronizedMap(new HashMap<>());
|
private static final Map<String, List<String>> subscribedScriptHashes = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
|
||||||
private static String previousServerAddress;
|
private static Server previousServer;
|
||||||
|
|
||||||
private static Map<String, String> retrievedScriptHashes = Collections.synchronizedMap(new HashMap<>());
|
private static Map<String, String> retrievedScriptHashes = Collections.synchronizedMap(new HashMap<>());
|
||||||
|
|
||||||
|
@ -59,14 +59,14 @@ public class ElectrumServer {
|
||||||
|
|
||||||
private static ElectrumServerRpc electrumServerRpc = new SimpleElectrumServerRpc();
|
private static ElectrumServerRpc electrumServerRpc = new SimpleElectrumServerRpc();
|
||||||
|
|
||||||
private static String bwtElectrumServer;
|
private static Server bwtElectrumServer;
|
||||||
|
|
||||||
private static final Pattern RPC_WALLET_LOADING_PATTERN = Pattern.compile(".*\"(Wallet loading failed:[^\"]*)\".*");
|
private static final Pattern RPC_WALLET_LOADING_PATTERN = Pattern.compile(".*\"(Wallet loading failed:[^\"]*)\".*");
|
||||||
|
|
||||||
private static synchronized CloseableTransport getTransport() throws ServerException {
|
private static synchronized CloseableTransport getTransport() throws ServerException {
|
||||||
if(transport == null) {
|
if(transport == null) {
|
||||||
try {
|
try {
|
||||||
String electrumServer = null;
|
Server electrumServer = null;
|
||||||
File electrumServerCert = null;
|
File electrumServerCert = null;
|
||||||
String proxyServer = null;
|
String proxyServer = null;
|
||||||
|
|
||||||
|
@ -78,8 +78,8 @@ public class ElectrumServer {
|
||||||
throw new ServerConfigException("Could not connect to Bitcoin Core RPC");
|
throw new ServerConfigException("Could not connect to Bitcoin Core RPC");
|
||||||
}
|
}
|
||||||
electrumServer = bwtElectrumServer;
|
electrumServer = bwtElectrumServer;
|
||||||
if(previousServerAddress != null && previousServerAddress.contains(Bwt.ELECTRUM_HOST)) {
|
if(previousServer != null && previousServer.getUrl().contains(Bwt.ELECTRUM_HOST)) {
|
||||||
previousServerAddress = bwtElectrumServer;
|
previousServer = bwtElectrumServer;
|
||||||
}
|
}
|
||||||
} else if(Config.get().getServerType() == ServerType.ELECTRUM_SERVER) {
|
} else if(Config.get().getServerType() == ServerType.ELECTRUM_SERVER) {
|
||||||
electrumServer = Config.get().getElectrumServer();
|
electrumServer = Config.get().getElectrumServer();
|
||||||
|
@ -95,33 +95,30 @@ public class ElectrumServer {
|
||||||
throw new ServerConfigException("Electrum server certificate file not found");
|
throw new ServerConfigException("Electrum server certificate file not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
Protocol protocol = Protocol.getProtocol(electrumServer);
|
Protocol protocol = electrumServer.getProtocol();
|
||||||
if(protocol == null) {
|
|
||||||
throw new ServerConfigException("Electrum server URL must start with " + Protocol.TCP.toUrlString() + " or " + Protocol.SSL.toUrlString());
|
|
||||||
}
|
|
||||||
|
|
||||||
//If changing server, don't rely on previous transaction history
|
//If changing server, don't rely on previous transaction history
|
||||||
if(previousServerAddress != null && !electrumServer.equals(previousServerAddress)) {
|
if(previousServer != null && !electrumServer.equals(previousServer)) {
|
||||||
retrievedScriptHashes.clear();
|
retrievedScriptHashes.clear();
|
||||||
retrievedTransactions.clear();
|
retrievedTransactions.clear();
|
||||||
}
|
}
|
||||||
previousServerAddress = electrumServer;
|
previousServer = electrumServer;
|
||||||
|
|
||||||
HostAndPort server = protocol.getServerHostAndPort(electrumServer);
|
HostAndPort hostAndPort = electrumServer.getHostAndPort();
|
||||||
boolean localNetworkAddress = !protocol.isOnionAddress(server) && IpAddressMatcher.isLocalNetworkAddress(server.getHost());
|
boolean localNetworkAddress = !protocol.isOnionAddress(hostAndPort) && IpAddressMatcher.isLocalNetworkAddress(hostAndPort.getHost());
|
||||||
|
|
||||||
if(!localNetworkAddress && Config.get().isUseProxy() && proxyServer != null && !proxyServer.isBlank()) {
|
if(!localNetworkAddress && Config.get().isUseProxy() && proxyServer != null && !proxyServer.isBlank()) {
|
||||||
HostAndPort proxy = HostAndPort.fromString(proxyServer);
|
HostAndPort proxy = HostAndPort.fromString(proxyServer);
|
||||||
if(electrumServerCert != null) {
|
if(electrumServerCert != null) {
|
||||||
transport = protocol.getTransport(server, electrumServerCert, proxy);
|
transport = protocol.getTransport(hostAndPort, electrumServerCert, proxy);
|
||||||
} else {
|
} else {
|
||||||
transport = protocol.getTransport(server, proxy);
|
transport = protocol.getTransport(hostAndPort, proxy);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(electrumServerCert != null) {
|
if(electrumServerCert != null) {
|
||||||
transport = protocol.getTransport(server, electrumServerCert);
|
transport = protocol.getTransport(hostAndPort, electrumServerCert);
|
||||||
} else {
|
} else {
|
||||||
transport = protocol.getTransport(server);
|
transport = protocol.getTransport(hostAndPort);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -1251,7 +1248,7 @@ public class ElectrumServer {
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void bwtElectrumReadyStatus(BwtElectrumReadyStatusEvent event) {
|
public void bwtElectrumReadyStatus(BwtElectrumReadyStatusEvent event) {
|
||||||
if(this.isRunning()) {
|
if(this.isRunning()) {
|
||||||
ElectrumServer.bwtElectrumServer = Protocol.TCP.toUrlString(HostAndPort.fromString(event.getElectrumAddr()));
|
ElectrumServer.bwtElectrumServer = new Server(Protocol.TCP.toUrlString(HostAndPort.fromString(event.getElectrumAddr())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ public final class IpAddressMatcher {
|
||||||
return InetAddress.getByName(address);
|
return InetAddress.getByName(address);
|
||||||
}
|
}
|
||||||
catch (UnknownHostException e) {
|
catch (UnknownHostException e) {
|
||||||
throw new IllegalArgumentException("Failed to parse address" + address, e);
|
throw new IllegalArgumentException("Failed to parse address: " + address, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.sparrowwallet.sparrow.net;
|
package com.sparrowwallet.sparrow.net;
|
||||||
|
|
||||||
import com.github.arteam.simplejsonrpc.client.Transport;
|
|
||||||
import com.google.common.net.HostAndPort;
|
import com.google.common.net.HostAndPort;
|
||||||
|
import com.sparrowwallet.sparrow.io.Server;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -121,6 +121,14 @@ public enum Protocol {
|
||||||
return host != null && host.toLowerCase(Locale.ROOT).endsWith(TorService.TOR_ADDRESS_SUFFIX);
|
return host != null && host.toLowerCase(Locale.ROOT).endsWith(TorService.TOR_ADDRESS_SUFFIX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isOnionAddress(Server server) {
|
||||||
|
if(server != null) {
|
||||||
|
return isOnionAddress(server.getHostAndPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isOnionAddress(HostAndPort server) {
|
public static boolean isOnionAddress(HostAndPort server) {
|
||||||
return isOnionHost(server.getHost());
|
return isOnionHost(server.getHost());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.sparrowwallet.sparrow.net;
|
package com.sparrowwallet.sparrow.net;
|
||||||
|
|
||||||
import com.sparrowwallet.drongo.Network;
|
import com.sparrowwallet.drongo.Network;
|
||||||
|
import com.sparrowwallet.sparrow.io.Server;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -15,23 +16,21 @@ public enum PublicElectrumServer {
|
||||||
TESTNET_ARANGUREN_ORG("testnet.aranguren.org", "ssl://testnet.aranguren.org:51002", Network.TESTNET);
|
TESTNET_ARANGUREN_ORG("testnet.aranguren.org", "ssl://testnet.aranguren.org:51002", Network.TESTNET);
|
||||||
|
|
||||||
PublicElectrumServer(String name, String url, Network network) {
|
PublicElectrumServer(String name, String url, Network network) {
|
||||||
this.name = name;
|
this.server = new Server(url, name);
|
||||||
this.url = url;
|
|
||||||
this.network = network;
|
this.network = network;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final List<Network> SUPPORTED_NETWORKS = List.of(Network.MAINNET, Network.TESTNET);
|
public static final List<Network> SUPPORTED_NETWORKS = List.of(Network.MAINNET, Network.TESTNET);
|
||||||
|
|
||||||
private final String name;
|
private final Server server;
|
||||||
private final String url;
|
|
||||||
private final Network network;
|
private final Network network;
|
||||||
|
|
||||||
public String getName() {
|
public Server getServer() {
|
||||||
return name;
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
return url;
|
return server.getUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Network getNetwork() {
|
public Network getNetwork() {
|
||||||
|
@ -46,10 +45,10 @@ public enum PublicElectrumServer {
|
||||||
return SUPPORTED_NETWORKS.contains(Network.get());
|
return SUPPORTED_NETWORKS.contains(Network.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PublicElectrumServer fromUrl(String url) {
|
public static PublicElectrumServer fromServer(Server server) {
|
||||||
for(PublicElectrumServer server : values()) {
|
for(PublicElectrumServer publicServer : values()) {
|
||||||
if(server.url.equals(url)) {
|
if(publicServer.getServer().equals(server)) {
|
||||||
return server;
|
return publicServer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +57,6 @@ public enum PublicElectrumServer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return server.getAlias();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,8 @@ public class TcpOverTlsTransport extends TcpTransport {
|
||||||
|
|
||||||
protected boolean shouldSaveCertificate() {
|
protected boolean shouldSaveCertificate() {
|
||||||
//Avoid saving the certificates for blockstream.info public servers - they change too often and encourage approval complacency
|
//Avoid saving the certificates for blockstream.info public servers - they change too often and encourage approval complacency
|
||||||
if(PublicElectrumServer.BLOCKSTREAM_INFO.getName().equals(server.getHost()) || PublicElectrumServer.ELECTRUM_BLOCKSTREAM_INFO.getName().equals(server.getHost())) {
|
if(PublicElectrumServer.BLOCKSTREAM_INFO.getServer().getHost().equals(server.getHost())
|
||||||
|
|| PublicElectrumServer.ELECTRUM_BLOCKSTREAM_INFO.getServer().getHost().equals(server.getHost())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,10 @@ public class TcpTransport implements CloseableTransport, TimeoutCounter {
|
||||||
log.trace("Sending to electrum server at " + server + ": " + request);
|
log.trace("Sending to electrum server at " + server + ": " + request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(socket == null) {
|
||||||
|
throw new IllegalStateException("Socket connection has not been established.");
|
||||||
|
}
|
||||||
|
|
||||||
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
|
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
|
||||||
out.println(request);
|
out.println(request);
|
||||||
out.flush();
|
out.flush();
|
||||||
|
@ -207,7 +211,7 @@ public class TcpTransport implements CloseableTransport, TimeoutCounter {
|
||||||
String response = readLine(in);
|
String response = readLine(in);
|
||||||
|
|
||||||
if(response == null) {
|
if(response == null) {
|
||||||
throw new IOException("Could not connect to server at " + Config.get().getServerAddress());
|
throw new IOException("Could not connect to server" + (Config.get().hasServer() ? " at " + Config.get().getServer().getUrl() : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
|
|
|
@ -0,0 +1,214 @@
|
||||||
|
package com.sparrowwallet.sparrow.preferences;
|
||||||
|
|
||||||
|
import com.sparrowwallet.sparrow.AppServices;
|
||||||
|
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
|
||||||
|
import com.sparrowwallet.sparrow.io.Config;
|
||||||
|
import com.sparrowwallet.sparrow.io.Server;
|
||||||
|
import com.sparrowwallet.sparrow.net.ServerType;
|
||||||
|
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
import javafx.beans.property.StringProperty;
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.event.Event;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.*;
|
||||||
|
import javafx.scene.control.cell.TextFieldTableCell;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.StackPane;
|
||||||
|
import javafx.util.converter.DefaultStringConverter;
|
||||||
|
import org.controlsfx.glyphfont.Glyph;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class ServerAliasDialog extends Dialog<Server> {
|
||||||
|
private final ServerType serverType;
|
||||||
|
private final TableView<ServerEntry> serverTable;
|
||||||
|
|
||||||
|
public ServerAliasDialog(ServerType serverType) {
|
||||||
|
this.serverType = serverType;
|
||||||
|
|
||||||
|
final DialogPane dialogPane = new ServerAliasDialogPane();
|
||||||
|
setDialogPane(dialogPane);
|
||||||
|
AppServices.setStageIcon(dialogPane.getScene().getWindow());
|
||||||
|
|
||||||
|
setTitle("Server Aliases");
|
||||||
|
dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm());
|
||||||
|
dialogPane.setHeaderText("Configure aliases for recently connected servers.\nNew servers are added to this list on successful connections.");
|
||||||
|
|
||||||
|
Image image = new Image("/image/sparrow-small.png");
|
||||||
|
dialogPane.setGraphic(new ImageView(image));
|
||||||
|
|
||||||
|
serverTable = new TableView<>();
|
||||||
|
serverTable.setPlaceholder(new Label("No servers added yet"));
|
||||||
|
|
||||||
|
TableColumn<ServerEntry, String> urlColumn = new TableColumn<>("URL");
|
||||||
|
urlColumn.setMinWidth(300);
|
||||||
|
urlColumn.setCellValueFactory((TableColumn.CellDataFeatures<ServerEntry, String> param) -> {
|
||||||
|
return new ReadOnlyObjectWrapper<>(param.getValue().getUrl());
|
||||||
|
});
|
||||||
|
|
||||||
|
TableColumn<ServerEntry, String> aliasColumn = new TableColumn<>("Alias");
|
||||||
|
aliasColumn.setCellValueFactory((TableColumn.CellDataFeatures<ServerEntry, String> param) -> {
|
||||||
|
return param.getValue().labelProperty();
|
||||||
|
});
|
||||||
|
aliasColumn.setCellFactory(value -> new AliasCell());
|
||||||
|
aliasColumn.setGraphic(getTagGlyph());
|
||||||
|
|
||||||
|
serverTable.getColumns().add(urlColumn);
|
||||||
|
serverTable.getColumns().add(aliasColumn);
|
||||||
|
serverTable.setEditable(true);
|
||||||
|
serverTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||||
|
|
||||||
|
List<Server> servers = serverType == ServerType.BITCOIN_CORE ? Config.get().getRecentCoreServers() : Config.get().getRecentElectrumServers();
|
||||||
|
List<ServerEntry> serverEntries = servers.stream().map(server -> new ServerEntry(serverType, server)).collect(Collectors.toList());
|
||||||
|
serverTable.setItems(FXCollections.observableArrayList(serverEntries));
|
||||||
|
|
||||||
|
StackPane stackPane = new StackPane();
|
||||||
|
stackPane.getChildren().add(serverTable);
|
||||||
|
dialogPane.setContent(stackPane);
|
||||||
|
|
||||||
|
ButtonType selectButtonType = new ButtonType("Select", ButtonBar.ButtonData.APPLY);
|
||||||
|
ButtonType deleteButtonType = new ButtonType("Delete", ButtonBar.ButtonData.LEFT);
|
||||||
|
dialogPane.getButtonTypes().addAll(deleteButtonType, ButtonType.CLOSE, selectButtonType);
|
||||||
|
|
||||||
|
Button selectButton = (Button)dialogPane.lookupButton(selectButtonType);
|
||||||
|
Button deleteButton = (Button)dialogPane.lookupButton(deleteButtonType);
|
||||||
|
selectButton.setDefaultButton(true);
|
||||||
|
selectButton.setDisable(true);
|
||||||
|
deleteButton.setDisable(true);
|
||||||
|
serverTable.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
selectButton.setDisable(newValue == null);
|
||||||
|
deleteButton.setDisable(newValue == null);
|
||||||
|
});
|
||||||
|
|
||||||
|
setResultConverter(buttonType -> buttonType == selectButtonType ? serverTable.getSelectionModel().getSelectedItem().getServer() : null);
|
||||||
|
|
||||||
|
dialogPane.setPrefWidth(680);
|
||||||
|
dialogPane.setPrefHeight(500);
|
||||||
|
AppServices.setStageIcon(dialogPane.getScene().getWindow());
|
||||||
|
AppServices.moveToActiveWindowScreen(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Glyph getTagGlyph() {
|
||||||
|
Glyph glyph = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.TAG);
|
||||||
|
glyph.setFontSize(12);
|
||||||
|
return glyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ServerAliasDialogPane extends DialogPane {
|
||||||
|
@Override
|
||||||
|
protected Node createButton(ButtonType buttonType) {
|
||||||
|
Node button;
|
||||||
|
if(buttonType.getButtonData() == ButtonBar.ButtonData.LEFT) {
|
||||||
|
Button deleteButton = new Button(buttonType.getText());
|
||||||
|
final ButtonBar.ButtonData buttonData = buttonType.getButtonData();
|
||||||
|
ButtonBar.setButtonData(deleteButton, buttonData);
|
||||||
|
deleteButton.setOnAction(event -> {
|
||||||
|
ServerEntry serverEntry = serverTable.getSelectionModel().getSelectedItem();
|
||||||
|
if(serverEntry != null) {
|
||||||
|
serverTable.getItems().remove(serverEntry);
|
||||||
|
if(serverType == ServerType.BITCOIN_CORE) {
|
||||||
|
Config.get().removeRecentCoreServer(serverEntry.getServer());
|
||||||
|
} else {
|
||||||
|
Config.get().removeRecentElectrumServer(serverEntry.getServer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
button = deleteButton;
|
||||||
|
} else {
|
||||||
|
button = super.createButton(buttonType);
|
||||||
|
}
|
||||||
|
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ServerEntry {
|
||||||
|
private final Server server;
|
||||||
|
private final StringProperty labelProperty = new SimpleStringProperty();
|
||||||
|
|
||||||
|
public ServerEntry(ServerType serverType, Server server) {
|
||||||
|
this.server = server;
|
||||||
|
labelProperty.set(server.getAlias());
|
||||||
|
labelProperty.addListener((observable, oldValue, newValue) -> {
|
||||||
|
String alias = newValue;
|
||||||
|
if(alias != null && alias.isEmpty()) {
|
||||||
|
alias = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Server newServer = new Server(server.getUrl(), alias);
|
||||||
|
if(serverType == ServerType.BITCOIN_CORE) {
|
||||||
|
Config.get().setCoreServerAlias(newServer);
|
||||||
|
} else {
|
||||||
|
Config.get().setElectrumServerAlias(newServer);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return server.getHostAndPort().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringProperty labelProperty() {
|
||||||
|
return labelProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Server getServer() {
|
||||||
|
return new Server(server.getUrl(), labelProperty.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AliasCell extends TextFieldTableCell<ServerEntry, String> {
|
||||||
|
public AliasCell() {
|
||||||
|
super(new DefaultStringConverter());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void commitEdit(String label) {
|
||||||
|
if(label != null) {
|
||||||
|
label = label.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This block is necessary to support commit on losing focus, because
|
||||||
|
// the baked-in mechanism sets our editing state to false before we can
|
||||||
|
// intercept the loss of focus. The default commitEdit(...) method
|
||||||
|
// simply bails if we are not editing...
|
||||||
|
if (!isEditing() && !label.equals(getItem())) {
|
||||||
|
TableView<ServerEntry> table = getTableView();
|
||||||
|
if(table != null) {
|
||||||
|
TableColumn<ServerEntry, String> column = getTableColumn();
|
||||||
|
TableColumn.CellEditEvent<ServerEntry, String> event = new TableColumn.CellEditEvent<>(
|
||||||
|
table, new TablePosition<>(table, getIndex(), column),
|
||||||
|
TableColumn.editCommitEvent(), label
|
||||||
|
);
|
||||||
|
Event.fireEvent(column, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.commitEdit(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startEdit() {
|
||||||
|
super.startEdit();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Field f = getClass().getSuperclass().getDeclaredField("textField");
|
||||||
|
f.setAccessible(true);
|
||||||
|
TextField textField = (TextField)f.get(this);
|
||||||
|
textField.focusedProperty().addListener((obs, wasFocused, isNowFocused) -> {
|
||||||
|
if (!isNowFocused) {
|
||||||
|
commitEdit(getConverter().fromString(textField.getText()));
|
||||||
|
setText(getConverter().fromString(textField.getText()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (Exception e) {
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,11 +12,13 @@ import com.sparrowwallet.sparrow.control.UnlabeledToggleSwitch;
|
||||||
import com.sparrowwallet.sparrow.event.*;
|
import com.sparrowwallet.sparrow.event.*;
|
||||||
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
|
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
|
||||||
import com.sparrowwallet.sparrow.io.Config;
|
import com.sparrowwallet.sparrow.io.Config;
|
||||||
|
import com.sparrowwallet.sparrow.io.Server;
|
||||||
import com.sparrowwallet.sparrow.io.Storage;
|
import com.sparrowwallet.sparrow.io.Storage;
|
||||||
import com.sparrowwallet.sparrow.net.*;
|
import com.sparrowwallet.sparrow.net.*;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.text.Font;
|
import javafx.scene.text.Font;
|
||||||
|
@ -51,6 +53,8 @@ import java.util.Random;
|
||||||
public class ServerPreferencesController extends PreferencesDetailController {
|
public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
private static final Logger log = LoggerFactory.getLogger(ServerPreferencesController.class);
|
private static final Logger log = LoggerFactory.getLogger(ServerPreferencesController.class);
|
||||||
|
|
||||||
|
private static final Server MANAGE_ALIASES_SERVER = new Server("tcp://localhost", "Manage Aliases...");
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private ToggleGroup serverTypeToggleGroup;
|
private ToggleGroup serverTypeToggleGroup;
|
||||||
|
|
||||||
|
@ -79,7 +83,7 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
private Form coreForm;
|
private Form coreForm;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private ComboBox<String> recentCoreServers;
|
private ComboBox<Server> recentCoreServers;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private ComboBoxTextField coreHost;
|
private ComboBoxTextField coreHost;
|
||||||
|
@ -121,7 +125,7 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
private Form electrumForm;
|
private Form electrumForm;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private ComboBox<String> recentElectrumServers;
|
private ComboBox<Server> recentElectrumServers;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private ComboBoxTextField electrumHost;
|
private ComboBoxTextField electrumHost;
|
||||||
|
@ -267,26 +271,52 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
recentCoreServers.setConverter(new UrlHostConverter());
|
recentCoreServers.setCellFactory(value -> new ServerCell());
|
||||||
recentCoreServers.setItems(FXCollections.observableList(Config.get().getRecentCoreServers() == null ? new ArrayList<>() : Config.get().getRecentCoreServers()));
|
recentCoreServers.setItems(getObservableServerList(Config.get().getRecentCoreServers()));
|
||||||
recentCoreServers.prefWidthProperty().bind(coreHost.widthProperty());
|
recentCoreServers.prefWidthProperty().bind(coreHost.widthProperty());
|
||||||
recentCoreServers.valueProperty().addListener((observable, oldValue, newValue) -> {
|
recentCoreServers.valueProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
if(newValue != null && Protocol.getProtocol(newValue) != null) {
|
if(newValue != null) {
|
||||||
HostAndPort hostAndPort = Protocol.getProtocol(newValue).getServerHostAndPort(newValue);
|
if(newValue == MANAGE_ALIASES_SERVER) {
|
||||||
coreHost.setText(hostAndPort.getHost());
|
ServerAliasDialog serverAliasDialog = new ServerAliasDialog(ServerType.BITCOIN_CORE);
|
||||||
corePort.setText(Integer.toString(hostAndPort.getPort()));
|
Optional<Server> optServer = serverAliasDialog.showAndWait();
|
||||||
|
recentCoreServers.setItems(getObservableServerList(Config.get().getRecentCoreServers()));
|
||||||
|
Server selectedServer = optServer.orElseGet(() -> Config.get().getCoreServer());
|
||||||
|
Platform.runLater(() -> recentCoreServers.setValue(selectedServer));
|
||||||
|
} else if(newValue.getHostAndPort() != null) {
|
||||||
|
HostAndPort hostAndPort = newValue.getHostAndPort();
|
||||||
|
corePort.setText(hostAndPort.hasPort() ? Integer.toString(hostAndPort.getPort()) : "");
|
||||||
|
if(newValue.getAlias() != null) {
|
||||||
|
coreHost.setText(newValue.getAlias());
|
||||||
|
} else {
|
||||||
|
coreHost.setText(hostAndPort.getHost());
|
||||||
|
}
|
||||||
|
coreHost.positionCaret(coreHost.getText().length());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
recentElectrumServers.setConverter(new UrlHostConverter());
|
recentElectrumServers.setCellFactory(value -> new ServerCell());
|
||||||
recentElectrumServers.setItems(FXCollections.observableList(Config.get().getRecentElectrumServers() == null ? new ArrayList<>() : Config.get().getRecentElectrumServers()));
|
recentElectrumServers.setItems(getObservableServerList(Config.get().getRecentElectrumServers()));
|
||||||
recentElectrumServers.prefWidthProperty().bind(electrumHost.widthProperty());
|
recentElectrumServers.prefWidthProperty().bind(electrumHost.widthProperty());
|
||||||
recentElectrumServers.valueProperty().addListener((observable, oldValue, newValue) -> {
|
recentElectrumServers.valueProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
if(newValue != null && Protocol.getProtocol(newValue) != null) {
|
if(newValue != null) {
|
||||||
HostAndPort hostAndPort = Protocol.getProtocol(newValue).getServerHostAndPort(newValue);
|
if(newValue == MANAGE_ALIASES_SERVER) {
|
||||||
electrumHost.setText(hostAndPort.getHost());
|
ServerAliasDialog serverAliasDialog = new ServerAliasDialog(ServerType.ELECTRUM_SERVER);
|
||||||
electrumPort.setText(Integer.toString(hostAndPort.getPort()));
|
Optional<Server> optServer = serverAliasDialog.showAndWait();
|
||||||
electrumUseSsl.setSelected(Protocol.getProtocol(newValue) == Protocol.SSL);
|
recentElectrumServers.setItems(getObservableServerList(Config.get().getRecentElectrumServers()));
|
||||||
|
Server selectedServer = optServer.orElseGet(() -> Config.get().getElectrumServer());
|
||||||
|
Platform.runLater(() -> recentElectrumServers.setValue(selectedServer));
|
||||||
|
} else if(newValue.getHostAndPort() != null) {
|
||||||
|
HostAndPort hostAndPort = newValue.getHostAndPort();
|
||||||
|
electrumPort.setText(hostAndPort.hasPort() ? Integer.toString(hostAndPort.getPort()) : "");
|
||||||
|
electrumUseSsl.setSelected(newValue.getProtocol() == Protocol.SSL);
|
||||||
|
if(newValue.getAlias() != null) {
|
||||||
|
electrumHost.setText(newValue.getAlias());
|
||||||
|
} else {
|
||||||
|
electrumHost.setText(hostAndPort.getHost());
|
||||||
|
}
|
||||||
|
electrumHost.positionCaret(electrumHost.getText().length());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -339,7 +369,7 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
setTestResultsFont();
|
setTestResultsFont();
|
||||||
testConnection.setOnAction(event -> {
|
testConnection.setOnAction(event -> {
|
||||||
testConnection.setGraphic(getGlyph(FontAwesome5.Glyph.ELLIPSIS_H, null));
|
testConnection.setGraphic(getGlyph(FontAwesome5.Glyph.ELLIPSIS_H, null));
|
||||||
testResults.setText("Connecting to " + config.getServerAddress() + "...");
|
testResults.setText("Connecting " + (config.hasServer() ? "to " + config.getServer().getUrl() : "") + "...");
|
||||||
|
|
||||||
if(Config.get().requiresInternalTor() && Tor.getDefault() == null) {
|
if(Config.get().requiresInternalTor() && Tor.getDefault() == null) {
|
||||||
startTor();
|
startTor();
|
||||||
|
@ -358,7 +388,7 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
testConnection.setVisible(true);
|
testConnection.setVisible(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
PublicElectrumServer configPublicElectrumServer = PublicElectrumServer.fromUrl(config.getPublicElectrumServer());
|
PublicElectrumServer configPublicElectrumServer = PublicElectrumServer.fromServer(config.getPublicElectrumServer());
|
||||||
if(configPublicElectrumServer == null && PublicElectrumServer.supportedNetwork()) {
|
if(configPublicElectrumServer == null && PublicElectrumServer.supportedNetwork()) {
|
||||||
List<PublicElectrumServer> servers = PublicElectrumServer.getServers();
|
List<PublicElectrumServer> servers = PublicElectrumServer.getServers();
|
||||||
if(!servers.isEmpty()) {
|
if(!servers.isEmpty()) {
|
||||||
|
@ -368,16 +398,16 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
publicElectrumServer.setValue(configPublicElectrumServer);
|
publicElectrumServer.setValue(configPublicElectrumServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
String coreServer = config.getCoreServer();
|
Server coreServer = config.getCoreServer();
|
||||||
if(coreServer != null) {
|
if(coreServer != null) {
|
||||||
Protocol protocol = Protocol.getProtocol(coreServer);
|
HostAndPort hostAndPort = coreServer.getHostAndPort();
|
||||||
|
Server server = config.getRecentCoreServers().stream().filter(coreServer::equals).findFirst().orElse(null);
|
||||||
if(protocol != null) {
|
if(server != null) {
|
||||||
HostAndPort server = protocol.getServerHostAndPort(coreServer);
|
coreHost.setLeft(getGlyph(FontAwesome5.Glyph.TAG, null));
|
||||||
coreHost.setText(server.getHost());
|
}
|
||||||
if(server.hasPort()) {
|
coreHost.setText(server == null || server.getAlias() == null ? hostAndPort.getHost() : server.getAlias());
|
||||||
corePort.setText(Integer.toString(server.getPort()));
|
if(hostAndPort.hasPort()) {
|
||||||
}
|
corePort.setText(Integer.toString(hostAndPort.getPort()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
coreHost.setText("127.0.0.1");
|
coreHost.setText("127.0.0.1");
|
||||||
|
@ -396,21 +426,22 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String electrumServer = config.getElectrumServer();
|
Server electrumServer = config.getElectrumServer();
|
||||||
if(electrumServer != null) {
|
if(electrumServer != null) {
|
||||||
Protocol protocol = Protocol.getProtocol(electrumServer);
|
Protocol protocol = electrumServer.getProtocol();
|
||||||
|
boolean ssl = protocol.equals(Protocol.SSL);
|
||||||
|
electrumUseSsl.setSelected(ssl);
|
||||||
|
electrumCertificate.setDisable(!ssl);
|
||||||
|
electrumCertificateSelect.setDisable(!ssl);
|
||||||
|
|
||||||
if(protocol != null) {
|
HostAndPort hostAndPort = electrumServer.getHostAndPort();
|
||||||
boolean ssl = protocol.equals(Protocol.SSL);
|
Server server = config.getRecentElectrumServers().stream().filter(electrumServer::equals).findFirst().orElse(null);
|
||||||
electrumUseSsl.setSelected(ssl);
|
if(server != null) {
|
||||||
electrumCertificate.setDisable(!ssl);
|
electrumHost.setLeft(getGlyph(FontAwesome5.Glyph.TAG, null));
|
||||||
electrumCertificateSelect.setDisable(!ssl);
|
}
|
||||||
|
electrumHost.setText(server == null || server.getAlias() == null ? hostAndPort.getHost() : server.getAlias());
|
||||||
HostAndPort server = protocol.getServerHostAndPort(electrumServer);
|
if(hostAndPort.hasPort()) {
|
||||||
electrumHost.setText(server.getHost());
|
electrumPort.setText(Integer.toString(hostAndPort.getPort()));
|
||||||
if(server.hasPort()) {
|
|
||||||
electrumPort.setText(Integer.toString(server.getPort()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,7 +480,7 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
torService.setOnSucceeded(workerStateEvent -> {
|
torService.setOnSucceeded(workerStateEvent -> {
|
||||||
Tor.setDefault(torService.getValue());
|
Tor.setDefault(torService.getValue());
|
||||||
torService.cancel();
|
torService.cancel();
|
||||||
testResults.appendText("\nTor running, connecting to " + Config.get().getServerAddress() + "...");
|
testResults.appendText("\nTor running, connecting to " + Config.get().getServer().getUrl() + "...");
|
||||||
startElectrumConnection();
|
startElectrumConnection();
|
||||||
});
|
});
|
||||||
torService.setOnFailed(workerStateEvent -> {
|
torService.setOnFailed(workerStateEvent -> {
|
||||||
|
@ -495,6 +526,13 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
Config.get().setMode(Mode.ONLINE);
|
Config.get().setMode(Mode.ONLINE);
|
||||||
connectionService.cancel();
|
connectionService.cancel();
|
||||||
useProxyOriginal = null;
|
useProxyOriginal = null;
|
||||||
|
if(Config.get().addRecentServer()) {
|
||||||
|
if(Config.get().getServerType() == ServerType.BITCOIN_CORE) {
|
||||||
|
recentCoreServers.setItems(getObservableServerList(Config.get().getRecentCoreServers()));
|
||||||
|
} else if(Config.get().getServerType() == ServerType.ELECTRUM_SERVER) {
|
||||||
|
recentElectrumServers.setItems(getObservableServerList(Config.get().getRecentElectrumServers()));
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
connectionService.setOnFailed(workerStateEvent -> {
|
connectionService.setOnFailed(workerStateEvent -> {
|
||||||
EventManager.get().unregister(connectionService);
|
EventManager.get().unregister(connectionService);
|
||||||
|
@ -668,24 +706,32 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
@NotNull
|
@NotNull
|
||||||
private ChangeListener<PublicElectrumServer> getPublicElectrumServerListener(Config config) {
|
private ChangeListener<PublicElectrumServer> getPublicElectrumServerListener(Config config) {
|
||||||
return (observable, oldValue, newValue) -> {
|
return (observable, oldValue, newValue) -> {
|
||||||
config.setPublicElectrumServer(newValue.getUrl());
|
config.setPublicElectrumServer(newValue.getServer());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private ChangeListener<String> getBitcoinCoreListener(Config config) {
|
private ChangeListener<String> getBitcoinCoreListener(Config config) {
|
||||||
return (observable, oldValue, newValue) -> {
|
return (observable, oldValue, newValue) -> {
|
||||||
|
Server existingServer = config.getRecentCoreServers().stream().filter(server -> coreHost.getText().equals(server.getAlias())).findFirst().orElse(null);
|
||||||
|
coreHost.setLeft(existingServer == null ? null : getGlyph(FontAwesome5.Glyph.TAG, null));
|
||||||
setCoreServerInConfig(config);
|
setCoreServerInConfig(config);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setCoreServerInConfig(Config config) {
|
private void setCoreServerInConfig(Config config) {
|
||||||
|
Server existingServer = config.getRecentCoreServers().stream().filter(server -> coreHost.getText().equals(server.getAlias())).findFirst().orElse(null);
|
||||||
|
if(existingServer != null) {
|
||||||
|
config.setCoreServer(existingServer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String hostAsString = getHost(coreHost.getText());
|
String hostAsString = getHost(coreHost.getText());
|
||||||
Integer portAsInteger = getPort(corePort.getText());
|
Integer portAsInteger = getPort(corePort.getText());
|
||||||
if(hostAsString != null && portAsInteger != null && isValidPort(portAsInteger)) {
|
if(hostAsString != null && portAsInteger != null && isValidPort(portAsInteger)) {
|
||||||
config.setCoreServer(Protocol.HTTP.toUrlString(hostAsString, portAsInteger));
|
config.setCoreServer(new Server(Protocol.HTTP.toUrlString(hostAsString, portAsInteger)));
|
||||||
} else if(hostAsString != null) {
|
} else if(hostAsString != null) {
|
||||||
config.setCoreServer(Protocol.HTTP.toUrlString(hostAsString));
|
config.setCoreServer(new Server(Protocol.HTTP.toUrlString(hostAsString)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,17 +745,25 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
@NotNull
|
@NotNull
|
||||||
private ChangeListener<String> getElectrumServerListener(Config config) {
|
private ChangeListener<String> getElectrumServerListener(Config config) {
|
||||||
return (observable, oldValue, newValue) -> {
|
return (observable, oldValue, newValue) -> {
|
||||||
|
Server existingServer = config.getRecentElectrumServers().stream().filter(server -> electrumHost.getText().equals(server.getAlias())).findFirst().orElse(null);
|
||||||
|
electrumHost.setLeft(existingServer == null ? null : getGlyph(FontAwesome5.Glyph.TAG, null));
|
||||||
setElectrumServerInConfig(config);
|
setElectrumServerInConfig(config);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setElectrumServerInConfig(Config config) {
|
private void setElectrumServerInConfig(Config config) {
|
||||||
|
Server existingServer = config.getRecentElectrumServers().stream().filter(server -> electrumHost.getText().equals(server.getAlias())).findFirst().orElse(null);
|
||||||
|
if(existingServer != null) {
|
||||||
|
config.setElectrumServer(existingServer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String hostAsString = getHost(electrumHost.getText());
|
String hostAsString = getHost(electrumHost.getText());
|
||||||
Integer portAsInteger = getPort(electrumPort.getText());
|
Integer portAsInteger = getPort(electrumPort.getText());
|
||||||
if(hostAsString != null && portAsInteger != null && isValidPort(portAsInteger)) {
|
if(hostAsString != null && portAsInteger != null && isValidPort(portAsInteger)) {
|
||||||
config.setElectrumServer(getProtocol().toUrlString(hostAsString, portAsInteger));
|
config.setElectrumServer(new Server(getProtocol().toUrlString(hostAsString, portAsInteger)));
|
||||||
} else if(hostAsString != null) {
|
} else if(hostAsString != null) {
|
||||||
config.setElectrumServer(getProtocol().toUrlString(hostAsString));
|
config.setElectrumServer(new Server(getProtocol().toUrlString(hostAsString)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -777,7 +831,7 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Glyph getGlyph(FontAwesome5.Glyph glyphName, String styleClass) {
|
private static Glyph getGlyph(FontAwesome5.Glyph glyphName, String styleClass) {
|
||||||
Glyph glyph = new Glyph(FontAwesome5.FONT_NAME, glyphName);
|
Glyph glyph = new Glyph(FontAwesome5.FONT_NAME, glyphName);
|
||||||
glyph.setFontSize(12);
|
glyph.setFontSize(12);
|
||||||
if(styleClass != null) {
|
if(styleClass != null) {
|
||||||
|
@ -813,6 +867,12 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ObservableList<Server> getObservableServerList(List<Server> servers) {
|
||||||
|
ObservableList<Server> serverObservableList = FXCollections.observableList(new ArrayList<>(servers));
|
||||||
|
serverObservableList.add(MANAGE_ALIASES_SERVER);
|
||||||
|
return serverObservableList;
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void bwtStatus(BwtStatusEvent event) {
|
public void bwtStatus(BwtStatusEvent event) {
|
||||||
if(!(event instanceof BwtSyncStatusEvent)) {
|
if(!(event instanceof BwtSyncStatusEvent)) {
|
||||||
|
@ -844,15 +904,28 @@ public class ServerPreferencesController extends PreferencesDetailController {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class UrlHostConverter extends StringConverter<String> {
|
private static class ServerCell extends ListCell<Server> {
|
||||||
@Override
|
@Override
|
||||||
public String toString(String serverUrl) {
|
protected void updateItem(Server server, boolean empty) {
|
||||||
return serverUrl == null || Protocol.getProtocol(serverUrl) == null ? "" : Protocol.getProtocol(serverUrl).getServerHostAndPort(serverUrl).getHost();
|
super.updateItem(server, empty);
|
||||||
}
|
if(server == null || empty) {
|
||||||
|
setText("");
|
||||||
|
setGraphic(null);
|
||||||
|
} else {
|
||||||
|
String serverAlias = server.getAlias();
|
||||||
|
|
||||||
@Override
|
if(server == MANAGE_ALIASES_SERVER) {
|
||||||
public String fromString(String string) {
|
setText(serverAlias);
|
||||||
return null;
|
setStyle("-fx-font-style: italic");
|
||||||
|
setGraphic(null);
|
||||||
|
} else if(serverAlias != null) {
|
||||||
|
setText(serverAlias);
|
||||||
|
setGraphic(getGlyph(FontAwesome5.Glyph.TAG, null));
|
||||||
|
} else {
|
||||||
|
setText(server.getHost());
|
||||||
|
setGraphic(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,6 +117,7 @@
|
||||||
<MenuItem fx:id="findMixingPartner" mnemonicParsing="false" text="Find Mix Partner" onAction="#findMixingPartner"/>
|
<MenuItem fx:id="findMixingPartner" mnemonicParsing="false" text="Find Mix Partner" onAction="#findMixingPartner"/>
|
||||||
<MenuItem fx:id="showPayNym" mnemonicParsing="false" text="Show PayNym" onAction="#showPayNym"/>
|
<MenuItem fx:id="showPayNym" mnemonicParsing="false" text="Show PayNym" onAction="#showPayNym"/>
|
||||||
<SeparatorMenuItem />
|
<SeparatorMenuItem />
|
||||||
|
<Menu fx:id="switchServer" text="Switch Server"/>
|
||||||
<MenuItem styleClass="osxHide,windowsHide" mnemonicParsing="false" text="Install Udev Rules" onAction="#installUdevRules"/>
|
<MenuItem styleClass="osxHide,windowsHide" mnemonicParsing="false" text="Install Udev Rules" onAction="#installUdevRules"/>
|
||||||
<CheckMenuItem fx:id="preventSleep" mnemonicParsing="false" text="Prevent Computer Sleep" onAction="#preventSleep"/>
|
<CheckMenuItem fx:id="preventSleep" mnemonicParsing="false" text="Prevent Computer Sleep" onAction="#preventSleep"/>
|
||||||
<MenuItem fx:id="restart" mnemonicParsing="false" text="Restart" onAction="#restart" />
|
<MenuItem fx:id="restart" mnemonicParsing="false" text="Restart" onAction="#restart" />
|
||||||
|
|
|
@ -51,4 +51,8 @@
|
||||||
|
|
||||||
#electrumUseSsl {
|
#electrumUseSsl {
|
||||||
-fx-padding: 4 0 2 0;
|
-fx-padding: 4 0 2 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#coreHost .left-pane, #electrumHost .left-pane {
|
||||||
|
-fx-padding: 0 3 0 6;
|
||||||
}
|
}
|
Loading…
Reference in a new issue