software wallet import and airgapped fixes

This commit is contained in:
Craig Raw 2020-04-29 16:51:33 +02:00
parent ae03da257a
commit 7a554df619
16 changed files with 83 additions and 22 deletions

2
drongo

@ -1 +1 @@
Subproject commit cbffaf3e416e0d94a01a9c00c99d9f2d61018d1e Subproject commit 019a3cf34f60da053ca7b5540e2bb7bcee6fbd50

View file

@ -57,11 +57,17 @@ public class DevicePane extends TitledPane {
getStyleClass().add("devicepane"); getStyleClass().add("devicepane");
setDefaultStatus(); setDefaultStatus();
removeArrow();
}
private void removeArrow() {
Platform.runLater(() -> { Platform.runLater(() -> {
Node arrow = this.lookup(".arrow"); Node arrow = this.lookup(".arrow");
if (arrow != null) { if (arrow != null) {
arrow.setVisible(false); arrow.setVisible(false);
arrow.setManaged(false); arrow.setManaged(false);
} else {
removeArrow();
} }
}); });
} }

View file

@ -1,5 +1,6 @@
package com.sparrowwallet.sparrow.control; package com.sparrowwallet.sparrow.control;
import com.google.gson.JsonParseException;
import com.sparrowwallet.drongo.wallet.Keystore; import com.sparrowwallet.drongo.wallet.Keystore;
import com.sparrowwallet.drongo.wallet.Wallet; import com.sparrowwallet.drongo.wallet.Wallet;
import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.EventManager;
@ -42,11 +43,17 @@ public class KeystoreFileImportPane extends TitledPane {
getStyleClass().add("importpane"); getStyleClass().add("importpane");
setContent(getContentBox(importer.getKeystoreImportDescription())); setContent(getContentBox(importer.getKeystoreImportDescription()));
removeArrow();
}
private void removeArrow() {
Platform.runLater(() -> { Platform.runLater(() -> {
Node arrow = this.lookup(".arrow"); Node arrow = this.lookup(".arrow");
if (arrow != null) { if (arrow != null) {
arrow.setVisible(false); arrow.setVisible(false);
arrow.setManaged(false); arrow.setManaged(false);
} else {
removeArrow();
} }
}); });
} }
@ -133,7 +140,14 @@ public class KeystoreFileImportPane extends TitledPane {
descriptionLabel.getStyleClass().remove("description-label"); descriptionLabel.getStyleClass().remove("description-label");
descriptionLabel.getStyleClass().add("description-error"); descriptionLabel.getStyleClass().add("description-error");
descriptionLabel.setText("Error Importing [View Details...]"); descriptionLabel.setText("Error Importing [View Details...]");
setContent(getContentBox(e.getMessage())); String errorMessage = e.getMessage();
if(e.getCause() != null) {
errorMessage = e.getCause().getMessage();
}
if(e instanceof JsonParseException || e.getCause() instanceof JsonParseException) {
errorMessage = "File was not in JSON format";
}
setContent(getContentBox(errorMessage));
} }
} }
} }
@ -143,10 +157,14 @@ public class KeystoreFileImportPane extends TitledPane {
details.setWrapText(true); details.setWrapText(true);
HBox contentBox = new HBox(); HBox contentBox = new HBox();
contentBox.setAlignment(Pos.TOP_RIGHT); contentBox.setAlignment(Pos.TOP_LEFT);
contentBox.getChildren().add(details); contentBox.getChildren().add(details);
contentBox.setPadding(new Insets(10, 30, 10, 30)); contentBox.setPadding(new Insets(10, 30, 10, 30));
contentBox.setPrefHeight(60);
double width = TextUtils.computeTextWidth(details.getFont(), message, 0.0D);
double numLines = Math.max(1, width / 400);
double height = Math.max(60, numLines * 40);
contentBox.setPrefHeight(height);
return contentBox; return contentBox;
} }

View file

@ -21,7 +21,7 @@ public class KeystoreImportAccordion extends Accordion {
if(importer instanceof KeystoreFileImport) { if(importer instanceof KeystoreFileImport) {
importPane = new KeystoreFileImportPane(this, wallet, (KeystoreFileImport)importer); importPane = new KeystoreFileImportPane(this, wallet, (KeystoreFileImport)importer);
} else if(importer instanceof KeystoreMnemonicImport) { } else if(importer instanceof KeystoreMnemonicImport) {
//TODO: //TODO: Import from the new Bip39KeystoreImport
} else { } else {
throw new IllegalArgumentException("Could not create ImportPane for importer of type " + importer.getClass()); throw new IllegalArgumentException("Could not create ImportPane for importer of type " + importer.getClass());
} }

View file

@ -37,7 +37,7 @@ public class Electrum implements KeystoreFileImport, SinglesigWalletImport, Mult
@Override @Override
public String getKeystoreImportDescription() { public String getKeystoreImportDescription() {
return "Import from an Electrum wallet"; return "Import a single keystore from an Electrum wallet (use File > Import > Electrum to import a multisig wallet)";
} }
@Override @Override
@ -45,12 +45,12 @@ public class Electrum implements KeystoreFileImport, SinglesigWalletImport, Mult
Wallet wallet = importWallet(inputStream); Wallet wallet = importWallet(inputStream);
if(!wallet.getPolicyType().equals(PolicyType.SINGLE) || wallet.getKeystores().size() != 1) { if(!wallet.getPolicyType().equals(PolicyType.SINGLE) || wallet.getKeystores().size() != 1) {
throw new ImportException("Multisig wallet detected - import it through the File > Import menu"); throw new ImportException("Multisig wallet detected - import it using File > Import > Electrum");
} }
if(!wallet.getScriptType().equals(scriptType)) { if(!wallet.getScriptType().equals(scriptType)) {
//TODO: Derive appropriate ScriptType keystore //TODO: Derive appropriate ScriptType keystore from xprv if present
throw new ImportException("Wallet has an incompatible script type of " + wallet.getScriptType()); throw new ImportException("Wallet has an incompatible script type of " + wallet.getScriptType() + ", and the correct script type cannot be derived without the master private key");
} }
return wallet.getKeystores().get(0); return wallet.getKeystores().get(0);
@ -88,7 +88,7 @@ public class Electrum implements KeystoreFileImport, SinglesigWalletImport, Mult
keystore.setSource(KeystoreSource.HW_USB); keystore.setSource(KeystoreSource.HW_USB);
keystore.setWalletModel(WalletModel.fromType(ek.hw_type)); keystore.setWalletModel(WalletModel.fromType(ek.hw_type));
if(keystore.getWalletModel() == null) { if(keystore.getWalletModel() == null) {
throw new ImportException("Unknown hardware wallet type " + ek.hw_type); throw new ImportException("Wallet has keystore of unknown hardware wallet type \"" + ek.hw_type + "\"");
} }
} else if("bip32".equals(ek.type)) { } else if("bip32".equals(ek.type)) {
if(ek.xprv != null) { if(ek.xprv != null) {

View file

@ -11,7 +11,7 @@ import javafx.fxml.FXML;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
public class UsbAirgappedController extends KeystoreImportDetailController { public class HwAirgappedController extends KeystoreImportDetailController {
@FXML @FXML
private KeystoreImportAccordion importAccordion; private KeystoreImportAccordion importAccordion;

View file

@ -7,7 +7,7 @@ import javafx.fxml.FXML;
import java.util.List; import java.util.List;
public class UsbDevicesController extends KeystoreImportDetailController { public class HwUsbDevicesController extends KeystoreImportDetailController {
@FXML @FXML
private DeviceAccordion deviceAccordion; private DeviceAccordion deviceAccordion;

View file

@ -9,7 +9,7 @@ import javafx.scene.control.Label;
import java.util.List; import java.util.List;
public class UsbScanController extends KeystoreImportDetailController { public class HwUsbScanController extends KeystoreImportDetailController {
@FXML @FXML
private Label message; private Label message;

View file

@ -39,19 +39,23 @@ public class KeystoreImportController implements Initializable {
importMenu.selectedToggleProperty().addListener((observable, oldValue, selectedToggle) -> { importMenu.selectedToggleProperty().addListener((observable, oldValue, selectedToggle) -> {
KeystoreSource importType = (KeystoreSource) selectedToggle.getUserData(); KeystoreSource importType = (KeystoreSource) selectedToggle.getUserData();
System.out.println(importType); System.out.println(importType);
setImportPane(importType.toString().toLowerCase()); String fxmlName = importType.toString().toLowerCase();
if(importType == KeystoreSource.SW_SEED || importType == KeystoreSource.SW_WATCH) {
fxmlName = "sw";
}
setImportPane(fxmlName);
}); });
} }
void showUsbDevices(List<Device> devices) { void showUsbDevices(List<Device> devices) {
FXMLLoader loader = setImportPane("hw_usb-devices"); FXMLLoader loader = setImportPane("hw_usb-devices");
UsbDevicesController controller = loader.getController(); HwUsbDevicesController controller = loader.getController();
controller.initializeView(devices); controller.initializeView(devices);
} }
void showUsbError(String message) { void showUsbError(String message) {
FXMLLoader loader = setImportPane("hw_usb-error"); FXMLLoader loader = setImportPane("hw_usb-error");
UsbScanController controller = loader.getController(); HwUsbScanController controller = loader.getController();
controller.initializeView(message); controller.initializeView(message);
} }

View file

@ -0,0 +1,19 @@
package com.sparrowwallet.sparrow.keystoreimport;
import com.sparrowwallet.sparrow.control.KeystoreImportAccordion;
import com.sparrowwallet.sparrow.external.Electrum;
import com.sparrowwallet.sparrow.external.KeystoreImport;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import java.util.List;
public class SwController extends KeystoreImportDetailController {
@FXML
private KeystoreImportAccordion importAccordion;
public void initializeView() {
List<KeystoreImport> importers = List.of(new Electrum());
importAccordion.setKeystoreImporters(getMasterController().getWallet(), FXCollections.observableList(importers));
}
}

View file

@ -8,7 +8,7 @@
<?import com.sparrowwallet.sparrow.control.KeystoreImportAccordion?> <?import com.sparrowwallet.sparrow.control.KeystoreImportAccordion?>
<AnchorPane stylesheets="@keystoreimport.css" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.keystoreimport.UsbAirgappedController"> <AnchorPane stylesheets="@keystoreimport.css" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.keystoreimport.HwAirgappedController">
<ScrollPane AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0" fitToWidth="true"> <ScrollPane AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0" fitToWidth="true">
<KeystoreImportAccordion fx:id="importAccordion" /> <KeystoreImportAccordion fx:id="importAccordion" />
</ScrollPane> </ScrollPane>

View file

@ -7,7 +7,7 @@
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import com.sparrowwallet.sparrow.control.DeviceAccordion?> <?import com.sparrowwallet.sparrow.control.DeviceAccordion?>
<AnchorPane stylesheets="@keystoreimport.css" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.keystoreimport.UsbDevicesController"> <AnchorPane stylesheets="@keystoreimport.css" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.keystoreimport.HwUsbDevicesController">
<ScrollPane AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0" fitToWidth="true"> <ScrollPane AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0" fitToWidth="true">
<DeviceAccordion fx:id="deviceAccordion" /> <DeviceAccordion fx:id="deviceAccordion" />
</ScrollPane> </ScrollPane>

View file

@ -7,7 +7,7 @@
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<?import org.controlsfx.glyphfont.Glyph?> <?import org.controlsfx.glyphfont.Glyph?>
<VBox alignment="CENTER" spacing="30" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.keystoreimport.UsbScanController"> <VBox alignment="CENTER" spacing="30" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.keystoreimport.HwUsbScanController">
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="50" icon="EXCLAMATION_CIRCLE" /> <Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="50" icon="EXCLAMATION_CIRCLE" />
<Label text="There was error connecting to the wallet:" /> <Label text="There was error connecting to the wallet:" />
<Label fx:id="message" /> <Label fx:id="message" />

View file

@ -10,7 +10,7 @@
<?import javafx.scene.image.ImageView?> <?import javafx.scene.image.ImageView?>
<?import org.controlsfx.glyphfont.Glyph?> <?import org.controlsfx.glyphfont.Glyph?>
<VBox alignment="CENTER" spacing="30" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.keystoreimport.UsbScanController"> <VBox alignment="CENTER" spacing="30" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.keystoreimport.HwUsbScanController">
<Glyph fontFamily="Font Awesome 5 Brands Regular" fontSize="50" icon="USB" /> <Glyph fontFamily="Font Awesome 5 Brands Regular" fontSize="50" icon="USB" />
<Label fx:id="message" text="Connect Hardware Wallet" /> <Label fx:id="message" text="Connect Hardware Wallet" />
<Button fx:id="scan" text="Scan..." wrapText="true" prefWidth="120" prefHeight="60" onAction="#scan"/> <Button fx:id="scan" text="Scan..." wrapText="true" prefWidth="120" prefHeight="60" onAction="#scan"/>

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import com.sparrowwallet.sparrow.control.KeystoreImportAccordion?>
<AnchorPane stylesheets="@keystoreimport.css" xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="com.sparrowwallet.sparrow.keystoreimport.SwController">
<ScrollPane AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0" fitToWidth="true">
<KeystoreImportAccordion fx:id="importAccordion" />
</ScrollPane>
</AnchorPane>

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB