diff --git a/src/main/java/com/sparrowwallet/sparrow/AppController.java b/src/main/java/com/sparrowwallet/sparrow/AppController.java index 9c207841..15ae9c28 100644 --- a/src/main/java/com/sparrowwallet/sparrow/AppController.java +++ b/src/main/java/com/sparrowwallet/sparrow/AppController.java @@ -978,6 +978,7 @@ public class AppController implements Initializable { List walletImporters = List.of(new ColdcardSinglesig(), new ColdcardMultisig(), new Electrum(), new SpecterDesktop(), + new Descriptor(), new CoboVaultSinglesig(), new CoboVaultMultisig(), new PassportSinglesig(), new KeystoneSinglesig(), new KeystoneMultisig(), diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java index b4c588a9..ac1908e1 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java @@ -42,9 +42,9 @@ public class WalletExportDialog extends Dialog { List exporters; if(wallet.getPolicyType() == PolicyType.SINGLE) { - exporters = List.of(new Electrum(), new SpecterDesktop(), new Sparrow()); + exporters = List.of(new Electrum(), new Descriptor(), new SpecterDesktop(), new Sparrow()); } else if(wallet.getPolicyType() == PolicyType.MULTI) { - exporters = List.of(new CaravanMultisig(), new ColdcardMultisig(), new CoboVaultMultisig(), new Electrum(), new KeystoneMultisig(), new PassportMultisig(), new SpecterDesktop(), new BlueWalletMultisig(), new SpecterDIY(), new Sparrow()); + exporters = List.of(new CaravanMultisig(), new ColdcardMultisig(), new CoboVaultMultisig(), new Electrum(), new KeystoneMultisig(), new Descriptor(), new PassportMultisig(), new SpecterDesktop(), new BlueWalletMultisig(), new SpecterDIY(), new Sparrow()); } 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 3b91c4c0..65c9a733 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java @@ -54,7 +54,7 @@ public class WalletImportDialog extends Dialog { importAccordion.getPanes().add(importPane); } - List walletImporters = List.of(new CaravanMultisig(), new ColdcardMultisig(), new CoboVaultMultisig(), new Electrum(), new KeystoneMultisig(), new SpecterDesktop(), new BlueWalletMultisig(), new Sparrow()); + List walletImporters = List.of(new CaravanMultisig(), new ColdcardMultisig(), new CoboVaultMultisig(), new Electrum(), new KeystoneMultisig(), new Descriptor(), new SpecterDesktop(), new BlueWalletMultisig(), new Sparrow()); for(WalletImport importer : walletImporters) { FileWalletImportPane importPane = new FileWalletImportPane(importer); importAccordion.getPanes().add(importPane); diff --git a/src/main/java/com/sparrowwallet/sparrow/io/Descriptor.java b/src/main/java/com/sparrowwallet/sparrow/io/Descriptor.java new file mode 100644 index 00000000..5e2976c9 --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/io/Descriptor.java @@ -0,0 +1,80 @@ +package com.sparrowwallet.sparrow.io; + +import com.sparrowwallet.drongo.OutputDescriptor; +import com.sparrowwallet.drongo.wallet.Wallet; +import com.sparrowwallet.drongo.wallet.WalletModel; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.stream.Collectors; + +public class Descriptor implements WalletImport, WalletExport { + + @Override + public String getName() { + return "Output Descriptor"; + } + + @Override + public WalletModel getWalletModel() { + return WalletModel.BITCOIN_CORE; + } + + @Override + public void exportWallet(Wallet wallet, OutputStream outputStream) throws ExportException { + try { + OutputDescriptor outputDescriptor = OutputDescriptor.getOutputDescriptor(wallet); + String outputDescriptorString = outputDescriptor.toString(true); + outputStream.write(outputDescriptorString.getBytes(StandardCharsets.UTF_8)); + outputStream.flush(); + } catch(Exception e) { + throw new ExportException("Error writing output descriptor", e); + } + } + + @Override + public String getWalletExportDescription() { + return "The output descriptor is a standardized description of the wallet compatible with Bitcoin Core, and can be used to create a watch-only copy using the Edit button on the Settings tab of a new Sparrow wallet."; + } + + @Override + public String getExportFileExtension(Wallet wallet) { + return "txt"; + } + + @Override + public boolean isWalletExportScannable() { + return false; + } + + @Override + public boolean walletExportRequiresDecryption() { + return false; + } + + @Override + public boolean isEncrypted(File file) { + return false; + } + + @Override + public String getWalletImportDescription() { + return "Import a file containing the output descriptor of a wallet. The output descriptor is a standardized description of the wallet compatible with Bitcoin Core."; + } + + @Override + public Wallet importWallet(InputStream inputStream, String password) throws ImportException { + try { + String outputDescriptor = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)).lines().collect(Collectors.joining("\n")); + OutputDescriptor descriptor = OutputDescriptor.getOutputDescriptor(outputDescriptor.trim()); + return descriptor.toWallet(); + } catch(Exception e) { + throw new ImportException("Error importing output descriptor", e); + } + } + + @Override + public boolean isWalletImportScannable() { + return false; + } +} diff --git a/src/main/resources/image/bitcoincore.png b/src/main/resources/image/bitcoincore.png new file mode 100644 index 00000000..79503e25 Binary files /dev/null and b/src/main/resources/image/bitcoincore.png differ diff --git a/src/main/resources/image/bitcoincore@2x.png b/src/main/resources/image/bitcoincore@2x.png new file mode 100644 index 00000000..d840474a Binary files /dev/null and b/src/main/resources/image/bitcoincore@2x.png differ diff --git a/src/main/resources/image/bitcoincore@3x.png b/src/main/resources/image/bitcoincore@3x.png new file mode 100644 index 00000000..84a36185 Binary files /dev/null and b/src/main/resources/image/bitcoincore@3x.png differ