mirror of
https://github.com/sparrowwallet/sparrow.git
synced 2024-11-02 20:36:44 +00:00
inputs and outputs panes #1
This commit is contained in:
parent
7a2e503624
commit
7bfddc1c98
18 changed files with 392 additions and 75 deletions
2
drongo
2
drongo
|
@ -1 +1 @@
|
|||
Subproject commit 7fb5601de38e79d5c0547ebc684ca137aa895134
|
||||
Subproject commit a1696ec2e8d5ca17fc98246e374e9d3ae9ab368f
|
|
@ -42,9 +42,6 @@ public class AppController implements Initializable {
|
|||
|
||||
File file = fileChooser.showOpenDialog(window);
|
||||
if (file != null) {
|
||||
System.out.println(file);
|
||||
//openFile(file);
|
||||
|
||||
if(file.exists()) {
|
||||
try {
|
||||
byte[] bytes = new byte[(int)file.length()];
|
||||
|
@ -52,16 +49,21 @@ public class AppController implements Initializable {
|
|||
stream.read(bytes);
|
||||
stream.close();
|
||||
|
||||
Tab tab = null;
|
||||
if(PSBT.isPSBT(Hex.toHexString(bytes))) {
|
||||
PSBT psbt = new PSBT(bytes);
|
||||
tab = addTransactionTab(file.getName(), null, psbt);
|
||||
}
|
||||
|
||||
Tab tab = new Tab(file.getName());
|
||||
FXMLLoader transactionLoader = new FXMLLoader(getClass().getResource("transaction.fxml"));
|
||||
tab.setContent(transactionLoader.load());
|
||||
TransactionController controller = transactionLoader.getController();
|
||||
controller.setPSBT(psbt);
|
||||
try {
|
||||
Transaction transaction = new Transaction(bytes);
|
||||
tab = addTransactionTab(file.getName(), transaction, null);
|
||||
} catch(Exception e) {
|
||||
//TODO: Handle not a transaction
|
||||
}
|
||||
|
||||
tabs.getTabs().add(tab);
|
||||
if(tab != null) {
|
||||
tabs.getSelectionModel().select(tab);
|
||||
}
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
@ -71,25 +73,41 @@ public class AppController implements Initializable {
|
|||
}
|
||||
|
||||
private void addExampleTxTabs() {
|
||||
addTransactionTab("p2pkh", "01000000019c2e0f24a03e72002a96acedb12a632e72b6b74c05dc3ceab1fe78237f886c48010000006a47304402203da9d487be5302a6d69e02a861acff1da472885e43d7528ed9b1b537a8e2cac9022002d1bca03a1e9715a99971bafe3b1852b7a4f0168281cbd27a220380a01b3307012102c9950c622494c2e9ff5a003e33b690fe4832477d32c2d256c67eab8bf613b34effffffff02b6f50500000000001976a914bdf63990d6dc33d705b756e13dd135466c06b3b588ac845e0201000000001976a9145fb0e9755a3424efd2ba0587d20b1e98ee29814a88ac06241559");
|
||||
addTransactionTab("p2sh-p2wpkh", "01000000000101db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a5477010000001716001479091972186c449eb1ded22b78e40d009bdf0089feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac0008af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac02473044022047ac8e878352d3ebbde1c94ce3a10d057c24175747116f8288e5d794d12d482f0220217f36a485cae903c713331d877c1f64677e3622ad4010726870540656fe9dcb012103ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a2687392040000");
|
||||
addTransactionTab("p2wpkh", "01000000000102fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f00000000494830450221008b9d1dc26ba6a9cb62127b02742fa9d754cd3bebf337f7a55d114c8e5cdd30be022040529b194ba3f9281a99f2b1c0a19c0489bc22ede944ccf4ecbab4cc618ef3ed01eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a0100000000ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093510d000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac000247304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee0121025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee635711000000");
|
||||
addTransactionTab("p2wsh", "01000000000102fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e000000004847304402200af4e47c9b9629dbecc21f73af989bdaa911f7e6f6c2e9394588a3aa68f81e9902204f3fcf6ade7e5abb1295b6774c8e0abd94ae62217367096bc02ee5e435b67da201ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac000347304402200de66acf4527789bfda55fc5459e214fa6083f936b430a762c629656216805ac0220396f550692cd347171cbc1ef1f51e15282e837bb2b30860dc77c8f78bc8501e503473044022027dc95ad6b740fe5129e7e62a75dd00f291a2aeb1200b84b09d9e3789406b6c002201a9ecd315dd6a0e632ab20bbb98948bc0c6fb204f2c286963bb48517a7058e27034721026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac00000000");
|
||||
addTransactionTab("test1", "02000000000102ba4dc5a4a14bfaa941b7d115b379b5e15f960635cf694c178b9116763cbd63b11600000017160014fc164cbcac023f5eacfcead2d17d8768c41949affeffffff074d44d2856beb68ba52e8832da60a1682768c2421c2d9a8109ef4e66babd1fd1e000000171600148c3098be6b430859115f5ee99c84c368afecd048feffffff02305310000000000017a914ffaf369c2212b178c7a2c21c9ccdd5d126e74c4187327f0300000000001976a914a7cda2e06b102a143ab606937a01d152e300cd3e88ac02473044022006da0ca227f765179219e08a33026b94e7cacff77f87b8cd8eb1b46d6dda11d6022064faa7912924fd23406b6ed3328f1bbbc3760dc51109a49c1b38bf57029d304f012103c6a2fcd030270427d4abe1041c8af929a9e2dbab07b243673453847ab842ee1f024730440220786316a16095105a0af28dccac5cf80f449dea2ea810a9559a89ecb989c2cb3d02205cbd9913d1217ffec144ae4f2bd895f16d778c2ec49ae9c929fdc8bcc2a2b1db0121024d4985241609d072a59be6418d700e87688f6c4d99a51ad68e66078211f076ee38820900");
|
||||
addTransactionTab("p2pkh", "01000000019c2e0f24a03e72002a96acedb12a632e72b6b74c05dc3ceab1fe78237f886c48010000006a47304402203da9d487be5302a6d69e02a861acff1da472885e43d7528ed9b1b537a8e2cac9022002d1bca03a1e9715a99971bafe3b1852b7a4f0168281cbd27a220380a01b3307012102c9950c622494c2e9ff5a003e33b690fe4832477d32c2d256c67eab8bf613b34effffffff02b6f50500000000001976a914bdf63990d6dc33d705b756e13dd135466c06b3b588ac845e0201000000001976a9145fb0e9755a3424efd2ba0587d20b1e98ee29814a88ac06241559", null);
|
||||
addTransactionTab("p2sh-p2wpkh", "01000000000101db6b1b20aa0fd7b23880be2ecbd4a98130974cf4748fb66092ac4d3ceb1a5477010000001716001479091972186c449eb1ded22b78e40d009bdf0089feffffff02b8b4eb0b000000001976a914a457b684d7f0d539a46a45bbc043f35b59d0d96388ac0008af2f000000001976a914fd270b1ee6abcaea97fea7ad0402e8bd8ad6d77c88ac02473044022047ac8e878352d3ebbde1c94ce3a10d057c24175747116f8288e5d794d12d482f0220217f36a485cae903c713331d877c1f64677e3622ad4010726870540656fe9dcb012103ad1d8e89212f0b92c74d23bb710c00662ad1470198ac48c43f7d6f93a2a2687392040000", null);
|
||||
addTransactionTab("p2wpkh", "01000000000102fff7f7881a8099afa6940d42d1e7f6362bec38171ea3edf433541db4e4ad969f00000000494830450221008b9d1dc26ba6a9cb62127b02742fa9d754cd3bebf337f7a55d114c8e5cdd30be022040529b194ba3f9281a99f2b1c0a19c0489bc22ede944ccf4ecbab4cc618ef3ed01eeffffffef51e1b804cc89d182d279655c3aa89e815b1b309fe287d9b2b55d57b90ec68a0100000000ffffffff02202cb206000000001976a9148280b37df378db99f66f85c95a783a76ac7a6d5988ac9093510d000000001976a9143bde42dbee7e4dbe6a21b2d50ce2f0167faa815988ac000247304402203609e17b84f6a7d30c80bfa610b5b4542f32a8a0d5447a12fb1366d7f01cc44a0220573a954c4518331561406f90300e8f3358f51928d43c212a8caed02de67eebee0121025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee635711000000", null);
|
||||
addTransactionTab("p2wsh", "01000000000102fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e000000004847304402200af4e47c9b9629dbecc21f73af989bdaa911f7e6f6c2e9394588a3aa68f81e9902204f3fcf6ade7e5abb1295b6774c8e0abd94ae62217367096bc02ee5e435b67da201ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac000347304402200de66acf4527789bfda55fc5459e214fa6083f936b430a762c629656216805ac0220396f550692cd347171cbc1ef1f51e15282e837bb2b30860dc77c8f78bc8501e503473044022027dc95ad6b740fe5129e7e62a75dd00f291a2aeb1200b84b09d9e3789406b6c002201a9ecd315dd6a0e632ab20bbb98948bc0c6fb204f2c286963bb48517a7058e27034721026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac00000000", null);
|
||||
addTransactionTab("test1", "02000000000102ba4dc5a4a14bfaa941b7d115b379b5e15f960635cf694c178b9116763cbd63b11600000017160014fc164cbcac023f5eacfcead2d17d8768c41949affeffffff074d44d2856beb68ba52e8832da60a1682768c2421c2d9a8109ef4e66babd1fd1e000000171600148c3098be6b430859115f5ee99c84c368afecd048feffffff02305310000000000017a914ffaf369c2212b178c7a2c21c9ccdd5d126e74c4187327f0300000000001976a914a7cda2e06b102a143ab606937a01d152e300cd3e88ac02473044022006da0ca227f765179219e08a33026b94e7cacff77f87b8cd8eb1b46d6dda11d6022064faa7912924fd23406b6ed3328f1bbbc3760dc51109a49c1b38bf57029d304f012103c6a2fcd030270427d4abe1041c8af929a9e2dbab07b243673453847ab842ee1f024730440220786316a16095105a0af28dccac5cf80f449dea2ea810a9559a89ecb989c2cb3d02205cbd9913d1217ffec144ae4f2bd895f16d778c2ec49ae9c929fdc8bcc2a2b1db0121024d4985241609d072a59be6418d700e87688f6c4d99a51ad68e66078211f076ee38820900", null);
|
||||
addTransactionTab("3of3-1signed.psbt", null, "70736274ff0100550200000001294c4871c059bb76be81e94b78059ee2e0c9b1b47f38edb6b4e75916062394930000000000feffffff01f82a0000000000001976a914e65b294f890792f2c2725d488567018d660f0cf488ac701c09004f0102aa7ed3044b1635bb800000021bf4bfc48934b7966b39bdebb689525d9b8bfed5c8b16e8c58f9afe4641d6d5f03800b5dbec0355c9f0b5e8227bc903e9d0ff1fe6ced0dcfb6d416541c7412c4331406b57041300000800000008000000080020000804f0102aa7ed3042cd31dee80000002d544b2364010378f8c6cec85f6b7ed83a8203dcdbedb97e2625f431f897b837e0363428de8fcfbfe373c0d9e1e0cc8163d886764bafe71c5822eaa232981356589145f63394f300000800000008000000080020000804f0102aa7ed3049ec7d9f580000002793e04aff18b4e40ebc48bcdc6232c54c69cf7265a38fbd85b35705e34d2d42f03368e79aa2b2b7f736d156905a7a45891df07baa2d0b7f127a537908cb82deed514130a48af300000800000008000000080020000800001012b983a000000000000220020f64748dad1cbad107761aaed5c59f25aba006498d260b440e0a091691350c9aa010569532102f26969eb8d1da34d17d33ff99e2f020cc33b3d11d9798ec14f46b82bc455d3262103171d9b824205cd5db6e9353676a292ca954b24d8310a36fc983469ba3fb507a221037f3794f3be4c4acc086ac84d6902c025713eabf8890f20f44acf0b34e3c0f0f753ae220602f26969eb8d1da34d17d33ff99e2f020cc33b3d11d9798ec14f46b82bc455d3261c130a48af300000800000008000000080020000800000000000000000220603171d9b824205cd5db6e9353676a292ca954b24d8310a36fc983469ba3fb507a21c5f63394f300000800000008000000080020000800000000000000000220203171d9b824205cd5db6e9353676a292ca954b24d8310a36fc983469ba3fb507a24830450221008d27cc4b03bc543726e73b69e7980e7364d6f33f979a5cd9b92fb3d050666bd002204fc81fc9c67baf7c3b77041ed316714a9c117a5bdbb020e8c771ea3bdc342434012206037f3794f3be4c4acc086ac84d6902c025713eabf8890f20f44acf0b34e3c0f0f71c06b570413000008000000080000000800200008000000000000000000000");
|
||||
}
|
||||
|
||||
private void addTransactionTab(String name, String hex) {
|
||||
try {
|
||||
byte[] txbytes = Utils.hexToBytes(hex);
|
||||
private void addTransactionTab(String name, String transactionHex, String psbtHex) {
|
||||
if(transactionHex != null) {
|
||||
byte[] txbytes = Utils.hexToBytes(transactionHex);
|
||||
Transaction transaction = new Transaction(txbytes);
|
||||
addTransactionTab(name, transaction, null);
|
||||
} else if(psbtHex != null) {
|
||||
PSBT psbt = PSBT.fromString(psbtHex);
|
||||
addTransactionTab(name, null, psbt);
|
||||
}
|
||||
}
|
||||
|
||||
private Tab addTransactionTab(String name, Transaction transaction, PSBT psbt) {
|
||||
try {
|
||||
Tab tab = new Tab(name);
|
||||
tab.setClosable(true);
|
||||
FXMLLoader transactionLoader = new FXMLLoader(getClass().getResource("transaction.fxml"));
|
||||
tab.setContent(transactionLoader.load());
|
||||
TransactionController controller = transactionLoader.getController();
|
||||
|
||||
if(transaction != null) {
|
||||
controller.setTransaction(transaction);
|
||||
} else if(psbt != null) {
|
||||
controller.setPSBT(psbt);
|
||||
}
|
||||
|
||||
tabs.getTabs().add(tab);
|
||||
return tab;
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import com.craigraw.drongo.psbt.PSBT;
|
|||
import com.craigraw.sparrow.form.*;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.control.TreeItem;
|
||||
import javafx.scene.control.TreeView;
|
||||
import javafx.scene.control.cell.TextFieldTreeCell;
|
||||
|
@ -47,7 +49,7 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
TreeItem<Form> rootItem = new TreeItem<>(headersForm);
|
||||
rootItem.setExpanded(true);
|
||||
|
||||
InputsForm inputsForm = new InputsForm(transaction);
|
||||
InputsForm inputsForm = new InputsForm(transaction, psbt);
|
||||
TreeItem<Form> inputsItem = new TreeItem<>(inputsForm);
|
||||
inputsItem.setExpanded(true);
|
||||
for(TransactionInput txInput : transaction.getInputs()) {
|
||||
|
@ -83,10 +85,16 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
|
||||
txtree.getSelectionModel().selectedItemProperty().addListener((observable, old_val, new_val) -> {
|
||||
Form form = new_val.getValue();
|
||||
|
||||
try {
|
||||
txpane.getChildren().removeAll();
|
||||
txpane.getChildren().add(form.getContents());
|
||||
Node node = form.getContents();
|
||||
txpane.getChildren().clear();
|
||||
txpane.getChildren().add(node);
|
||||
|
||||
if(node instanceof Parent) {
|
||||
Parent parent = (Parent)node;
|
||||
txhex.getStylesheets().clear();
|
||||
txhex.getStylesheets().addAll(parent.getStylesheets());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Can't find pane", e);
|
||||
}
|
||||
|
@ -120,24 +128,30 @@ public class TransactionController implements Initializable, TransactionListener
|
|||
}
|
||||
|
||||
//Number of inputs
|
||||
cursor = addText(hex, cursor, 2, "num-inputs");
|
||||
VarInt numInputs = new VarInt(transaction.getInputs().size());
|
||||
cursor = addText(hex, cursor, numInputs.getSizeInBytes()*2, "num-inputs");
|
||||
|
||||
//Inputs
|
||||
int totalInputLength = 0;
|
||||
for(TransactionInput input : transaction.getInputs()) {
|
||||
totalInputLength += input.getLength();
|
||||
cursor = addText(hex, cursor, 32*2, "input-hash");
|
||||
cursor = addText(hex, cursor, 4*2, "input-index");
|
||||
VarInt scriptLen = new VarInt(input.getScriptBytes().length);
|
||||
cursor = addText(hex, cursor, scriptLen.getSizeInBytes()*2, "input-sigscript-length");
|
||||
cursor = addText(hex, cursor, (int)scriptLen.value*2, "input-sigscript");
|
||||
cursor = addText(hex, cursor, 4*2, "input-sequence");
|
||||
}
|
||||
cursor = addText(hex, cursor, totalInputLength*2, "inputs");
|
||||
|
||||
//Number of outputs
|
||||
cursor = addText(hex, cursor, 2, "num-outputs");
|
||||
VarInt numOutputs = new VarInt(transaction.getOutputs().size());
|
||||
cursor = addText(hex, cursor, numOutputs.getSizeInBytes()*2, "num-outputs");
|
||||
|
||||
//Outputs
|
||||
int totalOutputLength = 0;
|
||||
for(TransactionOutput output : transaction.getOutputs()) {
|
||||
totalOutputLength += output.getLength();
|
||||
cursor = addText(hex, cursor, 8*2, "output-value");
|
||||
VarInt scriptLen = new VarInt(output.getScriptBytes().length);
|
||||
cursor = addText(hex, cursor, scriptLen.getSizeInBytes()*2, "output-pubkeyscript-length");
|
||||
cursor = addText(hex, cursor, (int)scriptLen.value*2, "output-pubkeyscript");
|
||||
}
|
||||
cursor = addText(hex, cursor, totalOutputLength*2, "outputs");
|
||||
|
||||
if(transaction.hasWitnesses()) {
|
||||
int totalWitnessLength = 0;
|
||||
|
|
46
src/main/java/com/craigraw/sparrow/form/FormController.java
Normal file
46
src/main/java/com/craigraw/sparrow/form/FormController.java
Normal file
|
@ -0,0 +1,46 @@
|
|||
package com.craigraw.sparrow.form;
|
||||
|
||||
import com.craigraw.drongo.address.Address;
|
||||
import com.craigraw.drongo.protocol.TransactionOutput;
|
||||
import com.craigraw.drongo.protocol.NonStandardScriptException;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.scene.chart.PieChart;
|
||||
import javafx.scene.control.Tooltip;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class FormController {
|
||||
protected void addPieData(PieChart pie, List<TransactionOutput> outputs) {
|
||||
ObservableList<PieChart.Data> outputsPieData = FXCollections.observableArrayList();
|
||||
|
||||
long totalAmt = 0;
|
||||
for(TransactionOutput output : outputs) {
|
||||
String name = "Unknown";
|
||||
try {
|
||||
Address[] addresses = output.getScript().getToAddresses();
|
||||
if(addresses.length == 1) {
|
||||
name = addresses[0].getAddress();
|
||||
} else {
|
||||
name = "[" + addresses[0].getAddress() + ",...]";
|
||||
}
|
||||
} catch(NonStandardScriptException e) {
|
||||
//ignore
|
||||
}
|
||||
|
||||
totalAmt += output.getValue();
|
||||
outputsPieData.add(new PieChart.Data(name, output.getValue()));
|
||||
}
|
||||
|
||||
pie.setData(outputsPieData);
|
||||
|
||||
final double totalSum = totalAmt;
|
||||
pie.getData().forEach(data -> {
|
||||
Tooltip tooltip = new Tooltip();
|
||||
double percent = 100.0 * (data.getPieValue() / totalSum);
|
||||
tooltip.setText(String.format("%.1f", percent) + "%");
|
||||
Tooltip.install(data.getNode(), tooltip);
|
||||
data.pieValueProperty().addListener((observable, oldValue, newValue) -> tooltip.setText(newValue + "%"));
|
||||
});
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ import com.craigraw.sparrow.TransactionListener;
|
|||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import tornadofx.control.DateTimePicker;
|
||||
import tornadofx.control.Field;
|
||||
import tornadofx.control.Fieldset;
|
||||
|
@ -20,9 +19,6 @@ public class HeadersController implements Initializable, TransactionListener {
|
|||
|
||||
private static final long MAX_BLOCK_LOCKTIME = 500000000L;
|
||||
|
||||
@FXML
|
||||
private GridPane layout;
|
||||
|
||||
@FXML
|
||||
private TextField id;
|
||||
|
||||
|
@ -65,6 +61,9 @@ public class HeadersController implements Initializable, TransactionListener {
|
|||
@FXML
|
||||
private TextField virtualSize;
|
||||
|
||||
@FXML
|
||||
private TextField feeRateField;
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
EventManager.get().subscribe(this);
|
||||
|
@ -72,6 +71,10 @@ public class HeadersController implements Initializable, TransactionListener {
|
|||
|
||||
void setModel(HeadersForm form) {
|
||||
this.headersForm = form;
|
||||
initializeView();
|
||||
}
|
||||
|
||||
private void initializeView() {
|
||||
Transaction tx = headersForm.getTransaction();
|
||||
|
||||
updateTxId();
|
||||
|
@ -137,15 +140,21 @@ public class HeadersController implements Initializable, TransactionListener {
|
|||
EventManager.get().notify(tx);
|
||||
});
|
||||
|
||||
if(form.getPsbt() != null) {
|
||||
fee.setText(form.getPsbt().getFee().toString() + " sats");
|
||||
size.setText(tx.getSize() + " B");
|
||||
virtualSize.setText(tx.getVirtualSize() + " vB");
|
||||
|
||||
Long feeAmt = null;
|
||||
if(headersForm.getPsbt() != null) {
|
||||
feeAmt = headersForm.getPsbt().getFee();
|
||||
}
|
||||
|
||||
if(feeAmt != null) {
|
||||
fee.setText(feeAmt + " sats");
|
||||
double feeRate = feeAmt.doubleValue() / tx.getVirtualSize();
|
||||
feeRateField.setText(String.format("%.2f", feeRate) + " sats/vByte");
|
||||
} else {
|
||||
fee.setText("Unknown");
|
||||
}
|
||||
|
||||
size.setText(tx.getSize() + " B");
|
||||
|
||||
virtualSize.setText(tx.getVirtualSize() + " vB");
|
||||
}
|
||||
|
||||
private void updateTxId() {
|
||||
|
|
|
@ -1,13 +1,32 @@
|
|||
package com.craigraw.sparrow.form;
|
||||
|
||||
import com.craigraw.drongo.protocol.*;
|
||||
import com.craigraw.drongo.psbt.PSBTInput;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.chart.PieChart;
|
||||
import javafx.scene.control.TextField;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class InputsController implements Initializable {
|
||||
public class InputsController extends FormController implements Initializable {
|
||||
private InputsForm inputsForm;
|
||||
|
||||
@FXML
|
||||
private TextField count;
|
||||
|
||||
@FXML
|
||||
private TextField total;
|
||||
|
||||
@FXML
|
||||
private TextField signatures;
|
||||
|
||||
@FXML
|
||||
private PieChart inputsPie;
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
|
||||
|
@ -15,5 +34,46 @@ public class InputsController implements Initializable {
|
|||
|
||||
public void setModel(InputsForm form) {
|
||||
this.inputsForm = form;
|
||||
initialiseView();
|
||||
}
|
||||
|
||||
private void initialiseView() {
|
||||
Transaction tx = inputsForm.getTransaction();
|
||||
count.setText(Integer.toString(tx.getInputs().size()));
|
||||
|
||||
total.setText("Unknown");
|
||||
signatures.setText("Unknown");
|
||||
|
||||
if(inputsForm.getPsbt() != null) {
|
||||
int reqSigs = 0;
|
||||
int foundSigs = 0;
|
||||
|
||||
List<TransactionOutput> outputs = new ArrayList<>();
|
||||
for(int i = 0; i < tx.getInputs().size(); i++) {
|
||||
TransactionInput input = tx.getInputs().get(i);
|
||||
PSBTInput psbtInput = inputsForm.getPsbt().getPsbtInputs().get(i);
|
||||
|
||||
if(psbtInput.getNonWitnessUtxo() != null) {
|
||||
outputs.add(psbtInput.getNonWitnessUtxo().getOutputs().get((int)input.getOutpoint().getIndex()));
|
||||
} else if(psbtInput.getWitnessUtxo() != null) {
|
||||
outputs.add(psbtInput.getWitnessUtxo());
|
||||
}
|
||||
|
||||
try {
|
||||
reqSigs += psbtInput.getSigningScript().getNumRequiredSignatures();
|
||||
foundSigs += psbtInput.getPartialSignatures().size();
|
||||
} catch (NonStandardScriptException e) {
|
||||
//TODO: Handle unusual transaction sig
|
||||
}
|
||||
}
|
||||
|
||||
long totalAmt = 0;
|
||||
for(TransactionOutput output : outputs) {
|
||||
totalAmt += output.getValue();
|
||||
}
|
||||
total.setText(totalAmt + " sats");
|
||||
signatures.setText(foundSigs + "/" + reqSigs);
|
||||
addPieData(inputsPie, outputs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.craigraw.sparrow.form;
|
||||
|
||||
import com.craigraw.drongo.protocol.Transaction;
|
||||
import com.craigraw.drongo.psbt.PSBT;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Node;
|
||||
|
||||
|
@ -8,9 +9,19 @@ import java.io.IOException;
|
|||
|
||||
public class InputsForm extends Form {
|
||||
private Transaction transaction;
|
||||
private PSBT psbt;
|
||||
|
||||
public InputsForm(Transaction transaction) {
|
||||
public InputsForm(Transaction transaction, PSBT psbt) {
|
||||
this.transaction = transaction;
|
||||
this.psbt = psbt;
|
||||
}
|
||||
|
||||
public Transaction getTransaction() {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public PSBT getPsbt() {
|
||||
return psbt;
|
||||
}
|
||||
|
||||
public Node getContents() throws IOException {
|
||||
|
|
|
@ -1,13 +1,27 @@
|
|||
package com.craigraw.sparrow.form;
|
||||
|
||||
import com.craigraw.drongo.protocol.Transaction;
|
||||
import com.craigraw.drongo.protocol.TransactionOutput;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
import javafx.scene.chart.PieChart;
|
||||
import javafx.scene.control.TextField;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class OutputsController implements Initializable {
|
||||
public class OutputsController extends FormController implements Initializable {
|
||||
private OutputsForm outputsForm;
|
||||
|
||||
@FXML
|
||||
private TextField count;
|
||||
|
||||
@FXML
|
||||
private TextField total;
|
||||
|
||||
@FXML
|
||||
private PieChart outputsPie;
|
||||
|
||||
@Override
|
||||
public void initialize(URL location, ResourceBundle resources) {
|
||||
|
||||
|
@ -15,5 +29,21 @@ public class OutputsController implements Initializable {
|
|||
|
||||
public void setModel(OutputsForm form) {
|
||||
this.outputsForm = form;
|
||||
initialiseView();
|
||||
}
|
||||
|
||||
private void initialiseView() {
|
||||
Transaction tx = outputsForm.getTransaction();
|
||||
count.setText(Integer.toString(tx.getOutputs().size()));
|
||||
|
||||
long totalAmt = 0;
|
||||
for(TransactionOutput output : tx.getOutputs()) {
|
||||
totalAmt += output.getValue();
|
||||
}
|
||||
total.setText(totalAmt + " sats");
|
||||
|
||||
if(totalAmt > 0) {
|
||||
addPieData(outputsPie, tx.getOutputs());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,10 @@ public class OutputsForm extends Form {
|
|||
this.transaction = transaction;
|
||||
}
|
||||
|
||||
public Transaction getTransaction() {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public Node getContents() throws IOException {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("outputs.fxml"));
|
||||
Node node = loader.load();
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
</Menu>
|
||||
</menus>
|
||||
</MenuBar>
|
||||
<TabPane prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE" VBox.vgrow="ALWAYS" fx:id="tabs" />
|
||||
<TabPane prefHeight="200.0" prefWidth="200.0" VBox.vgrow="ALWAYS" fx:id="tabs" />
|
||||
|
||||
<Label alignment="BOTTOM_LEFT" text="Label" />
|
||||
</children>
|
||||
|
|
18
src/main/resources/com/craigraw/sparrow/form/headers.css
Normal file
18
src/main/resources/com/craigraw/sparrow/form/headers.css
Normal file
|
@ -0,0 +1,18 @@
|
|||
.version-color { -fx-fill: #986801 }
|
||||
.segwit-marker-color { -fx-fill: #000000 }
|
||||
.segwit-flag-color { -fx-fill: #4078f2 }
|
||||
|
||||
.num-inputs-color { -fx-fill: #ca1243 }
|
||||
.input-hash-color { -fx-fill: #0184bc }
|
||||
.input-index-color { -fx-fill: #0184bc }
|
||||
.input-sigscript-length-color { -fx-fill: #0184bc }
|
||||
.input-sigscript-color { -fx-fill: #0184bc }
|
||||
.input-sequence-color { -fx-fill: #0184bc }
|
||||
|
||||
.num-outputs-color { -fx-fill: #ca1243 }
|
||||
.output-value-color { -fx-fill: #50a14f }
|
||||
.output-pubkeyscript-length-color { -fx-fill: #50a14f }
|
||||
.output-pubkeyscript-color { -fx-fill: #50a14f }
|
||||
|
||||
.witnesses-color { -fx-fill: #a626a4 }
|
||||
.locktime-color { -fx-fill: #986801 }
|
|
@ -12,15 +12,15 @@
|
|||
<?import tornadofx.control.Fieldset?>
|
||||
<?import tornadofx.control.Field?>
|
||||
|
||||
<GridPane fx:id="layout" hgap="10.0" prefHeight="350.0" prefWidth="600.0" vgap="10.0" alignment="CENTER" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.craigraw.sparrow.form.HeadersController" stylesheets="@../general.css">
|
||||
<GridPane hgap="10.0" prefHeight="350.0" prefWidth="600.0" vgap="10.0" alignment="TOP_CENTER" xmlns="http://javafx.com/javafx/10.0.2-internal" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.craigraw.sparrow.form.HeadersController" stylesheets="@headers.css, @../general.css">
|
||||
<padding>
|
||||
<Insets bottom="25.0" left="25.0" right="25.0" top="25.0" />
|
||||
</padding>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints minWidth="290" prefWidth="290"
|
||||
<ColumnConstraints minWidth="295" prefWidth="295"
|
||||
maxWidth="Infinity">
|
||||
</ColumnConstraints>
|
||||
<ColumnConstraints minWidth="290" prefWidth="290"
|
||||
<ColumnConstraints minWidth="295" prefWidth="295"
|
||||
maxWidth="Infinity">
|
||||
</ColumnConstraints>
|
||||
</columnConstraints>
|
||||
|
|
31
src/main/resources/com/craigraw/sparrow/form/inputs.css
Normal file
31
src/main/resources/com/craigraw/sparrow/form/inputs.css
Normal file
|
@ -0,0 +1,31 @@
|
|||
.version-color { -fx-fill: #e5e5e6 }
|
||||
.segwit-marker-color { -fx-fill: #e5e5e6 }
|
||||
.segwit-flag-color { -fx-fill: #e5e5e6 }
|
||||
|
||||
.num-inputs-color { -fx-fill: #ca1243 }
|
||||
.input-hash-color { -fx-fill: #0184bc }
|
||||
.input-index-color { -fx-fill: #000000 }
|
||||
.input-sigscript-length-color { -fx-fill: #a626a4 }
|
||||
.input-sigscript-color { -fx-fill: #50a14f }
|
||||
.input-sequence-color { -fx-fill: #986801 }
|
||||
|
||||
.num-outputs-color { -fx-fill: #e5e5e6 }
|
||||
.output-value-color { -fx-fill: #e5e5e6 }
|
||||
.output-pubkeyscript-length-color { -fx-fill: #e5e5e6 }
|
||||
.output-pubkeyscript-color { -fx-fill: #e5e5e6 }
|
||||
|
||||
.witnesses-color { -fx-fill: #e5e5e6 }
|
||||
.locktime-color { -fx-fill: #e5e5e6 }
|
||||
|
||||
.chart-legend-item{
|
||||
-fx-font-family: Courier;
|
||||
}
|
||||
|
||||
.default-color0.chart-pie { -fx-pie-color: #ca1243 }
|
||||
.default-color1.chart-pie { -fx-pie-color: #d75f00 }
|
||||
.default-color2.chart-pie { -fx-pie-color: #0184bc }
|
||||
.default-color3.chart-pie { -fx-pie-color: #c18401 }
|
||||
.default-color4.chart-pie { -fx-pie-color: #50a14f }
|
||||
.default-color5.chart-pie { -fx-pie-color: #4078f2 }
|
||||
.default-color6.chart-pie { -fx-pie-color: #a626a4 }
|
||||
.default-color7.chart-pie { -fx-pie-color: #986801 }
|
|
@ -1,14 +1,45 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import java.lang.*?>
|
||||
<?import java.util.*?>
|
||||
<?import javafx.scene.*?>
|
||||
<?import javafx.geometry.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import tornadofx.control.*?>
|
||||
|
||||
<AnchorPane xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="com.craigraw.sparrow.form.InputsController"
|
||||
prefHeight="400.0" prefWidth="600.0">
|
||||
<?import javafx.scene.chart.PieChart?>
|
||||
<GridPane alignment="TOP_CENTER" hgap="10.0" prefHeight="500.0" prefWidth="600.0" stylesheets="@inputs.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.craigraw.sparrow.form.InputsController">
|
||||
<padding>
|
||||
<Insets bottom="25.0" left="25.0" right="25.0" top="25.0" />
|
||||
</padding>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="290" prefWidth="290">
|
||||
</ColumnConstraints>
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="290" prefWidth="290">
|
||||
</ColumnConstraints>
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints />
|
||||
</rowConstraints>
|
||||
<Form GridPane.columnIndex="0" GridPane.rowIndex="0">
|
||||
<Fieldset inputGrow="SOMETIMES" text="Inputs">
|
||||
<Field text="Count:">
|
||||
<TextField fx:id="count" editable="false" minWidth="520" prefWidth="520" styleClass="copyable-label" />
|
||||
</Field>
|
||||
<Field text="Total:">
|
||||
<TextField fx:id="total" editable="false" minWidth="520" prefWidth="520" styleClass="copyable-label" />
|
||||
</Field>
|
||||
</Fieldset>
|
||||
</Form>
|
||||
|
||||
</AnchorPane>
|
||||
<Form GridPane.columnIndex="1" GridPane.rowIndex="0">
|
||||
<Fieldset inputGrow="SOMETIMES" text="Signatures">
|
||||
<Field text="Status:">
|
||||
<TextField fx:id="signatures" editable="false" minWidth="520" prefWidth="520" styleClass="copyable-label" />
|
||||
</Field>
|
||||
</Fieldset>
|
||||
</Form>
|
||||
|
||||
<Separator GridPane.columnIndex="0" GridPane.rowIndex="1" GridPane.columnSpan="2" styleClass="form-separator"/>
|
||||
|
||||
<PieChart fx:id="inputsPie" prefHeight="400" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="2" startAngle="180" labelLineLength="50" labelsVisible="false" />
|
||||
|
||||
</GridPane>
|
||||
|
|
31
src/main/resources/com/craigraw/sparrow/form/outputs.css
Normal file
31
src/main/resources/com/craigraw/sparrow/form/outputs.css
Normal file
|
@ -0,0 +1,31 @@
|
|||
.version-color { -fx-fill: #e5e5e6 }
|
||||
.segwit-marker-color { -fx-fill: #e5e5e6 }
|
||||
.segwit-flag-color { -fx-fill: #e5e5e6 }
|
||||
|
||||
.num-inputs-color { -fx-fill: #e5e5e6 }
|
||||
.input-hash-color { -fx-fill: #e5e5e6 }
|
||||
.input-index-color { -fx-fill: #e5e5e6 }
|
||||
.input-sigscript-length-color { -fx-fill: #e5e5e6 }
|
||||
.input-sigscript-color { -fx-fill: #e5e5e6 }
|
||||
.input-sequence-color { -fx-fill: #e5e5e6 }
|
||||
|
||||
.num-outputs-color { -fx-fill: #ca1243 }
|
||||
.output-value-color { -fx-fill: #000000 }
|
||||
.output-pubkeyscript-length-color { -fx-fill: #a626a4 }
|
||||
.output-pubkeyscript-color { -fx-fill: #50a14f }
|
||||
|
||||
.witnesses-color { -fx-fill: #e5e5e6 }
|
||||
.locktime-color { -fx-fill: #e5e5e6 }
|
||||
|
||||
.chart-legend-item{
|
||||
-fx-font-family: Courier;
|
||||
}
|
||||
|
||||
.default-color7.chart-pie { -fx-pie-color: #0184bc }
|
||||
.default-color6.chart-pie { -fx-pie-color: #a626a4 }
|
||||
.default-color5.chart-pie { -fx-pie-color: #d75f00 }
|
||||
.default-color4.chart-pie { -fx-pie-color: #986801 }
|
||||
.default-color3.chart-pie { -fx-pie-color: #ca1243 }
|
||||
.default-color2.chart-pie { -fx-pie-color: #c18401 }
|
||||
.default-color1.chart-pie { -fx-pie-color: #50a14f }
|
||||
.default-color0.chart-pie { -fx-pie-color: #4078f2 }
|
|
@ -1,14 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import java.lang.*?>
|
||||
<?import java.util.*?>
|
||||
<?import javafx.scene.*?>
|
||||
<?import javafx.geometry.*?>
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<?import tornadofx.control.*?>
|
||||
|
||||
<AnchorPane xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="com.craigraw.sparrow.form.OutputsController"
|
||||
prefHeight="400.0" prefWidth="600.0">
|
||||
<?import javafx.scene.chart.PieChart?>
|
||||
<GridPane alignment="TOP_CENTER" hgap="10.0" prefHeight="500.0" prefWidth="600.0" stylesheets="@outputs.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.craigraw.sparrow.form.OutputsController">
|
||||
<padding>
|
||||
<Insets bottom="25.0" left="25.0" right="25.0" top="25.0" />
|
||||
</padding>
|
||||
<columnConstraints>
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="290" prefWidth="290">
|
||||
</ColumnConstraints>
|
||||
<ColumnConstraints maxWidth="Infinity" minWidth="290" prefWidth="290">
|
||||
</ColumnConstraints>
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints />
|
||||
</rowConstraints>
|
||||
<Form GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="0">
|
||||
<Fieldset inputGrow="SOMETIMES" text="Outputs">
|
||||
<Field text="Count:">
|
||||
<TextField fx:id="count" editable="false" minWidth="520" prefWidth="520" styleClass="copyable-label" />
|
||||
</Field>
|
||||
<Field text="Total:">
|
||||
<TextField fx:id="total" editable="false" minWidth="520" prefWidth="520" styleClass="copyable-label" />
|
||||
</Field>
|
||||
</Fieldset>
|
||||
</Form>
|
||||
|
||||
<Separator GridPane.columnIndex="0" GridPane.rowIndex="1" GridPane.columnSpan="2" styleClass="form-separator"/>
|
||||
|
||||
<PieChart fx:id="outputsPie" prefHeight="400" GridPane.columnIndex="0" GridPane.columnSpan="2" GridPane.rowIndex="2" startAngle="180" labelLineLength="50" labelsVisible="false" />
|
||||
|
||||
</GridPane>
|
||||
|
||||
</AnchorPane>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
}
|
||||
|
||||
.form .fieldset:horizontal .label-container {
|
||||
-fx-pref-width: 80px;
|
||||
-fx-pref-width: 90px;
|
||||
-fx-pref-height: 25px;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,16 +4,6 @@
|
|||
-fx-padding: 2;
|
||||
}
|
||||
|
||||
.version-color { -fx-fill: #986801 }
|
||||
.segwit-marker-color { -fx-fill: #000000 }
|
||||
.segwit-flag-color { -fx-fill: #4078f2 }
|
||||
.num-inputs-color { -fx-fill: #ca1243 }
|
||||
.inputs-color { -fx-fill: #0184bc }
|
||||
.num-outputs-color { -fx-fill: #ca1243 }
|
||||
.outputs-color { -fx-fill: #50a14f }
|
||||
.witnesses-color { -fx-fill: #a626a4 }
|
||||
.locktime-color { -fx-fill: #986801 }
|
||||
|
||||
.color-0 { -fx-fill: #ca1243 }
|
||||
.color-1 { -fx-fill: #d75f00 }
|
||||
.color-2 { -fx-fill: #c18401 }
|
||||
|
|
Loading…
Reference in a new issue