I’ve been experimenting with the Bitcoin wallet daemon btcwallet for some time. btcd and btcwallet provide support for notifications via websockets which allows to process bitcoin payments in an event-driven programming style instead of polling. As of this writing proper notification support in bitcoind seems to be in limbo state (cf. this and that). It is possible to get notifications using scripts and the *notify command-line options but this seems to be a rather hackish solution.
So let’s build a websocket client to btcwallet. How do we do that in my favorite programming language, Scala?
Usually, it’s inconvenient to use websocket or json APIs directly. As an abstraction to btcwallet’s websocket API I use akka, a library that implements the Actor model. Actors are threadless, stackless units of execution that process messages (events) serially. Messages are delivered to an Actor’s mailbox, and the Actor processes them by looping over a method that pops the first message from the mailbox.David Pollak, Beginning Scala, Apress, Berkely, CA, 2009 I want to talk to btcwallet using Actor messages and receive Futures in return. Those messages will then be forwarded to btcwallet using its websocket API. When a response is available the corresponding Future will be completed.
Therefore, we can design our websocket client as follows. We define our
BtcWalletActor such that it establishes a websocket connection to btcwallet as soon as it starts. If it loses the connection, it tries to reconnect in five seconds intervals. Objects that need to talk to the websocket service use the ask pattern to send requests to our actor. Finally, we define the reactions to notifications and requests by implementing the
receive method of our actor.
In order to connect to our service we need a websocket library. There are several different options available. I’ve chosen Java-WebSocket because it is actively maintained, popular, and has support for TLS connections (right now only in the 1.3.1 development snapshot).
We also need a library for serializing and deserializing JSON. Again, there are numerous libraries available. I’ve chosen play-json. We also define some case classes for our actor messages, and for the JSON serialization.
Websocket messages are asynchronous, there is no request-response standard in the protocol. To work around this, btcwallet uses IDs in the request and response messages. Hence, when we make a request we need to supply and store an id for it. Then we can match the response message to our request.
To account for this aspect we implement our actor as follows. When our actor processes a message from another object that requests information from the websocket service, it creates a Promise and pipes the corresponding Future to the object that requested it. Then it generates a UUID for the request and saves it together with the Promise in a Map. After it receives the response (which also contains the UUID), it pops the Promise from the Map and fulfils it with the response. If you’re wondering what Futures and Promises are, then check out this introductory guide.
Once we put everything together, we get something like this (GitHub). I’ve provided an example in which I’m processing incoming transactions by sending the bitcoins back to the sender address. I’m using the outputs of the incoming transactions as inputs of the corresponding outgoing transactions. Therefore, there is no need to wait for confirmations.
Notes [ + ]