mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2025-11-05 11:56:37 +00:00
add cobo vault singlesig and multisig file import and export
This commit is contained in:
parent
eda712e269
commit
fa5ac7917b
13 changed files with 104 additions and 21 deletions
2
drongo
2
drongo
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3642ddc9581c4485b13d4d0fffee6290703a5768
|
Subproject commit 290fbabb54f0a334db15b66c968c9311122817e7
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
BIN
src/main/resources/image/cobovault-orig.png
Normal file
BIN
src/main/resources/image/cobovault-orig.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
BIN
src/main/resources/image/cobovault.png
Normal file
BIN
src/main/resources/image/cobovault.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
BIN
src/main/resources/image/cobovault@2x.png
Normal file
BIN
src/main/resources/image/cobovault@2x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
BIN
src/main/resources/image/cobovault@3x.png
Normal file
BIN
src/main/resources/image/cobovault@3x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
Loading…
Reference in a new issue