<!--Specify versions for migration below-->
# Migrating to libp2p@0.29

A migration guide for refactoring your application code from libp2p v0.28.x to v0.29.0.

## Table of Contents

- [API](#api)
  - [Pubsub](#pubsub)
  - [Uint8Arrays replace node Buffers](#uint8arrays-replace-node-buffers)
- [Module Updates](#module-updates)

## API

### Pubsub

The [`libp2p-gossipsub`](https://github.com/ChainSafe/js-libp2p-gossipsub) javascript implementation is now upgraded according to the Gossipsub v1.1 [spec](https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md) and it packs several security hardening extensions. You can read more about it in its [blogpost](https://blog.ipfs.io/2020-05-20-gossipsub-v1.1/).

We leveraged this update to rethink the pubsub interface, in order to make it easier, as well as to be consistent with the API of the routers. Moreover, the interface was also reconstructed to ease new pubsub router implementations.

#### Access router instance

Libp2p prior to 0.29 unnecessarily added a layer of abstraction over the pubsub routers. We now expose the pubsub router API directly and have a test suite in the [interface-pubsub](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/pubsub) to guarantee routers compliance. This enables more advanced usage of the underlying router.

**Before**

```js
libp2p.pubsub._pubsub.*
libp2p.pubsub._pubsub.topicValidators.set(topic, validator)
```

**After**

```js
libp2p.pubsub.*
libp2p.pubsub.topicValidators.set(topic, validator)
```

#### Publish

Publish uses `Uint8Array` data instead of `Buffer`.

**Before**

```js
const topic = 'topic'
const data = Buffer.from('data')

await libp2p.pubsub.publish(topic, data)
```

**After**

```js
const uint8ArrayFromString from 'uint8arrays/from-string')

const topic = 'topic'
const data = uint8ArrayFromString('data')

await libp2p.pubsub.publish(topic, data)
```

#### Subscribe

Handlers should no longer be passed when subscribing, instead, applications should bind event handlers for each topic they wish to subscribe too. This enables more flexibility at the application level without changing the underlying subscriptions.
Message data is now a `Uint8Array` instead of `Buffer`.

**Before**

```js
const topic = 'topic'
const handler = (msg) => {
  // msg.data - pubsub data received
  const data = msg.data.toString()
}
libp2p.pubsub.subscribe(topic, handler)
```

**After**

```js
const uint8ArrayToString from 'uint8arrays/to-string')

const topic = 'topic'
const handler = (msg) => {
  // msg.data - pubsub data received
  const data = uint8ArrayToString(msg.data)
}
libp2p.pubsub.on(topic, handler)
libp2p.pubsub.subscribe(topic)
```

In the latest release, despite not being documented in `libp2p` the underlying pubsub routers supported subscribing to multiple topics at the same time. We removed that code complexity, since this is easily achieved in the application layer if needed.

**Before**

```js
const topics = ['a', 'b']
const handler = (msg) => {
  // msg.data - pubsub data received
  const data = msg.data.toString()
}
libp2p.pubsub.subscribe(topics, handler)
```

**After**

```js
const uint8ArrayToString from 'uint8arrays/to-string')

const topics = ['a', 'b']
const handler = (msg) => {
  // msg.data - pubsub data received
  const data = uint8ArrayToString(msg.data)
}

topics.forEach((topic) => {
  libp2p.pubsub.on(topic, handler)
  libp2p.pubsub.subscribe(topic)
})
```

#### Unsubscribe

Handlers should not be directly bound to the subscription anymore.

**Before**

```js
const topic = 'topic'
const handler = (msg) => {
  // msg.data - pubsub data received
}
libp2p.pubsub.unsubscribe(topic, handler)
```

**After**

```js
const topic = 'topic'
const handler = (msg) => {
  // msg.data - pubsub data received
}
libp2p.pubsub.removeListener(topic, handler)
libp2p.pubsub.unsubscribe(topic)
```

#### Topic Validators

The validator function does not include the peer parameter anymore. It was redundant since it is included in the message and it could lead to issues as the peer that sent the message might not be the one who created the message in first place. The validator function should also throw an error instead of returning `false` when the message is not valid.

**Before**

```js
const validator = (msgTopic, peer, msg) => {
  // process message
  return false
}
libp2p.pubsub._pubsub.topicValidators.set(topic, validator)
```

**After**

```js
const validator = (msgTopic, msg) => {
  const from = msg.from
  // process message
  throw new Error('not a valid message')
}
libp2p.pubsub.topicValidators.set(topic, validator)
```

### Uint8Arrays replace node Buffers

Aiming to improve libp2p browser support, we are moving away from node core modules unless we can guarantee that the code we are writing will not run in a browser. It is worth mentioning that modern JavaScript runtimes have TypedArrays such as Uint8Array backed by ArrayBuffers. All libp2p dependencies were also updated to use Uint8Array.

We use the [uint8arrays](https://www.npmjs.com/package/uint8arrays) utilities module to deal with `Uint8Arrays` easily and we recommend its usage in the application layer. Thanks for the module [@achingbrain](https://github.com/achingbrain)! It includes utilities like `compare`, `concat`, `equals`, `fromString` and `toString`. In this migration examples, we will be using the following:

```js
const uint8ArrayFromString from 'uint8arrays/from-string')
const uint8ArrayToString from 'uint8arrays/to-string')
```

#### contentRouting.put

**Before**

```js
const key = '/key'
const value = Buffer.from('oh hello there')

await libp2p.contentRouting.put(key, value)
```

**After**

```js
const key = '/key'
const value = uint8ArrayFromString('oh hello there')

await libp2p.contentRouting.put(key, value)
```

#### contentRouting.get

**Before**

```js
const key = '/key'
const value = await libp2p.contentRouting.put(key)

console.log('store value is: ', value.toString())
```

**After**

```js
const key = '/key'
const value = await libp2p.contentRouting.put(key)

console.log('store value is: ', uint8ArrayToString(value))
```

#### metadataBook.set

**Before**

```js
peerStore.metadataBook.set(peerId, 'location', Buffer.from('Saturn'))
```

**After**

```js
peerStore.metadataBook.set(peerId, 'location', uint8ArrayFromString('Saturn'))
```

#### metadataBook.get

**Before**

```js
const data = peerStore.metadataBook.get(peerId)

console.log('stored location: ', data.get('location').toString())
```

**After**

```js
const data = peerStore.metadataBook.get(peerId)

console.log('stored location: ', uint8ArrayToString(data.get('location')))
```

#### metadataBook.getValue

**Before**

```js
const location = peerStore.metadataBook.getValue(peerId, 'location')

console.log('stored location: ', location.toString())
```

**After**

```js
const location = peerStore.metadataBook.getValue(peerId, 'location')

console.log('stored location: ', uint8ArrayToString(location))
```

#### keychain.cms.encrypt

**Before**

```js
const keyInfo = await libp2p.keychain.createKey('keyTest', 'rsa', 4096)
const enc = await libp2p.keychain.cms.encrypt('keyTest', Buffer.from('data'))
```

**After**

```js
const keyInfo = await libp2p.keychain.createKey('keyTest', 'rsa', 4096)
const enc = await libp2p.keychain.cms.encrypt('keyTest', uint8ArrayFromString('data'))
```

#### pubsub

Already specified in its own chapter above.

## Module Updates

With this release you should update the following libp2p modules if you are relying on them:

```json
"libp2p-bootstrap": "^0.12.0",
"libp2p-delegated-content-routing": "^0.6.0",
"libp2p-delegated-peer-routing": "^0.6.0",
"libp2p-floodsub": "^0.23.0",
"libp2p-gossipsub": "^0.6.0",
"libp2p-kad-dht": "^0.20.0",
"libp2p-mdns": "^0.15.0",
"libp2p-mplex": "^0.10.0",
"libp2p-noise": "^2.0.0",
"libp2p-secio": "^0.13.1",
"libp2p-tcp": "^0.15.1",
"libp2p-webrtc-star": "^0.20.0",
"libp2p-websockets": "^0.14.0",
```
