Constructing multiaddr to pass into libp2p.dialProtocol

I’m trying to look up peers in the DHT and then connect to them with libp2p.dialProtocol. I’m using go-ipfs connected via the ipfs-http-client for the DHT lookup operations, then using a js-libp2p instance to do the direct dialProtocol connection.

I start by using ipfs.dht.query and waiting for the FINAL_PEER event. That gives me the PeerID of the closest peers to the key I care about. But according to the docs for libp2p.dialProtocol (js-libp2p/API.md at master · libp2p/js-libp2p · GitHub), you cannot use it with just a PeerID, it also needs the multiaddrs for the peer.

So I use ipfs.dht.findPeer(peerid) to try to map the PeerID to its multiaddr. Filtering again for the FINAL_PEER event, I wind up with an object containing the PeerID and a list of multiaddrs for that peer, looking something like this:

{
  "id": "12D3KooWAic6sKMTErmwYrdSksY7vyE9WH3kbgjBNVRTHXpkgDhA",
  "multiaddrs": [
    "/ip4/149.28.200.219/udp/4001/quic",
    "/ip6/64:ff9b::951c:c8db/udp/4001/quic",
    "/ip4/127.0.0.1/udp/4001/quic",
    "/ip6/::1/udp/4001/quic",
    "/ip4/149.28.200.219/tcp/4001",
    "/ip4/127.0.0.1/tcp/4001",
    "/ip6/::1/tcp/4001"
  ]
}

Now I need to convert that object into something I can pass to libp2p.dialProtocol. Is there a convenient way to do this? It was hard to find what the desired string format is for a multiaddr that also includes the peerid, but I eventually found the comments for the Multiaddr type (js-multiaddr/index.ts at dbc801ab7075ceea3e9c60d24f7439c315e73bf8 · multiformats/js-multiaddr · GitHub), which suggests that adding /ipfs/<peerid> to the end of a multiaddr gives you the proper string format. I can make that transformation manually with string manipulation, but is there any existing function I can call with a multiaddr and a peerid to get a combined multiaddr-with-peerid?

The even bigger question is - findPeer does not return a single multiaddr but an array of multiaddrs for the peer. Is there a way to pass all the available multiaddrs to libp2p.dialProtocol? Or do I need to pick one? If I have to pick one, do I just choose randomly? Is there any way to get a sense as to which of the returned multiaddrs is “best”/most likely to be able to be successfully connected to?

Thank you!

If you add all of the discovered multiaddrs to the address book, you can just use the peer id to do the dial and libp2p will try all of them, returning a connection using the first one that works - js-libp2p/API.md at master · libp2p/js-libp2p · GitHub

If you do the dht lookup using the js dht client, it address the discovered addresses to the address book for you so you can skip that step.

When adding the peer id to the multiaddr, /ipfs/ is the older identifier for the peer id tuple, the more recent one is /p2p/, so:

'/ip4/127.0.0.1/tcp/4001' -> '/ip4/127.0.0.1/tcp/4001/p2p/12D3Foo'
1 Like

That’s perfect, thank you!!!