use of com.sparrowwallet.sparrow.wallet.TransactionEntry in project sparrow by sparrowwallet.
the class BalanceChart method update.
public void update(WalletTransactionsEntry walletTransactionsEntry) {
setVisible(!walletTransactionsEntry.getChildren().isEmpty());
balanceSeries.getData().clear();
List<Data<Number, Number>> balanceDataList = getTransactionEntries(walletTransactionsEntry).map(entry -> (TransactionEntry) entry).filter(txEntry -> txEntry.getBlockTransaction().getHeight() > 0).map(txEntry -> new XYChart.Data<>((Number) txEntry.getBlockTransaction().getDate().getTime(), (Number) txEntry.getBalance(), txEntry)).collect(Collectors.toList());
int size = balanceDataList.size() * 2;
for (int i = 0; i < size; i += 2) {
Data<Number, Number> data = balanceDataList.get(i);
if (i + 1 < balanceDataList.size()) {
Data<Number, Number> nextData = balanceDataList.get(i + 1);
Data<Number, Number> interstitialData = new Data<>(nextData.getXValue(), data.getYValue(), null);
balanceDataList.add(i + 1, interstitialData);
} else {
Date now = new Date();
Data<Number, Number> interstitialData = new Data<>(now.getTime(), data.getYValue(), null);
balanceDataList.add(interstitialData);
}
}
if (!balanceDataList.isEmpty()) {
long min = balanceDataList.stream().map(data -> data.getXValue().longValue()).min(Long::compare).get();
long max = balanceDataList.stream().map(data -> data.getXValue().longValue()).max(Long::compare).get();
DateAxisFormatter dateAxisFormatter = new DateAxisFormatter(max - min);
NumberAxis xAxis = (NumberAxis) getXAxis();
xAxis.setTickLabelFormatter(dateAxisFormatter);
}
balanceSeries.getData().addAll(balanceDataList);
if (selectedEntry != null) {
select(selectedEntry);
}
}
use of com.sparrowwallet.sparrow.wallet.TransactionEntry in project sparrow by sparrowwallet.
the class CoinCell method updateItem.
@Override
protected void updateItem(Number amount, boolean empty) {
super.updateItem(amount, empty);
if (empty || amount == null) {
setText(null);
setGraphic(null);
setTooltip(null);
} else {
Entry entry = getTreeTableView().getTreeItem(getIndex()).getValue();
EntryCell.applyRowStyles(this, entry);
CoinTreeTable coinTreeTable = (CoinTreeTable) getTreeTableView();
BitcoinUnit unit = coinTreeTable.getBitcoinUnit();
String satsValue = String.format(Locale.ENGLISH, "%,d", amount.longValue());
DecimalFormat decimalFormat = (amount.longValue() == 0L ? CoinLabel.getBTCFormat() : TABLE_BTC_FORMAT);
final String btcValue = decimalFormat.format(amount.doubleValue() / Transaction.SATOSHIS_PER_BITCOIN);
if (unit.equals(BitcoinUnit.BTC)) {
tooltip.setText(satsValue + " " + BitcoinUnit.SATOSHIS.getLabel());
setText(btcValue);
} else {
tooltip.setText(btcValue + " " + BitcoinUnit.BTC.getLabel());
setText(satsValue);
}
setTooltip(tooltip);
String tooltipValue = tooltip.getText();
if (entry instanceof TransactionEntry) {
TransactionEntry transactionEntry = (TransactionEntry) entry;
tooltip.setText(tooltipValue + " (" + transactionEntry.getConfirmationsDescription() + ")");
transactionEntry.confirmationsProperty().addListener((observable, oldValue, newValue) -> {
tooltip.setText(tooltipValue + " (" + transactionEntry.getConfirmationsDescription() + ")");
});
if (transactionEntry.isConfirming()) {
ConfirmationProgressIndicator arc = new ConfirmationProgressIndicator(transactionEntry.getConfirmations());
arc.confirmationsProperty().bind(transactionEntry.confirmationsProperty());
setGraphic(arc);
setContentDisplay(ContentDisplay.LEFT);
} else {
setGraphic(null);
}
if (amount.longValue() < 0) {
getStyleClass().add("negative-amount");
}
} else if (entry instanceof UtxoEntry) {
setGraphic(null);
} else if (entry instanceof HashIndexEntry) {
Region node = new Region();
node.setPrefWidth(10);
setGraphic(node);
setContentDisplay(ContentDisplay.RIGHT);
if (((HashIndexEntry) entry).getType() == HashIndexEntry.Type.INPUT) {
satsValue = "-" + satsValue;
}
} else {
setGraphic(null);
}
}
}
use of com.sparrowwallet.sparrow.wallet.TransactionEntry in project sparrow by sparrowwallet.
the class PayNymController method walletHistoryChanged.
@Subscribe
public void walletHistoryChanged(WalletHistoryChangedEvent event) {
List<Entry> changedLabelEntries = new ArrayList<>();
for (Map.Entry<Sha256Hash, PayNym> notificationTx : notificationTransactions.entrySet()) {
BlockTransaction blockTransaction = event.getWallet().getWalletTransaction(notificationTx.getKey());
if (blockTransaction != null && blockTransaction.getLabel() == null) {
blockTransaction.setLabel("Link " + notificationTx.getValue().nymName());
changedLabelEntries.add(new TransactionEntry(event.getWallet(), blockTransaction, Collections.emptyMap(), Collections.emptyMap()));
}
}
if (!changedLabelEntries.isEmpty()) {
Platform.runLater(() -> EventManager.get().post(new WalletEntryLabelsChangedEvent(event.getWallet(), changedLabelEntries)));
}
}
use of com.sparrowwallet.sparrow.wallet.TransactionEntry in project sparrow by sparrowwallet.
the class PayNymController method addWalletIfNotificationTransactionPresent.
private void addWalletIfNotificationTransactionPresent(Wallet decryptedWallet, Map<BlockTransaction, PayNym> unlinkedPayNyms, Map<BlockTransaction, WalletNode> unlinkedNotifications) {
List<Wallet> addedWallets = new ArrayList<>();
for (BlockTransaction blockTransaction : unlinkedNotifications.keySet()) {
try {
PayNym payNym = unlinkedPayNyms.get(blockTransaction);
PaymentCode externalPaymentCode = payNym.paymentCode();
WalletNode input0Node = unlinkedNotifications.get(blockTransaction);
Keystore keystore = input0Node.getWallet().isNested() ? decryptedWallet.getChildWallet(input0Node.getWallet().getName()).getKeystores().get(0) : decryptedWallet.getKeystores().get(0);
ECKey input0Key = keystore.getKey(input0Node);
TransactionOutPoint input0Outpoint = PaymentCode.getDesignatedInput(blockTransaction.getTransaction()).getOutpoint();
SecretPoint secretPoint = new SecretPoint(input0Key.getPrivKeyBytes(), externalPaymentCode.getNotificationKey().getPubKey());
byte[] blindingMask = PaymentCode.getMask(secretPoint.ECDHSecretAsBytes(), input0Outpoint.bitcoinSerialize());
byte[] blindedPaymentCode = PaymentCode.blind(getMasterWallet().getPaymentCode().getPayload(), blindingMask);
byte[] opReturnData = PaymentCode.getOpReturnData(blockTransaction.getTransaction());
if (Arrays.equals(opReturnData, blindedPaymentCode)) {
addedWallets.addAll(addChildWallets(payNym, externalPaymentCode));
} else {
blockTransaction.setLabel(INVALID_PAYMENT_CODE_LABEL);
EventManager.get().post(new WalletEntryLabelsChangedEvent(input0Node.getWallet(), new TransactionEntry(input0Node.getWallet(), blockTransaction, Collections.emptyMap(), Collections.emptyMap())));
}
} catch (Exception e) {
log.error("Error adding linked contact from notification transaction", e);
}
}
if (!addedWallets.isEmpty()) {
Wallet masterWallet = getMasterWallet();
Storage storage = AppServices.get().getOpenWallets().get(masterWallet);
EventManager.get().post(new ChildWalletsAddedEvent(storage, masterWallet, addedWallets));
followingList.refresh();
}
}
use of com.sparrowwallet.sparrow.wallet.TransactionEntry in project sparrow by sparrowwallet.
the class PayNymController method broadcastNotificationTransaction.
private void broadcastNotificationTransaction(Wallet decryptedWallet, WalletTransaction walletTransaction, PaymentCode paymentCode, PayNym payNym) {
try {
PaymentCode externalPaymentCode = payNym.paymentCode();
WalletNode input0Node = walletTransaction.getSelectedUtxos().entrySet().iterator().next().getValue();
Keystore keystore = input0Node.getWallet().isNested() ? decryptedWallet.getChildWallet(input0Node.getWallet().getName()).getKeystores().get(0) : decryptedWallet.getKeystores().get(0);
ECKey input0Key = keystore.getKey(input0Node);
TransactionOutPoint input0Outpoint = walletTransaction.getTransaction().getInputs().iterator().next().getOutpoint();
SecretPoint secretPoint = new SecretPoint(input0Key.getPrivKeyBytes(), externalPaymentCode.getNotificationKey().getPubKey());
byte[] blindingMask = PaymentCode.getMask(secretPoint.ECDHSecretAsBytes(), input0Outpoint.bitcoinSerialize());
byte[] blindedPaymentCode = PaymentCode.blind(paymentCode.getPayload(), blindingMask);
WalletTransaction finalWalletTx = getWalletTransaction(decryptedWallet, payNym, blindedPaymentCode, walletTransaction.getSelectedUtxos().keySet());
PSBT psbt = finalWalletTx.createPSBT();
decryptedWallet.sign(psbt);
decryptedWallet.finalise(psbt);
Transaction transaction = psbt.extractTransaction();
ElectrumServer.BroadcastTransactionService broadcastTransactionService = new ElectrumServer.BroadcastTransactionService(transaction);
broadcastTransactionService.setOnSucceeded(successEvent -> {
ElectrumServer.TransactionMempoolService transactionMempoolService = new ElectrumServer.TransactionMempoolService(walletTransaction.getWallet(), transaction.getTxId(), new HashSet<>(walletTransaction.getSelectedUtxos().values()));
transactionMempoolService.setDelay(Duration.seconds(2));
transactionMempoolService.setPeriod(Duration.seconds(5));
transactionMempoolService.setRestartOnFailure(false);
transactionMempoolService.setOnSucceeded(mempoolWorkerStateEvent -> {
Set<String> scriptHashes = transactionMempoolService.getValue();
if (!scriptHashes.isEmpty()) {
transactionMempoolService.cancel();
List<Wallet> addedWallets = addChildWallets(payNym, externalPaymentCode);
Wallet masterWallet = getMasterWallet();
Storage storage = AppServices.get().getOpenWallets().get(masterWallet);
EventManager.get().post(new ChildWalletsAddedEvent(storage, masterWallet, addedWallets));
retrievePayNymProgress.setVisible(false);
followingList.refresh();
BlockTransaction blockTransaction = walletTransaction.getWallet().getWalletTransaction(transaction.getTxId());
if (blockTransaction != null && blockTransaction.getLabel() == null) {
blockTransaction.setLabel("Link " + payNym.nymName());
TransactionEntry transactionEntry = new TransactionEntry(walletTransaction.getWallet(), blockTransaction, Collections.emptyMap(), Collections.emptyMap());
EventManager.get().post(new WalletEntryLabelsChangedEvent(walletTransaction.getWallet(), List.of(transactionEntry)));
}
}
if (transactionMempoolService.getIterationCount() > 5 && transactionMempoolService.isRunning()) {
transactionMempoolService.cancel();
retrievePayNymProgress.setVisible(false);
followingList.refresh();
log.error("Timeout searching for broadcasted notification transaction");
AppServices.showErrorDialog("Timeout searching for broadcasted transaction", "The transaction was broadcast but the server did not register it in the mempool. It is safe to try linking again.");
}
});
transactionMempoolService.setOnFailed(mempoolWorkerStateEvent -> {
transactionMempoolService.cancel();
log.error("Error searching for broadcasted notification transaction", mempoolWorkerStateEvent.getSource().getException());
retrievePayNymProgress.setVisible(false);
followingList.refresh();
AppServices.showErrorDialog("Timeout searching for broadcasted transaction", "The transaction was broadcast but the server did not register it in the mempool. It is safe to try linking again.");
});
transactionMempoolService.start();
});
broadcastTransactionService.setOnFailed(failedEvent -> {
log.error("Error broadcasting notification transaction", failedEvent.getSource().getException());
retrievePayNymProgress.setVisible(false);
followingList.refresh();
AppServices.showErrorDialog("Error broadcasting notification transaction", failedEvent.getSource().getException().getMessage());
});
retrievePayNymProgress.setVisible(true);
notificationTransactions.put(transaction.getTxId(), payNym);
broadcastTransactionService.start();
} catch (Exception e) {
log.error("Error creating notification transaction", e);
retrievePayNymProgress.setVisible(false);
followingList.refresh();
AppServices.showErrorDialog("Error creating notification transaction", e.getMessage());
}
}
Aggregations