Class WalletAppKit

java.lang.Object
com.google.common.util.concurrent.AbstractIdleService
org.bitcoinj.kits.WalletAppKit
All Implemented Interfaces:
com.google.common.util.concurrent.Service, Closeable, AutoCloseable

public class WalletAppKit extends com.google.common.util.concurrent.AbstractIdleService implements Closeable

Utility class that wraps the boilerplate needed to set up a new SPV bitcoinj app. Instantiate it with a directory and file prefix, optionally configure a few things, then use startAsync and optionally awaitRunning. The object will construct and configure a BlockChain, SPVBlockStore, Wallet and PeerGroup. Depending on the value of the blockingStartup property, startup will be considered complete once the block chain has fully synchronized, so it can take a while.

To add listeners and modify the objects that are constructed, you can either do that by overriding the onSetupCompleted() method (which will run on a background thread) and make your changes there, or by waiting for the service to start and then accessing the objects from wherever you want. However, you cannot access the objects this class creates until startup is complete.

The asynchronous design of this class may seem puzzling (just use AbstractIdleService.awaitRunning() if you don't want that). It is to make it easier to fit bitcoinj into GUI apps, which require a high degree of responsiveness on their main thread which handles all the animation and user interaction. Even when blockingStart is false, initializing bitcoinj means doing potentially blocking file IO, generating keys and other potentially intensive operations. By running it on a background thread, there's no risk of accidentally causing UI lag.

Note that AbstractIdleService.awaitRunning() can throw an unchecked IllegalStateException if anything goes wrong during startup - you should probably handle it and use Throwable.getCause() to figure out what went wrong more precisely. Same thing if you just use the AbstractIdleService.startAsync() method.

  • Field Details

    • log

      protected static final org.slf4j.Logger log
    • network

      protected final BitcoinNetwork network
    • params

      protected final NetworkParameters params
    • preferredOutputScriptType

      protected final ScriptType preferredOutputScriptType
    • structure

      protected final KeyChainGroupStructure structure
    • filePrefix

      protected final String filePrefix
    • vChain

      protected volatile BlockChain vChain
    • vStore

      protected volatile SPVBlockStore vStore
    • vWallet

      protected volatile Wallet vWallet
    • vPeerGroup

      protected volatile PeerGroup vPeerGroup
    • directory

      protected final File directory
    • vWalletFile

      protected volatile File vWalletFile
    • useAutoSave

      protected boolean useAutoSave
    • peerAddresses

      protected PeerAddress[] peerAddresses
    • downloadListener

      protected DownloadProgressTracker downloadListener
    • autoStop

      protected boolean autoStop
    • checkpoints

      protected InputStream checkpoints
    • blockingStartup

      protected boolean blockingStartup
    • userAgent

      protected String userAgent
    • version

      protected String version
    • walletFactory

      @Nonnull protected WalletProtobufSerializer.WalletFactory walletFactory
    • restoreFromSeed

      @Nullable protected DeterministicSeed restoreFromSeed
    • restoreFromKey

      @Nullable protected DeterministicKey restoreFromKey
    • discovery

      @Nullable protected PeerDiscovery discovery
  • Constructor Details

  • Method Details

    • launch

      public static WalletAppKit launch(BitcoinNetwork network, File directory, String filePrefix)
      Launch an instance of WalletAppKit with asynchronous startup. Wait until the PeerGroup is initialized.
      Parameters:
      network - The network the wallet connects to
      directory - The directory for creating .wallet and .spvchain files
      filePrefix - The base name for the .wallet and .spvchain files
      Returns:
      the instance
    • launch

      public static WalletAppKit launch(BitcoinNetwork network, File directory, String filePrefix, Consumer<WalletAppKit> configurer)
      Launch an instance of WalletAppKit with asynchronous startup. Wait until the PeerGroup is initialized.
      Parameters:
      network - The network the wallet connects to
      directory - The directory for creating .wallet and .spvchain files
      filePrefix - The base name for the .wallet and .spvchain files
      configurer - Callback to allow configuring the kit before it is started
      Returns:
      the instance
    • launch

      public static WalletAppKit launch(BitcoinNetwork network, File directory, String filePrefix, int maxConnections)
      Launch an instance of WalletAppKit with asynchronous startup. Wait until the PeerGroup is initialized.
      Parameters:
      network - The network the wallet connects to
      directory - The directory for creating .wallet and .spvchain files
      filePrefix - The base name for the .wallet and .spvchain files
      maxConnections - maximum number of peer connections.
      Returns:
      the instance
    • launch

      public static WalletAppKit launch(BitcoinNetwork network, File directory, String filePrefix, Consumer<WalletAppKit> configurer, int maxConnections)
      Launch an instance of WalletAppKit with asynchronous startup. Wait until the PeerGroup is initialized.
      Parameters:
      network - The network the wallet connects to
      directory - The directory for creating .wallet and .spvchain files
      filePrefix - The base name for the .wallet and .spvchain files
      configurer - Callback to allow configuring the kit before it is started
      maxConnections - maximum number of peer connections.
      Returns:
      the instance
    • setPeerNodes

      public WalletAppKit setPeerNodes(PeerAddress... addresses)
      Will only connect to the given addresses. Cannot be called after startup.
    • connectToLocalHost

      public WalletAppKit connectToLocalHost()
      Will only connect to localhost. Cannot be called after startup.
    • setAutoSave

      public WalletAppKit setAutoSave(boolean value)
      If true, the wallet will save itself to disk automatically whenever it changes.
    • setDownloadListener

      public WalletAppKit setDownloadListener(DownloadProgressTracker listener)
      If you want to learn about the sync process, you can provide a listener here. For instance, a DownloadProgressTracker is a good choice. This has no effect unless setBlockingStartup(false) has been called too, due to some missing implementation code.
    • setAutoStop

      public WalletAppKit setAutoStop(boolean autoStop)
      If true, will register a shutdown hook to stop the library. Defaults to true.
    • setCheckpoints

      public WalletAppKit setCheckpoints(InputStream checkpoints)
      If set, the file is expected to contain a checkpoints file calculated with BuildCheckpoints. It makes initial block sync faster for new users - please refer to the documentation on the bitcoinj website (https://bitcoinj.github.io/speeding-up-chain-sync) for further details.
    • setBlockingStartup

      public WalletAppKit setBlockingStartup(boolean blockingStartup)
      If true (the default) then the startup of this service won't be considered complete until the network has been brought up, peer connections established and the block chain synchronised. Therefore AbstractIdleService.awaitRunning() can potentially take a very long time. If false, then startup is considered complete once the network activity begins and peer connections/block chain sync will continue in the background.
    • setUserAgent

      public WalletAppKit setUserAgent(String userAgent, String version)
      Sets the string that will appear in the subver field of the version message.
      Parameters:
      userAgent - A short string that should be the name of your app, e.g. "My Wallet"
      version - A short string that contains the version number, e.g. "1.0-BETA"
    • setWalletFactory

      public WalletAppKit setWalletFactory(@Nonnull WalletProtobufSerializer.WalletFactory walletFactory)
      Sets a wallet factory which will be used when the kit creates a new wallet.
      Parameters:
      walletFactory - Factory for making new wallets (Use WalletProtobufSerializer.WalletFactory.DEFAULT for default behavior)
      Returns:
      WalletAppKit for method chaining purposes
    • restoreWalletFromSeed

      public WalletAppKit restoreWalletFromSeed(DeterministicSeed seed)
      If a seed is set here then any existing wallet that matches the file name will be renamed to a backup name, the chain file will be deleted, and the wallet object will be instantiated with the given seed instead of a fresh one being created. This is intended for restoring a wallet from the original seed. To implement restore you would shut down the existing appkit, if any, then recreate it with the seed given by the user, then start up the new kit. The next time your app starts it should work as normal (that is, don't keep calling this each time).
    • restoreWalletFromKey

      public WalletAppKit restoreWalletFromKey(DeterministicKey accountKey)
      If an account key is set here then any existing wallet that matches the file name will be renamed to a backup name, the chain file will be deleted, and the wallet object will be instantiated with the given key instead of a fresh seed being created. This is intended for restoring a wallet from an account key. To implement restore you would shut down the existing appkit, if any, then recreate it with the key given by the user, then start up the new kit. The next time your app starts it should work as normal (that is, don't keep calling this each time).
    • setDiscovery

      public WalletAppKit setDiscovery(@Nullable PeerDiscovery discovery)
      Sets the peer discovery class to use. If none is provided then DNS is used, which is a reasonable default.
    • provideWalletExtensions

      protected List<WalletExtension> provideWalletExtensions() throws Exception

      Override this to return wallet extensions if any are necessary.

      When this is called, chain(), store(), and peerGroup() will return the created objects, however they are not initialized/started.

      Throws:
      Exception
    • onSetupCompleted

      protected void onSetupCompleted()
      This method is invoked on a background thread after all objects are initialised, but before the peer group or block chain download is started. You can tweak the objects configuration here.
    • isChainFileLocked

      public boolean isChainFileLocked() throws IOException
      Tests to see if the spvchain file has an operating system file lock on it. Useful for checking if your app is already running. If another copy of your app is running and you start the appkit anyway, an exception will be thrown during the startup process. Returns false if the chain file does not exist or is a directory.
      Throws:
      IOException
    • startUp

      protected void startUp() throws Exception
      Specified by:
      startUp in class com.google.common.util.concurrent.AbstractIdleService
      Throws:
      Exception
    • setupAutoSave

      protected void setupAutoSave(Wallet wallet)
    • createWallet

      protected Wallet createWallet()
    • createPeerGroup

      protected PeerGroup createPeerGroup()
    • shutDown

      protected void shutDown() throws Exception
      Specified by:
      shutDown in class com.google.common.util.concurrent.AbstractIdleService
      Throws:
      Exception
    • close

      public void close()
      Close and release resources. Implements Closeable. This should be idempotent.
      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface Closeable
    • network

      public BitcoinNetwork network()
    • params

      public NetworkParameters params()
    • chain

      public BlockChain chain()
    • store

      public BlockStore store()
    • wallet

      public Wallet wallet()
    • peerGroup

      public PeerGroup peerGroup()
    • directory

      public File directory()