◐ Shell
clean mode source ↗

JavaScript - iroh

PlatformArchitectures
macOSarm64
Linuxx86_64, aarch64 (glibc and musl), armv7
Windowsx86_64, aarch64
Androidaarch64, armv7

All platforms require Node.js 20.3.0 or newer.

The JavaScript bindings to iroh are published on npm as @number0/iroh and shipped from iroh-ffi. They’re built with napi-rs, so the package distributes prebuilt native binaries. No Rust toolchain or local compilation is needed.

Install

npm install @number0/iroh

Requires Node.js 20.3.0 or newer. Prebuilt N-API binaries are published for:

  • macOS: arm64 (no Intel build)
  • Linux: x86_64 and aarch64 (glibc + musl), armv7 (gnueabihf + musleabihf)
  • Windows: x86_64 and aarch64
  • Android: aarch64 and armv7

Hello, iroh

import { Endpoint } from '@number0/iroh'

const ALPN = Array.from(Buffer.from('hello-iroh/0'))

const ep = await Endpoint.bind({ alpns: [ALPN] })
console.log('endpoint id:', ep.id().toString())
await ep.close()

Endpoint.bind applies the n0 preset (public discovery + default relays) by default. Pass an EndpointOptions object to override the preset, supply a fixed secret key, or set ALPNs.

A two-peer echo

A minimal sender/receiver pair over a bidirectional stream:

// main.mjs: run `node main.mjs receiver` or `node main.mjs sender <ticket>`
import { Endpoint, EndpointTicket } from '@number0/iroh'

const ALPN = Array.from(Buffer.from('hello-iroh/0'))

async function receiver() {
  const ep = await Endpoint.bind({ alpns: [ALPN] })
  console.log('ticket:', EndpointTicket.fromAddr(ep.addr()).toString())

  const incoming = await ep.acceptNext()
  const conn = await (await incoming.accept()).connect()
  const bi = await conn.acceptBi()
  const msg = await bi.recv.readToEnd(1024)
  await bi.send.writeAll(msg)
  await bi.send.finish()
  await ep.close()
}

async function sender(ticketStr) {
  const ep = await Endpoint.bind()
  const addr = EndpointTicket.fromString(ticketStr).endpointAddr()
  const conn = await ep.connect(addr, ALPN)

  const bi = await conn.openBi()
  await bi.send.writeAll(Array.from(Buffer.from('hello')))
  await bi.send.finish()
  const echoed = await bi.recv.readToEnd(1024)
  console.log('echoed:', Buffer.from(echoed).toString('utf8'))
  await ep.close()
}

const [cmd, arg] = process.argv.slice(2)
if (cmd === 'receiver') await receiver()
else if (cmd === 'sender') await sender(arg)
else console.error('usage: receiver | sender <ticket>')

Start the receiver in one terminal, copy the printed ticket, and run the sender with it in another.

Next steps