Recommended patterns
This page details some of the patterns we have adopted in our example apps (Web3Torrent and Rock Paper Scissors).
Decide on a funding strategy
This decision has an impact on how your design your application.
Direct
The user experience for a directly funded channel is that users need to deposit funds on chain during channel setup, and release them on chain during channel teardown. The wallet UI will pop up at the appropriate time to guide the user through those transactions.
Virtual
The user experience for a virtually funded channel is improved, in that users need only perform blockchain transactions in order to setup and a teard own a "site budget" and ledger channel connection to a state channel hub.
They might set this up on their first visit to your application, and maintain it for the lifetime of many application channels, which are then funded virtually through the hub. Importantly, the wallet UI will pop up when administering the hub connection, but will not pop up during management of application channels.
This route is best when you need to setup and teardown many channels between many distinct peers during the course of the application (as you would, for example, in a torrenting application).
Using the virtual funding strategy demands a much greater effort with respect to infastructure you must provide -- in particular it requires a state channel hub to be running. At the protocol level, this is just another statechannel participant: but in practice it needs to fulfill a number of important properties: for example, to be well funded, operate without user input and so on. Our reference implementation of such a hub is coming soon.
For a simple game like Rock Paper Scissors, the advantages of virtual funding may or may not be considered necessary. Regardless, switching from direct-funding to virtual-funding at a later stage should be straightforward: statechannel execution should be completely independent of the funding mechanism.
Application coding
In order for your app to construct state updates of the right format, you'll need to write some Javascript or Typescript helper code. The purpose of this code is to translate between the general-purpose, protocol-level concepts of appData
and outcome
and the specific data structures that your application needs to work with. Those structures should mirror those in the Solidity code you have already written. Here's an idea of what we did in Rock Paper Scissors (see the Solidity code here):
Wrapping the channelClient
We recommend that you wrap the channelClient in an AppSecificChannelClient
, which can leverage your app-specific coding as above. This additional layer of abstraction should result in cleaner code for the rest of your application.
Here's a sketch of what we did with Rock Paper Scissors (full code available here):
Maintain a cache of channel state
This is convenient data structure to maintain inside your channel client wrapper, as it can provide data synchronously to your UI.