use of bisq.core.btc.AddressEntry in project bisq-desktop by bisq-network.
the class CreateOfferViewModelTest method setUp.
@Before
public void setUp() {
final CryptoCurrency btc = new CryptoCurrency("BTC", "bitcoin");
GlobalSettings.setDefaultTradeCurrency(btc);
Res.setBaseCurrencyCode(btc.getCode());
Res.setBaseCurrencyName(btc.getName());
final BSFormatter bsFormatter = new BSFormatter();
final BtcValidator btcValidator = new BtcValidator(bsFormatter);
final AltcoinValidator altcoinValidator = new AltcoinValidator();
final FiatPriceValidator fiatPriceValidator = new FiatPriceValidator();
FeeService feeService = mock(FeeService.class);
AddressEntry addressEntry = mock(AddressEntry.class);
BtcWalletService btcWalletService = mock(BtcWalletService.class);
PriceFeedService priceFeedService = mock(PriceFeedService.class);
User user = mock(User.class);
PaymentAccount paymentAccount = mock(PaymentAccount.class);
BsqWalletService bsqWalletService = mock(BsqWalletService.class);
SecurityDepositValidator securityDepositValidator = mock(SecurityDepositValidator.class);
when(btcWalletService.getOrCreateAddressEntry(anyString(), any())).thenReturn(addressEntry);
when(btcWalletService.getBalanceForAddress(any())).thenReturn(Coin.valueOf(1000L));
when(priceFeedService.updateCounterProperty()).thenReturn(new SimpleIntegerProperty());
when(priceFeedService.getMarketPrice(anyString())).thenReturn(new MarketPrice("USD", 12684.0450, Instant.now().getEpochSecond(), true));
when(feeService.getTxFee(anyInt())).thenReturn(Coin.valueOf(1000L));
when(user.findFirstPaymentAccountWithCurrency(any())).thenReturn(paymentAccount);
when(user.getPaymentAccountsAsObservable()).thenReturn(FXCollections.observableSet());
when(securityDepositValidator.validate(any())).thenReturn(new InputValidator.ValidationResult(false));
CreateOfferDataModel dataModel = new CreateOfferDataModel(null, btcWalletService, bsqWalletService, empty, user, null, null, priceFeedService, null, null, null, feeService, bsFormatter);
dataModel.initWithData(OfferPayload.Direction.BUY, new CryptoCurrency("BTC", "bitcoin"));
dataModel.activate();
model = new CreateOfferViewModel(dataModel, null, fiatPriceValidator, altcoinValidator, btcValidator, null, securityDepositValidator, null, null, priceFeedService, null, null, bsFormatter, null);
model.activate();
}
use of bisq.core.btc.AddressEntry in project bisq-core by bisq-network.
the class BtcWalletService method getFeeEstimationTransaction.
// /////////////////////////////////////////////////////////////////////////////////////////
// Withdrawal Fee calculation
// /////////////////////////////////////////////////////////////////////////////////////////
public Transaction getFeeEstimationTransaction(String fromAddress, String toAddress, Coin amount, AddressEntry.Context context) throws AddressFormatException, AddressEntryException, InsufficientFundsException {
Optional<AddressEntry> addressEntry = findAddressEntry(fromAddress, context);
if (!addressEntry.isPresent())
throw new AddressEntryException("WithdrawFromAddress is not found in our wallet.");
checkNotNull(addressEntry.get().getAddress(), "addressEntry.get().getAddress() must nto be null");
try {
Coin fee;
int counter = 0;
int txSize = 0;
Transaction tx;
Coin txFeeForWithdrawalPerByte = getTxFeeForWithdrawalPerByte();
do {
counter++;
fee = txFeeForWithdrawalPerByte.multiply(txSize);
SendRequest sendRequest = getSendRequest(fromAddress, toAddress, amount, fee, aesKey, context);
wallet.completeTx(sendRequest);
tx = sendRequest.tx;
txSize = tx.bitcoinSerialize().length;
printTx("FeeEstimationTransaction", tx);
} while (feeEstimationNotSatisfied(counter, tx));
if (counter == 10)
log.error("Could not calculate the fee. Tx=" + tx);
return tx;
} catch (InsufficientMoneyException e) {
throw new InsufficientFundsException("The fees for that transaction exceed the available funds " + "or the resulting output value is below the min. dust value:\n" + "Missing " + (e.missing != null ? e.missing.toFriendlyString() : "null"));
}
}
use of bisq.core.btc.AddressEntry in project bisq-core by bisq-network.
the class BtcWalletService method doubleSpendTransaction.
// /////////////////////////////////////////////////////////////////////////////////////////
// Double spend unconfirmed transaction (unlock in case we got into a tx with a too low mining fee)
// /////////////////////////////////////////////////////////////////////////////////////////
public void doubleSpendTransaction(String txId, Runnable resultHandler, ErrorMessageHandler errorMessageHandler) throws InsufficientFundsException {
AddressEntry addressEntry = getOrCreateUnusedAddressEntry(AddressEntry.Context.AVAILABLE);
checkNotNull(addressEntry.getAddress(), "addressEntry.getAddress() must not be null");
Optional<Transaction> transactionOptional = wallet.getTransactions(true).stream().filter(t -> t.getHashAsString().equals(txId)).findAny();
if (transactionOptional.isPresent()) {
Transaction txToDoubleSpend = transactionOptional.get();
Address toAddress = addressEntry.getAddress();
final TransactionConfidence.ConfidenceType confidenceType = txToDoubleSpend.getConfidence().getConfidenceType();
if (confidenceType == TransactionConfidence.ConfidenceType.PENDING) {
log.debug("txToDoubleSpend no. of inputs " + txToDoubleSpend.getInputs().size());
Transaction newTransaction = new Transaction(params);
txToDoubleSpend.getInputs().stream().forEach(input -> {
final TransactionOutput connectedOutput = input.getConnectedOutput();
if (connectedOutput != null && connectedOutput.isMine(wallet) && connectedOutput.getParentTransaction() != null && connectedOutput.getParentTransaction().getConfidence() != null && input.getValue() != null) {
// if (connectedOutput.getParentTransaction().getConfidence().getConfidenceType() == TransactionConfidence.ConfidenceType.BUILDING) {
newTransaction.addInput(new TransactionInput(params, newTransaction, new byte[] {}, new TransactionOutPoint(params, input.getOutpoint().getIndex(), new Transaction(params, connectedOutput.getParentTransaction().bitcoinSerialize())), Coin.valueOf(input.getValue().value)));
/* } else {
log.warn("Confidence of parent tx is not of type BUILDING: ConfidenceType=" +
connectedOutput.getParentTransaction().getConfidence().getConfidenceType());
}*/
}
});
log.info("newTransaction no. of inputs " + newTransaction.getInputs().size());
log.info("newTransaction size in kB " + newTransaction.bitcoinSerialize().length / 1024);
if (!newTransaction.getInputs().isEmpty()) {
Coin amount = Coin.valueOf(newTransaction.getInputs().stream().mapToLong(input -> input.getValue() != null ? input.getValue().value : 0).sum());
newTransaction.addOutput(amount, toAddress);
try {
Coin fee;
int counter = 0;
int txSize = 0;
Transaction tx;
SendRequest sendRequest;
Coin txFeeForWithdrawalPerByte = getTxFeeForWithdrawalPerByte();
do {
counter++;
fee = txFeeForWithdrawalPerByte.multiply(txSize);
newTransaction.clearOutputs();
newTransaction.addOutput(amount.subtract(fee), toAddress);
sendRequest = SendRequest.forTx(newTransaction);
sendRequest.fee = fee;
sendRequest.feePerKb = Coin.ZERO;
sendRequest.ensureMinRequiredFee = false;
sendRequest.aesKey = aesKey;
sendRequest.coinSelector = new BtcCoinSelector(toAddress);
sendRequest.changeAddress = toAddress;
wallet.completeTx(sendRequest);
tx = sendRequest.tx;
txSize = tx.bitcoinSerialize().length;
printTx("FeeEstimationTransaction", tx);
sendRequest.tx.getOutputs().forEach(o -> log.debug("Output value " + o.getValue().toFriendlyString()));
} while (feeEstimationNotSatisfied(counter, tx));
if (counter == 10)
log.error("Could not calculate the fee. Tx=" + tx);
Wallet.SendResult sendResult = null;
try {
sendRequest = SendRequest.forTx(newTransaction);
sendRequest.fee = fee;
sendRequest.feePerKb = Coin.ZERO;
sendRequest.ensureMinRequiredFee = false;
sendRequest.aesKey = aesKey;
sendRequest.coinSelector = new BtcCoinSelector(toAddress);
sendRequest.changeAddress = toAddress;
sendResult = wallet.sendCoins(sendRequest);
} catch (InsufficientMoneyException e) {
// in some cases getFee did not calculate correctly and we still get an InsufficientMoneyException
log.warn("We still have a missing fee " + (e.missing != null ? e.missing.toFriendlyString() : ""));
amount = amount.subtract(e.missing);
newTransaction.clearOutputs();
newTransaction.addOutput(amount, toAddress);
sendRequest = SendRequest.forTx(newTransaction);
sendRequest.fee = fee;
sendRequest.feePerKb = Coin.ZERO;
sendRequest.ensureMinRequiredFee = false;
sendRequest.aesKey = aesKey;
sendRequest.coinSelector = new BtcCoinSelector(toAddress, false);
sendRequest.changeAddress = toAddress;
try {
sendResult = wallet.sendCoins(sendRequest);
printTx("FeeEstimationTransaction", newTransaction);
} catch (InsufficientMoneyException e2) {
errorMessageHandler.handleErrorMessage("We did not get the correct fee calculated. " + (e2.missing != null ? e2.missing.toFriendlyString() : ""));
}
}
if (sendResult != null) {
log.info("Broadcasting double spending transaction. " + sendResult.tx);
Futures.addCallback(sendResult.broadcastComplete, new FutureCallback<Transaction>() {
@Override
public void onSuccess(Transaction result) {
log.info("Double spending transaction published. " + result);
resultHandler.run();
}
@Override
public void onFailure(@NotNull Throwable t) {
log.error("Broadcasting double spending transaction failed. " + t.getMessage());
errorMessageHandler.handleErrorMessage(t.getMessage());
}
});
}
} catch (InsufficientMoneyException e) {
throw new InsufficientFundsException("The fees for that transaction exceed the available funds " + "or the resulting output value is below the min. dust value:\n" + "Missing " + (e.missing != null ? e.missing.toFriendlyString() : "null"));
}
} else {
String errorMessage = "We could not find inputs we control in the transaction we want to double spend.";
log.warn(errorMessage);
errorMessageHandler.handleErrorMessage(errorMessage);
}
} else if (confidenceType == TransactionConfidence.ConfidenceType.BUILDING) {
errorMessageHandler.handleErrorMessage("That transaction is already in the blockchain so we cannot double spend it.");
} else if (confidenceType == TransactionConfidence.ConfidenceType.DEAD) {
errorMessageHandler.handleErrorMessage("One of the inputs of that transaction has been already double spent.");
}
}
}
use of bisq.core.btc.AddressEntry in project bisq-core by bisq-network.
the class BtcWalletService method getOrCreateAddressEntry.
private AddressEntry getOrCreateAddressEntry(AddressEntry.Context context, Optional<AddressEntry> addressEntry) {
if (addressEntry.isPresent()) {
return addressEntry.get();
} else {
AddressEntry entry = addressEntryList.addAddressEntry(new AddressEntry(wallet.freshReceiveKey(), context));
saveAddressEntryList();
return entry;
}
}
use of bisq.core.btc.AddressEntry in project bisq-desktop by bisq-network.
the class MainViewModel method updateReservedBalance.
private void updateReservedBalance() {
Coin sum = Coin.valueOf(openOfferManager.getObservableList().stream().map(openOffer -> {
final Optional<AddressEntry> addressEntryOptional = btcWalletService.getAddressEntry(openOffer.getId(), AddressEntry.Context.RESERVED_FOR_TRADE);
if (addressEntryOptional.isPresent()) {
Address address = addressEntryOptional.get().getAddress();
return btcWalletService.getBalanceForAddress(address);
} else {
return null;
}
}).filter(e -> e != null).mapToLong(Coin::getValue).sum());
reservedBalance.set(formatter.formatCoinWithCode(sum));
}
Aggregations