Class WalletAppKit

  • All Implemented Interfaces:
    com.google.common.util.concurrent.Service, java.io.Closeable, java.lang.AutoCloseable

    public class WalletAppKit
    extends com.google.common.util.concurrent.AbstractIdleService
    implements java.io.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 Detail

      • log

        protected static final org.slf4j.Logger log
      • preferredOutputScriptType

        protected final ScriptType preferredOutputScriptType
      • filePrefix

        protected final java.lang.String filePrefix
      • vWallet

        protected volatile Wallet vWallet
      • vPeerGroup

        protected volatile PeerGroup vPeerGroup
      • directory

        protected final java.io.File directory
      • vWalletFile

        protected volatile java.io.File vWalletFile
      • useAutoSave

        protected boolean useAutoSave
      • autoStop

        protected boolean autoStop
      • checkpoints

        protected java.io.InputStream checkpoints
      • blockingStartup

        protected boolean blockingStartup
      • userAgent

        protected java.lang.String userAgent
      • version

        protected java.lang.String version
    • Method Detail

      • launch

        public static WalletAppKit launch​(BitcoinNetwork network,
                                          java.io.File directory,
                                          java.lang.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,
                                          java.io.File directory,
                                          java.lang.String filePrefix,
                                          java.util.function.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,
                                          java.io.File directory,
                                          java.lang.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,
                                          java.io.File directory,
                                          java.lang.String filePrefix,
                                          java.util.function.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​(java.io.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​(java.lang.String userAgent,
                                         java.lang.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"
      • 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 java.util.List<WalletExtension> provideWalletExtensions()
                                                                   throws java.lang.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:
        java.lang.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 java.io.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:
        java.io.IOException
      • startUp

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

        protected void setupAutoSave​(Wallet wallet)
      • createWallet

        protected Wallet createWallet()
      • createPeerGroup

        protected PeerGroup createPeerGroup()
      • shutDown

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

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

        public Wallet wallet()
      • directory

        public java.io.File directory()