WalletAppKit: add launch() methods, simplify examples

This commit is contained in:
Sean Gilligan 2023-03-26 14:45:13 -07:00 committed by Andreas Schildbach
parent 41ed5a984b
commit 3b6bdbad02
5 changed files with 86 additions and 54 deletions

View File

@ -60,6 +60,7 @@ import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import static org.bitcoinj.base.internal.Preconditions.checkState;
@ -151,6 +152,77 @@ public class WalletAppKit extends AbstractIdleService implements Closeable {
this.filePrefix = Objects.requireNonNull(filePrefix);
}
/**
* Launch an instance of WalletAppKit with asynchronous startup. Wait until the PeerGroup is initialized.
*
* @param network The network the wallet connects to
* @param directory The directory for creating {@code .wallet} and {@code .spvchain} files
* @param filePrefix The base name for the {@code .wallet} and {@code .spvchain} files
* @return the instance
*/
public static WalletAppKit launch(BitcoinNetwork network, File directory, String filePrefix) {
return WalletAppKit.launch(network, directory, filePrefix, 0);
}
/**
* Launch an instance of WalletAppKit with asynchronous startup. Wait until the PeerGroup is initialized.
*
* @param network The network the wallet connects to
* @param directory The directory for creating {@code .wallet} and {@code .spvchain} files
* @param filePrefix The base name for the {@code .wallet} and {@code .spvchain} files
* @param configurer Callback to allow configuring the kit before it is started
* @return the instance
*/
public static WalletAppKit launch(BitcoinNetwork network, File directory, String filePrefix, Consumer<WalletAppKit> configurer) {
return WalletAppKit.launch(network, directory, filePrefix, configurer, 0);
}
/**
* Launch an instance of WalletAppKit with asynchronous startup. Wait until the PeerGroup is initialized.
*
* @param network The network the wallet connects to
* @param directory The directory for creating {@code .wallet} and {@code .spvchain} files
* @param filePrefix The base name for the {@code .wallet} and {@code .spvchain} files
* @param maxConnections maximum number of peer connections.
* @return the instance
*/
public static WalletAppKit launch(BitcoinNetwork network, File directory, String filePrefix, int maxConnections) {
return WalletAppKit.launch(network, directory, filePrefix, (c) -> {}, maxConnections);
}
/**
* Launch an instance of WalletAppKit with asynchronous startup. Wait until the PeerGroup is initialized.
*
* @param network The network the wallet connects to
* @param directory The directory for creating {@code .wallet} and {@code .spvchain} files
* @param filePrefix The base name for the {@code .wallet} and {@code .spvchain} files
* @param configurer Callback to allow configuring the kit before it is started
* @param maxConnections maximum number of peer connections.
* @return the instance
*/
public static WalletAppKit launch(BitcoinNetwork network, File directory, String filePrefix, Consumer<WalletAppKit> configurer, int maxConnections) {
WalletAppKit kit = new WalletAppKit(network,
ScriptType.P2WPKH,
KeyChainGroupStructure.BIP32,
directory,
filePrefix);
if (network == BitcoinNetwork.REGTEST) {
// Regression test mode is designed for testing and development only, so there's no public network for it.
// If you pick this mode, you're expected to be running a local "bitcoind -regtest" instance.
kit.connectToLocalHost();
}
kit.setBlockingStartup(false); // Don't wait for blockchain synchronization before entering RUNNING state
configurer.accept(kit); // Call configurer before startup
kit.startAsync(); // Connect to the network and start downloading transactions
kit.awaitRunning(); // Wait for the service to reach the RUNNING state
if (maxConnections > 0) {
kit.peerGroup().setMaxConnections(maxConnections);
}
return kit;
}
/** Will only connect to the given addresses. Cannot be called after startup. */
public WalletAppKit setPeerNodes(PeerAddress... addresses) {
checkState(state() == State.NEW, () ->

View File

@ -18,12 +18,10 @@ package org.bitcoinj.examples;
import org.bitcoinj.base.Address;
import org.bitcoinj.base.BitcoinNetwork;
import org.bitcoinj.base.ScriptType;
import org.bitcoinj.core.*;
import org.bitcoinj.kits.WalletAppKit;
import org.bitcoinj.utils.BriefLogFormatter;
import org.bitcoinj.utils.Threading;
import org.bitcoinj.wallet.KeyChainGroupStructure;
import org.bitcoinj.wallet.Wallet;
import java.io.File;
@ -38,11 +36,9 @@ import static org.bitcoinj.base.Coin.*;
public class DoubleSpend {
public static void main(String[] args) throws Exception {
BriefLogFormatter.init();
WalletAppKit kit = new WalletAppKit(BitcoinNetwork.REGTEST, ScriptType.P2WPKH, KeyChainGroupStructure.BIP32, new File("."), "doublespend");
kit.connectToLocalHost();
kit.setAutoSave(false);
kit.startAsync();
kit.awaitRunning();
WalletAppKit kit = WalletAppKit.launch(BitcoinNetwork.REGTEST, new File("."), "doublespend", (k) ->
k.setAutoSave(false)
);
System.out.println(kit.wallet());

View File

@ -17,7 +17,6 @@
package org.bitcoinj.examples;
import org.bitcoinj.base.BitcoinNetwork;
import org.bitcoinj.base.ScriptType;
import org.bitcoinj.base.Sha256Hash;
import org.bitcoinj.base.Address;
import org.bitcoinj.base.Coin;
@ -30,7 +29,6 @@ import org.bitcoinj.kits.WalletAppKit;
import org.bitcoinj.utils.BriefLogFormatter;
import org.bitcoinj.wallet.CoinSelection;
import org.bitcoinj.wallet.CoinSelector;
import org.bitcoinj.wallet.KeyChainGroupStructure;
import org.bitcoinj.wallet.SendRequest;
import org.bitcoinj.wallet.Wallet;
import org.bitcoinj.wallet.listeners.WalletCoinsReceivedEventListener;
@ -112,29 +110,14 @@ public class ForwardingService implements Closeable {
this.network = network;
listener = this::coinsReceivedListener;
// Start up a basic app using a class that automates some boilerplate.
kit = new WalletAppKit(network,
ScriptType.P2WPKH,
KeyChainGroupStructure.BIP32,
directory,
getPrefix(network));
kit = WalletAppKit.launch(network, directory, getPrefix(network), MAX_CONNECTIONS);
}
/**
* Start the WalletAppKit
* Start the ForwardingService
* @return The receiving address for the forwarding wallet
*/
public Address start() {
if (network == BitcoinNetwork.REGTEST) {
// Regression test mode is designed for testing and development only, so there's no public network for it.
// If you pick this mode, you're expected to be running a local "bitcoind -regtest" instance.
kit.connectToLocalHost();
}
kit.setBlockingStartup(false); // Don't wait for blockchain synchronization before entering RUNNING state
kit.startAsync(); // Connect to the network and start downloading transactions
kit.awaitRunning(); // Wait for the service to reach the RUNNING state
kit.peerGroup().setMaxConnections(MAX_CONNECTIONS);
// Start listening and forwarding
kit.wallet().addCoinsReceivedEventListener(listener);
return kit.wallet().currentReceiveAddress();

View File

@ -17,20 +17,10 @@
package org.bitcoinj.examples;
import org.bitcoinj.base.BitcoinNetwork;
import org.bitcoinj.base.ScriptType;
import org.bitcoinj.core.*;
import org.bitcoinj.kits.WalletAppKit;
import org.bitcoinj.wallet.KeyChainGroupStructure;
import org.bitcoinj.wallet.Wallet;
import org.bitcoinj.wallet.listeners.KeyChainEventListener;
import org.bitcoinj.wallet.listeners.ScriptsChangeEventListener;
import org.bitcoinj.wallet.listeners.WalletCoinsReceivedEventListener;
import org.bitcoinj.wallet.listeners.WalletCoinsSentEventListener;
import java.io.File;
import java.util.List;
import org.bitcoinj.core.listeners.TransactionConfidenceEventListener;
/**
* The following example shows how to use the by bitcoinj provided WalletAppKit.
@ -55,18 +45,14 @@ public class Kit {
// For more information have a look at: https://bitcoinj.github.io/testing and https://bitcoin.org/en/developer-examples#testing-applications
BitcoinNetwork network = BitcoinNetwork.TESTNET;
// Now we initialize a new WalletAppKit. The kit handles all the boilerplate for us and is the easiest way to get everything up and running.
// Have a look at the WalletAppKit documentation and its source to understand what's happening behind the scenes: https://github.com/bitcoinj/bitcoinj/blob/master/core/src/main/java/org/bitcoinj/kits/WalletAppKit.java
WalletAppKit kit = new WalletAppKit(network, ScriptType.P2WPKH, KeyChainGroupStructure.BIP32, new File("."), "walletappkit-example");
// In case you want to connect with your local bitcoind tell the kit to connect to localhost.
// You must do that in reg test mode.
//kit.connectToLocalHost();
// Now we start the kit and sync the blockchain.
// bitcoinj is working a lot with the Google Guava libraries. The WalletAppKit extends the AbstractIdleService. Have a look at the introduction to Guava services: https://github.com/google/guava/wiki/ServiceExplained
kit.startAsync();
kit.awaitRunning();
// Initialize and start a WalletAppKit. The kit handles all the boilerplate for us and is the easiest way to get everything up and running.
// Look at the WalletAppKit documentation and its source to understand what's happening behind the scenes: https://github.com/bitcoinj/bitcoinj/blob/master/core/src/main/java/org/bitcoinj/kits/WalletAppKit.java
// WalletAppKit extends the Guava AbstractIdleService. Have a look at the introduction to Guava services: https://github.com/google/guava/wiki/ServiceExplained
WalletAppKit kit = WalletAppKit.launch(network, new File("."), "walletappkit-example", (k) -> {
// In case you want to connect with your local bitcoind tell the kit to connect to localhost.
// This is done automatically in reg test mode.
// k.connectToLocalHost();
});
kit.wallet().addCoinsReceivedEventListener((wallet, tx, prevBalance, newBalance) -> {
System.out.println("-----> coins resceived: " + tx.getTxId());

View File

@ -19,10 +19,8 @@ package org.bitcoinj.examples;
import org.bitcoinj.base.Address;
import org.bitcoinj.base.BitcoinNetwork;
import org.bitcoinj.base.Coin;
import org.bitcoinj.base.ScriptType;
import org.bitcoinj.core.*;
import org.bitcoinj.kits.WalletAppKit;
import org.bitcoinj.wallet.KeyChainGroupStructure;
import org.bitcoinj.wallet.Wallet;
import org.bitcoinj.wallet.Wallet.BalanceType;
@ -37,10 +35,7 @@ public class SendRequest {
public static void main(String[] args) throws Exception {
// We use the WalletAppKit that handles all the boilerplate for us. Have a look at the Kit.java example for more details.
WalletAppKit kit = new WalletAppKit(BitcoinNetwork.TESTNET, ScriptType.P2WPKH, KeyChainGroupStructure.BIP32, new File("."), "sendrequest-example");
kit.startAsync();
kit.awaitRunning();
WalletAppKit kit = WalletAppKit.launch(BitcoinNetwork.TESTNET, new File("."), "sendrequest-example");
// How much coins do we want to send?
// The Coin class represents a monetary Bitcoin value.