use of bisq.core.btc.data.InputsAndChangeOutput in project bisq-core by bisq-network.
the class SellerAsTakerCreatesDepositTxInputs method run.
@Override
protected void run() {
try {
runInterceptHook();
if (trade.getTradeAmount() != null) {
Coin txFee = trade.getTxFee();
Coin takerInputAmount = trade.getOffer().getSellerSecurityDeposit().add(txFee).add(txFee).add(trade.getTradeAmount());
BtcWalletService walletService = processModel.getBtcWalletService();
Address takersAddress = walletService.getOrCreateAddressEntry(processModel.getOffer().getId(), AddressEntry.Context.RESERVED_FOR_TRADE).getAddress();
Address takersChangeAddress = walletService.getOrCreateAddressEntry(AddressEntry.Context.AVAILABLE).getAddress();
InputsAndChangeOutput result = processModel.getTradeWalletService().takerCreatesDepositsTxInputs(takerInputAmount, txFee, takersAddress, takersChangeAddress);
processModel.setRawTransactionInputs(result.rawTransactionInputs);
processModel.setChangeOutputValue(result.changeOutputValue);
processModel.setChangeOutputAddress(result.changeOutputAddress);
complete();
} else {
failed("trade.getTradeAmount() = null");
}
} catch (Throwable t) {
failed(t);
}
}
use of bisq.core.btc.data.InputsAndChangeOutput in project bisq-core by bisq-network.
the class BuyerAsTakerCreatesDepositTxInputs method run.
@Override
protected void run() {
try {
runInterceptHook();
// In case we pay the taker fee in bsq we reduce tx fee by that as the burned bsq satoshis goes to miners.
Coin bsqTakerFee = trade.isCurrencyForTakerFeeBtc() ? Coin.ZERO : trade.getTakerFee();
Coin txFee = trade.getTxFee();
Coin takerInputAmount = trade.getOffer().getBuyerSecurityDeposit().add(txFee).add(txFee).subtract(bsqTakerFee);
BtcWalletService walletService = processModel.getBtcWalletService();
Address takersAddress = walletService.getOrCreateAddressEntry(processModel.getOffer().getId(), AddressEntry.Context.RESERVED_FOR_TRADE).getAddress();
Address takersChangeAddress = walletService.getOrCreateAddressEntry(AddressEntry.Context.AVAILABLE).getAddress();
InputsAndChangeOutput result = processModel.getTradeWalletService().takerCreatesDepositsTxInputs(takerInputAmount, txFee.subtract(bsqTakerFee), takersAddress, takersChangeAddress);
processModel.setRawTransactionInputs(result.rawTransactionInputs);
processModel.setChangeOutputValue(result.changeOutputValue);
processModel.setChangeOutputAddress(result.changeOutputAddress);
complete();
} catch (Throwable t) {
failed(t);
}
}
use of bisq.core.btc.data.InputsAndChangeOutput in project bisq-core by bisq-network.
the class TradeWalletService method takerCreatesDepositsTxInputs.
// /////////////////////////////////////////////////////////////////////////////////////////
// Trade
// /////////////////////////////////////////////////////////////////////////////////////////
// We construct the deposit transaction in the way that the buyer is always the first entry (inputs, outputs, MS keys) and then the seller.
// In the creation of the deposit tx the taker/maker roles are the determining roles instead of buyer/seller.
// In the payout tx is is the buyer/seller role. We keep the buyer/seller ordering over all transactions to not get confusion with ordering,
// which is important to follow correctly specially for the order of the MS keys.
/**
* The taker creates a dummy transaction to get the input(s) and optional change output for the amount and the takersAddress for that trade.
* That will be used to send to the maker for creating the deposit transaction.
*
* @param inputAmount Amount of takers input
* @param txFee Mining fee
* @param takersAddress Address of taker
* @return A data container holding the inputs, the output value and address
* @throws TransactionVerificationException
* @throws WalletException
*/
public InputsAndChangeOutput takerCreatesDepositsTxInputs(Coin inputAmount, Coin txFee, Address takersAddress, Address takersChangeAddress) throws TransactionVerificationException, WalletException {
log.debug("takerCreatesDepositsTxInputs called");
log.debug("inputAmount " + inputAmount.toFriendlyString());
log.debug("txFee " + txFee.toFriendlyString());
log.debug("takersAddress " + takersAddress.toString());
// We add the mining fee 2 times to the deposit tx:
// 1. Will be spent when publishing the deposit tx (paid by buyer)
// 2. Will be added to the MS amount, so when publishing the payout tx the fee is already there and the outputs are not changed by fee reduction
// The fee for the payout will be paid by the seller.
/*
The tx we create has that structure:
IN[0] any input > inputAmount (including tx fee) (unsigned)
IN[1...n] optional inputs supported, but normally there is just 1 input (unsigned)
OUT[0] dummyOutputAmount (inputAmount - tx fee)
OUT[1] Optional Change = inputAmount - dummyOutputAmount - tx fee
We are only interested in the inputs and the optional change output.
*/
// inputAmount includes the tx fee. So we subtract the fee to get the dummyOutputAmount.
Coin dummyOutputAmount = inputAmount.subtract(txFee);
Transaction dummyTX = new Transaction(params);
// The output is just used to get the right inputs and change outputs, so we use an anonymous ECKey, as it will never be used for anything.
// We don't care about fee calculation differences between the real tx and that dummy tx as we use a static tx fee.
TransactionOutput dummyOutput = new TransactionOutput(params, dummyTX, dummyOutputAmount, new ECKey().toAddress(params));
dummyTX.addOutput(dummyOutput);
// Find the needed inputs to pay the output, optionally add 1 change output.
// Normally only 1 input and no change output is used, but we support multiple inputs and 1 change output.
// Our spending transaction output is from the create offer fee payment.
addAvailableInputsAndChangeOutputs(dummyTX, takersAddress, takersChangeAddress, txFee);
// The completeTx() call signs the input, but we don't want to pass over signed tx inputs so we remove the signature
WalletService.removeSignatures(dummyTX);
WalletService.verifyTransaction(dummyTX);
// WalletService.printTx("dummyTX", dummyTX);
List<RawTransactionInput> rawTransactionInputList = dummyTX.getInputs().stream().map(e -> {
checkNotNull(e.getConnectedOutput(), "e.getConnectedOutput() must not be null");
checkNotNull(e.getConnectedOutput().getParentTransaction(), "e.getConnectedOutput().getParentTransaction() must not be null");
checkNotNull(e.getValue(), "e.getValue() must not be null");
return getRawInputFromTransactionInput(e);
}).collect(Collectors.toList());
// We don't support more then 1 change outputs, so there are max. 2 outputs
checkArgument(dummyTX.getOutputs().size() < 3);
// Only interested in optional change output, the dummy output at index 0 is ignored (that's why we use index 1)
TransactionOutput changeOutput = dummyTX.getOutputs().size() == 2 ? dummyTX.getOutputs().get(1) : null;
long changeOutputValue = 0L;
String changeOutputAddress = null;
if (changeOutput != null) {
changeOutputValue = changeOutput.getValue().getValue();
Address addressFromP2PKHScript = changeOutput.getAddressFromP2PKHScript(params);
checkNotNull(addressFromP2PKHScript, "changeOutput.getAddressFromP2PKHScript(params) must not be null");
changeOutputAddress = addressFromP2PKHScript.toString();
}
return new InputsAndChangeOutput(new ArrayList<>(rawTransactionInputList), changeOutputValue, changeOutputAddress);
}
Aggregations