From 622b681109632dd9e0b245a8e9285f9c4474ef11 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Mon, 8 Feb 2021 16:29:59 +0200 Subject: [PATCH] add blue wallet vault import and export and add wallet export via qr --- .../sparrow/control/FileWalletExportPane.java | 82 ++++++++++++++---- .../sparrow/control/WalletExportDialog.java | 2 +- .../sparrow/control/WalletImportDialog.java | 2 +- .../sparrow/io/BlueWalletMultisig.java | 50 +++++++++++ .../sparrow/io/CoboVaultMultisig.java | 5 ++ .../sparrow/io/ColdcardMultisig.java | 5 ++ .../sparrowwallet/sparrow/io/Electrum.java | 5 ++ .../sparrow/io/SpecterDesktop.java | 8 +- .../sparrow/io/WalletExport.java | 1 + src/main/resources/image/bluewallet.png | Bin 0 -> 6344 bytes src/main/resources/image/bluewallet@2x.png | Bin 0 -> 8104 bytes src/main/resources/image/bluewallet@3x.png | Bin 0 -> 11153 bytes 12 files changed, 141 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/sparrowwallet/sparrow/io/BlueWalletMultisig.java create mode 100644 src/main/resources/image/bluewallet.png create mode 100644 src/main/resources/image/bluewallet@2x.png create mode 100644 src/main/resources/image/bluewallet@3x.png diff --git a/src/main/java/com/sparrowwallet/sparrow/control/FileWalletExportPane.java b/src/main/java/com/sparrowwallet/sparrow/control/FileWalletExportPane.java index 01ad2199..be014589 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/FileWalletExportPane.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/FileWalletExportPane.java @@ -2,44 +2,81 @@ package com.sparrowwallet.sparrow.control; import com.sparrowwallet.drongo.SecureString; import com.sparrowwallet.drongo.wallet.Wallet; +import com.sparrowwallet.hummingbird.registry.RegistryType; +import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.EventManager; import com.sparrowwallet.sparrow.event.StorageEvent; import com.sparrowwallet.sparrow.event.TimedEvent; import com.sparrowwallet.sparrow.event.WalletExportEvent; +import com.sparrowwallet.sparrow.glyphfont.FontAwesome5; +import com.sparrowwallet.sparrow.io.CoboVaultMultisig; import com.sparrowwallet.sparrow.io.Storage; import com.sparrowwallet.sparrow.io.WalletExport; import javafx.geometry.Pos; import javafx.scene.control.Button; import javafx.scene.control.Control; +import javafx.scene.control.ToggleButton; import javafx.stage.FileChooser; import javafx.stage.Stage; +import org.controlsfx.control.SegmentedButton; +import org.controlsfx.glyphfont.Glyph; -import java.io.File; -import java.io.FileOutputStream; -import java.io.OutputStream; +import java.io.*; +import java.nio.charset.StandardCharsets; import java.util.Optional; public class FileWalletExportPane extends TitledDescriptionPane { private final Wallet wallet; private final WalletExport exporter; + private final boolean scannable; public FileWalletExportPane(Wallet wallet, WalletExport exporter) { super(exporter.getName(), "Wallet file export", exporter.getWalletExportDescription(), "image/" + exporter.getWalletModel().getType() + ".png"); this.wallet = wallet; this.exporter = exporter; + this.scannable = exporter.isWalletExportScannable(); + + buttonBox.getChildren().clear(); + buttonBox.getChildren().add(createButton()); } @Override protected Control createButton() { - Button exportButton = new Button("Export Wallet..."); - exportButton.setAlignment(Pos.CENTER_RIGHT); - exportButton.setOnAction(event -> { - exportWallet(); - }); - return exportButton; + if(scannable) { + ToggleButton showButton = new ToggleButton("Show..."); + Glyph cameraGlyph = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.CAMERA); + cameraGlyph.setFontSize(12); + showButton.setGraphic(cameraGlyph); + showButton.setOnAction(event -> { + showButton.setSelected(false); + exportQR(); + }); + + ToggleButton fileButton = new ToggleButton("Export File..."); + fileButton.setAlignment(Pos.CENTER_RIGHT); + fileButton.setOnAction(event -> { + fileButton.setSelected(false); + exportFile(); + }); + + SegmentedButton segmentedButton = new SegmentedButton(); + segmentedButton.getButtons().addAll(showButton, fileButton); + return segmentedButton; + } else { + Button exportButton = new Button("Export File..."); + exportButton.setAlignment(Pos.CENTER_RIGHT); + exportButton.setOnAction(event -> { + exportFile(); + }); + return exportButton; + } } - private void exportWallet() { + private void exportQR() { + exportWallet(null); + } + + private void exportFile() { Stage window = new Stage(); FileChooser fileChooser = new FileChooser(); @@ -59,17 +96,18 @@ public class FileWalletExportPane extends TitledDescriptionPane { WalletPasswordDialog dlg = new WalletPasswordDialog(WalletPasswordDialog.PasswordRequirement.LOAD); Optional password = dlg.showAndWait(); if(password.isPresent()) { + final File walletFile = AppServices.get().getOpenWallets().get(wallet).getWalletFile(); Storage.DecryptWalletService decryptWalletService = new Storage.DecryptWalletService(copy, password.get()); decryptWalletService.setOnSucceeded(workerStateEvent -> { - EventManager.get().post(new StorageEvent(file, TimedEvent.Action.END, "Done")); + EventManager.get().post(new StorageEvent(walletFile, TimedEvent.Action.END, "Done")); Wallet decryptedWallet = decryptWalletService.getValue(); exportWallet(file, decryptedWallet); }); decryptWalletService.setOnFailed(workerStateEvent -> { - EventManager.get().post(new StorageEvent(file, TimedEvent.Action.END, "Failed")); + EventManager.get().post(new StorageEvent(walletFile, TimedEvent.Action.END, "Failed")); setError("Export Error", decryptWalletService.getException().getMessage()); }); - EventManager.get().post(new StorageEvent(file, TimedEvent.Action.START, "Decrypting wallet...")); + EventManager.get().post(new StorageEvent(walletFile, TimedEvent.Action.START, "Decrypting wallet...")); decryptWalletService.start(); } } else { @@ -79,9 +117,21 @@ public class FileWalletExportPane extends TitledDescriptionPane { private void exportWallet(File file, Wallet decryptedWallet) { try { - OutputStream outputStream = new FileOutputStream(file); - exporter.exportWallet(decryptedWallet, outputStream); - EventManager.get().post(new WalletExportEvent(decryptedWallet)); + if(file != null) { + OutputStream outputStream = new FileOutputStream(file); + exporter.exportWallet(decryptedWallet, outputStream); + EventManager.get().post(new WalletExportEvent(decryptedWallet)); + } else { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + exporter.exportWallet(decryptedWallet, outputStream); + QRDisplayDialog qrDisplayDialog; + if(exporter instanceof CoboVaultMultisig) { + qrDisplayDialog = new QRDisplayDialog(RegistryType.BYTES.toString(), outputStream.toByteArray(), true); + } else { + qrDisplayDialog = new QRDisplayDialog(outputStream.toString(StandardCharsets.UTF_8)); + } + qrDisplayDialog.showAndWait(); + } } catch(Exception e) { String errorMessage = e.getMessage(); if(e.getCause() != null && e.getCause().getMessage() != null && !e.getCause().getMessage().isEmpty()) { diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java index 7eb197ec..14e98d4f 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WalletExportDialog.java @@ -43,7 +43,7 @@ public class WalletExportDialog extends Dialog { if(wallet.getPolicyType() == PolicyType.SINGLE) { exporters = List.of(new Electrum(), new SpecterDesktop()); } else if(wallet.getPolicyType() == PolicyType.MULTI) { - exporters = List.of(new ColdcardMultisig(), new CoboVaultMultisig(), new Electrum(), new SpecterDesktop()); + exporters = List.of(new ColdcardMultisig(), new CoboVaultMultisig(), new Electrum(), new SpecterDesktop(), new BlueWalletMultisig()); } 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 596a44f9..f431b11e 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WalletImportDialog.java @@ -45,7 +45,7 @@ public class WalletImportDialog extends Dialog { importAccordion.getPanes().add(importPane); } - List walletImporters = List.of(new ColdcardMultisig(), new CoboVaultMultisig(), new Electrum(), new SpecterDesktop()); + List walletImporters = List.of(new ColdcardMultisig(), new CoboVaultMultisig(), new Electrum(), new SpecterDesktop(), new BlueWalletMultisig()); for(WalletImport importer : walletImporters) { FileWalletImportPane importPane = new FileWalletImportPane(importer); importAccordion.getPanes().add(importPane); diff --git a/src/main/java/com/sparrowwallet/sparrow/io/BlueWalletMultisig.java b/src/main/java/com/sparrowwallet/sparrow/io/BlueWalletMultisig.java new file mode 100644 index 00000000..0ec7b312 --- /dev/null +++ b/src/main/java/com/sparrowwallet/sparrow/io/BlueWalletMultisig.java @@ -0,0 +1,50 @@ +package com.sparrowwallet.sparrow.io; + +import com.sparrowwallet.drongo.wallet.Keystore; +import com.sparrowwallet.drongo.wallet.Wallet; +import com.sparrowwallet.drongo.wallet.WalletModel; + +import java.io.InputStream; + +public class BlueWalletMultisig extends ColdcardMultisig { + @Override + public String getName() { + return "Blue Wallet Vault Multisig"; + } + + @Override + public WalletModel getWalletModel() { + return WalletModel.BLUE_WALLET; + } + + @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", "Blue Wallet")); + keystore.setWalletModel(WalletModel.BLUE_WALLET); + } + + return wallet; + } + + @Override + public String getWalletImportDescription() { + return "Import file or QR created by using the Wallet > Export Coordination Setup feature on your Blue Wallet Vault wallet."; + } + + @Override + public String getWalletExportDescription() { + return "Export file that can be read by Blue Wallet using the Add Wallet > Vault > Import wallet feature."; + } + + @Override + public boolean isWalletImportScannable() { + return true; + } + + @Override + public boolean isWalletExportScannable() { + return true; + } +} diff --git a/src/main/java/com/sparrowwallet/sparrow/io/CoboVaultMultisig.java b/src/main/java/com/sparrowwallet/sparrow/io/CoboVaultMultisig.java index 81b50734..084c199a 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/CoboVaultMultisig.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/CoboVaultMultisig.java @@ -62,4 +62,9 @@ public class CoboVaultMultisig extends ColdcardMultisig { public boolean isKeystoreImportScannable() { return true; } + + @Override + public boolean isWalletExportScannable() { + return true; + } } diff --git a/src/main/java/com/sparrowwallet/sparrow/io/ColdcardMultisig.java b/src/main/java/com/sparrowwallet/sparrow/io/ColdcardMultisig.java index 75a5c8c6..9f027ce0 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/ColdcardMultisig.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/ColdcardMultisig.java @@ -222,4 +222,9 @@ public class ColdcardMultisig implements WalletImport, KeystoreFileImport, Walle public boolean isKeystoreImportScannable() { return false; } + + @Override + public boolean isWalletExportScannable() { + return false; + } } diff --git a/src/main/java/com/sparrowwallet/sparrow/io/Electrum.java b/src/main/java/com/sparrowwallet/sparrow/io/Electrum.java index bd18c0e0..f91ded5e 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/Electrum.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/Electrum.java @@ -359,6 +359,11 @@ public class Electrum implements KeystoreFileImport, WalletImport, WalletExport return false; } + @Override + public boolean isWalletExportScannable() { + return false; + } + @Override public String getWalletExportDescription() { return "Export this wallet as an Electrum wallet file."; diff --git a/src/main/java/com/sparrowwallet/sparrow/io/SpecterDesktop.java b/src/main/java/com/sparrowwallet/sparrow/io/SpecterDesktop.java index fbc17eec..48c95cc7 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/SpecterDesktop.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/SpecterDesktop.java @@ -3,6 +3,7 @@ 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.BlockTransactionHash; import com.sparrowwallet.drongo.wallet.InvalidWalletException; import com.sparrowwallet.drongo.wallet.Wallet; import com.sparrowwallet.drongo.wallet.WalletModel; @@ -19,7 +20,7 @@ public class SpecterDesktop implements WalletImport, WalletExport { try { SpecterWallet specterWallet = new SpecterWallet(); specterWallet.label = wallet.getName(); - specterWallet.blockheight = wallet.getStoredBlockHeight(); + specterWallet.blockheight = wallet.getTransactions().values().stream().mapToInt(BlockTransactionHash::getHeight).min().orElse(wallet.getStoredBlockHeight()); specterWallet.descriptor = OutputDescriptor.getOutputDescriptor(wallet).toString(true); Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); @@ -83,6 +84,11 @@ public class SpecterDesktop implements WalletImport, WalletExport { return true; } + @Override + public boolean isWalletExportScannable() { + return true; + } + @Override public String getName() { return "Specter Desktop"; diff --git a/src/main/java/com/sparrowwallet/sparrow/io/WalletExport.java b/src/main/java/com/sparrowwallet/sparrow/io/WalletExport.java index 95f34344..75bf5009 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/WalletExport.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/WalletExport.java @@ -8,4 +8,5 @@ public interface WalletExport extends Export { void exportWallet(Wallet wallet, OutputStream outputStream) throws ExportException; String getWalletExportDescription(); String getExportFileExtension(); + boolean isWalletExportScannable(); } diff --git a/src/main/resources/image/bluewallet.png b/src/main/resources/image/bluewallet.png new file mode 100644 index 0000000000000000000000000000000000000000..746172d42d333285890b0441d222a677325ef307 GIT binary patch literal 6344 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/image/bluewallet@3x.png b/src/main/resources/image/bluewallet@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..79bad672cde2bae471f551be9c07bb4d5a1f1e9e GIT binary patch literal 11153 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