Java Code Examples for org.bitcoinj.core.Coin#subtract()

The following examples show how to use org.bitcoinj.core.Coin#subtract() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: TransactionActivity.java    From GreenBits with GNU General Public License v3.0 6 votes vote down vote up
private void onTransactionConstructed(final Transaction tx, final Coin oldFee, final Coin newFee) {
    final Coin feeDelta = newFee.subtract(oldFee);
    final boolean skipChoice = mService.isUnderLimit(feeDelta);
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mTwoFactor = UI.popupTwoFactorChoice(TransactionActivity.this, mService, skipChoice,
                                                 new CB.Runnable1T<String>() {
                public void run(String method) {
                    if (skipChoice && mService.hasAnyTwoFactor())
                        method = "limit";
                    showIncreaseSummary(method, oldFee, newFee, tx);
                }
            });
            if (mTwoFactor != null)
                mTwoFactor.show();
        }
    });
}
 
Example 2
Source File: ProposalsView.java    From bisq with GNU Affero General Public License v3.0 6 votes vote down vote up
@Override
public void onUpdateBalances(Coin availableConfirmedBalance,
                             Coin availableNonBsqBalance,
                             Coin unverifiedBalance,
                             Coin unconfirmedChangeBalance,
                             Coin lockedForVotingBalance,
                             Coin lockupBondsBalance,
                             Coin unlockingBondsBalance) {
    Coin blindVoteFee = BlindVoteConsensus.getFee(daoStateService, daoStateService.getChainHeight());
    if (isBlindVotePhaseButNotLastBlock()) {
        Coin availableForVoting = availableConfirmedBalance.subtract(blindVoteFee);
        if (availableForVoting.isNegative())
            availableForVoting = Coin.valueOf(0);
        stakeInputTextField.setPromptText(Res.get("dao.proposal.myVote.stake.prompt",
                bsqFormatter.formatCoinWithCode(availableForVoting)));

        BsqValidator stakeInputTextFieldValidator = new BsqValidator(bsqFormatter);
        stakeInputTextFieldValidator.setMaxValue(availableForVoting);

        stakeInputTextField.setValidator(stakeInputTextFieldValidator);
    } else
        stakeInputTextField.setPromptText("");
}
 
Example 3
Source File: BtcWalletService.java    From bisq-core with GNU Affero General Public License v3.0 5 votes vote down vote up
private SendRequest getSendRequest(String fromAddress,
                                   String toAddress,
                                   Coin amount,
                                   Coin fee,
                                   @Nullable KeyParameter aesKey,
                                   AddressEntry.Context context) throws AddressFormatException,
        AddressEntryException {
    Transaction tx = new Transaction(params);
    final Coin receiverAmount = amount.subtract(fee);
    Preconditions.checkArgument(Restrictions.isAboveDust(receiverAmount),
            "The amount is too low (dust limit).");
    tx.addOutput(receiverAmount, Address.fromBase58(params, toAddress));

    SendRequest sendRequest = SendRequest.forTx(tx);
    sendRequest.fee = fee;
    sendRequest.feePerKb = Coin.ZERO;
    sendRequest.ensureMinRequiredFee = false;
    sendRequest.aesKey = aesKey;
    sendRequest.shuffleOutputs = false;
    Optional<AddressEntry> addressEntry = findAddressEntry(fromAddress, context);
    if (!addressEntry.isPresent())
        throw new AddressEntryException("WithdrawFromAddress is not found in our wallet.");

    checkNotNull(addressEntry.get(), "addressEntry.get() must not be null");
    checkNotNull(addressEntry.get().getAddress(), "addressEntry.get().getAddress() must not be null");
    sendRequest.coinSelector = new BtcCoinSelector(addressEntry.get().getAddress());
    sendRequest.changeAddress = addressEntry.get().getAddress();
    return sendRequest;
}
 
Example 4
Source File: BsqBalanceUtil.java    From bisq with GNU Affero General Public License v3.0 5 votes vote down vote up
@Override
public void onUpdateBalances(Coin availableBalance,
                             Coin availableNonBsqBalance,
                             Coin unverifiedBalance,
                             Coin unconfirmedChangeBalance,
                             Coin lockedForVotingBalance,
                             Coin lockupBondsBalance,
                             Coin unlockingBondsBalance) {
    boolean isNonBsqBalanceAvailable = availableNonBsqBalance.value > 0;

    availableBalanceTextField.setText(bsqFormatter.formatCoinWithCode(availableBalance));
    Coin verified = availableBalance.subtract(unconfirmedChangeBalance);
    verifiedBalanceTextField.setText(bsqFormatter.formatCoinWithCode(verified));
    unconfirmedChangTextField.setText(bsqFormatter.formatCoinWithCode(unconfirmedChangeBalance));
    unverifiedBalanceTextField.setText(bsqFormatter.formatCoinWithCode(unverifiedBalance));

    lockedForVoteBalanceTextField.setText(bsqFormatter.formatCoinWithCode(lockedForVotingBalance));
    lockedInBondsBalanceTextField.setText(bsqFormatter.formatCoinWithCode(
            lockupBondsBalance.add(unlockingBondsBalance)));
    if (lockupAmountTextField != null && unlockingAmountTextField != null) {
        lockupAmountTextField.setText(bsqFormatter.formatCoinWithCode(lockupBondsBalance));
        unlockingAmountTextField.setText(bsqFormatter.formatCoinWithCode(unlockingBondsBalance));
    }

    availableNonBsqBalanceLabel.setVisible(isNonBsqBalanceAvailable);
    availableNonBsqBalanceLabel.setManaged(isNonBsqBalanceAvailable);
    availableNonBsqBalanceTextField.setVisible(isNonBsqBalanceAvailable);
    availableNonBsqBalanceTextField.setManaged(isNonBsqBalanceAvailable);
    availableNonBsqBalanceTextField.setText(bsqFormatter.formatBTCWithCode(availableNonBsqBalance.value));
    String bsqSatoshi = bsqFormatter.formatBSQSatoshisWithCode(daoFacade.getAvailableMerit());
    reputationBalanceTextField.setText(bsqSatoshi);
}
 
Example 5
Source File: TakeOfferDataModel.java    From bisq with GNU Affero General Public License v3.0 5 votes vote down vote up
public Coin getTotalTxFee() {
    Coin totalTxFees = txFeeFromFeeService.add(getTxFeeForDepositTx()).add(getTxFeeForPayoutTx());
    if (isCurrencyForTakerFeeBtc())
        return totalTxFees;
    else
        return totalTxFees.subtract(getTakerFee() != null ? getTakerFee() : Coin.ZERO);
}
 
Example 6
Source File: BuyerAsTakerCreatesDepositTxInputs.java    From bisq with GNU Affero General Public License v3.0 5 votes vote down vote up
@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 = checkNotNull(trade.getOffer()).getBuyerSecurityDeposit()
                .add(txFee)
                .add(txFee)
                .subtract(bsqTakerFee);
        Coin fee = txFee.subtract(bsqTakerFee);
        InputsAndChangeOutput result = processModel.getTradeWalletService().takerCreatesDepositTxInputs(
                processModel.getTakeOfferFeeTx(),
                takerInputAmount,
                fee);
        processModel.setRawTransactionInputs(result.rawTransactionInputs);
        processModel.setChangeOutputValue(result.changeOutputValue);
        processModel.setChangeOutputAddress(result.changeOutputAddress);

        complete();
    } catch (Throwable t) {
        failed(t);
    }
}
 
Example 7
Source File: BtcWalletService.java    From bisq with GNU Affero General Public License v3.0 5 votes vote down vote up
private SendRequest getSendRequest(String fromAddress,
                                   String toAddress,
                                   Coin amount,
                                   Coin fee,
                                   @Nullable KeyParameter aesKey,
                                   AddressEntry.Context context) throws AddressFormatException,
        AddressEntryException {
    Transaction tx = new Transaction(params);
    final Coin receiverAmount = amount.subtract(fee);
    Preconditions.checkArgument(Restrictions.isAboveDust(receiverAmount),
            "The amount is too low (dust limit).");
    tx.addOutput(receiverAmount, Address.fromBase58(params, toAddress));

    SendRequest sendRequest = SendRequest.forTx(tx);
    sendRequest.fee = fee;
    sendRequest.feePerKb = Coin.ZERO;
    sendRequest.ensureMinRequiredFee = false;
    sendRequest.aesKey = aesKey;
    sendRequest.shuffleOutputs = false;
    Optional<AddressEntry> addressEntry = findAddressEntry(fromAddress, context);
    if (!addressEntry.isPresent())
        throw new AddressEntryException("WithdrawFromAddress is not found in our wallet.");

    checkNotNull(addressEntry.get(), "addressEntry.get() must not be null");
    checkNotNull(addressEntry.get().getAddress(), "addressEntry.get().getAddress() must not be null");
    sendRequest.coinSelector = new BtcCoinSelector(addressEntry.get().getAddress(), preferences.getIgnoreDustThreshold());
    sendRequest.changeAddress = addressEntry.get().getAddress();
    return sendRequest;
}
 
Example 8
Source File: TradeWalletService.java    From bisq-core with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * 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);
}
 
Example 9
Source File: Verifier.java    From GreenBits with GNU General Public License v3.0 4 votes vote down vote up
static Coin verify(final GaService service,
                   final Map<TransactionOutPoint, Coin> countedUtxoValues, final PreparedTransaction ptx,
                   final Address recipient, final Coin amount, final List<Boolean> input) {
    final int changeIdx;
    if (input == null)
        changeIdx = -1;
    else if (input.get(0))
        changeIdx = 0;
    else if (input.get(1))
        changeIdx = 1;
    else
        throw new IllegalArgumentException("Verification: Change output missing.");

    if (input != null && input.get(0) && input.get(1)) {
        // Shouldn't happen really. In theory user can send money to a new change address
        // of themselves which they've generated manually, but it's unlikely, so for
        // simplicity we don't handle it.
        throw new IllegalArgumentException("Verification: Cannot send to a change address.");
    }
    final TransactionOutput output = ptx.mDecoded.getOutputs().get(1 - Math.abs(changeIdx));
    if (recipient != null) {
        final Address gotAddress = output.getScriptPubKey().getToAddress(service.getNetworkParameters());
        if (!gotAddress.equals(recipient))
            throw new IllegalArgumentException("Verification: Invalid recipient address.");
    }
    if (amount != null && !output.getValue().equals(amount))
        throw new IllegalArgumentException("Verification: Invalid output amount.");

    // 3. Verify fee value
    Coin fee = Coin.ZERO;
    for (final TransactionInput in : ptx.mDecoded.getInputs()) {
        if (countedUtxoValues.get(in.getOutpoint()) != null) {
            fee = fee.add(countedUtxoValues.get(in.getOutpoint()));
            continue;
        }

        final Transaction prevTx = ptx.mPrevoutRawTxs.get(in.getOutpoint().getHash().toString());
        if (!prevTx.getHash().equals(in.getOutpoint().getHash()))
            throw new IllegalArgumentException("Verification: Prev tx hash invalid");
        fee = fee.add(prevTx.getOutput((int) in.getOutpoint().getIndex()).getValue());
    }
    for (final TransactionOutput out : ptx.mDecoded.getOutputs())
        fee = fee.subtract(out.getValue());

    final double messageSize = ptx.mDecoded.getMessageSize();
    final double satoshiPerByte = fee.value / messageSize;
    final double satoshiPerKiloByte = satoshiPerByte * 1000.0;
    final Coin feeRate = Coin.valueOf((int) satoshiPerKiloByte);

    final Coin minFeeRate = service.getMinFeeRate();
    if (feeRate.isLessThan(minFeeRate) && service.getNetworkParameters() != RegTestParams.get())
        feeError("small", feeRate, minFeeRate);

    final Coin maxFeeRate = Coin.valueOf(15000 * 1000); // FIXME: Get max fee rate from server
    if (feeRate.isGreaterThan(maxFeeRate))
        feeError("large", feeRate, maxFeeRate);

    return amount == null ? output.getValue() : fee;
}
 
Example 10
Source File: TransactionActivity.java    From GreenBits with GNU General Public License v3.0 4 votes vote down vote up
private static Pair<Integer, JSONMap>
createRawTransaction(final GaService service,
                     final Transaction tx, final List<JSONMap> usedUtxos,
                     final List<JSONMap> utxos, final int subAccount,
                     GATx.ChangeOutput changeOutput,
                     final Coin amount, final Coin oldFee,
                     final Coin feeRate,
                     final JSONMap privateData, final boolean sendAll) {

    final boolean isRBF = usedUtxos != null;
    final boolean haveExistingChange = changeOutput != null;
    Coin total =  isRBF ? getUtxoSum(usedUtxos) : Coin.ZERO;
    Coin fee;

    // First add inputs until we cover the amount to send
    while ((sendAll || total.isLessThan(amount)) && !utxos.isEmpty())
        total = total.add(GATx.addUtxo(service, tx, utxos, usedUtxos));

    // Then add inputs until we cover amount + fee/change
    while (true) {
        fee = GATx.getTxFee(service, tx, feeRate);
        if (isRBF) {
            final Coin bandwidthFee = GATx.getTxFee(service, tx, service.getMinFeeRate());
            fee = (fee.isLessThan(oldFee) ? oldFee : fee).add(bandwidthFee);
        }

        final Coin minChange = changeOutput == null ? Coin.ZERO : service.getDustThreshold();
        final int cmp = sendAll ? 0 : total.compareTo(amount.add(fee).add(minChange));
        if (cmp < 0) {
            // Need more inputs to cover amount + fee/change
            if (utxos.isEmpty())
                return createFailed(R.string.insufficientFundsText); // None left, fail

            total = total.add(GATx.addUtxo(service, tx, utxos, usedUtxos));
            continue;
        }

        if (cmp == 0 || changeOutput != null) {
            // Inputs exactly match amount + fee/change, or are greater
            // and we have a change output for the excess
            break;
        }

        // Inputs greater than amount + fee, add a change output and try again
        changeOutput = GATx.addChangeOutput(service, tx, subAccount);
        if (changeOutput == null)
            return createFailed(R.string.unable_to_create_change);
    }

    boolean randomizedChange = false;
    if (changeOutput != null) {
        // Set the value of the change output
        if (tx.getOutputs().size() == 1)
            changeOutput.mOutput.setValue(total.subtract(fee)); // Redeposit
        else
            changeOutput.mOutput.setValue(total.subtract(amount).subtract(fee));
        if (haveExistingChange)
            randomizedChange = changeOutput.mOutput == tx.getOutput(0);
        else
            randomizedChange = GATx.randomizeChangeOutput(tx);
    }

    if (sendAll) {
        final Coin actualAmount = total.subtract(fee);
        if (!actualAmount.isGreaterThan(Coin.ZERO))
            return createFailed(R.string.insufficientFundsText);
        final int amtIndex = tx.getOutputs().size() == 1 ? 0 : (randomizedChange ? 1 : 0);
        tx.getOutput(amtIndex).setValue(actualAmount);
    }

    tx.setLockTime(service.getCurrentBlock()); // Prevent fee sniping

    int changeIndex = -1;
    if (changeOutput != null && tx.getOutputs().size() != 1)
        changeIndex = randomizedChange ? 0 : 1;
    return new Pair<>(0,
                      GATx.makeLimitsData(fee.subtract(oldFee), fee, changeIndex));
}
 
Example 11
Source File: SendFragment.java    From GreenBits with GNU General Public License v3.0 4 votes vote down vote up
private int createRawTransaction(final List<JSONMap> utxos, final String recipient,
                                 final Coin amount, final JSONMap privateData,
                                 final boolean sendAll, final Coin feeRate) {
    final GaService service = getGAService();

    if (service.isElements())
        return createRawElementsTransaction(utxos, recipient, amount, privateData, sendAll, feeRate);

    final GaActivity gaActivity = getGaActivity();

    final List<JSONMap> usedUtxos = new ArrayList<>();

    final Transaction tx = new Transaction(service.getNetworkParameters());

    if (!GATx.addTxOutput(service, tx, amount, recipient))
        return R.string.invalidAddress;

    Coin total = Coin.ZERO;
    Coin fee;
    boolean randomizedChange = false;
    GATx.ChangeOutput changeOutput = null;

    // First add inputs until we cover the amount to send
    while ((sendAll || total.isLessThan(amount)) && !utxos.isEmpty())
        total = total.add(GATx.addUtxo(service, tx, utxos, usedUtxos));

    // Then add inputs until we cover amount + fee/change
    while (true) {
        fee = GATx.getTxFee(service, tx, feeRate);

        final Coin minChange = changeOutput == null ? Coin.ZERO : service.getDustThreshold();
        final int cmp = sendAll ? 0 : total.compareTo(amount.add(fee).add(minChange));
        if (cmp < 0) {
            // Need more inputs to cover amount + fee/change
            if (utxos.isEmpty())
                return R.string.insufficientFundsText; // None left, fail

            total = total.add(GATx.addUtxo(service, tx, utxos, usedUtxos));
            continue;
        }

        if (cmp == 0 || changeOutput != null) {
            // Inputs exactly match amount + fee/change, or are greater
            // and we have a change output for the excess
            break;
        }

        // Inputs greater than amount + fee, add a change output and try again
        changeOutput = GATx.addChangeOutput(service, tx, mSubaccount);
        if (changeOutput == null)
            return R.string.unable_to_create_change;
    }

    if (changeOutput != null) {
        // Set the value of the change output
        changeOutput.mOutput.setValue(total.subtract(amount).subtract(fee));
        randomizedChange = GATx.randomizeChangeOutput(tx);
    }

    final Coin actualAmount;
    if (!sendAll)
        actualAmount = amount;
    else {
        actualAmount = total.subtract(fee);
        if (!actualAmount.isGreaterThan(Coin.ZERO))
            return R.string.insufficientFundsText;
        tx.getOutput(randomizedChange ? 1 : 0).setValue(actualAmount);
    }

    tx.setLockTime(service.getCurrentBlock()); // Prevent fee sniping

    final PreparedTransaction ptx;
    ptx = GATx.signTransaction(service, tx, usedUtxos, mSubaccount, changeOutput);

    final int changeIndex = changeOutput == null ? -1 : (randomizedChange ? 0 : 1);
    final JSONMap underLimits = GATx.makeLimitsData(actualAmount.add(fee), fee, changeIndex);

    final boolean skipChoice = service.isUnderLimit(underLimits.getCoin("amount"));
    final Coin sendFee = fee;
    gaActivity.runOnUiThread(new Runnable() {
        public void run() {
            mSendButton.setEnabled(true);
            mTwoFactor = UI.popupTwoFactorChoice(gaActivity, service, skipChoice,
                                                 new CB.Runnable1T<String>() {
                public void run(String method) {
                    if (skipChoice && service.hasAnyTwoFactor())
                        method = "limit";
                    onTransactionValidated(null, tx, recipient, actualAmount,
                                           method, sendFee, privateData, underLimits);
                }
            });
            if (mTwoFactor != null)
                mTwoFactor.show();
        }
    });
    return 0;
}
 
Example 12
Source File: TradeWalletService.java    From bisq with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * The taker creates a dummy transaction to get the input(s) and optional change output for the amount and the
 * taker's address for that trade. That will be used to send to the maker for creating the deposit transaction.
 *
 * @param takeOfferFeeTx the take offer fee tx
 * @param inputAmount    amount of takers input
 * @param txFee          mining fee
 * @return a data container holding the inputs, the output value and address
 * @throws TransactionVerificationException if there was an unexpected problem with the created dummy tx
 */
public InputsAndChangeOutput takerCreatesDepositTxInputs(Transaction takeOfferFeeTx,
                                                         Coin inputAmount,
                                                         Coin txFee)
        throws TransactionVerificationException {
    // 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]  input from taker fee tx > inputAmount (including tx fee) (unsigned)
     OUT[0] dummyOutputAmount (inputAmount - tx fee)

     We are only interested in the inputs.
     We get the exact input value from the taker fee tx so we don't create a 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.

    // We created the take offer fee tx in the structure that the second output is for the funds for the deposit tx.
    TransactionOutput reservedForTradeOutput = takeOfferFeeTx.getOutputs().get(1);
    dummyTX.addInput(reservedForTradeOutput);

    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());


    // TODO changeOutputValue and changeOutputAddress is not used as taker spends exact amount from fee tx.
    // Change is handled already at the fee tx creation so the handling of a change output for the deposit tx
    // can be removed here. We still keep it atm as we prefer to not introduce a larger
    // refactoring. When new trade protocol gets implemented this can be cleaned.
    // The maker though can have a change output if the taker takes less as the max. offer amount!
    return new InputsAndChangeOutput(new ArrayList<>(rawTransactionInputList), 0, null);
}