broadcast tx

This commit is contained in:
Craig Raw
2020-07-30 12:18:45 +02:00
parent 75f5fd2e12
commit c9d7b03afc
6 changed files with 109 additions and 8 deletions
@@ -24,6 +24,7 @@ public class BalanceChart extends LineChart<Number, Number> {
}
public void initialize(WalletTransactionsEntry walletTransactionsEntry) {
managedProperty().bind(visibleProperty());
balanceSeries = new XYChart.Series<>();
getData().add(balanceSeries);
update(walletTransactionsEntry);
@@ -33,6 +34,10 @@ public class BalanceChart extends LineChart<Number, Number> {
}
public void update(WalletTransactionsEntry walletTransactionsEntry) {
if(walletTransactionsEntry.getChildren().isEmpty()) {
setVisible(false);
}
balanceSeries.getData().clear();
List<Data<Number, Number>> balanceDataList = walletTransactionsEntry.getChildren().stream()
@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.github.arteam.simplejsonrpc.client.*;
import com.github.arteam.simplejsonrpc.client.builder.BatchRequestBuilder;
import com.github.arteam.simplejsonrpc.client.exception.JsonRpcBatchException;
import com.github.arteam.simplejsonrpc.client.exception.JsonRpcException;
import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcMethod;
import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcParam;
import com.github.arteam.simplejsonrpc.core.annotation.JsonRpcService;
@@ -594,6 +595,26 @@ public class ElectrumServer {
return targetBlocksFeeRatesSats;
}
public Sha256Hash broadcastTransaction(Transaction transaction) throws ServerException {
byte[] rawtxBytes = transaction.bitcoinSerialize();
String rawtxHex = Utils.bytesToHex(rawtxBytes);
JsonRpcClient client = new JsonRpcClient(getTransport());
try {
String strTxHash = client.createRequest().returnAs(String.class).method("blockchain.transaction.broadcast").id(1).param("raw_tx", rawtxHex).execute();
Sha256Hash receivedTxid = Sha256Hash.wrap(strTxHash);
if(!receivedTxid.equals(transaction.getTxId())) {
throw new ServerException("Received txid was different (" + receivedTxid + ")");
}
return receivedTxid;
} catch(JsonRpcException e) {
throw new ServerException(e.getErrorMessage().getMessage());
} catch(IllegalStateException e) {
throw new ServerException(e.getMessage());
}
}
public static String getScriptHash(Wallet wallet, WalletNode node) {
byte[] hash = Sha256Hash.hash(wallet.getOutputScript(node).getProgram());
byte[] reversed = Utils.reverseBytes(hash);
@@ -1139,6 +1160,24 @@ public class ElectrumServer {
}
}
public static class BroadcastTransactionService extends Service<Sha256Hash> {
private final Transaction transaction;
public BroadcastTransactionService(Transaction transaction) {
this.transaction = transaction;
}
@Override
protected Task<Sha256Hash> createTask() {
return new Task<>() {
protected Sha256Hash call() throws ServerException {
ElectrumServer electrumServer = new ElectrumServer();
return electrumServer.broadcastTransaction(transaction);
}
};
}
}
public enum Protocol {
TCP {
@Override
@@ -10,6 +10,7 @@ import com.sparrowwallet.sparrow.EventManager;
import com.sparrowwallet.sparrow.control.*;
import com.sparrowwallet.sparrow.event.*;
import com.sparrowwallet.sparrow.glyphfont.FontAwesome5Brands;
import com.sparrowwallet.sparrow.io.ElectrumServer;
import com.sparrowwallet.sparrow.io.Storage;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
@@ -154,6 +155,9 @@ public class HeadersController extends TransactionFormController implements Init
@FXML
private SignaturesProgressBar signaturesProgressBar;
@FXML
private ProgressBar broadcastProgressBar;
@FXML
private HBox signButtonBox;
@@ -163,6 +167,12 @@ public class HeadersController extends TransactionFormController implements Init
@FXML
private HBox broadcastButtonBox;
@FXML
private Button viewFinalButton;
@FXML
private Button broadcastButton;
@Override
public void initialize(URL location, ResourceBundle resources) {
EventManager.get().register(this);
@@ -302,6 +312,10 @@ public class HeadersController extends TransactionFormController implements Init
signButtonBox.managedProperty().bind(signButtonBox.visibleProperty());
broadcastButtonBox.managedProperty().bind(broadcastButtonBox.visibleProperty());
signaturesProgressBar.managedProperty().bind(signaturesProgressBar.visibleProperty());
broadcastProgressBar.managedProperty().bind(broadcastProgressBar.visibleProperty());
broadcastProgressBar.visibleProperty().bind(signaturesProgressBar.visibleProperty().not());
blockchainForm.setVisible(false);
signingWalletForm.setVisible(false);
sigHashForm.setVisible(false);
@@ -312,7 +326,7 @@ public class HeadersController extends TransactionFormController implements Init
if(headersForm.getBlockTransaction() != null) {
blockchainForm.setVisible(true);
updateBlockchainForm(headersForm.getBlockTransaction());
updateBlockchainForm(headersForm.getBlockTransaction(), AppController.getCurrentBlockHeight());
} else if(headersForm.getPsbt() != null) {
PSBT psbt = headersForm.getPsbt();
@@ -397,10 +411,9 @@ public class HeadersController extends TransactionFormController implements Init
feeRate.setText(String.format("%.2f", feeRateAmt) + " sats/vByte");
}
private void updateBlockchainForm(BlockTransaction blockTransaction) {
private void updateBlockchainForm(BlockTransaction blockTransaction, Integer currentHeight) {
blockchainForm.setVisible(true);
Integer currentHeight = AppController.getCurrentBlockHeight();
if(currentHeight == null) {
blockStatus.setText("Unknown");
} else {
@@ -604,7 +617,6 @@ public class HeadersController extends TransactionFormController implements Init
}
public void extractTransaction(ActionEvent event) {
Button viewFinalButton = (Button)event.getSource();
viewFinalButton.setDisable(true);
Transaction finalTx = headersForm.getPsbt().extractTransaction();
@@ -613,9 +625,22 @@ public class HeadersController extends TransactionFormController implements Init
}
public void broadcastTransaction(ActionEvent event) {
broadcastButton.setDisable(true);
extractTransaction(event);
ElectrumServer.BroadcastTransactionService broadcastTransactionService = new ElectrumServer.BroadcastTransactionService(headersForm.getTransaction());
broadcastTransactionService.setOnSucceeded(workerStateEvent -> {
//Do nothing and wait for WalletNodeHistoryChangedEvent to indicate tx is in mempool
});
broadcastTransactionService.setOnFailed(workerStateEvent -> {
broadcastProgressBar.setProgress(0);
AppController.showErrorDialog("Error broadcasting transaction", workerStateEvent.getSource().getException().getMessage());
broadcastButton.setDisable(false);
});
signaturesProgressBar.setVisible(false);
broadcastProgressBar.setProgress(-1);
broadcastTransactionService.start();
}
@Subscribe
@@ -635,7 +660,7 @@ public class HeadersController extends TransactionFormController implements Init
public void blockTransactionFetched(BlockTransactionFetchedEvent event) {
if(event.getTxId().equals(headersForm.getTransaction().getTxId())) {
if(event.getBlockTransaction() != null) {
updateBlockchainForm(event.getBlockTransaction());
updateBlockchainForm(event.getBlockTransaction(), AppController.getCurrentBlockHeight());
}
Long feeAmt = calculateFee(event.getInputTransactions());
@@ -766,4 +791,29 @@ public class HeadersController extends TransactionFormController implements Init
updateTxId();
}
}
@Subscribe
public void walletNodeHistoryChanged(WalletNodeHistoryChangedEvent event) {
if(headersForm.getSigningWallet() != null && event.getWalletNode(headersForm.getSigningWallet()) != null) {
Sha256Hash txid = headersForm.getTransaction().getTxId();
ElectrumServer.TransactionReferenceService transactionReferenceService = new ElectrumServer.TransactionReferenceService(Set.of(txid));
transactionReferenceService.setOnSucceeded(successEvent -> {
Map<Sha256Hash, BlockTransaction> transactionMap = transactionReferenceService.getValue();
BlockTransaction blockTransaction = transactionMap.get(txid);
if(blockTransaction != null) {
headersForm.setBlockTransaction(blockTransaction);
signaturesForm.setVisible(false);
updateBlockchainForm(blockTransaction, AppController.getCurrentBlockHeight());
}
});
transactionReferenceService.start();
}
}
@Subscribe
public void walletBlockHeightChanged(WalletBlockHeightChangedEvent event) {
if(headersForm.getSigningWallet() != null && event.getWallet() == headersForm.getSigningWallet() && headersForm.getBlockTransaction() != null) {
updateBlockchainForm(headersForm.getBlockTransaction(), event.getBlockHeight());
}
}
}
@@ -1,6 +1,7 @@
package com.sparrowwallet.sparrow.transaction;
import com.sparrowwallet.drongo.protocol.Transaction;
import com.sparrowwallet.drongo.wallet.BlockTransaction;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
@@ -15,6 +16,10 @@ public class HeadersForm extends TransactionForm {
txdata.setTransaction(finalTransaction);
}
void setBlockTransaction(BlockTransaction blockTransaction) {
txdata.setBlockTransaction(blockTransaction);
}
@Override
public Node getContents() throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("headers.fxml"));