From 39d1e686f4dc06d4274a926910fe713db5bdd3e5 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Fri, 4 Dec 2020 15:42:17 +0200 Subject: [PATCH] refactor singleton services from appcontroller to appservices --- .../sparrowwallet/sparrow/AppController.java | 407 +---------------- .../sparrowwallet/sparrow/AppServices.java | 423 ++++++++++++++++++ .../com/sparrowwallet/sparrow/MainApp.java | 5 +- .../sparrow/control/AddressTreeTable.java | 4 +- .../sparrow/control/DeviceDialog.java | 8 +- .../sparrow/control/EntryCell.java | 6 +- .../sparrow/control/IdLabel.java | 4 +- .../control/KeystorePassphraseDialog.java | 6 +- .../sparrow/control/MessageSignDialog.java | 22 +- .../sparrow/control/QRDisplayDialog.java | 6 +- .../sparrow/control/QRScanDialog.java | 4 +- .../sparrow/control/SeedDisplayDialog.java | 6 +- .../sparrow/control/TextAreaDialog.java | 6 +- .../control/TitledDescriptionPane.java | 4 +- .../sparrow/control/TransactionDiagram.java | 4 +- .../sparrow/control/TransactionIdDialog.java | 8 +- .../sparrow/control/WalletExportDialog.java | 4 +- .../sparrow/control/WalletImportDialog.java | 4 +- .../sparrow/control/WalletNameDialog.java | 6 +- .../sparrow/control/WalletPasswordDialog.java | 6 +- .../sparrow/control/WelcomeDialog.java | 6 +- .../KeystoreImportController.java | 4 +- .../keystoreimport/KeystoreImportDialog.java | 6 +- .../sparrow/net/SimpleElectrumServerRpc.java | 4 +- .../sparrow/net/VerboseTransaction.java | 4 +- .../preferences/PreferencesController.java | 7 +- .../preferences/PreferencesDialog.java | 6 +- .../transaction/HeadersController.java | 44 +- .../transaction/TransactionController.java | 6 +- .../sparrow/wallet/AdvancedDialog.java | 6 +- .../sparrow/wallet/KeystoreController.java | 8 +- .../sparrow/wallet/PaymentController.java | 8 +- .../sparrow/wallet/ReceiveController.java | 6 +- .../sparrow/wallet/SendController.java | 16 +- .../sparrow/wallet/SettingsController.java | 18 +- .../wallet/TransactionsController.java | 4 +- .../sparrow/wallet/WalletController.java | 4 +- .../sparrow/wallet/WalletForm.java | 12 +- 38 files changed, 583 insertions(+), 529 deletions(-) create mode 100644 src/main/java/com/sparrowwallet/sparrow/AppServices.java diff --git a/src/main/java/com/sparrowwallet/sparrow/AppController.java b/src/main/java/com/sparrowwallet/sparrow/AppController.java index 6f6ee84e..e2df277e 100644 --- a/src/main/java/com/sparrowwallet/sparrow/AppController.java +++ b/src/main/java/com/sparrowwallet/sparrow/AppController.java @@ -7,7 +7,6 @@ import com.sparrowwallet.drongo.BitcoinUnit; import com.sparrowwallet.drongo.Network; import com.sparrowwallet.drongo.SecureString; import com.sparrowwallet.drongo.Utils; -import com.sparrowwallet.drongo.address.Address; import com.sparrowwallet.drongo.crypto.ECKey; import com.sparrowwallet.drongo.crypto.EncryptionType; import com.sparrowwallet.drongo.crypto.InvalidPasswordException; @@ -19,15 +18,11 @@ import com.sparrowwallet.drongo.protocol.Transaction; import com.sparrowwallet.drongo.psbt.PSBT; import com.sparrowwallet.drongo.psbt.PSBTInput; import com.sparrowwallet.drongo.psbt.PSBTParseException; -import com.sparrowwallet.drongo.uri.BitcoinURI; import com.sparrowwallet.drongo.wallet.*; import com.sparrowwallet.sparrow.control.*; import com.sparrowwallet.sparrow.event.*; import com.sparrowwallet.sparrow.io.*; import com.sparrowwallet.sparrow.net.ElectrumServer; -import com.sparrowwallet.sparrow.net.ExchangeSource; -import com.sparrowwallet.sparrow.net.MempoolRateSize; -import com.sparrowwallet.sparrow.net.VersionCheckService; import com.sparrowwallet.sparrow.preferences.PreferencesDialog; import com.sparrowwallet.sparrow.transaction.TransactionController; import com.sparrowwallet.sparrow.transaction.TransactionData; @@ -37,10 +32,7 @@ import com.sparrowwallet.sparrow.wallet.WalletForm; import de.codecentric.centerdevice.MenuToolkit; import javafx.animation.*; import javafx.application.Platform; -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.SimpleBooleanProperty; import javafx.collections.ListChangeListener; -import javafx.concurrent.Worker; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; @@ -55,7 +47,6 @@ import javafx.scene.image.ImageView; import javafx.scene.input.Dragboard; import javafx.scene.input.TransferMode; import javafx.scene.layout.StackPane; -import javafx.scene.text.Font; import javafx.stage.FileChooser; import javafx.stage.Stage; import javafx.stage.StageStyle; @@ -70,27 +61,17 @@ import java.io.*; import java.net.URL; import java.nio.charset.StandardCharsets; import java.text.ParseException; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.temporal.ChronoUnit; import java.util.*; import java.util.List; import java.util.stream.Collectors; +import static com.sparrowwallet.sparrow.AppServices.*; + public class AppController implements Initializable { private static final Logger log = LoggerFactory.getLogger(AppController.class); - private static final int SERVER_PING_PERIOD = 1 * 60 * 1000; - private static final int ENUMERATE_HW_PERIOD = 30 * 1000; - private static final int RATES_PERIOD = 5 * 60 * 1000; - private static final int VERSION_CHECK_PERIOD_HOURS = 24; - private static final ExchangeSource DEFAULT_EXCHANGE_SOURCE = ExchangeSource.COINGECKO; - private static final Currency DEFAULT_FIAT_CURRENCY = Currency.getInstance("USD"); - public static final String DRAG_OVER_CLASS = "drag-over"; - private MainApp application; - @FXML private MenuItem saveTransaction; @@ -127,35 +108,8 @@ public class AppController implements Initializable { @FXML private UnlabeledToggleSwitch serverToggle; - //Determines if a change in serverToggle changes the offline/online mode - private boolean changeMode = true; - - private static final BooleanProperty onlineProperty = new SimpleBooleanProperty(false); - private Timeline statusTimeline; - private ExchangeSource.RatesService ratesService; - - private ElectrumServer.ConnectionService connectionService; - - private Hwi.ScheduledEnumerateService deviceEnumerateService; - - private VersionCheckService versionCheckService; - - private static Integer currentBlockHeight; - - private static Map targetBlockFeeRates; - - private static final Map> mempoolHistogram = new TreeMap<>(); - - private static Double minimumRelayFeeRate; - - private static CurrencyRate fiatCurrencyExchangeRate; - - private static List devices; - - private static final Map payjoinURIs = new HashMap<>(); - @Override public void initialize(URL location, ResourceBundle resources) { EventManager.get().register(this); @@ -258,152 +212,12 @@ public class AppController implements Initializable { showTxHex.setSelected(Config.get().isShowTransactionHex()); exportWallet.setDisable(true); - serverToggle.selectedProperty().addListener((observable, oldValue, newValue) -> { - if(changeMode) { - Config.get().setMode(newValue ? Mode.ONLINE : Mode.OFFLINE); - if(newValue) { - if(connectionService.getState() == Worker.State.CANCELLED) { - connectionService.reset(); - } - - if(!connectionService.isRunning()) { - connectionService.start(); - } - - if(ratesService.getState() == Worker.State.CANCELLED) { - ratesService.reset(); - } - - if(!ratesService.isRunning() && ratesService.getExchangeSource() != ExchangeSource.NONE) { - ratesService.start(); - } - - if(versionCheckService.getState() == Worker.State.CANCELLED) { - versionCheckService.reset(); - } - - if(!versionCheckService.isRunning() && Config.get().isCheckNewVersions()) { - versionCheckService.start(); - } - } else { - connectionService.cancel(); - ratesService.cancel(); - versionCheckService.cancel(); - } - } - }); - - onlineProperty.bindBidirectional(serverToggle.selectedProperty()); + onlineProperty().bindBidirectional(serverToggle.selectedProperty()); onlineProperty().addListener((observable, oldValue, newValue) -> { - Platform.runLater(this::setServerToggleTooltip); + Platform.runLater(() -> setServerToggleTooltip(getCurrentBlockHeight())); }); - Config config = Config.get(); - connectionService = createConnectionService(); - if(config.getMode() == Mode.ONLINE && config.getElectrumServer() != null && !config.getElectrumServer().isEmpty()) { - connectionService.start(); - } - - ExchangeSource source = config.getExchangeSource() != null ? config.getExchangeSource() : DEFAULT_EXCHANGE_SOURCE; - Currency currency = config.getFiatCurrency() != null ? config.getFiatCurrency() : DEFAULT_FIAT_CURRENCY; - ratesService = createRatesService(source, currency); - if(config.getMode() == Mode.ONLINE && source != ExchangeSource.NONE) { - ratesService.start(); - } - - versionCheckService = createVersionCheckService(); - if(config.getMode() == Mode.ONLINE && config.isCheckNewVersions()) { - versionCheckService.start(); - } - - openTransactionIdItem.disableProperty().bind(onlineProperty.not()); - } - - private ElectrumServer.ConnectionService createConnectionService() { - ElectrumServer.ConnectionService connectionService = new ElectrumServer.ConnectionService(); - connectionService.setPeriod(new Duration(SERVER_PING_PERIOD)); - connectionService.setRestartOnFailure(true); - - EventManager.get().register(connectionService); - connectionService.statusProperty().addListener((observable, oldValue, newValue) -> { - if(connectionService.isRunning()) { - EventManager.get().post(new StatusEvent(newValue)); - } - }); - - connectionService.setOnSucceeded(successEvent -> { - changeMode = false; - onlineProperty.setValue(true); - changeMode = true; - - if(connectionService.getValue() != null) { - EventManager.get().post(connectionService.getValue()); - } - }); - connectionService.setOnFailed(failEvent -> { - //Close connection here to create a new transport next time we try - connectionService.resetConnection(); - - changeMode = false; - onlineProperty.setValue(false); - changeMode = true; - - log.debug("Connection failed", failEvent.getSource().getException()); - EventManager.get().post(new ConnectionFailedEvent(failEvent.getSource().getException())); - }); - - return connectionService; - } - - private ExchangeSource.RatesService createRatesService(ExchangeSource exchangeSource, Currency currency) { - ExchangeSource.RatesService ratesService = new ExchangeSource.RatesService(exchangeSource, currency); - ratesService.setPeriod(new Duration(RATES_PERIOD)); - ratesService.setRestartOnFailure(true); - - ratesService.setOnSucceeded(successEvent -> { - EventManager.get().post(ratesService.getValue()); - }); - - return ratesService; - } - - private VersionCheckService createVersionCheckService() { - VersionCheckService versionCheckService = new VersionCheckService(); - versionCheckService.setDelay(Duration.seconds(10)); - versionCheckService.setPeriod(Duration.hours(VERSION_CHECK_PERIOD_HOURS)); - versionCheckService.setRestartOnFailure(true); - - versionCheckService.setOnSucceeded(successEvent -> { - VersionUpdatedEvent event = versionCheckService.getValue(); - if(event != null) { - EventManager.get().post(event); - } - }); - - return versionCheckService; - } - - private Hwi.ScheduledEnumerateService createDeviceEnumerateService() { - Hwi.ScheduledEnumerateService enumerateService = new Hwi.ScheduledEnumerateService(null); - enumerateService.setPeriod(new Duration(ENUMERATE_HW_PERIOD)); - enumerateService.setOnSucceeded(workerStateEvent -> { - List devices = enumerateService.getValue(); - - //Null devices are returned if the app is currently prompting for a pin. Otherwise, the enumerate clears the pin screen - if(devices != null) { - //If another instance of HWI is currently accessing the usb interface, HWI returns empty device models. Ignore this run if that happens - List validDevices = devices.stream().filter(device -> device.getModel() != null).collect(Collectors.toList()); - if(validDevices.size() == devices.size()) { - Platform.runLater(() -> EventManager.get().post(new UsbDeviceEvent(devices))); - } - } - }); - - return enumerateService; - } - - public void setApplication(MainApp application) { - this.application = application; + openTransactionIdItem.disableProperty().bind(onlineProperty().not()); } private void setOsxApplicationMenu() { @@ -577,7 +391,7 @@ public class AppController implements Initializable { log.error("Error scanning QR", result.exception); showErrorDialog("Error scanning QR", result.exception.getMessage()); } else { - AppController.showErrorDialog("Invalid QR Code", "Cannot parse QR code into a transaction or PSBT"); + AppServices.showErrorDialog("Invalid QR Code", "Cannot parse QR code into a transaction or PSBT"); } } } @@ -626,70 +440,12 @@ public class AppController implements Initializable { } } catch(IOException e) { log.error("Error saving transaction", e); - AppController.showErrorDialog("Error saving transaction", "Cannot write to " + file.getAbsolutePath()); + AppServices.showErrorDialog("Error saving transaction", "Cannot write to " + file.getAbsolutePath()); } } } } - public static boolean isOnline() { - return onlineProperty.get(); - } - - public void connect() { - serverToggle.selectedProperty().set(true); - } - - public void disconnect() { - serverToggle.selectedProperty().set(false); - } - - public static BooleanProperty onlineProperty() { return onlineProperty; } - - public static Integer getCurrentBlockHeight() { - return currentBlockHeight; - } - - public static Map getTargetBlockFeeRates() { - return targetBlockFeeRates; - } - - public static Map> getMempoolHistogram() { - return mempoolHistogram; - } - - private void addMempoolRateSizes(Set rateSizes) { - LocalDateTime dateMinute = LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES); - if(mempoolHistogram.isEmpty()) { - mempoolHistogram.put(Date.from(dateMinute.minusMinutes(1).atZone(ZoneId.systemDefault()).toInstant()), rateSizes); - } - - mempoolHistogram.put(Date.from(dateMinute.atZone(ZoneId.systemDefault()).toInstant()), rateSizes); - } - - public static Double getMinimumRelayFeeRate() { - return minimumRelayFeeRate == null ? Transaction.DEFAULT_MIN_RELAY_FEE : minimumRelayFeeRate; - } - - public static CurrencyRate getFiatCurrencyExchangeRate() { - return fiatCurrencyExchangeRate; - } - - public static List getDevices() { - return devices == null ? new ArrayList<>() : devices; - } - - public static BitcoinURI getPayjoinURI(Address address) { - return payjoinURIs.get(address); - } - - public static void addPayjoinURI(BitcoinURI bitcoinURI) { - if(bitcoinURI.getPayjoinUrl() == null) { - throw new IllegalArgumentException("Not a payjoin URI"); - } - payjoinURIs.put(bitcoinURI.getAddress(), bitcoinURI); - } - public Map getOpenWallets() { Map openWallets = new LinkedHashMap<>(); @@ -704,28 +460,6 @@ public class AppController implements Initializable { return openWallets; } - public static void showErrorDialog(String title, String content) { - Alert alert = new Alert(Alert.AlertType.ERROR); - setStageIcon(alert.getDialogPane().getScene().getWindow()); - alert.getDialogPane().getScene().getStylesheets().add(AppController.class.getResource("general.css").toExternalForm()); - alert.setTitle(title); - alert.setHeaderText(title); - alert.setContentText(content); - alert.showAndWait(); - } - - public static void setStageIcon(Window window) { - Stage stage = (Stage)window; - stage.getIcons().add(new Image(AppController.class.getResourceAsStream("/image/sparrow.png"))); - - if(stage.getScene() != null && Config.get().getTheme() == Theme.DARK) { - stage.getScene().getStylesheets().add(AppController.class.getResource("darktheme.css").toExternalForm()); - } - } - - public static Font getMonospaceFont() { - return Font.font("Roboto Mono", 13); - } public void selectTab(Wallet wallet) { for(Tab tab : tabs.getTabs()) { @@ -745,7 +479,7 @@ public class AppController implements Initializable { public void quit(ActionEvent event) { try { - application.stop(); + AppServices.get().getApplication().stop(); } catch (Exception e) { log.error("Error quitting application", e); } @@ -769,8 +503,8 @@ public class AppController implements Initializable { return FileType.JSON.equals(fileType) || FileType.BINARY.equals(fileType); } - private void setServerToggleTooltip() { - serverToggle.setTooltip(new Tooltip(isOnline() ? "Connected to " + Config.get().getElectrumServer() + (getCurrentBlockHeight() != null ? " at height " + getCurrentBlockHeight() : "") : "Disconnected")); + private void setServerToggleTooltip(Integer currentBlockHeight) { + serverToggle.setTooltip(new Tooltip(AppServices.isOnline() ? "Connected to " + Config.get().getElectrumServer() + (currentBlockHeight != null ? " at height " + currentBlockHeight : "") : "Disconnected")); } public void newWallet(ActionEvent event) { @@ -1266,6 +1000,7 @@ public class AppController implements Initializable { @Subscribe public void tabSelected(TabSelectedEvent event) { + //TODO: Handle multiple windows String tabName = event.getTabName(); if(tabs.getScene() != null) { Stage tabStage = (Stage)tabs.getScene().getWindow(); @@ -1304,11 +1039,13 @@ public class AppController implements Initializable { @Subscribe public void walletSettingsChanged(WalletSettingsChangedEvent event) { + //TODO: Handle multiple windows exportWallet.setDisable(!event.getWallet().isValid()); } @Subscribe public void newWalletTransactions(NewWalletTransactionsEvent event) { + //TODO: Handle multiple windows if(Config.get().isNotifyNewTransactions()) { String text; if(event.getBlockTransactions().size() == 1) { @@ -1380,7 +1117,7 @@ public class AppController implements Initializable { public void versionUpdated(VersionUpdatedEvent event) { Hyperlink versionUpdateLabel = new Hyperlink("Sparrow " + event.getVersion() + " available"); versionUpdateLabel.setOnAction(event1 -> { - application.getHostServices().showDocument("https://www.sparrowwallet.com/download"); + AppServices.get().getApplication().getHostServices().showDocument("https://www.sparrowwallet.com/download"); }); if(statusBar.getRightItems().size() > 0 && statusBar.getRightItems().get(0) instanceof Hyperlink) { @@ -1417,8 +1154,6 @@ public class AppController implements Initializable { @Subscribe public void usbDevicesFound(UsbDeviceEvent event) { - devices = Collections.unmodifiableList(event.getDevices()); - UsbStatusButton usbStatus = null; for(Node node : statusBar.getRightItems()) { if(node instanceof UsbStatusButton) { @@ -1442,46 +1177,21 @@ public class AppController implements Initializable { } } - @Subscribe - public void newConnection(ConnectionEvent event) { - currentBlockHeight = event.getBlockHeight(); - targetBlockFeeRates = event.getTargetBlockFeeRates(); - addMempoolRateSizes(event.getMempoolRateSizes()); - minimumRelayFeeRate = event.getMinimumRelayFeeRate(); - String banner = event.getServerBanner(); - String status = "Connected to " + Config.get().getElectrumServer() + " at height " + event.getBlockHeight(); - EventManager.get().post(new StatusEvent(status)); - } - - @Subscribe - public void connectionFailed(ConnectionFailedEvent event) { - String reason = event.getException().getCause() != null ? event.getException().getCause().getMessage() : event.getException().getMessage(); - String status = "Connection error: " + reason; - EventManager.get().post(new StatusEvent(status)); - } - @Subscribe public void newBlock(NewBlockEvent event) { - currentBlockHeight = event.getHeight(); - setServerToggleTooltip(); - String status = "Updating to new block height " + event.getHeight(); - EventManager.get().post(new StatusEvent(status)); - } - - @Subscribe - public void feesUpdated(FeeRatesUpdatedEvent event) { - targetBlockFeeRates = event.getTargetBlockFeeRates(); - addMempoolRateSizes(event.getMempoolRateSizes()); + setServerToggleTooltip(event.getHeight()); } @Subscribe public void viewTransaction(ViewTransactionEvent event) { + //TODO: Handle multiple windows Tab tab = addTransactionTab(event.getBlockTransaction(), event.getInitialView(), event.getInitialIndex()); tabs.getSelectionModel().select(tab); } @Subscribe public void viewPSBT(ViewPSBTEvent event) { + //TODO: Handle multiple windows Tab tab = addTransactionTab(event.getLabel(), event.getPsbt()); tabs.getSelectionModel().select(tab); } @@ -1492,102 +1202,27 @@ public class AppController implements Initializable { selectedToggle.ifPresent(toggle -> bitcoinUnit.selectToggle(toggle)); } - @Subscribe - public void feeRateSourceChanged(FeeRatesSourceChangedEvent event) { - ElectrumServer.FeeRatesService feeRatesService = new ElectrumServer.FeeRatesService(); - feeRatesService.setOnSucceeded(workerStateEvent -> { - EventManager.get().post(feeRatesService.getValue()); - }); - feeRatesService.start(); - } - - @Subscribe - public void fiatCurrencySelected(FiatCurrencySelectedEvent event) { - ratesService.cancel(); - - if (Config.get().getMode() != Mode.OFFLINE && event.getExchangeSource() != ExchangeSource.NONE) { - ratesService = createRatesService(event.getExchangeSource(), event.getCurrency()); - ratesService.start(); - } - } - - @Subscribe - public void exchangeRatesUpdated(ExchangeRatesUpdatedEvent event) { - fiatCurrencyExchangeRate = event.getCurrencyRate(); - } - - @Subscribe - public void versionCheckStatus(VersionCheckStatusEvent event) { - versionCheckService.cancel(); - - if(Config.get().getMode() != Mode.OFFLINE && event.isEnabled()) { - versionCheckService = createVersionCheckService(); - versionCheckService.start(); - } - } - - @Subscribe - public void openWallets(OpenWalletsEvent event) { - List walletFiles = event.getWalletsMap().values().stream().map(Storage::getWalletFile).collect(Collectors.toList()); - Config.get().setRecentWalletFiles(walletFiles); - - boolean usbWallet = false; - for(Map.Entry entry : event.getWalletsMap().entrySet()) { - Wallet wallet = entry.getKey(); - Storage storage = entry.getValue(); - - if(!storage.getWalletFile().exists() || wallet.containsSource(KeystoreSource.HW_USB)) { - usbWallet = true; - - if(deviceEnumerateService == null) { - deviceEnumerateService = createDeviceEnumerateService(); - } - - if(deviceEnumerateService.getState() == Worker.State.CANCELLED) { - deviceEnumerateService.reset(); - } - - if(!deviceEnumerateService.isRunning()) { - deviceEnumerateService.start(); - } - - break; - } - } - - if(!usbWallet && deviceEnumerateService != null && deviceEnumerateService.isRunning()) { - deviceEnumerateService.cancel(); - EventManager.get().post(new UsbDeviceEvent(Collections.emptyList())); - } - } - @Subscribe public void requestOpenWallets(RequestOpenWalletsEvent event) { + //TODO: Handle multiple windows EventManager.get().post(new OpenWalletsEvent(getOpenWallets())); } @Subscribe public void requestWalletOpen(RequestWalletOpenEvent event) { + //TODO: Handle multiple windows openWallet(null); } @Subscribe public void requestTransactionOpen(RequestTransactionOpenEvent event) { + //TODO: Handle multiple windows openTransactionFromFile(null); } @Subscribe public void requestQRScan(RequestQRScanEvent event) { + //TODO: Handle multiple windows openTransactionFromQR(null); } - - @Subscribe - public void requestConnect(RequestConnectEvent event) { - connect(); - } - - @Subscribe - public void requestDisconnect(RequestDisconnectEvent event) { - disconnect(); - } } \ No newline at end of file diff --git a/src/main/java/com/sparrowwallet/sparrow/AppServices.java b/src/main/java/com/sparrowwallet/sparrow/AppServices.java new file mode 100644 index 00000000..b7502190 --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/AppServices.java @@ -0,0 +1,423 @@ +package com.sparrowwallet.sparrow; + +import com.google.common.eventbus.Subscribe; +import com.sparrowwallet.drongo.address.Address; +import com.sparrowwallet.drongo.protocol.Transaction; +import com.sparrowwallet.drongo.uri.BitcoinURI; +import com.sparrowwallet.drongo.wallet.KeystoreSource; +import com.sparrowwallet.drongo.wallet.Wallet; +import com.sparrowwallet.sparrow.event.*; +import com.sparrowwallet.sparrow.io.Config; +import com.sparrowwallet.sparrow.io.Device; +import com.sparrowwallet.sparrow.io.Hwi; +import com.sparrowwallet.sparrow.io.Storage; +import com.sparrowwallet.sparrow.net.ElectrumServer; +import com.sparrowwallet.sparrow.net.ExchangeSource; +import com.sparrowwallet.sparrow.net.MempoolRateSize; +import com.sparrowwallet.sparrow.net.VersionCheckService; +import javafx.application.Platform; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; +import javafx.concurrent.ScheduledService; +import javafx.concurrent.Worker; +import javafx.scene.control.Alert; +import javafx.scene.image.Image; +import javafx.scene.text.Font; +import javafx.stage.Stage; +import javafx.stage.Window; +import javafx.util.Duration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.temporal.ChronoUnit; +import java.util.*; +import java.util.stream.Collectors; + +public class AppServices { + private static final Logger log = LoggerFactory.getLogger(AppServices.class); + + private static final int SERVER_PING_PERIOD = 1 * 60 * 1000; + private static final int ENUMERATE_HW_PERIOD = 30 * 1000; + private static final int RATES_PERIOD = 5 * 60 * 1000; + private static final int VERSION_CHECK_PERIOD_HOURS = 24; + private static final ExchangeSource DEFAULT_EXCHANGE_SOURCE = ExchangeSource.COINGECKO; + private static final Currency DEFAULT_FIAT_CURRENCY = Currency.getInstance("USD"); + + private static AppServices INSTANCE; + + private final MainApp application; + + private static final BooleanProperty onlineProperty = new SimpleBooleanProperty(false); + + private ExchangeSource.RatesService ratesService; + + private final ElectrumServer.ConnectionService connectionService; + + private Hwi.ScheduledEnumerateService deviceEnumerateService; + + private VersionCheckService versionCheckService; + + private static Integer currentBlockHeight; + + private static Map targetBlockFeeRates; + + private static final Map> mempoolHistogram = new TreeMap<>(); + + private static Double minimumRelayFeeRate; + + private static CurrencyRate fiatCurrencyExchangeRate; + + private static List devices; + + private static final Map payjoinURIs = new HashMap<>(); + + private final ChangeListener onlineServicesListener = new ChangeListener<>() { + @Override + public void changed(ObservableValue observable, Boolean oldValue, Boolean online) { + Config.get().setMode(online ? Mode.ONLINE : Mode.OFFLINE); + if(online) { + restartService(connectionService); + + if(ratesService.getExchangeSource() != ExchangeSource.NONE) { + restartService(ratesService); + } + + if(Config.get().isCheckNewVersions()) { + restartService(versionCheckService); + } + } else { + connectionService.cancel(); + ratesService.cancel(); + versionCheckService.cancel(); + } + } + }; + + private void restartService(ScheduledService service) { + if(service.getState() == Worker.State.CANCELLED) { + service.reset(); + } + + if(!service.isRunning()) { + service.start(); + } + } + + public AppServices(MainApp application) { + this.application = application; + + EventManager.get().register(this); + + Config config = Config.get(); + connectionService = createConnectionService(); + if(config.getMode() == Mode.ONLINE && config.getElectrumServer() != null && !config.getElectrumServer().isEmpty()) { + connectionService.start(); + } + + ExchangeSource source = config.getExchangeSource() != null ? config.getExchangeSource() : DEFAULT_EXCHANGE_SOURCE; + Currency currency = config.getFiatCurrency() != null ? config.getFiatCurrency() : DEFAULT_FIAT_CURRENCY; + ratesService = createRatesService(source, currency); + if(config.getMode() == Mode.ONLINE && source != ExchangeSource.NONE) { + ratesService.start(); + } + + versionCheckService = createVersionCheckService(); + if(config.getMode() == Mode.ONLINE && config.isCheckNewVersions()) { + versionCheckService.start(); + } + + onlineProperty.addListener(onlineServicesListener); + } + + private ElectrumServer.ConnectionService createConnectionService() { + ElectrumServer.ConnectionService connectionService = new ElectrumServer.ConnectionService(); + connectionService.setPeriod(new Duration(SERVER_PING_PERIOD)); + connectionService.setRestartOnFailure(true); + + EventManager.get().register(connectionService); + connectionService.statusProperty().addListener((observable, oldValue, newValue) -> { + if(connectionService.isRunning()) { + EventManager.get().post(new StatusEvent(newValue)); + } + }); + + connectionService.setOnSucceeded(successEvent -> { + onlineProperty.removeListener(onlineServicesListener); + onlineProperty.setValue(true); + onlineProperty.addListener(onlineServicesListener); + + if(connectionService.getValue() != null) { + EventManager.get().post(connectionService.getValue()); + } + }); + connectionService.setOnFailed(failEvent -> { + //Close connection here to create a new transport next time we try + connectionService.resetConnection(); + + onlineProperty.removeListener(onlineServicesListener); + onlineProperty.setValue(false); + onlineProperty.addListener(onlineServicesListener); + + log.debug("Connection failed", failEvent.getSource().getException()); + EventManager.get().post(new ConnectionFailedEvent(failEvent.getSource().getException())); + }); + + return connectionService; + } + + private ExchangeSource.RatesService createRatesService(ExchangeSource exchangeSource, Currency currency) { + ExchangeSource.RatesService ratesService = new ExchangeSource.RatesService(exchangeSource, currency); + ratesService.setPeriod(new Duration(RATES_PERIOD)); + ratesService.setRestartOnFailure(true); + + ratesService.setOnSucceeded(successEvent -> { + EventManager.get().post(ratesService.getValue()); + }); + + return ratesService; + } + + private VersionCheckService createVersionCheckService() { + VersionCheckService versionCheckService = new VersionCheckService(); + versionCheckService.setDelay(Duration.seconds(10)); + versionCheckService.setPeriod(Duration.hours(VERSION_CHECK_PERIOD_HOURS)); + versionCheckService.setRestartOnFailure(true); + + versionCheckService.setOnSucceeded(successEvent -> { + VersionUpdatedEvent event = versionCheckService.getValue(); + if(event != null) { + EventManager.get().post(event); + } + }); + + return versionCheckService; + } + + private Hwi.ScheduledEnumerateService createDeviceEnumerateService() { + Hwi.ScheduledEnumerateService enumerateService = new Hwi.ScheduledEnumerateService(null); + enumerateService.setPeriod(new Duration(ENUMERATE_HW_PERIOD)); + enumerateService.setOnSucceeded(workerStateEvent -> { + List devices = enumerateService.getValue(); + + //Null devices are returned if the app is currently prompting for a pin. Otherwise, the enumerate clears the pin screen + if(devices != null) { + //If another instance of HWI is currently accessing the usb interface, HWI returns empty device models. Ignore this run if that happens + List validDevices = devices.stream().filter(device -> device.getModel() != null).collect(Collectors.toList()); + if(validDevices.size() == devices.size()) { + Platform.runLater(() -> EventManager.get().post(new UsbDeviceEvent(devices))); + } + } + }); + + return enumerateService; + } + + static void initialize(MainApp application) { + INSTANCE = new AppServices(application); + } + + public static AppServices get() { + return INSTANCE; + } + + public MainApp getApplication() { + return application; + } + + public static boolean isOnline() { + return onlineProperty.get(); + } + + public static BooleanProperty onlineProperty() { + return onlineProperty; + } + + public static Integer getCurrentBlockHeight() { + return currentBlockHeight; + } + + public static Map getTargetBlockFeeRates() { + return targetBlockFeeRates; + } + + public static Map> getMempoolHistogram() { + return mempoolHistogram; + } + + private void addMempoolRateSizes(Set rateSizes) { + LocalDateTime dateMinute = LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES); + if(mempoolHistogram.isEmpty()) { + mempoolHistogram.put(Date.from(dateMinute.minusMinutes(1).atZone(ZoneId.systemDefault()).toInstant()), rateSizes); + } + + mempoolHistogram.put(Date.from(dateMinute.atZone(ZoneId.systemDefault()).toInstant()), rateSizes); + } + + public static Double getMinimumRelayFeeRate() { + return minimumRelayFeeRate == null ? Transaction.DEFAULT_MIN_RELAY_FEE : minimumRelayFeeRate; + } + + public static CurrencyRate getFiatCurrencyExchangeRate() { + return fiatCurrencyExchangeRate; + } + + public static List getDevices() { + return devices == null ? new ArrayList<>() : devices; + } + + public static BitcoinURI getPayjoinURI(Address address) { + return payjoinURIs.get(address); + } + + public static void addPayjoinURI(BitcoinURI bitcoinURI) { + if(bitcoinURI.getPayjoinUrl() == null) { + throw new IllegalArgumentException("Not a payjoin URI"); + } + payjoinURIs.put(bitcoinURI.getAddress(), bitcoinURI); + } + + public static void showErrorDialog(String title, String content) { + Alert alert = new Alert(Alert.AlertType.ERROR); + setStageIcon(alert.getDialogPane().getScene().getWindow()); + alert.getDialogPane().getScene().getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm()); + alert.setTitle(title); + alert.setHeaderText(title); + alert.setContentText(content); + alert.showAndWait(); + } + + public static void setStageIcon(Window window) { + Stage stage = (Stage)window; + stage.getIcons().add(new Image(AppServices.class.getResourceAsStream("/image/sparrow.png"))); + + if(stage.getScene() != null && Config.get().getTheme() == Theme.DARK) { + stage.getScene().getStylesheets().add(AppServices.class.getResource("darktheme.css").toExternalForm()); + } + } + + public static Font getMonospaceFont() { + return Font.font("Roboto Mono", 13); + } + + @Subscribe + public void newConnection(ConnectionEvent event) { + currentBlockHeight = event.getBlockHeight(); + targetBlockFeeRates = event.getTargetBlockFeeRates(); + addMempoolRateSizes(event.getMempoolRateSizes()); + minimumRelayFeeRate = event.getMinimumRelayFeeRate(); + String banner = event.getServerBanner(); + String status = "Connected to " + Config.get().getElectrumServer() + " at height " + event.getBlockHeight(); + EventManager.get().post(new StatusEvent(status)); + } + + @Subscribe + public void connectionFailed(ConnectionFailedEvent event) { + String reason = event.getException().getCause() != null ? event.getException().getCause().getMessage() : event.getException().getMessage(); + String status = "Connection error: " + reason; + EventManager.get().post(new StatusEvent(status)); + } + + @Subscribe + public void usbDevicesFound(UsbDeviceEvent event) { + devices = Collections.unmodifiableList(event.getDevices()); + } + + @Subscribe + public void newBlock(NewBlockEvent event) { + currentBlockHeight = event.getHeight(); + String status = "Updating to new block height " + event.getHeight(); + EventManager.get().post(new StatusEvent(status)); + } + + @Subscribe + public void feesUpdated(FeeRatesUpdatedEvent event) { + targetBlockFeeRates = event.getTargetBlockFeeRates(); + addMempoolRateSizes(event.getMempoolRateSizes()); + } + + @Subscribe + public void feeRateSourceChanged(FeeRatesSourceChangedEvent event) { + ElectrumServer.FeeRatesService feeRatesService = new ElectrumServer.FeeRatesService(); + feeRatesService.setOnSucceeded(workerStateEvent -> { + EventManager.get().post(feeRatesService.getValue()); + }); + //Perform once-off fee rates retrieval to immediately change displayed rates + feeRatesService.start(); + } + + @Subscribe + public void fiatCurrencySelected(FiatCurrencySelectedEvent event) { + ratesService.cancel(); + + if(Config.get().getMode() != Mode.OFFLINE && event.getExchangeSource() != ExchangeSource.NONE) { + ratesService = createRatesService(event.getExchangeSource(), event.getCurrency()); + ratesService.start(); + } + } + + @Subscribe + public void exchangeRatesUpdated(ExchangeRatesUpdatedEvent event) { + fiatCurrencyExchangeRate = event.getCurrencyRate(); + } + + @Subscribe + public void versionCheckStatus(VersionCheckStatusEvent event) { + versionCheckService.cancel(); + + if(Config.get().getMode() != Mode.OFFLINE && event.isEnabled()) { + versionCheckService = createVersionCheckService(); + versionCheckService.start(); + } + } + + @Subscribe + public void openWallets(OpenWalletsEvent event) { + List walletFiles = event.getWalletsMap().values().stream().map(Storage::getWalletFile).collect(Collectors.toList()); + //TODO: Handle multiple windows + Config.get().setRecentWalletFiles(walletFiles); + + boolean usbWallet = false; + for(Map.Entry entry : event.getWalletsMap().entrySet()) { + Wallet wallet = entry.getKey(); + Storage storage = entry.getValue(); + + if(!storage.getWalletFile().exists() || wallet.containsSource(KeystoreSource.HW_USB)) { + usbWallet = true; + + if(deviceEnumerateService == null) { + deviceEnumerateService = createDeviceEnumerateService(); + } + + if(deviceEnumerateService.getState() == Worker.State.CANCELLED) { + deviceEnumerateService.reset(); + } + + if(!deviceEnumerateService.isRunning()) { + deviceEnumerateService.start(); + } + + break; + } + } + + if(!usbWallet && deviceEnumerateService != null && deviceEnumerateService.isRunning()) { + deviceEnumerateService.cancel(); + EventManager.get().post(new UsbDeviceEvent(Collections.emptyList())); + } + } + + @Subscribe + public void requestConnect(RequestConnectEvent event) { + onlineProperty.set(true); + } + + @Subscribe + public void requestDisconnect(RequestDisconnectEvent event) { + onlineProperty.set(false); + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/MainApp.java b/src/main/java/com/sparrowwallet/sparrow/MainApp.java index 4d9c302b..5b7ec960 100644 --- a/src/main/java/com/sparrowwallet/sparrow/MainApp.java +++ b/src/main/java/com/sparrowwallet/sparrow/MainApp.java @@ -49,7 +49,7 @@ public class MainApp extends Application { GlyphFontRegistry.register(new FontAwesome5()); GlyphFontRegistry.register(new FontAwesome5Brands()); - Font.loadFont(AppController.class.getResourceAsStream("/font/RobotoMono-Regular.ttf"), 13); + Font.loadFont(AppServices.class.getResourceAsStream("/font/RobotoMono-Regular.ttf"), 13); boolean createNewWallet = false; Mode mode = Config.get().getMode(); @@ -68,10 +68,11 @@ public class MainApp extends Application { } } + AppServices.initialize(this); + FXMLLoader transactionLoader = new FXMLLoader(getClass().getResource("app.fxml")); Parent root = transactionLoader.load(); AppController appController = transactionLoader.getController(); - appController.setApplication(this); Scene scene = new Scene(root); scene.getStylesheets().add(getClass().getResource("app.css").toExternalForm()); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/AddressTreeTable.java b/src/main/java/com/sparrowwallet/sparrow/control/AddressTreeTable.java index 0c255a4c..1f80ca21 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/AddressTreeTable.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/AddressTreeTable.java @@ -1,7 +1,7 @@ package com.sparrowwallet.sparrow.control; import com.sparrowwallet.drongo.wallet.WalletNode; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.event.ReceiveActionEvent; import com.sparrowwallet.sparrow.event.ReceiveToEvent; @@ -33,7 +33,7 @@ public class AddressTreeTable extends CoinTreeTable { getColumns().add(addressCol); if(address != null) { - addressCol.setMinWidth(TextUtils.computeTextWidth(AppController.getMonospaceFont(), address, 0.0)); + addressCol.setMinWidth(TextUtils.computeTextWidth(AppServices.getMonospaceFont(), address, 0.0)); } TreeTableColumn labelCol = new TreeTableColumn<>("Label"); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/DeviceDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/DeviceDialog.java index 226891b9..a0146f4b 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/DeviceDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/DeviceDialog.java @@ -1,6 +1,6 @@ package com.sparrowwallet.sparrow.control; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.event.UsbDeviceEvent; import com.sparrowwallet.sparrow.glyphfont.FontAwesome5Brands; @@ -33,8 +33,8 @@ public abstract class DeviceDialog extends Dialog { this.operationFingerprints = operationFingerprints; final DialogPane dialogPane = getDialogPane(); - dialogPane.getStylesheets().add(AppController.class.getResource("general.css").toExternalForm()); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); StackPane stackPane = new StackPane(); dialogPane.setContent(stackPane); @@ -67,7 +67,7 @@ public abstract class DeviceDialog extends Dialog { stackPane.getChildren().addAll(anchorPane, scanBox); - List devices = AppController.getDevices(); + List devices = AppServices.getDevices(); if(devices == null || devices.isEmpty()) { scanBox.setVisible(true); } else { diff --git a/src/main/java/com/sparrowwallet/sparrow/control/EntryCell.java b/src/main/java/com/sparrowwallet/sparrow/control/EntryCell.java index 7e3b6196..cbf9257c 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/EntryCell.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/EntryCell.java @@ -5,7 +5,7 @@ import com.sparrowwallet.drongo.address.Address; import com.sparrowwallet.drongo.protocol.Transaction; import com.sparrowwallet.drongo.protocol.TransactionOutput; import com.sparrowwallet.drongo.wallet.*; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.event.*; import com.sparrowwallet.sparrow.glyphfont.FontAwesome5; @@ -202,11 +202,11 @@ class EntryCell extends TreeTableCell { } private static Double getMaxFeeRate() { - if(AppController.getTargetBlockFeeRates().isEmpty()) { + if(AppServices.getTargetBlockFeeRates().isEmpty()) { return 100.0; } - return AppController.getTargetBlockFeeRates().values().iterator().next(); + return AppServices.getTargetBlockFeeRates().values().iterator().next(); } private static void sendSelectedUtxos(TreeTableView treeTableView, HashIndexEntry hashIndexEntry) { diff --git a/src/main/java/com/sparrowwallet/sparrow/control/IdLabel.java b/src/main/java/com/sparrowwallet/sparrow/control/IdLabel.java index 51a4d97c..26f99365 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/IdLabel.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/IdLabel.java @@ -1,6 +1,6 @@ package com.sparrowwallet.sparrow.control; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; public class IdLabel extends CopyableLabel { public IdLabel() { @@ -9,6 +9,6 @@ public class IdLabel extends CopyableLabel { public IdLabel(String text) { super(text); - setFont(AppController.getMonospaceFont()); + setFont(AppServices.getMonospaceFont()); } } diff --git a/src/main/java/com/sparrowwallet/sparrow/control/KeystorePassphraseDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/KeystorePassphraseDialog.java index 6995feb4..6184a789 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/KeystorePassphraseDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/KeystorePassphraseDialog.java @@ -1,7 +1,7 @@ package com.sparrowwallet.sparrow.control; import com.sparrowwallet.drongo.wallet.Keystore; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.glyphfont.FontAwesome5; import javafx.application.Platform; import javafx.scene.control.ButtonType; @@ -25,8 +25,8 @@ public class KeystorePassphraseDialog extends Dialog { final DialogPane dialogPane = getDialogPane(); setTitle("Keystore Passphrase" + (walletName != null ? " - " + walletName : "")); dialogPane.setHeaderText("Please enter the passphrase for keystore: \n" + keystore.getLabel()); - dialogPane.getStylesheets().add(AppController.class.getResource("general.css").toExternalForm()); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); dialogPane.getButtonTypes().addAll(ButtonType.CANCEL, ButtonType.OK); dialogPane.setPrefWidth(380); dialogPane.setPrefHeight(200); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/MessageSignDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/MessageSignDialog.java index 7d71ccd4..74daf1fe 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/MessageSignDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/MessageSignDialog.java @@ -12,7 +12,7 @@ import com.sparrowwallet.drongo.wallet.Keystore; import com.sparrowwallet.drongo.wallet.KeystoreSource; import com.sparrowwallet.drongo.wallet.Wallet; import com.sparrowwallet.drongo.wallet.WalletNode; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.event.OpenWalletsEvent; import com.sparrowwallet.sparrow.event.RequestOpenWalletsEvent; @@ -37,8 +37,6 @@ import java.security.SignatureException; import java.util.List; import java.util.Optional; -import static com.sparrowwallet.sparrow.AppController.setStageIcon; - public class MessageSignDialog extends Dialog { private static final Logger log = LoggerFactory.getLogger(MessageSignDialog.class); @@ -84,8 +82,8 @@ public class MessageSignDialog extends Dialog { this.walletNode = walletNode; final DialogPane dialogPane = getDialogPane(); - dialogPane.getStylesheets().add(AppController.class.getResource("general.css").toExternalForm()); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); dialogPane.setHeaderText(wallet == null ? "Verify Message" : "Sign/Verify Message"); Image image = new Image("image/seed.png", 50, 50, false, false); @@ -209,7 +207,7 @@ public class MessageSignDialog extends Dialog { private void signMessage() { if(walletNode == null) { - AppController.showErrorDialog("Address not in wallet", "The provided address is not present in the currently selected wallet."); + AppServices.showErrorDialog("Address not in wallet", "The provided address is not present in the currently selected wallet."); return; } @@ -234,7 +232,7 @@ public class MessageSignDialog extends Dialog { signature.appendText(signatureText); } catch(Exception e) { log.error("Could not sign message", e); - AppController.showErrorDialog("Could not sign message", e.getMessage()); + AppServices.showErrorDialog("Could not sign message", e.getMessage()); } } @@ -272,19 +270,19 @@ public class MessageSignDialog extends Dialog { if(verified) { Alert alert = new Alert(Alert.AlertType.INFORMATION); - setStageIcon(alert.getDialogPane().getScene().getWindow()); + AppServices.setStageIcon(alert.getDialogPane().getScene().getWindow()); alert.setTitle("Verification Succeeded"); alert.setHeaderText("Verification Succeeded"); alert.setContentText("The signature verified against the message."); alert.showAndWait(); } else { - AppController.showErrorDialog("Verification failed", "The provided signature did not match the message for this address."); + AppServices.showErrorDialog("Verification failed", "The provided signature did not match the message for this address."); } } catch(IllegalArgumentException e) { - AppController.showErrorDialog("Could not verify message", e.getMessage()); + AppServices.showErrorDialog("Could not verify message", e.getMessage()); } catch(Exception e) { log.error("Could not verify message", e); - AppController.showErrorDialog("Could not verify message", e.getMessage()); + AppServices.showErrorDialog("Could not verify message", e.getMessage()); } } @@ -320,7 +318,7 @@ public class MessageSignDialog extends Dialog { }); decryptWalletService.setOnFailed(workerStateEvent -> { EventManager.get().post(new StorageEvent(storage.getWalletFile(), TimedEvent.Action.END, "Failed")); - AppController.showErrorDialog("Incorrect Password", decryptWalletService.getException().getMessage()); + AppServices.showErrorDialog("Incorrect Password", decryptWalletService.getException().getMessage()); }); EventManager.get().post(new StorageEvent(storage.getWalletFile(), TimedEvent.Action.START, "Decrypting wallet...")); decryptWalletService.start(); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/QRDisplayDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/QRDisplayDialog.java index cf663b01..632f013f 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/QRDisplayDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/QRDisplayDialog.java @@ -7,7 +7,7 @@ import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.QRCodeWriter; import com.sparrowwallet.hummingbird.LegacyUREncoder; import com.sparrowwallet.hummingbird.registry.RegistryType; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.glyphfont.FontAwesome5; import com.sparrowwallet.sparrow.io.ImportException; import com.sparrowwallet.hummingbird.UR; @@ -63,7 +63,7 @@ public class QRDisplayDialog extends Dialog { final DialogPane dialogPane = new QRDisplayDialogPane(); setDialogPane(dialogPane); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); StackPane stackPane = new StackPane(); qrImageView = new ImageView(); @@ -102,7 +102,7 @@ public class QRDisplayDialog extends Dialog { this.encoder = null; final DialogPane dialogPane = getDialogPane(); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); StackPane stackPane = new StackPane(); qrImageView = new ImageView(); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/QRScanDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/QRScanDialog.java index e4a69d75..b4e7ca64 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/QRScanDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/QRScanDialog.java @@ -19,10 +19,10 @@ import com.sparrowwallet.drongo.wallet.Keystore; import com.sparrowwallet.drongo.wallet.Wallet; import com.sparrowwallet.hummingbird.LegacyURDecoder; import com.sparrowwallet.hummingbird.registry.*; -import com.sparrowwallet.sparrow.AppController; import com.sparrowwallet.hummingbird.ResultType; import com.sparrowwallet.hummingbird.UR; import com.sparrowwallet.hummingbird.URDecoder; +import com.sparrowwallet.sparrow.AppServices; import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; @@ -66,7 +66,7 @@ public class QRScanDialog extends Dialog { WebcamView webcamView = new WebcamView(webcamService); final DialogPane dialogPane = getDialogPane(); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); StackPane stackPane = new StackPane(); stackPane.getChildren().add(webcamView.getView()); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/SeedDisplayDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/SeedDisplayDialog.java index f9ed4c10..bb2ea730 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/SeedDisplayDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/SeedDisplayDialog.java @@ -1,7 +1,7 @@ package com.sparrowwallet.sparrow.control; import com.sparrowwallet.drongo.wallet.Keystore; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import javafx.application.Platform; import javafx.scene.control.*; import javafx.scene.layout.AnchorPane; @@ -10,8 +10,8 @@ import javafx.scene.layout.StackPane; public class SeedDisplayDialog extends Dialog { public SeedDisplayDialog(Keystore decryptedKeystore) { final DialogPane dialogPane = getDialogPane(); - dialogPane.getStylesheets().add(AppController.class.getResource("general.css").toExternalForm()); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); int lines = decryptedKeystore.getSeed().getMnemonicCode().size() / 3; int height = lines * 40; diff --git a/src/main/java/com/sparrowwallet/sparrow/control/TextAreaDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/TextAreaDialog.java index f0cc3333..01c6f129 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/TextAreaDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/TextAreaDialog.java @@ -1,6 +1,6 @@ package com.sparrowwallet.sparrow.control; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import javafx.application.Platform; import javafx.beans.NamedArg; import javafx.scene.control.*; @@ -29,8 +29,8 @@ public class TextAreaDialog extends Dialog { this.defaultValue = defaultValue; dialogPane.setContent(hbox); - dialogPane.getStylesheets().add(AppController.class.getResource("general.css").toExternalForm()); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); dialogPane.getStyleClass().add("text-input-dialog"); dialogPane.getButtonTypes().addAll(ButtonType.OK, ButtonType.CANCEL); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/TitledDescriptionPane.java b/src/main/java/com/sparrowwallet/sparrow/control/TitledDescriptionPane.java index 0507243f..7d5879ff 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/TitledDescriptionPane.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/TitledDescriptionPane.java @@ -1,6 +1,6 @@ package com.sparrowwallet.sparrow.control; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import javafx.application.Platform; import javafx.geometry.Insets; import javafx.geometry.Pos; @@ -21,7 +21,7 @@ public class TitledDescriptionPane extends TitledPane { protected HBox buttonBox; public TitledDescriptionPane(String title, String description, String content, String imageUrl) { - getStylesheets().add(AppController.class.getResource("general.css").toExternalForm()); + getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm()); getStyleClass().add("titled-description-pane"); setPadding(Insets.EMPTY); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/TransactionDiagram.java b/src/main/java/com/sparrowwallet/sparrow/control/TransactionDiagram.java index 46ffc331..23bcb978 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/TransactionDiagram.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/TransactionDiagram.java @@ -7,7 +7,7 @@ import com.sparrowwallet.drongo.wallet.BlockTransactionHashIndex; import com.sparrowwallet.drongo.wallet.Payment; import com.sparrowwallet.drongo.wallet.WalletNode; import com.sparrowwallet.drongo.wallet.WalletTransaction; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.event.ExcludeUtxoEvent; import com.sparrowwallet.sparrow.glyphfont.FontAwesome5; @@ -103,7 +103,7 @@ public class TransactionDiagram extends GridPane { for(Payment payment : walletTx.getPayments()) { try { Address address = payment.getAddress(); - BitcoinURI bitcoinURI = AppController.getPayjoinURI(address); + BitcoinURI bitcoinURI = AppServices.getPayjoinURI(address); if(bitcoinURI != null) { return bitcoinURI; } diff --git a/src/main/java/com/sparrowwallet/sparrow/control/TransactionIdDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/TransactionIdDialog.java index d722e407..f00e40f2 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/TransactionIdDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/TransactionIdDialog.java @@ -2,7 +2,7 @@ package com.sparrowwallet.sparrow.control; import com.sparrowwallet.drongo.Utils; import com.sparrowwallet.drongo.protocol.Sha256Hash; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import javafx.application.Platform; import javafx.beans.binding.Bindings; import javafx.beans.binding.BooleanBinding; @@ -23,13 +23,13 @@ public class TransactionIdDialog extends Dialog { public TransactionIdDialog() { this.txid = (CustomTextField) TextFields.createClearableTextField(); - txid.setFont(AppController.getMonospaceFont()); + txid.setFont(AppServices.getMonospaceFont()); final DialogPane dialogPane = getDialogPane(); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); setTitle("Load Transaction"); dialogPane.setHeaderText("Enter the transaction ID:"); - dialogPane.getStylesheets().add(AppController.class.getResource("general.css").toExternalForm()); + dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm()); dialogPane.getButtonTypes().addAll(ButtonType.CANCEL); dialogPane.setPrefWidth(550); dialogPane.setPrefHeight(200); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java index f4bebeef..46d1db6c 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java @@ -3,7 +3,7 @@ package com.sparrowwallet.sparrow.control; import com.google.common.eventbus.Subscribe; import com.sparrowwallet.drongo.policy.PolicyType; import com.sparrowwallet.drongo.wallet.Wallet; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.event.WalletExportEvent; import com.sparrowwallet.sparrow.io.*; @@ -23,7 +23,7 @@ public class WalletExportDialog extends Dialog { }); final DialogPane dialogPane = getDialogPane(); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); StackPane stackPane = new StackPane(); dialogPane.setContent(stackPane); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java index 3f145159..f3bf7d69 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java @@ -2,7 +2,7 @@ package com.sparrowwallet.sparrow.control; import com.google.common.eventbus.Subscribe; import com.sparrowwallet.drongo.wallet.Wallet; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.event.WalletImportEvent; import com.sparrowwallet.sparrow.io.*; @@ -22,7 +22,7 @@ public class WalletImportDialog extends Dialog { }); final DialogPane dialogPane = getDialogPane(); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); StackPane stackPane = new StackPane(); dialogPane.setContent(stackPane); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WalletNameDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/WalletNameDialog.java index a1cc6628..708d3082 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WalletNameDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WalletNameDialog.java @@ -1,6 +1,6 @@ package com.sparrowwallet.sparrow.control; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.glyphfont.FontAwesome5; import com.sparrowwallet.sparrow.io.Storage; import javafx.application.Platform; @@ -22,11 +22,11 @@ public class WalletNameDialog extends Dialog { public WalletNameDialog() { this.name = (CustomTextField)TextFields.createClearableTextField(); final DialogPane dialogPane = getDialogPane(); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); setTitle("Wallet Name"); dialogPane.setHeaderText("Enter a name for this wallet:"); - dialogPane.getStylesheets().add(AppController.class.getResource("general.css").toExternalForm()); + dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm()); dialogPane.getButtonTypes().addAll(ButtonType.CANCEL); dialogPane.setPrefWidth(380); dialogPane.setPrefHeight(200); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WalletPasswordDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/WalletPasswordDialog.java index 8c760747..d84cc03f 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WalletPasswordDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WalletPasswordDialog.java @@ -1,7 +1,7 @@ package com.sparrowwallet.sparrow.control; import com.sparrowwallet.drongo.SecureString; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import javafx.application.Platform; import javafx.beans.binding.Bindings; import javafx.beans.binding.BooleanBinding; @@ -37,8 +37,8 @@ public class WalletPasswordDialog extends Dialog { final DialogPane dialogPane = getDialogPane(); setTitle("Wallet Password" + (walletName != null ? " - " + walletName : "")); dialogPane.setHeaderText(walletName != null ? requirement.description.substring(0, requirement.description.length() - 1) + " for " + walletName + ":" : requirement.description); - dialogPane.getStylesheets().add(AppController.class.getResource("general.css").toExternalForm()); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); dialogPane.getButtonTypes().addAll(ButtonType.CANCEL); dialogPane.setPrefWidth(380); dialogPane.setPrefHeight(260); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WelcomeDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/WelcomeDialog.java index 81c850df..44192217 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WelcomeDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WelcomeDialog.java @@ -1,6 +1,6 @@ package com.sparrowwallet.sparrow.control; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.Mode; import javafx.application.HostServices; import javafx.geometry.Insets; @@ -27,8 +27,8 @@ public class WelcomeDialog extends Dialog { setTitle("Welcome to Sparrow"); dialogPane.setHeaderText("Welcome to Sparrow!"); - dialogPane.getStylesheets().add(AppController.class.getResource("general.css").toExternalForm()); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + dialogPane.getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); dialogPane.setPrefWidth(600); dialogPane.setPrefHeight(480); diff --git a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportController.java b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportController.java index 786916a0..b17d620a 100644 --- a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportController.java +++ b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportController.java @@ -2,7 +2,7 @@ package com.sparrowwallet.sparrow.keystoreimport; import com.sparrowwallet.drongo.wallet.KeystoreSource; import com.sparrowwallet.drongo.wallet.Wallet; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.io.Device; import javafx.application.Platform; import javafx.fxml.FXML; @@ -84,7 +84,7 @@ public class KeystoreImportController implements Initializable { importPane.getChildren().removeAll(importPane.getChildren()); try { - FXMLLoader importLoader = new FXMLLoader(AppController.class.getResource("keystoreimport/" + fxmlName + ".fxml")); + FXMLLoader importLoader = new FXMLLoader(AppServices.class.getResource("keystoreimport/" + fxmlName + ".fxml")); Node importTypeNode = importLoader.load(); KeystoreImportDetailController controller = importLoader.getController(); controller.setMasterController(this); diff --git a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportDialog.java b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportDialog.java index ec5c070a..fe1c8c4f 100644 --- a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/KeystoreImportDialog.java @@ -7,7 +7,7 @@ import com.sparrowwallet.drongo.wallet.Keystore; import com.sparrowwallet.drongo.wallet.KeystoreSource; import com.sparrowwallet.drongo.wallet.Wallet; import com.sparrowwallet.drongo.wallet.WalletModel; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.event.KeystoreImportEvent; import javafx.fxml.FXMLLoader; @@ -32,10 +32,10 @@ public class KeystoreImportDialog extends Dialog { }); final DialogPane dialogPane = getDialogPane(); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); try { - FXMLLoader ksiLoader = new FXMLLoader(AppController.class.getResource("keystoreimport/keystoreimport.fxml")); + FXMLLoader ksiLoader = new FXMLLoader(AppServices.class.getResource("keystoreimport/keystoreimport.fxml")); dialogPane.setContent(Borders.wrap(ksiLoader.load()).emptyBorder().buildAll()); keystoreImportController = ksiLoader.getController(); keystoreImportController.initializeView(wallet); diff --git a/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java b/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java index dd1321d4..963a1bb1 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/SimpleElectrumServerRpc.java @@ -7,7 +7,7 @@ import com.sparrowwallet.drongo.Utils; import com.sparrowwallet.drongo.protocol.Sha256Hash; import com.sparrowwallet.drongo.protocol.Transaction; import com.sparrowwallet.drongo.wallet.Wallet; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.event.WalletHistoryStatusEvent; import org.slf4j.Logger; @@ -209,7 +209,7 @@ public class SimpleElectrumServerRpc implements ElectrumServerRpc { VerboseTransaction verboseTransaction = new VerboseTransaction(); verboseTransaction.txid = id; verboseTransaction.hex = rawTxHex; - verboseTransaction.confirmations = (height <= 0 ? 0 : AppController.getCurrentBlockHeight() - height + 1); + verboseTransaction.confirmations = (height <= 0 ? 0 : AppServices.getCurrentBlockHeight() - height + 1); verboseTransaction.blockhash = Sha256Hash.ZERO_HASH.toString(); result.put(txid, verboseTransaction); } catch(Exception ex) { diff --git a/src/main/java/com/sparrowwallet/sparrow/net/VerboseTransaction.java b/src/main/java/com/sparrowwallet/sparrow/net/VerboseTransaction.java index 89f55fe8..55121033 100644 --- a/src/main/java/com/sparrowwallet/sparrow/net/VerboseTransaction.java +++ b/src/main/java/com/sparrowwallet/sparrow/net/VerboseTransaction.java @@ -5,7 +5,7 @@ import com.sparrowwallet.drongo.Utils; import com.sparrowwallet.drongo.protocol.Sha256Hash; import com.sparrowwallet.drongo.protocol.Transaction; import com.sparrowwallet.drongo.wallet.BlockTransaction; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import java.util.Date; @@ -26,7 +26,7 @@ class VerboseTransaction { return 0; } - Integer currentHeight = AppController.getCurrentBlockHeight(); + Integer currentHeight = AppServices.getCurrentBlockHeight(); if(currentHeight != null) { return currentHeight - confirmations + 1; } diff --git a/src/main/java/com/sparrowwallet/sparrow/preferences/PreferencesController.java b/src/main/java/com/sparrowwallet/sparrow/preferences/PreferencesController.java index 5d3ffa1b..551ca2e3 100644 --- a/src/main/java/com/sparrowwallet/sparrow/preferences/PreferencesController.java +++ b/src/main/java/com/sparrowwallet/sparrow/preferences/PreferencesController.java @@ -1,10 +1,7 @@ package com.sparrowwallet.sparrow.preferences; -import com.sparrowwallet.drongo.wallet.KeystoreSource; -import com.sparrowwallet.drongo.wallet.Wallet; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.io.Config; -import com.sparrowwallet.sparrow.keystoreimport.KeystoreImportDetailController; import javafx.application.Platform; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; @@ -63,7 +60,7 @@ public class PreferencesController implements Initializable { preferencesPane.getChildren().removeAll(preferencesPane.getChildren()); try { - FXMLLoader preferencesDetailLoader = new FXMLLoader(AppController.class.getResource("preferences/" + fxmlName + ".fxml")); + FXMLLoader preferencesDetailLoader = new FXMLLoader(AppServices.class.getResource("preferences/" + fxmlName + ".fxml")); Node preferenceGroupNode = preferencesDetailLoader.load(); PreferencesDetailController controller = preferencesDetailLoader.getController(); controller.setMasterController(this); diff --git a/src/main/java/com/sparrowwallet/sparrow/preferences/PreferencesDialog.java b/src/main/java/com/sparrowwallet/sparrow/preferences/PreferencesDialog.java index 2d5325c3..efb7efd2 100644 --- a/src/main/java/com/sparrowwallet/sparrow/preferences/PreferencesDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/preferences/PreferencesDialog.java @@ -1,6 +1,6 @@ package com.sparrowwallet.sparrow.preferences; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.event.RequestConnectEvent; import com.sparrowwallet.sparrow.io.Config; @@ -27,10 +27,10 @@ public class PreferencesDialog extends Dialog { public PreferencesDialog(PreferenceGroup initialGroup, boolean initialSetup) { final DialogPane dialogPane = getDialogPane(); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); try { - FXMLLoader preferencesLoader = new FXMLLoader(AppController.class.getResource("preferences/preferences.fxml")); + FXMLLoader preferencesLoader = new FXMLLoader(AppServices.class.getResource("preferences/preferences.fxml")); dialogPane.setContent(Borders.wrap(preferencesLoader.load()).emptyBorder().buildAll()); PreferencesController preferencesController = preferencesLoader.getController(); preferencesController.initializeView(Config.get()); diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java b/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java index c78fb386..6cfe5d0f 100644 --- a/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java +++ b/src/main/java/com/sparrowwallet/sparrow/transaction/HeadersController.java @@ -11,7 +11,7 @@ import com.sparrowwallet.drongo.uri.BitcoinURI; import com.sparrowwallet.drongo.wallet.*; import com.sparrowwallet.hummingbird.UR; import com.sparrowwallet.hummingbird.registry.RegistryType; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.control.*; import com.sparrowwallet.sparrow.event.*; @@ -252,8 +252,8 @@ public class HeadersController extends TransactionFormController implements Init locktimeFieldset.getChildren().add(locktimeBlockField); Integer block = locktimeBlock.getValue(); if(block != null) { - locktimeCurrentHeight.setVisible(headersForm.isEditable() && AppController.getCurrentBlockHeight() != null && block < AppController.getCurrentBlockHeight()); - futureBlockWarning.setVisible(AppController.getCurrentBlockHeight() != null && block > AppController.getCurrentBlockHeight()); + locktimeCurrentHeight.setVisible(headersForm.isEditable() && AppServices.getCurrentBlockHeight() != null && block < AppServices.getCurrentBlockHeight()); + futureBlockWarning.setVisible(AppServices.getCurrentBlockHeight() != null && block > AppServices.getCurrentBlockHeight()); tx.setLocktime(block); if(old_toggle != null) { EventManager.get().post(new TransactionChangedEvent(tx)); @@ -303,8 +303,8 @@ public class HeadersController extends TransactionFormController implements Init locktimeBlock.valueProperty().addListener((obs, oldValue, newValue) -> { tx.setLocktime(newValue); - locktimeCurrentHeight.setVisible(headersForm.isEditable() && AppController.getCurrentBlockHeight() != null && newValue < AppController.getCurrentBlockHeight()); - futureBlockWarning.setVisible(AppController.getCurrentBlockHeight() != null && newValue > AppController.getCurrentBlockHeight()); + locktimeCurrentHeight.setVisible(headersForm.isEditable() && AppServices.getCurrentBlockHeight() != null && newValue < AppServices.getCurrentBlockHeight()); + futureBlockWarning.setVisible(AppServices.getCurrentBlockHeight() != null && newValue > AppServices.getCurrentBlockHeight()); if(oldValue != null) { EventManager.get().post(new TransactionChangedEvent(tx)); EventManager.get().post(new TransactionLocktimeChangedEvent(tx)); @@ -360,7 +360,7 @@ public class HeadersController extends TransactionFormController implements Init broadcastButton.managedProperty().bind(broadcastButton.visibleProperty()); saveFinalButton.managedProperty().bind(saveFinalButton.visibleProperty()); saveFinalButton.visibleProperty().bind(broadcastButton.visibleProperty().not()); - broadcastButton.visibleProperty().bind(AppController.onlineProperty()); + broadcastButton.visibleProperty().bind(AppServices.onlineProperty()); BitcoinURI payjoinURI = getPayjoinURI(); boolean isPayjoinOriginalTx = payjoinURI != null && headersForm.getPsbt() != null && headersForm.getPsbt().getPsbtInputs().stream().noneMatch(PSBTInput::isFinalized); @@ -377,7 +377,7 @@ public class HeadersController extends TransactionFormController implements Init broadcastButtonBox.setVisible(false); if(headersForm.getBlockTransaction() != null) { - updateBlockchainForm(headersForm.getBlockTransaction(), AppController.getCurrentBlockHeight()); + updateBlockchainForm(headersForm.getBlockTransaction(), AppServices.getCurrentBlockHeight()); } else if(headersForm.getPsbt() != null) { PSBT psbt = headersForm.getPsbt(); @@ -558,7 +558,7 @@ public class HeadersController extends TransactionFormController implements Init for(TransactionOutput txOutput : headersForm.getPsbt().getTransaction().getOutputs()) { try { Address address = txOutput.getScript().getToAddresses()[0]; - BitcoinURI bitcoinURI = AppController.getPayjoinURI(address); + BitcoinURI bitcoinURI = AppServices.getPayjoinURI(address); if(bitcoinURI != null) { return bitcoinURI; } @@ -602,8 +602,8 @@ public class HeadersController extends TransactionFormController implements Init } public void setLocktimeToCurrentHeight(ActionEvent event) { - if(AppController.getCurrentBlockHeight() != null && locktimeBlock.isEditable()) { - locktimeBlock.getValueFactory().setValue(AppController.getCurrentBlockHeight()); + if(AppServices.getCurrentBlockHeight() != null && locktimeBlock.isEditable()) { + locktimeBlock.getValueFactory().setValue(AppServices.getCurrentBlockHeight()); Platform.runLater(() -> locktimeBlockType.requestFocus()); } } @@ -659,7 +659,7 @@ public class HeadersController extends TransactionFormController implements Init } } catch(IOException e) { log.error("Error saving PSBT", e); - AppController.showErrorDialog("Error saving PSBT", "Cannot write to " + file.getAbsolutePath()); + AppServices.showErrorDialog("Error saving PSBT", "Cannot write to " + file.getAbsolutePath()); } } } @@ -700,7 +700,7 @@ public class HeadersController extends TransactionFormController implements Init }); decryptWalletService.setOnFailed(workerStateEvent -> { EventManager.get().post(new StorageEvent(file, TimedEvent.Action.END, "Failed")); - AppController.showErrorDialog("Incorrect Password", decryptWalletService.getException().getMessage()); + AppServices.showErrorDialog("Incorrect Password", decryptWalletService.getException().getMessage()); }); EventManager.get().post(new StorageEvent(file, TimedEvent.Action.START, "Decrypting wallet...")); decryptWalletService.start(); @@ -716,7 +716,7 @@ public class HeadersController extends TransactionFormController implements Init updateSignedKeystores(headersForm.getSigningWallet()); } catch(Exception e) { log.warn("Failed to Sign", e); - AppController.showErrorDialog("Failed to Sign", e.getMessage()); + AppServices.showErrorDialog("Failed to Sign", e.getMessage()); } } @@ -726,7 +726,7 @@ public class HeadersController extends TransactionFormController implements Init } List fingerprints = headersForm.getSigningWallet().getKeystores().stream().map(keystore -> keystore.getKeyDerivation().getMasterFingerprint()).collect(Collectors.toList()); - List signingDevices = AppController.getDevices().stream().filter(device -> fingerprints.contains(device.getFingerprint())).collect(Collectors.toList()); + List signingDevices = AppServices.getDevices().stream().filter(device -> fingerprints.contains(device.getFingerprint())).collect(Collectors.toList()); if(signingDevices.isEmpty() && headersForm.getSigningWallet().getKeystores().stream().noneMatch(keystore -> keystore.getSource().equals(KeystoreSource.HW_USB))) { return; } @@ -788,7 +788,7 @@ public class HeadersController extends TransactionFormController implements Init broadcastTransactionService.setOnFailed(workerStateEvent -> { broadcastProgressBar.setProgress(0); log.error("Error broadcasting transaction", workerStateEvent.getSource().getException()); - AppController.showErrorDialog("Error broadcasting transaction", "The server returned an error when broadcasting the transaction. The server response is contained in sparrow.log"); + AppServices.showErrorDialog("Error broadcasting transaction", "The server returned an error when broadcasting the transaction. The server response is contained in sparrow.log"); broadcastButton.setDisable(false); }); @@ -816,7 +816,7 @@ public class HeadersController extends TransactionFormController implements Init } } catch(IOException e) { log.error("Error saving transaction", e); - AppController.showErrorDialog("Error saving transaction", "Cannot write to " + file.getAbsolutePath()); + AppServices.showErrorDialog("Error saving transaction", "Cannot write to " + file.getAbsolutePath()); } } } @@ -832,7 +832,7 @@ public class HeadersController extends TransactionFormController implements Init PSBT proposalPsbt = payjoin.requestPayjoinPSBT(true); EventManager.get().post(new ViewPSBTEvent(headersForm.getName() + " Payjoin", proposalPsbt)); } catch(PayjoinReceiverException e) { - AppController.showErrorDialog("Invalid Payjoin Transaction", e.getMessage()); + AppServices.showErrorDialog("Invalid Payjoin Transaction", e.getMessage()); } } @@ -844,8 +844,8 @@ public class HeadersController extends TransactionFormController implements Init blockTransaction = headersForm.getSigningWallet().getTransactions().get(txId); } - if(blockTransaction != null && AppController.getCurrentBlockHeight() != null) { - updateBlockchainForm(blockTransaction, AppController.getCurrentBlockHeight()); + if(blockTransaction != null && AppServices.getCurrentBlockHeight() != null) { + updateBlockchainForm(blockTransaction, AppServices.getCurrentBlockHeight()); } } @@ -867,7 +867,7 @@ public class HeadersController extends TransactionFormController implements Init public void blockTransactionFetched(BlockTransactionFetchedEvent event) { if(event.getTxId().equals(headersForm.getTransaction().getTxId())) { if(event.getBlockTransaction() != null && (!Sha256Hash.ZERO_HASH.equals(event.getBlockTransaction().getBlockHash()) || headersForm.getBlockTransaction() == null)) { - updateBlockchainForm(event.getBlockTransaction(), AppController.getCurrentBlockHeight()); + updateBlockchainForm(event.getBlockTransaction(), AppServices.getCurrentBlockHeight()); } Long feeAmt = calculateFee(event.getInputTransactions()); @@ -1021,7 +1021,7 @@ public class HeadersController extends TransactionFormController implements Init BlockTransaction blockTransaction = transactionMap.get(txid); if(blockTransaction != null) { headersForm.setBlockTransaction(blockTransaction); - updateBlockchainForm(blockTransaction, AppController.getCurrentBlockHeight()); + updateBlockchainForm(blockTransaction, AppServices.getCurrentBlockHeight()); } }); transactionReferenceService.setOnFailed(failEvent -> { @@ -1064,7 +1064,7 @@ public class HeadersController extends TransactionFormController implements Init updateBlockchainForm(headersForm.getBlockTransaction(), event.getHeight()); } if(futureBlockWarning.isVisible()) { - futureBlockWarning.setVisible(AppController.getCurrentBlockHeight() != null && locktimeBlock.getValue() > event.getHeight()); + futureBlockWarning.setVisible(AppServices.getCurrentBlockHeight() != null && locktimeBlock.getValue() > event.getHeight()); } } diff --git a/src/main/java/com/sparrowwallet/sparrow/transaction/TransactionController.java b/src/main/java/com/sparrowwallet/sparrow/transaction/TransactionController.java index 72bcb23c..6a9917db 100644 --- a/src/main/java/com/sparrowwallet/sparrow/transaction/TransactionController.java +++ b/src/main/java/com/sparrowwallet/sparrow/transaction/TransactionController.java @@ -6,7 +6,7 @@ import com.sparrowwallet.drongo.psbt.PSBT; import com.sparrowwallet.drongo.psbt.PSBTInput; import com.sparrowwallet.drongo.psbt.PSBTOutput; import com.sparrowwallet.drongo.wallet.BlockTransaction; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.TransactionTabData; import com.sparrowwallet.sparrow.control.TransactionDiagram; @@ -326,7 +326,7 @@ public class TransactionController implements Initializable { } private void fetchThisAndInputBlockTransactions(int indexStart, int indexEnd) { - if(AppController.isOnline() && indexStart < getTransaction().getInputs().size()) { + if(AppServices.isOnline() && indexStart < getTransaction().getInputs().size()) { Set references = new HashSet<>(); if(getPSBT() == null) { references.add(getTransaction().getTxId()); @@ -378,7 +378,7 @@ public class TransactionController implements Initializable { } private void fetchOutputBlockTransactions(int indexStart, int indexEnd) { - if(AppController.isOnline() && getPSBT() == null && indexStart < getTransaction().getOutputs().size()) { + if(AppServices.isOnline() && getPSBT() == null && indexStart < getTransaction().getOutputs().size()) { int maxIndex = Math.min(getTransaction().getOutputs().size(), indexEnd); ElectrumServer.TransactionOutputsReferenceService transactionOutputsReferenceService = new ElectrumServer.TransactionOutputsReferenceService(getTransaction(), indexStart, maxIndex); transactionOutputsReferenceService.setOnSucceeded(successEvent -> { diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/AdvancedDialog.java b/src/main/java/com/sparrowwallet/sparrow/wallet/AdvancedDialog.java index 3e1d41dc..32c8953f 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/AdvancedDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/AdvancedDialog.java @@ -1,7 +1,7 @@ package com.sparrowwallet.sparrow.wallet; import com.sparrowwallet.drongo.wallet.Wallet; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import javafx.fxml.FXMLLoader; import javafx.scene.control.ButtonBar; import javafx.scene.control.ButtonType; @@ -14,10 +14,10 @@ import java.io.IOException; public class AdvancedDialog extends Dialog { public AdvancedDialog(Wallet wallet) { final DialogPane dialogPane = getDialogPane(); - AppController.setStageIcon(dialogPane.getScene().getWindow()); + AppServices.setStageIcon(dialogPane.getScene().getWindow()); try { - FXMLLoader advancedLoader = new FXMLLoader(AppController.class.getResource("wallet/advanced.fxml")); + FXMLLoader advancedLoader = new FXMLLoader(AppServices.class.getResource("wallet/advanced.fxml")); dialogPane.setContent(Borders.wrap(advancedLoader.load()).emptyBorder().buildAll()); AdvancedController settingsAdvancedController = advancedLoader.getController(); settingsAdvancedController.initializeView(wallet); diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/KeystoreController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/KeystoreController.java index 33f8f718..ad206f7a 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/KeystoreController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/KeystoreController.java @@ -5,7 +5,7 @@ import com.sparrowwallet.drongo.*; import com.sparrowwallet.drongo.wallet.Keystore; import com.sparrowwallet.drongo.wallet.KeystoreSource; import com.sparrowwallet.drongo.wallet.Wallet; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.control.QRDisplayDialog; import com.sparrowwallet.sparrow.control.QRScanDialog; @@ -340,7 +340,7 @@ public class KeystoreController extends WalletFormController implements Initiali }); decryptWalletService.setOnFailed(workerStateEvent -> { EventManager.get().post(new StorageEvent(getWalletForm().getWalletFile(), TimedEvent.Action.END, "Failed")); - AppController.showErrorDialog("Incorrect Password", decryptWalletService.getException().getMessage()); + AppServices.showErrorDialog("Incorrect Password", decryptWalletService.getException().getMessage()); }); EventManager.get().post(new StorageEvent(getWalletForm().getWalletFile(), TimedEvent.Action.START, "Decrypting wallet...")); decryptWalletService.start(); @@ -364,9 +364,9 @@ public class KeystoreController extends WalletFormController implements Initiali xpub.setText(result.extendedKey.getExtendedKey()); } else if(result.exception != null) { log.error("Error scanning QR", result.exception); - AppController.showErrorDialog("Error scanning QR", result.exception.getMessage()); + AppServices.showErrorDialog("Error scanning QR", result.exception.getMessage()); } else { - AppController.showErrorDialog("Invalid QR Code", "QR Code did not contain a valid " + Network.get().getXpubHeader().getDisplayName()); + AppServices.showErrorDialog("Invalid QR Code", "QR Code did not contain a valid " + Network.get().getXpubHeader().getDisplayName()); } } } diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/PaymentController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/PaymentController.java index 8616f8c0..0198c674 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/PaymentController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/PaymentController.java @@ -11,7 +11,7 @@ import com.sparrowwallet.drongo.uri.BitcoinURI; import com.sparrowwallet.drongo.wallet.MaxUtxoSelector; import com.sparrowwallet.drongo.wallet.Payment; import com.sparrowwallet.drongo.wallet.UtxoSelector; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.CurrencyRate; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.control.CoinTextFormatter; @@ -74,7 +74,7 @@ public class PaymentController extends WalletFormController implements Initializ Long recipientValueSats = getRecipientValueSats(); if(recipientValueSats != null) { - setFiatAmount(AppController.getFiatCurrencyExchangeRate(), recipientValueSats); + setFiatAmount(AppServices.getFiatCurrencyExchangeRate(), recipientValueSats); } else { fiatAmount.setText(""); } @@ -260,7 +260,7 @@ public class PaymentController extends WalletFormController implements Initializ label.setText(payment.getLabel()); } setRecipientValueSats(payment.getAmount()); - setFiatAmount(AppController.getFiatCurrencyExchangeRate(), payment.getAmount()); + setFiatAmount(AppServices.getFiatCurrencyExchangeRate(), payment.getAmount()); } } @@ -320,7 +320,7 @@ public class PaymentController extends WalletFormController implements Initializ setRecipientValueSats(bitcoinURI.getAmount()); } if(bitcoinURI.getPayjoinUrl() != null) { - AppController.addPayjoinURI(bitcoinURI); + AppServices.addPayjoinURI(bitcoinURI); } sendController.updateTransaction(); } diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/ReceiveController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/ReceiveController.java index fe497c8f..3a468dec 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/ReceiveController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/ReceiveController.java @@ -14,7 +14,7 @@ import com.sparrowwallet.drongo.wallet.BlockTransactionHashIndex; import com.sparrowwallet.drongo.wallet.Keystore; import com.sparrowwallet.drongo.wallet.KeystoreSource; import com.sparrowwallet.drongo.wallet.Wallet; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.control.*; import com.sparrowwallet.sparrow.event.ReceiveToEvent; @@ -116,7 +116,7 @@ public class ReceiveController extends WalletFormController implements Initializ outputDescriptor.clear(); outputDescriptor.append(nodeEntry.getOutputDescriptor(), "descriptor-text"); - updateDisplayAddress(AppController.getDevices()); + updateDisplayAddress(AppServices.getDevices()); } private void updateDerivationPath(NodeEntry nodeEntry) { @@ -138,7 +138,7 @@ public class ReceiveController extends WalletFormController implements Initializ private void updateLastUsed() { Set currentOutputs = currentEntry.getNode().getTransactionOutputs(); - if(AppController.isOnline() && currentOutputs.isEmpty()) { + if(AppServices.isOnline() && currentOutputs.isEmpty()) { lastUsed.setText("Never"); lastUsed.setGraphic(getUnusedGlyph()); } else if(!currentOutputs.isEmpty()) { diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/SendController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/SendController.java index 579335b1..744fce2a 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/SendController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/SendController.java @@ -6,7 +6,7 @@ import com.sparrowwallet.drongo.address.InvalidAddressException; import com.sparrowwallet.drongo.protocol.Transaction; import com.sparrowwallet.drongo.psbt.PSBT; import com.sparrowwallet.drongo.wallet.*; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.CurrencyRate; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.control.*; @@ -128,7 +128,7 @@ public class SendController extends WalletFormController implements Initializabl if(newValue.isEmpty()) { fiatFeeAmount.setText(""); } else { - setFiatFeeAmount(AppController.getFiatCurrencyExchangeRate(), getFeeValueSats()); + setFiatFeeAmount(AppServices.getFiatCurrencyExchangeRate(), getFeeValueSats()); } setTargetBlocks(getTargetBlocks()); @@ -390,7 +390,7 @@ public class SendController extends WalletFormController implements Initializabl Tab tab = new Tab(Integer.toString(highestTabNo.isPresent() ? highestTabNo.getAsInt() + 1 : 1)); try { - FXMLLoader paymentLoader = new FXMLLoader(AppController.class.getResource("wallet/payment.fxml")); + FXMLLoader paymentLoader = new FXMLLoader(AppServices.class.getResource("wallet/payment.fxml")); tab.setContent(paymentLoader.load()); PaymentController controller = paymentLoader.getController(); controller.setSendController(this); @@ -451,7 +451,7 @@ public class SendController extends WalletFormController implements Initializabl if(!userFeeSet.get() || (getFeeValueSats() != null && getFeeValueSats() > 0)) { Wallet wallet = getWalletForm().getWallet(); Long userFee = userFeeSet.get() ? getFeeValueSats() : null; - Integer currentBlockHeight = AppController.getCurrentBlockHeight(); + Integer currentBlockHeight = AppServices.getCurrentBlockHeight(); boolean groupByAddress = Config.get().isGroupByAddress(); boolean includeMempoolChange = Config.get().isIncludeMempoolChange(); boolean includeMempoolInputs = includeMempoolInputsProperty.get(); @@ -532,7 +532,7 @@ public class SendController extends WalletFormController implements Initializabl df.setMaximumFractionDigits(8); fee.setText(df.format(feeAmountUnit.getValue().getValue(feeValue))); fee.textProperty().addListener(feeListener); - setFiatFeeAmount(AppController.getFiatCurrencyExchangeRate(), feeValue); + setFiatFeeAmount(AppServices.getFiatCurrencyExchangeRate(), feeValue); } private Integer getTargetBlocks() { @@ -565,7 +565,7 @@ public class SendController extends WalletFormController implements Initializabl } private Map getTargetBlocksFeeRates() { - Map retrievedFeeRates = AppController.getTargetBlockFeeRates(); + Map retrievedFeeRates = AppServices.getTargetBlockFeeRates(); if(retrievedFeeRates == null) { retrievedFeeRates = TARGET_BLOCKS_RANGE.stream().collect(Collectors.toMap(java.util.function.Function.identity(), v -> FALLBACK_FEE_RATE, (u, v) -> { throw new IllegalStateException("Duplicate target blocks"); }, @@ -600,11 +600,11 @@ public class SendController extends WalletFormController implements Initializabl } private Map> getMempoolHistogram() { - return AppController.getMempoolHistogram(); + return AppServices.getMempoolHistogram(); } public boolean isInsufficientFeeRate() { - return walletTransactionProperty.get() != null && walletTransactionProperty.get().getFeeRate() < AppController.getMinimumRelayFeeRate(); + return walletTransactionProperty.get() != null && walletTransactionProperty.get().getFeeRate() < AppServices.getMinimumRelayFeeRate(); } private void setFeeRate(Double feeRateAmt) { diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/SettingsController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/SettingsController.java index bf44be1c..aa0586f5 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/SettingsController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/SettingsController.java @@ -11,7 +11,7 @@ import com.sparrowwallet.drongo.wallet.Keystore; import com.sparrowwallet.drongo.wallet.KeystoreSource; import com.sparrowwallet.drongo.wallet.Wallet; import com.sparrowwallet.drongo.wallet.WalletModel; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.control.*; import com.sparrowwallet.sparrow.event.RequestOpenWalletsEvent; @@ -223,7 +223,7 @@ public class SettingsController extends WalletFormController implements Initiali tab.setClosable(false); try { - FXMLLoader keystoreLoader = new FXMLLoader(AppController.class.getResource("wallet/keystore.fxml")); + FXMLLoader keystoreLoader = new FXMLLoader(AppServices.class.getResource("wallet/keystore.fxml")); tab.setContent(keystoreLoader.load()); KeystoreController controller = keystoreLoader.getController(); controller.setKeystore(getWalletForm(), keystore); @@ -258,7 +258,7 @@ public class SettingsController extends WalletFormController implements Initiali } else if(result.payload != null && !result.payload.isEmpty()) { setDescriptorText(result.payload); } else if(result.exception != null) { - AppController.showErrorDialog("Error scanning QR", result.exception.getMessage()); + AppServices.showErrorDialog("Error scanning QR", result.exception.getMessage()); } } } @@ -291,7 +291,7 @@ public class SettingsController extends WalletFormController implements Initiali EventManager.get().post(new SettingsChangedEvent(editedWallet, SettingsChangedEvent.Type.POLICY)); } catch(Exception e) { - AppController.showErrorDialog("Invalid output descriptor", e.getMessage()); + AppServices.showErrorDialog("Invalid output descriptor", e.getMessage()); } } @@ -353,7 +353,7 @@ public class SettingsController extends WalletFormController implements Initiali walletForm.saveBackup(); } catch(IOException e) { log.error("Error saving wallet backup", e); - AppController.showErrorDialog("Error saving wallet backup", e.getMessage()); + AppServices.showErrorDialog("Error saving wallet backup", e.getMessage()); revert.setDisable(false); apply.setDisable(false); return; @@ -369,7 +369,7 @@ public class SettingsController extends WalletFormController implements Initiali } } catch (IOException e) { log.error("Error saving wallet", e); - AppController.showErrorDialog("Error saving wallet", e.getMessage()); + AppServices.showErrorDialog("Error saving wallet", e.getMessage()); revert.setDisable(false); apply.setDisable(false); } @@ -384,7 +384,7 @@ public class SettingsController extends WalletFormController implements Initiali ECKey encryptionPubKey = ECKey.fromPublicOnly(encryptionFullKey); if(existingPubKey != null && !Storage.NO_PASSWORD_KEY.equals(existingPubKey) && !existingPubKey.equals(encryptionPubKey)) { - AppController.showErrorDialog("Incorrect Password", "The password was incorrect."); + AppServices.showErrorDialog("Incorrect Password", "The password was incorrect."); revert.setDisable(false); apply.setDisable(false); return; @@ -406,7 +406,7 @@ public class SettingsController extends WalletFormController implements Initiali } } catch (Exception e) { log.error("Error saving wallet", e); - AppController.showErrorDialog("Error saving wallet", e.getMessage()); + AppServices.showErrorDialog("Error saving wallet", e.getMessage()); revert.setDisable(false); apply.setDisable(false); } finally { @@ -418,7 +418,7 @@ public class SettingsController extends WalletFormController implements Initiali }); keyDerivationService.setOnFailed(workerStateEvent -> { EventManager.get().post(new StorageEvent(walletForm.getWalletFile(), TimedEvent.Action.END, "Failed")); - AppController.showErrorDialog("Error saving wallet", keyDerivationService.getException().getMessage()); + AppServices.showErrorDialog("Error saving wallet", keyDerivationService.getException().getMessage()); revert.setDisable(false); apply.setDisable(false); }); diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/TransactionsController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/TransactionsController.java index d22ba682..b418b9e6 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/TransactionsController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/TransactionsController.java @@ -1,7 +1,7 @@ package com.sparrowwallet.sparrow.wallet; import com.google.common.eventbus.Subscribe; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.CurrencyRate; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.control.BalanceChart; @@ -47,7 +47,7 @@ public class TransactionsController extends WalletFormController implements Init transactionsTable.initialize(walletTransactionsEntry); balance.valueProperty().addListener((observable, oldValue, newValue) -> { - setFiatBalance(AppController.getFiatCurrencyExchangeRate(), newValue.longValue()); + setFiatBalance(AppServices.getFiatCurrencyExchangeRate(), newValue.longValue()); }); balance.setValue(walletTransactionsEntry.getBalance()); mempoolBalance.setValue(walletTransactionsEntry.getMempoolBalance()); diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/WalletController.java b/src/main/java/com/sparrowwallet/sparrow/wallet/WalletController.java index bec99fd2..a664d52b 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/WalletController.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/WalletController.java @@ -1,7 +1,7 @@ package com.sparrowwallet.sparrow.wallet; import com.google.common.eventbus.Subscribe; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.event.ReceiveActionEvent; import com.sparrowwallet.sparrow.event.SendActionEvent; @@ -57,7 +57,7 @@ public class WalletController extends WalletFormController implements Initializa try { if(!existing) { - FXMLLoader functionLoader = new FXMLLoader(AppController.class.getResource("wallet/" + function.toString().toLowerCase() + ".fxml")); + FXMLLoader functionLoader = new FXMLLoader(AppServices.class.getResource("wallet/" + function.toString().toLowerCase() + ".fxml")); Node walletFunction = functionLoader.load(); walletFunction.setUserData(function); WalletFormController controller = functionLoader.getController(); diff --git a/src/main/java/com/sparrowwallet/sparrow/wallet/WalletForm.java b/src/main/java/com/sparrowwallet/sparrow/wallet/WalletForm.java index 92426abb..a2167dc4 100644 --- a/src/main/java/com/sparrowwallet/sparrow/wallet/WalletForm.java +++ b/src/main/java/com/sparrowwallet/sparrow/wallet/WalletForm.java @@ -4,7 +4,7 @@ import com.google.common.eventbus.Subscribe; import com.sparrowwallet.drongo.KeyPurpose; import com.sparrowwallet.drongo.wallet.Wallet; import com.sparrowwallet.drongo.wallet.WalletNode; -import com.sparrowwallet.sparrow.AppController; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.WalletTabData; import com.sparrowwallet.sparrow.event.*; @@ -32,7 +32,7 @@ public class WalletForm { public WalletForm(Storage storage, Wallet currentWallet) { this.storage = storage; this.wallet = currentWallet; - refreshHistory(AppController.getCurrentBlockHeight()); + refreshHistory(AppServices.getCurrentBlockHeight()); } public Wallet getWallet() { @@ -62,7 +62,7 @@ public class WalletForm { public void saveAndRefresh() throws IOException { wallet.clearHistory(); save(); - refreshHistory(AppController.getCurrentBlockHeight()); + refreshHistory(AppServices.getCurrentBlockHeight()); } public void saveBackup() throws IOException { @@ -75,7 +75,7 @@ public class WalletForm { public void refreshHistory(Integer blockHeight, WalletNode node) { Wallet previousWallet = wallet.copy(); - if(wallet.isValid() && AppController.isOnline()) { + if(wallet.isValid() && AppServices.isOnline()) { log.debug(node == null ? "Refreshing full wallet history" : "Requesting node wallet history for " + node.getDerivationPath()); ElectrumServer.TransactionHistoryService historyService = new ElectrumServer.TransactionHistoryService(wallet, getWalletTransactionNodes(node)); historyService.setOnSucceeded(workerStateEvent -> { @@ -226,7 +226,7 @@ public class WalletForm { walletUtxosEntry = null; accountEntries.clear(); EventManager.get().post(new WalletNodesChangedEvent(wallet)); - refreshHistory(AppController.getCurrentBlockHeight()); + refreshHistory(AppServices.getCurrentBlockHeight()); } } @@ -249,7 +249,7 @@ public class WalletForm { WalletNode walletNode = event.getWalletNode(wallet); if(walletNode != null) { log.debug(wallet.getName() + " history event for node " + walletNode); - refreshHistory(AppController.getCurrentBlockHeight(), walletNode); + refreshHistory(AppServices.getCurrentBlockHeight(), walletNode); } } }