scan seed qr to bip39 and watch only keystores

This commit is contained in:
Craig Raw 2022-05-17 09:18:09 +02:00
parent 948d663fbf
commit 766a8c267f
4 changed files with 58 additions and 21 deletions

View file

@ -24,18 +24,6 @@ public class MnemonicKeystoreDisplayPane extends MnemonicKeystorePane {
showWordList(keystore.getSeed()); showWordList(keystore.getSeed());
} }
private void showWordList(DeterministicSeed seed) {
List<String> words = seed.getMnemonicCode();
setContent(getMnemonicWordsEntry(words.size()));
setExpanded(true);
for(int i = 0; i < wordsPane.getChildren().size(); i++) {
WordEntry wordEntry = (WordEntry)wordsPane.getChildren().get(i);
wordEntry.getEditor().setText(words.get(i));
wordEntry.getEditor().setEditable(false);
}
}
protected Node getMnemonicWordsEntry(int numWords) { protected Node getMnemonicWordsEntry(int numWords) {
VBox vBox = new VBox(); VBox vBox = new VBox();
vBox.setSpacing(10); vBox.setSpacing(10);

View file

@ -1,6 +1,8 @@
package com.sparrowwallet.sparrow.control; package com.sparrowwallet.sparrow.control;
import com.sparrowwallet.drongo.wallet.Bip39MnemonicCode; import com.sparrowwallet.drongo.wallet.Bip39MnemonicCode;
import com.sparrowwallet.drongo.wallet.DeterministicSeed;
import com.sparrowwallet.sparrow.AppServices;
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5; import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.property.IntegerProperty; import javafx.beans.property.IntegerProperty;
@ -26,13 +28,16 @@ import org.controlsfx.validation.ValidationResult;
import org.controlsfx.validation.ValidationSupport; import org.controlsfx.validation.ValidationSupport;
import org.controlsfx.validation.Validator; import org.controlsfx.validation.Validator;
import org.controlsfx.validation.decoration.StyleClassValidationDecoration; import org.controlsfx.validation.decoration.StyleClassValidationDecoration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.Collections; import static com.sparrowwallet.sparrow.AppServices.showErrorDialog;
import java.util.List;
public class MnemonicKeystorePane extends TitledDescriptionPane { public class MnemonicKeystorePane extends TitledDescriptionPane {
private static final Logger log = LoggerFactory.getLogger(MnemonicKeystorePane.class);
protected SplitMenuButton enterMnemonicButton; protected SplitMenuButton enterMnemonicButton;
protected TilePane wordsPane; protected TilePane wordsPane;
protected Label validLabel; protected Label validLabel;
@ -73,9 +78,44 @@ public class MnemonicKeystorePane extends TitledDescriptionPane {
}); });
enterMnemonicButton.getItems().add(item); enterMnemonicButton.getItems().add(item);
} }
enterMnemonicButton.getItems().add(new SeparatorMenuItem());
MenuItem scanItem = new MenuItem("Scan QR...");
scanItem.setOnAction(event -> {
scanQR();
});
enterMnemonicButton.getItems().add(scanItem);
enterMnemonicButton.managedProperty().bind(enterMnemonicButton.visibleProperty()); enterMnemonicButton.managedProperty().bind(enterMnemonicButton.visibleProperty());
} }
protected void scanQR() {
QRScanDialog qrScanDialog = new QRScanDialog();
Optional<QRScanDialog.Result> optionalResult = qrScanDialog.showAndWait();
if(optionalResult.isPresent()) {
QRScanDialog.Result result = optionalResult.get();
if(result.seed != null) {
showWordList(result.seed);
Platform.runLater(() -> validLabel.requestFocus());
} else if(result.exception != null) {
log.error("Error scanning QR", result.exception);
showErrorDialog("Error scanning QR", result.exception.getMessage());
} else {
AppServices.showErrorDialog("Invalid QR Code", "Cannot parse QR code into a seed.");
}
}
}
protected void showWordList(DeterministicSeed seed) {
List<String> words = seed.getMnemonicCode();
setContent(getMnemonicWordsEntry(words.size()));
setExpanded(true);
for(int i = 0; i < wordsPane.getChildren().size(); i++) {
WordEntry wordEntry = (WordEntry)wordsPane.getChildren().get(i);
wordEntry.getEditor().setText(words.get(i));
wordEntry.getEditor().setEditable(false);
}
}
protected void enterMnemonic(int numWords) { protected void enterMnemonic(int numWords) {
setDescription("Generate new or enter existing"); setDescription("Generate new or enter existing");
showHideLink.setVisible(false); showHideLink.setVisible(false);

View file

@ -549,7 +549,7 @@ public class QRScanDialog extends Dialog<QRScanDialog.Result> {
} }
private DeterministicSeed getSeed(CryptoSeed cryptoSeed) { private DeterministicSeed getSeed(CryptoSeed cryptoSeed) {
return new DeterministicSeed(cryptoSeed.getSeed(), null, cryptoSeed.getBirthdate().getTime()); return new DeterministicSeed(cryptoSeed.getSeed(), null, cryptoSeed.getBirthdate() == null ? System.currentTimeMillis() : cryptoSeed.getBirthdate().getTime());
} }
private DeterministicSeed getSeed(CryptoBip39 cryptoBip39) { private DeterministicSeed getSeed(CryptoBip39 cryptoBip39) {

View file

@ -2,10 +2,7 @@ package com.sparrowwallet.sparrow.wallet;
import com.google.common.eventbus.Subscribe; import com.google.common.eventbus.Subscribe;
import com.sparrowwallet.drongo.*; import com.sparrowwallet.drongo.*;
import com.sparrowwallet.drongo.wallet.Keystore; import com.sparrowwallet.drongo.wallet.*;
import com.sparrowwallet.drongo.wallet.KeystoreSource;
import com.sparrowwallet.drongo.wallet.Wallet;
import com.sparrowwallet.drongo.wallet.WalletModel;
import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.AppServices;
import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.EventManager;
import com.sparrowwallet.sparrow.control.*; import com.sparrowwallet.sparrow.control.*;
@ -413,6 +410,18 @@ public class KeystoreController extends WalletFormController implements Initiali
} }
AppServices.showErrorDialog("Missing Script Type", "QR Code did not contain any information for the " + getWalletForm().getWallet().getScriptType().getDescription() + " script type."); AppServices.showErrorDialog("Missing Script Type", "QR Code did not contain any information for the " + getWalletForm().getWallet().getScriptType().getDescription() + " script type.");
} else if(result.seed != null) {
try {
Keystore keystore = Keystore.fromSeed(result.seed, getWalletForm().getWallet().getScriptType().getDefaultDerivation());
fingerprint.setText(keystore.getKeyDerivation().getMasterFingerprint());
derivation.setText(keystore.getKeyDerivation().getDerivationPath());
xpub.setText(keystore.getExtendedPublicKey().toString());
} catch(MnemonicException e) {
log.error("Error parsing seed", e);
AppServices.showErrorDialog("Error parsing seed", e.getMessage());
} finally {
result.seed.clear();
}
} else if(result.exception != null) { } else if(result.exception != null) {
log.error("Error scanning QR", result.exception); log.error("Error scanning QR", result.exception);
AppServices.showErrorDialog("Error scanning QR", result.exception.getMessage()); AppServices.showErrorDialog("Error scanning QR", result.exception.getMessage());