mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-03-13 19:37:49 +01:00
Merge 3a2a4b655f
into 93519cc65a
This commit is contained in:
commit
13eac0c6d5
2 changed files with 43 additions and 3 deletions
core/src/main/java/org/bitcoinj/core
wallettool/src/main/java/org/bitcoinj/wallettool
|
@ -34,6 +34,7 @@ import org.bitcoinj.wallet.Wallet;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.nio.BufferOverflowException;
|
import java.nio.BufferOverflowException;
|
||||||
import java.nio.BufferUnderflowException;
|
import java.nio.BufferUnderflowException;
|
||||||
|
@ -41,6 +42,7 @@ import java.nio.ByteBuffer;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import static org.bitcoinj.base.internal.Preconditions.checkArgument;
|
import static org.bitcoinj.base.internal.Preconditions.checkArgument;
|
||||||
import static org.bitcoinj.base.internal.Preconditions.checkState;
|
import static org.bitcoinj.base.internal.Preconditions.checkState;
|
||||||
|
@ -160,6 +162,25 @@ public class TransactionOutput {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can this output be converted to an address (for a given network.)
|
||||||
|
* @return true if this output has an address, false otherwise
|
||||||
|
*/
|
||||||
|
public boolean hasAddress() {
|
||||||
|
Script script = getScriptPubKey();
|
||||||
|
return ScriptPattern.isP2PKH(script) || ScriptPattern.isP2WPKH(script) || ScriptPattern.isP2TR(script) || ScriptPattern.isP2SH(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the address for this output.
|
||||||
|
* @param network the network this output exists on
|
||||||
|
* @return The address for this output or empty if an address can't be extracted
|
||||||
|
*/
|
||||||
|
public Optional<Address> getAddress(@Nonnull Network network) {
|
||||||
|
Objects.requireNonNull(network);
|
||||||
|
return Optional.ofNullable(hasAddress() ? getScriptPubKey().getToAddress(network) : null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value of this output. This is the amount of currency that the destination address
|
* Returns the value of this output. This is the amount of currency that the destination address
|
||||||
* receives.
|
* receives.
|
||||||
|
@ -357,11 +378,10 @@ public class TransactionOutput {
|
||||||
buf.append(Coin.valueOf(value).toFriendlyString());
|
buf.append(Coin.valueOf(value).toFriendlyString());
|
||||||
try {
|
try {
|
||||||
Script script = getScriptPubKey();
|
Script script = getScriptPubKey();
|
||||||
if (ScriptPattern.isP2PKH(script) || ScriptPattern.isP2WPKH(script) || ScriptPattern.isP2TR(script)
|
if (hasAddress()) {
|
||||||
|| ScriptPattern.isP2SH(script)) {
|
|
||||||
buf.append(" to ").append(script.getScriptType().name());
|
buf.append(" to ").append(script.getScriptType().name());
|
||||||
if (network != null)
|
if (network != null)
|
||||||
buf.append(" ").append(script.getToAddress(network));
|
buf.append(" ").append(getAddress(network).get());
|
||||||
} else if (ScriptPattern.isP2PK(script)) {
|
} else if (ScriptPattern.isP2PK(script)) {
|
||||||
buf.append(" to pubkey ").append(ByteUtils.formatHex(ScriptPattern.extractKeyFromP2PK(script)));
|
buf.append(" to pubkey ").append(ByteUtils.formatHex(ScriptPattern.extractKeyFromP2PK(script)));
|
||||||
} else if (ScriptPattern.isSentToMultisig(script)) {
|
} else if (ScriptPattern.isSentToMultisig(script)) {
|
||||||
|
|
|
@ -107,6 +107,7 @@ public class WalletTool implements Callable<Integer> {
|
||||||
" dump Loads and prints the given wallet in textual form to stdout. Private keys and seed are only printed if --dump-privkeys is specified. If the wallet is encrypted, also specify the --password option to dump the private keys and seed.%n" +
|
" dump Loads and prints the given wallet in textual form to stdout. Private keys and seed are only printed if --dump-privkeys is specified. If the wallet is encrypted, also specify the --password option to dump the private keys and seed.%n" +
|
||||||
" If --dump-lookahead is present, also show pregenerated but not yet issued keys.%n" +
|
" If --dump-lookahead is present, also show pregenerated but not yet issued keys.%n" +
|
||||||
" raw-dump Prints the wallet as a raw protobuf with no parsing or sanity checking applied.%n" +
|
" raw-dump Prints the wallet as a raw protobuf with no parsing or sanity checking applied.%n" +
|
||||||
|
" listunspent Prints unspent outputs in a simple format%n" +
|
||||||
" create Makes a new wallet in the file specified by --wallet. Will complain and require --force if the wallet already exists.%n" +
|
" create Makes a new wallet in the file specified by --wallet. Will complain and require --force if the wallet already exists.%n" +
|
||||||
" If --seed is present, it should specify either a mnemonic code or hex/base58 raw seed bytes.%n" +
|
" If --seed is present, it should specify either a mnemonic code or hex/base58 raw seed bytes.%n" +
|
||||||
" If --watchkey is present, it creates a watching wallet using the specified base58 xpub.%n" +
|
" If --watchkey is present, it creates a watching wallet using the specified base58 xpub.%n" +
|
||||||
|
@ -291,6 +292,7 @@ public class WalletTool implements Callable<Integer> {
|
||||||
public enum ActionEnum {
|
public enum ActionEnum {
|
||||||
DUMP,
|
DUMP,
|
||||||
RAW_DUMP,
|
RAW_DUMP,
|
||||||
|
LISTUNSPENT,
|
||||||
CREATE,
|
CREATE,
|
||||||
ADD_KEY,
|
ADD_KEY,
|
||||||
ADD_ADDR,
|
ADD_ADDR,
|
||||||
|
@ -391,6 +393,7 @@ public class WalletTool implements Callable<Integer> {
|
||||||
// What should we do?
|
// What should we do?
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case DUMP: dumpWallet(); break;
|
case DUMP: dumpWallet(); break;
|
||||||
|
case LISTUNSPENT: listUnspent(); break;
|
||||||
case ADD_KEY: addKey(); break;
|
case ADD_KEY: addKey(); break;
|
||||||
case ADD_ADDR: addAddr(); break;
|
case ADD_ADDR: addAddr(); break;
|
||||||
case DELETE_KEY: deleteKey(); break;
|
case DELETE_KEY: deleteKey(); break;
|
||||||
|
@ -1100,6 +1103,23 @@ public class WalletTool implements Callable<Integer> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void listUnspent() throws BlockStoreException {
|
||||||
|
// Setup to get the chain height so we can estimate lock times, but don't wipe the transactions if it's not
|
||||||
|
// there just for the listUnspent case.
|
||||||
|
if (chainFile.exists())
|
||||||
|
setup();
|
||||||
|
|
||||||
|
List<TransactionOutput> unspent = wallet.getUnspents();
|
||||||
|
Coin total = unspent.stream()
|
||||||
|
.map(TransactionOutput::getValue)
|
||||||
|
.reduce(Coin.ZERO, Coin::add);
|
||||||
|
unspent.forEach(output -> {
|
||||||
|
String addressInfo = output.getAddress(net).map(Object::toString).orElse("address unavailable");
|
||||||
|
System.out.printf("%s: %s\n", addressInfo , output.getValue().toPlainString());
|
||||||
|
});
|
||||||
|
System.out.printf("\nTotal: %s\n", total.toPlainString());
|
||||||
|
}
|
||||||
|
|
||||||
private void printWallet(@Nullable AesKey aesKey) {
|
private void printWallet(@Nullable AesKey aesKey) {
|
||||||
System.out.println(wallet.toString(dumpLookAhead, dumpPrivKeys, aesKey, true, true, chain));
|
System.out.println(wallet.toString(dumpLookAhead, dumpPrivKeys, aesKey, true, true, chain));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue