From 95200c714388bc43e5aa1f3f5b1d91d184a9a97b Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Wed, 22 Jan 2025 12:59:23 +0200 Subject: [PATCH] improve bitbox pairing flow --- drongo | 2 +- lark | 2 +- .../sparrow/control/BitBoxPairingDialog.java | 33 +++++++++++++++++++ .../com/sparrowwallet/sparrow/io/Hwi.java | 33 +++++++++++++------ 4 files changed, 58 insertions(+), 12 deletions(-) create mode 100644 src/main/java/com/sparrowwallet/sparrow/control/BitBoxPairingDialog.java diff --git a/drongo b/drongo index 89a6b129..0df1f79e 160000 --- a/drongo +++ b/drongo @@ -1 +1 @@ -Subproject commit 89a6b1296e75508eae498f0199928cff0b8a660c +Subproject commit 0df1f79e5c7e9fc1daa212c875c9da5dbcc0ee56 diff --git a/lark b/lark index 52918405..6bfa13a3 160000 --- a/lark +++ b/lark @@ -1 +1 @@ -Subproject commit 529184057a7ac5e0ccad9c84dd4b32796a8e835d +Subproject commit 6bfa13a3afccddeac2f4148a8abaaefed552261f diff --git a/src/main/java/com/sparrowwallet/sparrow/control/BitBoxPairingDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/BitBoxPairingDialog.java new file mode 100644 index 00000000..09e1464f --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/control/BitBoxPairingDialog.java @@ -0,0 +1,33 @@ +package com.sparrowwallet.sparrow.control; + +import com.sparrowwallet.sparrow.AppServices; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.control.Alert; +import javafx.scene.control.ButtonType; +import javafx.scene.control.Label; +import javafx.scene.layout.VBox; + +import static com.sparrowwallet.sparrow.AppServices.*; + +public class BitBoxPairingDialog extends Alert { + public BitBoxPairingDialog(String code) { + super(AlertType.INFORMATION); + initOwner(getActiveWindow()); + setStageIcon(getDialogPane().getScene().getWindow()); + getDialogPane().getStylesheets().add(AppServices.class.getResource("general.css").toExternalForm()); + setTitle("Confirm BitBox02 Pairing"); + setHeaderText(getTitle()); + VBox vBox = new VBox(20); + vBox.setAlignment(Pos.CENTER); + vBox.setPadding(new Insets(10, 20, 10, 20)); + Label instructions = new Label("Confirm the following code is shown on BitBox02"); + Label codeLabel = new Label(code); + codeLabel.getStyleClass().add("fixed-width"); + vBox.getChildren().addAll(instructions, codeLabel); + getDialogPane().setContent(vBox); + moveToActiveWindowScreen(this); + getDialogPane().getButtonTypes().clear(); + getDialogPane().getButtonTypes().add(ButtonType.CLOSE); + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/io/Hwi.java b/src/main/java/com/sparrowwallet/sparrow/io/Hwi.java index 4be64397..d74f5674 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/Hwi.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/Hwi.java @@ -11,11 +11,11 @@ import com.sparrowwallet.lark.DeviceException; import com.sparrowwallet.lark.Lark; import com.sparrowwallet.lark.bitbox02.BitBoxFileNoiseConfig; import com.sparrowwallet.sparrow.AppServices; +import com.sparrowwallet.sparrow.control.BitBoxPairingDialog; import javafx.application.Platform; import javafx.concurrent.ScheduledService; import javafx.concurrent.Service; import javafx.concurrent.Task; -import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,6 +31,8 @@ import java.util.concurrent.atomic.AtomicBoolean; public class Hwi { private static final Logger log = LoggerFactory.getLogger(Hwi.class); private static final String HWI_HOME_DIR = "hwi"; + private static final String LARK_HOME_DIR = "lark"; + private static final String BITBOX_FILENAME = "bitbox02.json"; private static boolean isPromptActive = false; @@ -482,32 +484,34 @@ public class Hwi { } private static final class BitBoxFxNoiseConfig extends BitBoxFileNoiseConfig { + private BitBoxPairingDialog pairingDialog; + public BitBoxFxNoiseConfig() { - super(Path.of(Storage.getSparrowDir().getAbsolutePath(), "lark", "bitbox02.json").toFile()); + super(Path.of(Storage.getSparrowHome().getAbsolutePath(), LARK_HOME_DIR, BITBOX_FILENAME).toFile()); } @Override public boolean showPairing(String code, DeviceResponse response) throws DeviceException { - CountDownLatch latch = new CountDownLatch(2); + CountDownLatch latch = new CountDownLatch(1); AtomicBoolean confirmedDevice = new AtomicBoolean(false); - AtomicBoolean confirmedApp = new AtomicBoolean(false); Thread showPairingDeviceThread = new Thread(() -> { try { + isPromptActive = true; confirmedDevice.set(response.call()); latch.countDown(); } catch(DeviceException e) { throw new RuntimeException(e); + } finally { + isPromptActive = false; } }); showPairingDeviceThread.start(); Platform.runLater(() -> { - Optional optConfirm = AppServices.showAlertDialog("Confirm Pairing", "Confirm the following code is shown on BitBox02:\n\n" + code, Alert.AlertType.CONFIRMATION, ButtonType.NO, ButtonType.YES); - if(optConfirm.isPresent() && optConfirm.get() == ButtonType.YES) { - confirmedApp.set(true); - } - latch.countDown(); + pairingDialog = new BitBoxPairingDialog(code); + pairingDialog.initOwner(AppServices.getActiveWindow()); + pairingDialog.show(); }); try { @@ -516,7 +520,16 @@ public class Hwi { Thread.currentThread().interrupt(); } - return confirmedDevice.get() && confirmedApp.get(); + Platform.runLater(() -> { + if(pairingDialog != null && pairingDialog.isShowing()) { + pairingDialog.setResult(ButtonType.APPLY); + } + if(!confirmedDevice.get()) { + AppServices.showWarningDialog("Pairing Refused", "Pairing was refused on the device."); + } + }); + + return confirmedDevice.get(); } } }