mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-12-15 07:52:58 -05:00
Fix nullpointer, add check for miningfee
This commit is contained in:
parent
4232a10f47
commit
9d9ce5918b
6 changed files with 106 additions and 45 deletions
|
|
@ -1040,18 +1040,4 @@ public class TradeWalletService {
|
||||||
throw new WalletException(t);
|
throw new WalletException(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// not used
|
|
||||||
/* private Coin getBalance(List<TransactionOutput> transactionOutputs, Address address) {
|
|
||||||
Coin balance = Coin.ZERO;
|
|
||||||
for (TransactionOutput transactionOutput : transactionOutputs) {
|
|
||||||
if (transactionOutput.getScriptPubKey().isSentToAddress() || transactionOutput.getScriptPubKey().isPayToScriptHash()) {
|
|
||||||
Address addressOutput = transactionOutput.getScriptPubKey().getToAddress(params);
|
|
||||||
if (addressOutput.equals(address))
|
|
||||||
balance = balance.add(transactionOutput.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return balance;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ import java.util.*;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -86,6 +87,7 @@ public class WalletService {
|
||||||
private final IntegerProperty numPeers = new SimpleIntegerProperty(0);
|
private final IntegerProperty numPeers = new SimpleIntegerProperty(0);
|
||||||
private final ObjectProperty<List<Peer>> connectedPeers = new SimpleObjectProperty<>();
|
private final ObjectProperty<List<Peer>> connectedPeers = new SimpleObjectProperty<>();
|
||||||
public final BooleanProperty shutDownDone = new SimpleBooleanProperty();
|
public final BooleanProperty shutDownDone = new SimpleBooleanProperty();
|
||||||
|
private ArbitraryTransactionBloomFilter arbitraryTransactionBloomFilter;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
@ -129,7 +131,11 @@ public class WalletService {
|
||||||
walletAppKit.wallet().allowSpendingUnconfirmedTransactions();
|
walletAppKit.wallet().allowSpendingUnconfirmedTransactions();
|
||||||
if (params != RegTestParams.get())
|
if (params != RegTestParams.get())
|
||||||
walletAppKit.peerGroup().setMaxConnections(11);
|
walletAppKit.peerGroup().setMaxConnections(11);
|
||||||
|
|
||||||
|
// https://groups.google.com/forum/#!msg/bitcoinj/Ys13qkTwcNg/9qxnhwnkeoIJ
|
||||||
|
// DEFAULT_BLOOM_FILTER_FP_RATE = 0.00001
|
||||||
walletAppKit.peerGroup().setBloomFilterFalsePositiveRate(0.00001);
|
walletAppKit.peerGroup().setBloomFilterFalsePositiveRate(0.00001);
|
||||||
|
|
||||||
wallet = walletAppKit.wallet();
|
wallet = walletAppKit.wallet();
|
||||||
wallet.addEventListener(walletEventListener);
|
wallet.addEventListener(walletEventListener);
|
||||||
|
|
||||||
|
|
@ -614,17 +620,35 @@ public class WalletService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* // TODO
|
public void requestTransactionFromBlockChain(Transaction transaction, Consumer<Coin> resultHandler) {
|
||||||
private class BloomFilterForForeignTx extends AbstractPeerEventListener implements PeerFilterProvider {
|
arbitraryTransactionBloomFilter = new ArbitraryTransactionBloomFilter(transaction, resultHandler);
|
||||||
private final String txId;
|
PeerGroup peerGroup = walletAppKit.peerGroup();
|
||||||
|
peerGroup.addEventListener(arbitraryTransactionBloomFilter);
|
||||||
|
peerGroup.addPeerFilterProvider(arbitraryTransactionBloomFilter);
|
||||||
|
}
|
||||||
|
|
||||||
public BloomFilterForForeignTx(String txId) {
|
private class ArbitraryTransactionBloomFilter extends AbstractPeerEventListener implements PeerFilterProvider {
|
||||||
this.txId = txId;
|
private final Transaction transaction;
|
||||||
|
private final Consumer<Coin> resultHandler;
|
||||||
|
private final Set<TransactionOutPoint> transactionOutPoints;
|
||||||
|
|
||||||
|
public ArbitraryTransactionBloomFilter(Transaction transaction, Consumer<Coin> resultHandler) {
|
||||||
|
this.transaction = transaction;
|
||||||
|
this.resultHandler = resultHandler;
|
||||||
|
|
||||||
|
transactionOutPoints = transaction.getInputs().stream()
|
||||||
|
.map(e -> e.getOutpoint() != null ? e.getOutpoint() : null)
|
||||||
|
.filter(e -> e != null)
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
log.debug("transaction=" + transaction);
|
||||||
|
log.debug("transaction.fee=" + transaction.getFee());
|
||||||
|
log.debug("outpoints=" + transactionOutPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getEarliestKeyCreationTime() {
|
public long getEarliestKeyCreationTime() {
|
||||||
return Utils.currentTimeSeconds();
|
return System.currentTimeMillis() / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -633,16 +657,15 @@ public class WalletService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getBloomFilterElementCount() {
|
public int getBloomFilterElementCount() {
|
||||||
return 1;
|
return transactionOutPoints.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BloomFilter getBloomFilter(int size, double falsePositiveRate, long nTweak) {
|
public BloomFilter getBloomFilter(int size, double falsePositiveRate, long nTweak) {
|
||||||
BloomFilter filter = new BloomFilter(size, falsePositiveRate, nTweak);
|
BloomFilter filter = new BloomFilter(size, falsePositiveRate, nTweak);
|
||||||
*//* for (TransactionOutPoint pledge : allPledges.keySet()) {
|
for (TransactionOutPoint transactionOutPoint : transactionOutPoints) {
|
||||||
filter.insert(pledge.bitcoinSerialize());
|
filter.insert(transactionOutPoint.bitcoinSerialize());
|
||||||
}*//*
|
}
|
||||||
// how to add txid ???
|
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -656,20 +679,15 @@ public class WalletService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTransaction(Peer peer, Transaction t) {
|
public void onTransaction(Peer peer, Transaction tx) {
|
||||||
// executor.checkOnThread();
|
if (transactionOutPoints.contains(tx))
|
||||||
// TODO: Gate this logic on t being announced by multiple peers.
|
transactionOutPoints.remove(tx);
|
||||||
// checkForRevocation(t);
|
|
||||||
// TODO: Watch out for the confirmation. If no confirmation of the revocation occurs within N hours, alert the user.
|
if (transactionOutPoints.isEmpty())
|
||||||
|
resultHandler.accept(transaction.getFee());
|
||||||
|
|
||||||
|
log.debug("onTransaction: transaction=" + tx);
|
||||||
|
log.debug("onTransaction: transaction.fee=" + tx.getFee());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
public void findTxInBlockChain(String txId) {
|
|
||||||
// https://groups.google.com/forum/?hl=de#!topic/bitcoinj/kinFP7lLsRE
|
|
||||||
// https://groups.google.com/forum/?hl=de#!topic/bitcoinj/f7m87kCWdb8
|
|
||||||
// https://groups.google.com/forum/?hl=de#!topic/bitcoinj/jNE5ohLExVM
|
|
||||||
walletAppKit.peerGroup().addPeerFilterProvider(new BloomFilterForForeignTx(txId));
|
|
||||||
}*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,8 @@ import javafx.beans.property.*;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.collections.SetChangeListener;
|
import javafx.collections.SetChangeListener;
|
||||||
import org.bitcoinj.core.Coin;
|
import org.bitcoinj.core.*;
|
||||||
|
import org.bitcoinj.script.Script;
|
||||||
import org.bitcoinj.utils.ExchangeRate;
|
import org.bitcoinj.utils.ExchangeRate;
|
||||||
import org.bitcoinj.utils.Fiat;
|
import org.bitcoinj.utils.Fiat;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
@ -84,6 +85,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||||
|
|
||||||
final BooleanProperty isWalletFunded = new SimpleBooleanProperty();
|
final BooleanProperty isWalletFunded = new SimpleBooleanProperty();
|
||||||
final BooleanProperty useMBTC = new SimpleBooleanProperty();
|
final BooleanProperty useMBTC = new SimpleBooleanProperty();
|
||||||
|
final BooleanProperty insufficientFee = new SimpleBooleanProperty();
|
||||||
|
|
||||||
final ObjectProperty<Coin> amountAsCoin = new SimpleObjectProperty<>();
|
final ObjectProperty<Coin> amountAsCoin = new SimpleObjectProperty<>();
|
||||||
final ObjectProperty<Coin> minAmountAsCoin = new SimpleObjectProperty<>();
|
final ObjectProperty<Coin> minAmountAsCoin = new SimpleObjectProperty<>();
|
||||||
|
|
@ -160,9 +162,43 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||||
|
|
||||||
private void addListeners() {
|
private void addListeners() {
|
||||||
walletService.addBalanceListener(balanceListener);
|
walletService.addBalanceListener(balanceListener);
|
||||||
|
walletService.getWallet().addEventListener(new WalletEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
|
||||||
|
walletService.requestTransactionFromBlockChain(tx, fee -> {
|
||||||
|
if (fee == null || fee.compareTo(FeePolicy.getFeePerKb()) < 0)
|
||||||
|
insufficientFee.set(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReorganize(Wallet wallet) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWalletChanged(Wallet wallet) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScriptsChanged(Wallet wallet, List<Script> scripts, boolean isAddingScripts) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onKeysAdded(List<ECKey> keys) {
|
||||||
|
}
|
||||||
|
});
|
||||||
user.getPaymentAccountsAsObservable().addListener(paymentAccountsChangeListener);
|
user.getPaymentAccountsAsObservable().addListener(paymentAccountsChangeListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void removeListeners() {
|
private void removeListeners() {
|
||||||
walletService.removeBalanceListener(balanceListener);
|
walletService.removeBalanceListener(balanceListener);
|
||||||
user.getPaymentAccountsAsObservable().removeListener(paymentAccountsChangeListener);
|
user.getPaymentAccountsAsObservable().removeListener(paymentAccountsChangeListener);
|
||||||
|
|
@ -323,7 +359,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
|
||||||
if (direction == Offer.Direction.BUY)
|
if (direction == Offer.Direction.BUY)
|
||||||
totalToPayAsCoin.set(offerFeeAsCoin.add(networkFeeAsCoin).add(securityDepositAsCoin));
|
totalToPayAsCoin.set(offerFeeAsCoin.add(networkFeeAsCoin).add(securityDepositAsCoin));
|
||||||
else
|
else
|
||||||
totalToPayAsCoin.set(offerFeeAsCoin.add(networkFeeAsCoin).add(securityDepositAsCoin).add(amountAsCoin.get()));
|
totalToPayAsCoin.set(offerFeeAsCoin.add(networkFeeAsCoin).add(securityDepositAsCoin).add(amountAsCoin.get() == null ? Coin.ZERO : amountAsCoin.get()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ package io.bitsquare.gui.main.offer.createoffer;
|
||||||
import de.jensd.fx.fontawesome.AwesomeDude;
|
import de.jensd.fx.fontawesome.AwesomeDude;
|
||||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||||
import io.bitsquare.app.BitsquareApp;
|
import io.bitsquare.app.BitsquareApp;
|
||||||
|
import io.bitsquare.btc.FeePolicy;
|
||||||
import io.bitsquare.common.util.Tuple2;
|
import io.bitsquare.common.util.Tuple2;
|
||||||
import io.bitsquare.common.util.Tuple3;
|
import io.bitsquare.common.util.Tuple3;
|
||||||
import io.bitsquare.gui.Navigation;
|
import io.bitsquare.gui.Navigation;
|
||||||
|
|
@ -100,9 +101,10 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
private ChangeListener<String> errorMessageListener;
|
private ChangeListener<String> errorMessageListener;
|
||||||
private ChangeListener<Boolean> isPlaceOfferSpinnerVisibleListener;
|
private ChangeListener<Boolean> isPlaceOfferSpinnerVisibleListener;
|
||||||
private ChangeListener<Boolean> showTransactionPublishedScreen;
|
private ChangeListener<Boolean> showTransactionPublishedScreen;
|
||||||
|
private ChangeListener<Boolean> insufficientFeeListener;
|
||||||
private EventHandler<ActionEvent> paymentAccountsComboBoxSelectionHandler;
|
private EventHandler<ActionEvent> paymentAccountsComboBoxSelectionHandler;
|
||||||
private EventHandler<ActionEvent> currencyComboBoxSelectionHandler;
|
|
||||||
|
|
||||||
|
private EventHandler<ActionEvent> currencyComboBoxSelectionHandler;
|
||||||
private int gridRow = 0;
|
private int gridRow = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -186,7 +188,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
public void onClose() {
|
public void onClose() {
|
||||||
// we use model.requestPlaceOfferSuccess to not react on close caused by placeOffer
|
// we use model.requestPlaceOfferSuccess to not react on close caused by placeOffer
|
||||||
if (model.dataModel.isWalletFunded.get() && !model.requestPlaceOfferSuccess.get())
|
if (model.dataModel.isWalletFunded.get() && !model.requestPlaceOfferSuccess.get())
|
||||||
new Popup().warning("You have already funds paid in.\nIn the <Funds/Open for withdrawal> section you can withdraw those funds.").show();
|
new Popup().warning("You have already funds paid in.\nIn the \"Funds/Open for withdrawal\" section you can withdraw those funds.").show();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCloseHandler(OfferView.CloseHandler closeHandler) {
|
public void setCloseHandler(OfferView.CloseHandler closeHandler) {
|
||||||
|
|
@ -421,6 +423,19 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
placeOfferSpinner.setVisible(newValue);
|
placeOfferSpinner.setVisible(newValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
insufficientFeeListener = (observable, oldValue, newValue) -> {
|
||||||
|
if (newValue) {
|
||||||
|
new Popup().warning("You need to use at least a mining fee of " +
|
||||||
|
model.formatCoin(FeePolicy.getFeePerKb()) +
|
||||||
|
".\n\nThe trade transactions might take too much time to be included in " +
|
||||||
|
"a block if the fee is too low.\n" +
|
||||||
|
"Please withdraw the amount you have funded back to your wallet and " +
|
||||||
|
"do a funding again with the correct fee.")
|
||||||
|
.onClose(() -> close())
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
paymentAccountsComboBoxSelectionHandler = e -> onPaymentAccountsComboBoxSelected();
|
paymentAccountsComboBoxSelectionHandler = e -> onPaymentAccountsComboBoxSelected();
|
||||||
currencyComboBoxSelectionHandler = e -> onCurrencyComboBoxSelected();
|
currencyComboBoxSelectionHandler = e -> onCurrencyComboBoxSelected();
|
||||||
|
|
||||||
|
|
@ -464,6 +479,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
model.showWarningAdjustedVolume.addListener(showWarningAdjustedVolumeListener);
|
model.showWarningAdjustedVolume.addListener(showWarningAdjustedVolumeListener);
|
||||||
model.errorMessage.addListener(errorMessageListener);
|
model.errorMessage.addListener(errorMessageListener);
|
||||||
model.isPlaceOfferSpinnerVisible.addListener(isPlaceOfferSpinnerVisibleListener);
|
model.isPlaceOfferSpinnerVisible.addListener(isPlaceOfferSpinnerVisibleListener);
|
||||||
|
model.dataModel.insufficientFee.addListener(insufficientFeeListener);
|
||||||
|
|
||||||
model.requestPlaceOfferSuccess.addListener(showTransactionPublishedScreen);
|
model.requestPlaceOfferSuccess.addListener(showTransactionPublishedScreen);
|
||||||
|
|
||||||
|
|
@ -485,6 +501,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||||
model.showWarningAdjustedVolume.removeListener(showWarningAdjustedVolumeListener);
|
model.showWarningAdjustedVolume.removeListener(showWarningAdjustedVolumeListener);
|
||||||
model.errorMessage.removeListener(errorMessageListener);
|
model.errorMessage.removeListener(errorMessageListener);
|
||||||
model.isPlaceOfferSpinnerVisible.removeListener(isPlaceOfferSpinnerVisibleListener);
|
model.isPlaceOfferSpinnerVisible.removeListener(isPlaceOfferSpinnerVisibleListener);
|
||||||
|
model.dataModel.insufficientFee.removeListener(insufficientFeeListener);
|
||||||
|
|
||||||
model.requestPlaceOfferSuccess.removeListener(showTransactionPublishedScreen);
|
model.requestPlaceOfferSuccess.removeListener(showTransactionPublishedScreen);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -476,6 +476,10 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
||||||
return paymentLabel;
|
return paymentLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String formatCoin(Coin coin) {
|
||||||
|
return formatter.formatCoin(coin);
|
||||||
|
}
|
||||||
|
|
||||||
public Offer createAndGetOffer() {
|
public Offer createAndGetOffer() {
|
||||||
offer = dataModel.createAndGetOffer();
|
offer = dataModel.createAndGetOffer();
|
||||||
return offer;
|
return offer;
|
||||||
|
|
|
||||||
|
|
@ -347,7 +347,7 @@ public class PeerManager implements ConnectionListener, MessageListener {
|
||||||
"Reported peers:");
|
"Reported peers:");
|
||||||
reportedPeers.stream().forEach(e -> result.append("\n").append(e));
|
reportedPeers.stream().forEach(e -> result.append("\n").append(e));
|
||||||
result.append("\n------------------------------------------------------------\n");
|
result.append("\n------------------------------------------------------------\n");
|
||||||
log.trace(result.toString());
|
//log.trace(result.toString());
|
||||||
log.info("Number of reported peers: {}", reportedPeers.size());
|
log.info("Number of reported peers: {}", reportedPeers.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue