use of com.sparrowwallet.drongo.protocol.Sha256Hash in project sparrow by sparrowwallet.
the class SparrowUtxoConfigPersister method doWrite.
@Override
protected void doWrite(UtxoConfigData data) throws Exception {
Wallet wallet = getWallet();
if (wallet == null) {
// Wallet is already closed
return;
}
Map<String, UtxoConfigPersisted> currentData = new HashMap<>(data.getUtxoConfigs());
Map<Sha256Hash, UtxoMixData> changedUtxoMixes = currentData.entrySet().stream().collect(Collectors.toMap(entry -> Sha256Hash.wrap(entry.getKey()), entry -> new UtxoMixData(entry.getValue().getMixsDone(), entry.getValue().getExpired()), (u, v) -> {
throw new IllegalStateException("Duplicate utxo config hashes");
}, HashMap::new));
MapDifference<Sha256Hash, UtxoMixData> mapDifference = Maps.difference(changedUtxoMixes, wallet.getUtxoMixes());
Map<Sha256Hash, UtxoMixData> removedUtxoMixes = mapDifference.entriesOnlyOnRight();
wallet.getUtxoMixes().putAll(changedUtxoMixes);
wallet.getUtxoMixes().keySet().removeAll(removedUtxoMixes.keySet());
if (!changedUtxoMixes.isEmpty() || !removedUtxoMixes.isEmpty()) {
EventManager.get().post(new WalletUtxoMixesChangedEvent(wallet, changedUtxoMixes, removedUtxoMixes));
}
}
use of com.sparrowwallet.drongo.protocol.Sha256Hash in project sparrow by sparrowwallet.
the class SparrowDataSource method fetchWalletResponse.
@Override
protected WalletResponse fetchWalletResponse() throws Exception {
WalletResponse walletResponse = new WalletResponse();
walletResponse.wallet = new WalletResponse.Wallet();
Map<Sha256Hash, BlockTransaction> allTransactions = new HashMap<>();
Map<Sha256Hash, String> allTransactionsZpubs = new HashMap<>();
List<WalletResponse.Address> addresses = new ArrayList<>();
List<WalletResponse.Tx> txes = new ArrayList<>();
List<UnspentOutput> unspentOutputs = new ArrayList<>();
int storedBlockHeight = 0;
String[] zpubs = getWalletSupplier().getPubs(true);
for (String zpub : zpubs) {
Wallet wallet = getWallet(zpub);
if (wallet == null) {
log.debug("No wallet for " + zpub + " found");
continue;
}
Map<Sha256Hash, BlockTransaction> walletTransactions = wallet.getWalletTransactions();
allTransactions.putAll(walletTransactions);
walletTransactions.keySet().forEach(txid -> allTransactionsZpubs.put(txid, zpub));
if (wallet.getStoredBlockHeight() != null) {
storedBlockHeight = Math.max(storedBlockHeight, wallet.getStoredBlockHeight());
}
WalletResponse.Address address = new WalletResponse.Address();
List<ExtendedKey.Header> headers = ExtendedKey.Header.getHeaders(Network.get());
ExtendedKey.Header header = headers.stream().filter(head -> head.getDefaultScriptType().equals(wallet.getScriptType()) && !head.isPrivateKey()).findFirst().orElse(ExtendedKey.Header.xpub);
address.address = wallet.getKeystores().get(0).getExtendedPublicKey().toString(header);
int receiveIndex = wallet.getNode(KeyPurpose.RECEIVE).getHighestUsedIndex() == null ? 0 : wallet.getNode(KeyPurpose.RECEIVE).getHighestUsedIndex() + 1;
address.account_index = wallet.getMixConfig() != null ? Math.max(receiveIndex, wallet.getMixConfig().getReceiveIndex()) : receiveIndex;
int changeIndex = wallet.getNode(KeyPurpose.CHANGE).getHighestUsedIndex() == null ? 0 : wallet.getNode(KeyPurpose.CHANGE).getHighestUsedIndex() + 1;
address.change_index = wallet.getMixConfig() != null ? Math.max(changeIndex, wallet.getMixConfig().getChangeIndex()) : changeIndex;
address.n_tx = walletTransactions.size();
addresses.add(address);
for (Map.Entry<BlockTransactionHashIndex, WalletNode> utxo : wallet.getWalletUtxos().entrySet()) {
BlockTransaction blockTransaction = wallet.getWalletTransaction(utxo.getKey().getHash());
if (blockTransaction != null && utxo.getKey().getStatus() != Status.FROZEN) {
unspentOutputs.add(Whirlpool.getUnspentOutput(utxo.getValue(), blockTransaction, (int) utxo.getKey().getIndex()));
}
}
}
for (BlockTransaction blockTransaction : allTransactions.values()) {
WalletResponse.Tx tx = new WalletResponse.Tx();
tx.block_height = blockTransaction.getHeight();
tx.hash = blockTransaction.getHashAsString();
tx.locktime = blockTransaction.getTransaction().getLocktime();
tx.version = (int) blockTransaction.getTransaction().getVersion();
tx.inputs = new WalletResponse.TxInput[blockTransaction.getTransaction().getInputs().size()];
for (int i = 0; i < blockTransaction.getTransaction().getInputs().size(); i++) {
TransactionInput txInput = blockTransaction.getTransaction().getInputs().get(i);
tx.inputs[i] = new WalletResponse.TxInput();
tx.inputs[i].vin = txInput.getIndex();
tx.inputs[i].sequence = txInput.getSequenceNumber();
if (allTransactionsZpubs.containsKey(txInput.getOutpoint().getHash())) {
tx.inputs[i].prev_out = new WalletResponse.TxOut();
tx.inputs[i].prev_out.txid = txInput.getOutpoint().getHash().toString();
tx.inputs[i].prev_out.vout = (int) txInput.getOutpoint().getIndex();
BlockTransaction spentTransaction = allTransactions.get(txInput.getOutpoint().getHash());
if (spentTransaction != null) {
TransactionOutput spentOutput = spentTransaction.getTransaction().getOutputs().get((int) txInput.getOutpoint().getIndex());
tx.inputs[i].prev_out.value = spentOutput.getValue();
}
tx.inputs[i].prev_out.xpub = new UnspentOutput.Xpub();
tx.inputs[i].prev_out.xpub.m = allTransactionsZpubs.get(txInput.getOutpoint().getHash());
}
}
tx.out = new WalletResponse.TxOutput[blockTransaction.getTransaction().getOutputs().size()];
for (int i = 0; i < blockTransaction.getTransaction().getOutputs().size(); i++) {
TransactionOutput txOutput = blockTransaction.getTransaction().getOutputs().get(i);
tx.out[i] = new WalletResponse.TxOutput();
tx.out[i].n = txOutput.getIndex();
tx.out[i].value = txOutput.getValue();
tx.out[i].xpub = new UnspentOutput.Xpub();
tx.out[i].xpub.m = allTransactionsZpubs.get(blockTransaction.getHash());
}
txes.add(tx);
}
walletResponse.addresses = addresses.toArray(new WalletResponse.Address[0]);
walletResponse.txs = txes.toArray(new WalletResponse.Tx[0]);
walletResponse.unspent_outputs = unspentOutputs.toArray(new UnspentOutput[0]);
walletResponse.info = new WalletResponse.Info();
walletResponse.info.latest_block = new WalletResponse.InfoBlock();
walletResponse.info.latest_block.height = AppServices.getCurrentBlockHeight() == null ? storedBlockHeight : AppServices.getCurrentBlockHeight();
walletResponse.info.latest_block.hash = Sha256Hash.ZERO_HASH.toString();
walletResponse.info.latest_block.time = AppServices.getLatestBlockHeader() == null ? 1 : AppServices.getLatestBlockHeader().getTime();
walletResponse.info.fees = new LinkedHashMap<>();
for (MinerFeeTarget target : MinerFeeTarget.values()) {
walletResponse.info.fees.put(target.getValue(), getMinerFeeSupplier().getFee(target));
}
return walletResponse;
}
use of com.sparrowwallet.drongo.protocol.Sha256Hash in project sparrow by sparrowwallet.
the class SorobanController method getWalletTransaction.
private WalletTransaction getWalletTransaction(Wallet wallet, WalletTransaction walletTransaction, Transaction transaction, Map<Sha256Hash, BlockTransaction> inputTransactions) {
Map<BlockTransactionHashIndex, WalletNode> allWalletUtxos = wallet.getWalletTxos();
Map<BlockTransactionHashIndex, WalletNode> walletUtxos = new LinkedHashMap<>();
Map<BlockTransactionHashIndex, WalletNode> externalUtxos = new LinkedHashMap<>();
for (TransactionInput txInput : transaction.getInputs()) {
Optional<BlockTransactionHashIndex> optWalletUtxo = allWalletUtxos.keySet().stream().filter(txo -> txo.getHash().equals(txInput.getOutpoint().getHash()) && txo.getIndex() == txInput.getOutpoint().getIndex()).findFirst();
if (optWalletUtxo.isPresent()) {
walletUtxos.put(optWalletUtxo.get(), allWalletUtxos.get(optWalletUtxo.get()));
} else {
BlockTransactionHashIndex externalUtxo;
if (inputTransactions != null && inputTransactions.containsKey(txInput.getOutpoint().getHash())) {
BlockTransaction blockTransaction = inputTransactions.get(txInput.getOutpoint().getHash());
TransactionOutput txOutput = blockTransaction.getTransaction().getOutputs().get((int) txInput.getOutpoint().getIndex());
externalUtxo = new BlockTransactionHashIndex(blockTransaction.getHash(), blockTransaction.getHeight(), blockTransaction.getDate(), blockTransaction.getFee(), txInput.getOutpoint().getIndex(), txOutput.getValue());
} else {
externalUtxo = new BlockTransactionHashIndex(txInput.getOutpoint().getHash(), 0, null, null, txInput.getOutpoint().getIndex(), 0);
}
externalUtxos.put(externalUtxo, null);
}
}
List<Map<BlockTransactionHashIndex, WalletNode>> selectedUtxoSets = new ArrayList<>();
selectedUtxoSets.add(walletUtxos);
selectedUtxoSets.add(externalUtxos);
Map<Address, WalletNode> walletAddresses = wallet.getWalletAddresses();
List<Payment> payments = new ArrayList<>();
Map<WalletNode, Long> changeMap = new LinkedHashMap<>();
for (TransactionOutput txOutput : transaction.getOutputs()) {
Address address = txOutput.getScript().getToAddress();
if (address != null) {
Optional<Payment> optPayment = walletTransaction == null ? Optional.empty() : walletTransaction.getPayments().stream().filter(payment -> payment.getAddress().equals(address) && payment.getAmount() == txOutput.getValue()).findFirst();
if (optPayment.isPresent()) {
payments.add(optPayment.get());
} else if (walletAddresses.containsKey(address) && walletAddresses.get(address).getKeyPurpose() == KeyPurpose.CHANGE) {
changeMap.put(walletAddresses.get(address), txOutput.getValue());
} else {
Payment payment = new Payment(address, null, txOutput.getValue(), false);
if (transaction.getOutputs().stream().anyMatch(txo -> txo != txOutput && txo.getValue() == txOutput.getValue())) {
payment.setType(Payment.Type.MIX);
}
payments.add(payment);
}
}
}
long fee = calculateFee(walletTransaction, selectedUtxoSets, transaction);
return new WalletTransaction(wallet, transaction, Collections.emptyList(), selectedUtxoSets, payments, changeMap, fee, inputTransactions);
}
use of com.sparrowwallet.drongo.protocol.Sha256Hash 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();
}
use of com.sparrowwallet.drongo.protocol.Sha256Hash in project sparrow by sparrowwallet.
the class BlockTransactionMapper method map.
@Override
public Map.Entry<Sha256Hash, BlockTransaction> map(ResultSet rs, StatementContext ctx) throws SQLException {
Sha256Hash txid = Sha256Hash.wrap(rs.getBytes("txid"));
byte[] txBytes = rs.getBytes("transaction");
Transaction transaction = null;
if (txBytes != null) {
transaction = new Transaction(txBytes);
}
Long fee = rs.getLong("fee");
if (rs.wasNull()) {
fee = null;
}
BlockTransaction blockTransaction = new BlockTransaction(Sha256Hash.wrap(rs.getBytes("hash")), rs.getInt("height"), rs.getTimestamp("date"), fee, transaction, rs.getBytes("blockHash") == null ? null : Sha256Hash.wrap(rs.getBytes("blockHash")), rs.getString("label"));
blockTransaction.setId(rs.getLong("id"));
return new Map.Entry<>() {
@Override
public Sha256Hash getKey() {
return txid;
}
@Override
public BlockTransaction getValue() {
return blockTransaction;
}
@Override
public BlockTransaction setValue(BlockTransaction value) {
return null;
}
};
}
Aggregations