mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-24 12:46:45 +00:00
add coldcard single sig wallet import
This commit is contained in:
parent
750f6483cb
commit
f95cb67912
4 changed files with 129 additions and 5 deletions
|
@ -770,6 +770,18 @@ public class AppController implements Initializable {
|
||||||
if(optionalWallet.isPresent()) {
|
if(optionalWallet.isPresent()) {
|
||||||
Wallet wallet = optionalWallet.get();
|
Wallet wallet = optionalWallet.get();
|
||||||
File walletFile = Storage.getWalletFile(wallet.getName());
|
File walletFile = Storage.getWalletFile(wallet.getName());
|
||||||
|
|
||||||
|
if(walletFile.exists()) {
|
||||||
|
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
||||||
|
alert.setTitle("Existing wallet found");
|
||||||
|
alert.setHeaderText("Replace existing wallet?");
|
||||||
|
alert.setContentText("Wallet file " + wallet.getName() + " already exists");
|
||||||
|
Optional<ButtonType> result = alert.showAndWait();
|
||||||
|
if(result.isPresent() && result.get() == ButtonType.CANCEL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Storage storage = new Storage(walletFile);
|
Storage storage = new Storage(walletFile);
|
||||||
Tab tab = addWalletTab(storage, wallet);
|
Tab tab = addWalletTab(storage, wallet);
|
||||||
tabs.getSelectionModel().select(tab);
|
tabs.getSelectionModel().select(tab);
|
||||||
|
|
|
@ -28,7 +28,7 @@ public abstract class FileImportPane extends TitledDescriptionPane {
|
||||||
private static final Logger log = LoggerFactory.getLogger(FileImportPane.class);
|
private static final Logger log = LoggerFactory.getLogger(FileImportPane.class);
|
||||||
|
|
||||||
private final FileImport importer;
|
private final FileImport importer;
|
||||||
private Button importButton;
|
protected Button importButton;
|
||||||
private final SimpleStringProperty password = new SimpleStringProperty("");
|
private final SimpleStringProperty password = new SimpleStringProperty("");
|
||||||
|
|
||||||
public FileImportPane(FileImport importer, String title, String description, String content, String imageUrl) {
|
public FileImportPane(FileImport importer, String title, String description, String content, String imageUrl) {
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
import com.sparrowwallet.drongo.policy.Policy;
|
||||||
|
import com.sparrowwallet.drongo.policy.PolicyType;
|
||||||
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
|
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||||
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
|
import com.sparrowwallet.sparrow.event.WalletImportEvent;
|
||||||
|
import com.sparrowwallet.sparrow.io.ImportException;
|
||||||
|
import com.sparrowwallet.sparrow.io.KeystoreFileImport;
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.ComboBox;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.Priority;
|
||||||
|
import javafx.scene.layout.Region;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class FileWalletKeystoreImportPane extends FileImportPane {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(FileWalletKeystoreImportPane.class);
|
||||||
|
|
||||||
|
private final KeystoreFileImport importer;
|
||||||
|
private String fileName;
|
||||||
|
private byte[] fileBytes;
|
||||||
|
|
||||||
|
public FileWalletKeystoreImportPane(KeystoreFileImport importer) {
|
||||||
|
super(importer, importer.getName(), "Wallet file import", importer.getKeystoreImportDescription(), "image/" + importer.getWalletModel().getType() + ".png");
|
||||||
|
this.importer = importer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void importFile(String fileName, InputStream inputStream, String password) throws ImportException {
|
||||||
|
this.fileName = fileName;
|
||||||
|
try {
|
||||||
|
fileBytes = ByteStreams.toByteArray(inputStream);
|
||||||
|
} catch(IOException e) {
|
||||||
|
throw new ImportException("Could not read file", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
setContent(getScriptTypeEntry());
|
||||||
|
setExpanded(true);
|
||||||
|
importButton.setDisable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void importWallet(ScriptType scriptType) throws ImportException {
|
||||||
|
ByteArrayInputStream bais = new ByteArrayInputStream(fileBytes);
|
||||||
|
Keystore keystore = importer.getKeystore(scriptType, bais, "");
|
||||||
|
|
||||||
|
Wallet wallet = new Wallet();
|
||||||
|
wallet.setName(fileName);
|
||||||
|
wallet.setPolicyType(PolicyType.SINGLE);
|
||||||
|
wallet.setScriptType(scriptType);
|
||||||
|
wallet.getKeystores().add(keystore);
|
||||||
|
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, scriptType, wallet.getKeystores(), null));
|
||||||
|
|
||||||
|
EventManager.get().post(new WalletImportEvent(wallet));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node getScriptTypeEntry() {
|
||||||
|
Label label = new Label("Script Type:");
|
||||||
|
ComboBox<ScriptType> scriptTypeComboBox = new ComboBox<>(FXCollections.observableArrayList(ScriptType.getAddressableScriptTypes(PolicyType.SINGLE)));
|
||||||
|
scriptTypeComboBox.setValue(ScriptType.P2WPKH);
|
||||||
|
|
||||||
|
Region region = new Region();
|
||||||
|
HBox.setHgrow(region, Priority.SOMETIMES);
|
||||||
|
|
||||||
|
Button importFileButton = new Button("Import");
|
||||||
|
importFileButton.setOnAction(event -> {
|
||||||
|
showHideLink.setVisible(true);
|
||||||
|
setExpanded(false);
|
||||||
|
try {
|
||||||
|
importWallet(scriptTypeComboBox.getValue());
|
||||||
|
} catch(ImportException e) {
|
||||||
|
log.error("Error importing file", e);
|
||||||
|
String errorMessage = e.getMessage();
|
||||||
|
if(e.getCause() instanceof JsonParseException) {
|
||||||
|
errorMessage = "File was not in JSON format";
|
||||||
|
} else if(e.getCause() != null && e.getCause().getMessage() != null && !e.getCause().getMessage().isEmpty()) {
|
||||||
|
errorMessage = e.getCause().getMessage();
|
||||||
|
}
|
||||||
|
setError("Import Error", errorMessage);
|
||||||
|
importButton.setDisable(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
HBox contentBox = new HBox();
|
||||||
|
contentBox.setAlignment(Pos.CENTER_RIGHT);
|
||||||
|
contentBox.setSpacing(20);
|
||||||
|
contentBox.getChildren().addAll(label, scriptTypeComboBox, region, importFileButton);
|
||||||
|
contentBox.setPadding(new Insets(10, 30, 10, 30));
|
||||||
|
contentBox.setPrefHeight(60);
|
||||||
|
|
||||||
|
return contentBox;
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,16 +29,22 @@ public class WalletImportDialog extends Dialog<Wallet> {
|
||||||
stackPane.getChildren().add(anchorPane);
|
stackPane.getChildren().add(anchorPane);
|
||||||
|
|
||||||
ScrollPane scrollPane = new ScrollPane();
|
ScrollPane scrollPane = new ScrollPane();
|
||||||
scrollPane.setPrefHeight(280);
|
scrollPane.setPrefHeight(320);
|
||||||
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
|
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
|
||||||
anchorPane.getChildren().add(scrollPane);
|
anchorPane.getChildren().add(scrollPane);
|
||||||
scrollPane.setFitToWidth(true);
|
scrollPane.setFitToWidth(true);
|
||||||
AnchorPane.setLeftAnchor(scrollPane, 0.0);
|
AnchorPane.setLeftAnchor(scrollPane, 0.0);
|
||||||
AnchorPane.setRightAnchor(scrollPane, 0.0);
|
AnchorPane.setRightAnchor(scrollPane, 0.0);
|
||||||
|
|
||||||
List<WalletImport> importers = List.of(new ColdcardMultisig(), new Electrum());
|
|
||||||
Accordion importAccordion = new Accordion();
|
Accordion importAccordion = new Accordion();
|
||||||
for(WalletImport importer : importers) {
|
List<KeystoreFileImport> keystoreImporters = List.of(new ColdcardSinglesig());
|
||||||
|
for(KeystoreFileImport importer : keystoreImporters) {
|
||||||
|
FileWalletKeystoreImportPane importPane = new FileWalletKeystoreImportPane(importer);
|
||||||
|
importAccordion.getPanes().add(importPane);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<WalletImport> walletImporters = List.of(new ColdcardMultisig(), new Electrum());
|
||||||
|
for(WalletImport importer : walletImporters) {
|
||||||
FileWalletImportPane importPane = new FileWalletImportPane(importer);
|
FileWalletImportPane importPane = new FileWalletImportPane(importer);
|
||||||
importAccordion.getPanes().add(importPane);
|
importAccordion.getPanes().add(importPane);
|
||||||
}
|
}
|
||||||
|
@ -47,7 +53,7 @@ public class WalletImportDialog extends Dialog<Wallet> {
|
||||||
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(500);
|
dialogPane.setPrefWidth(500);
|
||||||
dialogPane.setPrefHeight(360);
|
dialogPane.setPrefHeight(400);
|
||||||
|
|
||||||
setResultConverter(dialogButton -> dialogButton != cancelButtonType ? wallet : null);
|
setResultConverter(dialogButton -> dialogButton != cancelButtonType ? wallet : null);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue