add cobo vault singlesig and multisig file import and export

This commit is contained in:
Craig Raw 2020-10-07 12:31:58 +02:00
parent eda712e269
commit fa5ac7917b
13 changed files with 104 additions and 21 deletions

2
drongo

@ -1 +1 @@
Subproject commit 3642ddc9581c4485b13d4d0fffee6290703a5768 Subproject commit 290fbabb54f0a334db15b66c968c9311122817e7

View file

@ -885,7 +885,7 @@ public class AppController implements Initializable {
} }
private boolean attemptImportWallet(File file, SecureString password) { private boolean attemptImportWallet(File file, SecureString password) {
List<WalletImport> walletImporters = List.of(new ColdcardSinglesig(), new ColdcardMultisig(), new Electrum(), new Specter()); List<WalletImport> walletImporters = List.of(new ColdcardSinglesig(), new ColdcardMultisig(), new Electrum(), new Specter(), new CoboVaultSinglesig(), new CoboVaultMultisig());
for(WalletImport importer : walletImporters) { for(WalletImport importer : walletImporters) {
try(FileInputStream inputStream = new FileInputStream(file)) { try(FileInputStream inputStream = new FileInputStream(file)) {
if(importer.isEncrypted(file) && password == null) { if(importer.isEncrypted(file) && password == null) {

View file

@ -53,7 +53,8 @@ public abstract class FileImportPane extends TitledDescriptionPane {
fileChooser.setTitle("Open " + importer.getWalletModel().toDisplayString() + " File"); fileChooser.setTitle("Open " + importer.getWalletModel().toDisplayString() + " File");
fileChooser.getExtensionFilters().addAll( fileChooser.getExtensionFilters().addAll(
new FileChooser.ExtensionFilter("All Files", "*.*"), new FileChooser.ExtensionFilter("All Files", "*.*"),
new FileChooser.ExtensionFilter("JSON", "*.json") new FileChooser.ExtensionFilter("JSON", "*.json"),
new FileChooser.ExtensionFilter("TXT", "*.txt")
); );
File file = fileChooser.showOpenDialog(window); File file = fileChooser.showOpenDialog(window);

View file

@ -6,10 +6,7 @@ import com.sparrowwallet.drongo.wallet.Wallet;
import com.sparrowwallet.sparrow.AppController; import com.sparrowwallet.sparrow.AppController;
import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.EventManager;
import com.sparrowwallet.sparrow.event.WalletExportEvent; import com.sparrowwallet.sparrow.event.WalletExportEvent;
import com.sparrowwallet.sparrow.io.ColdcardMultisig; import com.sparrowwallet.sparrow.io.*;
import com.sparrowwallet.sparrow.io.Electrum;
import com.sparrowwallet.sparrow.io.Specter;
import com.sparrowwallet.sparrow.io.WalletExport;
import javafx.scene.control.*; import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPane;
@ -35,7 +32,7 @@ public class WalletExportDialog extends Dialog<Wallet> {
stackPane.getChildren().add(anchorPane); stackPane.getChildren().add(anchorPane);
ScrollPane scrollPane = new ScrollPane(); ScrollPane scrollPane = new ScrollPane();
scrollPane.setPrefHeight(280); scrollPane.setPrefHeight(400);
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
anchorPane.getChildren().add(scrollPane); anchorPane.getChildren().add(scrollPane);
scrollPane.setFitToWidth(true); scrollPane.setFitToWidth(true);
@ -46,7 +43,7 @@ public class WalletExportDialog extends Dialog<Wallet> {
if(wallet.getPolicyType() == PolicyType.SINGLE) { if(wallet.getPolicyType() == PolicyType.SINGLE) {
exporters = List.of(new Electrum(), new Specter()); exporters = List.of(new Electrum(), new Specter());
} else if(wallet.getPolicyType() == PolicyType.MULTI) { } else if(wallet.getPolicyType() == PolicyType.MULTI) {
exporters = List.of(new ColdcardMultisig(), new Electrum(), new Specter()); exporters = List.of(new ColdcardMultisig(), new CoboVaultMultisig(), new Electrum(), new Specter());
} else { } else {
throw new UnsupportedOperationException("Cannot export wallet with policy type " + wallet.getPolicyType()); throw new UnsupportedOperationException("Cannot export wallet with policy type " + wallet.getPolicyType());
} }
@ -61,7 +58,7 @@ public class WalletExportDialog 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(480);
setResultConverter(dialogButton -> dialogButton != cancelButtonType ? wallet : null); setResultConverter(dialogButton -> dialogButton != cancelButtonType ? wallet : null);
} }

View file

@ -31,7 +31,7 @@ public class WalletImportDialog extends Dialog<Wallet> {
stackPane.getChildren().add(anchorPane); stackPane.getChildren().add(anchorPane);
ScrollPane scrollPane = new ScrollPane(); ScrollPane scrollPane = new ScrollPane();
scrollPane.setPrefHeight(400); scrollPane.setPrefHeight(420);
scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER);
anchorPane.getChildren().add(scrollPane); anchorPane.getChildren().add(scrollPane);
scrollPane.setFitToWidth(true); scrollPane.setFitToWidth(true);
@ -39,13 +39,13 @@ public class WalletImportDialog extends Dialog<Wallet> {
AnchorPane.setRightAnchor(scrollPane, 0.0); AnchorPane.setRightAnchor(scrollPane, 0.0);
Accordion importAccordion = new Accordion(); Accordion importAccordion = new Accordion();
List<KeystoreFileImport> keystoreImporters = List.of(new ColdcardSinglesig()); List<KeystoreFileImport> keystoreImporters = List.of(new ColdcardSinglesig(), new CoboVaultSinglesig());
for(KeystoreFileImport importer : keystoreImporters) { for(KeystoreFileImport importer : keystoreImporters) {
FileWalletKeystoreImportPane importPane = new FileWalletKeystoreImportPane(importer); FileWalletKeystoreImportPane importPane = new FileWalletKeystoreImportPane(importer);
importAccordion.getPanes().add(importPane); importAccordion.getPanes().add(importPane);
} }
List<WalletImport> walletImporters = List.of(new ColdcardMultisig(), new Electrum(), new Specter()); List<WalletImport> walletImporters = List.of(new ColdcardMultisig(), new CoboVaultMultisig(), new Electrum(), new Specter());
for(WalletImport importer : walletImporters) { for(WalletImport importer : walletImporters) {
FileWalletImportPane importPane = new FileWalletImportPane(importer); FileWalletImportPane importPane = new FileWalletImportPane(importer);
importAccordion.getPanes().add(importPane); importAccordion.getPanes().add(importPane);
@ -55,7 +55,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(480); dialogPane.setPrefHeight(500);
setResultConverter(dialogButton -> dialogButton != cancelButtonType ? wallet : null); setResultConverter(dialogButton -> dialogButton != cancelButtonType ? wallet : null);
} }

View file

@ -0,0 +1,55 @@
package com.sparrowwallet.sparrow.io;
import com.sparrowwallet.drongo.protocol.ScriptType;
import com.sparrowwallet.drongo.wallet.Keystore;
import com.sparrowwallet.drongo.wallet.Wallet;
import com.sparrowwallet.drongo.wallet.WalletModel;
import java.io.InputStream;
public class CoboVaultMultisig extends ColdcardMultisig {
@Override
public String getName() {
return "Cobo Vault Multisig";
}
@Override
public WalletModel getWalletModel() {
return WalletModel.COBO_VAULT;
}
@Override
public Keystore getKeystore(ScriptType scriptType, InputStream inputStream, String password) throws ImportException {
Keystore keystore = super.getKeystore(scriptType, inputStream, password);
keystore.setLabel("Cobo Vault");
keystore.setWalletModel(getWalletModel());
return keystore;
}
@Override
public String getKeystoreImportDescription() {
return "Import file created by using the Multisig Wallet > Show/Export XPUB > Export All > Export feature on your Cobo Vault.";
}
@Override
public Wallet importWallet(InputStream inputStream, String password) throws ImportException {
Wallet wallet = super.importWallet(inputStream, password);
for(Keystore keystore : wallet.getKeystores()) {
keystore.setLabel(keystore.getLabel().replace("Coldcard", "Cobo Vault"));
keystore.setWalletModel(WalletModel.COBO_VAULT);
}
return wallet;
}
@Override
public String getWalletImportDescription() {
return "Import file created by using the Multisig Wallet > Create Multisig Wallet feature on your Cobo Vault.";
}
@Override
public String getWalletExportDescription() {
return "Export file that can be read by your Cobo Vault using the Multisig Wallet > Import Multisig Wallet feature.";
}
}

View file

@ -0,0 +1,33 @@
package com.sparrowwallet.sparrow.io;
import com.sparrowwallet.drongo.protocol.ScriptType;
import com.sparrowwallet.drongo.wallet.Keystore;
import com.sparrowwallet.drongo.wallet.WalletModel;
import java.io.InputStream;
public class CoboVaultSinglesig extends ColdcardSinglesig {
@Override
public String getName() {
return "Cobo Vault";
}
@Override
public String getKeystoreImportDescription() {
return "Import file created by using the Watch-Only Wallet > Generic Wallet > Export Wallet feature on your Cobo Vault.";
}
@Override
public WalletModel getWalletModel() {
return WalletModel.COBO_VAULT;
}
@Override
public Keystore getKeystore(ScriptType scriptType, InputStream inputStream, String password) throws ImportException {
Keystore keystore = super.getKeystore(scriptType, inputStream, password);
keystore.setLabel("Cobo Vault");
keystore.setWalletModel(getWalletModel());
return keystore;
}
}

View file

@ -1,7 +1,6 @@
package com.sparrowwallet.sparrow.io; package com.sparrowwallet.sparrow.io;
import com.google.common.io.CharStreams; import com.google.common.io.CharStreams;
import com.google.gson.Gson;
import com.sparrowwallet.drongo.ExtendedKey; import com.sparrowwallet.drongo.ExtendedKey;
import com.sparrowwallet.drongo.KeyDerivation; import com.sparrowwallet.drongo.KeyDerivation;
import com.sparrowwallet.drongo.Utils; import com.sparrowwallet.drongo.Utils;
@ -19,8 +18,6 @@ import java.util.List;
import java.util.Set; import java.util.Set;
public class ColdcardMultisig implements WalletImport, KeystoreFileImport, WalletExport { public class ColdcardMultisig implements WalletImport, KeystoreFileImport, WalletExport {
private final Gson gson = new Gson();
@Override @Override
public String getName() { public String getName() {
return "Coldcard Multisig"; return "Coldcard Multisig";
@ -153,7 +150,7 @@ public class ColdcardMultisig implements WalletImport, KeystoreFileImport, Walle
} }
if(!wallet.getPolicyType().equals(PolicyType.MULTI)) { if(!wallet.getPolicyType().equals(PolicyType.MULTI)) {
throw new ExportException("Coldcard multisig import requires a multisig wallet"); throw new ExportException(getName() + " import requires a multisig wallet");
} }
boolean multipleDerivations = false; boolean multipleDerivations = false;
@ -167,7 +164,7 @@ public class ColdcardMultisig implements WalletImport, KeystoreFileImport, Walle
try { try {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream)); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
writer.append("# Coldcard Multisig setup file (created by Sparrow)\n"); writer.append("# " + getName() + " setup file (created by Sparrow)\n");
writer.append("#\n"); writer.append("#\n");
writer.append("Name: ").append(wallet.getName()).append("\n"); writer.append("Name: ").append(wallet.getName()).append("\n");
writer.append("Policy: ").append(Integer.toString(wallet.getDefaultPolicy().getNumSignaturesRequired())).append(" of ").append(Integer.toString(wallet.getKeystores().size())).append("\n"); writer.append("Policy: ").append(Integer.toString(wallet.getDefaultPolicy().getNumSignaturesRequired())).append(" of ").append(Integer.toString(wallet.getKeystores().size())).append("\n");

View file

@ -16,9 +16,9 @@ public class HwAirgappedController extends KeystoreImportDetailController {
public void initializeView() { public void initializeView() {
List<KeystoreFileImport> importers = Collections.emptyList(); List<KeystoreFileImport> importers = Collections.emptyList();
if(getMasterController().getWallet().getPolicyType().equals(PolicyType.SINGLE)) { if(getMasterController().getWallet().getPolicyType().equals(PolicyType.SINGLE)) {
importers = List.of(new ColdcardSinglesig()); importers = List.of(new ColdcardSinglesig(), new CoboVaultSinglesig());
} else if(getMasterController().getWallet().getPolicyType().equals(PolicyType.MULTI)) { } else if(getMasterController().getWallet().getPolicyType().equals(PolicyType.MULTI)) {
importers = List.of(new ColdcardMultisig()); importers = List.of(new ColdcardMultisig(), new CoboVaultMultisig());
} }
for(KeystoreImport importer : importers) { for(KeystoreImport importer : importers) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB