Client Node

The interactions with go-perun channels are managed by a Client object. This Client object is of central importance. All the foregone setup was only means to be able to create it since the client.New function needs all of them as input. To manage all state we will create a node struct:

type node struct {
	role Role

	account         wallet.Account
	transactor      *hd.Transactor
	contractBackend ethchannel.ContractBackend
	assetholder     common.Address
	listener        net.Listener
	bus             *net.Bus
	client          *client.Client
	ch              *client.Channel
	done            chan struct{} // Signals that the channel got closed.

It is named node to not be mixed up with a go-perun Client.


go-perun uses callbacks to forward interactions from the channels to the user. There are four callbacks that the user needs to provide; Proposal, Update, NewChannel and AdjudicatorEvent. go-perun expects the user to implement two interfaces ProposalHandler and UpdateHandler. The NewChannel and AdjudicatorEvent callbacks are implemented as function pointers. We define all these callbacks on our node but leave them empty for now:

The Proposal callback is called whenever the Client receives a channel proposal. The user can then accept or reject the proposal depending on whether he wants to open that channel.

func (n *node) HandleProposal(_proposal client.ChannelProposal, responder *client.ProposalResponder) {

The Update callback queries the user whether he wants to accept the channel update that was proposed to him.

func (n *node) HandleUpdate(update client.ChannelUpdate, responder *client.UpdateResponder) {

NewChannel is used whenever a new channel was successfully opened.

func (n *node) HandleNewChannel(ch *client.Channel) {

AdjudicatorEvent is called when the watcher received an on-chain event from the Adjudicator. This will be relevant for closing a channel and handling disputes.

func (n *node) HandleAdjudicatorEvent(e channel.AdjudicatorEvent) {