js-libp2p/doc/migrations/v0.26-v0.27.md
Alex Potsides 199395de4d
feat: convert to typescript (#1172)
Converts this module to typescript.

- Ecosystem modules renamed from (e.g.) `libp2p-tcp` to `@libp2p/tcp`
- Ecosystem module now have named exports
- Configuration has been updated, now pass instances of modules instead of classes:
- Some configuration keys have been renamed to make them more descriptive.  `transport` -> `transports`, `connEncryption` -> `connectionEncryption`.  In general where we pass multiple things, the key is now plural, e.g. `streamMuxer` -> `streamMuxers`, `contentRouting` -> `contentRouters`, etc.  Where we are configuring a singleton the config key is singular, e.g. `connProtector` -> `connectionProtector` etc.
- Properties of the `modules` config key have been moved to the root
- Properties of the `config` config key have been moved to the root
```js
// before
import Libp2p from 'libp2p'
import TCP from 'libp2p-tcp'

await Libp2p.create({
  modules: {
    transport: [
      TCP
    ],
  }
  config: {
    transport: {
      [TCP.tag]: {
        foo: 'bar'
      }
    },
    relay: {
      enabled: true,
      hop: {
        enabled: true,
        active: true
      }
    }
  }
})
```
```js
// after
import { createLibp2p } from 'libp2p'
import { TCP } from '@libp2p/tcp'

await createLibp2p({
  transports: [
    new TCP({ foo: 'bar' })
  ],
  relay: {
    enabled: true,
    hop: {
      enabled: true,
      active: true
    }
  }
})
```
- Use of `enabled` flag has been reduced - previously you could pass a module but disable it with config.  Now if you don't want a feature, just don't pass an implementation.   Eg:
```js
// before
await Libp2p.create({
  modules: {
    transport: [
      TCP
    ],
    pubsub: Gossipsub
  },
  config: {
    pubsub: {
      enabled: false
    }
  }
})
```
```js
// after
await createLibp2p({
  transports: [
    new TCP()
  ]
})
```
- `.multiaddrs` renamed to `.getMultiaddrs()` because it's not a property accessor, work is done by that method to calculate announce addresses, observed addresses, etc
- `/p2p/${peerId}` is now appended to all addresses returned by `.getMultiaddrs()` so they can be used opaquely (every consumer has to append the peer ID to the address to actually use it otherwise).  If you need low-level unadulterated addresses, call methods on the address manager.

BREAKING CHANGE: types are no longer hand crafted, this module is now ESM only
2022-03-28 14:30:27 +01:00

5.2 KiB

Migrating to the libp2p@0.27 API

A migration guide for refactoring your application code from libp2p v0.26.x to v0.27.0.

Table of Contents

Migrating from callbacks

Callbacks are no longer supported in the libp2p API, as the API has now fully moved to async / await. You can see a full list of the available methods in the API readme

Before

libp2p.start((err) => {
  if (err) throw err
  console.log('libp2p started')
})

After

await libp2p.start()
console.log('libp2p started')

Pull Streams to Streaming Iterables

The libp2p API no longer supports Pull Streams and has migrated to Streaming Iterables. If you would like to continue using Pull Streams in your application code, or need additional time to migrate your code base, you can leverage the conversion modules async-iterator-to-pull-stream and pull-stream-to-async-iterator.

For a growing list of async iterator modules, you should follow the it-awesome repo.

Sample API Migrations

Registering Protocol Handlers

Protocol registration is very similar to how it previously was, however, the handler now takes a single parameter containing the incoming stream and its protocol. Additionally, you can now pass an array of protocols to .handle, but a single string is still supported.

Before

const pull from 'pull-stream')
libp2p.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))

After

const pipe from 'it-pipe')
libp2p.handle(['/echo/1.0.0'], ({ protocol, stream }) => pipe(stream, stream))

Dialing and Sending Data

dialProtocol no longer takes a callback, and will now return a Streaming Iterable and the protocol that was successfully negotiated. The new stream can be used with async iterator modules, see it-awesome, instead of pull streams.

Before

const pull from 'pull-stream')
libp2p.dialProtocol(peerInfo, '/echo/1.0.0', (err, conn) => {
  if (err) { throw err }
  pull(
    pull.values(['hey']),
    conn,
    pull.drain((data) => {
      console.log('received echo:', data.toString())
    }, (err) => {
      if (err) { throw err }
    })
  )
})

After

const pipe from 'it-pipe')
const { protocol, stream } = await libp2p.dialProtocol(peerInfo, '/echo/1.0.0')
await pipe(
  ['hey'],
  stream,
  async function (source) {
    for await (const data of source) {
      console.log('received echo:', data.toString())
    }
  }
)

Checking if a peer is connected

peerInfo.isConnected has been deprecated. libp2p now tracks all connections centrally and will no longer update the state of peerInfo.isConnected. Consumers should switch to using libp2p.registrar.getConnection(peerInfo), which will return an open connection to that peer if one exists.

Before

if (peerInfo.isConnected()) {
  // ...do something if connected
}

After

const connection = libp2p.registrar.getConnection(peerInfo)
if (connection) {
  // ...do something if connected
}

Pinging another peer

libp2p.ping will no longer callback with a Ping event emitter. The internal logic has been simplified to give more flexibility to the API. libp2p.ping will now execute a single ping and return the latency.

Before

libp2p.ping(peerInfo, (err, ping) => {
  if (err) throw err
  ping.once('ping', (latency) => {
    console.log('Latency is %s ms', latency)
    ping.stop()
  })

  ping.start()
})

After

const latency = await libp2p.ping(peerInfo)
console.log('Latency is %s ms', latency)

Pubsub

Getting subscribers

libp2p.pubsub.peers() is now libp2p.pubsub.getSubscribers() and is no longer an asynchronous action.

Before

libp2p.pubsub.peers(topic, (err, subscribers) => {
  if (err) throw err
  console.log('Subscribers:', subscribers)
})

After

const subscribers = libp2p.pubsub.getSubscribers(topic)
console.log('Subscribers:', subscribers)

Getting subscribed topics

libp2p.pubsub.ls() is now libp2p.pubsub.getTopics() and is no longer an asynchronous action.

Before

libp2p.pubsub.ls((err, topics) => {
  if (err) throw err
  console.log('Topics:', topics)
})

After

const topics = libp2p.pubsub.getTopics()
console.log('Topics:', topics)