# 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 to the libp2p@0.27 API](#migrating-to-the-libp2p027-api)
  - [Table of Contents](#table-of-contents)
  - [Migrating from callbacks](#migrating-from-callbacks)
  - [Pull Streams to Streaming Iterables](#pull-streams-to-streaming-iterables)
  - [Sample API Migrations](#sample-api-migrations)
    - [Registering Protocol Handlers](#registering-protocol-handlers)
    - [Dialing and Sending Data](#dialing-and-sending-data)
    - [Checking if a peer is connected](#checking-if-a-peer-is-connected)
    - [Pinging another peer](#pinging-another-peer)
    - [Pubsub](#pubsub)
      - [Getting subscribers](#getting-subscribers)
      - [Getting subscribed topics](#getting-subscribed-topics)

## 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][api]

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

**After**
```js
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][streaming_iterable]. 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](https://github.com/alanshaw/async-iterator-to-pull-stream) and [pull-stream-to-async-iterator](https://github.com/alanshaw/pull-stream-to-async-iterator).

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

## 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**
```js
const pull = require('pull-stream')
libp2p.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
```

**After**
```js
const pipe = require('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][streaming_iterable] and the protocol that was successfully negotiated. The new stream can be used with async iterator modules, see [it-awesome][it_awesome], instead of pull streams.

**Before**
```js
const pull = require('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**
```js
const pipe = require('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**
```js
if (peerInfo.isConnected()) {
  // ...do something if connected
}
```

**After**
```js
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**
```js
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**
```js
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**
```js
libp2p.pubsub.peers(topic, (err, subscribers) => {
  if (err) throw err
  console.log('Subscribers:', subscribers)
})
```

**After**
```js
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**
```js
libp2p.pubsub.ls((err, topics) => {
  if (err) throw err
  console.log('Topics:', topics)
})
```

**After**
```js
const topics = libp2p.pubsub.getTopics()
console.log('Topics:', topics)
```

[api]: ../API.md
[it_awesome]: https://github.com/alanshaw/it-awesome
[streaming_iterable]: ../STREAMING_ITERABLES.md
