mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-11-01 21:17:13 +00:00
Wallet: Make SendRequest a top level class.
This commit is contained in:
@@ -26,6 +26,7 @@ import org.bitcoinj.core.*;
|
|||||||
import org.bitcoinj.crypto.TransactionSignature;
|
import org.bitcoinj.crypto.TransactionSignature;
|
||||||
import org.bitcoinj.script.Script;
|
import org.bitcoinj.script.Script;
|
||||||
import org.bitcoinj.utils.Threading;
|
import org.bitcoinj.utils.Threading;
|
||||||
|
import org.bitcoinj.wallet.SendRequest;
|
||||||
import org.bitcoinj.wallet.Wallet;
|
import org.bitcoinj.wallet.Wallet;
|
||||||
import org.bitcoinj.wallet.listeners.WalletCoinsReceivedEventListener;
|
import org.bitcoinj.wallet.listeners.WalletCoinsReceivedEventListener;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -239,7 +240,7 @@ public abstract class PaymentChannelClientState {
|
|||||||
* channel. For example if you want it to only use specific coins, you can adjust the coin selector here.
|
* channel. For example if you want it to only use specific coins, you can adjust the coin selector here.
|
||||||
* The default implementation does nothing.
|
* The default implementation does nothing.
|
||||||
*/
|
*/
|
||||||
protected void editContractSendRequest(Wallet.SendRequest req) {
|
protected void editContractSendRequest(SendRequest req) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.bitcoinj.protocols.channels;
|
package org.bitcoinj.protocols.channels;
|
||||||
|
|
||||||
|
import org.bitcoinj.wallet.SendRequest;
|
||||||
import org.bitcoinj.wallet.Wallet;
|
import org.bitcoinj.wallet.Wallet;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
@@ -215,13 +216,13 @@ public abstract class PaymentChannelServerState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a payment transaction with valueToMe going back to us
|
// Create a payment transaction with valueToMe going back to us
|
||||||
protected synchronized Wallet.SendRequest makeUnsignedChannelContract(Coin valueToMe) {
|
protected synchronized SendRequest makeUnsignedChannelContract(Coin valueToMe) {
|
||||||
Transaction tx = new Transaction(wallet.getParams());
|
Transaction tx = new Transaction(wallet.getParams());
|
||||||
if (!getTotalValue().subtract(valueToMe).equals(Coin.ZERO)) {
|
if (!getTotalValue().subtract(valueToMe).equals(Coin.ZERO)) {
|
||||||
tx.addOutput(getTotalValue().subtract(valueToMe), getClientKey().toAddress(wallet.getParams()));
|
tx.addOutput(getTotalValue().subtract(valueToMe), getClientKey().toAddress(wallet.getParams()));
|
||||||
}
|
}
|
||||||
tx.addInput(contract.getOutput(0));
|
tx.addInput(contract.getOutput(0));
|
||||||
return Wallet.SendRequest.forTx(tx);
|
return SendRequest.forTx(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -248,7 +249,7 @@ public abstract class PaymentChannelServerState {
|
|||||||
if (newValueToMe.compareTo(bestValueToMe) < 0)
|
if (newValueToMe.compareTo(bestValueToMe) < 0)
|
||||||
throw new ValueOutOfRangeException("Attempt to roll back payment on the channel.");
|
throw new ValueOutOfRangeException("Attempt to roll back payment on the channel.");
|
||||||
|
|
||||||
Wallet.SendRequest req = makeUnsignedChannelContract(newValueToMe);
|
SendRequest req = makeUnsignedChannelContract(newValueToMe);
|
||||||
|
|
||||||
if (!fullyUsedUp && refundSize.isLessThan(req.tx.getOutput(0).getMinNonDustValue()))
|
if (!fullyUsedUp && refundSize.isLessThan(req.tx.getOutput(0).getMinNonDustValue()))
|
||||||
throw new ValueOutOfRangeException("Attempt to refund negative value or value too small to be accepted by the network");
|
throw new ValueOutOfRangeException("Attempt to refund negative value or value too small to be accepted by the network");
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.bitcoinj.crypto.TransactionSignature;
|
|||||||
import org.bitcoinj.script.Script;
|
import org.bitcoinj.script.Script;
|
||||||
import org.bitcoinj.script.ScriptBuilder;
|
import org.bitcoinj.script.ScriptBuilder;
|
||||||
import org.bitcoinj.wallet.AllowUnconfirmedCoinSelector;
|
import org.bitcoinj.wallet.AllowUnconfirmedCoinSelector;
|
||||||
|
import org.bitcoinj.wallet.SendRequest;
|
||||||
import org.bitcoinj.wallet.Wallet;
|
import org.bitcoinj.wallet.Wallet;
|
||||||
import org.spongycastle.crypto.params.KeyParameter;
|
import org.spongycastle.crypto.params.KeyParameter;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
@@ -136,7 +137,7 @@ public class PaymentChannelV1ClientState extends PaymentChannelClientState {
|
|||||||
TransactionOutput multisigOutput = template.addOutput(totalValue, ScriptBuilder.createMultiSigOutputScript(2, keys));
|
TransactionOutput multisigOutput = template.addOutput(totalValue, ScriptBuilder.createMultiSigOutputScript(2, keys));
|
||||||
if (multisigOutput.isDust())
|
if (multisigOutput.isDust())
|
||||||
throw new ValueOutOfRangeException("totalValue too small to use");
|
throw new ValueOutOfRangeException("totalValue too small to use");
|
||||||
Wallet.SendRequest req = Wallet.SendRequest.forTx(template);
|
SendRequest req = SendRequest.forTx(template);
|
||||||
req.coinSelector = AllowUnconfirmedCoinSelector.get();
|
req.coinSelector = AllowUnconfirmedCoinSelector.get();
|
||||||
editContractSendRequest(req);
|
editContractSendRequest(req);
|
||||||
req.shuffleOutputs = false; // TODO: Fix things so shuffling is usable.
|
req.shuffleOutputs = false; // TODO: Fix things so shuffling is usable.
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.bitcoinj.core.*;
|
|||||||
import org.bitcoinj.crypto.TransactionSignature;
|
import org.bitcoinj.crypto.TransactionSignature;
|
||||||
import org.bitcoinj.script.Script;
|
import org.bitcoinj.script.Script;
|
||||||
import org.bitcoinj.script.ScriptBuilder;
|
import org.bitcoinj.script.ScriptBuilder;
|
||||||
|
import org.bitcoinj.wallet.SendRequest;
|
||||||
import org.bitcoinj.wallet.Wallet;
|
import org.bitcoinj.wallet.Wallet;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
@@ -210,7 +211,7 @@ public class PaymentChannelV1ServerState extends PaymentChannelServerState {
|
|||||||
}
|
}
|
||||||
Transaction tx = null;
|
Transaction tx = null;
|
||||||
try {
|
try {
|
||||||
Wallet.SendRequest req = makeUnsignedChannelContract(bestValueToMe);
|
SendRequest req = makeUnsignedChannelContract(bestValueToMe);
|
||||||
tx = req.tx;
|
tx = req.tx;
|
||||||
// Provide a throwaway signature so that completeTx won't complain out about unsigned inputs it doesn't
|
// Provide a throwaway signature so that completeTx won't complain out about unsigned inputs it doesn't
|
||||||
// know how to sign. Note that this signature does actually have to be valid, so we can't use a dummy
|
// know how to sign. Note that this signature does actually have to be valid, so we can't use a dummy
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.bitcoinj.crypto.TransactionSignature;
|
|||||||
import org.bitcoinj.script.Script;
|
import org.bitcoinj.script.Script;
|
||||||
import org.bitcoinj.script.ScriptBuilder;
|
import org.bitcoinj.script.ScriptBuilder;
|
||||||
import org.bitcoinj.wallet.AllowUnconfirmedCoinSelector;
|
import org.bitcoinj.wallet.AllowUnconfirmedCoinSelector;
|
||||||
|
import org.bitcoinj.wallet.SendRequest;
|
||||||
import org.bitcoinj.wallet.Wallet;
|
import org.bitcoinj.wallet.Wallet;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -110,7 +111,7 @@ public class PaymentChannelV2ClientState extends PaymentChannelClientState {
|
|||||||
ScriptBuilder.createP2SHOutputScript(redeemScript));
|
ScriptBuilder.createP2SHOutputScript(redeemScript));
|
||||||
if (transactionOutput.isDust())
|
if (transactionOutput.isDust())
|
||||||
throw new ValueOutOfRangeException("totalValue too small to use");
|
throw new ValueOutOfRangeException("totalValue too small to use");
|
||||||
Wallet.SendRequest req = Wallet.SendRequest.forTx(template);
|
SendRequest req = SendRequest.forTx(template);
|
||||||
req.coinSelector = AllowUnconfirmedCoinSelector.get();
|
req.coinSelector = AllowUnconfirmedCoinSelector.get();
|
||||||
editContractSendRequest(req);
|
editContractSendRequest(req);
|
||||||
req.shuffleOutputs = false; // TODO: Fix things so shuffling is usable.
|
req.shuffleOutputs = false; // TODO: Fix things so shuffling is usable.
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.bitcoinj.core.*;
|
|||||||
import org.bitcoinj.crypto.TransactionSignature;
|
import org.bitcoinj.crypto.TransactionSignature;
|
||||||
import org.bitcoinj.script.Script;
|
import org.bitcoinj.script.Script;
|
||||||
import org.bitcoinj.script.ScriptBuilder;
|
import org.bitcoinj.script.ScriptBuilder;
|
||||||
|
import org.bitcoinj.wallet.SendRequest;
|
||||||
import org.bitcoinj.wallet.Wallet;
|
import org.bitcoinj.wallet.Wallet;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -165,7 +166,7 @@ public class PaymentChannelV2ServerState extends PaymentChannelServerState {
|
|||||||
}
|
}
|
||||||
Transaction tx = null;
|
Transaction tx = null;
|
||||||
try {
|
try {
|
||||||
Wallet.SendRequest req = makeUnsignedChannelContract(bestValueToMe);
|
SendRequest req = makeUnsignedChannelContract(bestValueToMe);
|
||||||
tx = req.tx;
|
tx = req.tx;
|
||||||
// Provide a throwaway signature so that completeTx won't complain out about unsigned inputs it doesn't
|
// Provide a throwaway signature so that completeTx won't complain out about unsigned inputs it doesn't
|
||||||
// know how to sign. Note that this signature does actually have to be valid, so we can't use a dummy
|
// know how to sign. Note that this signature does actually have to be valid, so we can't use a dummy
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import org.bitcoinj.params.MainNetParams;
|
|||||||
import org.bitcoinj.protocols.payments.PaymentProtocol.PkiVerificationData;
|
import org.bitcoinj.protocols.payments.PaymentProtocol.PkiVerificationData;
|
||||||
import org.bitcoinj.uri.BitcoinURI;
|
import org.bitcoinj.uri.BitcoinURI;
|
||||||
import org.bitcoinj.utils.Threading;
|
import org.bitcoinj.utils.Threading;
|
||||||
import org.bitcoinj.wallet.Wallet;
|
import org.bitcoinj.wallet.SendRequest;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
@@ -293,13 +293,13 @@ public class PaymentSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@link Wallet.SendRequest} suitable for broadcasting to the network.
|
* Returns a {@link SendRequest} suitable for broadcasting to the network.
|
||||||
*/
|
*/
|
||||||
public Wallet.SendRequest getSendRequest() {
|
public SendRequest getSendRequest() {
|
||||||
Transaction tx = new Transaction(params);
|
Transaction tx = new Transaction(params);
|
||||||
for (Protos.Output output : paymentDetails.getOutputsList())
|
for (Protos.Output output : paymentDetails.getOutputsList())
|
||||||
tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(output.getAmount()), output.getScript().toByteArray()));
|
tx.addOutput(new TransactionOutput(params, tx, Coin.valueOf(output.getAmount()), output.getScript().toByteArray()));
|
||||||
return Wallet.SendRequest.forTx(tx).fromPaymentDetails(paymentDetails);
|
return SendRequest.forTx(tx).fromPaymentDetails(paymentDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public interface EncryptableKeyChain extends KeyChain {
|
|||||||
/**
|
/**
|
||||||
* Decrypt the key chain with the given AES key and whatever {@link KeyCrypter} is already set. Note that if you
|
* Decrypt the key chain with the given AES key and whatever {@link KeyCrypter} is already set. Note that if you
|
||||||
* just want to spend money from an encrypted wallet, don't decrypt the whole thing first. Instead, set the
|
* just want to spend money from an encrypted wallet, don't decrypt the whole thing first. Instead, set the
|
||||||
* {@link org.bitcoinj.wallet.Wallet.SendRequest#aesKey} field before asking the wallet to build the send.
|
* {@link org.bitcoinj.wallet.SendRequest#aesKey} field before asking the wallet to build the send.
|
||||||
*
|
*
|
||||||
* @param aesKey AES key to use (normally created using KeyCrypter#deriveKey and cached as it is time consuming to
|
* @param aesKey AES key to use (normally created using KeyCrypter#deriveKey and cached as it is time consuming to
|
||||||
* create from a password)
|
* create from a password)
|
||||||
|
|||||||
267
core/src/main/java/org/bitcoinj/wallet/SendRequest.java
Normal file
267
core/src/main/java/org/bitcoinj/wallet/SendRequest.java
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013 Google Inc.
|
||||||
|
* Copyright 2014 Andreas Schildbach
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.bitcoinj.wallet;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.bitcoin.protocols.payments.Protos.PaymentDetails;
|
||||||
|
import org.bitcoinj.core.Address;
|
||||||
|
import org.bitcoinj.core.Coin;
|
||||||
|
import org.bitcoinj.core.Context;
|
||||||
|
import org.bitcoinj.core.ECKey;
|
||||||
|
import org.bitcoinj.core.NetworkParameters;
|
||||||
|
import org.bitcoinj.core.Transaction;
|
||||||
|
import org.bitcoinj.core.TransactionOutput;
|
||||||
|
import org.bitcoinj.script.Script;
|
||||||
|
import org.bitcoinj.script.ScriptBuilder;
|
||||||
|
import org.bitcoinj.utils.ExchangeRate;
|
||||||
|
import org.bitcoinj.wallet.KeyChain.KeyPurpose;
|
||||||
|
import org.bitcoinj.wallet.Wallet.MissingSigsMode;
|
||||||
|
import org.spongycastle.crypto.params.KeyParameter;
|
||||||
|
|
||||||
|
import com.google.common.base.MoreObjects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A SendRequest gives the wallet information about precisely how to send money to a recipient or set of recipients.
|
||||||
|
* Static methods are provided to help you create SendRequests and there are a few helper methods on the wallet that
|
||||||
|
* just simplify the most common use cases. You may wish to customize a SendRequest if you want to attach a fee or
|
||||||
|
* modify the change address.
|
||||||
|
*/
|
||||||
|
public class SendRequest {
|
||||||
|
/**
|
||||||
|
* <p>A transaction, probably incomplete, that describes the outline of what you want to do. This typically will
|
||||||
|
* mean it has some outputs to the intended destinations, but no inputs or change address (and therefore no
|
||||||
|
* fees) - the wallet will calculate all that for you and update tx later.</p>
|
||||||
|
*
|
||||||
|
* <p>Be careful when adding outputs that you check the min output value
|
||||||
|
* ({@link TransactionOutput#getMinNonDustValue(Coin)}) to avoid the whole transaction being rejected
|
||||||
|
* because one output is dust.</p>
|
||||||
|
*
|
||||||
|
* <p>If there are already inputs to the transaction, make sure their out point has a connected output,
|
||||||
|
* otherwise their value will be added to fee. Also ensure they are either signed or are spendable by a wallet
|
||||||
|
* key, otherwise the behavior of {@link Wallet#completeTx(Wallet.SendRequest)} is undefined (likely
|
||||||
|
* RuntimeException).</p>
|
||||||
|
*/
|
||||||
|
public Transaction tx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When emptyWallet is set, all coins selected by the coin selector are sent to the first output in tx
|
||||||
|
* (its value is ignored and set to {@link org.bitcoinj.wallet.Wallet#getBalance()} - the fees required
|
||||||
|
* for the transaction). Any additional outputs are removed.
|
||||||
|
*/
|
||||||
|
public boolean emptyWallet = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "Change" means the difference between the value gathered by a transactions inputs (the size of which you
|
||||||
|
* don't really control as it depends on who sent you money), and the value being sent somewhere else. The
|
||||||
|
* change address should be selected from this wallet, normally. <b>If null this will be chosen for you.</b>
|
||||||
|
*/
|
||||||
|
public Address changeAddress = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>A transaction can have a fee attached, which is defined as the difference between the input values
|
||||||
|
* and output values. Any value taken in that is not provided to an output can be claimed by a miner. This
|
||||||
|
* is how mining is incentivized in later years of the Bitcoin system when inflation drops. It also provides
|
||||||
|
* a way for people to prioritize their transactions over others and is used as a way to make denial of service
|
||||||
|
* attacks expensive.</p>
|
||||||
|
*
|
||||||
|
* <p>This is a dynamic fee (in satoshis) which will be added to the transaction for each kilobyte in size
|
||||||
|
* including the first. This is useful as as miners usually sort pending transactions by their fee per unit size
|
||||||
|
* when choosing which transactions to add to a block. Note that, to keep this equivalent to Bitcoin Core
|
||||||
|
* definition, a kilobyte is defined as 1000 bytes, not 1024.</p>
|
||||||
|
*/
|
||||||
|
public Coin feePerKb = Context.get().getFeePerKb();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Requires that there be enough fee for a default Bitcoin Core to at least relay the transaction.
|
||||||
|
* (ie ensure the transaction will not be outright rejected by the network). Defaults to true, you should
|
||||||
|
* only set this to false if you know what you're doing.</p>
|
||||||
|
*
|
||||||
|
* <p>Note that this does not enforce certain fee rules that only apply to transactions which are larger than
|
||||||
|
* 26,000 bytes. If you get a transaction which is that large, you should set a feePerKb of at least
|
||||||
|
* {@link Transaction#REFERENCE_DEFAULT_MIN_TX_FEE}.</p>
|
||||||
|
*/
|
||||||
|
public boolean ensureMinRequiredFee = Context.get().isEnsureMinRequiredFee();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true (the default), the inputs will be signed.
|
||||||
|
*/
|
||||||
|
public boolean signInputs = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The AES key to use to decrypt the private keys before signing.
|
||||||
|
* If null then no decryption will be performed and if decryption is required an exception will be thrown.
|
||||||
|
* You can get this from a password by doing wallet.getKeyCrypter().deriveKey(password).
|
||||||
|
*/
|
||||||
|
public KeyParameter aesKey = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If not null, the {@link org.bitcoinj.wallet.CoinSelector} to use instead of the wallets default. Coin selectors are
|
||||||
|
* responsible for choosing which transaction outputs (coins) in a wallet to use given the desired send value
|
||||||
|
* amount.
|
||||||
|
*/
|
||||||
|
public CoinSelector coinSelector = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true (the default), the outputs will be shuffled during completion to randomize the location of the change
|
||||||
|
* output, if any. This is normally what you want for privacy reasons but in unit tests it can be annoying
|
||||||
|
* so it can be disabled here.
|
||||||
|
*/
|
||||||
|
public boolean shuffleOutputs = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies what to do with missing signatures left after completing this request. Default strategy is to
|
||||||
|
* throw an exception on missing signature ({@link MissingSigsMode#THROW}).
|
||||||
|
* @see MissingSigsMode
|
||||||
|
*/
|
||||||
|
public MissingSigsMode missingSigsMode = MissingSigsMode.THROW;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If not null, this exchange rate is recorded with the transaction during completion.
|
||||||
|
*/
|
||||||
|
public ExchangeRate exchangeRate = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If not null, this memo is recorded with the transaction during completion. It can be used to record the memo
|
||||||
|
* of the payment request that initiated the transaction.
|
||||||
|
*/
|
||||||
|
public String memo = null;
|
||||||
|
|
||||||
|
// Tracks if this has been passed to wallet.completeTx already: just a safety check.
|
||||||
|
boolean completed;
|
||||||
|
|
||||||
|
private SendRequest() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Creates a new SendRequest to the given address for the given value.</p>
|
||||||
|
*
|
||||||
|
* <p>Be very careful when value is smaller than {@link Transaction#MIN_NONDUST_OUTPUT} as the transaction will
|
||||||
|
* likely be rejected by the network in this case.</p>
|
||||||
|
*/
|
||||||
|
public static SendRequest to(Address destination, Coin value) {
|
||||||
|
SendRequest req = new SendRequest();
|
||||||
|
final NetworkParameters parameters = destination.getParameters();
|
||||||
|
checkNotNull(parameters, "Address is for an unknown network");
|
||||||
|
req.tx = new Transaction(parameters);
|
||||||
|
req.tx.addOutput(value, destination);
|
||||||
|
return req;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Creates a new SendRequest to the given pubkey for the given value.</p>
|
||||||
|
*
|
||||||
|
* <p>Be careful to check the output's value is reasonable using
|
||||||
|
* {@link TransactionOutput#getMinNonDustValue(Coin)} afterwards or you risk having the transaction
|
||||||
|
* rejected by the network. Note that using {@link SendRequest#to(Address, Coin)} will result
|
||||||
|
* in a smaller output, and thus the ability to use a smaller output value without rejection.</p>
|
||||||
|
*/
|
||||||
|
public static SendRequest to(NetworkParameters params, ECKey destination, Coin value) {
|
||||||
|
SendRequest req = new SendRequest();
|
||||||
|
req.tx = new Transaction(params);
|
||||||
|
req.tx.addOutput(value, destination);
|
||||||
|
return req;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Simply wraps a pre-built incomplete transaction provided by you. */
|
||||||
|
public static SendRequest forTx(Transaction tx) {
|
||||||
|
SendRequest req = new SendRequest();
|
||||||
|
req.tx = tx;
|
||||||
|
return req;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SendRequest emptyWallet(Address destination) {
|
||||||
|
SendRequest req = new SendRequest();
|
||||||
|
final NetworkParameters parameters = destination.getParameters();
|
||||||
|
checkNotNull(parameters, "Address is for an unknown network");
|
||||||
|
req.tx = new Transaction(parameters);
|
||||||
|
req.tx.addOutput(Coin.ZERO, destination);
|
||||||
|
req.emptyWallet = true;
|
||||||
|
return req;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a SendRequest for a CPFP (child-pays-for-parent) transaction. The resulting transaction is already
|
||||||
|
* completed, so you should directly proceed to signing and broadcasting/committing the transaction. CPFP is
|
||||||
|
* currently only supported by a few miners, so use with care.
|
||||||
|
*/
|
||||||
|
public static SendRequest childPaysForParent(Wallet wallet, Transaction parentTransaction, Coin feeRaise) {
|
||||||
|
TransactionOutput outputToSpend = null;
|
||||||
|
for (final TransactionOutput output : parentTransaction.getOutputs()) {
|
||||||
|
if (output.isMine(wallet) && output.isAvailableForSpending()
|
||||||
|
&& output.getValue().isGreaterThan(feeRaise)) {
|
||||||
|
outputToSpend = output;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO spend another confirmed output of own wallet if needed
|
||||||
|
checkNotNull(outputToSpend, "Can't find adequately sized output that spends to us");
|
||||||
|
|
||||||
|
final Transaction tx = new Transaction(parentTransaction.getParams());
|
||||||
|
tx.addInput(outputToSpend);
|
||||||
|
tx.addOutput(outputToSpend.getValue().subtract(feeRaise), wallet.freshAddress(KeyPurpose.CHANGE));
|
||||||
|
tx.setPurpose(Transaction.Purpose.RAISE_FEE);
|
||||||
|
final SendRequest req = forTx(tx);
|
||||||
|
req.completed = true;
|
||||||
|
return req;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SendRequest toCLTVPaymentChannel(NetworkParameters params, Date releaseTime, ECKey from, ECKey to, Coin value) {
|
||||||
|
long time = releaseTime.getTime() / 1000L;
|
||||||
|
checkArgument(time >= Transaction.LOCKTIME_THRESHOLD, "Release time was too small");
|
||||||
|
return toCLTVPaymentChannel(params, BigInteger.valueOf(time), from, to, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SendRequest toCLTVPaymentChannel(NetworkParameters params, int releaseBlock, ECKey from, ECKey to, Coin value) {
|
||||||
|
checkArgument(0 <= releaseBlock && releaseBlock < Transaction.LOCKTIME_THRESHOLD, "Block number was too large");
|
||||||
|
return toCLTVPaymentChannel(params, BigInteger.valueOf(releaseBlock), from, to, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SendRequest toCLTVPaymentChannel(NetworkParameters params, BigInteger time, ECKey from, ECKey to, Coin value) {
|
||||||
|
SendRequest req = new SendRequest();
|
||||||
|
Script output = ScriptBuilder.createCLTVPaymentChannelOutput(time, from, to);
|
||||||
|
req.tx = new Transaction(params);
|
||||||
|
req.tx.addOutput(value, output);
|
||||||
|
return req;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Copy data from payment request. */
|
||||||
|
public SendRequest fromPaymentDetails(PaymentDetails paymentDetails) {
|
||||||
|
if (paymentDetails.hasMemo())
|
||||||
|
this.memo = paymentDetails.getMemo();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
// print only the user-settable fields
|
||||||
|
MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(this).omitNullValues();
|
||||||
|
helper.add("emptyWallet", emptyWallet);
|
||||||
|
helper.add("changeAddress", changeAddress);
|
||||||
|
helper.add("feePerKb", feePerKb);
|
||||||
|
helper.add("ensureMinRequiredFee", ensureMinRequiredFee);
|
||||||
|
helper.add("signInputs", signInputs);
|
||||||
|
helper.add("aesKey", aesKey != null ? "set" : null); // careful to not leak the key
|
||||||
|
helper.add("coinSelector", coinSelector);
|
||||||
|
helper.add("shuffleOutputs", shuffleOutputs);
|
||||||
|
return helper.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,7 +62,6 @@ import org.bitcoinj.crypto.*;
|
|||||||
import org.bitcoinj.script.*;
|
import org.bitcoinj.script.*;
|
||||||
import org.bitcoinj.signers.*;
|
import org.bitcoinj.signers.*;
|
||||||
import org.bitcoinj.utils.*;
|
import org.bitcoinj.utils.*;
|
||||||
import org.bitcoinj.wallet.KeyChain.KeyPurpose;
|
|
||||||
import org.bitcoinj.wallet.Protos.Wallet.*;
|
import org.bitcoinj.wallet.Protos.Wallet.*;
|
||||||
import org.bitcoinj.wallet.WalletTransaction.*;
|
import org.bitcoinj.wallet.WalletTransaction.*;
|
||||||
import org.bitcoinj.wallet.listeners.KeyChainEventListener;
|
import org.bitcoinj.wallet.listeners.KeyChainEventListener;
|
||||||
@@ -3708,232 +3707,6 @@ public class Wallet extends BaseTaggableObject
|
|||||||
THROW
|
THROW
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A SendRequest gives the wallet information about precisely how to send money to a recipient or set of recipients.
|
|
||||||
* Static methods are provided to help you create SendRequests and there are a few helper methods on the wallet that
|
|
||||||
* just simplify the most common use cases. You may wish to customize a SendRequest if you want to attach a fee or
|
|
||||||
* modify the change address.
|
|
||||||
*/
|
|
||||||
public static class SendRequest {
|
|
||||||
/**
|
|
||||||
* <p>A transaction, probably incomplete, that describes the outline of what you want to do. This typically will
|
|
||||||
* mean it has some outputs to the intended destinations, but no inputs or change address (and therefore no
|
|
||||||
* fees) - the wallet will calculate all that for you and update tx later.</p>
|
|
||||||
*
|
|
||||||
* <p>Be careful when adding outputs that you check the min output value
|
|
||||||
* ({@link TransactionOutput#getMinNonDustValue(Coin)}) to avoid the whole transaction being rejected
|
|
||||||
* because one output is dust.</p>
|
|
||||||
*
|
|
||||||
* <p>If there are already inputs to the transaction, make sure their out point has a connected output,
|
|
||||||
* otherwise their value will be added to fee. Also ensure they are either signed or are spendable by a wallet
|
|
||||||
* key, otherwise the behavior of {@link Wallet#completeTx(Wallet.SendRequest)} is undefined (likely
|
|
||||||
* RuntimeException).</p>
|
|
||||||
*/
|
|
||||||
public Transaction tx;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When emptyWallet is set, all coins selected by the coin selector are sent to the first output in tx
|
|
||||||
* (its value is ignored and set to {@link org.bitcoinj.wallet.Wallet#getBalance()} - the fees required
|
|
||||||
* for the transaction). Any additional outputs are removed.
|
|
||||||
*/
|
|
||||||
public boolean emptyWallet = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* "Change" means the difference between the value gathered by a transactions inputs (the size of which you
|
|
||||||
* don't really control as it depends on who sent you money), and the value being sent somewhere else. The
|
|
||||||
* change address should be selected from this wallet, normally. <b>If null this will be chosen for you.</b>
|
|
||||||
*/
|
|
||||||
public Address changeAddress = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>A transaction can have a fee attached, which is defined as the difference between the input values
|
|
||||||
* and output values. Any value taken in that is not provided to an output can be claimed by a miner. This
|
|
||||||
* is how mining is incentivized in later years of the Bitcoin system when inflation drops. It also provides
|
|
||||||
* a way for people to prioritize their transactions over others and is used as a way to make denial of service
|
|
||||||
* attacks expensive.</p>
|
|
||||||
*
|
|
||||||
* <p>This is a dynamic fee (in satoshis) which will be added to the transaction for each kilobyte in size
|
|
||||||
* including the first. This is useful as as miners usually sort pending transactions by their fee per unit size
|
|
||||||
* when choosing which transactions to add to a block. Note that, to keep this equivalent to Bitcoin Core
|
|
||||||
* definition, a kilobyte is defined as 1000 bytes, not 1024.</p>
|
|
||||||
*/
|
|
||||||
public Coin feePerKb = Context.get().getFeePerKb();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Requires that there be enough fee for a default Bitcoin Core to at least relay the transaction.
|
|
||||||
* (ie ensure the transaction will not be outright rejected by the network). Defaults to true, you should
|
|
||||||
* only set this to false if you know what you're doing.</p>
|
|
||||||
*
|
|
||||||
* <p>Note that this does not enforce certain fee rules that only apply to transactions which are larger than
|
|
||||||
* 26,000 bytes. If you get a transaction which is that large, you should set a feePerKb of at least
|
|
||||||
* {@link Transaction#REFERENCE_DEFAULT_MIN_TX_FEE}.</p>
|
|
||||||
*/
|
|
||||||
public boolean ensureMinRequiredFee = Context.get().isEnsureMinRequiredFee();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If true (the default), the inputs will be signed.
|
|
||||||
*/
|
|
||||||
public boolean signInputs = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The AES key to use to decrypt the private keys before signing.
|
|
||||||
* If null then no decryption will be performed and if decryption is required an exception will be thrown.
|
|
||||||
* You can get this from a password by doing wallet.getKeyCrypter().deriveKey(password).
|
|
||||||
*/
|
|
||||||
public KeyParameter aesKey = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If not null, the {@link org.bitcoinj.wallet.CoinSelector} to use instead of the wallets default. Coin selectors are
|
|
||||||
* responsible for choosing which transaction outputs (coins) in a wallet to use given the desired send value
|
|
||||||
* amount.
|
|
||||||
*/
|
|
||||||
public CoinSelector coinSelector = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If true (the default), the outputs will be shuffled during completion to randomize the location of the change
|
|
||||||
* output, if any. This is normally what you want for privacy reasons but in unit tests it can be annoying
|
|
||||||
* so it can be disabled here.
|
|
||||||
*/
|
|
||||||
public boolean shuffleOutputs = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies what to do with missing signatures left after completing this request. Default strategy is to
|
|
||||||
* throw an exception on missing signature ({@link MissingSigsMode#THROW}).
|
|
||||||
* @see MissingSigsMode
|
|
||||||
*/
|
|
||||||
public MissingSigsMode missingSigsMode = MissingSigsMode.THROW;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If not null, this exchange rate is recorded with the transaction during completion.
|
|
||||||
*/
|
|
||||||
public ExchangeRate exchangeRate = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If not null, this memo is recorded with the transaction during completion. It can be used to record the memo
|
|
||||||
* of the payment request that initiated the transaction.
|
|
||||||
*/
|
|
||||||
public String memo = null;
|
|
||||||
|
|
||||||
// Tracks if this has been passed to wallet.completeTx already: just a safety check.
|
|
||||||
private boolean completed;
|
|
||||||
|
|
||||||
private SendRequest() {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Creates a new SendRequest to the given address for the given value.</p>
|
|
||||||
*
|
|
||||||
* <p>Be very careful when value is smaller than {@link Transaction#MIN_NONDUST_OUTPUT} as the transaction will
|
|
||||||
* likely be rejected by the network in this case.</p>
|
|
||||||
*/
|
|
||||||
public static SendRequest to(Address destination, Coin value) {
|
|
||||||
SendRequest req = new SendRequest();
|
|
||||||
final NetworkParameters parameters = destination.getParameters();
|
|
||||||
checkNotNull(parameters, "Address is for an unknown network");
|
|
||||||
req.tx = new Transaction(parameters);
|
|
||||||
req.tx.addOutput(value, destination);
|
|
||||||
return req;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Creates a new SendRequest to the given pubkey for the given value.</p>
|
|
||||||
*
|
|
||||||
* <p>Be careful to check the output's value is reasonable using
|
|
||||||
* {@link TransactionOutput#getMinNonDustValue(Coin)} afterwards or you risk having the transaction
|
|
||||||
* rejected by the network. Note that using {@link SendRequest#to(Address, Coin)} will result
|
|
||||||
* in a smaller output, and thus the ability to use a smaller output value without rejection.</p>
|
|
||||||
*/
|
|
||||||
public static SendRequest to(NetworkParameters params, ECKey destination, Coin value) {
|
|
||||||
SendRequest req = new SendRequest();
|
|
||||||
req.tx = new Transaction(params);
|
|
||||||
req.tx.addOutput(value, destination);
|
|
||||||
return req;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Simply wraps a pre-built incomplete transaction provided by you. */
|
|
||||||
public static SendRequest forTx(Transaction tx) {
|
|
||||||
SendRequest req = new SendRequest();
|
|
||||||
req.tx = tx;
|
|
||||||
return req;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SendRequest emptyWallet(Address destination) {
|
|
||||||
SendRequest req = new SendRequest();
|
|
||||||
final NetworkParameters parameters = destination.getParameters();
|
|
||||||
checkNotNull(parameters, "Address is for an unknown network");
|
|
||||||
req.tx = new Transaction(parameters);
|
|
||||||
req.tx.addOutput(Coin.ZERO, destination);
|
|
||||||
req.emptyWallet = true;
|
|
||||||
return req;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a SendRequest for a CPFP (child-pays-for-parent) transaction. The resulting transaction is already
|
|
||||||
* completed, so you should directly proceed to signing and broadcasting/committing the transaction. CPFP is
|
|
||||||
* currently only supported by a few miners, so use with care.
|
|
||||||
*/
|
|
||||||
public static SendRequest childPaysForParent(Wallet wallet, Transaction parentTransaction, Coin feeRaise) {
|
|
||||||
TransactionOutput outputToSpend = null;
|
|
||||||
for (final TransactionOutput output : parentTransaction.getOutputs()) {
|
|
||||||
if (output.isMine(wallet) && output.isAvailableForSpending()
|
|
||||||
&& output.getValue().isGreaterThan(feeRaise)) {
|
|
||||||
outputToSpend = output;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO spend another confirmed output of own wallet if needed
|
|
||||||
checkNotNull(outputToSpend, "Can't find adequately sized output that spends to us");
|
|
||||||
|
|
||||||
final Transaction tx = new Transaction(parentTransaction.getParams());
|
|
||||||
tx.addInput(outputToSpend);
|
|
||||||
tx.addOutput(outputToSpend.getValue().subtract(feeRaise), wallet.freshAddress(KeyPurpose.CHANGE));
|
|
||||||
tx.setPurpose(Transaction.Purpose.RAISE_FEE);
|
|
||||||
final SendRequest req = forTx(tx);
|
|
||||||
req.completed = true;
|
|
||||||
return req;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SendRequest toCLTVPaymentChannel(NetworkParameters params, Date releaseTime, ECKey from, ECKey to, Coin value) {
|
|
||||||
long time = releaseTime.getTime() / 1000L;
|
|
||||||
checkArgument(time >= Transaction.LOCKTIME_THRESHOLD, "Release time was too small");
|
|
||||||
return toCLTVPaymentChannel(params, BigInteger.valueOf(time), from, to, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SendRequest toCLTVPaymentChannel(NetworkParameters params, int releaseBlock, ECKey from, ECKey to, Coin value) {
|
|
||||||
checkArgument(0 <= releaseBlock && releaseBlock < Transaction.LOCKTIME_THRESHOLD, "Block number was too large");
|
|
||||||
return toCLTVPaymentChannel(params, BigInteger.valueOf(releaseBlock), from, to, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SendRequest toCLTVPaymentChannel(NetworkParameters params, BigInteger time, ECKey from, ECKey to, Coin value) {
|
|
||||||
SendRequest req = new SendRequest();
|
|
||||||
Script output = ScriptBuilder.createCLTVPaymentChannelOutput(time, from, to);
|
|
||||||
req.tx = new Transaction(params);
|
|
||||||
req.tx.addOutput(value, output);
|
|
||||||
return req;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Copy data from payment request. */
|
|
||||||
public SendRequest fromPaymentDetails(PaymentDetails paymentDetails) {
|
|
||||||
if (paymentDetails.hasMemo())
|
|
||||||
this.memo = paymentDetails.getMemo();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
// print only the user-settable fields
|
|
||||||
MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(this).omitNullValues();
|
|
||||||
helper.add("emptyWallet", emptyWallet);
|
|
||||||
helper.add("changeAddress", changeAddress);
|
|
||||||
helper.add("feePerKb", feePerKb);
|
|
||||||
helper.add("ensureMinRequiredFee", ensureMinRequiredFee);
|
|
||||||
helper.add("signInputs", signInputs);
|
|
||||||
helper.add("aesKey", aesKey != null ? "set" : null); // careful to not leak the key
|
|
||||||
helper.add("coinSelector", coinSelector);
|
|
||||||
helper.add("shuffleOutputs", shuffleOutputs);
|
|
||||||
return helper.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Statelessly creates a transaction that sends the given value to address. The change is sent to
|
* <p>Statelessly creates a transaction that sends the given value to address. The change is sent to
|
||||||
* {@link Wallet#currentChangeAddress()}, so you must have added at least one key.</p>
|
* {@link Wallet#currentChangeAddress()}, so you must have added at least one key.</p>
|
||||||
@@ -3943,7 +3716,7 @@ public class Wallet extends BaseTaggableObject
|
|||||||
* transaction, commit to the wallet and broadcast it to the network all in one go. This method is lower level
|
* transaction, commit to the wallet and broadcast it to the network all in one go. This method is lower level
|
||||||
* and lets you see the proposed transaction before anything is done with it.</p>
|
* and lets you see the proposed transaction before anything is done with it.</p>
|
||||||
*
|
*
|
||||||
* <p>This is a helper method that is equivalent to using {@link Wallet.SendRequest#to(Address, Coin)}
|
* <p>This is a helper method that is equivalent to using {@link SendRequest#to(Address, Coin)}
|
||||||
* followed by {@link Wallet#completeTx(Wallet.SendRequest)} and returning the requests transaction object.
|
* followed by {@link Wallet#completeTx(Wallet.SendRequest)} and returning the requests transaction object.
|
||||||
* Note that this means a fee may be automatically added if required, if you want more control over the process,
|
* Note that this means a fee may be automatically added if required, if you want more control over the process,
|
||||||
* just do those two steps yourself.</p>
|
* just do those two steps yourself.</p>
|
||||||
@@ -4481,7 +4254,7 @@ public class Wallet extends BaseTaggableObject
|
|||||||
* A coin selector is responsible for choosing which outputs to spend when creating transactions. The default
|
* A coin selector is responsible for choosing which outputs to spend when creating transactions. The default
|
||||||
* selector implements a policy of spending transactions that appeared in the best chain and pending transactions
|
* selector implements a policy of spending transactions that appeared in the best chain and pending transactions
|
||||||
* that were created by this wallet, but not others. You can override the coin selector for any given send
|
* that were created by this wallet, but not others. You can override the coin selector for any given send
|
||||||
* operation by changing {@link Wallet.SendRequest#coinSelector}.
|
* operation by changing {@link SendRequest#coinSelector}.
|
||||||
*/
|
*/
|
||||||
public void setCoinSelector(CoinSelector coinSelector) {
|
public void setCoinSelector(CoinSelector coinSelector) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import org.bitcoinj.store.BlockStoreException;
|
|||||||
import org.bitcoinj.store.FullPrunedBlockStore;
|
import org.bitcoinj.store.FullPrunedBlockStore;
|
||||||
import org.bitcoinj.utils.BlockFileLoader;
|
import org.bitcoinj.utils.BlockFileLoader;
|
||||||
import org.bitcoinj.utils.BriefLogFormatter;
|
import org.bitcoinj.utils.BriefLogFormatter;
|
||||||
|
import org.bitcoinj.wallet.SendRequest;
|
||||||
import org.bitcoinj.wallet.Wallet;
|
import org.bitcoinj.wallet.Wallet;
|
||||||
import org.bitcoinj.wallet.WalletTransaction;
|
import org.bitcoinj.wallet.WalletTransaction;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -327,7 +328,7 @@ public abstract class AbstractFullPrunedBlockChainTest {
|
|||||||
ECKey toKey2 = new ECKey();
|
ECKey toKey2 = new ECKey();
|
||||||
Coin amount2 = amount.divide(2);
|
Coin amount2 = amount.divide(2);
|
||||||
Address address2 = new Address(PARAMS, toKey2.getPubKeyHash());
|
Address address2 = new Address(PARAMS, toKey2.getPubKeyHash());
|
||||||
Wallet.SendRequest req = Wallet.SendRequest.to(address2, amount2);
|
SendRequest req = SendRequest.to(address2, amount2);
|
||||||
wallet.completeTx(req);
|
wallet.completeTx(req);
|
||||||
wallet.commitTx(req.tx);
|
wallet.commitTx(req.tx);
|
||||||
Coin fee = Coin.ZERO;
|
Coin fee = Coin.ZERO;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.google.common.util.concurrent.*;
|
|||||||
import org.bitcoinj.core.listeners.TransactionConfidenceEventListener;
|
import org.bitcoinj.core.listeners.TransactionConfidenceEventListener;
|
||||||
import org.bitcoinj.testing.*;
|
import org.bitcoinj.testing.*;
|
||||||
import org.bitcoinj.utils.*;
|
import org.bitcoinj.utils.*;
|
||||||
|
import org.bitcoinj.wallet.SendRequest;
|
||||||
import org.bitcoinj.wallet.Wallet;
|
import org.bitcoinj.wallet.Wallet;
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
import org.junit.runner.*;
|
import org.junit.runner.*;
|
||||||
@@ -244,7 +245,7 @@ public class TransactionBroadcastTest extends TestWithPeerGroup {
|
|||||||
|
|
||||||
// Do the same thing with an offline transaction.
|
// Do the same thing with an offline transaction.
|
||||||
peerGroup.removeWallet(wallet);
|
peerGroup.removeWallet(wallet);
|
||||||
Wallet.SendRequest req = Wallet.SendRequest.to(dest, valueOf(2, 0));
|
SendRequest req = SendRequest.to(dest, valueOf(2, 0));
|
||||||
Transaction t3 = checkNotNull(wallet.sendCoinsOffline(req));
|
Transaction t3 = checkNotNull(wallet.sendCoinsOffline(req));
|
||||||
assertNull(outbound(p1)); // Nothing sent.
|
assertNull(outbound(p1)); // Nothing sent.
|
||||||
// Add the wallet to the peer group (simulate initialization). Transactions should be announced.
|
// Add the wallet to the peer group (simulate initialization). Transactions should be announced.
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import org.bitcoinj.params.MainNetParams;
|
|||||||
import org.bitcoinj.script.Script;
|
import org.bitcoinj.script.Script;
|
||||||
import org.bitcoinj.script.ScriptBuilder;
|
import org.bitcoinj.script.ScriptBuilder;
|
||||||
import org.bitcoinj.testing.TestWithWallet;
|
import org.bitcoinj.testing.TestWithWallet;
|
||||||
import org.bitcoinj.wallet.Wallet;
|
import org.bitcoinj.wallet.SendRequest;
|
||||||
import org.hamcrest.CoreMatchers;
|
import org.hamcrest.CoreMatchers;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -55,7 +55,7 @@ public class TransactionOutputTest extends TestWithWallet {
|
|||||||
Script scriptPubKey = ScriptBuilder.createMultiSigOutputScript(2, keys);
|
Script scriptPubKey = ScriptBuilder.createMultiSigOutputScript(2, keys);
|
||||||
multiSigTransaction.addOutput(Coin.COIN, scriptPubKey);
|
multiSigTransaction.addOutput(Coin.COIN, scriptPubKey);
|
||||||
|
|
||||||
Wallet.SendRequest req = Wallet.SendRequest.forTx(multiSigTransaction);
|
SendRequest req = SendRequest.forTx(multiSigTransaction);
|
||||||
this.wallet.completeTx(req);
|
this.wallet.completeTx(req);
|
||||||
TransactionOutput multiSigTransactionOutput = multiSigTransaction.getOutput(0);
|
TransactionOutput multiSigTransactionOutput = multiSigTransaction.getOutput(0);
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ import org.bitcoinj.core.*;
|
|||||||
import org.bitcoinj.script.Script;
|
import org.bitcoinj.script.Script;
|
||||||
import org.bitcoinj.script.ScriptBuilder;
|
import org.bitcoinj.script.ScriptBuilder;
|
||||||
import org.bitcoinj.testing.TestWithWallet;
|
import org.bitcoinj.testing.TestWithWallet;
|
||||||
|
import org.bitcoinj.wallet.SendRequest;
|
||||||
import org.bitcoinj.wallet.Wallet;
|
import org.bitcoinj.wallet.Wallet;
|
||||||
import org.bitcoinj.wallet.Wallet.SendRequest;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
@@ -340,7 +340,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
|
|||||||
// we can broadcast the refund and get our balance back.
|
// we can broadcast the refund and get our balance back.
|
||||||
|
|
||||||
// Spend the client wallet's one coin
|
// Spend the client wallet's one coin
|
||||||
Transaction spendCoinTx = wallet.sendCoinsOffline(Wallet.SendRequest.to(new ECKey().toAddress(PARAMS), COIN));
|
Transaction spendCoinTx = wallet.sendCoinsOffline(SendRequest.to(new ECKey().toAddress(PARAMS), COIN));
|
||||||
assertEquals(Coin.ZERO, wallet.getBalance());
|
assertEquals(Coin.ZERO, wallet.getBalance());
|
||||||
chain.add(makeSolvedTestBlock(blockStore.getChainHead().getHeader(), spendCoinTx, createFakeTx(PARAMS, CENT, myAddress)));
|
chain.add(makeSolvedTestBlock(blockStore.getChainHead().getHeader(), spendCoinTx, createFakeTx(PARAMS, CENT, myAddress)));
|
||||||
assertEquals(CENT, wallet.getBalance());
|
assertEquals(CENT, wallet.getBalance());
|
||||||
@@ -691,7 +691,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
|
|||||||
Context.propagate(new Context(PARAMS, 100, Coin.ZERO, true));
|
Context.propagate(new Context(PARAMS, 100, Coin.ZERO, true));
|
||||||
|
|
||||||
// Spend the client wallet's one coin
|
// Spend the client wallet's one coin
|
||||||
final SendRequest request = Wallet.SendRequest.to(new ECKey().toAddress(PARAMS), COIN);
|
final SendRequest request = SendRequest.to(new ECKey().toAddress(PARAMS), COIN);
|
||||||
request.ensureMinRequiredFee = false;
|
request.ensureMinRequiredFee = false;
|
||||||
wallet.sendCoinsOffline(request);
|
wallet.sendCoinsOffline(request);
|
||||||
assertEquals(Coin.ZERO, wallet.getBalance());
|
assertEquals(Coin.ZERO, wallet.getBalance());
|
||||||
@@ -819,7 +819,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
|
|||||||
case VERSION_1:
|
case VERSION_1:
|
||||||
clientState = new PaymentChannelV1ClientState(wallet, myKey, ECKey.fromPublicOnly(serverKey.getPubKey()), CENT, EXPIRE_TIME) {
|
clientState = new PaymentChannelV1ClientState(wallet, myKey, ECKey.fromPublicOnly(serverKey.getPubKey()), CENT, EXPIRE_TIME) {
|
||||||
@Override
|
@Override
|
||||||
protected void editContractSendRequest(Wallet.SendRequest req) {
|
protected void editContractSendRequest(SendRequest req) {
|
||||||
req.coinSelector = wallet.getCoinSelector();
|
req.coinSelector = wallet.getCoinSelector();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -828,7 +828,7 @@ public class PaymentChannelStateTest extends TestWithWallet {
|
|||||||
case VERSION_2:
|
case VERSION_2:
|
||||||
clientState = new PaymentChannelV2ClientState(wallet, myKey, ECKey.fromPublicOnly(serverKey.getPubKey()), CENT, EXPIRE_TIME) {
|
clientState = new PaymentChannelV2ClientState(wallet, myKey, ECKey.fromPublicOnly(serverKey.getPubKey()), CENT, EXPIRE_TIME) {
|
||||||
@Override
|
@Override
|
||||||
protected void editContractSendRequest(Wallet.SendRequest req) {
|
protected void editContractSendRequest(SendRequest req) {
|
||||||
req.coinSelector = wallet.getCoinSelector();
|
req.coinSelector = wallet.getCoinSelector();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ import com.google.common.collect.Lists;
|
|||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import org.bitcoinj.wallet.Protos.Wallet.EncryptionType;
|
import org.bitcoinj.wallet.Protos.Wallet.EncryptionType;
|
||||||
import org.bitcoinj.wallet.Wallet.SendRequest;
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
@@ -307,7 +306,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
|
|
||||||
// Try to send too much and fail.
|
// Try to send too much and fail.
|
||||||
Coin vHuge = valueOf(10, 0);
|
Coin vHuge = valueOf(10, 0);
|
||||||
Wallet.SendRequest req = Wallet.SendRequest.to(destination, vHuge);
|
SendRequest req = SendRequest.to(destination, vHuge);
|
||||||
try {
|
try {
|
||||||
wallet.completeTx(req);
|
wallet.completeTx(req);
|
||||||
fail();
|
fail();
|
||||||
@@ -317,7 +316,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
|
|
||||||
// Prepare to send.
|
// Prepare to send.
|
||||||
Coin v2 = valueOf(0, 50);
|
Coin v2 = valueOf(0, 50);
|
||||||
req = Wallet.SendRequest.to(destination, v2);
|
req = SendRequest.to(destination, v2);
|
||||||
|
|
||||||
if (encryptedWallet != null) {
|
if (encryptedWallet != null) {
|
||||||
KeyCrypter keyCrypter = encryptedWallet.getKeyCrypter();
|
KeyCrypter keyCrypter = encryptedWallet.getKeyCrypter();
|
||||||
@@ -334,7 +333,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
assertEquals("Wrong number of ALL", 1, wallet.getTransactions(true).size());
|
assertEquals("Wrong number of ALL", 1, wallet.getTransactions(true).size());
|
||||||
|
|
||||||
// Try to create a send with a fee but the wrong password (this should fail).
|
// Try to create a send with a fee but the wrong password (this should fail).
|
||||||
req = Wallet.SendRequest.to(destination, v2);
|
req = SendRequest.to(destination, v2);
|
||||||
req.aesKey = wrongAesKey;
|
req.aesKey = wrongAesKey;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -348,7 +347,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
assertEquals("Wrong number of ALL", 1, wallet.getTransactions(true).size());
|
assertEquals("Wrong number of ALL", 1, wallet.getTransactions(true).size());
|
||||||
|
|
||||||
// Create a send with a fee with the correct password (this should succeed).
|
// Create a send with a fee with the correct password (this should succeed).
|
||||||
req = Wallet.SendRequest.to(destination, v2);
|
req = SendRequest.to(destination, v2);
|
||||||
req.aesKey = aesKey;
|
req.aesKey = aesKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,7 +445,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
wallet = roundTrip(wallet);
|
wallet = roundTrip(wallet);
|
||||||
Coin v3 = valueOf(0, 50);
|
Coin v3 = valueOf(0, 50);
|
||||||
assertEquals(v3, wallet.getBalance());
|
assertEquals(v3, wallet.getBalance());
|
||||||
Wallet.SendRequest req = Wallet.SendRequest.to(OTHER_ADDRESS, valueOf(0, 48));
|
SendRequest req = SendRequest.to(OTHER_ADDRESS, valueOf(0, 48));
|
||||||
req.aesKey = aesKey;
|
req.aesKey = aesKey;
|
||||||
req.shuffleOutputs = false;
|
req.shuffleOutputs = false;
|
||||||
wallet.completeTx(req);
|
wallet.completeTx(req);
|
||||||
@@ -2106,7 +2105,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
assertEquals(key.getPubKeyPoint(), encryptedWallet.getImportedKeys().get(0).getPubKeyPoint());
|
assertEquals(key.getPubKeyPoint(), encryptedWallet.getImportedKeys().get(0).getPubKeyPoint());
|
||||||
sendMoneyToWallet(encryptedWallet, AbstractBlockChain.NewBlockType.BEST_CHAIN, Coin.COIN, key.toAddress(PARAMS));
|
sendMoneyToWallet(encryptedWallet, AbstractBlockChain.NewBlockType.BEST_CHAIN, Coin.COIN, key.toAddress(PARAMS));
|
||||||
assertEquals(Coin.COIN, encryptedWallet.getBalance());
|
assertEquals(Coin.COIN, encryptedWallet.getBalance());
|
||||||
SendRequest req = Wallet.SendRequest.emptyWallet(OTHER_ADDRESS);
|
SendRequest req = SendRequest.emptyWallet(OTHER_ADDRESS);
|
||||||
req.aesKey = checkNotNull(encryptedWallet.getKeyCrypter()).deriveKey(PASSWORD1);
|
req.aesKey = checkNotNull(encryptedWallet.getKeyCrypter()).deriveKey(PASSWORD1);
|
||||||
encryptedWallet.sendCoinsOffline(req);
|
encryptedWallet.sendCoinsOffline(req);
|
||||||
}
|
}
|
||||||
@@ -2141,7 +2140,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
for (int i = 0; i < 3100; i++) {
|
for (int i = 0; i < 3100; i++) {
|
||||||
tx.addOutput(v, new Address(PARAMS, bits));
|
tx.addOutput(v, new Address(PARAMS, bits));
|
||||||
}
|
}
|
||||||
Wallet.SendRequest req = Wallet.SendRequest.forTx(tx);
|
SendRequest req = SendRequest.forTx(tx);
|
||||||
wallet.completeTx(req);
|
wallet.completeTx(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2153,7 +2152,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
Coin messagePrice = Coin.ZERO;
|
Coin messagePrice = Coin.ZERO;
|
||||||
Script script = ScriptBuilder.createOpReturnScript("hello world!".getBytes());
|
Script script = ScriptBuilder.createOpReturnScript("hello world!".getBytes());
|
||||||
tx.addOutput(messagePrice, script);
|
tx.addOutput(messagePrice, script);
|
||||||
SendRequest request = Wallet.SendRequest.forTx(tx);
|
SendRequest request = SendRequest.forTx(tx);
|
||||||
request.ensureMinRequiredFee = true;
|
request.ensureMinRequiredFee = true;
|
||||||
wallet.completeTx(request);
|
wallet.completeTx(request);
|
||||||
}
|
}
|
||||||
@@ -2166,7 +2165,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
Coin messagePrice = CENT;
|
Coin messagePrice = CENT;
|
||||||
Script script = ScriptBuilder.createOpReturnScript("hello world!".getBytes());
|
Script script = ScriptBuilder.createOpReturnScript("hello world!".getBytes());
|
||||||
tx.addOutput(messagePrice, script);
|
tx.addOutput(messagePrice, script);
|
||||||
SendRequest request = Wallet.SendRequest.forTx(tx);
|
SendRequest request = SendRequest.forTx(tx);
|
||||||
wallet.completeTx(request);
|
wallet.completeTx(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2179,7 +2178,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
Script script = ScriptBuilder.createOpReturnScript("hello world!".getBytes());
|
Script script = ScriptBuilder.createOpReturnScript("hello world!".getBytes());
|
||||||
tx.addOutput(CENT, OTHER_ADDRESS);
|
tx.addOutput(CENT, OTHER_ADDRESS);
|
||||||
tx.addOutput(messagePrice, script);
|
tx.addOutput(messagePrice, script);
|
||||||
SendRequest request = Wallet.SendRequest.forTx(tx);
|
SendRequest request = SendRequest.forTx(tx);
|
||||||
wallet.completeTx(request);
|
wallet.completeTx(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2193,7 +2192,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
Script script2 = ScriptBuilder.createOpReturnScript("hello world 2!".getBytes());
|
Script script2 = ScriptBuilder.createOpReturnScript("hello world 2!".getBytes());
|
||||||
tx.addOutput(messagePrice, script1);
|
tx.addOutput(messagePrice, script1);
|
||||||
tx.addOutput(messagePrice, script2);
|
tx.addOutput(messagePrice, script2);
|
||||||
SendRequest request = Wallet.SendRequest.forTx(tx);
|
SendRequest request = SendRequest.forTx(tx);
|
||||||
request.ensureMinRequiredFee = true;
|
request.ensureMinRequiredFee = true;
|
||||||
wallet.completeTx(request);
|
wallet.completeTx(request);
|
||||||
}
|
}
|
||||||
@@ -2203,7 +2202,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
// Tests sending dust, should throw DustySendRequested.
|
// Tests sending dust, should throw DustySendRequested.
|
||||||
Transaction tx = new Transaction(PARAMS);
|
Transaction tx = new Transaction(PARAMS);
|
||||||
tx.addOutput(Transaction.MIN_NONDUST_OUTPUT.subtract(SATOSHI), OTHER_ADDRESS);
|
tx.addOutput(Transaction.MIN_NONDUST_OUTPUT.subtract(SATOSHI), OTHER_ADDRESS);
|
||||||
SendRequest request = Wallet.SendRequest.forTx(tx);
|
SendRequest request = SendRequest.forTx(tx);
|
||||||
request.ensureMinRequiredFee = true;
|
request.ensureMinRequiredFee = true;
|
||||||
wallet.completeTx(request);
|
wallet.completeTx(request);
|
||||||
}
|
}
|
||||||
@@ -2217,7 +2216,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
tx.addOutput(c, OTHER_ADDRESS);
|
tx.addOutput(c, OTHER_ADDRESS);
|
||||||
tx.addOutput(c, OTHER_ADDRESS);
|
tx.addOutput(c, OTHER_ADDRESS);
|
||||||
tx.addOutput(c, OTHER_ADDRESS);
|
tx.addOutput(c, OTHER_ADDRESS);
|
||||||
SendRequest request = Wallet.SendRequest.forTx(tx);
|
SendRequest request = SendRequest.forTx(tx);
|
||||||
wallet.completeTx(request);
|
wallet.completeTx(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2228,7 +2227,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
Transaction tx = new Transaction(PARAMS);
|
Transaction tx = new Transaction(PARAMS);
|
||||||
tx.addOutput(Coin.ZERO, ScriptBuilder.createOpReturnScript("hello world!".getBytes()));
|
tx.addOutput(Coin.ZERO, ScriptBuilder.createOpReturnScript("hello world!".getBytes()));
|
||||||
tx.addOutput(Coin.SATOSHI, OTHER_ADDRESS);
|
tx.addOutput(Coin.SATOSHI, OTHER_ADDRESS);
|
||||||
SendRequest request = Wallet.SendRequest.forTx(tx);
|
SendRequest request = SendRequest.forTx(tx);
|
||||||
request.ensureMinRequiredFee = true;
|
request.ensureMinRequiredFee = true;
|
||||||
wallet.completeTx(request);
|
wallet.completeTx(request);
|
||||||
}
|
}
|
||||||
@@ -2240,7 +2239,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
Transaction tx = new Transaction(PARAMS);
|
Transaction tx = new Transaction(PARAMS);
|
||||||
tx.addOutput(Coin.CENT, ScriptBuilder.createOpReturnScript("hello world!".getBytes()));
|
tx.addOutput(Coin.CENT, ScriptBuilder.createOpReturnScript("hello world!".getBytes()));
|
||||||
tx.addOutput(Transaction.MIN_NONDUST_OUTPUT.subtract(SATOSHI), OTHER_ADDRESS);
|
tx.addOutput(Transaction.MIN_NONDUST_OUTPUT.subtract(SATOSHI), OTHER_ADDRESS);
|
||||||
SendRequest request = Wallet.SendRequest.forTx(tx);
|
SendRequest request = SendRequest.forTx(tx);
|
||||||
request.ensureMinRequiredFee = true;
|
request.ensureMinRequiredFee = true;
|
||||||
wallet.completeTx(request);
|
wallet.completeTx(request);
|
||||||
}
|
}
|
||||||
@@ -3148,7 +3147,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
for (TransactionInput input : req.tx.getInputs())
|
for (TransactionInput input : req.tx.getInputs())
|
||||||
input.clearScriptBytes();
|
input.clearScriptBytes();
|
||||||
Wallet watching = Wallet.fromWatchingKey(PARAMS, wallet.getWatchingKey().dropParent().dropPrivateBytes());
|
Wallet watching = Wallet.fromWatchingKey(PARAMS, wallet.getWatchingKey().dropParent().dropPrivateBytes());
|
||||||
watching.completeTx(Wallet.SendRequest.forTx(req.tx));
|
watching.completeTx(SendRequest.forTx(req.tx));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -3175,7 +3174,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
myAddress = wallet.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS);
|
myAddress = wallet.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS);
|
||||||
sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, COIN, myAddress);
|
sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, COIN, myAddress);
|
||||||
|
|
||||||
Wallet.SendRequest req = Wallet.SendRequest.emptyWallet(OTHER_ADDRESS);
|
SendRequest req = SendRequest.emptyWallet(OTHER_ADDRESS);
|
||||||
wallet.completeTx(req);
|
wallet.completeTx(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3185,7 +3184,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
myAddress = wallet.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS);
|
myAddress = wallet.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS);
|
||||||
sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, COIN, myAddress);
|
sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, COIN, myAddress);
|
||||||
|
|
||||||
Wallet.SendRequest req = Wallet.SendRequest.emptyWallet(OTHER_ADDRESS);
|
SendRequest req = SendRequest.emptyWallet(OTHER_ADDRESS);
|
||||||
req.missingSigsMode = missSigMode;
|
req.missingSigsMode = missSigMode;
|
||||||
wallet.completeTx(req);
|
wallet.completeTx(req);
|
||||||
TransactionInput input = req.tx.getInput(0);
|
TransactionInput input = req.tx.getInput(0);
|
||||||
@@ -3214,7 +3213,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
Transaction t2 = sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, pub);
|
Transaction t2 = sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, pub);
|
||||||
Transaction t3 = sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, priv2);
|
Transaction t3 = sendMoneyToWallet(AbstractBlockChain.NewBlockType.BEST_CHAIN, CENT, priv2);
|
||||||
|
|
||||||
Wallet.SendRequest req = Wallet.SendRequest.emptyWallet(OTHER_ADDRESS);
|
SendRequest req = SendRequest.emptyWallet(OTHER_ADDRESS);
|
||||||
req.missingSigsMode = missSigMode;
|
req.missingSigsMode = missSigMode;
|
||||||
wallet.completeTx(req);
|
wallet.completeTx(req);
|
||||||
byte[] dummySig = TransactionSignature.dummy().encodeToBitcoin();
|
byte[] dummySig = TransactionSignature.dummy().encodeToBitcoin();
|
||||||
@@ -3397,7 +3396,7 @@ public class WalletTest extends TestWithWallet {
|
|||||||
Address myAddress = wallet.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS);
|
Address myAddress = wallet.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS);
|
||||||
sendMoneyToWallet(wallet, AbstractBlockChain.NewBlockType.BEST_CHAIN, COIN, myAddress);
|
sendMoneyToWallet(wallet, AbstractBlockChain.NewBlockType.BEST_CHAIN, COIN, myAddress);
|
||||||
|
|
||||||
Wallet.SendRequest req = Wallet.SendRequest.emptyWallet(OTHER_ADDRESS);
|
SendRequest req = SendRequest.emptyWallet(OTHER_ADDRESS);
|
||||||
req.missingSigsMode = Wallet.MissingSigsMode.USE_DUMMY_SIG;
|
req.missingSigsMode = Wallet.MissingSigsMode.USE_DUMMY_SIG;
|
||||||
wallet.completeTx(req);
|
wallet.completeTx(req);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import org.bitcoinj.core.listeners.PeerDisconnectedEventListener;
|
|||||||
import org.bitcoinj.kits.WalletAppKit;
|
import org.bitcoinj.kits.WalletAppKit;
|
||||||
import org.bitcoinj.params.MainNetParams;
|
import org.bitcoinj.params.MainNetParams;
|
||||||
import org.bitcoinj.utils.BriefLogFormatter;
|
import org.bitcoinj.utils.BriefLogFormatter;
|
||||||
|
import org.bitcoinj.wallet.SendRequest;
|
||||||
import org.bitcoinj.wallet.Wallet;
|
import org.bitcoinj.wallet.Wallet;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -74,7 +75,7 @@ public class TestFeeLevel {
|
|||||||
value = value.subtract(outputValue);
|
value = value.subtract(outputValue);
|
||||||
}
|
}
|
||||||
transaction.addOutput(value, kit.wallet().freshReceiveAddress());
|
transaction.addOutput(value, kit.wallet().freshReceiveAddress());
|
||||||
Wallet.SendRequest request = Wallet.SendRequest.forTx(transaction);
|
SendRequest request = SendRequest.forTx(transaction);
|
||||||
request.feePerKb = feeToTest;
|
request.feePerKb = feeToTest;
|
||||||
request.ensureMinRequiredFee = false;
|
request.ensureMinRequiredFee = false;
|
||||||
kit.wallet().completeTx(request);
|
kit.wallet().completeTx(request);
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import org.bitcoinj.core.listeners.BlocksDownloadedEventListener;
|
|||||||
import org.bitcoinj.core.listeners.DownloadProgressTracker;
|
import org.bitcoinj.core.listeners.DownloadProgressTracker;
|
||||||
import org.bitcoinj.wallet.MarriedKeyChain;
|
import org.bitcoinj.wallet.MarriedKeyChain;
|
||||||
import org.bitcoinj.wallet.Protos;
|
import org.bitcoinj.wallet.Protos;
|
||||||
|
import org.bitcoinj.wallet.SendRequest;
|
||||||
import org.bitcoinj.wallet.Wallet;
|
import org.bitcoinj.wallet.Wallet;
|
||||||
import org.bitcoinj.wallet.WalletExtension;
|
import org.bitcoinj.wallet.WalletExtension;
|
||||||
import org.bitcoinj.wallet.WalletProtobufSerializer;
|
import org.bitcoinj.wallet.WalletProtobufSerializer;
|
||||||
@@ -594,7 +595,7 @@ public class WalletTool {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Wallet.SendRequest req = Wallet.SendRequest.forTx(t);
|
SendRequest req = SendRequest.forTx(t);
|
||||||
if (t.getOutputs().size() == 1 && t.getOutput(0).getValue().equals(wallet.getBalance())) {
|
if (t.getOutputs().size() == 1 && t.getOutput(0).getValue().equals(wallet.getBalance())) {
|
||||||
log.info("Emptying out wallet, recipient may get less than what you expect");
|
log.info("Emptying out wallet, recipient may get less than what you expect");
|
||||||
req.emptyWallet = true;
|
req.emptyWallet = true;
|
||||||
@@ -726,7 +727,7 @@ public class WalletTool {
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
Wallet.SendRequest req = Wallet.SendRequest.toCLTVPaymentChannel(params, BigInteger.valueOf(lockTime), refundKey, outputKey, value);
|
SendRequest req = SendRequest.toCLTVPaymentChannel(params, BigInteger.valueOf(lockTime), refundKey, outputKey, value);
|
||||||
if (req.tx.getOutputs().size() == 1 && req.tx.getOutput(0).getValue().equals(wallet.getBalance())) {
|
if (req.tx.getOutputs().size() == 1 && req.tx.getOutput(0).getValue().equals(wallet.getBalance())) {
|
||||||
log.info("Emptying out wallet, recipient may get less than what you expect");
|
log.info("Emptying out wallet, recipient may get less than what you expect");
|
||||||
req.emptyWallet = true;
|
req.emptyWallet = true;
|
||||||
@@ -796,9 +797,9 @@ public class WalletTool {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Wallet.SendRequest req = outputSpec.isAddress() ?
|
SendRequest req = outputSpec.isAddress() ?
|
||||||
Wallet.SendRequest.to(outputSpec.addr, value) :
|
SendRequest.to(outputSpec.addr, value) :
|
||||||
Wallet.SendRequest.to(params, outputSpec.key, value);
|
SendRequest.to(params, outputSpec.key, value);
|
||||||
if (feePerKb != null)
|
if (feePerKb != null)
|
||||||
req.feePerKb = feePerKb;
|
req.feePerKb = feePerKb;
|
||||||
|
|
||||||
@@ -900,9 +901,9 @@ public class WalletTool {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Wallet.SendRequest req = outputSpec.isAddress() ?
|
SendRequest req = outputSpec.isAddress() ?
|
||||||
Wallet.SendRequest.to(outputSpec.addr, value) :
|
SendRequest.to(outputSpec.addr, value) :
|
||||||
Wallet.SendRequest.to(params, outputSpec.key, value);
|
SendRequest.to(params, outputSpec.key, value);
|
||||||
if (feePerKb != null)
|
if (feePerKb != null)
|
||||||
req.feePerKb = feePerKb;
|
req.feePerKb = feePerKb;
|
||||||
|
|
||||||
@@ -1057,7 +1058,7 @@ public class WalletTool {
|
|||||||
System.out.println("Pki-Verified Name: " + session.pkiVerificationData.displayName);
|
System.out.println("Pki-Verified Name: " + session.pkiVerificationData.displayName);
|
||||||
System.out.println("PKI data verified by: " + session.pkiVerificationData.rootAuthorityName);
|
System.out.println("PKI data verified by: " + session.pkiVerificationData.rootAuthorityName);
|
||||||
}
|
}
|
||||||
final Wallet.SendRequest req = session.getSendRequest();
|
final SendRequest req = session.getSendRequest();
|
||||||
if (password != null) {
|
if (password != null) {
|
||||||
req.aesKey = passwordToKey(true);
|
req.aesKey = passwordToKey(true);
|
||||||
if (req.aesKey == null)
|
if (req.aesKey == null)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ package wallettemplate;
|
|||||||
|
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import org.bitcoinj.core.*;
|
import org.bitcoinj.core.*;
|
||||||
|
import org.bitcoinj.wallet.SendRequest;
|
||||||
import org.bitcoinj.wallet.Wallet;
|
import org.bitcoinj.wallet.Wallet;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
@@ -66,11 +67,11 @@ public class SendMoneyController {
|
|||||||
try {
|
try {
|
||||||
Coin amount = Coin.parseCoin(amountEdit.getText());
|
Coin amount = Coin.parseCoin(amountEdit.getText());
|
||||||
Address destination = Address.fromBase58(Main.params, address.getText());
|
Address destination = Address.fromBase58(Main.params, address.getText());
|
||||||
Wallet.SendRequest req;
|
SendRequest req;
|
||||||
if (amount.equals(Main.bitcoin.wallet().getBalance()))
|
if (amount.equals(Main.bitcoin.wallet().getBalance()))
|
||||||
req = Wallet.SendRequest.emptyWallet(destination);
|
req = SendRequest.emptyWallet(destination);
|
||||||
else
|
else
|
||||||
req = Wallet.SendRequest.to(destination, amount);
|
req = SendRequest.to(destination, amount);
|
||||||
req.aesKey = aesKey;
|
req.aesKey = aesKey;
|
||||||
sendResult = Main.bitcoin.wallet().sendCoins(req);
|
sendResult = Main.bitcoin.wallet().sendCoins(req);
|
||||||
Futures.addCallback(sendResult.broadcastComplete, new FutureCallback<Transaction>() {
|
Futures.addCallback(sendResult.broadcastComplete, new FutureCallback<Transaction>() {
|
||||||
|
|||||||
Reference in New Issue
Block a user