diff --git a/drongo b/drongo index 10ebfe46..70fdecf9 160000 --- a/drongo +++ b/drongo @@ -1 +1 @@ -Subproject commit 10ebfe463d504f39be2aacec41d48c2cf5ba4c56 +Subproject commit 70fdecf919ea9dcae46cc35df23e0a20ba90683f diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java index 788f7c53..c61a5c64 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java @@ -8,6 +8,7 @@ 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 javafx.scene.control.*; import javafx.scene.layout.AnchorPane; @@ -43,9 +44,9 @@ public class WalletExportDialog extends Dialog { List exporters; if(wallet.getPolicyType() == PolicyType.SINGLE) { - exporters = List.of(new Electrum()); + exporters = List.of(new Electrum(), new Specter()); } else if(wallet.getPolicyType() == PolicyType.MULTI) { - exporters = List.of(new ColdcardMultisig(), new Electrum()); + exporters = List.of(new ColdcardMultisig(), new Electrum(), new Specter()); } else { throw new UnsupportedOperationException("Cannot export wallet with policy type " + wallet.getPolicyType()); } diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java index 69978ff4..65598149 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(320); + scrollPane.setPrefHeight(400); scrollPane.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); anchorPane.getChildren().add(scrollPane); scrollPane.setFitToWidth(true); @@ -45,7 +45,7 @@ public class WalletImportDialog extends Dialog { importAccordion.getPanes().add(importPane); } - List walletImporters = List.of(new ColdcardMultisig(), new Electrum()); + List walletImporters = List.of(new ColdcardMultisig(), 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(400); + dialogPane.setPrefHeight(480); setResultConverter(dialogButton -> dialogButton != cancelButtonType ? wallet : null); } diff --git a/src/main/java/com/sparrowwallet/sparrow/io/Specter.java b/src/main/java/com/sparrowwallet/sparrow/io/Specter.java new file mode 100644 index 00000000..0fc71858 --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/io/Specter.java @@ -0,0 +1,93 @@ +package com.sparrowwallet.sparrow.io; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.sparrowwallet.drongo.OutputDescriptor; +import com.sparrowwallet.drongo.wallet.Wallet; +import com.sparrowwallet.drongo.wallet.WalletModel; + +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +public class Specter implements WalletImport, WalletExport { + @Override + public void exportWallet(Wallet wallet, OutputStream outputStream) throws ExportException { + try { + SpecterWallet specterWallet = new SpecterWallet(); + specterWallet.label = wallet.getName(); + specterWallet.blockheight = wallet.getStoredBlockHeight(); + specterWallet.descriptor = OutputDescriptor.getOutputDescriptor(wallet).toString(); + + Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); + String json = gson.toJson(specterWallet); + outputStream.write(json.getBytes(StandardCharsets.UTF_8)); + outputStream.flush(); + outputStream.close(); + } catch(Exception e) { + throw new ExportException(e); + } + } + + @Override + public String getWalletExportDescription() { + return "Export a Specter wallet that can be read by Specter Desktop using Add new wallet > Import from wallet software"; + } + + @Override + public String getExportFileExtension() { + return "json"; + } + + @Override + public String getWalletImportDescription() { + return "Import a Specter wallet created by using the Wallets > Settings > Export to Wallet Software in Specter Desktop"; + } + + @Override + public Wallet importWallet(InputStream inputStream, String password) throws ImportException { + try { + Gson gson = new Gson(); + SpecterWallet specterWallet = gson.fromJson(new InputStreamReader(inputStream), SpecterWallet.class); + + if(specterWallet.descriptor != null) { + OutputDescriptor outputDescriptor = OutputDescriptor.getOutputDescriptor(specterWallet.descriptor); + Wallet wallet = outputDescriptor.toWallet(); + wallet.setName(specterWallet.label); + + if(!wallet.isValid()) { + throw new ImportException("Specter wallet file did not contain a valid wallet"); + } + + return wallet; + } + } catch(Exception e) { + throw new ImportException(e); + } + + throw new ImportException("Could not import Specter wallet"); + } + + @Override + public boolean isEncrypted(File file) { + return false; + } + + @Override + public String getName() { + return "Specter"; + } + + @Override + public WalletModel getWalletModel() { + return WalletModel.SPECTER; + } + + public static class SpecterWallet { + public String label; + public Integer blockheight; + public String descriptor; + } +} diff --git a/src/main/resources/image/specter.png b/src/main/resources/image/specter.png new file mode 100644 index 00000000..71badb56 Binary files /dev/null and b/src/main/resources/image/specter.png differ diff --git a/src/main/resources/image/specter@2x.png b/src/main/resources/image/specter@2x.png new file mode 100644 index 00000000..625855c5 Binary files /dev/null and b/src/main/resources/image/specter@2x.png differ diff --git a/src/main/resources/image/specter@3x.png b/src/main/resources/image/specter@3x.png new file mode 100644 index 00000000..1d95cdfe Binary files /dev/null and b/src/main/resources/image/specter@3x.png differ