use json persistence for sparrow wallet export, add sparrow wallet import to wallets dir

This commit is contained in:
Craig Raw 2021-06-11 11:29:54 +02:00
parent 8914acff68
commit 9ebabecfbe
5 changed files with 66 additions and 19 deletions

View file

@ -858,10 +858,6 @@ public class AppServices {
deviceEnumerateService = createDeviceEnumerateService(); deviceEnumerateService = createDeviceEnumerateService();
} }
if(deviceEnumerateService.isRunning()) {
deviceEnumerateService.cancel();
}
if(deviceEnumerateService.getState() == Worker.State.CANCELLED) { if(deviceEnumerateService.getState() == Worker.State.CANCELLED) {
deviceEnumerateService.reset(); deviceEnumerateService.reset();
} }

View file

@ -9,10 +9,7 @@ import com.sparrowwallet.sparrow.event.StorageEvent;
import com.sparrowwallet.sparrow.event.TimedEvent; import com.sparrowwallet.sparrow.event.TimedEvent;
import com.sparrowwallet.sparrow.event.WalletExportEvent; import com.sparrowwallet.sparrow.event.WalletExportEvent;
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5; import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
import com.sparrowwallet.sparrow.io.CoboVaultMultisig; import com.sparrowwallet.sparrow.io.*;
import com.sparrowwallet.sparrow.io.PassportMultisig;
import com.sparrowwallet.sparrow.io.Storage;
import com.sparrowwallet.sparrow.io.WalletExport;
import javafx.geometry.Pos; import javafx.geometry.Pos;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.Control; import javafx.scene.control.Control;
@ -83,8 +80,8 @@ public class FileWalletExportPane extends TitledDescriptionPane {
FileChooser fileChooser = new FileChooser(); FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Export " + exporter.getWalletModel().toDisplayString() + " File"); fileChooser.setTitle("Export " + exporter.getWalletModel().toDisplayString() + " File");
String extension = exporter.getExportFileExtension(wallet); String extension = exporter.getExportFileExtension(wallet);
fileChooser.setInitialFileName(wallet.getName() + "-" + fileChooser.setInitialFileName(wallet.getName() +
exporter.getWalletModel().toDisplayString().toLowerCase().replace(" ", "") + (exporter instanceof Sparrow ? "" : "-" + exporter.getWalletModel().toDisplayString().toLowerCase().replace(" ", "")) +
(extension == null || extension.isEmpty() ? "" : "." + extension)); (extension == null || extension.isEmpty() ? "" : "." + extension));
AppServices.moveToActiveWindowScreen(window, 800, 450); AppServices.moveToActiveWindowScreen(window, 800, 450);
@ -137,7 +134,7 @@ public class FileWalletExportPane extends TitledDescriptionPane {
QRDisplayDialog qrDisplayDialog; QRDisplayDialog qrDisplayDialog;
if(exporter instanceof CoboVaultMultisig) { if(exporter instanceof CoboVaultMultisig) {
qrDisplayDialog = new QRDisplayDialog(RegistryType.BYTES.toString(), outputStream.toByteArray(), true); qrDisplayDialog = new QRDisplayDialog(RegistryType.BYTES.toString(), outputStream.toByteArray(), true);
} else if(exporter instanceof PassportMultisig) { } else if(exporter instanceof PassportMultisig || exporter instanceof KeystoneMultisig) {
qrDisplayDialog = new QRDisplayDialog(RegistryType.BYTES.toString(), outputStream.toByteArray(), false); qrDisplayDialog = new QRDisplayDialog(RegistryType.BYTES.toString(), outputStream.toByteArray(), false);
} else { } else {
qrDisplayDialog = new QRDisplayDialog(outputStream.toString(StandardCharsets.UTF_8)); qrDisplayDialog = new QRDisplayDialog(outputStream.toString(StandardCharsets.UTF_8));

View file

@ -53,7 +53,7 @@ public class WalletImportDialog extends Dialog<Wallet> {
importAccordion.getPanes().add(importPane); importAccordion.getPanes().add(importPane);
} }
List<WalletImport> walletImporters = List.of(new ColdcardMultisig(), new CoboVaultMultisig(), new Electrum(), new KeystoneMultisig(), new SpecterDesktop(), new BlueWalletMultisig()); List<WalletImport> walletImporters = List.of(new ColdcardMultisig(), new CoboVaultMultisig(), new Electrum(), new KeystoneMultisig(), new SpecterDesktop(), new BlueWalletMultisig(), new Sparrow());
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);

View file

@ -1,15 +1,19 @@
package com.sparrowwallet.sparrow.io; package com.sparrowwallet.sparrow.io;
import com.google.common.io.Files;
import com.sparrowwallet.drongo.wallet.Wallet; import com.sparrowwallet.drongo.wallet.Wallet;
import com.sparrowwallet.drongo.wallet.WalletModel; import com.sparrowwallet.drongo.wallet.WalletModel;
import com.sparrowwallet.sparrow.AppServices; import com.sparrowwallet.sparrow.AppServices;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.file.Files; import java.nio.file.StandardCopyOption;
public class Sparrow implements WalletExport { public class Sparrow implements WalletImport, WalletExport {
private static final Logger log = LoggerFactory.getLogger(Sparrow.class); private static final Logger log = LoggerFactory.getLogger(Sparrow.class);
@Override @Override
@ -26,8 +30,14 @@ public class Sparrow implements WalletExport {
public void exportWallet(Wallet wallet, OutputStream outputStream) throws ExportException { public void exportWallet(Wallet wallet, OutputStream outputStream) throws ExportException {
try { try {
Storage storage = AppServices.get().getOpenWallets().get(wallet); Storage storage = AppServices.get().getOpenWallets().get(wallet);
storage.copyWallet(outputStream); File tempFile = File.createTempFile(wallet.getName(), null);
Storage tempStorage = new Storage(PersistenceType.JSON, tempFile);
tempStorage.setKeyDeriver(storage.getKeyDeriver());
tempStorage.setEncryptionPubKey(storage.getEncryptionPubKey());
tempStorage.saveWallet(wallet);
Files.copy(tempStorage.getWalletFile(), outputStream);
outputStream.flush(); outputStream.flush();
tempStorage.getWalletFile().delete();
} catch(Exception e) { } catch(Exception e) {
log.error("Error exporting Sparrow wallet file", e); log.error("Error exporting Sparrow wallet file", e);
throw new ExportException("Error exporting Sparrow wallet file", e); throw new ExportException("Error exporting Sparrow wallet file", e);
@ -36,13 +46,19 @@ public class Sparrow implements WalletExport {
@Override @Override
public String getWalletExportDescription() { public String getWalletExportDescription() {
return "Exports a copy of your Sparrow wallet file, which can be loaded in another Sparrow instance running on any supported platform."; return "Exports your Sparrow wallet file, which can be imported into another Sparrow instance running on any supported platform.";
} }
@Override @Override
public String getExportFileExtension(Wallet wallet) { public String getExportFileExtension(Wallet wallet) {
Storage storage = AppServices.get().getOpenWallets().get(wallet); try {
return storage.getWalletFileExtension(); Storage storage = AppServices.get().getOpenWallets().get(wallet);
return storage.isEncrypted() ? "" : PersistenceType.JSON.getExtension();
} catch(IOException e) {
//ignore
}
return "";
} }
@Override @Override
@ -54,4 +70,41 @@ public class Sparrow implements WalletExport {
public boolean walletExportRequiresDecryption() { public boolean walletExportRequiresDecryption() {
return false; return false;
} }
@Override
public boolean isEncrypted(File file) {
return Storage.isEncrypted(file);
}
@Override
public String getWalletImportDescription() {
return "Imports an exported Sparrow wallet file into Sparrow's wallets folder.";
}
@Override
public Wallet importWallet(InputStream inputStream, String password) throws ImportException {
File tempFile = null;
try {
tempFile = File.createTempFile("sparrow", null);
java.nio.file.Files.copy(inputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
Storage storage = new Storage(PersistenceType.JSON, tempFile);
if(!isEncrypted(tempFile)) {
return storage.loadUnencryptedWallet().getWallet();
} else {
return storage.loadEncryptedWallet(password).getWallet();
}
} catch(IOException | StorageException e) {
log.error("Error importing Sparrow wallet", e);
throw new ImportException("Error importing Sparrow wallet", e);
} finally {
if(tempFile != null) {
tempFile.delete();
}
}
}
@Override
public boolean isWalletImportScannable() {
return false;
}
} }

View file

@ -37,6 +37,7 @@ public class Storage {
public static final String WALLETS_BACKUP_DIR = "backup"; public static final String WALLETS_BACKUP_DIR = "backup";
public static final String CERTS_DIR = "certs"; public static final String CERTS_DIR = "certs";
public static final String TEMP_BACKUP_PREFIX = "tmp"; public static final String TEMP_BACKUP_PREFIX = "tmp";
public static final List<String> RESERVED_WALLET_NAMES = List.of("temp");
private Persistence persistence; private Persistence persistence;
private File walletFile; private File walletFile;
@ -284,7 +285,7 @@ public class Storage {
} }
} }
return false; return RESERVED_WALLET_NAMES.contains(walletName);
} }
public static File getExistingWallet(String walletName) { public static File getExistingWallet(String walletName) {