mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-11-04 13:26:44 +00:00
support usb message signing
This commit is contained in:
parent
885efd7985
commit
6e10784e49
9 changed files with 236 additions and 12 deletions
2
drongo
2
drongo
|
@ -1 +1 @@
|
||||||
Subproject commit ee49ddd94bdfec1e87d334f17833a63382958790
|
Subproject commit 10ebfe463d504f39be2aacec41d48c2cf5ba4c56
|
|
@ -854,7 +854,8 @@ public class AppController implements Initializable {
|
||||||
if(tab != null && tab.getUserData() instanceof WalletTabData) {
|
if(tab != null && tab.getUserData() instanceof WalletTabData) {
|
||||||
WalletTabData walletTabData = (WalletTabData)tab.getUserData();
|
WalletTabData walletTabData = (WalletTabData)tab.getUserData();
|
||||||
Wallet wallet = walletTabData.getWallet();
|
Wallet wallet = walletTabData.getWallet();
|
||||||
if(wallet.getKeystores().size() == 1 && wallet.getKeystores().get(0).hasSeed()) {
|
if(wallet.getKeystores().size() == 1 &&
|
||||||
|
(wallet.getKeystores().get(0).hasSeed() || wallet.getKeystores().get(0).getSource() == KeystoreSource.HW_USB)) {
|
||||||
//Can sign and verify
|
//Can sign and verify
|
||||||
messageSignDialog = new MessageSignDialog(wallet);
|
messageSignDialog = new MessageSignDialog(wallet);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
import com.sparrowwallet.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.event.AddressDisplayedEvent;
|
import com.sparrowwallet.sparrow.event.AddressDisplayedEvent;
|
||||||
import com.sparrowwallet.sparrow.event.KeystoreImportEvent;
|
import com.sparrowwallet.sparrow.event.KeystoreImportEvent;
|
||||||
|
import com.sparrowwallet.sparrow.event.MessageSignedEvent;
|
||||||
import com.sparrowwallet.sparrow.event.PSBTSignedEvent;
|
import com.sparrowwallet.sparrow.event.PSBTSignedEvent;
|
||||||
import com.sparrowwallet.sparrow.io.Device;
|
import com.sparrowwallet.sparrow.io.Device;
|
||||||
import com.sparrowwallet.sparrow.io.Hwi;
|
import com.sparrowwallet.sparrow.io.Hwi;
|
||||||
|
@ -38,6 +39,7 @@ public class DevicePane extends TitledDescriptionPane {
|
||||||
private final Wallet wallet;
|
private final Wallet wallet;
|
||||||
private final PSBT psbt;
|
private final PSBT psbt;
|
||||||
private final KeyDerivation keyDerivation;
|
private final KeyDerivation keyDerivation;
|
||||||
|
private final String message;
|
||||||
private final Device device;
|
private final Device device;
|
||||||
|
|
||||||
private CustomPasswordField pinField;
|
private CustomPasswordField pinField;
|
||||||
|
@ -47,6 +49,7 @@ public class DevicePane extends TitledDescriptionPane {
|
||||||
private SplitMenuButton importButton;
|
private SplitMenuButton importButton;
|
||||||
private Button signButton;
|
private Button signButton;
|
||||||
private Button displayAddressButton;
|
private Button displayAddressButton;
|
||||||
|
private Button signMessageButton;
|
||||||
|
|
||||||
private final SimpleStringProperty passphrase = new SimpleStringProperty("");
|
private final SimpleStringProperty passphrase = new SimpleStringProperty("");
|
||||||
|
|
||||||
|
@ -56,6 +59,7 @@ public class DevicePane extends TitledDescriptionPane {
|
||||||
this.wallet = wallet;
|
this.wallet = wallet;
|
||||||
this.psbt = null;
|
this.psbt = null;
|
||||||
this.keyDerivation = null;
|
this.keyDerivation = null;
|
||||||
|
this.message = null;
|
||||||
this.device = device;
|
this.device = device;
|
||||||
|
|
||||||
setDefaultStatus();
|
setDefaultStatus();
|
||||||
|
@ -81,6 +85,7 @@ public class DevicePane extends TitledDescriptionPane {
|
||||||
this.wallet = null;
|
this.wallet = null;
|
||||||
this.psbt = psbt;
|
this.psbt = psbt;
|
||||||
this.keyDerivation = null;
|
this.keyDerivation = null;
|
||||||
|
this.message = null;
|
||||||
this.device = device;
|
this.device = device;
|
||||||
|
|
||||||
setDefaultStatus();
|
setDefaultStatus();
|
||||||
|
@ -106,6 +111,7 @@ public class DevicePane extends TitledDescriptionPane {
|
||||||
this.wallet = wallet;
|
this.wallet = wallet;
|
||||||
this.psbt = null;
|
this.psbt = null;
|
||||||
this.keyDerivation = keyDerivation;
|
this.keyDerivation = keyDerivation;
|
||||||
|
this.message = null;
|
||||||
this.device = device;
|
this.device = device;
|
||||||
|
|
||||||
setDefaultStatus();
|
setDefaultStatus();
|
||||||
|
@ -125,6 +131,32 @@ public class DevicePane extends TitledDescriptionPane {
|
||||||
buttonBox.getChildren().addAll(setPassphraseButton, displayAddressButton);
|
buttonBox.getChildren().addAll(setPassphraseButton, displayAddressButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DevicePane(Wallet wallet, String message, KeyDerivation keyDerivation, Device device) {
|
||||||
|
super(device.getModel().toDisplayString(), "", "", "image/" + device.getType() + ".png");
|
||||||
|
this.deviceOperation = DeviceOperation.SIGN_MESSAGE;
|
||||||
|
this.wallet = wallet;
|
||||||
|
this.psbt = null;
|
||||||
|
this.keyDerivation = keyDerivation;
|
||||||
|
this.message = message;
|
||||||
|
this.device = device;
|
||||||
|
|
||||||
|
setDefaultStatus();
|
||||||
|
showHideLink.setVisible(false);
|
||||||
|
|
||||||
|
createSetPassphraseButton();
|
||||||
|
createSignMessageButton();
|
||||||
|
|
||||||
|
if (device.getNeedsPinSent() != null && device.getNeedsPinSent()) {
|
||||||
|
unlockButton.setVisible(true);
|
||||||
|
} else if(device.getNeedsPassphraseSent() != null && device.getNeedsPassphraseSent()) {
|
||||||
|
setPassphraseButton.setVisible(true);
|
||||||
|
} else {
|
||||||
|
showOperationButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonBox.getChildren().addAll(setPassphraseButton, signMessageButton);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Control createButton() {
|
protected Control createButton() {
|
||||||
createUnlockButton();
|
createUnlockButton();
|
||||||
|
@ -209,6 +241,22 @@ public class DevicePane extends TitledDescriptionPane {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createSignMessageButton() {
|
||||||
|
signMessageButton = new Button("Sign Message");
|
||||||
|
signMessageButton.setDefaultButton(true);
|
||||||
|
signMessageButton.setAlignment(Pos.CENTER_RIGHT);
|
||||||
|
signMessageButton.setOnAction(event -> {
|
||||||
|
signMessageButton.setDisable(true);
|
||||||
|
signMessage();
|
||||||
|
});
|
||||||
|
signMessageButton.managedProperty().bind(signMessageButton.visibleProperty());
|
||||||
|
signMessageButton.setVisible(false);
|
||||||
|
|
||||||
|
if(device.getFingerprint() != null && !device.getFingerprint().equals(keyDerivation.getMasterFingerprint())) {
|
||||||
|
signMessageButton.setDisable(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void unlock(Device device) {
|
private void unlock(Device device) {
|
||||||
if(device.getModel().equals(WalletModel.TREZOR_1)) {
|
if(device.getModel().equals(WalletModel.TREZOR_1)) {
|
||||||
promptPin();
|
promptPin();
|
||||||
|
@ -438,6 +486,20 @@ public class DevicePane extends TitledDescriptionPane {
|
||||||
displayAddressService.start();
|
displayAddressService.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void signMessage() {
|
||||||
|
Hwi.SignMessageService signMessageService = new Hwi.SignMessageService(device, passphrase.get(), message, keyDerivation.getDerivationPath());
|
||||||
|
signMessageService.setOnSucceeded(successEvent -> {
|
||||||
|
String signature = signMessageService.getValue();
|
||||||
|
EventManager.get().post(new MessageSignedEvent(wallet, signature));
|
||||||
|
});
|
||||||
|
signMessageService.setOnFailed(failedEvent -> {
|
||||||
|
setError("Could not sign message", signMessageService.getException().getMessage());
|
||||||
|
signMessageButton.setDisable(false);
|
||||||
|
});
|
||||||
|
setDescription("Signing message...");
|
||||||
|
signMessageService.start();
|
||||||
|
}
|
||||||
|
|
||||||
private void showOperationButton() {
|
private void showOperationButton() {
|
||||||
if(deviceOperation.equals(DeviceOperation.IMPORT)) {
|
if(deviceOperation.equals(DeviceOperation.IMPORT)) {
|
||||||
importButton.setVisible(true);
|
importButton.setVisible(true);
|
||||||
|
@ -450,6 +512,9 @@ public class DevicePane extends TitledDescriptionPane {
|
||||||
} else if(deviceOperation.equals(DeviceOperation.DISPLAY_ADDRESS)) {
|
} else if(deviceOperation.equals(DeviceOperation.DISPLAY_ADDRESS)) {
|
||||||
displayAddressButton.setVisible(true);
|
displayAddressButton.setVisible(true);
|
||||||
showHideLink.setVisible(false);
|
showHideLink.setVisible(false);
|
||||||
|
} else if(deviceOperation.equals(DeviceOperation.SIGN_MESSAGE)) {
|
||||||
|
signMessageButton.setVisible(true);
|
||||||
|
showHideLink.setVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,6 +555,6 @@ public class DevicePane extends TitledDescriptionPane {
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DeviceOperation {
|
public enum DeviceOperation {
|
||||||
IMPORT, SIGN, DISPLAY_ADDRESS;
|
IMPORT, SIGN, DISPLAY_ADDRESS, SIGN_MESSAGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
import com.sparrowwallet.drongo.KeyDerivation;
|
||||||
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
|
import com.sparrowwallet.sparrow.event.MessageSignedEvent;
|
||||||
|
import com.sparrowwallet.sparrow.io.Device;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DeviceSignMessageDialog extends DeviceDialog<String> {
|
||||||
|
private final Wallet wallet;
|
||||||
|
private final String message;
|
||||||
|
private final KeyDerivation keyDerivation;
|
||||||
|
|
||||||
|
public DeviceSignMessageDialog(List<String> operationFingerprints, Wallet wallet, String message, KeyDerivation keyDerivation) {
|
||||||
|
super(operationFingerprints);
|
||||||
|
this.wallet = wallet;
|
||||||
|
this.message = message;
|
||||||
|
this.keyDerivation = keyDerivation;
|
||||||
|
EventManager.get().register(this);
|
||||||
|
setOnCloseRequest(event -> {
|
||||||
|
EventManager.get().unregister(this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DevicePane getDevicePane(Device device) {
|
||||||
|
return new DevicePane(wallet, message, keyDerivation, device);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void messageSigned(MessageSignedEvent event) {
|
||||||
|
if(wallet == event.getWallet()) {
|
||||||
|
setResult(event.getSignature());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package com.sparrowwallet.sparrow.control;
|
||||||
import com.sparrowwallet.drongo.Utils;
|
import com.sparrowwallet.drongo.Utils;
|
||||||
import com.sparrowwallet.drongo.address.Address;
|
import com.sparrowwallet.drongo.address.Address;
|
||||||
import com.sparrowwallet.drongo.wallet.BlockTransaction;
|
import com.sparrowwallet.drongo.wallet.BlockTransaction;
|
||||||
|
import com.sparrowwallet.drongo.wallet.KeystoreSource;
|
||||||
import com.sparrowwallet.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.event.*;
|
import com.sparrowwallet.sparrow.event.*;
|
||||||
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
|
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5;
|
||||||
|
@ -88,7 +89,8 @@ class EntryCell extends TreeTableCell<Entry, Entry> {
|
||||||
});
|
});
|
||||||
actionBox.getChildren().add(receiveButton);
|
actionBox.getChildren().add(receiveButton);
|
||||||
|
|
||||||
if(nodeEntry.getWallet().getKeystores().size() == 1 && nodeEntry.getWallet().getKeystores().get(0).hasSeed()) {
|
if(nodeEntry.getWallet().getKeystores().size() == 1 &&
|
||||||
|
(nodeEntry.getWallet().getKeystores().get(0).hasSeed() || nodeEntry.getWallet().getKeystores().get(0).getSource() == KeystoreSource.HW_USB)) {
|
||||||
Button signMessageButton = new Button("");
|
Button signMessageButton = new Button("");
|
||||||
Glyph signMessageGlyph = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.PEN_FANCY);
|
Glyph signMessageGlyph = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.PEN_FANCY);
|
||||||
signMessageGlyph.setFontSize(12);
|
signMessageGlyph.setFontSize(12);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.sparrowwallet.sparrow.control;
|
package com.sparrowwallet.sparrow.control;
|
||||||
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
import com.sparrowwallet.drongo.KeyDerivation;
|
||||||
import com.sparrowwallet.drongo.SecureString;
|
import com.sparrowwallet.drongo.SecureString;
|
||||||
import com.sparrowwallet.drongo.address.Address;
|
import com.sparrowwallet.drongo.address.Address;
|
||||||
import com.sparrowwallet.drongo.address.InvalidAddressException;
|
import com.sparrowwallet.drongo.address.InvalidAddressException;
|
||||||
|
@ -8,6 +9,7 @@ import com.sparrowwallet.drongo.crypto.ECKey;
|
||||||
import com.sparrowwallet.drongo.policy.PolicyType;
|
import com.sparrowwallet.drongo.policy.PolicyType;
|
||||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||||
import com.sparrowwallet.drongo.wallet.Keystore;
|
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||||
|
import com.sparrowwallet.drongo.wallet.KeystoreSource;
|
||||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
import com.sparrowwallet.drongo.wallet.WalletNode;
|
import com.sparrowwallet.drongo.wallet.WalletNode;
|
||||||
import com.sparrowwallet.sparrow.AppController;
|
import com.sparrowwallet.sparrow.AppController;
|
||||||
|
@ -32,7 +34,7 @@ import tornadofx.control.Fieldset;
|
||||||
import tornadofx.control.Form;
|
import tornadofx.control.Form;
|
||||||
|
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
import java.util.Arrays;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static com.sparrowwallet.sparrow.AppController.setStageIcon;
|
import static com.sparrowwallet.sparrow.AppController.setStageIcon;
|
||||||
|
@ -73,8 +75,8 @@ public class MessageSignDialog extends Dialog<ButtonBar.ButtonData> {
|
||||||
if(wallet.getKeystores().size() != 1) {
|
if(wallet.getKeystores().size() != 1) {
|
||||||
throw new IllegalArgumentException("Cannot sign messages using a wallet with multiple keystores - a single key is required");
|
throw new IllegalArgumentException("Cannot sign messages using a wallet with multiple keystores - a single key is required");
|
||||||
}
|
}
|
||||||
if(!wallet.getKeystores().get(0).hasSeed()) {
|
if(!wallet.getKeystores().get(0).hasSeed() && wallet.getKeystores().get(0).getSource() != KeystoreSource.HW_USB) {
|
||||||
throw new IllegalArgumentException("Cannot sign messages using a wallet without a seed");
|
throw new IllegalArgumentException("Cannot sign messages using a wallet without a seed or USB keystore");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,10 +213,14 @@ public class MessageSignDialog extends Dialog<ButtonBar.ButtonData> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(wallet.isEncrypted()) {
|
if(wallet.containsSeeds()) {
|
||||||
EventManager.get().post(new RequestOpenWalletsEvent());
|
if(wallet.isEncrypted()) {
|
||||||
} else {
|
EventManager.get().post(new RequestOpenWalletsEvent());
|
||||||
signUnencryptedKeystore(wallet);
|
} else {
|
||||||
|
signUnencryptedKeystore(wallet);
|
||||||
|
}
|
||||||
|
} else if(wallet.containsSource(KeystoreSource.HW_USB)) {
|
||||||
|
signUsbKeystore(wallet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,6 +238,17 @@ public class MessageSignDialog extends Dialog<ButtonBar.ButtonData> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void signUsbKeystore(Wallet usbWallet) {
|
||||||
|
List<String> fingerprints = List.of(usbWallet.getKeystores().get(0).getKeyDerivation().getMasterFingerprint());
|
||||||
|
KeyDerivation fullDerivation = usbWallet.getKeystores().get(0).getKeyDerivation().extend(walletNode.getDerivation());
|
||||||
|
DeviceSignMessageDialog deviceSignMessageDialog = new DeviceSignMessageDialog(fingerprints, usbWallet, message.getText().trim(), fullDerivation);
|
||||||
|
Optional<String> optSignature = deviceSignMessageDialog.showAndWait();
|
||||||
|
if(optSignature.isPresent()) {
|
||||||
|
signature.clear();
|
||||||
|
signature.appendText(optSignature.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void verifyMessage() {
|
private void verifyMessage() {
|
||||||
try {
|
try {
|
||||||
//Find ECKey from message and signature
|
//Find ECKey from message and signature
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.sparrowwallet.sparrow.event;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This event is used by the DeviceSignMessageDialog to indicate that a USB device has signed a message
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class MessageSignedEvent {
|
||||||
|
private final Wallet wallet;
|
||||||
|
private final String signature;
|
||||||
|
|
||||||
|
public MessageSignedEvent(Wallet wallet, String signature) {
|
||||||
|
this.wallet = wallet;
|
||||||
|
this.signature = signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Wallet getWallet() {
|
||||||
|
return wallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSignature() {
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
}
|
|
@ -116,13 +116,44 @@ public class Hwi {
|
||||||
if(result.get("address") != null) {
|
if(result.get("address") != null) {
|
||||||
return result.get("address").getAsString();
|
return result.get("address").getAsString();
|
||||||
} else {
|
} else {
|
||||||
throw new DisplayAddressException("Could not retrieve address");
|
JsonElement error = result.get("error");
|
||||||
|
if(error != null) {
|
||||||
|
throw new DisplayAddressException(error.getAsString());
|
||||||
|
} else {
|
||||||
|
throw new DisplayAddressException("Could not retrieve address");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
throw new DisplayAddressException(e);
|
throw new DisplayAddressException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String signMessage(Device device, String passphrase, String message, String derivationPath) throws SignMessageException {
|
||||||
|
try {
|
||||||
|
isPromptActive = false;
|
||||||
|
String output;
|
||||||
|
if(passphrase != null && !passphrase.isEmpty() && device.getModel().equals(WalletModel.TREZOR_1)) {
|
||||||
|
output = execute(getDeviceCommand(device, passphrase, Command.SIGN_MESSAGE, message, derivationPath));
|
||||||
|
} else {
|
||||||
|
output = execute(getDeviceCommand(device, Command.SIGN_MESSAGE, message, derivationPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject result = JsonParser.parseString(output).getAsJsonObject();
|
||||||
|
if(result.get("signature") != null) {
|
||||||
|
return result.get("signature").getAsString();
|
||||||
|
} else {
|
||||||
|
JsonElement error = result.get("error");
|
||||||
|
if(error != null) {
|
||||||
|
throw new SignMessageException(error.getAsString());
|
||||||
|
} else {
|
||||||
|
throw new SignMessageException("Could not sign message");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(IOException e) {
|
||||||
|
throw new SignMessageException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public PSBT signPSBT(Device device, String passphrase, PSBT psbt) throws SignTransactionException {
|
public PSBT signPSBT(Device device, String passphrase, PSBT psbt) throws SignTransactionException {
|
||||||
try {
|
try {
|
||||||
String psbtBase64 = psbt.toBase64String();
|
String psbtBase64 = psbt.toBase64String();
|
||||||
|
@ -409,6 +440,30 @@ public class Hwi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class SignMessageService extends Service<String> {
|
||||||
|
private final Device device;
|
||||||
|
private final String passphrase;
|
||||||
|
private final String message;
|
||||||
|
private final String derivationPath;
|
||||||
|
|
||||||
|
public SignMessageService(Device device, String passphrase, String message, String derivationPath) {
|
||||||
|
this.device = device;
|
||||||
|
this.passphrase = passphrase;
|
||||||
|
this.message = message;
|
||||||
|
this.derivationPath = derivationPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Task<String> createTask() {
|
||||||
|
return new Task<>() {
|
||||||
|
protected String call() throws SignMessageException {
|
||||||
|
Hwi hwi = new Hwi();
|
||||||
|
return hwi.signMessage(device, passphrase, message, derivationPath);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class GetXpubService extends Service<String> {
|
public static class GetXpubService extends Service<String> {
|
||||||
private final Device device;
|
private final Device device;
|
||||||
private final String passphrase;
|
private final String passphrase;
|
||||||
|
@ -479,6 +534,7 @@ public class Hwi {
|
||||||
PROMPT_PIN("promptpin", true),
|
PROMPT_PIN("promptpin", true),
|
||||||
SEND_PIN("sendpin", false),
|
SEND_PIN("sendpin", false),
|
||||||
DISPLAY_ADDRESS("displayaddress", true),
|
DISPLAY_ADDRESS("displayaddress", true),
|
||||||
|
SIGN_MESSAGE("signmessage", true),
|
||||||
GET_XPUB("getxpub", true),
|
GET_XPUB("getxpub", true),
|
||||||
SIGN_TX("signtx", true);
|
SIGN_TX("signtx", true);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.sparrowwallet.sparrow.io;
|
||||||
|
|
||||||
|
public class SignMessageException extends Exception {
|
||||||
|
public SignMessageException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SignMessageException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SignMessageException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SignMessageException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue