mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2026-08-09 08:14:43 +00:00
attempt to import wallet file if open fails
This commit is contained in:
@@ -773,6 +773,9 @@ public class AppController implements Initializable {
|
||||
Wallet wallet = storage.loadWallet();
|
||||
checkWalletNetwork(wallet);
|
||||
restorePublicKeysFromSeed(wallet, null);
|
||||
if(!wallet.isValid()) {
|
||||
throw new IllegalStateException("Wallet file is not valid.");
|
||||
}
|
||||
Tab tab = addWalletTab(storage, wallet);
|
||||
tabs.getSelectionModel().select(tab);
|
||||
} else if(FileType.BINARY.equals(fileType)) {
|
||||
@@ -804,8 +807,11 @@ public class AppController implements Initializable {
|
||||
if(exception instanceof InvalidPasswordException) {
|
||||
showErrorDialog("Invalid Password", "The wallet password was invalid.");
|
||||
} else {
|
||||
log.error("Error Opening Wallet", exception);
|
||||
showErrorDialog("Error Opening Wallet", exception.getMessage());
|
||||
if(!attemptImportWallet(file, password)) {
|
||||
log.error("Error Opening Wallet", exception);
|
||||
showErrorDialog("Error Opening Wallet", exception.getMessage());
|
||||
}
|
||||
password.clear();
|
||||
}
|
||||
});
|
||||
EventManager.get().post(new StorageEvent(storage.getWalletFile(), TimedEvent.Action.START, "Decrypting wallet..."));
|
||||
@@ -814,8 +820,10 @@ public class AppController implements Initializable {
|
||||
throw new IOException("Unsupported file type");
|
||||
}
|
||||
} catch(Exception e) {
|
||||
log.error("Error opening wallet", e);
|
||||
showErrorDialog("Error Opening Wallet", e.getMessage());
|
||||
if(!attemptImportWallet(file, null)) {
|
||||
log.error("Error opening wallet", e);
|
||||
showErrorDialog("Error Opening Wallet", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -872,35 +880,65 @@ public class AppController implements Initializable {
|
||||
Optional<Wallet> optionalWallet = dlg.showAndWait();
|
||||
if(optionalWallet.isPresent()) {
|
||||
Wallet wallet = optionalWallet.get();
|
||||
File walletFile = Storage.getWalletFile(wallet.getName());
|
||||
addImportedWallet(wallet);
|
||||
}
|
||||
}
|
||||
|
||||
if(walletFile.exists()) {
|
||||
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
||||
alert.setTitle("Existing wallet found");
|
||||
alert.setHeaderText("Replace existing wallet?");
|
||||
alert.setContentText("Wallet file " + wallet.getName() + " already exists");
|
||||
Optional<ButtonType> result = alert.showAndWait();
|
||||
if(result.isPresent() && result.get() == ButtonType.CANCEL) {
|
||||
return;
|
||||
private boolean attemptImportWallet(File file, SecureString password) {
|
||||
List<WalletImport> walletImporters = List.of(new ColdcardSinglesig(), new ColdcardMultisig(), new Electrum(), new Specter());
|
||||
for(WalletImport importer : walletImporters) {
|
||||
try(FileInputStream inputStream = new FileInputStream(file)) {
|
||||
if(importer.isEncrypted(file) && password == null) {
|
||||
WalletPasswordDialog dlg = new WalletPasswordDialog(file.getName(), WalletPasswordDialog.PasswordRequirement.LOAD);
|
||||
Optional<SecureString> optionalPassword = dlg.showAndWait();
|
||||
if(optionalPassword.isPresent()) {
|
||||
password = optionalPassword.get();
|
||||
}
|
||||
}
|
||||
|
||||
//Close existing wallet first if open
|
||||
for(Iterator<Tab> iter = tabs.getTabs().iterator(); iter.hasNext(); ) {
|
||||
Tab tab = iter.next();
|
||||
TabData tabData = (TabData)tab.getUserData();
|
||||
if(tabData.getType() == TabData.TabType.WALLET) {
|
||||
WalletTabData walletTabData = (WalletTabData) tabData;
|
||||
if(walletTabData.getStorage().getWalletFile().equals(walletFile)) {
|
||||
iter.remove();
|
||||
}
|
||||
Wallet wallet = importer.importWallet(inputStream, password == null ? null: password.asString());
|
||||
if(wallet.getName() == null) {
|
||||
wallet.setName(file.getName());
|
||||
}
|
||||
addImportedWallet(wallet);
|
||||
return true;
|
||||
} catch(Exception e) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addImportedWallet(Wallet wallet) {
|
||||
File walletFile = Storage.getWalletFile(wallet.getName());
|
||||
|
||||
if(walletFile.exists()) {
|
||||
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
||||
alert.setTitle("Existing wallet found");
|
||||
alert.setHeaderText("Replace existing wallet?");
|
||||
alert.setContentText("Wallet file " + wallet.getName() + " already exists");
|
||||
Optional<ButtonType> result = alert.showAndWait();
|
||||
if(result.isPresent() && result.get() == ButtonType.CANCEL) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Close existing wallet first if open
|
||||
for(Iterator<Tab> iter = tabs.getTabs().iterator(); iter.hasNext(); ) {
|
||||
Tab tab = iter.next();
|
||||
TabData tabData = (TabData)tab.getUserData();
|
||||
if(tabData.getType() == TabData.TabType.WALLET) {
|
||||
WalletTabData walletTabData = (WalletTabData) tabData;
|
||||
if(walletTabData.getStorage().getWalletFile().equals(walletFile)) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Storage storage = new Storage(walletFile);
|
||||
Tab tab = addWalletTab(storage, wallet);
|
||||
tabs.getSelectionModel().select(tab);
|
||||
}
|
||||
|
||||
Storage storage = new Storage(walletFile);
|
||||
Tab tab = addWalletTab(storage, wallet);
|
||||
tabs.getSelectionModel().select(tab);
|
||||
}
|
||||
|
||||
public void exportWallet(ActionEvent event) {
|
||||
|
||||
@@ -5,9 +5,12 @@ import com.google.gson.JsonElement;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.sparrowwallet.drongo.ExtendedKey;
|
||||
import com.sparrowwallet.drongo.KeyDerivation;
|
||||
import com.sparrowwallet.drongo.policy.Policy;
|
||||
import com.sparrowwallet.drongo.policy.PolicyType;
|
||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||
import com.sparrowwallet.drongo.wallet.KeystoreSource;
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import com.sparrowwallet.drongo.wallet.WalletModel;
|
||||
|
||||
import java.io.File;
|
||||
@@ -16,7 +19,7 @@ import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
|
||||
public class ColdcardSinglesig implements KeystoreFileImport {
|
||||
public class ColdcardSinglesig implements KeystoreFileImport, WalletImport {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Coldcard";
|
||||
@@ -77,6 +80,29 @@ public class ColdcardSinglesig implements KeystoreFileImport {
|
||||
throw new ImportException("Correct derivation not found for script type: " + scriptType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWalletImportDescription() {
|
||||
return getKeystoreImportDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Wallet importWallet(InputStream inputStream, String password) throws ImportException {
|
||||
//Use default of P2WPKH
|
||||
Keystore keystore = getKeystore(ScriptType.P2WPKH, inputStream, "");
|
||||
|
||||
Wallet wallet = new Wallet();
|
||||
wallet.setPolicyType(PolicyType.SINGLE);
|
||||
wallet.setScriptType(ScriptType.P2WPKH);
|
||||
wallet.getKeystores().add(keystore);
|
||||
wallet.setDefaultPolicy(Policy.getPolicy(PolicyType.SINGLE, ScriptType.P2WPKH, wallet.getKeystores(), null));
|
||||
|
||||
if(!wallet.isValid()) {
|
||||
throw new ImportException("Wallet is in an inconsistent state.");
|
||||
}
|
||||
|
||||
return wallet;
|
||||
}
|
||||
|
||||
private static class ColdcardKeystore {
|
||||
public String deriv;
|
||||
public String name;
|
||||
|
||||
@@ -81,7 +81,7 @@ public class Storage {
|
||||
return gsonBuilder.setPrettyPrinting().disableHtmlEscaping().create();
|
||||
}
|
||||
|
||||
public Wallet loadWallet() throws IOException, MnemonicException {
|
||||
public Wallet loadWallet() throws IOException {
|
||||
Reader reader = new FileReader(walletFile);
|
||||
Wallet wallet = gson.fromJson(reader, Wallet.class);
|
||||
reader.close();
|
||||
@@ -90,7 +90,7 @@ public class Storage {
|
||||
return wallet;
|
||||
}
|
||||
|
||||
public WalletAndKey loadWallet(CharSequence password) throws IOException, MnemonicException, StorageException {
|
||||
public WalletAndKey loadWallet(CharSequence password) throws IOException, StorageException {
|
||||
InputStream fileStream = new FileInputStream(walletFile);
|
||||
ECKey encryptionKey = getEncryptionKey(password, fileStream);
|
||||
|
||||
@@ -461,11 +461,9 @@ public class Storage {
|
||||
protected Task<WalletAndKey> createTask() {
|
||||
return new Task<>() {
|
||||
protected WalletAndKey call() throws IOException, StorageException, MnemonicException {
|
||||
try {
|
||||
return storage.loadWallet(password);
|
||||
} finally {
|
||||
password.clear();
|
||||
}
|
||||
WalletAndKey walletAndKey = storage.loadWallet(password);
|
||||
password.clear();
|
||||
return walletAndKey;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user