Go: your own libp2p host
This page shows how to use pkg/client on a go-libp2p host your application already has, such as one that also runs a DHT, GossipSub or your own protocols. If you are starting from nothing, follow the Quickstart instead.
What the host needs
Section titled “What the host needs”client.New takes any host.Host. It opens a stream per request and never closes the host, so the host can serve the rest of your application. To reach a go-ricochet 1.1.0 server, the host needs the three things the server’s host uses.
| Layer | Requirement | go-libp2p option |
|---|---|---|
| Transport | UDX, from github.com/stephanfeb/go-libp2p-udx-transport |
libp2p.Transport(udxtransport.NewTransport) |
| Security | Noise | libp2p.Security(noise.ID, noise.New); included in go-libp2p’s defaults |
| Muxer | Yamux, /yamux/1.0.0 |
libp2p.Muxer("/yamux/1.0.0", yamux.DefaultTransport); the go-libp2p default |
| Identity | Any libp2p key; Ed25519 if you call client.WithEncryption |
libp2p.Identity(priv) |
The transport is the one change most hosts need. The server listens on nothing but UDX, so a host with only go-libp2p’s default transports (TCP, QUIC, WebSocket, WebTransport, WebRTC) cannot dial it. libp2p.New() with no options builds exactly such a host.
Versions
Section titled “Versions”go-ricochet 1.1.0 pins these versions in its go.mod. Match them, or at least the UDX wire version.
| Module | Version |
|---|---|
| Go | 1.25.7 |
github.com/libp2p/go-libp2p |
v0.49.0 |
github.com/stephanfeb/go-libp2p-udx-transport |
v0.1.8 |
github.com/stephanfeb/go-udx (through the transport) |
v0.1.3, UDX wire version 3 |
go get github.com/stephanfeb/go-ricochet@v1.1.0go get github.com/stephanfeb/go-libp2p-udx-transport@v0.1.8Add UDX next to your transports
Section titled “Add UDX next to your transports”libp2p.Transport replaces go-libp2p’s default transport set rather than adding to it. To keep your existing transports, list libp2p.DefaultTransports (or your own set) as well.
// Sketch: a host that keeps go-libp2p's default transports and adds UDX.package main
import ( "github.com/libp2p/go-libp2p" "github.com/libp2p/go-libp2p/core/crypto" "github.com/libp2p/go-libp2p/core/host" udxtransport "github.com/stephanfeb/go-libp2p-udx-transport")
func newHost(priv crypto.PrivKey) (host.Host, error) { return libp2p.New( libp2p.Identity(priv), libp2p.DefaultTransports, libp2p.Transport(udxtransport.NewTransport), libp2p.ListenAddrStrings( "/ip4/0.0.0.0/tcp/0", "/ip4/0.0.0.0/udp/0/udx", ), // go-libp2p's default security (TLS and Noise) and muxer (Yamux) // already include what the server speaks. )}If your host sets libp2p.Security or libp2p.Muxer explicitly, it loses the defaults for that layer: make sure Noise and /yamux/1.0.0 are in the list.
If the host exists only to talk to Ricochet, build it the way go-ricochet’s own examples/mailbox does, with UDX alone:
// From examples/mailbox: a host that speaks what the server speaks.h, err := libp2p.New( libp2p.Identity(priv), libp2p.NoTransports, libp2p.Transport(udxtransport.NewTransport), libp2p.ListenAddrStrings("/ip4/0.0.0.0/udp/0/udx"), libp2p.Security(noise.ID, noise.New), libp2p.Muxer("/yamux/1.0.0", yamux.DefaultTransport),)Attach the client
Section titled “Attach the client”Connect to the server, then create the client with that server as a preference.
// Sketch: attach a Ricochet client to an existing host h.info, err := peer.AddrInfoFromString( "/ip4/203.0.113.10/udp/55223/udx/p2p/12D3KooW...")if err != nil { return err}if err := h.Connect(ctx, *info); err != nil { return err}
cl := client.New(h, client.Config{ PreferredServers: []client.ServerPreference{ {PeerID: info.ID, Priority: 1}, },})defer cl.Close() // removes the client's stream handlers; h stays open
res, err := cl.SendMessage(ctx, recipient, []byte("hello"))Streams find the server through the peerstore. h.Connect stores its address only briefly, and the connection keeps it there while it lasts; to redial after a drop, call h.Connect again, as examples/mailbox does, or store the address with a longer TTL (h.Peerstore().AddAddrs(info.ID, info.Addrs, peerstore.PermanentAddrTTL)). client.Config has two more fields: ConnectionTimeout (default 10 s) and MessageTimeout (default 30 s). The rest of the API is in Creating a client.
Notifications on a shared host
Section titled “Notifications on a shared host”cl.RegisterNotificationHandler registers a stream handler for /ricochet/mailbox-notify/1.0.0 on your host, and cl.Close removes it. The server opens that stream over the connection your host already holds, so the host does not need a public address. Notifications for shared and public mailboxes go out on GossipSub topics instead; pkg/client does not subscribe to them, so if your host runs GossipSub you can subscribe to /ricochet/mailbox/<ownerPeerID>/<folderPath> yourself. See Push notifications.
Behind NAT
Section titled “Behind NAT”A client host only dials out, so it works behind NAT without relay or hole punching. The server also runs a Circuit Relay v2 service by default; see NAT traversal & relay.