bip39 word list usability improvements

This commit is contained in:
Craig Raw 2020-08-17 19:42:30 +02:00
parent 75bf63d936
commit e878648587
2 changed files with 37 additions and 9 deletions

View file

@ -40,6 +40,7 @@ public class MnemonicKeystoreImportPane extends TitledDescriptionPane {
private TilePane wordsPane; private TilePane wordsPane;
private Button verifyButton; private Button verifyButton;
private Button backButton;
private Button confirmButton; private Button confirmButton;
private List<String> generatedMnemonicCode; private List<String> generatedMnemonicCode;
@ -148,7 +149,7 @@ public class MnemonicKeystoreImportPane extends TitledDescriptionPane {
if(!displayWordsOnly) { if(!displayWordsOnly) {
PassphraseEntry passphraseEntry = new PassphraseEntry(); PassphraseEntry passphraseEntry = new PassphraseEntry();
passphraseEntry.setPadding(new Insets(0, 32, 0, 10)); passphraseEntry.setPadding(new Insets(0, 32, 10, 10));
vBox.getChildren().add(passphraseEntry); vBox.getChildren().add(passphraseEntry);
AnchorPane buttonPane = new AnchorPane(); AnchorPane buttonPane = new AnchorPane();
@ -158,16 +159,18 @@ public class MnemonicKeystoreImportPane extends TitledDescriptionPane {
generateButton.setOnAction(event -> { generateButton.setOnAction(event -> {
generateNew(); generateNew();
}); });
generateButton.setTooltip(new Tooltip("Generate a unique set of words that provide the seed for your wallet"));
buttonPane.getChildren().add(generateButton); buttonPane.getChildren().add(generateButton);
AnchorPane.setLeftAnchor(generateButton, 0.0); AnchorPane.setLeftAnchor(generateButton, 0.0);
confirmButton = new Button("Confirm Backup"); confirmButton = new Button("Confirm Written Backup");
confirmButton.setOnAction(event -> { confirmButton.setOnAction(event -> {
confirmBackup(); confirmBackup();
}); });
confirmButton.managedProperty().bind(confirmButton.visibleProperty()); confirmButton.managedProperty().bind(confirmButton.visibleProperty());
confirmButton.setVisible(false); confirmButton.setVisible(false);
confirmButton.setDefaultButton(true); confirmButton.setDefaultButton(true);
confirmButton.setTooltip(new Tooltip("Write down the words above as a backup - you will need to re-enter them to confirm your backup is correct"));
buttonPane.getChildren().add(confirmButton); buttonPane.getChildren().add(confirmButton);
AnchorPane.setRightAnchor(confirmButton, 0.0); AnchorPane.setRightAnchor(confirmButton, 0.0);
@ -178,6 +181,15 @@ public class MnemonicKeystoreImportPane extends TitledDescriptionPane {
prepareImport(); prepareImport();
}); });
verifyButton.managedProperty().bind(verifyButton.visibleProperty()); verifyButton.managedProperty().bind(verifyButton.visibleProperty());
verifyButton.setTooltip(new Tooltip("Enter the words you have just written down to confirm the backup is correct"));
backButton = new Button("Back");
backButton.setOnAction(event -> {
displayMnemonicCode();
});
backButton.managedProperty().bind(backButton.visibleProperty());
backButton.setTooltip(new Tooltip("Go back to the generated word list"));
backButton.setVisible(false);
wordEntriesProperty.addListener((ListChangeListener<String>) c -> { wordEntriesProperty.addListener((ListChangeListener<String>) c -> {
for(String word : wordEntryList) { for(String word : wordEntryList) {
@ -189,8 +201,13 @@ public class MnemonicKeystoreImportPane extends TitledDescriptionPane {
verifyButton.setDisable(false); verifyButton.setDisable(false);
}); });
buttonPane.getChildren().add(verifyButton);
AnchorPane.setRightAnchor(verifyButton, 0.0); HBox rightBox = new HBox();
rightBox.setSpacing(10);
rightBox.getChildren().addAll(backButton, verifyButton);
buttonPane.getChildren().add(rightBox);
AnchorPane.setRightAnchor(rightBox, 0.0);
vBox.getChildren().add(buttonPane); vBox.getChildren().add(buttonPane);
} }
@ -199,14 +216,19 @@ public class MnemonicKeystoreImportPane extends TitledDescriptionPane {
} }
private void generateNew() { private void generateNew() {
setDescription("Write down word list to confirm backup");
showHideLink.setVisible(false);
int mnemonicSeedLength = wordEntriesProperty.get().size() * 11; int mnemonicSeedLength = wordEntriesProperty.get().size() * 11;
int entropyLength = mnemonicSeedLength - (mnemonicSeedLength/33); int entropyLength = mnemonicSeedLength - (mnemonicSeedLength/33);
DeterministicSeed deterministicSeed = new DeterministicSeed(new SecureRandom(), entropyLength, ""); DeterministicSeed deterministicSeed = new DeterministicSeed(new SecureRandom(), entropyLength, "");
generatedMnemonicCode = deterministicSeed.getMnemonicCode(); generatedMnemonicCode = deterministicSeed.getMnemonicCode();
displayMnemonicCode();
}
private void displayMnemonicCode() {
setDescription("Write down word list to confirm backup");
showHideLink.setVisible(false);
if(generatedMnemonicCode.size() != wordsPane.getChildren().size()) { if(generatedMnemonicCode.size() != wordsPane.getChildren().size()) {
throw new IllegalStateException("Generated mnemonic words list not same size as displayed words list"); throw new IllegalStateException("Generated mnemonic words list not same size as displayed words list");
} }
@ -219,6 +241,7 @@ public class MnemonicKeystoreImportPane extends TitledDescriptionPane {
verifyButton.setVisible(false); verifyButton.setVisible(false);
confirmButton.setVisible(true); confirmButton.setVisible(true);
backButton.setVisible(false);
} }
private void confirmBackup() { private void confirmBackup() {
@ -226,6 +249,7 @@ public class MnemonicKeystoreImportPane extends TitledDescriptionPane {
showHideLink.setVisible(false); showHideLink.setVisible(false);
setContent(getMnemonicWordsEntry(wordEntriesProperty.get().size(), false)); setContent(getMnemonicWordsEntry(wordEntriesProperty.get().size(), false));
setExpanded(true); setExpanded(true);
backButton.setVisible(true);
} }
private void prepareImport() { private void prepareImport() {
@ -341,7 +365,11 @@ public class MnemonicKeystoreImportPane extends TitledDescriptionPane {
passphraseProperty.bind(passphraseField.textProperty()); passphraseProperty.bind(passphraseField.textProperty());
passphraseField.setPromptText("Leave blank for none"); passphraseField.setPromptText("Leave blank for none");
getChildren().addAll(passphraseLabel, passphraseField); HelpLabel helpLabel = new HelpLabel();
helpLabel.setStyle("-fx-padding: 0 0 0 0");
helpLabel.setHelpText("A passphrase provides optional added security - it is not stored so it must be remembered!");
getChildren().addAll(passphraseLabel, passphraseField, helpLabel);
} }
} }

View file

@ -39,7 +39,7 @@ public class KeystoreImportDialog extends Dialog<Keystore> {
final ButtonType cancelButtonType = new javafx.scene.control.ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE); final ButtonType cancelButtonType = new javafx.scene.control.ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);
dialogPane.getButtonTypes().addAll(cancelButtonType); dialogPane.getButtonTypes().addAll(cancelButtonType);
dialogPane.setPrefWidth(650); dialogPane.setPrefWidth(650);
dialogPane.setPrefHeight(600); dialogPane.setPrefHeight(620);
setResultConverter(dialogButton -> dialogButton != cancelButtonType ? keystore : null); setResultConverter(dialogButton -> dialogButton != cancelButtonType ? keystore : null);
} catch(IOException e) { } catch(IOException e) {