# @hyperswarm/dht

> The DHT powering Hyperswarm

Latest version **6.5.1** (published 2023-03-12) · MIT license · 0 weekly downloads

## Install

```sh
npm install @hyperswarm/dht
pnpm add @hyperswarm/dht
yarn add @hyperswarm/dht
bun add @hyperswarm/dht
```

Provides the command `hyperswarm-dht`.

## Health

**Score 30/100 (F)** — status: abandoned.

Positive: no vulnerabilities; high maintenance score.

Warnings: low downloads; no types; no esm support.

Negative: abandoned.

## Facts

| | |
|---|---|
| Version | 6.5.1 |
| Published | 2023-03-12 |
| First published | 2018-09-25 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 15 |
| Unpacked size | 110 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 408 |
| Author | Mathias Buus |
| Maintainers | kasperisager, mafintosh, davidmarkclements |

## Links

- npm: https://www.npmjs.com/package/@hyperswarm/dht
- Repository: https://github.com/holepunchto/hyperswarm-dht
- Homepage: https://github.com/holepunchto/hyperswarm-dht#readme
- Issues: https://github.com/holepunchto/hyperswarm-dht/issues
- npm.io page: https://npm.io/package/@hyperswarm/dht

## Dependencies (15)

- [b4a](https://npm.io/package/b4a.md) ^1.3.1
- [bogon](https://npm.io/package/bogon.md) ^1.0.0
- [xache](https://npm.io/package/xache.md) ^1.1.0
- [events](https://npm.io/package/events.md) ^3.3.0
- [dht-rpc](https://npm.io/package/dht-rpc.md) ^6.6.3
- [record-cache](https://npm.io/package/record-cache.md) ^1.1.1
- [safety-catch](https://npm.io/package/safety-catch.md) ^1.0.1
- [noise-curve-ed](https://npm.io/package/noise-curve-ed.md) ^2.0.0
- [noise-handshake](https://npm.io/package/noise-handshake.md) ^3.0.0
- [compact-encoding](https://npm.io/package/compact-encoding.md) ^2.4.1
- [debugging-stream](https://npm.io/package/debugging-stream.md) ^2.0.0
- [hypercore-crypto](https://npm.io/package/hypercore-crypto.md) ^3.3.0
- [sodium-universal](https://npm.io/package/sodium-universal.md) ^4.0.0
- [compact-encoding-net](https://npm.io/package/compact-encoding-net.md) ^1.0.1
- [@hyperswarm/secret-stream](https://npm.io/package/@hyperswarm/secret-stream.md) ^6.0.0

## Recent versions

- 6.5.1 (latest) — 2023-03-12
- 5.0.25 (next) — 2022-04-29
- 6.5.0 — 2023-02-07
- 6.4.4 — 2023-01-18
- 6.4.3 — 2023-01-14
- 6.4.2 — 2023-01-10
- 6.4.1 — 2023-01-03
- 6.4.0 — 2022-12-21
- 6.3.5 — 2022-12-14
- 6.3.4 — 2022-12-08
- 6.3.3 — 2022-11-22
- 6.3.2 — 2022-11-08
- 6.3.1 — 2022-10-21
- 6.3.0 — 2022-10-13
- 6.2.3 — 2022-09-16
- … 83 more at https://npm.io/package/@hyperswarm/dht/versions

## README

# @hyperswarm/dht

### [See the full API docs at docs.holepunch.to](https://docs.holepunch.to/building-blocks/hyperswarm#dht)

The DHT powering Hyperswarm

```
npm install @hyperswarm/dht
```

Built on top of [dht-rpc](https://github.com/mafintosh/dht-rpc).

The Hyperswarm DHT uses a series of holepunching techniques to make sure connectivity works on most networks,
and is mainly used to facilitate finding and connecting to peers using end to end encrypted Noise streams.

## Usage

To try it out, first instantiate a DHT instance

``` js
import DHT from '@hyperswarm/dht'

const node = new DHT()
```

Then on one computer listen for connections

``` js
// create a server to listen for secure connections
const server = node.createServer()

server.on('connection', function (socket) {
  // socket is E2E encrypted between you and the other peer
  console.log('Remote public key', socket.remotePublicKey)

  // pipe it somewhere like any duplex stream
  process.stdin.pipe(socket).pipe(process.stdout)
})

// make a ed25519 keypair to listen on
const keyPair = DHT.keyPair()

// this makes the server accept connections on this keypair
await server.listen(keyPair)
```

Then on another connect to the computer using the public key of the key-pair it is listening on

``` js
// publicKey here is keyPair.publicKey from above
const socket = anotherNode.connect(publicKey)

socket.on('open', function () {
  // socket fully open with the other peer
})

// pipe it somewhere like any duplex stream
process.stdin.pipe(socket).pipe(process.stdout)
```

## API

#### `const node = new DHT([options])`

Create a new HyperSwarm DHT node.

Options include:

```js
{
  // Optionally overwrite the default bootstrap servers, just need to be an array of any known dht node(s)
  // Defaults to ['node1.hyperdht.org:49737', 'node2.hyperdht.org:49737', 'node3.hyperdht.org:49737']
  bootstrap: ['host:port'],
  keyPair // set the default key pair to use for server.listen and connect
}
```

See [dht-rpc](https://github.com/mafintosh/dht-rpc) for more options as HyperDHT inherits from that.

*Note:* The default bootstrap servers are publicly served on behalf of the commons. To run a fully isolated DHT, start one or more dht nodes with an empty bootstrap array (`new DHT({bootstrap:[]})`) and then use the addresses of those nodes as the `bootstrap` option in all other dht nodes. You'll need at least one persistent node for the network to be completely operational.

#### `keyPair = DHT.keyPair([seed])`

Use this method to generate the required keypair for DHT operations.

Returns an object with `{publicKey, secretKey}`. `publicKey` holds a public key buffer, `secretKey` holds a private key buffer.

If you pass any options they are forwarded to dht-rpc.

#### `await node.destroy([options])`

Fully destroy this DHT node.

This will also unannounce any running servers.
If you want to force close the node without waiting for the servers to unannounce pass `{ force: true }`.

#### `node = DHT.bootstrapper(port, host, [options])`

If you want to run your own Hyperswarm network use this method to easily create a bootstrap node.

## Creating P2P servers

#### `const server = node.createServer([options], [onconnection])`

Create a new server for accepting incoming encrypted P2P connections.

Options include:

```js
{
  firewall (remotePublicKey, remoteHandshakePayload) {
    // validate if you want a connection from remotePublicKey
    // if you do return false, else return true
    // remoteHandshakePayload contains their ip and some more info
    return true
  }
}
```

You can run servers on normal home computers, as the DHT will UDP holepunch connections for you.

#### `await server.listen(keyPair)`

Make the server listen on a keyPair.
To connect to this server use keyPair.publicKey as the connect address.

#### `server.refresh()`

Refresh the server, causing it to reannounce its address. This is automatically called on network changes.

#### `server.on('connection', socket)`

Emitted when a new encrypted connection has passed the firewall check.

`socket` is a [NoiseSecretStream](https://github.com/holepunchto/hyperswarm-secret-stream) instance.

You can check who you are connected to using `socket.remotePublicKey` and `socket.handshakeHash` contains a unique hash representing this crypto session (same on both sides).

#### `server.on('listening')`

Emitted when the server is fully listening on a keyPair.

#### `server.address()`

Returns an object containing the address of the server:

```js
{
  host, // external IP of the server,
  port, // external port of the server if predictable,
  publicKey // public key of the server
}
```

You can also get this info from `node.remoteAddress()` minus the public key.

#### `await server.close()`

Stop listening.

#### `server.on('close')`

Emitted when the server is fully closed.

## Connecting to P2P servers

#### `const socket = node.connect(remotePublicKey, [options])`

Connect to a remote server. Similar to `createServer` this performs UDP holepunching for P2P connectivity.

Options include:

```js
{
  nodes: [...], // optional array of close dht nodes to speed up connecting
  keyPair // optional key pair to use when connection (defaults to node.defaultKeyPair)
}
```

#### `socket.on('open')`

Emitted when the encrypted connection has been fully established with the server.

#### `socket.remotePublicKey`

The public key of the remote peer.

#### `socket.publicKey`

The public key of the local socket.

## Additional peer discovery

#### `const stream = node.lookup(topic, [options])`

Look for peers in the DHT on the given topic. Topic should be a 32 byte buffer (normally a hash of something).

The returned stream looks like this

```js
{
  // Who sent the response?
  from: { id, host, port },
  // What address they responded to (i.e. your address)
  to: { host, port },
  // List of peers announcing under this topic
  peers: [ { publicKey, nodes: [{ host, port }, ...] } ]
}
```

To connect to the peers you should afterwards call `connect` with those public keys.

If you pass any options they are forwarded to dht-rpc.

#### `const stream = node.announce(topic, keyPair, [relayAddresses], [options])`

Announce that you are listening on a key-pair to the DHT under a specific topic.

When announcing you'll send a signed proof to peers that you own the key-pair and wish to announce under the specific topic. Optionally you can provide up to 3 nodes, indicating which DHT nodes can relay messages to you - this speeds up connects later on for other users.

An announce does a parallel lookup so the stream returned looks like the lookup stream.

Creating a server using `dht.createServer` automatically announces itself periodically on the key-pair it is listening on. When announcing the server under a specific topic, you can access the nodes it is close to using `server.nodes`.

If you pass any options they are forwarded to dht-rpc.

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

Unannounce a key-pair.

If you pass any options they are forwarded to dht-rpc.

## Mutable/immutable records

#### `{ hash, closestNodes } = await node.immutablePut(value, [options])`

Store an immutable value in the DHT. When successful, the hash of the value is returned.

If you pass any options they are forwarded to dht-rpc.

#### `{ value, from } = await node.immutableGet(hash, [options])`

Fetch an immutable value from the DHT. When successful, it returns the value corresponding to the hash.

If you pass any options they are forwarded to dht-rpc.

#### `await { publicKey, closestNodes, seq, signature } = node.mutablePut(keyPair, value, [options])`

Store a mutable value in the DHT.

If you pass any options they are forwarded to dht-rpc.

#### `await { value, from, seq, signature } = node.mutableGet(publicKey, [options])`

Fetch a mutable value from the DHT.

Options:

* `seq` - OPTIONAL, default `0`, a number which will only return values with corresponding `seq` values that are greater than or equal to the supplied `seq` option.
* `latest` - OPTIONAL - default `false`, a boolean indicating whether the query should try to find the highest seq before returning, or just the first verified value larger than `options.seq` it sees.

Any additional options you pass are forwarded to dht-rpc.

## Additional API

See [dht-rpc](https://github.com/mafintosh/dht-rpc) for the additional APIs the DHT exposes.

## CLI

You can start a DHT node in the command line, with the bundled cli tool:

```sh
npm install -g @hyperswarm/dht
hyperswarm-dht # runs a DHT node
hyperswarm-dht --bootstrap # runs a DHT node with bootstrap settings
hyperswarm-dht --nodes 5 # runs 5 nodes
```

## License

MIT

---
_Source: https://npm.io/package/@hyperswarm/dht · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
