mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-23 20:36:44 +00:00
improve wallet descriptor and add output descriptor retrieval
This commit is contained in:
parent
e65f1ef3cc
commit
b8c3bf1bea
9 changed files with 166 additions and 15 deletions
2
drongo
2
drongo
|
@ -1 +1 @@
|
|||
Subproject commit 08c159ebadee78af391e83d91b6a453a28acbf3e
|
||||
Subproject commit 488752c142765bacd0373390faccbdb11b47487a
|
|
@ -1,6 +1,9 @@
|
|||
package com.sparrowwallet.sparrow;
|
||||
|
||||
import com.sparrowwallet.drongo.policy.PolicyType;
|
||||
import com.sparrowwallet.drongo.protocol.ScriptChunk;
|
||||
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||
import com.sparrowwallet.sparrow.control.DescriptorArea;
|
||||
import com.sparrowwallet.sparrow.control.ScriptArea;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.scene.control.Label;
|
||||
|
@ -39,4 +42,42 @@ public abstract class BaseController {
|
|||
protected String describeScriptChunk(ScriptChunk chunk) {
|
||||
return chunk.toString();
|
||||
}
|
||||
|
||||
protected void initializeDescriptorField(DescriptorArea descriptorArea) {
|
||||
Popup popup = new Popup();
|
||||
Label popupMsg = new Label();
|
||||
popupMsg.getStyleClass().add("tooltip");
|
||||
popup.getContent().add(popupMsg);
|
||||
|
||||
descriptorArea.setMouseOverTextDelay(Duration.ofMillis(150));
|
||||
descriptorArea.addEventHandler(MouseOverTextEvent.MOUSE_OVER_TEXT_BEGIN, e -> {
|
||||
TwoDimensional.Position position = descriptorArea.getParagraph(0).getStyleSpans().offsetToPosition(e.getCharacterIndex(), Backward);
|
||||
int index = descriptorArea.getWallet().getPolicyType() == PolicyType.SINGLE ? position.getMajor() - 1 : ((position.getMajor() - 1) / 2);
|
||||
if(position.getMajor() > 0 && index >= 0 && index < descriptorArea.getWallet().getKeystores().size()) {
|
||||
Keystore hoverKeystore = descriptorArea.getWallet().getKeystores().get(index);
|
||||
Point2D pos = e.getScreenPosition();
|
||||
popupMsg.setText(describeKeystore(hoverKeystore));
|
||||
popup.show(descriptorArea, pos.getX(), pos.getY() + 10);
|
||||
}
|
||||
});
|
||||
descriptorArea.addEventHandler(MouseOverTextEvent.MOUSE_OVER_TEXT_END, e -> {
|
||||
popup.hide();
|
||||
});
|
||||
}
|
||||
|
||||
protected String describeKeystore(Keystore keystore) {
|
||||
if(keystore.isValid()) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("[");
|
||||
builder.append(keystore.getKeyDerivation().getMasterFingerprint());
|
||||
builder.append("/");
|
||||
builder.append(keystore.getKeyDerivation().getDerivationPath().replaceFirst("^m?/", ""));
|
||||
builder.append("]");
|
||||
builder.append(keystore.getExtendedPublicKey().toString());
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
return "Invalid";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
package com.sparrowwallet.sparrow.control;
|
||||
|
||||
import com.sparrowwallet.drongo.OutputDescriptor;
|
||||
import com.sparrowwallet.drongo.policy.PolicyType;
|
||||
import com.sparrowwallet.drongo.protocol.ScriptType;
|
||||
import com.sparrowwallet.drongo.wallet.Keystore;
|
||||
import com.sparrowwallet.drongo.wallet.Wallet;
|
||||
import javafx.scene.control.ContextMenu;
|
||||
import javafx.scene.control.MenuItem;
|
||||
import javafx.scene.input.Clipboard;
|
||||
import javafx.scene.input.ClipboardContent;
|
||||
import org.fxmisc.richtext.CodeArea;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.sparrowwallet.drongo.policy.PolicyType.MULTI;
|
||||
import static com.sparrowwallet.drongo.policy.PolicyType.SINGLE;
|
||||
import static com.sparrowwallet.drongo.protocol.ScriptType.MULTISIG;
|
||||
|
||||
public class DescriptorArea extends CodeArea {
|
||||
private Wallet wallet;
|
||||
|
||||
public void setWallet(Wallet wallet) {
|
||||
clear();
|
||||
this.wallet = wallet;
|
||||
|
||||
DescriptorContextMenu contextMenu = new DescriptorContextMenu(wallet, this);
|
||||
setContextMenu(contextMenu);
|
||||
|
||||
PolicyType policyType = wallet.getPolicyType();
|
||||
ScriptType scriptType = wallet.getScriptType();
|
||||
List<Keystore> keystores = wallet.getKeystores();
|
||||
int threshold = wallet.getDefaultPolicy().getNumSignaturesRequired();
|
||||
|
||||
if(SINGLE.equals(policyType)) {
|
||||
append(scriptType.getDescriptor(), "descriptor-text");
|
||||
replace(getLength(), getLength(), keystores.get(0).getScriptName(), List.of(keystores.get(0).isValid() ? "descriptor-text" : "descriptor-error", keystores.get(0).getScriptName()));
|
||||
append(scriptType.getCloseDescriptor(), "descriptor-text");
|
||||
}
|
||||
|
||||
if(MULTI.equals(policyType)) {
|
||||
append(scriptType.getDescriptor(), "descriptor-text");
|
||||
append(MULTISIG.getDescriptor(), "descriptor-text");
|
||||
append(Integer.toString(threshold), "descriptor-text");
|
||||
|
||||
for(Keystore keystore : keystores) {
|
||||
append(",", "descriptor-text");
|
||||
replace(getLength(), getLength(), keystore.getScriptName(), List.of(keystore.isValid() ? "descriptor-text" : "descriptor-error", keystore.getScriptName()));
|
||||
}
|
||||
|
||||
append(MULTISIG.getCloseDescriptor(), "descriptor-text");
|
||||
append(scriptType.getCloseDescriptor(), "descriptor-text");
|
||||
}
|
||||
}
|
||||
|
||||
public Wallet getWallet() {
|
||||
return wallet;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
super.clear();
|
||||
this.wallet = null;
|
||||
setDisable(false);
|
||||
setContextMenu(null);
|
||||
}
|
||||
|
||||
private static class DescriptorContextMenu extends ContextMenu {
|
||||
public DescriptorContextMenu(Wallet wallet, DescriptorArea descriptorArea) {
|
||||
MenuItem copyvalue = new MenuItem("Copy Value");
|
||||
copyvalue.setOnAction(AE -> {
|
||||
hide();
|
||||
ClipboardContent content = new ClipboardContent();
|
||||
content.putString(descriptorArea.getText());
|
||||
Clipboard.getSystemClipboard().setContent(content);
|
||||
});
|
||||
getItems().add(copyvalue);
|
||||
|
||||
MenuItem copyOutputDescriptor = new MenuItem("Copy Output Descriptor");
|
||||
copyOutputDescriptor.setOnAction(AE -> {
|
||||
hide();
|
||||
ClipboardContent content = new ClipboardContent();
|
||||
content.putString(OutputDescriptor.getOutputDescriptor(wallet).toString(true));
|
||||
Clipboard.getSystemClipboard().setContent(content);
|
||||
});
|
||||
getItems().add(copyOutputDescriptor);
|
||||
this.setStyle("-fx-background-color: -fx-color; -fx-font-family: System; -fx-font-size: 1em;");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@ package com.sparrowwallet.sparrow.control;
|
|||
|
||||
import com.sparrowwallet.drongo.protocol.Script;
|
||||
import com.sparrowwallet.drongo.protocol.ScriptChunk;
|
||||
import com.sparrowwallet.sparrow.transaction.ScriptContextMenu;
|
||||
import javafx.geometry.Pos;
|
||||
import org.controlsfx.control.decoration.Decorator;
|
||||
import org.controlsfx.control.decoration.GraphicDecoration;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.sparrowwallet.sparrow.transaction;
|
||||
package com.sparrowwallet.sparrow.control;
|
||||
|
||||
import com.sparrowwallet.drongo.protocol.Script;
|
||||
import com.sparrowwallet.drongo.protocol.ScriptChunk;
|
||||
|
@ -33,7 +33,7 @@ public class ScriptContextMenu extends ContextMenu {
|
|||
});
|
||||
|
||||
getItems().add(copyvalue);
|
||||
this.setStyle("-fx-background-color: -fx-color; -fx-font-family: sans-serif; -fx-font-size: 1em;");
|
||||
this.setStyle("-fx-background-color: -fx-color; -fx-font-family: System; -fx-font-size: 1em;");
|
||||
|
||||
area.addEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, event -> {
|
||||
hoverChunk = null;
|
|
@ -13,6 +13,7 @@ import com.sparrowwallet.drongo.wallet.WalletModel;
|
|||
import com.sparrowwallet.sparrow.AppController;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
||||
import com.sparrowwallet.sparrow.control.DescriptorArea;
|
||||
import com.sparrowwallet.sparrow.control.WalletPasswordDialog;
|
||||
import com.sparrowwallet.sparrow.event.SettingsChangedEvent;
|
||||
import com.sparrowwallet.sparrow.event.StorageEvent;
|
||||
|
@ -46,7 +47,7 @@ public class SettingsController extends WalletFormController implements Initiali
|
|||
private ComboBox<PolicyType> policyType;
|
||||
|
||||
@FXML
|
||||
private TextField spendingMiniscript;
|
||||
private DescriptorArea descriptor;
|
||||
|
||||
@FXML
|
||||
private ComboBox<ScriptType> scriptType;
|
||||
|
@ -160,6 +161,8 @@ public class SettingsController extends WalletFormController implements Initiali
|
|||
}
|
||||
});
|
||||
|
||||
initializeDescriptorField(descriptor);
|
||||
|
||||
revert.setOnAction(event -> {
|
||||
keystoreTabs.getTabs().removeAll(keystoreTabs.getTabs());
|
||||
totalKeystores.unbind();
|
||||
|
@ -224,6 +227,7 @@ public class SettingsController extends WalletFormController implements Initiali
|
|||
KeystoreController controller = keystoreLoader.getController();
|
||||
controller.setKeystore(getWalletForm(), keystore);
|
||||
tab.textProperty().bind(controller.getLabel().textProperty());
|
||||
tab.setUserData(keystore);
|
||||
|
||||
controller.getValidationSupport().validationResultProperty().addListener((o, oldValue, result) -> {
|
||||
if(result.getErrors().isEmpty()) {
|
||||
|
@ -243,6 +247,19 @@ public class SettingsController extends WalletFormController implements Initiali
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String describeKeystore(Keystore keystore) {
|
||||
if(!keystore.isValid()) {
|
||||
for(Tab tab : keystoreTabs.getTabs()) {
|
||||
if(tab.getUserData() == keystore && tab.getTooltip() != null) {
|
||||
return tab.getTooltip().getText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.describeKeystore(keystore);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void update(SettingsChangedEvent event) {
|
||||
Wallet wallet = event.getWallet();
|
||||
|
@ -253,7 +270,7 @@ public class SettingsController extends WalletFormController implements Initiali
|
|||
wallet.setDefaultPolicy(Policy.getPolicy(wallet.getPolicyType(), wallet.getScriptType(), wallet.getKeystores(), (int)multisigControl.getLowValue()));
|
||||
}
|
||||
|
||||
spendingMiniscript.setText(wallet.getDefaultPolicy().getMiniscript().getScript());
|
||||
descriptor.setWallet(wallet);
|
||||
revert.setDisable(false);
|
||||
apply.setDisable(!wallet.isValid());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
.descriptor-text { -fx-fill: #000000 }
|
||||
.descriptor-error { -fx-fill: #ca1243 }
|
||||
|
|
@ -10,8 +10,4 @@
|
|||
-fx-alignment: center-left;
|
||||
}
|
||||
|
||||
#spendingMiniscript {
|
||||
-fx-font-size: 13px;
|
||||
-fx-font-family: 'Roboto Mono';
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,10 @@
|
|||
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
||||
<?import com.sparrowwallet.drongo.policy.PolicyType?>
|
||||
<?import com.sparrowwallet.drongo.protocol.ScriptType?>
|
||||
<?import com.sparrowwallet.sparrow.control.DescriptorArea?>
|
||||
<?import org.fxmisc.flowless.VirtualizedScrollPane?>
|
||||
|
||||
<BorderPane stylesheets="@settings.css, @wallet.css, @../general.css" styleClass="wallet-pane" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.wallet.SettingsController">
|
||||
<BorderPane stylesheets="@settings.css, @wallet.css, @../script.css, @../descriptor.css, @../general.css" styleClass="wallet-pane" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.wallet.SettingsController">
|
||||
<center>
|
||||
<GridPane hgap="10.0" vgap="10.0">
|
||||
<padding>
|
||||
|
@ -59,7 +61,7 @@
|
|||
<Form GridPane.columnIndex="1" GridPane.rowIndex="0">
|
||||
<Fieldset inputGrow="SOMETIMES" text="" fx:id="multisigFieldset">
|
||||
<Field text="Cosigners:">
|
||||
<RangeSlider fx:id="multisigControl" showTickMarks="true" showTickLabels="true" blockIncrement="1" min="2" max="9" lowValue="2" highValue="3" snapToTicks="true" majorTickUnit="1" minorTickCount="0" />
|
||||
<RangeSlider fx:id="multisigControl" showTickMarks="true" showTickLabels="true" blockIncrement="1" min="1" max="9" highValue="3" lowValue="2" snapToTicks="true" majorTickUnit="1" minorTickCount="0" />
|
||||
</Field>
|
||||
<Field text="M of N:">
|
||||
<CopyableLabel fx:id="multisigLowLabel" />
|
||||
|
@ -70,9 +72,13 @@
|
|||
</Form>
|
||||
|
||||
<Form GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="1">
|
||||
<Fieldset inputGrow="SOMETIMES" text="Spending Policy">
|
||||
<Field text="Miniscript:">
|
||||
<TextField fx:id="spendingMiniscript" editable="false" />
|
||||
<Fieldset inputGrow="SOMETIMES" text="Script Policy">
|
||||
<Field text="Descriptor:">
|
||||
<VirtualizedScrollPane hbarPolicy="NEVER" vbarPolicy="NEVER">
|
||||
<content>
|
||||
<DescriptorArea fx:id="descriptor" editable="false" styleClass="uneditable-codearea" prefHeight="27" maxHeight="27" />
|
||||
</content>
|
||||
</VirtualizedScrollPane>
|
||||
</Field>
|
||||
</Fieldset>
|
||||
</Form>
|
||||
|
|
Loading…
Reference in a new issue