# Migrating to libp2p@39 <!-- omit in toc -->

A migration guide for refactoring your application code from libp2p v0.37.x to v0.38.0.

## Table of Contents <!-- omit in toc -->

- [Streams](#streams)
- [Tagging peers](#tagging-peers)
- [Protocol stream limits](#protocol-stream-limits)

## Streams

The type of streams has changed. Previously it was `Duplex<Uint8Array>`, now it is `Duplex<Uint8ArrayList, Uint8ArrayList | Uint8Array>`.

This means you will source [`Uint8ArrayList`](https://www.npmjs.com/package/uint8arraylist)s and sink `Uint8ArrayList | Uint8Array`.

This has changed because bytes returned by stream sources are usually obtained from multiplexed streams. A single data message sent over these streams may be transmitted as multiple smaller messages, for example where the data being sent is bigger than the multiplexer's message size limit. To return a contiguous block of bytes as a `Uint8Array`, where the bytes were sent as multiple message this would then involve a memory copy which is expensive.

Instead the stream will now yield `Uint8ArrayList`s which can be backed by multiple `Uint8Array` or subarrays of `Uint8Array` which avoid the memory-copy penalty.

Either `Uint8ArrayList`s or `Uint8Array`s can be yielded to the stream sink and they will be handled transparently.

If you require `Uint8Array`s in a stream handler, you can call `.subarray` on the `Uint8ArrayList` which will return a `Uint8Array` of the list contents - where the list is backed by a single `Uint8Array` it will be returned as-is, otherwise a new `Uint8Array` will be created and the contents of the list's backing `Uint8Array`s copied into it, which is similar to the behaviour of older `libp2p` versions.

**Before**

```js
const stream = await libp2p.dialProtocol(peerId, protocol)

await pipe(
  stream,
  async function * (source) {
    for await (const buf of source) {
      // buf is a Uint8Array
    }
  },
  stream
)
```

**After**

```js
const stream = await libp2p.dialProtocol(peerId, protocol)

await pipe(
  stream,
  async function * (source) {
    for await (const list of source) {
      // list is a Uint8ArrayList
      const buf = list.subarray()
      // buf is a Uint8Array, only convert if necessary to avoid copying memory
    }
  },
  stream
)
```

## Tagging peers

`libp2p@0.38.x` brings a new mechanism for tagging peers in the peer store with values.  These values are used to select connections to close when limits are reached, and there are also some special values that trigger certain behaviour like connecting to peers on startup.

The peer tagging mechanism replaces the notion of peer values in the connection manager.

Subsystems such as `kad-dht` and `gossipsub` will tag peers important to them (KAD-close or in topic meshes, for example) to ensure connections are prioritized appropriately.

When not specified, default values will be used as [defined in the registrar](https://github.com/libp2p/js-libp2p/blob/master/src/registrar.ts#L14-L15).

**Before**

```js
libp2p.connectionManager.setPeerValue(peerId, 0.5)
```

**After**

```js
import { KEEP_ALIVE } from '@libp2p/interface-peer-store/tags'

// this peer will be connected to on startup and also reconnected to if the connection drops
await libp2p.connectionManager.tagPeer(peerId, KEEP_ALIVE)

await libp2p.connectionManager.tagPeer(peerId, 'my-tag-value', {
  // a value 0-100
  value: 0.5,

  // an optional time in ms after which the tag will be removed
  ttl: 1000
})
```

## Protocol stream limits

To prevent remote peers overloading nodes by opening excessive amounts of protocol streams, stream handlers can specify limits on how many streams can be open concurrently for that protocol.

**Before**

```js
await libp2p.handle('/my-protocol/1.0.0', (stream) => {
  // ...handle stream
})
```

**After**

```js
await libp2p.handle('/my-protocol/1.0.0', (stream) => {
  // ...handle stream
}, {
  // specify the maximum number of concurrent inbound streams for this protocol
  maxInboundStreams: 1,
  // specify the maximum number of concurrent outbound streams for this protocol
  maxOutboundStreams: 1
})
```

For built-in protocols, these can be configured using the `createLibp2p` factory function:

**Before**

```js
const node = await createLibp2p({
  //... other options
})
```

**After**

```js
const node = await createLibp2p({
  identify: {
    maxInboundStreams: 1,
    maxOutboundStreams: 1,
    maxPushIncomingStreams: 1,
    maxPushOutgoingStreams: 1
  },
  ping: {
    maxInboundStreams: 1,
    maxOutboundStreams: 1,
  },
  fetch: {
    maxInboundStreams: 1
    maxOutboundStreams: 1
  }
  //... other options
})
```
