mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-24 12:46:45 +00:00
add seed tool as an airgapped hardware wallet
This commit is contained in:
parent
73b6b9219b
commit
e6de33034b
12 changed files with 69 additions and 9 deletions
2
drongo
2
drongo
|
@ -1 +1 @@
|
||||||
Subproject commit 645be6a5a5a7b434ea9a3991ae85e0b8b6d4f50b
|
Subproject commit c1f6a1245e4632deb19af64faaa6ffaaca475313
|
|
@ -42,12 +42,14 @@ public abstract class FileImportPane extends TitledDescriptionPane {
|
||||||
protected ButtonBase importButton;
|
protected ButtonBase importButton;
|
||||||
private final SimpleStringProperty password = new SimpleStringProperty("");
|
private final SimpleStringProperty password = new SimpleStringProperty("");
|
||||||
private final boolean scannable;
|
private final boolean scannable;
|
||||||
|
private final boolean fileFormatAvailable;
|
||||||
protected List<Wallet> wallets;
|
protected List<Wallet> wallets;
|
||||||
|
|
||||||
public FileImportPane(FileImport importer, String title, String description, String content, String imageUrl, boolean scannable) {
|
public FileImportPane(FileImport importer, String title, String description, String content, String imageUrl, boolean scannable, boolean fileFormatAvailable) {
|
||||||
super(title, description, content, imageUrl);
|
super(title, description, content, imageUrl);
|
||||||
this.importer = importer;
|
this.importer = importer;
|
||||||
this.scannable = scannable;
|
this.scannable = scannable;
|
||||||
|
this.fileFormatAvailable = fileFormatAvailable;
|
||||||
|
|
||||||
buttonBox.getChildren().clear();
|
buttonBox.getChildren().clear();
|
||||||
buttonBox.getChildren().add(createButton());
|
buttonBox.getChildren().add(createButton());
|
||||||
|
@ -55,7 +57,7 @@ public abstract class FileImportPane extends TitledDescriptionPane {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Control createButton() {
|
protected Control createButton() {
|
||||||
if(scannable) {
|
if(scannable && fileFormatAvailable) {
|
||||||
ToggleButton scanButton = new ToggleButton("Scan...");
|
ToggleButton scanButton = new ToggleButton("Scan...");
|
||||||
Glyph cameraGlyph = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.CAMERA);
|
Glyph cameraGlyph = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.CAMERA);
|
||||||
cameraGlyph.setFontSize(12);
|
cameraGlyph.setFontSize(12);
|
||||||
|
@ -76,6 +78,16 @@ public abstract class FileImportPane extends TitledDescriptionPane {
|
||||||
SegmentedButton segmentedButton = new SegmentedButton();
|
SegmentedButton segmentedButton = new SegmentedButton();
|
||||||
segmentedButton.getButtons().addAll(scanButton, fileButton);
|
segmentedButton.getButtons().addAll(scanButton, fileButton);
|
||||||
return segmentedButton;
|
return segmentedButton;
|
||||||
|
} else if(scannable) {
|
||||||
|
importButton = new Button("Scan...");
|
||||||
|
Glyph cameraGlyph = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.CAMERA);
|
||||||
|
cameraGlyph.setFontSize(12);
|
||||||
|
importButton.setGraphic(cameraGlyph);
|
||||||
|
importButton.setAlignment(Pos.CENTER_RIGHT);
|
||||||
|
importButton.setOnAction(event -> {
|
||||||
|
importQR();
|
||||||
|
});
|
||||||
|
return importButton;
|
||||||
} else {
|
} else {
|
||||||
importButton = new Button("Import File...");
|
importButton = new Button("Import File...");
|
||||||
importButton.setAlignment(Pos.CENTER_RIGHT);
|
importButton.setAlignment(Pos.CENTER_RIGHT);
|
||||||
|
|
|
@ -16,7 +16,7 @@ public class FileKeystoreImportPane extends FileImportPane {
|
||||||
private final KeyDerivation requiredDerivation;
|
private final KeyDerivation requiredDerivation;
|
||||||
|
|
||||||
public FileKeystoreImportPane(Wallet wallet, KeystoreFileImport importer, KeyDerivation requiredDerivation) {
|
public FileKeystoreImportPane(Wallet wallet, KeystoreFileImport importer, KeyDerivation requiredDerivation) {
|
||||||
super(importer, importer.getName(), "Keystore import", importer.getKeystoreImportDescription(), "image/" + importer.getWalletModel().getType() + ".png", importer.isKeystoreImportScannable());
|
super(importer, importer.getName(), "Keystore import", importer.getKeystoreImportDescription(), "image/" + importer.getWalletModel().getType() + ".png", importer.isKeystoreImportScannable(), importer.isFileFormatAvailable());
|
||||||
this.wallet = wallet;
|
this.wallet = wallet;
|
||||||
this.importer = importer;
|
this.importer = importer;
|
||||||
this.requiredDerivation = requiredDerivation;
|
this.requiredDerivation = requiredDerivation;
|
||||||
|
|
|
@ -12,7 +12,7 @@ public class FileWalletImportPane extends FileImportPane {
|
||||||
private final WalletImport importer;
|
private final WalletImport importer;
|
||||||
|
|
||||||
public FileWalletImportPane(WalletImport importer) {
|
public FileWalletImportPane(WalletImport importer) {
|
||||||
super(importer, importer.getName(), "Wallet import", importer.getWalletImportDescription(), "image/" + importer.getWalletModel().getType() + ".png", importer.isWalletImportScannable());
|
super(importer, importer.getName(), "Wallet import", importer.getWalletImportDescription(), "image/" + importer.getWalletModel().getType() + ".png", importer.isWalletImportScannable(), true);
|
||||||
this.importer = importer;
|
this.importer = importer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ public class FileWalletKeystoreImportPane extends FileImportPane {
|
||||||
private byte[] fileBytes;
|
private byte[] fileBytes;
|
||||||
|
|
||||||
public FileWalletKeystoreImportPane(KeystoreFileImport importer) {
|
public FileWalletKeystoreImportPane(KeystoreFileImport importer) {
|
||||||
super(importer, importer.getName(), "Wallet import", importer.getKeystoreImportDescription(), "image/" + importer.getWalletModel().getType() + ".png", importer.isKeystoreImportScannable());
|
super(importer, importer.getName(), "Wallet import", importer.getKeystoreImportDescription(), "image/" + importer.getWalletModel().getType() + ".png", importer.isKeystoreImportScannable(), importer.isFileFormatAvailable());
|
||||||
this.importer = importer;
|
this.importer = importer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ public class WalletImportDialog extends Dialog<Wallet> {
|
||||||
AnchorPane.setRightAnchor(scrollPane, 0.0);
|
AnchorPane.setRightAnchor(scrollPane, 0.0);
|
||||||
|
|
||||||
importAccordion = new Accordion();
|
importAccordion = new Accordion();
|
||||||
List<KeystoreFileImport> keystoreImporters = List.of(new ColdcardSinglesig(), new CoboVaultSinglesig(), new KeystoneSinglesig(), new PassportSinglesig(), new SpecterDIY());
|
List<KeystoreFileImport> keystoreImporters = List.of(new ColdcardSinglesig(), new CoboVaultSinglesig(), new KeystoneSinglesig(), new PassportSinglesig(), new SeedTool(), new SpecterDIY());
|
||||||
for(KeystoreFileImport importer : keystoreImporters) {
|
for(KeystoreFileImport importer : keystoreImporters) {
|
||||||
FileWalletKeystoreImportPane importPane = new FileWalletKeystoreImportPane(importer);
|
FileWalletKeystoreImportPane importPane = new FileWalletKeystoreImportPane(importer);
|
||||||
importAccordion.getPanes().add(importPane);
|
importAccordion.getPanes().add(importPane);
|
||||||
|
|
|
@ -8,4 +8,7 @@ import java.io.InputStream;
|
||||||
public interface KeystoreFileImport extends KeystoreImport, FileImport {
|
public interface KeystoreFileImport extends KeystoreImport, FileImport {
|
||||||
Keystore getKeystore(ScriptType scriptType, InputStream inputStream, String password) throws ImportException;
|
Keystore getKeystore(ScriptType scriptType, InputStream inputStream, String password) throws ImportException;
|
||||||
boolean isKeystoreImportScannable();
|
boolean isKeystoreImportScannable();
|
||||||
|
default boolean isFileFormatAvailable() {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
45
src/main/java/com/sparrowwallet/sparrow/io/SeedTool.java
Normal file
45
src/main/java/com/sparrowwallet/sparrow/io/SeedTool.java
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
package com.sparrowwallet.sparrow.io;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
|
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||||
|
import com.sparrowwallet.drongo.wallet.WalletModel;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class SeedTool implements KeystoreFileImport {
|
||||||
|
@Override
|
||||||
|
public boolean isEncrypted(File file) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Seed Tool";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WalletModel getWalletModel() {
|
||||||
|
return WalletModel.SEED_TOOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Keystore getKeystore(ScriptType scriptType, InputStream inputStream, String password) throws ImportException {
|
||||||
|
throw new ImportException("Only QR imports are supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isKeystoreImportScannable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKeystoreImportDescription() {
|
||||||
|
return "Select your seed and scan the QR code created by Authenticate > Derive Key > Other Key Derivations > Account Descriptor. Click the share icon at the bottom to show the QR.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFileFormatAvailable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,9 +18,9 @@ public class HwAirgappedController extends KeystoreImportDetailController {
|
||||||
public void initializeView() {
|
public void initializeView() {
|
||||||
List<KeystoreFileImport> importers = Collections.emptyList();
|
List<KeystoreFileImport> importers = Collections.emptyList();
|
||||||
if(getMasterController().getWallet().getPolicyType().equals(PolicyType.SINGLE)) {
|
if(getMasterController().getWallet().getPolicyType().equals(PolicyType.SINGLE)) {
|
||||||
importers = List.of(new ColdcardSinglesig(), new CoboVaultSinglesig(), new KeystoneSinglesig(), new PassportSinglesig(), new SeedSigner(), new SpecterDIY());
|
importers = List.of(new ColdcardSinglesig(), new CoboVaultSinglesig(), new KeystoneSinglesig(), new PassportSinglesig(), new SeedSigner(), new SeedTool(), new SpecterDIY());
|
||||||
} else if(getMasterController().getWallet().getPolicyType().equals(PolicyType.MULTI)) {
|
} else if(getMasterController().getWallet().getPolicyType().equals(PolicyType.MULTI)) {
|
||||||
importers = List.of(new ColdcardMultisig(), new CoboVaultMultisig(), new KeystoneMultisig(), new PassportMultisig(), new SeedSigner(), new SpecterDIY());
|
importers = List.of(new ColdcardMultisig(), new CoboVaultMultisig(), new KeystoneMultisig(), new PassportMultisig(), new SeedSigner(), new SeedTool(), new SpecterDIY());
|
||||||
}
|
}
|
||||||
|
|
||||||
for(KeystoreFileImport importer : importers) {
|
for(KeystoreFileImport importer : importers) {
|
||||||
|
|
BIN
src/main/resources/image/seedtool.png
Normal file
BIN
src/main/resources/image/seedtool.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
BIN
src/main/resources/image/seedtool@2x.png
Normal file
BIN
src/main/resources/image/seedtool@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
BIN
src/main/resources/image/seedtool@3x.png
Normal file
BIN
src/main/resources/image/seedtool@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.9 KiB |
Loading…
Reference in a new issue