mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-12-23 20:36:44 +00:00
input pane sequence number
This commit is contained in:
parent
d58167552a
commit
4d97832d97
17 changed files with 290 additions and 96 deletions
2
drongo
2
drongo
|
@ -1 +1 @@
|
|||
Subproject commit d28186f8c9ca7fd53a6978b84b07e6096d55df1c
|
||||
Subproject commit 130fea0937629b62305892d00bc8099872259095
|
|
@ -106,7 +106,7 @@ public class AppController implements Initializable {
|
|||
addTransactionTab("p2sh-p2wsh", "01000000000101708256c5896fb3f00ef37601f8e30c5b460dbcd1fca1cd7199f9b56fc4ecd5400000000023220020615ae01ed1bc1ffaad54da31d7805d0bb55b52dfd3941114330368c1bbf69b4cffffffff01603edb0300000000160014bbef244bcad13cffb68b5cef3017c7423675552204004730440220010d2854b86b90b7c33661ca25f9d9f15c24b88c5c4992630f77ff004b998fb802204106fc3ec8481fa98e07b7e78809ac91b6ccaf60bf4d3f729c5a75899bb664a501473044022046d66321c6766abcb1366a793f9bfd0e11e0b080354f18188588961ea76c5ad002207262381a0661d66f5c39825202524c45f29d500c6476176cd910b1691176858701695221026ccfb8061f235cc110697c0bfb3afb99d82c886672f6b9b5393b25a434c0cbf32103befa190c0c22e2f53720b1be9476dcf11917da4665c44c9c71c3a2d28a933c352102be46dc245f58085743b1cc37c82f0d63a960efa43b5336534275fc469b49f4ac53ae00000000", null);
|
||||
addTransactionTab("p2wpkh", "01000000000101109d2e41430bfdec7e6dfb02bf78b5827eeb717ef25210ff3203b0db8c76c9260000000000ffffffff01a032eb0500000000160014bbef244bcad13cffb68b5cef3017c742367555220247304402202f7cac3494e521018ae0be4ca18517639ef7c00658d42a9f938b2b344c8454e2022039a54218832fad5d14b331329d9042c51ee6be287e95e49ee5b96fda1f5ce13f0121026ccfb8061f235cc110697c0bfb3afb99d82c886672f6b9b5393b25a434c0cbf300000000", null);
|
||||
addTransactionTab("p2wsh", "0100000000010193a2db37b841b2a46f4e9bb63fe9c1012da3ab7fe30b9f9c974242778b5af8980000000000ffffffff01806fb307000000001976a914bbef244bcad13cffb68b5cef3017c7423675552288ac040047304402203cdcaf02a44e37e409646e8a506724e9e1394b890cb52429ea65bac4cc2403f1022024b934297bcd0c21f22cee0e48751c8b184cc3a0d704cae2684e14858550af7d01483045022100feb4e1530c13e72226dc912dcd257df90d81ae22dbddb5a3c2f6d86f81d47c8e022069889ddb76388fa7948aaa018b2480ac36132009bb9cfade82b651e88b4b137a01695221026ccfb8061f235cc110697c0bfb3afb99d82c886672f6b9b5393b25a434c0cbf32103befa190c0c22e2f53720b1be9476dcf11917da4665c44c9c71c3a2d28a933c352102be46dc245f58085743b1cc37c82f0d63a960efa43b5336534275fc469b49f4ac53ae00000000", null);
|
||||
addTransactionTab("test1", "02000000000102ba4dc5a4a14bfaa941b7d115b379b5e15f960635cf694c178b9116763cbd63b11600000017160014fc164cbcac023f5eacfcead2d17d8768c41949affeffffff074d44d2856beb68ba52e8832da60a1682768c2421c2d9a8109ef4e66babd1fd1e000000171600148c3098be6b430859115f5ee99c84c368afecd048feffffff02305310000000000017a914ffaf369c2212b178c7a2c21c9ccdd5d126e74c4187327f0300000000001976a914a7cda2e06b102a143ab606937a01d152e300cd3e88ac02473044022006da0ca227f765179219e08a33026b94e7cacff77f87b8cd8eb1b46d6dda11d6022064faa7912924fd23406b6ed3328f1bbbc3760dc51109a49c1b38bf57029d304f012103c6a2fcd030270427d4abe1041c8af929a9e2dbab07b243673453847ab842ee1f024730440220786316a16095105a0af28dccac5cf80f449dea2ea810a9559a89ecb989c2cb3d02205cbd9913d1217ffec144ae4f2bd895f16d778c2ec49ae9c929fdc8bcc2a2b1db0121024d4985241609d072a59be6418d700e87688f6c4d99a51ad68e66078211f076ee38820900", null);
|
||||
addTransactionTab("test1", "02000000000102ba4dc5a4a14bfaa941b7d115b379b5e15f960635cf694c178b9116763cbd63b11600000017160014fc164cbcac023f5eacfcead2d17d8768c41949affeffffff074d44d2856beb68ba52e8832da60a1682768c2421c2d9a8109ef4e66babd1fd1e000000171600148c3098be6b430859115f5ee99c84c368afecd0481500400002305310000000000017a914ffaf369c2212b178c7a2c21c9ccdd5d126e74c4187327f0300000000001976a914a7cda2e06b102a143ab606937a01d152e300cd3e88ac02473044022006da0ca227f765179219e08a33026b94e7cacff77f87b8cd8eb1b46d6dda11d6022064faa7912924fd23406b6ed3328f1bbbc3760dc51109a49c1b38bf57029d304f012103c6a2fcd030270427d4abe1041c8af929a9e2dbab07b243673453847ab842ee1f024730440220786316a16095105a0af28dccac5cf80f449dea2ea810a9559a89ecb989c2cb3d02205cbd9913d1217ffec144ae4f2bd895f16d778c2ec49ae9c929fdc8bcc2a2b1db0121024d4985241609d072a59be6418d700e87688f6c4d99a51ad68e66078211f076ee38820900", null);
|
||||
addTransactionTab("3of3-1signed.psbt", null, "70736274ff0100550200000001294c4871c059bb76be81e94b78059ee2e0c9b1b47f38edb6b4e75916062394930000000000feffffff01f82a0000000000001976a914e65b294f890792f2c2725d488567018d660f0cf488ac701c09004f0102aa7ed3044b1635bb800000021bf4bfc48934b7966b39bdebb689525d9b8bfed5c8b16e8c58f9afe4641d6d5f03800b5dbec0355c9f0b5e8227bc903e9d0ff1fe6ced0dcfb6d416541c7412c4331406b57041300000800000008000000080020000804f0102aa7ed3042cd31dee80000002d544b2364010378f8c6cec85f6b7ed83a8203dcdbedb97e2625f431f897b837e0363428de8fcfbfe373c0d9e1e0cc8163d886764bafe71c5822eaa232981356589145f63394f300000800000008000000080020000804f0102aa7ed3049ec7d9f580000002793e04aff18b4e40ebc48bcdc6232c54c69cf7265a38fbd85b35705e34d2d42f03368e79aa2b2b7f736d156905a7a45891df07baa2d0b7f127a537908cb82deed514130a48af300000800000008000000080020000800001012b983a000000000000220020f64748dad1cbad107761aaed5c59f25aba006498d260b440e0a091691350c9aa010569532102f26969eb8d1da34d17d33ff99e2f020cc33b3d11d9798ec14f46b82bc455d3262103171d9b824205cd5db6e9353676a292ca954b24d8310a36fc983469ba3fb507a221037f3794f3be4c4acc086ac84d6902c025713eabf8890f20f44acf0b34e3c0f0f753ae220602f26969eb8d1da34d17d33ff99e2f020cc33b3d11d9798ec14f46b82bc455d3261c130a48af300000800000008000000080020000800000000000000000220603171d9b824205cd5db6e9353676a292ca954b24d8310a36fc983469ba3fb507a21c5f63394f300000800000008000000080020000800000000000000000220203171d9b824205cd5db6e9353676a292ca954b24d8310a36fc983469ba3fb507a24830450221008d27cc4b03bc543726e73b69e7980e7364d6f33f979a5cd9b92fb3d050666bd002204fc81fc9c67baf7c3b77041ed316714a9c117a5bdbb020e8c771ea3bdc342434012206037f3794f3be4c4acc086ac84d6902c025713eabf8890f20f44acf0b34e3c0f0f71c06b570413000008000000080000000800200008000000000000000000000");
|
||||
}
|
||||
|
||||
|
|
|
@ -14,9 +14,9 @@ import java.time.*;
|
|||
import java.util.ResourceBundle;
|
||||
|
||||
public class HeadersController extends TransactionFormController implements Initializable, TransactionListener {
|
||||
private HeadersForm headersForm;
|
||||
public static final String LOCKTIME_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
private static final long MAX_BLOCK_LOCKTIME = 500000000L;
|
||||
private HeadersForm headersForm;
|
||||
|
||||
@FXML
|
||||
private TextField id;
|
||||
|
@ -110,7 +110,7 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
locktimeFieldset.getChildren().remove(locktimeBlockField);
|
||||
locktimeFieldset.getChildren().remove(locktimeNoneField);
|
||||
locktimeFieldset.getChildren().add(locktimeNoneField);
|
||||
tx.setLockTime(0);
|
||||
tx.setLocktime(0);
|
||||
EventManager.get().notify(tx);
|
||||
} else if(selection.equals("block")) {
|
||||
locktimeFieldset.getChildren().remove(locktimeDateField);
|
||||
|
@ -119,7 +119,7 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
locktimeFieldset.getChildren().add(locktimeBlockField);
|
||||
Integer block = locktimeBlock.getValue();
|
||||
if(block != null) {
|
||||
tx.setLockTime(block);
|
||||
tx.setLocktime(block);
|
||||
EventManager.get().notify(tx);
|
||||
}
|
||||
} else {
|
||||
|
@ -130,17 +130,17 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
LocalDateTime date = locktimeDate.getDateTimeValue();
|
||||
if(date != null) {
|
||||
locktimeDate.setDateTimeValue(date);
|
||||
tx.setLockTime(date.toEpochSecond(OffsetDateTime.now(ZoneId.systemDefault()).getOffset()));
|
||||
tx.setLocktime(date.toEpochSecond(OffsetDateTime.now(ZoneId.systemDefault()).getOffset()));
|
||||
EventManager.get().notify(tx);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
locktimeNone.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, (int)MAX_BLOCK_LOCKTIME-1, 0));
|
||||
if(tx.getLockTime() < MAX_BLOCK_LOCKTIME) {
|
||||
locktimeBlock.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, (int)MAX_BLOCK_LOCKTIME-1, (int)tx.getLockTime()));
|
||||
if(tx.getLockTime() == 0) {
|
||||
locktimeNone.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, (int)Transaction.MAX_BLOCK_LOCKTIME-1, 0));
|
||||
if(tx.getLocktime() < Transaction.MAX_BLOCK_LOCKTIME) {
|
||||
locktimeBlock.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, (int)Transaction.MAX_BLOCK_LOCKTIME-1, (int)tx.getLocktime()));
|
||||
if(tx.getLocktime() == 0) {
|
||||
locktimeToggleGroup.selectToggle(locktimeNoneType);
|
||||
} else {
|
||||
locktimeToggleGroup.selectToggle(locktimeBlockType);
|
||||
|
@ -148,20 +148,20 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
LocalDateTime date = Instant.now().atZone(ZoneId.systemDefault()).toLocalDateTime();
|
||||
locktimeDate.setDateTimeValue(date);
|
||||
} else {
|
||||
locktimeBlock.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, (int)MAX_BLOCK_LOCKTIME-1));
|
||||
LocalDateTime date = Instant.ofEpochSecond(tx.getLockTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
|
||||
locktimeBlock.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, (int)Transaction.MAX_BLOCK_LOCKTIME-1));
|
||||
LocalDateTime date = Instant.ofEpochSecond(tx.getLocktime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
|
||||
locktimeDate.setDateTimeValue(date);
|
||||
locktimeToggleGroup.selectToggle(locktimeDateType);
|
||||
}
|
||||
|
||||
locktimeBlock.valueProperty().addListener((obs, oldValue, newValue) -> {
|
||||
tx.setLockTime(newValue);
|
||||
tx.setLocktime(newValue);
|
||||
EventManager.get().notify(tx);
|
||||
});
|
||||
|
||||
locktimeDate.setFormat("yyyy-MM-dd HH:mm:ss");
|
||||
locktimeDate.setFormat(LOCKTIME_DATE_FORMAT);
|
||||
locktimeDate.dateTimeValueProperty().addListener((obs, oldValue, newValue) -> {
|
||||
tx.setLockTime(newValue.toEpochSecond(OffsetDateTime.now(ZoneId.systemDefault()).getOffset()));
|
||||
tx.setLocktime(newValue.toEpochSecond(OffsetDateTime.now(ZoneId.systemDefault()).getOffset()));
|
||||
EventManager.get().notify(tx);
|
||||
});
|
||||
|
||||
|
@ -189,6 +189,6 @@ public class HeadersController extends TransactionFormController implements Init
|
|||
@Override
|
||||
public void updated(Transaction transaction) {
|
||||
updateTxId();
|
||||
locktimeFieldset.setText(headersForm.getTransaction().isLockTimeEnabled() ? "Locktime" : "Locktime (Disabled)");
|
||||
locktimeFieldset.setText(headersForm.getTransaction().isLocktimeSequenceEnabled() ? "Absolute Locktime" : "Absolute Locktime (sequence disabled)");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,20 +8,12 @@ import javafx.scene.Node;
|
|||
import java.io.IOException;
|
||||
|
||||
public class HeadersForm extends TransactionForm {
|
||||
private Transaction transaction;
|
||||
private PSBT psbt;
|
||||
|
||||
public HeadersForm(Transaction transaction, PSBT psbt) {
|
||||
this.transaction = transaction;
|
||||
this.psbt = psbt;
|
||||
public HeadersForm(PSBT psbt) {
|
||||
super(psbt);
|
||||
}
|
||||
|
||||
public Transaction getTransaction() {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public PSBT getPsbt() {
|
||||
return psbt;
|
||||
public HeadersForm(Transaction transaction) {
|
||||
super(transaction);
|
||||
}
|
||||
|
||||
public Node getContents() throws IOException {
|
||||
|
@ -33,6 +25,6 @@ public class HeadersForm extends TransactionForm {
|
|||
}
|
||||
|
||||
public String toString() {
|
||||
return "Tx [" + transaction.calculateTxId(false).toString().substring(0, 6) + "]";
|
||||
return "Tx [" + getTransaction().calculateTxId(false).toString().substring(0, 6) + "]";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,17 +2,23 @@ package com.sparrowwallet.sparrow.transaction;
|
|||
|
||||
import com.sparrowwallet.drongo.protocol.Script;
|
||||
import com.sparrowwallet.drongo.protocol.ScriptChunk;
|
||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||
import com.sparrowwallet.drongo.protocol.TransactionInput;
|
||||
import com.sparrowwallet.drongo.psbt.PSBTInput;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.control.*;
|
||||
import org.fxmisc.richtext.CodeArea;
|
||||
import tornadofx.control.Field;
|
||||
import tornadofx.control.Fieldset;
|
||||
import org.fxmisc.flowless.VirtualizedScrollPane;
|
||||
|
||||
import java.net.URL;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
|
@ -49,6 +55,42 @@ public class InputController extends TransactionFormController implements Initia
|
|||
@FXML
|
||||
private CodeArea witnessesArea;
|
||||
|
||||
@FXML
|
||||
private ToggleGroup locktimeToggleGroup;
|
||||
|
||||
@FXML
|
||||
private ToggleButton locktimeNoneType;
|
||||
|
||||
@FXML
|
||||
private ToggleButton locktimeAbsoluteType;
|
||||
|
||||
@FXML
|
||||
private ToggleButton locktimeRelativeType;
|
||||
|
||||
@FXML
|
||||
private Fieldset locktimeFieldset;
|
||||
|
||||
@FXML
|
||||
private Field locktimeNoneField;
|
||||
|
||||
@FXML
|
||||
private Field locktimeAbsoluteField;
|
||||
|
||||
@FXML
|
||||
private Field locktimeRelativeField;
|
||||
|
||||
@FXML
|
||||
private Spinner<Integer> locktimeNone;
|
||||
|
||||
@FXML
|
||||
private TextField locktimeAbsolute;
|
||||
|
||||
@FXML
|
||||
private Spinner<Integer> locktimeRelative;
|
||||
|
||||
@FXML
|
||||
private ComboBox<String> locktimeRelativeCombo;
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
|
||||
|
@ -63,7 +105,12 @@ public class InputController extends TransactionFormController implements Initia
|
|||
|
||||
//TODO: Enable select outpoint when wallet present
|
||||
outpointSelect.setDisable(true);
|
||||
initializeScriptFields(txInput);
|
||||
|
||||
initializeLocktimeFields(txInput);
|
||||
}
|
||||
|
||||
private void initializeScriptFields(TransactionInput txInput) {
|
||||
//TODO: Is this safe?
|
||||
Script redeemScript = txInput.getScriptSig().getFirstNestedScript();
|
||||
|
||||
|
@ -95,6 +142,75 @@ public class InputController extends TransactionFormController implements Initia
|
|||
}
|
||||
}
|
||||
|
||||
private void initializeLocktimeFields(TransactionInput txInput) {
|
||||
Transaction transaction = inputForm.getTransaction();
|
||||
locktimeToggleGroup.selectedToggleProperty().addListener((ov, old_toggle, new_toggle) -> {
|
||||
if(locktimeToggleGroup.getSelectedToggle() != null) {
|
||||
String selection = locktimeToggleGroup.getSelectedToggle().getUserData().toString();
|
||||
if(selection.equals("none")) {
|
||||
locktimeFieldset.getChildren().removeAll(locktimeRelativeField, locktimeAbsoluteField, locktimeNoneField);
|
||||
locktimeFieldset.getChildren().add(locktimeNoneField);
|
||||
txInput.setSequenceNumber(TransactionInput.SEQUENCE_LOCKTIME_DISABLED);
|
||||
EventManager.get().notify(transaction);
|
||||
} else if(selection.equals("absolute")) {
|
||||
locktimeFieldset.getChildren().removeAll(locktimeRelativeField, locktimeAbsoluteField, locktimeNoneField);
|
||||
locktimeFieldset.getChildren().add(locktimeAbsoluteField);
|
||||
long locktime = transaction.getLocktime();
|
||||
if(locktime < Transaction.MAX_BLOCK_LOCKTIME) {
|
||||
locktimeAbsoluteField.setText("Block:");
|
||||
locktimeAbsolute.setText(Long.toString(locktime));
|
||||
} else {
|
||||
locktimeAbsoluteField.setText("Date:");
|
||||
LocalDateTime localDateTime = Instant.ofEpochSecond(locktime).atZone(ZoneId.systemDefault()).toLocalDateTime();
|
||||
locktimeAbsolute.setText(DateTimeFormatter.ofPattern(HeadersController.LOCKTIME_DATE_FORMAT).format(localDateTime));
|
||||
}
|
||||
//TODO: Check RBF field and set appropriately
|
||||
txInput.setSequenceNumber(TransactionInput.SEQUENCE_LOCKTIME_DISABLED - 1);
|
||||
EventManager.get().notify(transaction);
|
||||
} else {
|
||||
locktimeFieldset.getChildren().removeAll(locktimeRelativeField, locktimeAbsoluteField, locktimeNoneField);
|
||||
locktimeFieldset.getChildren().add(locktimeRelativeField);
|
||||
setRelativeLocktime(txInput, transaction, locktimeRelative.getValue());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
locktimeNone.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, (int)Transaction.MAX_BLOCK_LOCKTIME-1, (int)transaction.getLocktime()));
|
||||
locktimeRelativeCombo.getSelectionModel().select(0);
|
||||
locktimeRelative.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, (int)TransactionInput.MAX_RELATIVE_TIMELOCK_IN_BLOCKS, 0));
|
||||
if(txInput.isAbsoluteTimeLockDisabled()) {
|
||||
locktimeToggleGroup.selectToggle(locktimeNoneType);
|
||||
} else if(txInput.isAbsoluteTimeLocked()) {
|
||||
locktimeToggleGroup.selectToggle(locktimeAbsoluteType);
|
||||
} else {
|
||||
locktimeRelative.valueFactoryProperty().get().setValue((int)txInput.getRelativeLocktime());
|
||||
if(txInput.isRelativeTimeLockedInBlocks()) {
|
||||
locktimeRelativeCombo.getSelectionModel().select(0);
|
||||
} else {
|
||||
locktimeRelativeCombo.getSelectionModel().select(1);
|
||||
}
|
||||
locktimeToggleGroup.selectToggle(locktimeRelativeType);
|
||||
}
|
||||
|
||||
locktimeRelative.valueProperty().addListener((obs, oldValue, newValue) -> {
|
||||
setRelativeLocktime(txInput, transaction, newValue);
|
||||
});
|
||||
|
||||
locktimeRelativeCombo.getSelectionModel().selectedItemProperty().addListener((ov, old_toggle, new_toggle) -> {
|
||||
setRelativeLocktime(txInput, transaction, locktimeRelative.getValue());
|
||||
});
|
||||
}
|
||||
|
||||
private void setRelativeLocktime(TransactionInput txInput, Transaction transaction, Integer value) {
|
||||
String relativeSelection = locktimeRelativeCombo.getValue();
|
||||
if (relativeSelection.equals("blocks")) {
|
||||
txInput.setSequenceNumber(value & 0xFFFF);
|
||||
} else {
|
||||
txInput.setSequenceNumber((value & 0xFFFF) | 0x400000);
|
||||
}
|
||||
EventManager.get().notify(transaction);
|
||||
}
|
||||
|
||||
public void setModel(InputForm form) {
|
||||
this.inputForm = form;
|
||||
initializeView();
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package com.sparrowwallet.sparrow.transaction;
|
||||
|
||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||
import com.sparrowwallet.drongo.protocol.TransactionInput;
|
||||
import com.sparrowwallet.drongo.psbt.PSBT;
|
||||
import com.sparrowwallet.drongo.psbt.PSBTInput;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Node;
|
||||
|
@ -11,11 +13,17 @@ public class InputForm extends TransactionForm {
|
|||
private TransactionInput transactionInput;
|
||||
private PSBTInput psbtInput;
|
||||
|
||||
public InputForm(TransactionInput transactionInput, PSBTInput psbtInput) {
|
||||
this.transactionInput = transactionInput;
|
||||
public InputForm(PSBT psbt, PSBTInput psbtInput) {
|
||||
super(psbt);
|
||||
this.transactionInput = psbt.getTransaction().getInputs().get(psbt.getPsbtInputs().indexOf(psbtInput));
|
||||
this.psbtInput = psbtInput;
|
||||
}
|
||||
|
||||
public InputForm(Transaction transaction, TransactionInput transactionInput) {
|
||||
super(transaction);
|
||||
this.transactionInput = transactionInput;
|
||||
}
|
||||
|
||||
public TransactionInput getTransactionInput() {
|
||||
return transactionInput;
|
||||
}
|
||||
|
|
|
@ -8,20 +8,12 @@ import javafx.scene.Node;
|
|||
import java.io.IOException;
|
||||
|
||||
public class InputsForm extends TransactionForm {
|
||||
private Transaction transaction;
|
||||
private PSBT psbt;
|
||||
|
||||
public InputsForm(Transaction transaction, PSBT psbt) {
|
||||
this.transaction = transaction;
|
||||
this.psbt = psbt;
|
||||
public InputsForm(PSBT psbt) {
|
||||
super(psbt);
|
||||
}
|
||||
|
||||
public Transaction getTransaction() {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public PSBT getPsbt() {
|
||||
return psbt;
|
||||
public InputsForm(Transaction transaction) {
|
||||
super(transaction);
|
||||
}
|
||||
|
||||
public Node getContents() throws IOException {
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package com.sparrowwallet.sparrow.transaction;
|
||||
|
||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||
import com.sparrowwallet.drongo.protocol.TransactionOutput;
|
||||
import com.sparrowwallet.drongo.psbt.PSBT;
|
||||
import com.sparrowwallet.drongo.psbt.PSBTOutput;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Node;
|
||||
|
||||
|
@ -8,8 +11,16 @@ import java.io.IOException;
|
|||
|
||||
public class OutputForm extends TransactionForm {
|
||||
private TransactionOutput transactionOutput;
|
||||
private PSBTOutput psbtOutput;
|
||||
|
||||
public OutputForm(TransactionOutput transactionOutput) {
|
||||
public OutputForm(PSBT psbt, PSBTOutput psbtOutput) {
|
||||
super(psbt);
|
||||
this.transactionOutput = psbt.getTransaction().getOutputs().get(psbt.getPsbtOutputs().indexOf(psbtOutput));
|
||||
this.psbtOutput = psbtOutput;
|
||||
}
|
||||
|
||||
public OutputForm(Transaction transaction, TransactionOutput transactionOutput) {
|
||||
super(transaction);
|
||||
this.transactionOutput = transactionOutput;
|
||||
}
|
||||
|
||||
|
@ -17,6 +28,10 @@ public class OutputForm extends TransactionForm {
|
|||
return transactionOutput;
|
||||
}
|
||||
|
||||
public PSBTOutput getPsbtOutput() {
|
||||
return psbtOutput;
|
||||
}
|
||||
|
||||
public Node getContents() throws IOException {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("output.fxml"));
|
||||
Node node = loader.load();
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
package com.sparrowwallet.sparrow.transaction;
|
||||
|
||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||
import com.sparrowwallet.drongo.psbt.PSBT;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Node;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class OutputsForm extends TransactionForm {
|
||||
private Transaction transaction;
|
||||
|
||||
public OutputsForm(Transaction transaction) {
|
||||
this.transaction = transaction;
|
||||
public OutputsForm(PSBT psbt) {
|
||||
super(psbt);
|
||||
}
|
||||
|
||||
public Transaction getTransaction() {
|
||||
return transaction;
|
||||
public OutputsForm(Transaction transaction) {
|
||||
super(transaction);
|
||||
}
|
||||
|
||||
public Node getContents() throws IOException {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.sparrowwallet.sparrow.transaction;
|
||||
|
||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||
import com.sparrowwallet.drongo.psbt.PSBTInput;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Node;
|
||||
|
@ -9,7 +10,8 @@ import java.io.IOException;
|
|||
public class PartialInputForm extends TransactionForm {
|
||||
private PSBTInput psbtInput;
|
||||
|
||||
public PartialInputForm(PSBTInput psbtInput) {
|
||||
public PartialInputForm(Transaction transaction, PSBTInput psbtInput) {
|
||||
super(transaction);
|
||||
this.psbtInput = psbtInput;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.sparrowwallet.sparrow.transaction;
|
||||
|
||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||
import com.sparrowwallet.drongo.psbt.PSBTOutput;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Node;
|
||||
|
@ -9,7 +10,8 @@ import java.io.IOException;
|
|||
public class PartialOutputForm extends TransactionForm {
|
||||
private PSBTOutput psbtOutput;
|
||||
|
||||
public PartialOutputForm(PSBTOutput psbtOutput) {
|
||||
public PartialOutputForm(Transaction transaction, PSBTOutput psbtOutput) {
|
||||
super(transaction);
|
||||
this.psbtOutput = psbtOutput;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,23 +1,28 @@
|
|||
package com.sparrowwallet.sparrow.transaction;
|
||||
|
||||
import com.sparrowwallet.drongo.protocol.Script;
|
||||
import com.sparrowwallet.drongo.protocol.ScriptChunk;
|
||||
import javafx.geometry.Point2D;
|
||||
import javafx.scene.control.ContextMenu;
|
||||
import javafx.scene.control.IndexRange;
|
||||
import javafx.scene.control.MenuItem;
|
||||
import javafx.scene.input.Clipboard;
|
||||
import javafx.scene.input.ClipboardContent;
|
||||
import javafx.scene.input.ContextMenuEvent;
|
||||
import org.fxmisc.richtext.CodeArea;
|
||||
import org.fxmisc.richtext.model.TwoDimensional;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
|
||||
import static org.fxmisc.richtext.model.TwoDimensional.Bias.Backward;
|
||||
|
||||
public class ScriptContextMenu extends ContextMenu {
|
||||
private Script script;
|
||||
private MenuItem copyvalue;
|
||||
private CodeArea area;
|
||||
private IndexRange range;
|
||||
private ScriptChunk hoverChunk;
|
||||
|
||||
public ScriptContextMenu()
|
||||
public ScriptContextMenu(CodeArea area, Script script)
|
||||
{
|
||||
showingProperty().addListener((ob,ov,showing) -> checkMenuItems(showing));
|
||||
this.
|
||||
this.script = script;
|
||||
|
||||
copyvalue = new MenuItem("Copy Value");
|
||||
copyvalue.setOnAction(AE -> {
|
||||
|
@ -28,20 +33,22 @@ public class ScriptContextMenu extends ContextMenu {
|
|||
});
|
||||
|
||||
getItems().add(copyvalue);
|
||||
|
||||
this.setStyle("-fx-background-color: -fx-color; -fx-font-family: sans-serif; -fx-font-size: 1em;");
|
||||
}
|
||||
|
||||
private void checkMenuItems(boolean showing)
|
||||
{
|
||||
if(!showing) return;
|
||||
area = (CodeArea)getOwnerNode();
|
||||
|
||||
range = area.getSelection();
|
||||
copyvalue.setDisable(hoverChunk == null);
|
||||
}
|
||||
|
||||
public void setHoverChunk(ScriptChunk hoverChunk) {
|
||||
this.hoverChunk = hoverChunk;
|
||||
area.addEventHandler(ContextMenuEvent.CONTEXT_MENU_REQUESTED, event -> {
|
||||
hoverChunk = null;
|
||||
Point2D point = area.screenToLocal(event.getScreenX(), event.getScreenY());
|
||||
OptionalInt characterIndex = area.hit(point.getX(), point.getY()).getCharacterIndex();
|
||||
if(characterIndex.isPresent()) {
|
||||
TwoDimensional.Position position = area.getParagraph(0).getStyleSpans().offsetToPosition(characterIndex.getAsInt(), Backward);
|
||||
if(position.getMajor() % 2 == 0) {
|
||||
ScriptChunk chunk = script.getChunks().get(position.getMajor() / 2);
|
||||
if(!chunk.isOpCode()) {
|
||||
this.hoverChunk = chunk;
|
||||
}
|
||||
}
|
||||
}
|
||||
copyvalue.setDisable(hoverChunk == null);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.sparrowwallet.drongo.Utils;
|
|||
import com.sparrowwallet.drongo.protocol.*;
|
||||
import com.sparrowwallet.drongo.psbt.PSBT;
|
||||
import com.sparrowwallet.drongo.psbt.PSBTInput;
|
||||
import com.sparrowwallet.drongo.psbt.PSBTOutput;
|
||||
import com.sparrowwallet.sparrow.EventManager;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
|
@ -48,11 +49,11 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
}
|
||||
|
||||
private void initializeTxTree() {
|
||||
HeadersForm headersForm = new HeadersForm(transaction, psbt);
|
||||
HeadersForm headersForm = (psbt == null ? new HeadersForm(transaction) : new HeadersForm(psbt));
|
||||
TreeItem<TransactionForm> rootItem = new TreeItem<>(headersForm);
|
||||
rootItem.setExpanded(true);
|
||||
|
||||
InputsForm inputsForm = new InputsForm(transaction, psbt);
|
||||
InputsForm inputsForm = (psbt == null ? new InputsForm(transaction) : new InputsForm(psbt));
|
||||
TreeItem<TransactionForm> inputsItem = new TreeItem<>(inputsForm);
|
||||
inputsItem.setExpanded(true);
|
||||
for(TransactionInput txInput : transaction.getInputs()) {
|
||||
|
@ -60,16 +61,20 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
if(psbt != null && psbt.getPsbtInputs().size() > txInput.getIndex()) {
|
||||
psbtInput = psbt.getPsbtInputs().get(txInput.getIndex());
|
||||
}
|
||||
InputForm inputForm = new InputForm(txInput, psbtInput);
|
||||
InputForm inputForm = (psbt == null ? new InputForm(transaction, txInput) : new InputForm(psbt, psbtInput));
|
||||
TreeItem<TransactionForm> inputItem = new TreeItem<>(inputForm);
|
||||
inputsItem.getChildren().add(inputItem);
|
||||
}
|
||||
|
||||
OutputsForm outputsForm = new OutputsForm(transaction);
|
||||
OutputsForm outputsForm = (psbt == null ? new OutputsForm(transaction) : new OutputsForm(psbt));
|
||||
TreeItem<TransactionForm> outputsItem = new TreeItem<>(outputsForm);
|
||||
outputsItem.setExpanded(true);
|
||||
for(TransactionOutput txOutput : transaction.getOutputs()) {
|
||||
OutputForm outputForm = new OutputForm(txOutput);
|
||||
PSBTOutput psbtOutput = null;
|
||||
if(psbt != null && psbt.getPsbtOutputs().size() > txOutput.getIndex()) {
|
||||
psbtOutput = psbt.getPsbtOutputs().get(txOutput.getIndex());
|
||||
}
|
||||
OutputForm outputForm = (psbt == null ? new OutputForm(transaction, txOutput) : new OutputForm(psbt, psbtOutput));
|
||||
TreeItem<TransactionForm> outputItem = new TreeItem<>(outputForm);
|
||||
outputsItem.getChildren().add(outputItem);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,31 @@
|
|||
package com.sparrowwallet.sparrow.transaction;
|
||||
|
||||
import com.sparrowwallet.drongo.protocol.Transaction;
|
||||
import com.sparrowwallet.drongo.psbt.PSBT;
|
||||
import javafx.scene.Node;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class TransactionForm {
|
||||
private Transaction transaction;
|
||||
private PSBT psbt;
|
||||
|
||||
public TransactionForm(PSBT psbt) {
|
||||
this.transaction = psbt.getTransaction();
|
||||
this.psbt = psbt;
|
||||
}
|
||||
|
||||
public TransactionForm(Transaction transaction) {
|
||||
this.transaction = transaction;
|
||||
}
|
||||
|
||||
public Transaction getTransaction() {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public PSBT getPsbt() {
|
||||
return psbt;
|
||||
}
|
||||
|
||||
public abstract Node getContents() throws IOException;
|
||||
}
|
||||
|
|
|
@ -88,7 +88,6 @@ public abstract class TransactionFormController {
|
|||
} else if(chunk.isPubKey()) {
|
||||
codeArea.append("<pubkey" + pubKeyCount++ + ">", "script-pubkey");
|
||||
} else {
|
||||
System.out.println(chunk.isOpCode() + " " + chunk.opcode);
|
||||
codeArea.append(chunk.toString(), "script-other");
|
||||
}
|
||||
|
||||
|
@ -102,7 +101,7 @@ public abstract class TransactionFormController {
|
|||
}
|
||||
|
||||
protected void addScriptPopup(CodeArea area, Script script) {
|
||||
ScriptContextMenu contextMenu = new ScriptContextMenu();
|
||||
ScriptContextMenu contextMenu = new ScriptContextMenu(area, script);
|
||||
area.setContextMenu(contextMenu);
|
||||
|
||||
Popup popup = new Popup();
|
||||
|
@ -116,15 +115,10 @@ public abstract class TransactionFormController {
|
|||
if(position.getMajor() % 2 == 0) {
|
||||
ScriptChunk hoverChunk = script.getChunks().get(position.getMajor()/2);
|
||||
if(!hoverChunk.isOpCode()) {
|
||||
contextMenu.setHoverChunk(hoverChunk);
|
||||
Point2D pos = e.getScreenPosition();
|
||||
popupMsg.setText(hoverChunk.toString());
|
||||
popup.show(area, pos.getX(), pos.getY() + 10);
|
||||
} else {
|
||||
contextMenu.setHoverChunk(null);
|
||||
}
|
||||
} else {
|
||||
contextMenu.setHoverChunk(null);
|
||||
}
|
||||
});
|
||||
area.addEventHandler(MouseOverTextEvent.MOUSE_OVER_TEXT_END, e -> {
|
||||
|
|
|
@ -50,14 +50,14 @@
|
|||
</Form>
|
||||
|
||||
<Form GridPane.columnIndex="1" GridPane.rowIndex="2">
|
||||
<Fieldset fx:id="locktimeFieldset" text="Locktime" inputGrow="SOMETIMES">
|
||||
<Fieldset fx:id="locktimeFieldset" text="Absolute Locktime" inputGrow="SOMETIMES">
|
||||
<Field text="Type:">
|
||||
<SegmentedButton>
|
||||
<toggleGroup>
|
||||
<ToggleGroup fx:id="locktimeToggleGroup" />
|
||||
</toggleGroup>
|
||||
<buttons>
|
||||
<ToggleButton fx:id="locktimeNoneType" text="None" userData="none" toggleGroup="$locktimeToggleGroup" />
|
||||
<ToggleButton fx:id="locktimeNoneType" text="Disabled" userData="none" toggleGroup="$locktimeToggleGroup" />
|
||||
<ToggleButton fx:id="locktimeBlockType" text="Block" userData="block" toggleGroup="$locktimeToggleGroup" />
|
||||
<ToggleButton fx:id="locktimeDateType" text="Date" userData="date" toggleGroup="$locktimeToggleGroup" />
|
||||
</buttons>
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
<?import tornadofx.control.*?>
|
||||
<?import org.fxmisc.richtext.CodeArea?>
|
||||
<?import org.fxmisc.flowless.VirtualizedScrollPane?>
|
||||
<?import org.controlsfx.control.SegmentedButton?>
|
||||
<?import javafx.collections.FXCollections?>
|
||||
<?import java.lang.String?>
|
||||
|
||||
<GridPane alignment="TOP_CENTER" hgap="10.0" prefHeight="500.0" prefWidth="620.0" stylesheets="@input.css, @../general.css" vgap="10.0" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.sparrowwallet.sparrow.transaction.InputController">
|
||||
<padding>
|
||||
|
@ -40,8 +43,8 @@
|
|||
<Form GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="2">
|
||||
<Fieldset inputGrow="SOMETIMES" text="Script">
|
||||
<Field text="ScriptSig:">
|
||||
<HBox>
|
||||
<VirtualizedScrollPane prefHeight="42">
|
||||
<HBox prefHeight="42">
|
||||
<VirtualizedScrollPane>
|
||||
<content>
|
||||
<CodeArea fx:id="scriptSigArea" editable="false" minWidth="570" prefWidth="570" wrapText="true" styleClass="uneditable-codearea" />
|
||||
</content>
|
||||
|
@ -49,8 +52,8 @@
|
|||
</HBox>
|
||||
</Field>
|
||||
<Field text="RedeemScript:">
|
||||
<HBox>
|
||||
<VirtualizedScrollPane fx:id="redeemScriptScroll" prefHeight="42">
|
||||
<HBox prefHeight="42">
|
||||
<VirtualizedScrollPane fx:id="redeemScriptScroll">
|
||||
<content>
|
||||
<CodeArea fx:id="redeemScriptArea" editable="false" minWidth="570" prefWidth="570" wrapText="true" styleClass="uneditable-codearea" />
|
||||
</content>
|
||||
|
@ -58,8 +61,8 @@
|
|||
</HBox>
|
||||
</Field>
|
||||
<Field text="Witnesses:">
|
||||
<HBox>
|
||||
<VirtualizedScrollPane fx:id="witnessesScroll" prefHeight="42">
|
||||
<HBox prefHeight="42">
|
||||
<VirtualizedScrollPane fx:id="witnessesScroll">
|
||||
<content>
|
||||
<CodeArea fx:id="witnessesArea" editable="false" minWidth="570" prefWidth="570" wrapText="true" styleClass="uneditable-codearea" />
|
||||
</content>
|
||||
|
@ -67,8 +70,8 @@
|
|||
</HBox>
|
||||
</Field>
|
||||
<Field text="WitnessScript:">
|
||||
<HBox>
|
||||
<VirtualizedScrollPane fx:id="witnessScriptScroll" prefHeight="42">
|
||||
<HBox prefHeight="42">
|
||||
<VirtualizedScrollPane fx:id="witnessScriptScroll">
|
||||
<content>
|
||||
<CodeArea fx:id="witnessScriptArea" editable="false" minWidth="570" prefWidth="570" wrapText="true" styleClass="uneditable-codearea" />
|
||||
</content>
|
||||
|
@ -77,4 +80,41 @@
|
|||
</Field>
|
||||
</Fieldset>
|
||||
</Form>
|
||||
|
||||
<Separator styleClass="form-separator" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="3" />
|
||||
|
||||
<Form GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="4">
|
||||
<Fieldset fx:id="locktimeFieldset" text="Locktime" inputGrow="SOMETIMES">
|
||||
<Field text="Type:">
|
||||
<SegmentedButton>
|
||||
<toggleGroup>
|
||||
<ToggleGroup fx:id="locktimeToggleGroup" />
|
||||
</toggleGroup>
|
||||
<buttons>
|
||||
<ToggleButton fx:id="locktimeNoneType" text="Disabled" userData="none" toggleGroup="$locktimeToggleGroup" />
|
||||
<ToggleButton fx:id="locktimeAbsoluteType" text="Absolute" userData="absolute" toggleGroup="$locktimeToggleGroup" />
|
||||
<ToggleButton fx:id="locktimeRelativeType" text="Relative" userData="relative" toggleGroup="$locktimeToggleGroup" />
|
||||
</buttons>
|
||||
</SegmentedButton>
|
||||
</Field>
|
||||
<Field fx:id="locktimeNoneField" text="Block:">
|
||||
<Spinner fx:id="locktimeNone" disable="true" prefWidth="90"/>
|
||||
</Field>
|
||||
<Field fx:id="locktimeAbsoluteField" text="Block:">
|
||||
<TextField fx:id="locktimeAbsolute" editable="false" prefWidth="120" styleClass="copyable-label"/>
|
||||
</Field>
|
||||
<Field fx:id="locktimeRelativeField" text="Block:">
|
||||
<Spinner fx:id="locktimeRelative" editable="true" prefWidth="90" prefHeight="25"/>
|
||||
<ComboBox fx:id="locktimeRelativeCombo">
|
||||
<items>
|
||||
<FXCollections fx:factory="observableArrayList">
|
||||
<String fx:value="blocks" />
|
||||
<String fx:value="seconds" />
|
||||
</FXCollections>
|
||||
</items>
|
||||
</ComboBox>
|
||||
</Field>
|
||||
</Fieldset>
|
||||
</Form>
|
||||
|
||||
</GridPane>
|
||||
|
|
Loading…
Reference in a new issue