mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-11-04 21:36:45 +00:00
psbt combining, transaction viewer updating
This commit is contained in:
parent
b0f4d3b4c9
commit
ef5124a9b9
23 changed files with 333 additions and 144 deletions
2
drongo
2
drongo
|
@ -1 +1 @@
|
||||||
Subproject commit 70d0b7afcd6f0575bf424a45f54dd6e039057dba
|
Subproject commit 0466755883c19a9e679f5e937b2f7db55a73e05b
|
|
@ -703,7 +703,15 @@ public class AppController implements Initializable {
|
||||||
TabData tabData = (TabData)tab.getUserData();
|
TabData tabData = (TabData)tab.getUserData();
|
||||||
if(tabData instanceof TransactionTabData) {
|
if(tabData instanceof TransactionTabData) {
|
||||||
TransactionTabData transactionTabData = (TransactionTabData)tabData;
|
TransactionTabData transactionTabData = (TransactionTabData)tabData;
|
||||||
if(transactionTabData.getTransaction().getTxId().equals(transaction.getTxId())) {
|
|
||||||
|
//If an exact match bytewise of an existing tab, return that tab
|
||||||
|
if(Arrays.equals(transactionTabData.getTransaction().bitcoinSerialize(), transaction.bitcoinSerialize())) {
|
||||||
|
//As per BIP174, combine PSBTs with matching transactions
|
||||||
|
if(transactionTabData.getPsbt() != null && psbt != null) {
|
||||||
|
transactionTabData.getPsbt().combine(psbt);
|
||||||
|
EventManager.get().post(new PSBTCombinedEvent(transactionTabData.getPsbt()));
|
||||||
|
}
|
||||||
|
|
||||||
return tab;
|
return tab;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -717,7 +725,7 @@ public class AppController implements Initializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
Tab tab = new Tab(tabName);
|
Tab tab = new Tab(tabName);
|
||||||
TabData tabData = new TransactionTabData(TabData.TabType.TRANSACTION, transaction);
|
TabData tabData = new TransactionTabData(TabData.TabType.TRANSACTION, transaction, psbt);
|
||||||
tab.setUserData(tabData);
|
tab.setUserData(tabData);
|
||||||
tab.setContextMenu(getTabContextMenu(tab));
|
tab.setContextMenu(getTabContextMenu(tab));
|
||||||
tab.setClosable(true);
|
tab.setClosable(true);
|
||||||
|
@ -733,6 +741,8 @@ public class AppController implements Initializable {
|
||||||
controller.setTransaction(transaction);
|
controller.setTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
controller.setName(name);
|
||||||
|
|
||||||
if(initialView != null) {
|
if(initialView != null) {
|
||||||
controller.setInitialView(initialView, initialIndex);
|
controller.setInitialView(initialView, initialIndex);
|
||||||
}
|
}
|
||||||
|
@ -919,4 +929,9 @@ public class AppController implements Initializable {
|
||||||
public void requestWalletOpen(RequestWalletOpenEvent event) {
|
public void requestWalletOpen(RequestWalletOpenEvent event) {
|
||||||
openWallet(null);
|
openWallet(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void requestTransactionOpen(RequestTransactionOpenEvent event) {
|
||||||
|
openTransactionFromFile(null);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,108 +1,37 @@
|
||||||
package com.sparrowwallet.sparrow;
|
package com.sparrowwallet.sparrow;
|
||||||
|
|
||||||
import com.sparrowwallet.drongo.protocol.Script;
|
|
||||||
import com.sparrowwallet.drongo.protocol.ScriptChunk;
|
import com.sparrowwallet.drongo.protocol.ScriptChunk;
|
||||||
import com.sparrowwallet.sparrow.transaction.ScriptContextMenu;
|
import com.sparrowwallet.sparrow.control.ScriptArea;
|
||||||
import javafx.geometry.Point2D;
|
import javafx.geometry.Point2D;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.stage.Popup;
|
import javafx.stage.Popup;
|
||||||
import org.fxmisc.richtext.CodeArea;
|
|
||||||
import org.fxmisc.richtext.event.MouseOverTextEvent;
|
import org.fxmisc.richtext.event.MouseOverTextEvent;
|
||||||
import org.fxmisc.richtext.model.TwoDimensional;
|
import org.fxmisc.richtext.model.TwoDimensional;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
|
||||||
import static com.sparrowwallet.drongo.protocol.ScriptType.*;
|
|
||||||
import static com.sparrowwallet.drongo.protocol.ScriptType.P2WSH;
|
|
||||||
import static org.fxmisc.richtext.model.TwoDimensional.Bias.Backward;
|
import static org.fxmisc.richtext.model.TwoDimensional.Bias.Backward;
|
||||||
|
|
||||||
public abstract class BaseController {
|
public abstract class BaseController {
|
||||||
protected void appendScript(CodeArea codeArea, Script script) {
|
protected void initializeScriptField(ScriptArea scriptArea) {
|
||||||
appendScript(codeArea, script, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void appendScript(CodeArea codeArea, Script script, Script redeemScript, Script witnessScript) {
|
|
||||||
if(P2PKH.isScriptType(script)) {
|
|
||||||
codeArea.append(script.getChunks().get(0).toString(), "script-opcode");
|
|
||||||
codeArea.append(" ", "");
|
|
||||||
codeArea.append(script.getChunks().get(1).toString(), "script-opcode");
|
|
||||||
codeArea.append(" ", "");
|
|
||||||
codeArea.append("<pkh>", "script-hash");
|
|
||||||
codeArea.append(" ", "");
|
|
||||||
codeArea.append(script.getChunks().get(3).toString(), "script-opcode");
|
|
||||||
codeArea.append(" ", "");
|
|
||||||
codeArea.append(script.getChunks().get(4).toString(), "script-opcode");
|
|
||||||
} else if(P2SH.isScriptType(script)) {
|
|
||||||
codeArea.append(script.getChunks().get(0).toString(), "script-opcode");
|
|
||||||
codeArea.append(" ", "");
|
|
||||||
codeArea.append("<sh>", "script-hash");
|
|
||||||
codeArea.append(" ", "");
|
|
||||||
codeArea.append(script.getChunks().get(2).toString(), "script-opcode");
|
|
||||||
} else if(P2WPKH.isScriptType(script)) {
|
|
||||||
codeArea.append(script.getChunks().get(0).toString(), "script-opcode");
|
|
||||||
codeArea.append(" ", "");
|
|
||||||
codeArea.append("<wpkh>", "script-hash");
|
|
||||||
} else if(P2WSH.isScriptType(script)) {
|
|
||||||
codeArea.append(script.getChunks().get(0).toString(), "script-opcode");
|
|
||||||
codeArea.append(" ", "");
|
|
||||||
codeArea.append("<wsh>", "script-hash");
|
|
||||||
} else {
|
|
||||||
int signatureCount = 1;
|
|
||||||
int pubKeyCount = 1;
|
|
||||||
for (int i = 0; i < script.getChunks().size(); i++) {
|
|
||||||
ScriptChunk chunk = script.getChunks().get(i);
|
|
||||||
if(chunk.isOpCode()) {
|
|
||||||
codeArea.append(chunk.toString(), "script-opcode");
|
|
||||||
} else if(chunk.isSignature()) {
|
|
||||||
codeArea.append("<signature" + signatureCount++ + ">", "script-signature");
|
|
||||||
} else if(chunk.isPubKey()) {
|
|
||||||
codeArea.append("<pubkey" + pubKeyCount++ + ">", "script-pubkey");
|
|
||||||
} else if(chunk.isScript()) {
|
|
||||||
Script nestedScript = chunk.getScript();
|
|
||||||
if (nestedScript.equals(redeemScript)) {
|
|
||||||
codeArea.append("<RedeemScript>", "script-redeem");
|
|
||||||
} else if (nestedScript.equals(witnessScript)) {
|
|
||||||
codeArea.append("<WitnessScript>", "script-redeem");
|
|
||||||
} else {
|
|
||||||
codeArea.append("(", "script-nest");
|
|
||||||
appendScript(codeArea, nestedScript);
|
|
||||||
codeArea.append(")", "script-nest");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
codeArea.append(chunk.toString(), "script-other");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(i < script.getChunks().size() - 1) {
|
|
||||||
codeArea.append(" ", "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addScriptPopup(codeArea, script);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addScriptPopup(CodeArea area, Script script) {
|
|
||||||
ScriptContextMenu contextMenu = new ScriptContextMenu(area, script);
|
|
||||||
area.setContextMenu(contextMenu);
|
|
||||||
|
|
||||||
Popup popup = new Popup();
|
Popup popup = new Popup();
|
||||||
Label popupMsg = new Label();
|
Label popupMsg = new Label();
|
||||||
popupMsg.getStyleClass().add("tooltip");
|
popupMsg.getStyleClass().add("tooltip");
|
||||||
popup.getContent().add(popupMsg);
|
popup.getContent().add(popupMsg);
|
||||||
|
|
||||||
area.setMouseOverTextDelay(Duration.ofMillis(150));
|
scriptArea.setMouseOverTextDelay(Duration.ofMillis(150));
|
||||||
area.addEventHandler(MouseOverTextEvent.MOUSE_OVER_TEXT_BEGIN, e -> {
|
scriptArea.addEventHandler(MouseOverTextEvent.MOUSE_OVER_TEXT_BEGIN, e -> {
|
||||||
TwoDimensional.Position position = area.getParagraph(0).getStyleSpans().offsetToPosition(e.getCharacterIndex(), Backward);
|
TwoDimensional.Position position = scriptArea.getParagraph(0).getStyleSpans().offsetToPosition(e.getCharacterIndex(), Backward);
|
||||||
if(position.getMajor() % 2 == 0) {
|
if(position.getMajor() % 2 == 0) {
|
||||||
ScriptChunk hoverChunk = script.getChunks().get(position.getMajor()/2);
|
ScriptChunk hoverChunk = scriptArea.getScript().getChunks().get(position.getMajor()/2);
|
||||||
if(!hoverChunk.isOpCode()) {
|
if(!hoverChunk.isOpCode()) {
|
||||||
Point2D pos = e.getScreenPosition();
|
Point2D pos = e.getScreenPosition();
|
||||||
popupMsg.setText(describeScriptChunk(hoverChunk));
|
popupMsg.setText(describeScriptChunk(hoverChunk));
|
||||||
popup.show(area, pos.getX(), pos.getY() + 10);
|
popup.show(scriptArea, pos.getX(), pos.getY() + 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
area.addEventHandler(MouseOverTextEvent.MOUSE_OVER_TEXT_END, e -> {
|
scriptArea.addEventHandler(MouseOverTextEvent.MOUSE_OVER_TEXT_END, e -> {
|
||||||
popup.hide();
|
popup.hide();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,27 @@
|
||||||
package com.sparrowwallet.sparrow;
|
package com.sparrowwallet.sparrow;
|
||||||
|
|
||||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||||
|
import com.sparrowwallet.drongo.psbt.PSBT;
|
||||||
|
|
||||||
public class TransactionTabData extends TabData {
|
public class TransactionTabData extends TabData {
|
||||||
private Transaction transaction;
|
private final Transaction transaction;
|
||||||
|
private final PSBT psbt;
|
||||||
|
|
||||||
public TransactionTabData(TabType type, Transaction transaction) {
|
public TransactionTabData(TabType type, Transaction transaction) {
|
||||||
|
this(type, transaction, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransactionTabData(TabType type, Transaction transaction, PSBT psbt) {
|
||||||
super(type);
|
super(type);
|
||||||
this.transaction = transaction;
|
this.transaction = transaction;
|
||||||
|
this.psbt = psbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Transaction getTransaction() {
|
public Transaction getTransaction() {
|
||||||
return transaction;
|
return transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PSBT getPsbt() {
|
||||||
|
return psbt;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
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;
|
||||||
|
import org.fxmisc.richtext.CodeArea;
|
||||||
|
|
||||||
|
import static com.sparrowwallet.drongo.protocol.ScriptType.*;
|
||||||
|
|
||||||
|
public class ScriptArea extends CodeArea {
|
||||||
|
private Script script;
|
||||||
|
|
||||||
|
public void appendScript(Script script) {
|
||||||
|
appendScript(script, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendScript(Script script, Script redeemScript, Script witnessScript) {
|
||||||
|
if(this.script == null) {
|
||||||
|
this.script = script;
|
||||||
|
ScriptContextMenu contextMenu = new ScriptContextMenu(this, script);
|
||||||
|
setContextMenu(contextMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(P2PKH.isScriptType(script)) {
|
||||||
|
append(script.getChunks().get(0).toString(), "script-opcode");
|
||||||
|
append(" ", "");
|
||||||
|
append(script.getChunks().get(1).toString(), "script-opcode");
|
||||||
|
append(" ", "");
|
||||||
|
append("<pkh>", "script-hash");
|
||||||
|
append(" ", "");
|
||||||
|
append(script.getChunks().get(3).toString(), "script-opcode");
|
||||||
|
append(" ", "");
|
||||||
|
append(script.getChunks().get(4).toString(), "script-opcode");
|
||||||
|
} else if(P2SH.isScriptType(script)) {
|
||||||
|
append(script.getChunks().get(0).toString(), "script-opcode");
|
||||||
|
append(" ", "");
|
||||||
|
append("<sh>", "script-hash");
|
||||||
|
append(" ", "");
|
||||||
|
append(script.getChunks().get(2).toString(), "script-opcode");
|
||||||
|
} else if(P2WPKH.isScriptType(script)) {
|
||||||
|
append(script.getChunks().get(0).toString(), "script-opcode");
|
||||||
|
append(" ", "");
|
||||||
|
append("<wpkh>", "script-hash");
|
||||||
|
} else if(P2WSH.isScriptType(script)) {
|
||||||
|
append(script.getChunks().get(0).toString(), "script-opcode");
|
||||||
|
append(" ", "");
|
||||||
|
append("<wsh>", "script-hash");
|
||||||
|
} else {
|
||||||
|
int signatureCount = 1;
|
||||||
|
int pubKeyCount = 1;
|
||||||
|
for (int i = 0; i < script.getChunks().size(); i++) {
|
||||||
|
ScriptChunk chunk = script.getChunks().get(i);
|
||||||
|
if(chunk.isOpCode()) {
|
||||||
|
append(chunk.toString(), "script-opcode");
|
||||||
|
} else if(chunk.isSignature()) {
|
||||||
|
append("<signature" + signatureCount++ + ">", "script-signature");
|
||||||
|
} else if(chunk.isPubKey()) {
|
||||||
|
append("<pubkey" + pubKeyCount++ + ">", "script-pubkey");
|
||||||
|
} else if(chunk.isScript()) {
|
||||||
|
Script nestedScript = chunk.getScript();
|
||||||
|
if (nestedScript.equals(redeemScript)) {
|
||||||
|
append("<RedeemScript>", "script-redeem");
|
||||||
|
} else if(nestedScript.equals(witnessScript)) {
|
||||||
|
append("<WitnessScript>", "script-redeem");
|
||||||
|
} else {
|
||||||
|
append("(", "script-nest");
|
||||||
|
appendScript(nestedScript);
|
||||||
|
append(")", "script-nest");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
append(chunk.toString(), "script-other");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i < script.getChunks().size() - 1) {
|
||||||
|
append(" ", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
super.clear();
|
||||||
|
this.script = null;
|
||||||
|
setDisable(false);
|
||||||
|
setContextMenu(null);
|
||||||
|
Decorator.removeAllDecorations(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPSBTDecoration(String description, String styleClass) {
|
||||||
|
Decorator.addDecoration(this, new GraphicDecoration(new TextDecoration("PSBT", description, styleClass), Pos.TOP_RIGHT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Script getScript() {
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.sparrowwallet.sparrow.event;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.psbt.PSBT;
|
||||||
|
|
||||||
|
public class PSBTCombinedEvent extends PSBTEvent {
|
||||||
|
public PSBTCombinedEvent(PSBT psbt) {
|
||||||
|
super(psbt);
|
||||||
|
}
|
||||||
|
}
|
15
src/main/java/com/sparrowwallet/sparrow/event/PSBTEvent.java
Normal file
15
src/main/java/com/sparrowwallet/sparrow/event/PSBTEvent.java
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
package com.sparrowwallet.sparrow.event;
|
||||||
|
|
||||||
|
import com.sparrowwallet.drongo.psbt.PSBT;
|
||||||
|
|
||||||
|
public class PSBTEvent {
|
||||||
|
private final PSBT psbt;
|
||||||
|
|
||||||
|
public PSBTEvent(PSBT psbt) {
|
||||||
|
this.psbt = psbt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PSBT getPsbt() {
|
||||||
|
return psbt;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.sparrowwallet.sparrow.event;
|
||||||
|
|
||||||
|
public class RequestTransactionOpenEvent {
|
||||||
|
//Empty event class used to request the transaction open dialog
|
||||||
|
}
|
|
@ -15,6 +15,8 @@ public class FontAwesome5 extends GlyphFont {
|
||||||
* The individual glyphs offered by the FontAwesome5 font.
|
* The individual glyphs offered by the FontAwesome5 font.
|
||||||
*/
|
*/
|
||||||
public static enum Glyph implements INamedCharacter {
|
public static enum Glyph implements INamedCharacter {
|
||||||
|
ARROW_UP('\uf062'),
|
||||||
|
CAMERA('\uf030'),
|
||||||
CHECK_CIRCLE('\uf058'),
|
CHECK_CIRCLE('\uf058'),
|
||||||
CIRCLE('\uf111'),
|
CIRCLE('\uf111'),
|
||||||
COINS('\uf51e'),
|
COINS('\uf51e'),
|
||||||
|
|
|
@ -21,6 +21,8 @@ import javafx.fxml.Initializable;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.input.Clipboard;
|
import javafx.scene.input.Clipboard;
|
||||||
import javafx.scene.input.ClipboardContent;
|
import javafx.scene.input.ClipboardContent;
|
||||||
|
import javafx.stage.FileChooser;
|
||||||
|
import javafx.stage.Stage;
|
||||||
import org.controlsfx.glyphfont.Glyph;
|
import org.controlsfx.glyphfont.Glyph;
|
||||||
import tornadofx.control.DateTimePicker;
|
import tornadofx.control.DateTimePicker;
|
||||||
import tornadofx.control.Field;
|
import tornadofx.control.Field;
|
||||||
|
@ -29,7 +31,10 @@ import com.google.common.eventbus.Subscribe;
|
||||||
import tornadofx.control.Form;
|
import tornadofx.control.Form;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.time.*;
|
import java.time.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -434,11 +439,47 @@ public class HeadersController extends TransactionFormController implements Init
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showPSBT(ActionEvent event) {
|
public void showPSBT(ActionEvent event) {
|
||||||
|
ToggleButton toggleButton = (ToggleButton)event.getSource();
|
||||||
|
toggleButton.setSelected(false);
|
||||||
|
|
||||||
headersForm.getSignedKeystores().add(headersForm.getSigningWallet().getKeystores().get(0));
|
headersForm.getSignedKeystores().add(headersForm.getSigningWallet().getKeystores().get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void savePSBT(ActionEvent event) {
|
public void scanPSBT(ActionEvent event) {
|
||||||
|
ToggleButton toggleButton = (ToggleButton)event.getSource();
|
||||||
|
toggleButton.setSelected(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void savePSBT(ActionEvent event) {
|
||||||
|
ToggleButton toggleButton = (ToggleButton)event.getSource();
|
||||||
|
toggleButton.setSelected(false);
|
||||||
|
|
||||||
|
Stage window = new Stage();
|
||||||
|
|
||||||
|
FileChooser fileChooser = new FileChooser();
|
||||||
|
fileChooser.setTitle("Save PSBT");
|
||||||
|
|
||||||
|
if(headersForm.getName() != null && !headersForm.getName().isEmpty()) {
|
||||||
|
fileChooser.setInitialFileName(headersForm.getName() + ".psbt");
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = fileChooser.showSaveDialog(window);
|
||||||
|
if(file != null) {
|
||||||
|
try {
|
||||||
|
try(PrintWriter writer = new PrintWriter(file, StandardCharsets.UTF_8)) {
|
||||||
|
writer.print(headersForm.getPsbt().toBase64String());
|
||||||
|
}
|
||||||
|
} catch(IOException e) {
|
||||||
|
AppController.showErrorDialog("Error saving PSBT", "Cannot write to " + file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadPSBT(ActionEvent event) {
|
||||||
|
ToggleButton toggleButton = (ToggleButton)event.getSource();
|
||||||
|
toggleButton.setSelected(false);
|
||||||
|
|
||||||
|
EventManager.get().post(new RequestTransactionOpenEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void signPSBT(ActionEvent event) {
|
public void signPSBT(ActionEvent event) {
|
||||||
|
@ -570,4 +611,11 @@ public class HeadersController extends TransactionFormController implements Init
|
||||||
signaturesForm.setVisible(true);
|
signaturesForm.setVisible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void psbtCombined(PSBTCombinedEvent event) {
|
||||||
|
if(event.getPsbt().equals(headersForm.getPsbt()) && headersForm.getSigningWallet() != null) {
|
||||||
|
updateSignedKeystores(headersForm.getSigningWallet());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -14,17 +14,12 @@ import com.sparrowwallet.sparrow.event.*;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
import javafx.geometry.Pos;
|
|
||||||
import javafx.scene.Node;
|
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.control.Button;
|
|
||||||
import org.controlsfx.control.ToggleSwitch;
|
import org.controlsfx.control.ToggleSwitch;
|
||||||
import org.controlsfx.control.decoration.Decorator;
|
import org.fxmisc.flowless.VirtualizedScrollPane;
|
||||||
import org.controlsfx.control.decoration.GraphicDecoration;
|
|
||||||
import org.fxmisc.richtext.CodeArea;
|
import org.fxmisc.richtext.CodeArea;
|
||||||
import tornadofx.control.Field;
|
import tornadofx.control.Field;
|
||||||
import tornadofx.control.Fieldset;
|
import tornadofx.control.Fieldset;
|
||||||
import org.fxmisc.flowless.VirtualizedScrollPane;
|
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
|
@ -60,25 +55,25 @@ public class InputController extends TransactionFormController implements Initia
|
||||||
private AddressLabel address;
|
private AddressLabel address;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CodeArea scriptSigArea;
|
private ScriptArea scriptSigArea;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private VirtualizedScrollPane<CodeArea> redeemScriptScroll;
|
private VirtualizedScrollPane<CodeArea> redeemScriptScroll;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CodeArea redeemScriptArea;
|
private ScriptArea redeemScriptArea;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private VirtualizedScrollPane<CodeArea> witnessScriptScroll;
|
private VirtualizedScrollPane<CodeArea> witnessScriptScroll;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CodeArea witnessScriptArea;
|
private ScriptArea witnessScriptArea;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private VirtualizedScrollPane<CodeArea> witnessesScroll;
|
private VirtualizedScrollPane<CodeArea> witnessesScroll;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CodeArea witnessesArea;
|
private ScriptArea witnessesArea;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CopyableLabel signatures;
|
private CopyableLabel signatures;
|
||||||
|
@ -130,12 +125,12 @@ public class InputController extends TransactionFormController implements Initia
|
||||||
|
|
||||||
initializeInputFields(txInput, psbtInput);
|
initializeInputFields(txInput, psbtInput);
|
||||||
initializeScriptFields(txInput, psbtInput);
|
initializeScriptFields(txInput, psbtInput);
|
||||||
initializeStatusFields(txInput);
|
initializeStatusFields(txInput, psbtInput);
|
||||||
initializeLocktimeFields(txInput);
|
initializeLocktimeFields(txInput);
|
||||||
|
|
||||||
if(psbtInput != null) {
|
if(psbtInput != null) {
|
||||||
inputForm.getSignedKeystores().addListener((ListChangeListener<Keystore>) c -> {
|
inputForm.getSignedKeystores().addListener((ListChangeListener<Keystore>) c -> {
|
||||||
updateSignatures();
|
updateSignatures(inputForm.getPsbtInput());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,6 +218,20 @@ public class InputController extends TransactionFormController implements Initia
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeScriptFields(TransactionInput txInput, PSBTInput psbtInput) {
|
private void initializeScriptFields(TransactionInput txInput, PSBTInput psbtInput) {
|
||||||
|
initializeScriptField(scriptSigArea);
|
||||||
|
initializeScriptField(redeemScriptArea);
|
||||||
|
initializeScriptField(witnessesArea);
|
||||||
|
initializeScriptField(witnessScriptArea);
|
||||||
|
|
||||||
|
updateScriptFields(txInput, psbtInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateScriptFields(TransactionInput txInput, PSBTInput psbtInput) {
|
||||||
|
scriptSigArea.clear();
|
||||||
|
redeemScriptArea.clear();
|
||||||
|
witnessesArea.clear();
|
||||||
|
witnessScriptArea.clear();
|
||||||
|
|
||||||
//TODO: While we immediately check if the referenced transaction output is P2SH, where this is not present getting the first nested script is not safe
|
//TODO: While we immediately check if the referenced transaction output is P2SH, where this is not present getting the first nested script is not safe
|
||||||
Script redeemScript = txInput.getScriptSig().getFirstNestedScript();
|
Script redeemScript = txInput.getScriptSig().getFirstNestedScript();
|
||||||
if(redeemScript != null && inputForm.getReferencedTransactionOutput() != null) {
|
if(redeemScript != null && inputForm.getReferencedTransactionOutput() != null) {
|
||||||
|
@ -233,31 +242,27 @@ public class InputController extends TransactionFormController implements Initia
|
||||||
}
|
}
|
||||||
|
|
||||||
if(redeemScript == null && psbtInput != null && psbtInput.getRedeemScript() != null) {
|
if(redeemScript == null && psbtInput != null && psbtInput.getRedeemScript() != null) {
|
||||||
addPSBTDecoration(redeemScriptArea, "PSBT Redeem Script", "non-final");
|
redeemScriptArea.addPSBTDecoration("PSBT Redeem Script", "non-final");
|
||||||
redeemScript = psbtInput.getRedeemScript();
|
redeemScript = psbtInput.getRedeemScript();
|
||||||
}
|
}
|
||||||
if(redeemScript == null && psbtInput != null && psbtInput.getFinalScriptSig() != null) {
|
if(redeemScript == null && psbtInput != null && psbtInput.getFinalScriptSig() != null) {
|
||||||
addPSBTDecoration(redeemScriptArea, "PSBT Final ScriptSig", "final");
|
redeemScriptArea.addPSBTDecoration("PSBT Final ScriptSig", "final");
|
||||||
redeemScript = psbtInput.getFinalScriptSig().getFirstNestedScript();
|
redeemScript = psbtInput.getFinalScriptSig().getFirstNestedScript();
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptSigArea.clear();
|
|
||||||
if(txInput.getScriptSig().isEmpty() && psbtInput != null && psbtInput.getFinalScriptSig() != null) {
|
if(txInput.getScriptSig().isEmpty() && psbtInput != null && psbtInput.getFinalScriptSig() != null) {
|
||||||
appendScript(scriptSigArea, psbtInput.getFinalScriptSig(), redeemScript, null);
|
scriptSigArea.appendScript(psbtInput.getFinalScriptSig(), redeemScript, null);
|
||||||
addPSBTDecoration(scriptSigArea, "PSBT Final ScriptSig", "final");
|
scriptSigArea.addPSBTDecoration("PSBT Final ScriptSig", "final");
|
||||||
} else {
|
} else {
|
||||||
appendScript(scriptSigArea, txInput.getScriptSig(), redeemScript, null);
|
scriptSigArea.appendScript(txInput.getScriptSig(), redeemScript, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
redeemScriptArea.clear();
|
|
||||||
if(redeemScript != null) {
|
if(redeemScript != null) {
|
||||||
appendScript(redeemScriptArea, redeemScript);
|
redeemScriptArea.appendScript(redeemScript);
|
||||||
} else {
|
} else {
|
||||||
redeemScriptScroll.setDisable(true);
|
redeemScriptScroll.setDisable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
witnessesArea.clear();
|
|
||||||
witnessScriptArea.clear();
|
|
||||||
Script witnesses = null;
|
Script witnesses = null;
|
||||||
Script witnessScript = null;
|
Script witnessScript = null;
|
||||||
|
|
||||||
|
@ -268,36 +273,31 @@ public class InputController extends TransactionFormController implements Initia
|
||||||
if(psbtInput.getFinalScriptWitness() != null) {
|
if(psbtInput.getFinalScriptWitness() != null) {
|
||||||
witnesses = new Script(psbtInput.getFinalScriptWitness().asScriptChunks());
|
witnesses = new Script(psbtInput.getFinalScriptWitness().asScriptChunks());
|
||||||
witnessScript = psbtInput.getFinalScriptWitness().getWitnessScript();
|
witnessScript = psbtInput.getFinalScriptWitness().getWitnessScript();
|
||||||
addPSBTDecoration(witnessesArea, "PSBT Final ScriptWitness", "final");
|
witnessesArea.addPSBTDecoration("PSBT Final ScriptWitness", "final");
|
||||||
addPSBTDecoration(witnessScriptArea, "PSBT Final ScriptWitness", "final");
|
witnessScriptArea.addPSBTDecoration("PSBT Final ScriptWitness", "final");
|
||||||
} else if(psbtInput.getWitnessScript() != null) {
|
} else if(psbtInput.getWitnessScript() != null) {
|
||||||
witnessScript = psbtInput.getWitnessScript();
|
witnessScript = psbtInput.getWitnessScript();
|
||||||
addPSBTDecoration(witnessScriptArea, "PSBT Witness Script", "non-final");
|
witnessScriptArea.addPSBTDecoration("PSBT Witness Script", "non-final");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(witnesses != null) {
|
if(witnesses != null) {
|
||||||
appendScript(witnessesArea, witnesses, null, witnessScript);
|
witnessesArea.appendScript(witnesses, null, witnessScript);
|
||||||
} else {
|
} else {
|
||||||
witnessesScroll.setDisable(true);
|
witnessesScroll.setDisable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(witnessScript != null) {
|
if(witnessScript != null) {
|
||||||
appendScript(witnessScriptArea, witnessScript);
|
witnessScriptArea.appendScript(witnessScript);
|
||||||
} else {
|
} else {
|
||||||
witnessScriptScroll.setDisable(true);
|
witnessScriptScroll.setDisable(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPSBTDecoration(Node target, String description, String styleClass) {
|
private void initializeStatusFields(TransactionInput txInput, PSBTInput psbtInput) {
|
||||||
Decorator.addDecoration(target, new GraphicDecoration(new TextDecoration("PSBT", description, styleClass), Pos.TOP_RIGHT));
|
updateSignatures(psbtInput);
|
||||||
}
|
|
||||||
|
|
||||||
private void initializeStatusFields(TransactionInput txInput) {
|
|
||||||
Transaction transaction = inputForm.getTransaction();
|
Transaction transaction = inputForm.getTransaction();
|
||||||
|
|
||||||
updateSignatures();
|
|
||||||
|
|
||||||
rbf.setSelected(txInput.isReplaceByFeeEnabled());
|
rbf.setSelected(txInput.isReplaceByFeeEnabled());
|
||||||
rbf.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
rbf.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
if(newValue) {
|
if(newValue) {
|
||||||
|
@ -323,11 +323,9 @@ public class InputController extends TransactionFormController implements Initia
|
||||||
rbf.setDisable(!inputForm.isEditable());
|
rbf.setDisable(!inputForm.isEditable());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSignatures() {
|
private void updateSignatures(PSBTInput psbtInput) {
|
||||||
signatures.setText("Unknown");
|
signatures.setText("Unknown");
|
||||||
if(inputForm.getPsbtInput() != null) {
|
if(inputForm.getPsbtInput() != null) {
|
||||||
PSBTInput psbtInput = inputForm.getPsbtInput();
|
|
||||||
|
|
||||||
int reqSigs = -1;
|
int reqSigs = -1;
|
||||||
if(psbtInput.getUtxo() != null && psbtInput.getSigningScript() != null) {
|
if(psbtInput.getUtxo() != null && psbtInput.getSigningScript() != null) {
|
||||||
try {
|
try {
|
||||||
|
@ -519,4 +517,13 @@ public class InputController extends TransactionFormController implements Initia
|
||||||
locktimeRelativeCombo.setDisable(true);
|
locktimeRelativeCombo.setDisable(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void psbtCombined(PSBTCombinedEvent event) {
|
||||||
|
if(event.getPsbt().equals(inputForm.getPsbt())) {
|
||||||
|
updateSpends(inputForm.getPsbtInput().getUtxo());
|
||||||
|
updateScriptFields(inputForm.getTransactionInput(), inputForm.getPsbtInput());
|
||||||
|
updateSignatures(inputForm.getPsbtInput());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import com.sparrowwallet.sparrow.control.CoinLabel;
|
||||||
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
||||||
import com.sparrowwallet.sparrow.event.BitcoinUnitChangedEvent;
|
import com.sparrowwallet.sparrow.event.BitcoinUnitChangedEvent;
|
||||||
import com.sparrowwallet.sparrow.event.BlockTransactionFetchedEvent;
|
import com.sparrowwallet.sparrow.event.BlockTransactionFetchedEvent;
|
||||||
|
import com.sparrowwallet.sparrow.event.PSBTCombinedEvent;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
|
@ -106,7 +107,6 @@ public class InputsController extends TransactionFormController implements Initi
|
||||||
signatures.setText(foundSigs + "/?");
|
signatures.setText(foundSigs + "/?");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
addPieData(inputsPie, outputs);
|
addPieData(inputsPie, outputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,4 +173,11 @@ public class InputsController extends TransactionFormController implements Initi
|
||||||
public void bitcoinUnitChanged(BitcoinUnitChangedEvent event) {
|
public void bitcoinUnitChanged(BitcoinUnitChangedEvent event) {
|
||||||
total.refresh(event.getBitcoinUnit());
|
total.refresh(event.getBitcoinUnit());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void psbtCombined(PSBTCombinedEvent event) {
|
||||||
|
if(event.getPsbt().equals(inputsForm.getPsbt())) {
|
||||||
|
updatePSBTInputs(inputsForm.getPsbt());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.control.AddressLabel;
|
import com.sparrowwallet.sparrow.control.AddressLabel;
|
||||||
import com.sparrowwallet.sparrow.control.CoinLabel;
|
import com.sparrowwallet.sparrow.control.CoinLabel;
|
||||||
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
||||||
|
import com.sparrowwallet.sparrow.control.ScriptArea;
|
||||||
import com.sparrowwallet.sparrow.event.BitcoinUnitChangedEvent;
|
import com.sparrowwallet.sparrow.event.BitcoinUnitChangedEvent;
|
||||||
import com.sparrowwallet.sparrow.event.BlockTransactionOutputsFetchedEvent;
|
import com.sparrowwallet.sparrow.event.BlockTransactionOutputsFetchedEvent;
|
||||||
import com.sparrowwallet.sparrow.event.ViewTransactionEvent;
|
import com.sparrowwallet.sparrow.event.ViewTransactionEvent;
|
||||||
|
@ -54,7 +55,7 @@ public class OutputController extends TransactionFormController implements Initi
|
||||||
private Hyperlink spentBy;
|
private Hyperlink spentBy;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CodeArea scriptPubKeyArea;
|
private ScriptArea scriptPubKeyArea;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(URL location, ResourceBundle resources) {
|
public void initialize(URL location, ResourceBundle resources) {
|
||||||
|
@ -92,8 +93,9 @@ public class OutputController extends TransactionFormController implements Initi
|
||||||
spent.setText("Unknown");
|
spent.setText("Unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initializeScriptField(scriptPubKeyArea);
|
||||||
scriptPubKeyArea.clear();
|
scriptPubKeyArea.clear();
|
||||||
appendScript(scriptPubKeyArea, txOutput.getScript(), null, null);
|
scriptPubKeyArea.appendScript(txOutput.getScript(), null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateSpent(List<BlockTransaction> outputTransactions) {
|
private void updateSpent(List<BlockTransaction> outputTransactions) {
|
||||||
|
|
|
@ -368,6 +368,10 @@ public class TransactionController implements Initializable {
|
||||||
this.txdata = new TransactionData(transaction);
|
this.txdata = new TransactionData(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.txdata.setName(name);
|
||||||
|
}
|
||||||
|
|
||||||
public PSBT getPSBT() {
|
public PSBT getPSBT() {
|
||||||
return txdata.getPsbt();
|
return txdata.getPsbt();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import java.util.Map;
|
||||||
|
|
||||||
public class TransactionData {
|
public class TransactionData {
|
||||||
private final Transaction transaction;
|
private final Transaction transaction;
|
||||||
|
private String name;
|
||||||
private PSBT psbt;
|
private PSBT psbt;
|
||||||
private BlockTransaction blockTransaction;
|
private BlockTransaction blockTransaction;
|
||||||
private Map<Sha256Hash, BlockTransaction> inputTransactions;
|
private Map<Sha256Hash, BlockTransaction> inputTransactions;
|
||||||
|
@ -49,6 +50,14 @@ public class TransactionData {
|
||||||
return transaction;
|
return transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
public PSBT getPsbt() {
|
public PSBT getPsbt() {
|
||||||
return psbt;
|
return psbt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,10 @@ public abstract class TransactionForm {
|
||||||
return txdata.getTransaction();
|
return txdata.getTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return txdata.getName();
|
||||||
|
}
|
||||||
|
|
||||||
public PSBT getPsbt() {
|
public PSBT getPsbt() {
|
||||||
return txdata.getPsbt();
|
return txdata.getPsbt();
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import com.sparrowwallet.sparrow.AppController;
|
||||||
import com.sparrowwallet.sparrow.EventManager;
|
import com.sparrowwallet.sparrow.EventManager;
|
||||||
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
import com.sparrowwallet.sparrow.control.CopyableLabel;
|
||||||
import com.sparrowwallet.sparrow.control.CopyableTextField;
|
import com.sparrowwallet.sparrow.control.CopyableTextField;
|
||||||
|
import com.sparrowwallet.sparrow.control.ScriptArea;
|
||||||
import com.sparrowwallet.sparrow.event.ReceiveToEvent;
|
import com.sparrowwallet.sparrow.event.ReceiveToEvent;
|
||||||
import com.sparrowwallet.sparrow.event.WalletHistoryChangedEvent;
|
import com.sparrowwallet.sparrow.event.WalletHistoryChangedEvent;
|
||||||
import com.sparrowwallet.sparrow.event.WalletNodesChangedEvent;
|
import com.sparrowwallet.sparrow.event.WalletNodesChangedEvent;
|
||||||
|
@ -53,7 +54,7 @@ public class ReceiveController extends WalletFormController implements Initializ
|
||||||
private ImageView qrCode;
|
private ImageView qrCode;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CodeArea scriptPubKeyArea;
|
private ScriptArea scriptPubKeyArea;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private CodeArea outputDescriptor;
|
private CodeArea outputDescriptor;
|
||||||
|
@ -67,7 +68,7 @@ public class ReceiveController extends WalletFormController implements Initializ
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initializeView() {
|
public void initializeView() {
|
||||||
|
initializeScriptField(scriptPubKeyArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNodeEntry(NodeEntry nodeEntry) {
|
public void setNodeEntry(NodeEntry nodeEntry) {
|
||||||
|
@ -88,7 +89,7 @@ public class ReceiveController extends WalletFormController implements Initializ
|
||||||
}
|
}
|
||||||
|
|
||||||
scriptPubKeyArea.clear();
|
scriptPubKeyArea.clear();
|
||||||
appendScript(scriptPubKeyArea, nodeEntry.getOutputScript(), null, null);
|
scriptPubKeyArea.appendScript(nodeEntry.getOutputScript(), null, null);
|
||||||
|
|
||||||
outputDescriptor.clear();
|
outputDescriptor.clear();
|
||||||
outputDescriptor.appendText(nodeEntry.getOutputDescriptor());
|
outputDescriptor.appendText(nodeEntry.getOutputDescriptor());
|
||||||
|
|
|
@ -137,6 +137,7 @@ public class SendController extends WalletFormController implements Initializabl
|
||||||
targetBlocks.setTooltip(tooltip);
|
targetBlocks.setTooltip(tooltip);
|
||||||
|
|
||||||
userFeeSet.set(false);
|
userFeeSet.set(false);
|
||||||
|
revalidate(amount, amountListener);
|
||||||
updateTransaction();
|
updateTransaction();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
-fx-padding: 10 20 10 20;
|
-fx-padding: 10 20 10 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
.signatures-buttons .button {
|
.signatures-buttons .segmented-button, .signatures-buttons .button, .signatures-buttons .toggle-button {
|
||||||
-fx-pref-height: 75px;
|
-fx-pref-height: 75px;
|
||||||
-fx-max-width: Infinity;
|
-fx-max-width: Infinity;
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,16 +171,34 @@
|
||||||
</VBox>
|
</VBox>
|
||||||
<VBox>
|
<VBox>
|
||||||
<HBox styleClass="signatures-buttons" spacing="20">
|
<HBox styleClass="signatures-buttons" spacing="20">
|
||||||
<Button HBox.hgrow="ALWAYS" text="Show QR" contentDisplay="TOP" wrapText="true" textAlignment="CENTER" onAction="#showPSBT">
|
<SegmentedButton HBox.hgrow="ALWAYS">
|
||||||
|
<buttons>
|
||||||
|
<ToggleButton HBox.hgrow="ALWAYS" text="Show QR" contentDisplay="TOP" wrapText="true" textAlignment="CENTER" onAction="#showPSBT">
|
||||||
<graphic>
|
<graphic>
|
||||||
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="QRCODE" />
|
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="QRCODE" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</Button>
|
</ToggleButton>
|
||||||
<Button HBox.hgrow="ALWAYS" text="Save PSBT" contentDisplay="TOP" wrapText="true" textAlignment="CENTER" onAction="#savePSBT">
|
<ToggleButton HBox.hgrow="ALWAYS" text="Scan QR" contentDisplay="TOP" wrapText="true" textAlignment="CENTER" onAction="#scanPSBT">
|
||||||
|
<graphic>
|
||||||
|
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="CAMERA" />
|
||||||
|
</graphic>
|
||||||
|
</ToggleButton>
|
||||||
|
</buttons>
|
||||||
|
</SegmentedButton>
|
||||||
|
<SegmentedButton HBox.hgrow="ALWAYS">
|
||||||
|
<buttons>
|
||||||
|
<ToggleButton HBox.hgrow="ALWAYS" text="Save PSBT" contentDisplay="TOP" wrapText="true" textAlignment="CENTER" onAction="#savePSBT">
|
||||||
<graphic>
|
<graphic>
|
||||||
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="SD_CARD" />
|
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="SD_CARD" />
|
||||||
</graphic>
|
</graphic>
|
||||||
</Button>
|
</ToggleButton>
|
||||||
|
<ToggleButton HBox.hgrow="ALWAYS" text="Load PSBT" contentDisplay="TOP" wrapText="true" textAlignment="CENTER" onAction="#loadPSBT">
|
||||||
|
<graphic>
|
||||||
|
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="ARROW_UP" />
|
||||||
|
</graphic>
|
||||||
|
</ToggleButton>
|
||||||
|
</buttons>
|
||||||
|
</SegmentedButton>
|
||||||
<Button fx:id="signButton" defaultButton="true" HBox.hgrow="ALWAYS" text="Sign" contentDisplay="TOP" wrapText="true" textAlignment="CENTER" onAction="#signPSBT">
|
<Button fx:id="signButton" defaultButton="true" HBox.hgrow="ALWAYS" text="Sign" contentDisplay="TOP" wrapText="true" textAlignment="CENTER" onAction="#signPSBT">
|
||||||
<graphic>
|
<graphic>
|
||||||
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="PEN_FANCY" />
|
<Glyph fontFamily="Font Awesome 5 Free Solid" fontSize="20" icon="PEN_FANCY" />
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
<?import com.sparrowwallet.sparrow.control.CoinLabel?>
|
<?import com.sparrowwallet.sparrow.control.CoinLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.AddressLabel?>
|
<?import com.sparrowwallet.sparrow.control.AddressLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.UnlabeledToggleSwitch?>
|
<?import com.sparrowwallet.sparrow.control.UnlabeledToggleSwitch?>
|
||||||
|
<?import com.sparrowwallet.sparrow.control.ScriptArea?>
|
||||||
|
|
||||||
<GridPane hgap="10.0" vgap="10.0" styleClass="tx-pane" stylesheets="@input.css, @transaction.css, @../script.css, @../general.css" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.transaction.InputController">
|
<GridPane hgap="10.0" vgap="10.0" styleClass="tx-pane" stylesheets="@input.css, @transaction.css, @../script.css, @../general.css" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.transaction.InputController">
|
||||||
<padding>
|
<padding>
|
||||||
|
@ -55,28 +56,28 @@
|
||||||
<Field text="ScriptSig:">
|
<Field text="ScriptSig:">
|
||||||
<VirtualizedScrollPane>
|
<VirtualizedScrollPane>
|
||||||
<content>
|
<content>
|
||||||
<CodeArea fx:id="scriptSigArea" editable="false" wrapText="true" prefHeight="42" maxHeight="42" styleClass="uneditable-codearea" />
|
<ScriptArea fx:id="scriptSigArea" editable="false" wrapText="true" prefHeight="42" maxHeight="42" styleClass="uneditable-codearea" />
|
||||||
</content>
|
</content>
|
||||||
</VirtualizedScrollPane>
|
</VirtualizedScrollPane>
|
||||||
</Field>
|
</Field>
|
||||||
<Field text="RedeemScript:">
|
<Field text="RedeemScript:">
|
||||||
<VirtualizedScrollPane fx:id="redeemScriptScroll">
|
<VirtualizedScrollPane fx:id="redeemScriptScroll">
|
||||||
<content>
|
<content>
|
||||||
<CodeArea fx:id="redeemScriptArea" editable="false" wrapText="true" prefHeight="42" maxHeight="42" styleClass="uneditable-codearea" />
|
<ScriptArea fx:id="redeemScriptArea" editable="false" wrapText="true" prefHeight="42" maxHeight="42" styleClass="uneditable-codearea" />
|
||||||
</content>
|
</content>
|
||||||
</VirtualizedScrollPane>
|
</VirtualizedScrollPane>
|
||||||
</Field>
|
</Field>
|
||||||
<Field text="Witnesses:">
|
<Field text="Witnesses:">
|
||||||
<VirtualizedScrollPane fx:id="witnessesScroll">
|
<VirtualizedScrollPane fx:id="witnessesScroll">
|
||||||
<content>
|
<content>
|
||||||
<CodeArea fx:id="witnessesArea" editable="false" wrapText="true" prefHeight="42" maxHeight="42" styleClass="uneditable-codearea" />
|
<ScriptArea fx:id="witnessesArea" editable="false" wrapText="true" prefHeight="42" maxHeight="42" styleClass="uneditable-codearea" />
|
||||||
</content>
|
</content>
|
||||||
</VirtualizedScrollPane>
|
</VirtualizedScrollPane>
|
||||||
</Field>
|
</Field>
|
||||||
<Field text="WitnessScript:">
|
<Field text="WitnessScript:">
|
||||||
<VirtualizedScrollPane fx:id="witnessScriptScroll">
|
<VirtualizedScrollPane fx:id="witnessScriptScroll">
|
||||||
<content>
|
<content>
|
||||||
<CodeArea fx:id="witnessScriptArea" editable="false" wrapText="true" prefHeight="42" maxHeight="42" styleClass="uneditable-codearea" />
|
<ScriptArea fx:id="witnessScriptArea" editable="false" wrapText="true" prefHeight="42" maxHeight="42" styleClass="uneditable-codearea" />
|
||||||
</content>
|
</content>
|
||||||
</VirtualizedScrollPane>
|
</VirtualizedScrollPane>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CoinLabel?>
|
<?import com.sparrowwallet.sparrow.control.CoinLabel?>
|
||||||
<?import com.sparrowwallet.sparrow.control.AddressLabel?>
|
<?import com.sparrowwallet.sparrow.control.AddressLabel?>
|
||||||
|
<?import com.sparrowwallet.sparrow.control.ScriptArea?>
|
||||||
|
|
||||||
<GridPane hgap="10.0" vgap="10.0" styleClass="tx-pane" stylesheets="@output.css, @transaction.css, @../script.css, @../general.css" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.transaction.OutputController">
|
<GridPane hgap="10.0" vgap="10.0" styleClass="tx-pane" stylesheets="@output.css, @transaction.css, @../script.css, @../general.css" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.transaction.OutputController">
|
||||||
<padding>
|
<padding>
|
||||||
|
@ -50,7 +51,7 @@
|
||||||
<Field text="ScriptPubKey:">
|
<Field text="ScriptPubKey:">
|
||||||
<VirtualizedScrollPane>
|
<VirtualizedScrollPane>
|
||||||
<content>
|
<content>
|
||||||
<CodeArea fx:id="scriptPubKeyArea" editable="false" wrapText="true" prefHeight="42" maxHeight="42" styleClass="uneditable-codearea" />
|
<ScriptArea fx:id="scriptPubKeyArea" editable="false" wrapText="true" prefHeight="42" maxHeight="42" styleClass="uneditable-codearea" />
|
||||||
</content>
|
</content>
|
||||||
</VirtualizedScrollPane>
|
</VirtualizedScrollPane>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
<?import com.sparrowwallet.sparrow.control.CopyableLabel?>
|
||||||
<?import org.controlsfx.glyphfont.Glyph?>
|
<?import org.controlsfx.glyphfont.Glyph?>
|
||||||
<?import com.sparrowwallet.sparrow.control.CopyableTextField?>
|
<?import com.sparrowwallet.sparrow.control.CopyableTextField?>
|
||||||
|
<?import com.sparrowwallet.sparrow.control.ScriptArea?>
|
||||||
|
|
||||||
<BorderPane stylesheets="@receive.css, @wallet.css, @../script.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.ReceiveController">
|
<BorderPane stylesheets="@receive.css, @wallet.css, @../script.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.ReceiveController">
|
||||||
<center>
|
<center>
|
||||||
|
@ -59,7 +60,7 @@
|
||||||
<Field text="ScriptPubKey">
|
<Field text="ScriptPubKey">
|
||||||
<VirtualizedScrollPane>
|
<VirtualizedScrollPane>
|
||||||
<content>
|
<content>
|
||||||
<CodeArea fx:id="scriptPubKeyArea" editable="false" wrapText="true" prefHeight="42" maxHeight="42" styleClass="uneditable-codearea" />
|
<ScriptArea fx:id="scriptPubKeyArea" editable="false" wrapText="true" prefHeight="42" maxHeight="42" styleClass="uneditable-codearea" />
|
||||||
</content>
|
</content>
|
||||||
</VirtualizedScrollPane>
|
</VirtualizedScrollPane>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
Loading…
Reference in a new issue