diff --git a/drongo b/drongo index 3642ddc9..290fbabb 160000 --- a/drongo +++ b/drongo @@ -1 +1 @@ -Subproject commit 3642ddc9581c4485b13d4d0fffee6290703a5768 +Subproject commit 290fbabb54f0a334db15b66c968c9311122817e7 diff --git a/src/main/java/com/sparrowwallet/sparrow/AppController.java b/src/main/java/com/sparrowwallet/sparrow/AppController.java index 6a1f8336..b6628243 100644 --- a/src/main/java/com/sparrowwallet/sparrow/AppController.java +++ b/src/main/java/com/sparrowwallet/sparrow/AppController.java @@ -885,7 +885,7 @@ public class AppController implements Initializable { } private boolean attemptImportWallet(File file, SecureString password) { - List walletImporters = List.of(new ColdcardSinglesig(), new ColdcardMultisig(), new Electrum(), new Specter()); + List walletImporters = List.of(new ColdcardSinglesig(), new ColdcardMultisig(), new Electrum(), new Specter(), new CoboVaultSinglesig(), new CoboVaultMultisig()); for(WalletImport importer : walletImporters) { try(FileInputStream inputStream = new FileInputStream(file)) { if(importer.isEncrypted(file) && password == null) { diff --git a/src/main/java/com/sparrowwallet/sparrow/control/FileImportPane.java b/src/main/java/com/sparrowwallet/sparrow/control/FileImportPane.java index d77a15d5..2175ed09 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/FileImportPane.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/FileImportPane.java @@ -53,7 +53,8 @@ public abstract class FileImportPane extends TitledDescriptionPane { fileChooser.setTitle("Open " + importer.getWalletModel().toDisplayString() + " File"); fileChooser.getExtensionFilters().addAll( 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); diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java index c61a5c64..f4bebeef 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java @@ -6,10 +6,7 @@ import com.sparrowwallet.drongo.wallet.Wallet; import com.sparrowwallet.sparrow.AppController; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.event.WalletExportEvent; -import com.sparrowwallet.sparrow.io.ColdcardMultisig; -import com.sparrowwallet.sparrow.io.Electrum; -import com.sparrowwallet.sparrow.io.Specter; -import com.sparrowwallet.sparrow.io.WalletExport; +import com.sparrowwallet.sparrow.io.*; import javafx.scene.control.*; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.StackPane; @@ -35,7 +32,7 @@ public class WalletExportDialog extends Dialog { stackPane.getChildren().add(anchorPane); ScrollPane scrollPane = new ScrollPane(); - scrollPane.setPrefHeight(280); + scrollPane.setPrefHeight(400); scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); anchorPane.getChildren().add(scrollPane); scrollPane.setFitToWidth(true); @@ -46,7 +43,7 @@ public class WalletExportDialog extends Dialog { if(wallet.getPolicyType() == PolicyType.SINGLE) { exporters = List.of(new Electrum(), new Specter()); } 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 { throw new UnsupportedOperationException("Cannot export wallet with policy type " + wallet.getPolicyType()); } @@ -61,7 +58,7 @@ public class WalletExportDialog extends Dialog { final ButtonType cancelButtonType = new javafx.scene.control.ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE); dialogPane.getButtonTypes().addAll(cancelButtonType); dialogPane.setPrefWidth(500); - dialogPane.setPrefHeight(360); + dialogPane.setPrefHeight(480); setResultConverter(dialogButton -> dialogButton != cancelButtonType ? wallet : null); } diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java index 65598149..3f145159 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java @@ -31,7 +31,7 @@ public class WalletImportDialog extends Dialog { stackPane.getChildren().add(anchorPane); ScrollPane scrollPane = new ScrollPane(); - scrollPane.setPrefHeight(400); + scrollPane.setPrefHeight(420); scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); anchorPane.getChildren().add(scrollPane); scrollPane.setFitToWidth(true); @@ -39,13 +39,13 @@ public class WalletImportDialog extends Dialog { AnchorPane.setRightAnchor(scrollPane, 0.0); Accordion importAccordion = new Accordion(); - List keystoreImporters = List.of(new ColdcardSinglesig()); + List keystoreImporters = List.of(new ColdcardSinglesig(), new CoboVaultSinglesig()); for(KeystoreFileImport importer : keystoreImporters) { FileWalletKeystoreImportPane importPane = new FileWalletKeystoreImportPane(importer); importAccordion.getPanes().add(importPane); } - List walletImporters = List.of(new ColdcardMultisig(), new Electrum(), new Specter()); + List walletImporters = List.of(new ColdcardMultisig(), new CoboVaultMultisig(), new Electrum(), new Specter()); for(WalletImport importer : walletImporters) { FileWalletImportPane importPane = new FileWalletImportPane(importer); importAccordion.getPanes().add(importPane); @@ -55,7 +55,7 @@ public class WalletImportDialog extends Dialog { final ButtonType cancelButtonType = new javafx.scene.control.ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE); dialogPane.getButtonTypes().addAll(cancelButtonType); dialogPane.setPrefWidth(500); - dialogPane.setPrefHeight(480); + dialogPane.setPrefHeight(500); setResultConverter(dialogButton -> dialogButton != cancelButtonType ? wallet : null); } diff --git a/src/main/java/com/sparrowwallet/sparrow/io/CoboVaultMultisig.java b/src/main/java/com/sparrowwallet/sparrow/io/CoboVaultMultisig.java new file mode 100644 index 00000000..c5d61ff2 --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/io/CoboVaultMultisig.java @@ -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."; + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/io/CoboVaultSinglesig.java b/src/main/java/com/sparrowwallet/sparrow/io/CoboVaultSinglesig.java new file mode 100644 index 00000000..631fd4f7 --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/io/CoboVaultSinglesig.java @@ -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; + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/io/ColdcardMultisig.java b/src/main/java/com/sparrowwallet/sparrow/io/ColdcardMultisig.java index ede49697..b7f1bcf8 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/ColdcardMultisig.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/ColdcardMultisig.java @@ -1,7 +1,6 @@ package com.sparrowwallet.sparrow.io; import com.google.common.io.CharStreams; -import com.google.gson.Gson; import com.sparrowwallet.drongo.ExtendedKey; import com.sparrowwallet.drongo.KeyDerivation; import com.sparrowwallet.drongo.Utils; @@ -19,8 +18,6 @@ import java.util.List; import java.util.Set; public class ColdcardMultisig implements WalletImport, KeystoreFileImport, WalletExport { - private final Gson gson = new Gson(); - @Override public String getName() { return "Coldcard Multisig"; @@ -153,7 +150,7 @@ public class ColdcardMultisig implements WalletImport, KeystoreFileImport, Walle } 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; @@ -167,7 +164,7 @@ public class ColdcardMultisig implements WalletImport, KeystoreFileImport, Walle try { 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("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"); diff --git a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwAirgappedController.java b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwAirgappedController.java index b79a92f2..d66735e7 100644 --- a/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwAirgappedController.java +++ b/src/main/java/com/sparrowwallet/sparrow/keystoreimport/HwAirgappedController.java @@ -16,9 +16,9 @@ public class HwAirgappedController extends KeystoreImportDetailController { public void initializeView() { List importers = Collections.emptyList(); 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)) { - importers = List.of(new ColdcardMultisig()); + importers = List.of(new ColdcardMultisig(), new CoboVaultMultisig()); } for(KeystoreImport importer : importers) { diff --git a/src/main/resources/image/cobovault-orig.png b/src/main/resources/image/cobovault-orig.png new file mode 100644 index 00000000..4516c482 Binary files /dev/null and b/src/main/resources/image/cobovault-orig.png differ diff --git a/src/main/resources/image/cobovault.png b/src/main/resources/image/cobovault.png new file mode 100644 index 00000000..46a0d4a0 Binary files /dev/null and b/src/main/resources/image/cobovault.png differ diff --git a/src/main/resources/image/cobovault@2x.png b/src/main/resources/image/cobovault@2x.png new file mode 100644 index 00000000..91108346 Binary files /dev/null and b/src/main/resources/image/cobovault@2x.png differ diff --git a/src/main/resources/image/cobovault@3x.png b/src/main/resources/image/cobovault@3x.png new file mode 100644 index 00000000..e6a40115 Binary files /dev/null and b/src/main/resources/image/cobovault@3x.png differ