mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-24 12:46:45 +00:00
import airgapped keystores
This commit is contained in:
parent
40d31ff025
commit
728b6efbdf
19 changed files with 340 additions and 45 deletions
2
drongo
2
drongo
|
@ -1 +1 @@
|
||||||
Subproject commit ed056bc49fb919799f70a6d7ee2dd65a38c25b5d
|
Subproject commit d740895bd68f0ded97e382e5944feb26fa759875
|
|
@ -37,8 +37,8 @@ public class MainApp extends Application {
|
||||||
appController.initializeView();
|
appController.initializeView();
|
||||||
|
|
||||||
Wallet wallet = new Wallet();
|
Wallet wallet = new Wallet();
|
||||||
wallet.setPolicyType(PolicyType.SINGLE);
|
wallet.setPolicyType(PolicyType.MULTI);
|
||||||
wallet.setScriptType(ScriptType.P2PKH);
|
wallet.setScriptType(ScriptType.P2SH);
|
||||||
|
|
||||||
KeystoreImportDialog dlg = new KeystoreImportDialog(wallet);
|
KeystoreImportDialog dlg = new KeystoreImportDialog(wallet);
|
||||||
dlg.showAndWait();
|
dlg.showAndWait();
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class DevicePane extends TitledPane {
|
||||||
this.wallet = wallet;
|
this.wallet = wallet;
|
||||||
this.device = device;
|
this.device = device;
|
||||||
|
|
||||||
setPadding(new Insets(0, 0, 0, 0));
|
setPadding(Insets.EMPTY);
|
||||||
|
|
||||||
setGraphic(getTitle());
|
setGraphic(getTitle());
|
||||||
getStyleClass().add("devicepane");
|
getStyleClass().add("devicepane");
|
||||||
|
@ -92,14 +92,14 @@ public class DevicePane extends TitledPane {
|
||||||
labelsBox.setAlignment(Pos.CENTER_LEFT);
|
labelsBox.setAlignment(Pos.CENTER_LEFT);
|
||||||
this.mainLabel = new Label();
|
this.mainLabel = new Label();
|
||||||
mainLabel.setText(device.getModel().toDisplayString());
|
mainLabel.setText(device.getModel().toDisplayString());
|
||||||
mainLabel.getStyleClass().add("devicelist-main-label");
|
mainLabel.getStyleClass().add("main-label");
|
||||||
labelsBox.getChildren().add(mainLabel);
|
labelsBox.getChildren().add(mainLabel);
|
||||||
|
|
||||||
this.statusLabel = new Label();
|
this.statusLabel = new Label();
|
||||||
statusLabel.textProperty().bind(status);
|
statusLabel.textProperty().bind(status);
|
||||||
|
|
||||||
labelsBox.getChildren().add(statusLabel);
|
labelsBox.getChildren().add(statusLabel);
|
||||||
statusLabel.getStyleClass().add("devicelist-status-label");
|
statusLabel.getStyleClass().add("status-label");
|
||||||
listItem.getChildren().add(labelsBox);
|
listItem.getChildren().add(labelsBox);
|
||||||
HBox.setHgrow(labelsBox, Priority.ALWAYS);
|
HBox.setHgrow(labelsBox, Priority.ALWAYS);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||||
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
|
import com.sparrowwallet.sparrow.event.KeystoreImportEvent;
|
||||||
|
import com.sparrowwallet.sparrow.external.KeystoreFileImport;
|
||||||
|
import javafx.application.Platform;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.TitledPane;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.Priority;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import javafx.stage.FileChooser;
|
||||||
|
import javafx.stage.Stage;
|
||||||
|
import org.controlsfx.control.HyperlinkLabel;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class KeystoreFileImportPane extends TitledPane {
|
||||||
|
private final KeystoreImportAccordion importAccordion;
|
||||||
|
private final Wallet wallet;
|
||||||
|
private final KeystoreFileImport importer;
|
||||||
|
|
||||||
|
private Label mainLabel;
|
||||||
|
private HyperlinkLabel descriptionLabel;
|
||||||
|
|
||||||
|
public KeystoreFileImportPane(KeystoreImportAccordion importAccordion, Wallet wallet, KeystoreFileImport importer) {
|
||||||
|
this.importAccordion = importAccordion;
|
||||||
|
this.wallet = wallet;
|
||||||
|
this.importer = importer;
|
||||||
|
|
||||||
|
setPadding(Insets.EMPTY);
|
||||||
|
|
||||||
|
setGraphic(getTitle());
|
||||||
|
getStyleClass().add("importpane");
|
||||||
|
setContent(getContentBox(importer.getKeystoreImportDescription()));
|
||||||
|
|
||||||
|
Platform.runLater(() -> {
|
||||||
|
Node arrow = this.lookup(".arrow");
|
||||||
|
if(arrow != null) {
|
||||||
|
arrow.setVisible(false);
|
||||||
|
arrow.setManaged(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node getTitle() {
|
||||||
|
HBox listItem = new HBox();
|
||||||
|
listItem.setPadding(new Insets(10, 20, 10, 10));
|
||||||
|
listItem.setSpacing(10);
|
||||||
|
|
||||||
|
HBox imageBox = new HBox();
|
||||||
|
imageBox.setMinWidth(50);
|
||||||
|
imageBox.setMinHeight(50);
|
||||||
|
listItem.getChildren().add(imageBox);
|
||||||
|
|
||||||
|
Image image = new Image("image/" + importer.getWalletModel().getType() + ".png", 50, 50, true, true);
|
||||||
|
if (!image.isError()) {
|
||||||
|
ImageView imageView = new ImageView();
|
||||||
|
imageView.setImage(image);
|
||||||
|
imageBox.getChildren().add(imageView);
|
||||||
|
}
|
||||||
|
|
||||||
|
VBox labelsBox = new VBox();
|
||||||
|
labelsBox.setSpacing(5);
|
||||||
|
labelsBox.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
this.mainLabel = new Label();
|
||||||
|
mainLabel.setText(importer.getName());
|
||||||
|
mainLabel.getStyleClass().add("main-label");
|
||||||
|
labelsBox.getChildren().add(mainLabel);
|
||||||
|
|
||||||
|
this.descriptionLabel = new HyperlinkLabel();
|
||||||
|
|
||||||
|
labelsBox.getChildren().add(descriptionLabel);
|
||||||
|
descriptionLabel.getStyleClass().add("description-label");
|
||||||
|
descriptionLabel.setText("Keystore file import [View Details...]");
|
||||||
|
descriptionLabel.setOnAction(event -> {
|
||||||
|
setExpanded(true);
|
||||||
|
});
|
||||||
|
listItem.getChildren().add(labelsBox);
|
||||||
|
HBox.setHgrow(labelsBox, Priority.ALWAYS);
|
||||||
|
|
||||||
|
HBox buttonBox = new HBox();
|
||||||
|
buttonBox.setAlignment(Pos.CENTER_RIGHT);
|
||||||
|
|
||||||
|
Button importButton = new Button("Import File...");
|
||||||
|
importButton.setAlignment(Pos.CENTER_RIGHT);
|
||||||
|
importButton.setOnAction(event -> {
|
||||||
|
importFile();
|
||||||
|
});
|
||||||
|
|
||||||
|
buttonBox.getChildren().add(importButton);
|
||||||
|
listItem.getChildren().add(buttonBox);
|
||||||
|
|
||||||
|
this.layoutBoundsProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
listItem.setPrefWidth(newValue.getWidth());
|
||||||
|
});
|
||||||
|
|
||||||
|
return listItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void importFile() {
|
||||||
|
Stage window = new Stage();
|
||||||
|
|
||||||
|
FileChooser fileChooser = new FileChooser();
|
||||||
|
fileChooser.setTitle("Open " + importer.getWalletModel().toDisplayString() + " keystore");
|
||||||
|
fileChooser.getExtensionFilters().addAll(
|
||||||
|
new FileChooser.ExtensionFilter("All Files", "*.*"),
|
||||||
|
new FileChooser.ExtensionFilter("JSON", "*.json")
|
||||||
|
);
|
||||||
|
|
||||||
|
File file = fileChooser.showOpenDialog(window);
|
||||||
|
if(file != null) {
|
||||||
|
importFile(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void importFile(File file) {
|
||||||
|
if(file.exists()) {
|
||||||
|
try {
|
||||||
|
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
|
||||||
|
Keystore keystore = importer.getKeystore(wallet.getScriptType(), inputStream);
|
||||||
|
EventManager.get().post(new KeystoreImportEvent(keystore));
|
||||||
|
} catch (Exception e) {
|
||||||
|
setExpanded(false);
|
||||||
|
descriptionLabel.getStyleClass().remove("description-label");
|
||||||
|
descriptionLabel.getStyleClass().add("description-error");
|
||||||
|
descriptionLabel.setText("Error Importing [View Details...]");
|
||||||
|
setContent(getContentBox(e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node getContentBox(String message) {
|
||||||
|
Label details = new Label(message);
|
||||||
|
details.setWrapText(true);
|
||||||
|
|
||||||
|
HBox contentBox = new HBox();
|
||||||
|
contentBox.setAlignment(Pos.TOP_RIGHT);
|
||||||
|
contentBox.getChildren().add(details);
|
||||||
|
contentBox.setPadding(new Insets(10, 30, 10, 30));
|
||||||
|
contentBox.setPrefHeight(60);
|
||||||
|
|
||||||
|
return contentBox;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
|
import com.sparrowwallet.sparrow.external.KeystoreFileImport;
|
||||||
|
import com.sparrowwallet.sparrow.external.KeystoreImport;
|
||||||
|
import com.sparrowwallet.sparrow.external.KeystoreMnemonicImport;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.scene.control.Accordion;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class KeystoreImportAccordion extends Accordion {
|
||||||
|
private List<KeystoreImport> importers;
|
||||||
|
|
||||||
|
public void setKeystoreImporters(Wallet wallet, ObservableList<KeystoreImport> importers) {
|
||||||
|
this.importers = importers;
|
||||||
|
|
||||||
|
for(KeystoreImport importer : importers) {
|
||||||
|
KeystoreFileImportPane importPane = null;
|
||||||
|
|
||||||
|
if(importer instanceof KeystoreFileImport) {
|
||||||
|
importPane = new KeystoreFileImportPane(this, wallet, (KeystoreFileImport)importer);
|
||||||
|
} else if(importer instanceof KeystoreMnemonicImport) {
|
||||||
|
//TODO:
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Could not create ImportPane for importer of type " + importer.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getPanes().add(importPane);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import com.sparrowwallet.drongo.policy.PolicyType;
|
||||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
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.drongo.wallet.WalletModel;
|
||||||
import com.sparrowwallet.sparrow.storage.Storage;
|
import com.sparrowwallet.sparrow.storage.Storage;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
@ -17,19 +18,24 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class ColdcardMultisig implements MultisigWalletImport, KeystoreImport, WalletExport {
|
public class ColdcardMultisig implements MultisigWalletImport, KeystoreFileImport, WalletExport {
|
||||||
private final Gson gson = new Gson();
|
private final Gson gson = new Gson();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Coldcard (Multisig)";
|
return "Coldcard Multisig";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PolicyType getPolicyType() {
|
public PolicyType getKeystorePolicyType() {
|
||||||
return PolicyType.MULTI;
|
return PolicyType.MULTI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WalletModel getWalletModel() {
|
||||||
|
return WalletModel.COLDCARD;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Keystore getKeystore(ScriptType scriptType, InputStream inputStream) throws ImportException {
|
public Keystore getKeystore(ScriptType scriptType, InputStream inputStream) throws ImportException {
|
||||||
InputStreamReader reader = new InputStreamReader(inputStream);
|
InputStreamReader reader = new InputStreamReader(inputStream);
|
||||||
|
|
|
@ -9,6 +9,7 @@ import com.sparrowwallet.drongo.policy.PolicyType;
|
||||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
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.drongo.wallet.WalletModel;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
@ -16,7 +17,7 @@ import java.util.List;
|
||||||
|
|
||||||
import static com.sparrowwallet.drongo.protocol.ScriptType.*;
|
import static com.sparrowwallet.drongo.protocol.ScriptType.*;
|
||||||
|
|
||||||
public class ColdcardSinglesig implements SinglesigWalletImport {
|
public class ColdcardSinglesig implements KeystoreFileImport, SinglesigWalletImport {
|
||||||
public static final List<ScriptType> ALLOWED_SCRIPT_TYPES = List.of(P2PKH, P2SH_P2WPKH, P2WPKH);
|
public static final List<ScriptType> ALLOWED_SCRIPT_TYPES = List.of(P2PKH, P2SH_P2WPKH, P2WPKH);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,7 +26,29 @@ public class ColdcardSinglesig implements SinglesigWalletImport {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Wallet importWallet(InputStream inputStream, ScriptType scriptType) throws ImportException {
|
public PolicyType getKeystorePolicyType() {
|
||||||
|
return PolicyType.SINGLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKeystoreImportDescription() {
|
||||||
|
return "Import file created by using the Advanced > Dump Summary feature on your Coldcard";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WalletModel getWalletModel() {
|
||||||
|
return WalletModel.COLDCARD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Keystore getKeystore(ScriptType scriptType, InputStream inputStream) throws ImportException {
|
||||||
|
Wallet wallet = importWallet(scriptType, inputStream);
|
||||||
|
|
||||||
|
return wallet.getKeystores().get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Wallet importWallet(ScriptType scriptType, InputStream inputStream) throws ImportException {
|
||||||
if(!ALLOWED_SCRIPT_TYPES.contains(scriptType)) {
|
if(!ALLOWED_SCRIPT_TYPES.contains(scriptType)) {
|
||||||
throw new ImportException("Script type of " + scriptType + " is not allowed");
|
throw new ImportException("Script type of " + scriptType + " is not allowed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import com.sparrowwallet.drongo.policy.PolicyType;
|
||||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
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.drongo.wallet.WalletModel;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
@ -17,12 +18,43 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class Electrum implements SinglesigWalletImport, MultisigWalletImport, WalletExport {
|
public class Electrum implements KeystoreFileImport, SinglesigWalletImport, MultisigWalletImport, WalletExport {
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Electrum";
|
return "Electrum";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PolicyType getKeystorePolicyType() {
|
||||||
|
return PolicyType.SINGLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WalletModel getWalletModel() {
|
||||||
|
return WalletModel.ELECTRUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKeystoreImportDescription() {
|
||||||
|
return "Import from an Electrum wallet";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Keystore getKeystore(ScriptType scriptType, InputStream inputStream) throws ImportException {
|
||||||
|
Wallet wallet = importWallet(inputStream);
|
||||||
|
|
||||||
|
if(!wallet.getPolicyType().equals(PolicyType.SINGLE) || wallet.getKeystores().size() != 1) {
|
||||||
|
throw new ImportException("Multisig wallet detected - import it through the File > Import menu");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!wallet.getScriptType().equals(scriptType)) {
|
||||||
|
//TODO: Derive appropriate ScriptType keystore
|
||||||
|
throw new ImportException("Wallet has an incompatible script type of " + wallet.getScriptType());
|
||||||
|
}
|
||||||
|
|
||||||
|
return wallet.getKeystores().get(0);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Wallet importWallet(InputStream inputStream) throws ImportException {
|
public Wallet importWallet(InputStream inputStream) throws ImportException {
|
||||||
InputStreamReader reader = new InputStreamReader(inputStream);
|
InputStreamReader reader = new InputStreamReader(inputStream);
|
||||||
|
@ -89,7 +121,7 @@ public class Electrum implements SinglesigWalletImport, MultisigWalletImport, Wa
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Wallet importWallet(InputStream inputStream, ScriptType scriptType) throws ImportException {
|
public Wallet importWallet(ScriptType scriptType, InputStream inputStream) throws ImportException {
|
||||||
Wallet wallet = importWallet(inputStream);
|
Wallet wallet = importWallet(inputStream);
|
||||||
wallet.setScriptType(scriptType);
|
wallet.setScriptType(scriptType);
|
||||||
|
|
||||||
|
|
|
@ -23,29 +23,9 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class Hwi implements KeystoreImport {
|
public class Hwi {
|
||||||
private static File hwiExecutable;
|
private static File hwiExecutable;
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "Hardware Wallet";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getKeystoreImportDescription() {
|
|
||||||
return "Imports a connected hardware wallet";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PolicyType getPolicyType() {
|
|
||||||
return PolicyType.SINGLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Keystore getKeystore(ScriptType scriptType, InputStream inputStream) throws ImportException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Device> enumerate(String passphrase) throws ImportException {
|
public List<Device> enumerate(String passphrase) throws ImportException {
|
||||||
try {
|
try {
|
||||||
List<String> command;
|
List<String> command;
|
||||||
|
|
10
src/main/java/com/sparrowwallet/sparrow/external/KeystoreFileImport.java
vendored
Normal file
10
src/main/java/com/sparrowwallet/sparrow/external/KeystoreFileImport.java
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package com.sparrowwallet.sparrow.external;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
|
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public interface KeystoreFileImport extends KeystoreImport {
|
||||||
|
Keystore getKeystore(ScriptType scriptType, InputStream inputStream) throws ImportException;
|
||||||
|
}
|
|
@ -1,13 +1,10 @@
|
||||||
package com.sparrowwallet.sparrow.external;
|
package com.sparrowwallet.sparrow.external;
|
||||||
|
|
||||||
import com.sparrowwallet.drongo.policy.PolicyType;
|
import com.sparrowwallet.drongo.policy.PolicyType;
|
||||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
import com.sparrowwallet.drongo.wallet.WalletModel;
|
||||||
import com.sparrowwallet.drongo.wallet.Keystore;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
public interface KeystoreImport extends Import {
|
public interface KeystoreImport extends Import {
|
||||||
PolicyType getPolicyType();
|
PolicyType getKeystorePolicyType();
|
||||||
Keystore getKeystore(ScriptType scriptType, InputStream inputStream) throws ImportException;
|
WalletModel getWalletModel();
|
||||||
String getKeystoreImportDescription();
|
String getKeystoreImportDescription();
|
||||||
}
|
}
|
||||||
|
|
8
src/main/java/com/sparrowwallet/sparrow/external/KeystoreMnemonicImport.java
vendored
Normal file
8
src/main/java/com/sparrowwallet/sparrow/external/KeystoreMnemonicImport.java
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package com.sparrowwallet.sparrow.external;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
|
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||||
|
|
||||||
|
public interface KeystoreMnemonicImport extends KeystoreImport {
|
||||||
|
Keystore getKeystore(ScriptType scriptType, String[] mnemonicWords, String passphrase) throws ImportException;
|
||||||
|
}
|
|
@ -7,5 +7,5 @@ import java.io.InputStream;
|
||||||
|
|
||||||
public interface SinglesigWalletImport extends Import {
|
public interface SinglesigWalletImport extends Import {
|
||||||
String getWalletImportDescription();
|
String getWalletImportDescription();
|
||||||
Wallet importWallet(InputStream inputStream, ScriptType scriptType) throws ImportException;
|
Wallet importWallet(ScriptType scriptType, InputStream inputStream) throws ImportException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,7 @@ public class KeystoreImportController implements Initializable {
|
||||||
Node importTypeNode = importLoader.load();
|
Node importTypeNode = importLoader.load();
|
||||||
KeystoreImportDetailController controller = importLoader.getController();
|
KeystoreImportDetailController controller = importLoader.getController();
|
||||||
controller.setMasterController(this);
|
controller.setMasterController(this);
|
||||||
|
controller.initializeView();
|
||||||
importPane.getChildren().add(importTypeNode);
|
importPane.getChildren().add(importTypeNode);
|
||||||
|
|
||||||
return importLoader;
|
return importLoader;
|
||||||
|
|
|
@ -10,4 +10,8 @@ public abstract class KeystoreImportDetailController {
|
||||||
void setMasterController(KeystoreImportController masterController) {
|
void setMasterController(KeystoreImportController masterController) {
|
||||||
this.masterController = masterController;
|
this.masterController = masterController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void initializeView() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ public class KeystoreImportDialog extends Dialog<Keystore> {
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void keystoreImported(KeystoreImportEvent event) {
|
public void keystoreImported(KeystoreImportEvent event) {
|
||||||
this.keystore = event.getKeystore();
|
this.keystore = event.getKeystore();
|
||||||
|
System.out.println(keystore.getLabel() + " " + keystore.getKeyDerivation().getMasterFingerprint());
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.sparrowwallet.sparrow.keystoreimport;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.policy.PolicyType;
|
||||||
|
import com.sparrowwallet.sparrow.control.KeystoreImportAccordion;
|
||||||
|
import com.sparrowwallet.sparrow.external.ColdcardMultisig;
|
||||||
|
import com.sparrowwallet.sparrow.external.ColdcardSinglesig;
|
||||||
|
import com.sparrowwallet.sparrow.external.KeystoreImport;
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class UsbAirgappedController extends KeystoreImportDetailController {
|
||||||
|
@FXML
|
||||||
|
private KeystoreImportAccordion importAccordion;
|
||||||
|
|
||||||
|
public void initializeView() {
|
||||||
|
List<KeystoreImport> importers = Collections.emptyList();
|
||||||
|
if(getMasterController().getWallet().getPolicyType().equals(PolicyType.SINGLE)) {
|
||||||
|
importers = List.of(new ColdcardSinglesig());
|
||||||
|
} else if(getMasterController().getWallet().getPolicyType().equals(PolicyType.MULTI)) {
|
||||||
|
importers = List.of(new ColdcardMultisig());
|
||||||
|
}
|
||||||
|
|
||||||
|
importAccordion.setKeystoreImporters(getMasterController().getWallet(), FXCollections.observableList(importers));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?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.UsbAirgappedController">
|
||||||
|
<ScrollPane AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0" fitToWidth="true">
|
||||||
|
<KeystoreImportAccordion fx:id="importAccordion" />
|
||||||
|
</ScrollPane>
|
||||||
|
</AnchorPane>
|
|
@ -47,14 +47,19 @@
|
||||||
-fx-translate-x: -1000;
|
-fx-translate-x: -1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.devicelist-main-label .text {
|
.main-label .text {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.devicelist-status-label .text {
|
.status-label .text, .description-label Text {
|
||||||
-fx-fill: #a0a1a7;
|
-fx-fill: #a0a1a7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-error .text {
|
.status-error .text, .description-error Text {
|
||||||
-fx-fill: #ca1243;
|
-fx-fill: #ca1243;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.description-label .text, description-error .text {
|
||||||
|
-fx-fill: #1e88cf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue