use of com.sparrowwallet.sparrow.io.Storage 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());
}
}
use of com.sparrowwallet.sparrow.io.Storage in project sparrow by sparrowwallet.
the class PayNymController method broadcastNotificationTransaction.
public void broadcastNotificationTransaction(PayNym payNym) {
Wallet masterWallet = getMasterWallet();
WalletTransaction walletTransaction;
try {
walletTransaction = getWalletTransaction(masterWallet, payNym, new byte[80], null);
} catch (InsufficientFundsException e) {
try {
Wallet wallet = AppServices.get().getWallet(walletId);
walletTransaction = getWalletTransaction(wallet, payNym, new byte[80], null);
} catch (InsufficientFundsException e2) {
AppServices.showErrorDialog("Insufficient Funds", "There are not enough funds in this wallet to broadcast the notification transaction.");
followingList.refresh();
return;
}
}
final WalletTransaction walletTx = walletTransaction;
final PaymentCode paymentCode = masterWallet.getPaymentCode();
Wallet wallet = walletTransaction.getWallet();
Storage storage = AppServices.get().getOpenWallets().get(wallet);
if (wallet.isEncrypted()) {
WalletPasswordDialog dlg = new WalletPasswordDialog(wallet.getMasterName(), WalletPasswordDialog.PasswordRequirement.LOAD);
Optional<SecureString> password = dlg.showAndWait();
if (password.isPresent()) {
Storage.DecryptWalletService decryptWalletService = new Storage.DecryptWalletService(wallet.copy(), password.get());
decryptWalletService.setOnSucceeded(workerStateEvent -> {
EventManager.get().post(new StorageEvent(storage.getWalletId(wallet), TimedEvent.Action.END, "Done"));
Wallet decryptedWallet = decryptWalletService.getValue();
broadcastNotificationTransaction(decryptedWallet, walletTx, paymentCode, payNym);
decryptedWallet.clearPrivate();
});
decryptWalletService.setOnFailed(workerStateEvent -> {
EventManager.get().post(new StorageEvent(storage.getWalletId(wallet), TimedEvent.Action.END, "Failed"));
followingList.refresh();
AppServices.showErrorDialog("Incorrect Password", decryptWalletService.getException().getMessage());
});
EventManager.get().post(new StorageEvent(storage.getWalletId(wallet), TimedEvent.Action.START, "Decrypting wallet..."));
decryptWalletService.start();
}
} else {
broadcastNotificationTransaction(wallet, walletTx, paymentCode, payNym);
}
}
use of com.sparrowwallet.sparrow.io.Storage in project sparrow by sparrowwallet.
the class SendController method addChildWallets.
private void addChildWallets(Wallet wallet, PaymentCode externalPaymentCode, Transaction transaction, PayNym payNym) {
List<Wallet> addedWallets = addChildWallets(externalPaymentCode, payNym);
Wallet masterWallet = getWalletForm().getMasterWallet();
Storage storage = AppServices.get().getOpenWallets().get(masterWallet);
EventManager.get().post(new ChildWalletsAddedEvent(storage, masterWallet, addedWallets));
BlockTransaction blockTransaction = wallet.getWalletTransaction(transaction.getTxId());
if (blockTransaction != null && blockTransaction.getLabel() == null) {
blockTransaction.setLabel("Link " + (payNym == null ? externalPaymentCode.toAbbreviatedString() : payNym.nymName()));
TransactionEntry transactionEntry = new TransactionEntry(wallet, blockTransaction, Collections.emptyMap(), Collections.emptyMap());
EventManager.get().post(new WalletEntryLabelsChangedEvent(wallet, List.of(transactionEntry)));
}
if (paymentTabs.getTabs().size() > 0 && !addedWallets.isEmpty()) {
Wallet addedWallet = addedWallets.stream().filter(w -> w.getScriptType() == ScriptType.P2WPKH).findFirst().orElse(addedWallets.iterator().next());
PaymentController controller = (PaymentController) paymentTabs.getTabs().get(0).getUserData();
controller.setPayNym(payNym == null ? PayNym.fromWallet(addedWallet) : payNym);
}
Glyph successGlyph = new Glyph(FontAwesome5.FONT_NAME, FontAwesome5.Glyph.CHECK_CIRCLE);
successGlyph.getStyleClass().add("success");
successGlyph.setFontSize(50);
AppServices.showAlertDialog("Notification Successful", "The notification transaction was successfully sent for payment code " + externalPaymentCode.toAbbreviatedString() + (payNym == null ? "" : " (" + payNym.nymName() + ")") + ".\n\nYou can send to it by entering the payment code, or selecting `PayNym or Payment code` in the Pay to dropdown.", Alert.AlertType.INFORMATION, successGlyph, ButtonType.OK);
}
use of com.sparrowwallet.sparrow.io.Storage in project sparrow by sparrowwallet.
the class SendController method broadcastNotification.
public void broadcastNotification(ActionEvent event) {
Wallet wallet = getWalletForm().getWallet();
Storage storage = AppServices.get().getOpenWallets().get(wallet);
if (wallet.isEncrypted()) {
WalletPasswordDialog dlg = new WalletPasswordDialog(wallet.getMasterName(), WalletPasswordDialog.PasswordRequirement.LOAD);
Optional<SecureString> password = dlg.showAndWait();
if (password.isPresent()) {
Storage.DecryptWalletService decryptWalletService = new Storage.DecryptWalletService(wallet.copy(), password.get());
decryptWalletService.setOnSucceeded(workerStateEvent -> {
EventManager.get().post(new StorageEvent(storage.getWalletId(wallet), TimedEvent.Action.END, "Done"));
Wallet decryptedWallet = decryptWalletService.getValue();
broadcastNotification(decryptedWallet);
decryptedWallet.clearPrivate();
});
decryptWalletService.setOnFailed(workerStateEvent -> {
EventManager.get().post(new StorageEvent(storage.getWalletId(wallet), TimedEvent.Action.END, "Failed"));
AppServices.showErrorDialog("Incorrect Password", decryptWalletService.getException().getMessage());
});
EventManager.get().post(new StorageEvent(storage.getWalletId(wallet), TimedEvent.Action.START, "Decrypting wallet..."));
decryptWalletService.start();
}
} else {
broadcastNotification(wallet);
}
}
use of com.sparrowwallet.sparrow.io.Storage in project sparrow by sparrowwallet.
the class SendController method broadcastPremix.
public void broadcastPremix(ActionEvent event) {
// Ensure all child wallets have been saved
Wallet masterWallet = getWalletForm().getWallet().isMasterWallet() ? getWalletForm().getWallet() : getWalletForm().getWallet().getMasterWallet();
for (Wallet childWallet : masterWallet.getChildWallets()) {
if (!childWallet.isNested()) {
Storage storage = AppServices.get().getOpenWallets().get(childWallet);
if (!storage.isPersisted(childWallet)) {
try {
storage.saveWallet(childWallet);
} catch (Exception e) {
AppServices.showErrorDialog("Error saving wallet " + childWallet.getName(), e.getMessage());
}
}
}
}
// The WhirlpoolWallet has already been configured for the tx0 preview
Whirlpool whirlpool = AppServices.getWhirlpoolServices().getWhirlpool(getWalletForm().getStorage().getWalletId(masterWallet));
Map<BlockTransactionHashIndex, WalletNode> utxos = walletTransactionProperty.get().getSelectedUtxos();
Whirlpool.Tx0BroadcastService tx0BroadcastService = new Whirlpool.Tx0BroadcastService(whirlpool, whirlpoolProperty.get(), utxos.keySet());
tx0BroadcastService.setOnRunning(workerStateEvent -> {
premixButton.setDisable(true);
addWalletTransactionNodes();
});
tx0BroadcastService.setOnSucceeded(workerStateEvent -> {
premixButton.setDisable(false);
Sha256Hash txid = tx0BroadcastService.getValue();
clear(null);
});
tx0BroadcastService.setOnFailed(workerStateEvent -> {
premixButton.setDisable(false);
Throwable exception = workerStateEvent.getSource().getException();
while (exception.getCause() != null) {
exception = exception.getCause();
}
AppServices.showErrorDialog("Error broadcasting premix transaction", exception.getMessage());
});
ServiceProgressDialog progressDialog = new ServiceProgressDialog("Whirlpool", "Broadcast Premix Transaction", "/image/whirlpool.png", tx0BroadcastService);
AppServices.moveToActiveWindowScreen(progressDialog);
tx0BroadcastService.start();
}
Aggregations