LogoPear Docs
ReferenceBuilding blocks

HyperDHT

P2P DHT for keyed peer lookup, hole punching, and encrypted direct connections.

stable

HyperDHT is the lower-level keyed connection layer underneath Hyperswarm. Use it when you want to dial a known public key directly or work with raw DHT discovery and record APIs.

Install

npm i hyperdht

Quickstart

import DHT from 'hyperdht'
import { once } from 'node:events'

const serverNode = new DHT()
const clientNode = new DHT()
const keyPair = DHT.keyPair()

const server = serverNode.createServer(socket => {
  socket.end('hello from hyperdht')
})

await server.listen(keyPair)
const socket = clientNode.connect(keyPair.publicKey)

await once(socket, 'open')
socket.write('ping')

for await (const chunk of socket) {
  console.log(chunk.toString())
}

await server.close()
await Promise.all([serverNode.destroy(), clientNode.destroy()])

API Reference

Node setup

new DHT([options])

API definition on GitHub

  • Signature: const node = new DHT([options]) (GitHub)
  • Parameters (GitHub):
    • options.bootstrap: Optional array of bootstrap nodes. In Pear apps this defaults to Pear.config.dht.bootstrap; elsewhere it defaults to the public HyperDHT bootstrap nodes.
    • options.keyPair: Optional default key pair used by server.listen() and node.connect().
    • options.connectionKeepAlive: Optional default socket keep-alive in milliseconds. Defaults to 5000; set false to disable it.
    • options.randomPunchInterval: Optional punch interval in milliseconds. Defaults to 20000.
    • Any additional options are forwarded to dht-rpc.
  • Returns: A new DHT node instance. (GitHub)
  • Example:
import DHT from 'hyperdht'

const node = new DHT({
  bootstrap: ['203.0.113.10:49737'],
  connectionKeepAlive: 10000
})

DHT.keyPair([seed])

API definition on GitHub

  • Signature: const keyPair = DHT.keyPair([seed]) (GitHub)
  • Parameters (GitHub):
    • seed: Optional seed value when you want deterministic key generation.
  • Returns: An object with publicKey and secretKey buffers. (GitHub)
  • Example:
const keyPair = DHT.keyPair()
console.log(keyPair.publicKey)

DHT.bootstrapper(port, host, [options])

API definition on GitHub

  • Signature: const bootstrapNode = DHT.bootstrapper(port, host, [options]) (GitHub)
  • Parameters (GitHub):
    • port: UDP port for the bootstrap node.
    • host: Hostname or IP address to bind to.
    • options: Optional bootstrap-node settings.
  • Returns: A DHT bootstrap node for isolated or self-hosted networks. (GitHub)
  • Example:
const bootstrapNode = DHT.bootstrapper(49737, '0.0.0.0')

Servers

node.createServer([options], [onconnection])

API definition on GitHub

  • Signature: const server = node.createServer([options], [onconnection]) (GitHub)
  • Parameters (GitHub):
    • options.firewall(remotePublicKey, remoteHandshakePayload): Optional predicate that returns false to accept a connection or true to reject it.
    • onconnection: Optional handler that runs for each accepted socket.
  • Returns: A HyperDHT server that accepts encrypted NoiseSecretStream connections. (GitHub)
  • Example:
const server = node.createServer((socket) => {
  socket.write('connected')
})

await server.listen(keyPair)

API definition on GitHub

  • Signature: await server.listen(keyPair) (GitHub)
  • Parameters (GitHub):
    • keyPair: The { publicKey, secretKey } pair the server should announce and accept connections on.
  • Returns: A promise that resolves when the server is listening. (GitHub)
  • Example:
const keyPair = DHT.keyPair()
await server.listen(keyPair)

server.refresh()

API definition on GitHub

  • Signature: server.refresh() (GitHub)
  • Parameters: None. (GitHub)
  • Returns: Nothing. (GitHub)
  • Example:
server.refresh()

Call this to reannounce the server address. HyperDHT also calls it automatically when the network changes.

server.address()

API definition on GitHub

  • Signature: const address = server.address() (GitHub)
  • Parameters: None. (GitHub)
  • Returns: An object with host, port, and publicKey. (GitHub)
  • Example:
const { host, port, publicKey } = server.address()
console.log(host, port, publicKey)

server.on('connection', socket)

API definition on GitHub

  • Signature: server.on('connection', socket => { ... }) (GitHub)
  • Parameters (GitHub):
    • socket: A NoiseSecretStream for the accepted peer.
  • Returns: Event subscription. (GitHub)
  • Example:
server.on('connection', socket => {
  console.log(socket.remotePublicKey)
})

The socket exposes socket.remotePublicKey, and socket.handshakeHash is a shared identifier for the encrypted session.

server.on('listening')

API definition on GitHub

  • Signature: server.on('listening', () => { ... }) (GitHub)
  • Parameters: A listener callback with no arguments. (GitHub)
  • Returns: Event subscription. (GitHub)
  • Example:
server.on('listening', () => {
  console.log('ready')
})

await server.close()

API definition on GitHub

  • Signature: await server.close() (GitHub)
  • Parameters: None. (GitHub)
  • Returns: A promise that resolves when the server has stopped listening. (GitHub)
  • Example:
await server.close()

server.on('close')

API definition on GitHub

  • Signature: server.on('close', () => { ... }) (GitHub)
  • Parameters: A listener callback with no arguments. (GitHub)
  • Returns: Event subscription. (GitHub)
  • Example:
server.on('close', () => {
  console.log('server closed')
})

Clients and sockets

node.connect(remotePublicKey, [options])

API definition on GitHub

  • Signature: const socket = node.connect(remotePublicKey, [options]) (GitHub)
  • Parameters (GitHub):
    • remotePublicKey: The server public key as a buffer, hex string, or z-base32 string.
    • options.nodes: Optional nearby DHT nodes that can speed up connection attempts.
    • options.keyPair: Optional local key pair for the outgoing connection. Defaults to node.defaultKeyPair.
  • Returns: A NoiseSecretStream socket. (GitHub)
  • Example:
const socket = node.connect(remotePublicKey)

socket.on('open')

API definition on GitHub

  • Signature: socket.on('open', () => { ... }) (GitHub)
  • Parameters: A listener callback with no arguments. (GitHub)
  • Returns: Event subscription. (GitHub)
  • Example:
socket.on('open', () => {
  console.log('connected')
})

socket.remotePublicKey

API definition on GitHub

  • Signature: socket.remotePublicKey (GitHub)
  • Returns: The remote peer's public key buffer. (GitHub)
  • Example:
console.log(socket.remotePublicKey)

socket.publicKey

API definition on GitHub

  • Signature: socket.publicKey (GitHub)
  • Returns: The local socket public key buffer. (GitHub)
  • Example:
console.log(socket.publicKey)

Peer discovery

node.lookup(topic, [options])

API definition on GitHub

  • Signature: const stream = node.lookup(topic, [options]) (GitHub)
  • Parameters (GitHub):
    • topic: A 32-byte topic buffer, typically a hash.
    • options: Optional lookup settings forwarded to dht-rpc.
  • Returns: A stream of lookup responses shaped like { from, to, peers }. (GitHub)
  • Example:
for await (const result of node.lookup(topic)) {
  console.log(result.peers)
}

node.announce(topic, keyPair, [relayAddresses], [options])

API definition on GitHub

  • Signature: const stream = node.announce(topic, keyPair, [relayAddresses], [options]) (GitHub)
  • Parameters (GitHub):
    • topic: A 32-byte topic buffer.
    • keyPair: The key pair being announced under that topic.
    • relayAddresses: Optional array of up to three relay-capable nodes that help other peers connect faster.
    • options: Optional announce settings forwarded to dht-rpc.
  • Returns: A stream with the same shape as node.lookup(). (GitHub)
  • Example:
const stream = node.announce(topic, keyPair, server.nodes)
for await (const result of stream) {
  console.log(result.from)
}

Servers created with node.createServer() already announce themselves on the key pair they are listening on. Use node.announce() when you also want to publish a topic mapping.

await node.unannounce(topic, keyPair, [options])

API definition on GitHub

  • Signature: await node.unannounce(topic, keyPair, [options]) (GitHub)
  • Parameters (GitHub):
    • topic: The topic to stop announcing on.
    • keyPair: The key pair previously announced for that topic.
    • options: Optional unannounce settings forwarded to dht-rpc.
  • Returns: A promise that resolves when the announcement has been removed. (GitHub)
  • Example:
await node.unannounce(topic, keyPair)

Mutable and immutable records

await node.immutablePut(value, [options])

API definition on GitHub

  • Signature: const { hash, closestNodes } = await node.immutablePut(value, [options]) (GitHub)
  • Parameters (GitHub):
    • value: The immutable buffer or value to store in the DHT.
    • options: Optional put settings forwarded to dht-rpc.
  • Returns: An object with the stored hash and closestNodes. (GitHub)
  • Example:
const { hash } = await node.immutablePut(Buffer.from('hello'))

await node.immutableGet(hash, [options])

API definition on GitHub

  • Signature: const { value, from } = await node.immutableGet(hash, [options]) (GitHub)
  • Parameters (GitHub):
    • hash: The content hash returned by immutablePut().
    • options: Optional get settings forwarded to dht-rpc.
  • Returns: An object with the stored value and the responding node in from. (GitHub)
  • Example:
const { value } = await node.immutableGet(hash)

await node.mutablePut(keyPair, value, [options])

API definition on GitHub

  • Signature: const { publicKey, closestNodes, seq, signature } = await node.mutablePut(keyPair, value, [options]) (GitHub)
  • Parameters (GitHub):
    • keyPair: The signing key pair for the mutable record.
    • value: The record value to publish.
    • options: Optional put settings forwarded to dht-rpc.
  • Returns: An object with the announcing publicKey, closestNodes, seq, and signature. (GitHub)
  • Example:
const record = await node.mutablePut(keyPair, Buffer.from('v1'))

await node.mutableGet(publicKey, [options])

API definition on GitHub

  • Signature: const { value, from, seq, signature } = await node.mutableGet(publicKey, [options]) (GitHub)
  • Parameters (GitHub):
    • publicKey: The public key for the mutable record.
    • options.seq: Optional minimum sequence number to accept. Defaults to 0.
    • options.latest: Optional boolean that prefers the highest sequence number before returning. Defaults to false.
    • Any additional options are forwarded to dht-rpc.
  • Returns: An object with value, from, seq, and signature. (GitHub)
  • Example:
const { value, seq } = await node.mutableGet(keyPair.publicKey, {
  latest: true
})

Lifecycle

await node.destroy([options])

API definition on GitHub

  • Signature: await node.destroy([options]) (GitHub)
  • Parameters (GitHub):
    • options.force: Set to true to force shutdown without waiting for servers to unannounce.
  • Returns: A promise that resolves when the node is fully destroyed. (GitHub)
  • Example:
await node.destroy()

HyperDHT inherits additional lower-level RPC APIs from dht-rpc. Reach for those when you need custom queries beyond the keyed connection and record helpers above.

See also

On this page