mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-24 12:46:45 +00:00
integrate keystore importer
This commit is contained in:
parent
9af17bcac8
commit
6872e069a9
5 changed files with 75 additions and 8 deletions
|
@ -2,6 +2,7 @@ package com.sparrowwallet.sparrow.io;
|
||||||
|
|
||||||
import com.google.gson.*;
|
import com.google.gson.*;
|
||||||
import com.sparrowwallet.drongo.ExtendedKey;
|
import com.sparrowwallet.drongo.ExtendedKey;
|
||||||
|
import com.sparrowwallet.drongo.Utils;
|
||||||
import com.sparrowwallet.drongo.crypto.ECKey;
|
import com.sparrowwallet.drongo.crypto.ECKey;
|
||||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
|
|
||||||
|
@ -22,7 +23,9 @@ public class Storage {
|
||||||
GsonBuilder gsonBuilder = new GsonBuilder();
|
GsonBuilder gsonBuilder = new GsonBuilder();
|
||||||
gsonBuilder.registerTypeAdapter(ExtendedKey.class, new ExtendedPublicKeySerializer());
|
gsonBuilder.registerTypeAdapter(ExtendedKey.class, new ExtendedPublicKeySerializer());
|
||||||
gsonBuilder.registerTypeAdapter(ExtendedKey.class, new ExtendedPublicKeyDeserializer());
|
gsonBuilder.registerTypeAdapter(ExtendedKey.class, new ExtendedPublicKeyDeserializer());
|
||||||
gson = gsonBuilder.setPrettyPrinting().create();
|
gsonBuilder.registerTypeAdapter(byte[].class, new ByteArraySerializer());
|
||||||
|
gsonBuilder.registerTypeAdapter(byte[].class, new ByteArrayDeserializer());
|
||||||
|
gson = gsonBuilder.setPrettyPrinting().disableHtmlEscaping().create();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Storage getStorage() {
|
public static Storage getStorage() {
|
||||||
|
@ -76,7 +79,7 @@ public class Storage {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] getEncryptionMagic() {
|
private static byte[] getEncryptionMagic() {
|
||||||
return "BIE1".getBytes(StandardCharsets.UTF_8);
|
return "SPRW1".getBytes(StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getWalletFile(String walletName) {
|
public File getWalletFile(String walletName) {
|
||||||
|
@ -84,7 +87,12 @@ public class Storage {
|
||||||
}
|
}
|
||||||
|
|
||||||
public File getWalletsDir() {
|
public File getWalletsDir() {
|
||||||
return new File(getSparrowDir(), WALLETS_DIR);
|
File walletsDir = new File(getSparrowDir(), WALLETS_DIR);
|
||||||
|
if(!walletsDir.exists()) {
|
||||||
|
walletsDir.mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
return walletsDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
private File getSparrowDir() {
|
private File getSparrowDir() {
|
||||||
|
@ -108,4 +116,18 @@ public class Storage {
|
||||||
return ExtendedKey.fromDescriptor(json.getAsJsonPrimitive().getAsString());
|
return ExtendedKey.fromDescriptor(json.getAsJsonPrimitive().getAsString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ByteArraySerializer implements JsonSerializer<byte[]> {
|
||||||
|
@Override
|
||||||
|
public JsonElement serialize(byte[] src, Type typeOfSrc, JsonSerializationContext context) {
|
||||||
|
return new JsonPrimitive(Utils.bytesToHex(src));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ByteArrayDeserializer implements JsonDeserializer<byte[]> {
|
||||||
|
@Override
|
||||||
|
public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||||
|
return Utils.hexToBytes(json.getAsJsonPrimitive().getAsString());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ public class KeystoreImportDialog extends Dialog<Keystore> {
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void keystoreImported(KeystoreImportEvent event) {
|
public void keystoreImported(KeystoreImportEvent event) {
|
||||||
this.keystore = event.getKeystore();
|
this.keystore = event.getKeystore();
|
||||||
System.out.println(keystore.getLabel() + " " + keystore.getKeyDerivation().getMasterFingerprint());
|
setResult(keystore);
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.sparrowwallet.drongo.ExtendedKey;
|
||||||
import com.sparrowwallet.drongo.KeyDerivation;
|
import com.sparrowwallet.drongo.KeyDerivation;
|
||||||
import com.sparrowwallet.drongo.Utils;
|
import com.sparrowwallet.drongo.Utils;
|
||||||
import com.sparrowwallet.drongo.wallet.Keystore;
|
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||||
|
import com.sparrowwallet.drongo.wallet.KeystoreSource;
|
||||||
import com.sparrowwallet.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.keystoreimport.KeystoreImportDialog;
|
import com.sparrowwallet.sparrow.keystoreimport.KeystoreImportDialog;
|
||||||
import com.sparrowwallet.sparrow.event.SettingsChangedEvent;
|
import com.sparrowwallet.sparrow.event.SettingsChangedEvent;
|
||||||
|
@ -12,6 +13,7 @@ import javafx.event.ActionEvent;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.scene.control.Control;
|
import javafx.scene.control.Control;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.TextArea;
|
import javafx.scene.control.TextArea;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
import org.controlsfx.validation.ValidationResult;
|
import org.controlsfx.validation.ValidationResult;
|
||||||
|
@ -27,6 +29,9 @@ import java.util.stream.Collectors;
|
||||||
public class KeystoreController extends WalletFormController implements Initializable {
|
public class KeystoreController extends WalletFormController implements Initializable {
|
||||||
private Keystore keystore;
|
private Keystore keystore;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Label type;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private TextField label;
|
private TextField label;
|
||||||
|
|
||||||
|
@ -55,6 +60,8 @@ public class KeystoreController extends WalletFormController implements Initiali
|
||||||
public void initializeView() {
|
public void initializeView() {
|
||||||
Platform.runLater(this::setupValidation);
|
Platform.runLater(this::setupValidation);
|
||||||
|
|
||||||
|
updateType();
|
||||||
|
|
||||||
label.setText(keystore.getLabel());
|
label.setText(keystore.getLabel());
|
||||||
|
|
||||||
if(keystore.getExtendedPublicKey() != null) {
|
if(keystore.getExtendedPublicKey() != null) {
|
||||||
|
@ -102,7 +109,7 @@ public class KeystoreController extends WalletFormController implements Initiali
|
||||||
validationSupport.registerValidator(label, Validator.combine(
|
validationSupport.registerValidator(label, Validator.combine(
|
||||||
Validator.createEmptyValidator("Label is required"),
|
Validator.createEmptyValidator("Label is required"),
|
||||||
(Control c, String newValue) -> ValidationResult.fromErrorIf( c, "Label is not unique", walletForm.getWallet().getKeystores().stream().filter(k -> k != keystore).map(Keystore::getLabel).collect(Collectors.toList()).contains(newValue)),
|
(Control c, String newValue) -> ValidationResult.fromErrorIf( c, "Label is not unique", walletForm.getWallet().getKeystores().stream().filter(k -> k != keystore).map(Keystore::getLabel).collect(Collectors.toList()).contains(newValue)),
|
||||||
(Control c, String newValue) -> ValidationResult.fromErrorIf( c, "Label is too long", newValue.length() > 16)
|
(Control c, String newValue) -> ValidationResult.fromErrorIf( c, "Label is too long", newValue.replace(" ", "").length() > 16)
|
||||||
));
|
));
|
||||||
|
|
||||||
validationSupport.registerValidator(xpub, Validator.combine(
|
validationSupport.registerValidator(xpub, Validator.combine(
|
||||||
|
@ -123,11 +130,43 @@ public class KeystoreController extends WalletFormController implements Initiali
|
||||||
validationSupport.setValidationDecorator(new StyleClassValidationDecoration());
|
validationSupport.setValidationDecorator(new StyleClassValidationDecoration());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateType() {
|
||||||
|
type.setText(getTypeLabel(keystore));
|
||||||
|
|
||||||
|
boolean editable = (keystore.getSource() == KeystoreSource.SW_WATCH);
|
||||||
|
label.setEditable(editable);
|
||||||
|
fingerprint.setEditable(editable);
|
||||||
|
derivation.setEditable(editable);
|
||||||
|
xpub.setEditable(editable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getTypeLabel(Keystore keystore) {
|
||||||
|
switch (keystore.getSource()) {
|
||||||
|
case HW_USB:
|
||||||
|
return "Connected Hardware Wallet (" + keystore.getWalletModel().toDisplayString() + ")";
|
||||||
|
case HW_AIRGAPPED:
|
||||||
|
return "Airgapped Hardware Wallet (" + keystore.getWalletModel().toDisplayString() + ")";
|
||||||
|
case SW_SEED:
|
||||||
|
return "Software Wallet";
|
||||||
|
case SW_WATCH:
|
||||||
|
default:
|
||||||
|
return "Software Wallet (Watch Only)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void importKeystore(ActionEvent event) {
|
public void importKeystore(ActionEvent event) {
|
||||||
KeystoreImportDialog dlg = new KeystoreImportDialog(getWalletForm().getWallet());
|
KeystoreImportDialog dlg = new KeystoreImportDialog(getWalletForm().getWallet());
|
||||||
Optional<Keystore> result = dlg.showAndWait();
|
Optional<Keystore> result = dlg.showAndWait();
|
||||||
if(result.isPresent()) {
|
if(result.isPresent()) {
|
||||||
Keystore keystore = result.get();
|
Keystore importedKeystore = result.get();
|
||||||
|
keystore.setSource(importedKeystore.getSource());
|
||||||
|
keystore.setWalletModel(importedKeystore.getWalletModel());
|
||||||
|
keystore.setLabel(importedKeystore.getLabel());
|
||||||
|
keystore.setKeyDerivation(importedKeystore.getKeyDerivation());
|
||||||
|
keystore.setExtendedPublicKey(importedKeystore.getExtendedPublicKey());
|
||||||
|
keystore.setSeed(importedKeystore.getSeed());
|
||||||
|
|
||||||
|
updateType();
|
||||||
label.setText(keystore.getLabel());
|
label.setText(keystore.getLabel());
|
||||||
fingerprint.setText(keystore.getKeyDerivation().getMasterFingerprint());
|
fingerprint.setText(keystore.getKeyDerivation().getMasterFingerprint());
|
||||||
derivation.setText(keystore.getKeyDerivation().getDerivationPath());
|
derivation.setText(keystore.getKeyDerivation().getDerivationPath());
|
||||||
|
|
|
@ -89,9 +89,12 @@ public class SettingsController extends WalletFormController implements Initiali
|
||||||
|
|
||||||
multisigFieldset.setVisible(policyType.equals(PolicyType.MULTI));
|
multisigFieldset.setVisible(policyType.equals(PolicyType.MULTI));
|
||||||
if(policyType.equals(PolicyType.MULTI)) {
|
if(policyType.equals(PolicyType.MULTI)) {
|
||||||
|
totalKeystores.unbind();
|
||||||
|
totalKeystores.set(0);
|
||||||
totalKeystores.bind(multisigControl.highValueProperty());
|
totalKeystores.bind(multisigControl.highValueProperty());
|
||||||
} else {
|
} else {
|
||||||
totalKeystores.unbind();
|
totalKeystores.unbind();
|
||||||
|
totalKeystores.set(0);
|
||||||
totalKeystores.set(1);
|
totalKeystores.set(1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,11 +16,14 @@
|
||||||
</padding>
|
</padding>
|
||||||
<Form GridPane.columnIndex="0" GridPane.rowIndex="0">
|
<Form GridPane.columnIndex="0" GridPane.rowIndex="0">
|
||||||
<Fieldset inputGrow="SOMETIMES" text="">
|
<Fieldset inputGrow="SOMETIMES" text="">
|
||||||
<Field text="Label:">
|
<Field text="Type:">
|
||||||
<TextField fx:id="label" maxWidth="160"/>
|
<Label fx:id="type"/>
|
||||||
<Pane HBox.hgrow="ALWAYS" />
|
<Pane HBox.hgrow="ALWAYS" />
|
||||||
<Button text="Import..." onAction="#importKeystore"/>
|
<Button text="Import..." onAction="#importKeystore"/>
|
||||||
</Field>
|
</Field>
|
||||||
|
<Field text="Label:">
|
||||||
|
<TextField fx:id="label" maxWidth="160"/>
|
||||||
|
</Field>
|
||||||
<Field text="Master fingerprint:">
|
<Field text="Master fingerprint:">
|
||||||
<TextField fx:id="fingerprint" maxWidth="80"/>
|
<TextField fx:id="fingerprint" maxWidth="80"/>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
Loading…
Reference in a new issue