LogoPear Docs
ReferenceBuilding blocks

Hyperswarm

Topic-based peer discovery and encrypted connections on top of HyperDHT.

stable

Hyperswarm is the high-level networking layer for discovering peers by a shared 32-byte topic and opening encrypted connections between them. Prefer one swarm instance per app and join multiple topics on that same instance when possible.

Install

npm i hyperswarm

Quickstart

import Hyperswarm from 'hyperswarm'

const server = new Hyperswarm()
const client = new Hyperswarm()

server.on('connection', socket => {
  socket.end('hello from the server')
})

client.on('connection', socket => {
  socket.once('data', async buf => {
    console.log(buf.toString())
    await Promise.all([client.destroy(), server.destroy()])
  })
})

const topic = Buffer.alloc(32).fill('pear-docs-topic')
const discovery = server.join(topic, { server: true, client: false })
await discovery.flushed()

client.join(topic, { server: false, client: true })
await client.flush()

API Reference

Constructor and state

new Hyperswarm(opts = {})

  • Signature: const swarm = new Hyperswarm(opts)
  • Parameters:
    • opts.keyPair: Noise key pair to use for DHT listen and connect operations. Defaults to a new key pair.
    • opts.seed: 32-byte seed used to derive a deterministic key pair.
    • opts.maxPeers: Maximum number of peer connections to keep open.
    • opts.firewall: Synchronous function (remotePublicKey) => boolean that rejects a peer when it returns true.
    • opts.dht: Existing hyperdht instance to reuse instead of creating one internally.
  • Returns: A new Hyperswarm instance.
  • Example:
const swarm = new Hyperswarm({ maxPeers: 32 })
await swarm.listen()

swarm.connecting

  • Signature: swarm.connecting
  • Returns: number count of outbound connections still opening.
  • Example:
if (swarm.connecting > 0) console.log('connecting...')

swarm.connections

  • Signature: swarm.connections
  • Returns: Set of active encrypted duplex connections.
  • Example:
for (const socket of swarm.connections) socket.write('ping')

swarm.peers

  • Signature: swarm.peers
  • Returns: Map<string, PeerInfo> keyed by the remote Noise public key as a hex string.
  • Example:
for (const [key, peer] of swarm.peers) {
  console.log(key, peer.prioritized)
}

swarm.dht

  • Signature: swarm.dht
  • Returns: The underlying hyperdht instance used by the swarm.
  • Example:
console.log('bootstrap ready:', !!swarm.dht)

Topic membership

swarm.join(topic, opts = {})

  • Signature: const discovery = swarm.join(topic, opts)
  • Parameters:
    • topic: 32-byte Buffer that identifies the swarm topic.
    • opts.server: Announce on the DHT and accept inbound connections for this topic. Defaults to true.
    • opts.client: Query the DHT and connect to discovered servers for this topic. Defaults to true.
    • opts.limit: Maximum peers to connect to for this topic. Defaults to Infinity.
  • Returns: A PeerDiscovery object for the topic.
  • Example:
const discovery = swarm.join(topic, { server: true, client: false })
await discovery.flushed()

Client mode discovers and dials servers for a topic. Server mode announces that topic and accepts inbound connections. Connections opened in client mode update peerInfo.topics; inbound server connections are not tied to a single topic.

await swarm.leave(topic)

  • Signature: await swarm.leave(topic)
  • Parameters:
    • topic: 32-byte Buffer previously joined with swarm.join(...).
  • Returns: A promise that resolves after discovery and announcement for that topic stop.
  • Example:
await swarm.leave(topic)

Leaving a topic stops new discovery work but does not close already-open connections.

swarm.status(topic)

  • Signature: const discovery = swarm.status(topic)
  • Parameters:
    • topic: 32-byte Buffer for a joined topic.
  • Returns: The current PeerDiscovery for that topic, or null if the topic is not active.
  • Example:
const discovery = swarm.status(topic)
if (discovery) await discovery.refresh({ client: true, server: true })

await swarm.flush()

  • Signature: await swarm.flush()
  • Returns: A promise that resolves after pending DHT announces complete and queued peer connections have been processed.
  • Example:
swarm.join(topic, { client: true, server: false })
await swarm.flush()

flush() is global to the swarm rather than scoped to one topic, so it can be comparatively expensive.

Direct peers and events

swarm.joinPeer(noisePublicKey)

  • Signature: swarm.joinPeer(noisePublicKey)
  • Parameters:
    • noisePublicKey: 32-byte Buffer containing the remote peer's Noise public key.
  • Returns: Nothing. Hyperswarm starts and maintains a direct connection attempt to that peer.
  • Example:
swarm.joinPeer(remotePublicKey)

swarm.leavePeer(noisePublicKey)

  • Signature: swarm.leavePeer(noisePublicKey)
  • Parameters:
    • noisePublicKey: 32-byte Buffer for a peer previously targeted with joinPeer(...).
  • Returns: Nothing. Future reconnect attempts stop.
  • Example:
swarm.leavePeer(remotePublicKey)

If the peer is already connected, leavePeer(...) does not close that existing socket.

swarm.on('connection', (socket, peerInfo) => {})

  • Signature: swarm.on('connection', (socket, peerInfo) => {})
  • Parameters:
    • socket: End-to-end encrypted duplex stream for the peer connection.
    • peerInfo: PeerInfo object describing the connected peer.
  • Returns: The swarm emits this event whenever a new peer connection opens.
  • Example:
swarm.on('connection', (socket, peerInfo) => {
  console.log(peerInfo.publicKey)
  socket.write('hello')
})

swarm.on('update', () => {})

  • Signature: swarm.on('update', () => {})
  • Returns: The swarm emits this event whenever internal counters or connection state change.
  • Example:
swarm.on('update', () => {
  console.log(swarm.connecting, swarm.connections.size)
})

swarm.on('ban', (peerInfo, err) => {})

  • Signature: swarm.on('ban', (peerInfo, err) => {})
  • Parameters:
    • peerInfo: Banned peer metadata.
    • err: Error describing why the peer was banned, such as a firewall rejection.
  • Returns: The swarm emits this event after a peer becomes banned.
  • Example:
swarm.on('ban', (peerInfo, err) => {
  console.log('banned', peerInfo.publicKey, err?.message)
})

Listening and lifecycle

await swarm.listen()

  • Signature: await swarm.listen()
  • Returns: A promise that resolves once the swarm is listening for inbound connections.
  • Example:
await swarm.listen()

listen() is usually called for you after the first join(...), but it is available when you want listening to start earlier.

await swarm.suspend({ log } = {})

  • Signature: await swarm.suspend({ log })
  • Parameters:
    • log: Optional logging function used while the swarm suspends networking. Defaults to a no-op.
  • Returns: A promise that resolves after peer connections, server listening, and discovery are suspended.
  • Example:
await swarm.suspend({ log: console.log })

await swarm.resume({ log } = {})

  • Signature: await swarm.resume({ log })
  • Parameters:
    • log: Optional logging function used while the swarm resumes networking. Defaults to a no-op.
  • Returns: A promise that resolves after the DHT, listening server, and discovery resume.
  • Example:
await swarm.resume({ log: console.log })

await swarm.destroy({ force } = {})

  • Signature: await swarm.destroy({ force })
  • Parameters:
    • force: Optional boolean that skips graceful topic cleanup when true.
  • Returns: A promise that resolves after the swarm closes its server, discovery work, and underlying DHT instance.
  • Example:
await swarm.destroy()

PeerDiscovery

await discovery.flushed()

  • Signature: await discovery.flushed()
  • Returns: A promise that resolves once a server-mode topic has been fully announced on the DHT.
  • Example:
const discovery = swarm.join(topic, { server: true, client: false })
await discovery.flushed()

await discovery.refresh({ client, server })

  • Signature: await discovery.refresh({ client, server })
  • Parameters:
    • client: Optional boolean to enable or disable client lookups.
    • server: Optional boolean to enable or disable server announcements.
  • Returns: A promise that resolves after the topic configuration is refreshed.
  • Example:
await discovery.refresh({ client: true, server: true })

Refreshing a server-mode discovery also triggers a new DHT announcement for that topic.

await discovery.destroy()

  • Signature: await discovery.destroy()
  • Returns: A promise that resolves after discovery and announcements for that topic stop.
  • Example:
await discovery.destroy()

PeerInfo

peerInfo.publicKey

  • Signature: peerInfo.publicKey
  • Returns: The peer's Noise public key as a Buffer.
  • Example:
console.log(peerInfo.publicKey)

peerInfo.topics

  • Signature: peerInfo.topics
  • Returns: Array of joined topics associated with the peer when the local swarm connected in client mode.
  • Example:
for (const topic of peerInfo.topics) console.log(topic)

peerInfo.prioritized

  • Signature: peerInfo.prioritized
  • Returns: true when the swarm should reconnect to the peer aggressively.
  • Example:
if (peerInfo.prioritized) console.log('high-priority peer')

peerInfo.ban(banStatus = false)

  • Signature: peerInfo.ban(banStatus = false)
  • Parameters:
    • banStatus: true to ban the peer or false to unban it.
  • Returns: Nothing. Updates whether the swarm should avoid future reconnect attempts.
  • Example:
peerInfo.ban(true)

Banning prevents future reconnection attempts, but it does not close an already-open connection.

See also

On this page