diff --git a/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java b/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java index 916810eb..c6d3df14 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/DevicePane.java @@ -325,12 +325,22 @@ public class DevicePane extends TitledDescriptionPane { passphrase.bind(passphraseField.textProperty()); HBox.setHgrow(passphraseField, Priority.ALWAYS); - Button sendPassphraseButton = new Button("Send Passphrase"); + SplitMenuButton sendPassphraseButton = new SplitMenuButton(); + sendPassphraseButton.setText("Send Passphrase"); sendPassphraseButton.setOnAction(event -> { setExpanded(false); + setDescription("Confirm passphrase on device..."); sendPassphrase(passphrase.get()); }); + MenuItem removePassphrase = new MenuItem("Toggle Passphrase Off"); + removePassphrase.setOnAction(event -> { + setExpanded(false); + setDescription("Toggling passphrase off, check device..."); + togglePassphraseOff(); + }); + sendPassphraseButton.getItems().add(removePassphrase); + HBox contentBox = new HBox(); contentBox.setAlignment(Pos.TOP_RIGHT); contentBox.setSpacing(20); @@ -343,6 +353,35 @@ public class DevicePane extends TitledDescriptionPane { return contentBox; } + private Node getTogglePassphraseOn() { + CopyableLabel label = new CopyableLabel("Passphrase is currently disabled"); + HBox.setHgrow(label, Priority.ALWAYS); + + Button togglePassphraseOn = new Button("Toggle Passphrase On"); + togglePassphraseOn.setOnAction(event -> { + setExpanded(false); + hideButtons(importButton, signButton, displayAddressButton, signMessageButton); + setDescription("Toggling passphrase on, check device..."); + togglePassphraseOn(); + }); + + HBox contentBox = new HBox(); + contentBox.setSpacing(20); + contentBox.setAlignment(Pos.CENTER_LEFT); + contentBox.getChildren().addAll(label, togglePassphraseOn); + contentBox.setPadding(new Insets(10, 30, 10, 30)); + + return contentBox; + } + + private void hideButtons(Node... buttons) { + for(Node button : buttons) { + if(button != null) { + button.setVisible(false); + } + } + } + private void promptPin() { Hwi.PromptPinService promptPinService = new Hwi.PromptPinService(device); promptPinService.setOnSucceeded(workerStateEvent -> { @@ -356,7 +395,7 @@ public class DevicePane extends TitledDescriptionPane { } }); promptPinService.setOnFailed(workerStateEvent -> { - setError(promptPinService.getException().getMessage(), null); + setError("Error", promptPinService.getException().getMessage()); unlockButton.setDisable(false); }); promptPinService.start(); @@ -379,6 +418,7 @@ public class DevicePane extends TitledDescriptionPane { setExpanded(true); } else { showOperationButton(); + setContent(getTogglePassphraseOn()); } } else { setError("Incorrect PIN", null); @@ -418,13 +458,43 @@ public class DevicePane extends TitledDescriptionPane { } }); enumerateService.setOnFailed(workerStateEvent -> { - setError(enumerateService.getException().getMessage(), null); + setError("Error", enumerateService.getException().getMessage()); setPassphraseButton.setDisable(false); setPassphraseButton.setVisible(true); }); enumerateService.start(); } + private void togglePassphraseOff() { + Hwi.TogglePassphraseService togglePassphraseService = new Hwi.TogglePassphraseService(device); + togglePassphraseService.setOnSucceeded(workerStateEvent -> { + device.setNeedsPassphraseSent(false); + setPassphraseButton.setVisible(false); + setDescription("Unlocked"); + showOperationButton(); + }); + togglePassphraseService.setOnFailed(workerStateEvent -> { + setError("Error", togglePassphraseService.getException().getMessage()); + }); + togglePassphraseService.start(); + } + + private void togglePassphraseOn() { + Hwi.TogglePassphraseService togglePassphraseService = new Hwi.TogglePassphraseService(device); + togglePassphraseService.setOnSucceeded(workerStateEvent -> { + device.setNeedsPassphraseSent(true); + setPassphraseButton.setVisible(true); + setPassphraseButton.setDisable(true); + setDescription("Enter passphrase"); + setContent(getPassphraseEntry()); + setExpanded(true); + }); + togglePassphraseService.setOnFailed(workerStateEvent -> { + setError("Error", togglePassphraseService.getException().getMessage()); + }); + togglePassphraseService.start(); + } + private void importKeystore(List derivation) { if(device.getFingerprint() == null) { Hwi.EnumerateService enumerateService = new Hwi.EnumerateService(passphrase.get()); @@ -439,7 +509,7 @@ public class DevicePane extends TitledDescriptionPane { importXpub(derivation); }); enumerateService.setOnFailed(workerStateEvent -> { - setError(enumerateService.getException().getMessage(), null); + setError("Error", enumerateService.getException().getMessage()); importButton.setDisable(false); }); enumerateService.start(); diff --git a/src/main/java/com/sparrowwallet/sparrow/io/Hwi.java b/src/main/java/com/sparrowwallet/sparrow/io/Hwi.java index 36a56fd6..8c8264ed 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/Hwi.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/Hwi.java @@ -78,6 +78,16 @@ public class Hwi { } } + public boolean togglePassphrase(Device device) throws ImportException { + try { + String output = execute(getDeviceCommand(device, Command.TOGGLE_PASSPHRASE)); + isPromptActive = false; + return wasSuccessful(output); + } catch(IOException e) { + throw new ImportException(e); + } + } + public String getXpub(Device device, String passphrase, String derivationPath) throws ImportException { try { String output; @@ -468,6 +478,24 @@ public class Hwi { } } + public static class TogglePassphraseService extends Service { + private final Device device; + + public TogglePassphraseService(Device device) { + this.device = device; + } + + @Override + protected Task createTask() { + return new Task<>() { + protected Boolean call() throws ImportException { + Hwi hwi = new Hwi(); + return hwi.togglePassphrase(device); + } + }; + } + } + public static class DisplayAddressService extends Service { private final Device device; private final String passphrase; @@ -595,6 +623,7 @@ public class Hwi { ENUMERATE("enumerate", true), PROMPT_PIN("promptpin", true), SEND_PIN("sendpin", false), + TOGGLE_PASSPHRASE("togglepassphrase", true), DISPLAY_ADDRESS("displayaddress", true), SIGN_MESSAGE("signmessage", true), GET_XPUB("getxpub", true),